home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1993 #2
/
Image.iso
/
personal
/
hac11.zip
/
HAC.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1993-06-23
|
93KB
|
2,293 lines
(*
Home Accounts System
Version 1.1, June 1993
Copyright (C) 1992, 1993 Paul Coxwell. All rights reserved.
*)
PROGRAM HAC;
{$V-}
USES DOS,CRTCLERR,STRINGS,TIME,CRT,ENHCON;
CONST
FNEXT = '.DAT'; { EXTENSION FOR DATA FILES }
ACSTATFN = 'ACSTAT'; { NAME OF ACCOUNT STATUS FILE }
TRANSFN = 'TRANS'; { PREFIX FOR TRANSACTION FILE NAMES }
AUTOFN = 'AUTO'; { PREFIX FOR AUTO TRANSACTIONS FILE NAMES }
HELPFN = 'HAC.HLP'; { NAME OF ON-LINE HELP FILE }
ACNAMELEN = 30; { MAX. LENGTH FOR ACCOUNT NAME }
DETAILLEN = 20; { MAX. LENGTH OF TRANSACTION DETAIL }
MAXMONEY = 999999999; { MAX. VALUE OF $9,999,999.99 }
MNYFORMAT = 'BCP14:2'; { FORMAT FOR DISPLAY OF AMOUNT, BLANK ZERO }
MNYZFORMAT = 'CP14:2'; { FORMAT FOR DISPLAY OF AMOUNT, SHOW ZERO }
MNYDFORMAT = '$CP14:2'; { FORMAT FOR DISPLAY OF AMOUNT, WITH SIGN }
MNYLFORMAT = 'BLCP14:2'; { FORMAT FOR LEFT-JUSTIFIED MONEY EDITS }
MNYLZFORMAT = 'LCP14:2'; { FORMAT FOR LEFT-JUSTIFIED EDIT WITH ZERO }
MAXCHECKNUM = 999999; { MAX. NUMBER FOR A CHECK }
CHKFORMAT = 'Z6'; { FORMAT FOR CHECK NUMBERS }
TRANSKEYS = [CR,KEYUP,KEYDOWN,HT,KEYSTAB,KEYF10];
AUTOKEYS = TRANSKEYS+[KEYPGUP,KEYPGDN,KEYCPGUP,KEYCPGDN,KEYF4];
HELPONLINE: BOOLEAN = TRUE; { SET IF HELP AVAILABLE }
STATCOLOR: BYTE = MONONORMAL; { COLOR OF STATUS BLOCK }
TITLECOLOR: BYTE = MONOREVERSE; { COLOR OF TITLES/HEADINGS }
MAINCOLOR: BYTE = MONONORMAL; { COLOR OF MAIN SCREEN AREA }
HIGHCOLOR: BYTE = MONOINTENSE; { COLOR OF HIGHLIGHTED TEXT }
TYPE
ACCOUNTTYPE = (UNUSED,CHECKING,SAVINGS,CARD);
ACCOUNTREC = RECORD
NAME: STRING[ACNAMELEN]; { ACCOUNT NAME }
ACTYPE: ACCOUNTTYPE; { TYPE OF ACCOUNT }
RECBAL, { TOTAL RECONCILED }
UNRECBAL, { TOTAL UNRECONCILED }
CHECKNUM: LONGINT; { NEXT CHECK NUMBER }
DRDEFAULT, { MISC. DEBIT TEXT }
CRDEFAULT: STRING[DETAILLEN]; { MISC. CREDIT TEXT }
END;
TRANSTYPE = (USER,AUTO,XFER);
RECONTYPE = (UNREC,REC,BAL);
AUTOTYPE = (DEBIT,CREDIT);
TRANSREC = RECORD
DATE: WORD; { TRANSACTION DATE }
AMOUNT, { AMOUNT IN CENTS }
BALANCE: LONGINT; { BALANCE TO DATE }
DETAIL: STRING[DETAILLEN]; { DESCRIPTION }
RECON: RECONTYPE; { RECONCILIATION FLAG }
END;
AUTOREC = RECORD
DATE: DATEREC; { DATE OF NEXT ENTRY }
UPDATE: LONGINT; { UPDATE PERIOD }
COUNT: LONGINT; { NUMBER OF ENTRIES }
AUTODRCR: AUTOTYPE; { TRANSACTION TYPE }
AMOUNT: LONGINT; { VALUE OF ENTRY }
DETAIL: STRING[DETAILLEN]; { DESCRIPTION }
END;
PROMPTSTR = STRING[38]; { STRING FOR YES/NO POP-UP WINDOW }
VAR
PRN: TEXT; { PRINT OUTPUT }
ACSTATFILE: FILE OF ACCOUNTREC; { ACCOUNT STATUS FILE }
TRANSFILE: FILE OF TRANSREC; { TRANSACTION FILES }
AUTOFILE: FILE OF AUTOREC; { AUTO ENTRY FILES }
ACSTATUS: ARRAY['A'..'Z'] OF ACCOUNTREC; { STATUS OF ACCOUNT }
STATWINDOW, { TOP STATUS BLOCK }
MAINWINDOW, { MAIN DISPLAY AREA }
PROMPTWINDOW, { POP-UP WINDOW FOR PROMPTS }
EDITERRWINDOW, { POP-UP WINDOW FOR ERROR MESSAGES }
CRTCLWINDOW, { POP-UP WINDOW FOR CRITICAL ERRORS }
VIEWWINDOW, { AREA FOR TRANSACTION DISPLAY }
ENTERWINDOW, { WINDOW FOR TRANSACTION ENTRY }
HELPSTATWINDOW, { HELP SYSTEM STATUS WINDOW }
OPTLINEWINDOW: WINDOWDEFINITION; { BOTTOM LINE MESSAGES }
MONEYEDIT, { AMOUNT FIELDS FOR TRANS. ENTRY }
ACTYPEEDIT, { ACCOUNT TYPE IN SET-UP ROUTINE }
ACNAMEEDIT, { ACCOUNT NAME AND DETAIL }
ACREFEDIT, { AUX. ACCOUNT REFERENCE FIELD }
CHECKNUMEDIT, { CHECK NUMBERS }
TRANSDATEEDIT, { DATE }
APMONEYEDIT, { AMOUNT EDITING DURING AUTO PROCESS }
AUTODETAILEDIT, { DETAIL FOR AUTO ENTRIES }
AUTOMONEYEDIT, { AMOUNT FOR AUTO ENTRIES }
AUTODATEEDIT, { DATE FOR AUTO ENTRIES }
AUTONUMEDIT, { COUNT/INTERVAL FOR AUTO ENTRIES }
AUTOINTERVALEDIT: EDITFORMATREC; { DAYS/MONTHS FIELD FOR AUTO ENTRIES }
ONLINEHELP: HELPCONFIGURATION; { SETTINGS FOR HELP SYSTEM }
MAINOPT: CHAR; { MAIN MENU OPTION }
CONFIGFILENAME, { PATH/NAME FOR CONFIG. FILE }
DATAFILEPATH: STRING[80]; { PATH FOR DATA FILES }
(*
OPEN WINDOW, DISPLAY ERROR MESSAGE, WAIT FOR ESC, THEN CLOSE WINDOW.
*)
PROCEDURE DISPLAYERROR(S: PROMPTSTR);
VAR
C: CHAR;
BEGIN
OPENWINDOW(4);
WRITEWINDOW(JUSTC(S,38));
GOTOXY(1,2);
WRITEWINDOW(JUSTC('Press ESC to continue',38));
WRITE(BEL);
REPEAT UNTIL READKEY=ESC;
CLOSEWINDOW(4);
END;
{$F+}
(*
CRITICAL ERROR HANDLER. OPEN WINDOW, DISPLAY ERROR MESSAGE, AND WAIT
FOR INPUT OF (R)ETRY OR (A)BORT. RETURN SELECTION TO DOS.
*)
PROCEDURE CRTCLERRHANDLER(FLAGS,CS,IP,AX,BX,CX,DX,SI,DI,DS,ES,BP: WORD);
INTERRUPT;
VAR
C: CHAR;
BEGIN
INLINE($FB); { ENABLE INTERRUPTS }
OPENWINDOW(5); { OPEN ERROR WINDOW, GET RESPONSE }
WRITEWINDOW(JUSTC(CRITICALERRORMSG(DI),38));
GOTOXY(1,2);
WRITEWINDOW(JUSTC('Retry or Abort? (R/A)',38));
WRITE(BEL);
REPEAT
C:=UPCASE(READKEY);
UNTIL C IN ['R','A'];
CLOSEWINDOW(5); { CLOSE WINDOW, RETURN OPTION TO DOS }
IF C='R' THEN AX:=(AX AND $FF00)+1 ELSE AX:=(AX AND $FF00)+2;
END;
(*
ERROR HANDLER FOR ON-LINE HELP SYSTEM.
IF HELP FILE NOT FOUND, RUN WITHOUT HELP. FOR ALL OTHER ERRORS,
DISPLAY ERROR, WAIT FOR ESC THEN CONTINUE WITHOUT HELP SYSTEM.
*)
PROCEDURE HELPERRHANDLER(ERRCODE: BYTE);
VAR
W: BYTE;
BEGIN
HELPONLINE:=FALSE;
W:=CURRENTWINDOW;
SELECTWINDOW(9);
CLRSCR;
WRITE('No help');
SELECTWINDOW(W);
IF ERRCODE<>CONERRNOHELPFILE THEN
DISPLAYERROR('Error in on-line help system');
END;
(*
ERROR HANDLING ROUTINES FOR EDIT FUNCTIONS. DISPLAY APPROPRIATE ERROR
MESSAGE AND WAIT FOR ESC TO CONTINUE.
*)
PROCEDURE EDITERRMONEY(W: BYTE); { ERROR HANDLER FOR MONEY EDITS }
BEGIN
DISPLAYERROR('Amount entered is not acceptable');
END;
PROCEDURE EDITERRCHECKNUM(W: BYTE); { ERROR HANDLER FOR CHECK NUMBER EDITS }
BEGIN
DISPLAYERROR('Invalid check number');
END;
PROCEDURE EDITERRAUTONUM(W: BYTE); { ERROR HANDLER FOR AUTO NUMERICS }
BEGIN
DISPLAYERROR('Number entered is not acceptable');
END;
PROCEDURE EDITERRDATE(W: BYTE); { ERROR HANDLER FOR DATE EDITS }
BEGIN
DISPLAYERROR('Invalid date entered');
END;
{$F-}
(*
CHECK I/O RESULT CODE FOR DISK ERRORS. IF AN ERROR HAS OCCURRED, SHOW
APPROPRIATE MESSAGE, WAIT FOR ESC, THEN ABORT PROGRAM.
*)
PROCEDURE DISKCHECK(ERRCODE: BYTE); { DISPLAY DISK ERROR AND ABORT }
VAR
S: PROMPTSTR;
BEGIN
CASE ERRCODE OF { SET ERROR MESSAGE }
0: EXIT;
2: S:='File not found';
3: S:='Path not found';
5: S:='File access denied';
100: S:='Disk read error';
101: S:='Disk write error';
ELSE
S:='Disk error';
END;
HELPCONTEXT:=17;
OPENWINDOW(4); { DISPLAY ERROR, WAIT FOR ESC }
WRITEWINDOW(JUSTC(S,38));
GOTOXY(1,2);
WRITEWINDOW(JUSTC('Press ESC to terminate',38));
WRITE(BEL);
REPEAT
UNTIL READKEY=ESC;
CLOSEWINDOW(4);
HALT(1); { ABORT PROGRAM }
END;
(*
REMOVE ALL CONSOLE WINDOW DEFINITIONS READY FOR REDEFINITION.
*)
PROCEDURE PURGEALLWINDOWS;
VAR
K: BYTE;
BEGIN
FOR K:=1 TO 9 DO
PURGEWINDOW(K);
END;
(*
SET UP ALL CONSOLE EDIT AND WINDOW DISPLAY OPTIONS.
*)
PROCEDURE DEFINECONSOLEIO;
BEGIN
WITH MONEYEDIT DO { SETTING FOR EDITING FIELDS ON DISPLAY }
BEGIN
ATTRIBUTE:=0;
STARTCHAR:=#16; ENDCHAR:=#17; MARKERATTR:=HIGHCOLOR;
ALLOWCHARS:=STANDARDCHARS;
EXITKEYS:=TRANSKEYS;
EDITKEY:=NUL; RESTOREKEY:=NUL; ABORTKEY:=ESC;
NUMFORMAT:=MNYLFORMAT;
SIGNALERROR:=EDITERRMONEY;
FLAGS:=EDFLAGINSSTAT+EDFLAGFIRSTCLR+EDFLAGHIDECRSR;
END;
ACTYPEEDIT:=MONEYEDIT;
WITH ACTYPEEDIT DO
BEGIN
ALLOWCHARS:=[];
EXITKEYS:=EXITKEYS+[#32];
END;
ACNAMEEDIT:=MONEYEDIT;
ACNAMEEDIT.FLAGS:=ACNAMEEDIT.FLAGS+EDFLAGTRIML+EDFLAGTRIMR;
ACREFEDIT:=MONEYEDIT;
WITH ACREFEDIT DO
BEGIN
ALLOWCHARS:=['A'..'Z',#32];
FLAGS:=FLAGS+EDFLAGUPPER+EDFLAGPADR;
END;
TRANSDATEEDIT:=MONEYEDIT;
TRANSDATEEDIT.EXITKEYS:=TRANSKEYS+['+','-'];
TRANSDATEEDIT.SIGNALERROR:=EDITERRDATE;
CHECKNUMEDIT:=MONEYEDIT;
WITH CHECKNUMEDIT DO
BEGIN
NUMFORMAT:=CHKFORMAT;
SIGNALERROR:=EDITERRCHECKNUM;
END;
APMONEYEDIT:=MONEYEDIT;
WITH APMONEYEDIT DO
BEGIN
EXITKEYS:=[CR,KEYF3,KEYF4];
NUMFORMAT:=MNYZFORMAT;
END;
AUTODETAILEDIT:=ACNAMEEDIT;
WITH AUTODETAILEDIT DO
EXITKEYS:=AUTOKEYS;
AUTOMONEYEDIT:=MONEYEDIT;
WITH AUTOMONEYEDIT DO
BEGIN
EXITKEYS:=AUTOKEYS;
NUMFORMAT:=MNYLZFORMAT;
END;
AUTODATEEDIT:=TRANSDATEEDIT;
AUTODATEEDIT.EXITKEYS:=AUTOKEYS+['+','-'];
AUTONUMEDIT:=MONEYEDIT;
WITH AUTONUMEDIT DO
BEGIN
EXITKEYS:=AUTOKEYS;
NUMFORMAT:='4';
SIGNALERROR:=EDITERRAUTONUM;
END;
AUTOINTERVALEDIT:=ACREFEDIT;
WITH AUTOINTERVALEDIT DO
BEGIN
ALLOWCHARS:=[];
EXITKEYS:=AUTOKEYS+[#32];
END;
WITH STATWINDOW DO { WINDOW FOR TOP STATUS LINE }
BEGIN
X1:=1; Y1:=1;
X2:=80; Y2:=1;
DEFAULTATTR:=STATCOLOR;
DEFAULTCRSRHIDE:=TRUE; DEFAULTCRSRSIZE:=WCRSRDEFAULT;
FLAGS:=WFLAGCLROPEN;
END;
WITH MAINWINDOW DO { WINDOW FOR MAIN DISPLAY AREA }
BEGIN
X1:=1; Y1:=5;
X2:=80; Y2:=24;
DEFAULTATTR:=MAINCOLOR;
DEFAULTCRSRHIDE:=TRUE; DEFAULTCRSRSIZE:=WCRSRDEFAULT;
FLAGS:=WFLAGCLROPEN;
END;
WITH PROMPTWINDOW DO { POP-UP WINDOW FOR OCCASIONAL QUESTIONS }
BEGIN
X1:=20; Y1:=12;
X2:=60; Y2:=15;
DEFAULTATTR:=MAINCOLOR;
DEFAULTCRSRHIDE:=TRUE; DEFAULTCRSRSIZE:=WCRSRDEFAULT;
BORDER:=WBORDER1; BORDERATTR:=HIGHCOLOR;
HDRTEXT:=''; FTRTEXT:='';
FLAGS:=WFLAGCLROPEN+WFLAGRESTORE+WFLAGSHOWBRDR;
END;
EDITERRWINDOW:=PROMPTWINDOW; { POP-UP WINDOW FOR EDITING ERRORS }
WITH CRTCLWINDOW DO { POP-UP WINDOW FOR CRITICAL ERRORS }
BEGIN
X1:=20; Y1:=12;
X2:=60; Y2:=15;
DEFAULTATTR:=MAINCOLOR;
DEFAULTCRSRHIDE:=TRUE; DEFAULTCRSRSIZE:=WCRSRDEFAULT;
BORDER:=WBORDER2; BORDERATTR:=HIGHCOLOR;
HDRTEXT:='CRITICAL ERROR';
HDRATTR:=HIGHCOLOR; HDRPOS:=WJUSTLEFT;
FTRTEXT:='';
FLAGS:=WFLAGCLROPEN+WFLAGRESTORE+WFLAGSHOWBRDR;
END;
WITH VIEWWINDOW DO { DISPLAY AREA FOR ACCOUNT TRANSACTIONS }
BEGIN
X1:=1; Y1:=12;
X2:=80; Y2:=23;
DEFAULTATTR:=MAINCOLOR;
DEFAULTCRSRHIDE:=TRUE; DEFAULTCRSRSIZE:=WCRSRDEFAULT;
FLAGS:=WFLAGCLROPEN+WFLAGRESTORE;
END;
ENTERWINDOW:=VIEWWINDOW; { TRANSACTION/AUTO ENTRIES EDITING }
ENTERWINDOW.Y1:=11;
WITH OPTLINEWINDOW DO { OPTION REMINDER LINE WINDOW }
BEGIN
X1:=17; Y1:=24;
X2:=80; Y2:=25;
DEFAULTATTR:=MAINCOLOR;
DEFAULTCRSRHIDE:=TRUE; DEFAULTCRSRSIZE:=WCRSRDEFAULT;
FLAGS:=WFLAGCLROPEN;
END;
WITH HELPSTATWINDOW DO
BEGIN
X1:=1; Y1:=25;
X2:=10; Y2:=25;
DEFAULTATTR:=MAINCOLOR;
DEFAULTCRSRHIDE:=TRUE; DEFAULTCRSRSIZE:=WCRSRDEFAULT;
FLAGS:=WFLAGCLROPEN;
END;
DEFINEWINDOW(1,STATWINDOW);
DEFINEWINDOW(2,MAINWINDOW);
DEFINEWINDOW(3,PROMPTWINDOW);
DEFINEWINDOW(4,EDITERRWINDOW);
DEFINEWINDOW(5,CRTCLWINDOW);
DEFINEWINDOW(6,VIEWWINDOW);
DEFINEWINDOW(7,OPTLINEWINDOW);
DEFINEWINDOW(8,ENTERWINDOW);
DEFINEWINDOW(9,HELPSTATWINDOW);
END; { DEFINECONSOLEIO }
(*
READ CONFIGURATION FILE, IF PRESENT, AND SET OPTIONS.
CONFIGURABLE OPTIONS ARE DATA, PRINT, DATE, AND COLORS.
*)
PROCEDURE READCONFIGURATION;
VAR
F: TEXT;
C,
R: INTEGER;
S1,
S2,
S3: STRING[80];
BEGIN
{$I-}
ASSIGN(F,CONFIGFILENAME); { OPEN CONFIG. FILE }
RESET(F);
R:=IORESULT;
IF (R=2) AND (PARAMCOUNT=0) THEN { IF NOT EXPLICITLY SPECIFIED }
EXIT { AND NOT PRESENT, SKIP ROUTINE }
ELSE
DISKCHECK(R);
WHILE NOT(EOF(F)) DO { GET EACH OPTION LINE }
BEGIN
READLN(F,S1);
S1:=UPPERCASE(TRIML(TRIMR(S1)));
S2:=TRIMR(PRECEDE(S1,'='));
S3:=TRIML(FOLLOW(S1,'='));
IF S2='DATA' THEN { SET PATH FOR DATA FILES }
DATAFILEPATH:=S3;
IF S2='PRINT' THEN { SET PATH/FILE FOR PRINTING }
IF S3<>'' THEN
ASSIGN(PRN,S3);
IF S2='DATE' THEN { SET REQUIRED DATE FORMAT }
IF S3='MDY' THEN
BEGIN
DATEFORMAT:=DATEFORMMDY;
DATEDELIMITER:='/';
END
ELSE
IF S3='DMY' THEN
BEGIN
DATEFORMAT:=DATEFORMDMY;
DATEDELIMITER:='.';
END;
IF S2='CURRENCY' THEN { SET CURRENCY SYMBOL }
BEGIN
VAL(S3,C,R);
FORMATCONFIG.CURRENCY:=CHR(C);
END;
IF S2='COLORS' THEN { SET DISPLAY ATTRIBUTES }
BEGIN
S2:=SPAN(S3,DECDIGITS);
VAL(S2,MAINCOLOR,R);
S2:=BREAK(S3,DECDIGITS);
S2:=SPAN(S3,DECDIGITS);
VAL(S2,HIGHCOLOR,R);
S2:=BREAK(S3,DECDIGITS);
S2:=SPAN(S3,DECDIGITS);
VAL(S2,TITLECOLOR,R);
S2:=BREAK(S3,DECDIGITS);
S2:=SPAN(S3,DECDIGITS);
VAL(S2,STATCOLOR,R);
END;
END; { WHILE }
CLOSE(F); DISKCHECK(IORESULT);
{$I+}
END; { READCONFIGURATION }
(*
OPEN WINDOW, SHOW TWO LINE PROMPT, THEN WAIT FOR (Y)ES OR (N)O RESPONSE.
RETURN TRUE IF YES, FALSE IF NO OR ESC.
*)
FUNCTION GETYESNO(S1,S2: PROMPTSTR): BOOLEAN;
VAR
C: CHAR;
BEGIN
OPENWINDOW(3);
WRITEWINDOW(JUSTC(S1,38));
GOTOXY(1,2);
WRITEWINDOW(JUSTC(S2+' (Y/N)',38));
REPEAT
C:=UPCASE(READKEY);
UNTIL C IN ['Y','N',ESC];
GETYESNO:=(C='Y');
CLOSEWINDOW(3);
END; { GETYESNO }
(*
UPDATE ACCOUNTS STATUS FILE WITH CURRENT ACCOUNT RECORDS.
*)
PROCEDURE UPDATEACSTATFILE;
VAR
C: CHAR;
BEGIN
{$I-}
SEEK(ACSTATFILE,0); DISKCHECK(IORESULT);
FOR C:='A' TO 'Z' DO
BEGIN
WRITE(ACSTATFILE,ACSTATUS[C]); DISKCHECK(IORESULT);
END;
{$I+}
END;
(*
INITIALIZE STATUS RECORD FOR EACH ACCOUNT.
IF DATA FILE IS FOUND, READ ACCOUNT DATA FROM FILE, OTHERWISE PROMPT USER
TO CREATE A NEW ACCOUNTS SYSTEM AND INITIALIZE ALL ACCOUNTS TO UNUSED.
RETURNS TRUE IF SUCCESSFUL, FALSE IF FILE NOT FOUND AND USER DOES NOT
REQUEST NEW SYSTEM TO BE SET UP.
*)
FUNCTION ACSTATINIT: BOOLEAN;
VAR
C: CHAR;
B: BOOLEAN;
R: BYTE;
BEGIN
{$I-}
RESET(ACSTATFILE); { ATTEMPT TO OPEN STATUS FILE }
R:=IORESULT;
CASE R OF
0: BEGIN { IF FOUND, READ ACCOUNT RECORDS }
FOR C:='A' TO 'Z' DO
BEGIN
READ(ACSTATFILE,ACSTATUS[C]); DISKCHECK(IORESULT);
END;
ACSTATINIT:=TRUE;
END;
2: BEGIN { IF NOT FOUND, CREATE NEW RECORDS }
B:=GETYESNO('Accounts data not found',
'Create new accounts records?');
IF B THEN
BEGIN
FOR C:='A' TO 'Z' DO
WITH ACSTATUS[C] DO
BEGIN
NAME:='';
ACTYPE:=UNUSED;
RECBAL:=0;
UNRECBAL:=0;
CHECKNUM:=1;
DRDEFAULT:='';
CRDEFAULT:='';
END;
REWRITE(ACSTATFILE); DISKCHECK(IORESULT);
UPDATEACSTATFILE;
END;
ACSTATINIT:=B;
END;
ELSE { IF ANY OTHER ERROR, ABORT PROGRAM }
DISKCHECK(R);
END; { CASE R }
{$I+}
END; { ACSTATINIT }
(*
READ A SPECIFIED TRANSACTION NUMBER FROM TRANSFILE.
*)
PROCEDURE READTRANS(REC: LONGINT; VAR TRANS: TRANSREC);
BEGIN
{$I-}
SEEK(TRANSFILE,REC); DISKCHECK(IORESULT);
READ(TRANSFILE,TRANS); DISKCHECK(IORESULT);
{$I+}
END;
(*
WRITE A TRANSACTION TO A SPECIFIED POSITION IN TRANSFILE.
*)
PROCEDURE WRITETRANS(REC: LONGINT; TRANS: TRANSREC);
BEGIN
{$I-}
SEEK(TRANSFILE,REC); DISKCHECK(IORESULT);
WRITE(TRANSFILE,TRANS); DISKCHECK(IORESULT);
{$I+}
END;
(*
ADD TRANSACTION TO CURRENTLY OPEN TRANSACTION FILE.
INSERTS TRANSACTION IN CORRECT CHRONOLOGICAL ORDER, SHIFTING LATER
TRANSACTIONS FORWARD AND ADJUSTING BALANCES ACCORDINGLY.
AMENDS ACCOUNT RECORD PASSED IN AC TO REFLECT NEW BALANCE.
*)
PROCEDURE ADDTRANS(VAR AC: ACCOUNTREC; TRANS: TRANSREC);
VAR
T1,T2: TRANSREC;
I,J,K: LONGINT;
BEGIN
WITH AC DO
IF TRANS.RECON=UNREC THEN { UPDATE ACCOUNT BALANCE }
UNRECBAL:=UNRECBAL+TRANS.AMOUNT
ELSE
RECBAL:=RECBAL+TRANS.AMOUNT;
I:=FILESIZE(TRANSFILE); { GET LOCATION OF LAST RECORD }
J:=I;
REPEAT { FIND CORRECT CHRONOLOGICAL POS. }
DEC(I);
READTRANS(I,T1);
UNTIL (T1.DATE<=TRANS.DATE) OR (T1.RECON=BAL);
T2:=TRANS;
REPEAT { ADJUST FOLLOWING TRANSACTIONS }
T2.BALANCE:=T1.BALANCE+T2.AMOUNT;
INC(I);
IF I<J THEN
READTRANS(I,T1);
WRITETRANS(I,T2);
TRANS:=T1; T1:=T2; T2:=TRANS;
UNTIL I=J;
END; { ADDTRANS }
(*
LIST ACCOUNT NAMES AND IDENTIFIERS.
*)
PROCEDURE LISTACCOUNTS;
VAR
C: CHAR;
BEGIN
CLRSCR;
FOR C:='A' TO 'M' DO
WRITELN(' ',C,'':3,PADR(ACSTATUS[C].NAME,40),
CHR(ORD(C)+13),'':3,ACSTATUS[CHR(ORD(C)+13)].NAME);
GOTOXY(1,20);
END; { LISTACCOUNTS }
(*
LIST OPTIONS ON LAST LINE OF DISPLAY.
*)
PROCEDURE SHOWOPTIONS(K1,S1,K2,S2,K3,S3,K4,S4: PROMPTSTR);
VAR
W: BYTE;
BEGIN
W:=CURRENTWINDOW;
SELECTWINDOW(7);
CLRSCR;
GOTOXY(1,2);
TEXTATTR:=HIGHCOLOR; WRITE(K1);
TEXTATTR:=MAINCOLOR; WRITE(#32,S1);
GOTOXY(17,2);
TEXTATTR:=HIGHCOLOR; WRITE(K2);
TEXTATTR:=MAINCOLOR; WRITE(#32,S2);
GOTOXY(33,2);
TEXTATTR:=HIGHCOLOR; WRITE(K3);
TEXTATTR:=MAINCOLOR; WRITE(#32,S3);
GOTOXY(49,2);
TEXTATTR:=HIGHCOLOR; WRITE(K4);
TEXTATTR:=MAINCOLOR; WRITE(#32,S4);
SELECTWINDOW(W);
END; { SHOWOPTIONS }
(*
DISPLAY MAIN MENU, RETURN USER'S OPTION.
*)
FUNCTION MAINMENU: CHAR;
VAR
D: DATEREC;
C: CHAR;
BEGIN
GETTODAY(D);
SELECTWINDOW(1); { DISPLAY TITLE & DATE }
CLRSCR;
WRITE(PADR('HOME ACCOUNTS',70),DATESTR(D));
SELECTWINDOW(2);
LISTACCOUNTS; { SHOW LIST OF ACCOUNTS }
SHOWOPTIONS('F3','Summary', { SHOW OPTIONS }
'A-Z','Select',
'F4', 'Maint.',
'F10','Quit');
REPEAT
C:=UPCASE(READKEY); { INPUT/RETURN CHOICE }
UNTIL C IN ['A'..'Z',KEYF3,KEYF4,KEYF10];
MAINMENU:=C;
END; { MAINMENU }
(*
CONVERT TRANSACTION RECORD TO PRINTABLE STRING.
*)
FUNCTION TRANSTOSTR(T: TRANSREC): STRING;
CONST
RECCHAR = '*'; { UNRECONCILED MARKER CHARACTER }
VAR
S: STRING[80];
D: DATEREC;
BEGIN
WITH T DO
BEGIN
WORDTODATE(DATE,D);
IF RECON=BAL THEN
S:=DUPLCHAR(#32,11)
ELSE
S:=' '+DATESTR(D)+' ';
S:=S+PADR(DETAIL,DETAILLEN)+' ';
IF RECON=BAL THEN
S:=S+DUPLCHAR(#32,29)
ELSE
IF AMOUNT>0 THEN
S:=S+DUPLCHAR(#32,15)+FORMAT(AMOUNT/100,MNYFORMAT)
ELSE
S:=S+FORMAT(-AMOUNT/100,MNYFORMAT)+DUPLCHAR(#32,15);
S:=S+' '+FORMAT(BALANCE/100,MNYZFORMAT)+' ';
IF RECON=UNREC THEN
S:=S+'*'
ELSE
S:=S+' ';
END;
TRANSTOSTR:=S;
END; { TRANSTOSTR }
(*
DELETE RECORD FROM AUTO-ENTRIES FILE, SHIFT RECORDS, AND TRUNCATE FILE.
*)
PROCEDURE DELETEAUTOTRANSENTRY(I: LONGINT);
VAR
T: AUTOREC;
BEGIN
{$I-}
INC(I);
WHILE (I<FILESIZE(AUTOFILE)) DO
BEGIN
SEEK(AUTOFILE,I); DISKCHECK(IORESULT);
READ(AUTOFILE,T); DISKCHECK(IORESULT);
SEEK(AUTOFILE,I-1); DISKCHECK(IORESULT);
WRITE(AUTOFILE,T); DISKCHECK(IORESULT);
INC(I);
END;
DEC(I);
SEEK(AUTOFILE,I); DISKCHECK(IORESULT);
TRUNCATE(AUTOFILE); DISKCHECK(IORESULT);
{$I-}
END;
(*
MAIN MENU OPTION TO ACCESS SPECIFIED ACCOUNT.
RETURNS KEY CODE THAT CAUSED MAIN LOOP TO TERMINATE.
*)
FUNCTION ACCESSACCOUNT(ID: CHAR): CHAR;
VAR
CURDATE: DATEREC; { CURRENT DATE }
TRANS: TRANSREC;
F5TRANS, { IDENTIFYING STRINGS FOR F5/F6 KEYS }
F6TRANS: STRING[10];
TOPTRANS: LONGINT; { REC. NUMBER OF TRANS. AT TOP OF WINDOW }
CRSROFFSET: BYTE; { OFFSET FROM WINDOW TOP TO CURSOR }
OPT: CHAR;
SAVEDHC: BYTE;
B: BOOLEAN;
PROCEDURE SHOWBAL; { UPDATE DISPLAY OF REC./UNREC. BALANCES }
CONST
TCOL = 48; { COLUMN FOR BALANCE TITLES }
FCOL = 63; { COLUMN FOR BALANCE FIELDS }
VAR
W: BYTE;
BEGIN
W:=CURRENTWINDOW;
SELECTWINDOW(2);
WITH ACSTATUS[ID] DO
BEGIN
GOTOXY(TCOL,1);
WRITE('Reconciled ',
FORMAT(RECBAL/100,MNYZFORMAT));
GOTOXY(TCOL,2);
WRITE('Unreconciled ',
FORMAT(UNRECBAL/100,MNYZFORMAT),' *');
GOTOXY(FCOL,3);
WRITE(DUPLCHAR(#196,14));
GOTOXY(TCOL,4);
WRITE('Balance ',
FORMAT((RECBAL+UNRECBAL)/100,MNYDFORMAT));
GOTOXY(FCOL,5);
WRITE(DUPLCHAR(#205,14));
END;
SELECTWINDOW(W);
END; { SHOWBAL }
PROCEDURE TRANSPAGE; { DISPLAY PAGE OF TRANSACTIONS }
VAR
T: TRANSREC;
FS: LONGINT;
I: BYTE;
BEGIN
CLRSCR;
FS:=FILESIZE(TRANSFILE)-1;
FOR I:=0 TO 11 DO
BEGIN
READTRANS(TOPTRANS+I,T);
GOTOXY(1,I+1);
WRITEWINDOW(TRANSTOSTR(T));
IF TOPTRANS+I=FS THEN EXIT;
END;
END; { TRANSPAGE }
PROCEDURE MARKTRANS(M: BOOLEAN); { SET/CLEAR TRANSACTION MARKERS }
BEGIN
GOTOXY(1,CRSROFFSET+1);
IF M THEN
BEGIN
TEXTATTR:=HIGHCOLOR; WRITEWINDOW(#16);
END
ELSE
WRITEWINDOW(#32);
GOTOXY(80,CRSROFFSET+1);
IF M THEN
BEGIN
TEXTATTR:=HIGHCOLOR; WRITEWINDOW(#17);
END
ELSE
WRITEWINDOW(#32);
TEXTATTR:=MAINCOLOR;
END; { MARKTRANS }
{ MOVE FORWARD TO NEXT TRANSACTION.
RETURN TRUE IF SUCCESSFUL, FALSE IF ALREADY AT LAST TRANSACTION. }
FUNCTION NEXTTRANS: BOOLEAN;
BEGIN
NEXTTRANS:=TRUE;
IF TOPTRANS+CRSROFFSET+1<FILESIZE(TRANSFILE) THEN
IF CRSROFFSET<11 THEN
INC(CRSROFFSET)
ELSE
BEGIN
INC(TOPTRANS);
GOTOXY(1,1);
DELLINE;
GOTOXY(1,12);
READTRANS(TOPTRANS+11,TRANS);
WRITEWINDOW(TRANSTOSTR(TRANS));
END
ELSE
BEGIN
WRITE(BEL);
NEXTTRANS:=FALSE;
END;
END; { NEXTTRANS }
{ MOVE BACK TO PREVIOUS TRANSACTION.
RETURN TRUE IF SUCCESSFUL, FALSE IF ALREADY AT START OF FILE. }
FUNCTION PREVTRANS: BOOLEAN;
BEGIN
PREVTRANS:=TRUE;
IF CRSROFFSET<>0 THEN
DEC(CRSROFFSET)
ELSE
IF TOPTRANS<>0 THEN
BEGIN
DEC(TOPTRANS);
READTRANS(TOPTRANS,TRANS);
GOTOXY(1,1);
INSLINE;
WRITEWINDOW(TRANSTOSTR(TRANS));
END
ELSE
BEGIN
WRITE(BEL);
PREVTRANS:=FALSE;
END;
END; { PREVTRANS }
PROCEDURE FIRSTTRANS; { MOVE TO FIRST TRANSACTION }
BEGIN
TOPTRANS:=0;
CRSROFFSET:=0;
TRANSPAGE;
END;
PROCEDURE LASTTRANS; { MOVE TO LAST TRANSACTION }
BEGIN
TOPTRANS:=FILESIZE(TRANSFILE)-12;
IF TOPTRANS<0 THEN
BEGIN
TOPTRANS:=0;
CRSROFFSET:=FILESIZE(TRANSFILE)-1;
END
ELSE
CRSROFFSET:=11;
TRANSPAGE;
END;
PROCEDURE AUTOTRANS; { EDIT LIST OF AUTOMATIC ENTRIES }
CONST
TCOL = 15; { COLUMN FOR FIELD TITLES }
FCOL = 40; { COLUMN FOR FIELD EDITING }
VAR
T: AUTOREC; { AUTO TRANSACTION RECORD }
ATN: LONGINT; { CURRENT AUTO TRANSACTION NUMBER }
FIELD: BYTE; { EDIT FIELD INDICATOR }
C: CHAR;
S,TS: STRING[6];
I: LONGINT;
DMFLAG: BOOLEAN;
BEGIN
OPENWINDOW(8); { SET UP DISPLAY }
TEXTATTR:=TITLECOLOR;
WRITEWINDOW(PADR('Automatic transactions',80));
TEXTATTR:=MAINCOLOR;
GOTOXY(TCOL,3); WRITE('Date');
GOTOXY(TCOL,5); WRITE('Detail');
GOTOXY(TCOL,7); WRITE('Amount');
GOTOXY(FCOL+20,7); WRITE('(Zero for prompt)');
GOTOXY(TCOL,10); WRITE('Number of entries');
GOTOXY(FCOL+20,10); WRITE('(Zero for unlimited)');
GOTOXY(TCOL,12); WRITE('Interval');
SHOWOPTIONS(#24+#25,'Select','F4','Delete',
'F10','Accept','ESC','Abort');
ATN:=FILESIZE(AUTOFILE);
REPEAT { MAIN LOOP }
TEXTATTR:=TITLECOLOR;
GOTOXY(40,1); CLREOL;
IF ATN>=FILESIZE(AUTOFILE) THEN { CREATE NEW RECORD OR READ }
WITH T DO
BEGIN
DATE:=CURDATE;
UPDATE:=-1;
COUNT:=0;
AUTODRCR:=DEBIT;
AMOUNT:=0;
DETAIL:='';
WRITE('New');
END
ELSE
BEGIN
WRITE('#',ATN+1);
{$I-}
SEEK(AUTOFILE,ATN); DISKCHECK(IORESULT);
READ(AUTOFILE,T); DISKCHECK(IORESULT);
{$I+}
END;
GOTOXY(65,1); WRITE('Total: ',FILESIZE(AUTOFILE));
TEXTATTR:=MAINCOLOR;
FIELD:=0;
REPEAT { EDIT RECORD LOOP }
WITH T DO { DISPLAY RECORD }
BEGIN
GOTOXY(FCOL,3);
WRITE(#32,DATESTR(DATE));
GOTOXY(FCOL,5);
WRITE(PADR(DETAIL,DETAILLEN));
GOTOXY(FCOL,7);
WRITE(FORMAT(AMOUNT/100,MNYLZFORMAT));
CASE AUTODRCR OF
DEBIT: TS:='Debit ';
CREDIT: TS:='Credit';
END;
GOTOXY(FCOL,8); WRITE(TS);
GOTOXY(FCOL,10); WRITE(COUNT:4);
GOTOXY(FCOL,12);
IF UPDATE>0 THEN
BEGIN
WRITE(UPDATE:4);
S:=' Days ';
END
ELSE
BEGIN
WRITE(-UPDATE:4);
S:='Months';
END;
GOTOXY(FCOL,13); WRITE(S);
CASE FIELD OF { CALL EDIT ROUTINES }
0: BEGIN
GOTOXY(FCOL,3);
REPEAT
C:=EDITDATE(AUTODATEEDIT,DATE);
IF C='+' THEN
ADJUSTDATE(DATE,1);
IF C='-' THEN
ADJUSTDATE(DATE,-1);
UNTIL NOT(C IN ['+','-']);
END;
1: BEGIN
GOTOXY(FCOL,5);
C:=EDITSTRING(AUTODETAILEDIT,
DETAIL,DETAILLEN);
END;
2: BEGIN
GOTOXY(FCOL,7);
C:=EDITINT(AUTOMONEYEDIT,AMOUNT,
0,MAXMONEY);
END;
3: BEGIN
GOTOXY(FCOL,8);
C:=EDITSTRING(AUTOINTERVALEDIT,TS,6);
IF C=#32 THEN
BEGIN
CASE AUTODRCR OF
DEBIT: BEGIN
AUTODRCR:=CREDIT;
TS:='Credit';
END;
CREDIT: BEGIN
AUTODRCR:=DEBIT;
TS:='Debit ';
END;
END; { CASE AUTODRCR }
WRITE(TS);
END;
END;
4: BEGIN
GOTOXY(FCOL,10);
C:=EDITINT(AUTONUMEDIT,COUNT,0,9999);
END;
5: BEGIN
GOTOXY(FCOL,12);
DMFLAG:=(UPDATE<0);
IF DMFLAG THEN
UPDATE:=-UPDATE;
C:=EDITINT(AUTONUMEDIT,UPDATE,1,9999);
IF DMFLAG THEN
UPDATE:=-UPDATE;
END;
6: BEGIN
GOTOXY(FCOL,13);
C:=EDITSTRING(AUTOINTERVALEDIT,S,6);
IF C=#32 THEN
BEGIN
UPDATE:=-UPDATE;
IF UPDATE>0 THEN
S:=' Days '
ELSE
S:='Months';
WRITE(S);
END;
END;
END; { CASE FIELD }
CASE C OF { MOVE TO NEXT FIELD }
KEYUP,KEYSTAB:
IF FIELD=0 THEN FIELD:=6 ELSE DEC(FIELD);
CR,KEYDOWN,HT:
IF FIELD=6 THEN FIELD:=0 ELSE INC(FIELD);
END; { CASE C }
END; { WITH T }
UNTIL C IN
[KEYF10,ESC,KEYPGUP,KEYPGDN,KEYCPGUP,KEYCPGDN,KEYF4];
IF C=KEYF4 THEN
IF ATN>=FILESIZE(AUTOFILE) THEN
WRITE(BEL)
ELSE { DELETE A RECORD }
BEGIN
IF GETYESNO('Delete automatic transaction',
'Are you sure?') THEN
DELETEAUTOTRANSENTRY(ATN);
END
ELSE
BEGIN
IF ((ATN<FILESIZE(AUTOFILE)) AND
(C<>ESC)) OR (C=KEYF10) THEN
BEGIN { UPDATE RECORD }
{$I-}
SEEK(AUTOFILE,ATN); DISKCHECK(IORESULT);
WRITE(AUTOFILE,T); DISKCHECK(IORESULT);
{$I+}
END;
CASE C OF { MOVE TO NEXT RECORD }
KEYPGUP: IF ATN>0 THEN
DEC(ATN)
ELSE
ATN:=FILESIZE(AUTOFILE);
KEYPGDN: IF ATN<FILESIZE(AUTOFILE) THEN
INC(ATN)
ELSE
ATN:=0;
KEYCPGUP: ATN:=0;
KEYCPGDN: ATN:=FILESIZE(AUTOFILE);
END; { CASE }
END;
UNTIL C IN [KEYF10,ESC];
CLOSEWINDOW(8); { TIDY UP DISPLAY }
END; { AUTOTRANS }
{ ENTER A TRANSACTION. RETURNS TRUE IF TRANSACTION ACCEPTED,
FALSE IF ENTRY ABORTED. }
FUNCTION ENTERTRANS: BOOLEAN;
CONST
TCOL = 15; { COLUMN FOR FIELD TITLES }
FCOL = 40; { COLUMN FOR EDIT FIELDS }
VAR
NEWTRANS: TRANSREC;
VALIDAUXAC, { CONTROL OF AUXILIARY A/C SELECTION }
OPTCREDIT, { CONTROL OF CREDIT A/C FIELD }
OPTCHECKNUM, { CONTROL OF CHECK NUMBER FIELD }
OPTCHECKAC: BOOLEAN; { CONTROL OF CHECKING A/C FIELD }
D: DATEREC;
FIELD: BYTE; { POS. FOR FIELD EDITING }
CN: LONGINT; { CHECK NUMBER FOR EDITING }
PREVAC,
AC: STRING[1]; { CREDIT/CHECKING A/C FOR EDITING }
C: CHAR;
BEGIN
OPENWINDOW(8); { SET UP ENTRY AREA OF DISPLAY }
WITH NEWTRANS DO { INITIALIZE NEW TRANSACTION RECORD }
BEGIN
DATE:=DATETOWORD(CURDATE);
AMOUNT:=0;
RECON:=UNREC;
WITH ACSTATUS[ID] DO
CASE OPT OF
KEYF7: DETAIL:=DRDEFAULT;
KEYF8: DETAIL:=CRDEFAULT;
ELSE
DETAIL:='';
END;
END; { WITH NEWTRANS }
TEXTATTR:=TITLECOLOR; { DISPLAY ENTRY WINDOW TITLE }
CASE OPT OF
KEYF4: WRITEWINDOW(JUSTC('Transfer funds',80));
KEYF5: WRITEWINDOW(JUSTC(F5TRANS,80));
KEYF6: WRITEWINDOW(JUSTC(F6TRANS,80));
KEYF7: WRITEWINDOW(JUSTC('Miscellaneous debit',80));
KEYF8: WRITEWINDOW(JUSTC('Miscellaneous credit',80));
END;
SHOWOPTIONS(#24+#25,'Select','','','F10','Accept','ESC','Abort');
TEXTATTR:=MAINCOLOR;
WITH ACSTATUS[ID] DO { CHECK WHICH OPTIONS REQUIRED }
BEGIN
OPTCREDIT:=(OPT=KEYF4) OR
((OPT=KEYF5) AND (ACTYPE=CHECKING));
OPTCHECKNUM:=((OPT=KEYF5) AND (ACTYPE=CHECKING)) OR
((OPT=KEYF6) AND (ACTYPE=CARD));
OPTCHECKAC:=(OPT=KEYF6) AND (ACTYPE=CARD);
AC:=' ';
IF ACTYPE=CHECKING THEN
CN:=CHECKNUM
ELSE
CN:=0;
END;
GOTOXY(TCOL,3); WRITE('Date'); { SET UP FIELDS }
GOTOXY(FCOL,3); WRITE(#32,DATESTR(CURDATE));
IF OPT<>KEYF4 THEN
BEGIN
GOTOXY(TCOL,5); WRITE('Detail');
END;
GOTOXY(TCOL,7); WRITE('Amount');
IF OPTCREDIT THEN
BEGIN
GOTOXY(TCOL,9); WRITE('Credit A/C');
END;
IF OPTCHECKAC THEN
BEGIN
GOTOXY(TCOL,9); WRITE('Checking A/C');
END;
IF OPTCHECKNUM THEN
WITH ACSTATUS[ID] DO
BEGIN
GOTOXY(TCOL,11); WRITE('Check number');
IF ACTYPE=CHECKING THEN
BEGIN
GOTOXY(FCOL,11);
WRITE(FORMAT(CHECKNUM,CHKFORMAT));
END;
END;
FIELD:=0; { SET STARTING FIELD }
WITH NEWTRANS DO
REPEAT { MAIN EDIT LOOP }
CASE FIELD OF
0: BEGIN { EDIT DATE }
GOTOXY(FCOL,3);
WORDTODATE(DATE,D);
REPEAT
C:=EDITDATE(TRANSDATEEDIT,D);
IF C='+' THEN
ADJUSTDATE(D,1);
IF C='-' THEN
ADJUSTDATE(D,-1);
UNTIL NOT(C IN ['+','-']);
DATE:=DATETOWORD(D);
END;
1: IF OPT<>KEYF4 THEN { EDIT DETAIL }
BEGIN
GOTOXY(FCOL,5);
IF (ACSTATUS[ID].ACTYPE=CHECKING) AND
(OPT=KEYF5) THEN
C:=EDITSTRING
(ACNAMEEDIT,DETAIL,DETAILLEN-7)
ELSE
C:=EDITSTRING(ACNAMEEDIT,DETAIL,DETAILLEN);
END;
2: BEGIN { EDIT AMOUNT }
GOTOXY(FCOL,7);
C:=EDITINT(MONEYEDIT,AMOUNT,0,MAXMONEY);
END;
3: BEGIN { EDIT AUX. ACCOUNT ID }
GOTOXY(FCOL,9);
REPEAT
PREVAC:=AC;
C:=EDITSTRING(ACREFEDIT,AC,1);
VALIDAUXAC:=TRUE;
IF AC[1]<>#32 THEN
CASE ACSTATUS[AC[1]].ACTYPE OF
UNUSED:
BEGIN
VALIDAUXAC:=FALSE;
DISPLAYERROR
('Account not in use');
AC:=PREVAC;
END;
SAVINGS,
CARD:
IF OPTCHECKAC THEN
BEGIN
VALIDAUXAC:=FALSE;
DISPLAYERROR
('Not a checking account');
AC:=PREVAC;
END;
END; { CASE }
IF AC[1]=ID THEN
BEGIN
VALIDAUXAC:=FALSE;
DISPLAYERROR
('Cannot transfer to same account');
AC:=PREVAC;
END;
UNTIL VALIDAUXAC;
IF OPTCHECKAC AND (PREVAC[1]<>AC[1]) THEN
BEGIN
GOTOXY(FCOL,11);
IF AC[1]<>#32 THEN
BEGIN
CN:=ACSTATUS[AC[1]].CHECKNUM;
WRITE(FORMAT(CN,CHKFORMAT));
DETAIL:='PAYMENT: '+AC[1]+'-'+
FORMAT(CN,CHKFORMAT);
GOTOXY(FCOL,5);
WRITE(PADR(DETAIL,DETAILLEN));
END
ELSE
BEGIN
WRITE('':6);
CN:=0;
DETAIL:='';
GOTOXY(FCOL,5); CLREOL;
END;
END;
END;
4: BEGIN { EDIT CHECK NUMBER }
GOTOXY(FCOL,11);
IF CN<>0 THEN
BEGIN
C:=EDITINT(CHECKNUMEDIT,
CN,1,MAXCHECKNUM);
IF (AC[1]<>#32) AND (OPT<>KEYF5) THEN
BEGIN
DETAIL:='PAYMENT: '+AC[1]+'-'+
FORMAT(CN,CHKFORMAT);
GOTOXY(FCOL,5);
WRITE(PADR(DETAIL,DETAILLEN));
END;
END;
END;
END; { CASE FIELD }
CASE C OF { MOVE TO NEXT FIELD, AS REQUIRED }
KEYUP,
KEYSTAB:
IF FIELD=0 THEN
IF OPTCHECKNUM THEN
FIELD:=4
ELSE
IF OPTCREDIT THEN
FIELD:=3
ELSE
FIELD:=2
ELSE
DEC(FIELD);
CR,
KEYDOWN,
HT:
BEGIN
INC(FIELD);
IF (FIELD=3) AND
NOT(OPTCREDIT OR OPTCHECKAC) THEN
FIELD:=0;
IF (FIELD=4) AND NOT(OPTCHECKNUM) THEN
FIELD:=0;
END;
END; { CASE C }
VALIDAUXAC:=(OPT<>KEYF4) OR (AC[1]<>#32) OR (C=ESC);
IF (C=KEYF10) AND NOT(VALIDAUXAC) THEN
BEGIN
DISPLAYERROR('Transfer account not specified');
FIELD:=3;
END;
UNTIL (C IN [KEYF10,ESC]) AND VALIDAUXAC;
IF C=KEYF10 THEN { PROCESS TRANSACTION }
BEGIN
WORDTODATE(NEWTRANS.DATE,CURDATE);
WITH ACSTATUS[ID] DO { ADD CHECK NUMBER, UPDATE NEXT }
IF (ACTYPE=CHECKING) AND (OPT=KEYF5) THEN
BEGIN
NEWTRANS.DETAIL:=FORMAT(CN,CHKFORMAT)+' '+
NEWTRANS.DETAIL;
CHECKNUM:=CN+1;
END;
IF OPT=KEYF4 THEN { ADD DESCRIPTION FOR TRANSFER }
NEWTRANS.DETAIL:='Transfer to A/C '+AC[1];
IF OPT IN [KEYF4,KEYF5,KEYF7] THEN { NEGATE IF DEBIT }
NEWTRANS.AMOUNT:=-NEWTRANS.AMOUNT;
ADDTRANS(ACSTATUS[ID],NEWTRANS);
IF AC[1]<>#32 THEN { CHECK FOR AUX. ACCOUNT ENTRY }
BEGIN
{$I-}
CLOSE(TRANSFILE);
DISKCHECK(IORESULT); { SWITCH TO AUX. }
ASSIGN(TRANSFILE,DATAFILEPATH+TRANSFN+AC[1]+FNEXT);
RESET(TRANSFILE); DISKCHECK(IORESULT);
WITH NEWTRANS DO
BEGIN
AMOUNT:=-AMOUNT; { SWAP DR/CR ENTRY }
IF OPTCREDIT THEN { CHANGE DETAIL FIELD }
IF OPT=KEYF4 THEN
DETAIL:='Transfer from A/C '+ID
ELSE
DETAIL:='Transfer: '+ID+'-'+
FORMAT(CN,CHKFORMAT)
ELSE
WITH ACSTATUS[AC[1]] DO
BEGIN
DETAIL:=FORMAT(CN,CHKFORMAT)+
' Account '+ID;
CHECKNUM:=CN+1;
END;
END; { WITH NEWTRANS }
ADDTRANS(ACSTATUS[AC[1]],NEWTRANS);
{ ADD AUX. TRANSACTION }
CLOSE(TRANSFILE);
DISKCHECK(IORESULT); { SWITCH BACK ACCOUNT }
ASSIGN(TRANSFILE,DATAFILEPATH+TRANSFN+ID+FNEXT);
RESET(TRANSFILE); DISKCHECK(IORESULT);
{$I+}
END;
ENTERTRANS:=TRUE;
END
ELSE
ENTERTRANS:=FALSE;
CLOSEWINDOW(8); { RESTORE DISPLAY }
END; { ENTERTRANS }
PROCEDURE PRINTTRANS; { PRINT TRANSACTIONS }
VAR
T: TRANSREC; { TRANSACTION STORAGE }
B: LONGINT; { BALANCE }
I: LONGINT; { TRANSACTION RECORD NUMBER }
PN: WORD; { PAGE NUMBER }
LC: BYTE; { LINE COUNTER }
BEGIN
MARKTRANS(TRUE);
IF GETYESNO('Print from current transaction to end',
'Are you sure?') THEN
BEGIN
OPENWINDOW(3); { SET UP }
WRITEWINDOW(JUSTC('Printing - Please wait',38));
GOTOXY(1,2);
WRITEWINDOW(JUSTC('Press ESC to abort',38));
I:=TOPTRANS+CRSROFFSET;
READTRANS(I,T);
B:=T.BALANCE-T.AMOUNT;
PN:=1; LC:=0;
WHILE (I<FILESIZE(TRANSFILE)) DO
BEGIN { FOR EACH TRANSACTION }
READTRANS(I,T);
IF LC=0 THEN { PRINT PAGE HEADING IF NECESSARY }
WITH ACSTATUS[ID] DO
BEGIN
WRITELN(PRN);
WRITELN(PRN,ID+': '+PADR(NAME,68),
'Page ',PN:3);
WRITELN(PRN,DUPLCHAR('-',79));
WRITELN(PRN);
WRITELN(PRN,' Date ',
'Detail ',
'Debit':14,' ','Credit':14,' ',
'Balance':14,' Rec');
WRITELN(PRN);
IF T.RECON<>BAL THEN
BEGIN
WRITELN(PRN,'':11,
PADR('Balance b/f',51),
FORMAT(B/100,MNYZFORMAT));
WRITELN(PRN);
LC:=8;
END
ELSE
LC:=6;
INC(PN);
END;
WRITELN(PRN,TRANSTOSTR(T));
{ PRINT TRANSACTION }
INC(LC);
IF KEYPRESSED THEN { CHECK FOR USR ABORT }
IF READKEY=ESC THEN
BEGIN
WRITELN(PRN);
WRITELN(PRN,'Aborted by user');
WRITE(PRN,FF);
CLOSEWINDOW(3);
EXIT;
END;
IF (LC=53) AND
(I<(FILESIZE(TRANSFILE)-1)) THEN
BEGIN
B:=T.BALANCE;
WRITELN(PRN);
WRITELN(PRN,'':11,
PADR('Balance c/f',51),
FORMAT(B/100,MNYZFORMAT),FF);
LC:=0;
END;
INC(I);
END;
IF LC<>0 THEN
WRITE(PRN,FF);
CLOSEWINDOW(3); { RESTORE DISPLAY }
END;
MARKTRANS(FALSE);
END; { PRINTTRANS }
{ PURGE TRANSACTIONS FROM FILE AND UPDATE B/F BALANCE.
RETURNS TRUE IF PURGE CARRIED OUT, OTHERWISE RETURNS FALSE. }
FUNCTION PURGETRANS: BOOLEAN;
VAR
B,T: TRANSREC;
I,J: LONGINT;
BEGIN
PURGETRANS:=FALSE;
I:=TOPTRANS+CRSROFFSET;
IF I=0 THEN
BEGIN
DISPLAYERROR('No transactions to purge');
EXIT;
END;
REPEAT
READTRANS(I,T);
IF T.RECON=UNREC THEN
BEGIN
DISPLAYERROR('Cannot purge - Unreconciled entries');
EXIT;
END;
DEC(I);
UNTIL I=0;
MARKTRANS(TRUE);
WRITE(BEL,BEL);
IF GETYESNO('Purge to current transaction','Are you sure?') THEN
BEGIN
I:=0;
J:=TOPTRANS+CRSROFFSET;
READTRANS(I,B);
READTRANS(J,T);
B.AMOUNT:=T.BALANCE;
B.BALANCE:=B.AMOUNT;
WRITETRANS(I,B);
INC(I); INC(J);
WHILE (J<FILESIZE(TRANSFILE)) DO
BEGIN
READTRANS(J,T);
WRITETRANS(I,T);
INC(I); INC(J);
END;
SEEK(TRANSFILE,I); DISKCHECK(IORESULT);
TRUNCATE(TRANSFILE); DISKCHECK(IORESULT);
PURGETRANS:=TRUE;
END;
MARKTRANS(FALSE);
END; { PURGETRANS }
BEGIN { ACCESSACCOUNT }
SAVEDHC:=HELPCONTEXT;
GETTODAY(CURDATE);
SELECTWINDOW(1); { SET UP DISPLAY }
CLRSCR;
WRITE(PADR(ID+': '+ACSTATUS[ID].NAME,70),DATESTR(CURDATE));
SELECTWINDOW(2);
CLRSCR;
{ OPEN APPROPRIATE FILES }
ASSIGN(TRANSFILE,DATAFILEPATH+TRANSFN+ID+FNEXT);
ASSIGN(AUTOFILE,DATAFILEPATH+AUTOFN+ID+FNEXT);
{$I-}
RESET(TRANSFILE); DISKCHECK(IORESULT);
RESET(AUTOFILE); DISKCHECK(IORESULT);
{$I+}
CASE ACSTATUS[ID].ACTYPE OF { SET NAMES OF MAIN DR/CR OPTIONS }
CHECKING: BEGIN
F5TRANS:='Check'; F6TRANS:='Deposit';
END;
SAVINGS: BEGIN
F5TRANS:='Withdrawal'; F6TRANS:='Deposit';
END;
CARD: BEGIN
F5TRANS:='Purchase'; F6TRANS:='Payment';
END;
END; { CASE }
TEXTATTR:=HIGHCOLOR; WRITE('F2');
TEXTATTR:=MAINCOLOR; WRITELN(' Purge');
TEXTATTR:=HIGHCOLOR; WRITE('F3');
TEXTATTR:=MAINCOLOR; WRITELN(' Auto entries');
TEXTATTR:=HIGHCOLOR; WRITE('F4');
TEXTATTR:=MAINCOLOR; WRITELN(' Transfer');
TEXTATTR:=HIGHCOLOR; WRITE('F9');
TEXTATTR:=MAINCOLOR; WRITELN(' Print');
GOTOXY(25,1);
TEXTATTR:=HIGHCOLOR; WRITE('F5');
TEXTATTR:=MAINCOLOR; WRITE(#32,F5TRANS);
GOTOXY(25,2);
TEXTATTR:=HIGHCOLOR; WRITE('F6');
TEXTATTR:=MAINCOLOR; WRITE(#32,F6TRANS);
GOTOXY(25,3);
TEXTATTR:=HIGHCOLOR; WRITE('F7');
TEXTATTR:=MAINCOLOR; WRITE(' Misc. debit');
GOTOXY(25,4);
TEXTATTR:=HIGHCOLOR; WRITE('F8');
TEXTATTR:=MAINCOLOR; WRITE(' Misc. credit');
GOTOXY(1,7);
TEXTATTR:=TITLECOLOR;
WRITE(' Date ','Detail ','Debit':14,' ',
'Credit':14,' ','Balance':14,' Rec');
TEXTATTR:=MAINCOLOR;
SHOWBAL;
OPENWINDOW(6); { WINDOW FOR VIEWING TRANSACTIONS }
LASTTRANS;
WITH ACSTATUS[ID] DO
BEGIN
REPEAT { MAIN LOOP }
SHOWOPTIONS(#24+#25,'Select','Enter','Rec',
'+ -','Next unrec','ESC','Main menu');
MARKTRANS(TRUE);
OPT:=READKEY;
MARKTRANS(FALSE);
CASE OPT OF
KEYUP:
B:=PREVTRANS;
KEYDOWN:
B:=NEXTTRANS;
KEYPGUP:
IF TOPTRANS+CRSROFFSET=0 THEN
WRITE(BEL)
ELSE
BEGIN
TOPTRANS:=TOPTRANS-11;
IF TOPTRANS<0 THEN
BEGIN
TOPTRANS:=0;
CRSROFFSET:=0;
END;
TRANSPAGE;
END;
KEYPGDN:
IF TOPTRANS+CRSROFFSET+1=FILESIZE(TRANSFILE) THEN
WRITE(BEL)
ELSE
BEGIN
TOPTRANS:=TOPTRANS+11;
IF TOPTRANS+11>=FILESIZE(TRANSFILE) THEN
BEGIN
TOPTRANS:=FILESIZE(TRANSFILE)-12;
IF TOPTRANS<0 THEN
BEGIN
TOPTRANS:=0;
CRSROFFSET:=
FILESIZE(TRANSFILE)-1;
END
ELSE
CRSROFFSET:=11;
END;
TRANSPAGE;
END;
KEYHOME: FIRSTTRANS;
KEYEND: LASTTRANS;
HT,'+':
REPEAT
B:=NEXTTRANS;
READTRANS(TOPTRANS+CRSROFFSET,TRANS);
UNTIL NOT(B) OR (TRANS.RECON=UNREC);
KEYSTAB,'-':
REPEAT
B:=PREVTRANS;
READTRANS(TOPTRANS+CRSROFFSET,TRANS);
UNTIL NOT(B) OR (TRANS.RECON=UNREC);
CR: BEGIN
READTRANS(TOPTRANS+CRSROFFSET,TRANS);
WITH TRANS DO
CASE RECON OF
UNREC: BEGIN
RECON:=REC;
UNRECBAL:=UNRECBAL-AMOUNT;
RECBAL:=RECBAL+AMOUNT;
END;
REC: BEGIN
RECON:=UNREC;
RECBAL:=RECBAL-AMOUNT;
UNRECBAL:=UNRECBAL+AMOUNT;
END;
BAL: DISPLAYERROR
('Cannot reconcile b/f balance');
END;
WRITETRANS(TOPTRANS+CRSROFFSET,TRANS);
GOTOXY(1,CRSROFFSET+1);
WRITEWINDOW(TRANSTOSTR(TRANS));
SHOWBAL;
END;
KEYF2: IF PURGETRANS THEN FIRSTTRANS;
KEYF3:
BEGIN
HELPCONTEXT:=7;
AUTOTRANS;
END;
KEYF4,KEYF5,KEYF6,KEYF7,KEYF8:
BEGIN
CASE OPT OF
KEYF4: HELPCONTEXT:=8;
KEYF5: CASE ACTYPE OF
CHECKING: HELPCONTEXT:=9;
SAVINGS: HELPCONTEXT:=10;
CARD: HELPCONTEXT:=11;
END;
KEYF6: IF ACTYPE=CARD THEN
HELPCONTEXT:=13
ELSE
HELPCONTEXT:=12;
KEYF7: HELPCONTEXT:=14;
KEYF8: HELPCONTEXT:=15;
END; { CASE OPT }
IF ENTERTRANS THEN
BEGIN
SHOWBAL;
LASTTRANS;
END;
END;
KEYF9: PRINTTRANS;
END; { CASE OPT }
HELPCONTEXT:=SAVEDHC;
UNTIL OPT IN [ESC,KEYCPGUP,KEYCPGDN,KEYCHOME,KEYCEND];
END; { WITH ACSTATUS[ID] }
ACCESSACCOUNT:=OPT; { RETURN TERMINATING KEY }
CLOSEWINDOW(6); { CLEAR DISPLAY }
{$I-}
CLOSE(TRANSFILE); DISKCHECK(IORESULT); { CLOSE ACCOUNT FILES }
CLOSE(AUTOFILE); DISKCHECK(IORESULT);
{$I+}
UPDATEACSTATFILE;
END; { ACCESSACCOUNT }
(*
DISPLAY SUMMARY OF ACCOUNT BALANCES.
*)
PROCEDURE ACCOUNTSUMMARY;
VAR
BAL: ARRAY[ACCOUNTTYPE] OF LONGINT;
T: ACCOUNTTYPE;
DT: DATEREC;
C: CHAR;
BEGIN
CLRSCR;
SHOWOPTIONS('','','F9','Print','','','ESC','Main menu');
GOTOXY(1,3);
WRITEWINDOW(JUSTC('SUMMARY OF ACCOUNTS',80));
BAL[CHECKING]:=0;
BAL[SAVINGS]:=0;
BAL[CARD]:=0;
FOR C:='A' TO 'Z' DO
WITH ACSTATUS[C] DO
BAL[ACTYPE]:=BAL[ACTYPE]+RECBAL+UNRECBAL;
GOTOXY(1,8);
WRITELN('':25,'Checking accounts',
FORMAT(BAL[CHECKING]/100,MNYZFORMAT));
WRITELN('':25,'Savings accounts ',
FORMAT(BAL[SAVINGS]/100,MNYZFORMAT));
WRITELN('':25,'Credit accounts ',
FORMAT(BAL[CARD]/100,MNYZFORMAT));
WRITELN('':42,DUPLCHAR(#196,14));
WRITELN('':25,'Total ',
FORMAT((BAL[CHECKING]+BAL[SAVINGS]+BAL[CARD])/100,MNYDFORMAT));
WRITELN('':42,DUPLCHAR(#205,14));
REPEAT
C:=READKEY;
IF C=KEYF9 THEN
IF GETYESNO('Print detailed summary','Are you sure?') THEN
BEGIN
GETTODAY(DT);
WRITELN(PRN);
WRITELN(PRN,PADR('ACCOUNTS SUMMARY',70),DATESTR(DT));
WRITELN(PRN,DUPLCHAR('-',79));
WRITELN(PRN,DUPLCHAR(LF,5));
FOR T:=CHECKING TO CARD DO
BEGIN
CASE T OF
CHECKING:
WRITELN(PRN,'Checking accounts',LF);
SAVINGS:
WRITELN(PRN,'Savings accounts',LF);
CARD:
WRITELN(PRN,'Credit accounts',LF);
END;
FOR C:='A' TO 'Z' DO
WITH ACSTATUS[C] DO
IF ACTYPE=T THEN
WRITELN(PRN,
C:10,' ',PADR(NAME,33),
FORMAT((RECBAL+UNRECBAL)/100,
MNYFORMAT));
WRITELN(PRN,'':46,DUPLCHAR('-',14),
FORMAT(BAL[T]/100,
MNYZFORMAT),LF,LF);
END;
WRITELN(PRN,LF,'':60,DUPLCHAR('-',14));
WRITELN(PRN,'':60,
FORMAT((BAL[CHECKING]+BAL[SAVINGS]+BAL[CARD])/100,
MNYDFORMAT));
WRITE(PRN,'':60,DUPLCHAR('=',14),FF);
END;
UNTIL C=ESC;
END; { ACCOUNTSUMMARY }
(*
MAIN MENU OPTION TO SET-UP ACCOUNTS AND MISCELLANEOUS DATA.
*)
PROCEDURE ACCOUNTSETUP;
VAR
CURDATE: DATEREC;
C: CHAR;
FUNCTION ACTYPETOSTR(T: ACCOUNTTYPE): STRING; { CONVERT TYPE TO STRING }
BEGIN
CASE T OF
CHECKING: ACTYPETOSTR:='Checking ';
SAVINGS: ACTYPETOSTR:='Savings ';
CARD: ACTYPETOSTR:='Credit/Loan';
UNUSED: ACTYPETOSTR:='DELETE ';
END;
END; { ACTYPETOSTR }
PROCEDURE EDITACCOUNTSTAT(ID: CHAR); { CREATE/EDIT ACCOUNT DETAILS }
CONST
TCOL = 12;
FCOL = 35;
VAR
STAT: ACCOUNTREC;
T: TRANSREC;
FIELD: BYTE;
R: BYTE;
C: CHAR;
S: STRING[11];
NEWAC: BOOLEAN;
BEGIN
STAT:=ACSTATUS[ID];
ASSIGN(TRANSFILE,DATAFILEPATH+TRANSFN+ID+FNEXT);
ASSIGN(AUTOFILE,DATAFILEPATH+AUTOFN+ID+FNEXT);
NEWAC:=(STAT.ACTYPE=UNUSED);
IF NEWAC THEN { CREATE A NEW ACCOUNT }
BEGIN
IF GETYESNO('Account '+ID+' not in use at present',
'Create this account?') THEN
BEGIN
STAT.ACTYPE:=CHECKING;
STAT.NAME:='Account name';
END
ELSE
EXIT;
END;
CLRSCR; { DISPLAY CURRENT DETAILS }
WRITEWINDOW(JUSTC('Account '+ID,80));
SHOWOPTIONS(#24+#25,'Select','','','F10','Accept','ESC','Abort');
WITH STAT DO
BEGIN
GOTOXY(TCOL,5);
WRITE('Account type ',ACTYPETOSTR(ACTYPE));
GOTOXY(TCOL,7);
WRITE('Name ',NAME);
GOTOXY(TCOL,9);
WRITE('Debit default ',DRDEFAULT);
GOTOXY(TCOL,11);
WRITE('Credit default ',CRDEFAULT);
GOTOXY(TCOL,13);
WRITE('Next check no. ',
FORMAT(CHECKNUM,CHKFORMAT));
FIELD:=0;
REPEAT
CASE FIELD OF
0: BEGIN { EDIT ACCOUNT TYPE }
GOTOXY(FCOL,5);
S:=ACTYPETOSTR(ACTYPE);
C:=EDITSTRING(ACTYPEEDIT,S,11);
IF C=#32 THEN
IF ACTYPE=CARD THEN
IF NEWAC THEN
ACTYPE:=CHECKING
ELSE
ACTYPE:=UNUSED
ELSE
INC(ACTYPE);
END;
1: BEGIN { EDIT ACCOUNT NAME }
GOTOXY(FCOL,7);
C:=EDITSTRING(ACNAMEEDIT,NAME,ACNAMELEN);
END;
2: BEGIN { EDIT DEBIT TEXT }
GOTOXY(FCOL,9);
C:=EDITSTRING(ACNAMEEDIT,DRDEFAULT,
DETAILLEN);
END;
3: BEGIN { EDIT CREDIT TEXT }
GOTOXY(FCOL,11);
C:=EDITSTRING(ACNAMEEDIT,CRDEFAULT,
DETAILLEN);
END;
4: BEGIN { EDIT CHECK NUMBER }
GOTOXY(FCOL,13);
C:=EDITINT(CHECKNUMEDIT,CHECKNUM,
1,MAXCHECKNUM);
END;
END; { CASE FIELD }
CASE C OF { MOVE TO SELECTED FIELD }
KEYUP,KEYSTAB:
IF FIELD=0 THEN FIELD:=4 ELSE DEC(FIELD);
KEYDOWN,HT,CR:
IF FIELD=4 THEN FIELD:=0 ELSE INC(FIELD);
END;
IF C=KEYF10 THEN
IF (ACTYPE=UNUSED) AND
(ACSTATUS[ID].ACTYPE<>UNUSED) THEN
IF (RECBAL=0) AND (UNRECBAL=0) THEN
{ ALLOW DEL IF ZERO BAL & ALL RECONCILED }
BEGIN
WRITE(BEL,BEL);
IF GETYESNO('Delete '+NAME,
'Are you sure?') THEN
BEGIN
NAME:='';
RECBAL:=0;
UNRECBAL:=0;
DRDEFAULT:='';
CRDEFAULT:='';
CHECKNUM:=1;
{$I-}
ERASE(TRANSFILE);
R:=IORESULT;
IF R<>2 THEN
DISKCHECK(R);
ERASE(AUTOFILE);
R:=IORESULT;
IF R<>2 THEN
DISKCHECK(R);
{$I+}
END
ELSE
C:=NUL;
END
ELSE
BEGIN
IF UNRECBAL<>0 THEN
DISPLAYERROR
('Cannot delete - Unreconciled entries')
ELSE
DISPLAYERROR
('Cannot delete - Balance is not zero');
C:=NUL;
END;
UNTIL C IN [KEYF10,ESC]; { RPT UNTIL ACCEPT OR ABORT }
END; { WITH STAT }
IF C=KEYF10 THEN
BEGIN
ACSTATUS[ID]:=STAT; { IF CHANGES ACCEPTED, UPDATE AC REC. }
IF NEWAC THEN { IF NEW ACCOUNT, CREATE FILES }
BEGIN
{$I-}
REWRITE(TRANSFILE); DISKCHECK(IORESULT);
WITH T DO
BEGIN
DATE:=DATETOWORD(CURDATE);
AMOUNT:=0;
BALANCE:=0;
DETAIL:='Balance b/f';
RECON:=BAL;
END;
WRITETRANS(0,T);
CLOSE(TRANSFILE); DISKCHECK(IORESULT);
REWRITE(AUTOFILE); DISKCHECK(IORESULT);
CLOSE(AUTOFILE); DISKCHECK(IORESULT);
{$I+}
END;
END;
END; { EDITACCOUNTSTAT }
BEGIN { ACCOUNTSETUP }
GETTODAY(CURDATE);
SELECTWINDOW(1); { DISPLAY OPTIONS }
CLRSCR;
WRITE(PADR('ACCOUNT MAINTENANCE',70),DATESTR(CURDATE));
REPEAT
SELECTWINDOW(2);
LISTACCOUNTS;
SHOWOPTIONS('','','A-Z','Select','','','ESC','Main menu');
C:=UPCASE(READKEY); { GET CHOICE, ACT AS REQUIRED }
PUSHHELPCONTEXT(5);
IF C IN ['A'..'Z'] THEN
EDITACCOUNTSTAT(C);
POPHELPCONTEXT;
UNTIL C=ESC;
UPDATEACSTATFILE;
END; { ACCOUNTSETUP }
(*
PROCESS AUTOMATIC TRANSACTION ENTRIES.
*)
PROCEDURE PROCESSAUTOTRANS;
VAR
T: TRANSREC;
ATR: AUTOREC;
DT: DATEREC;
D: WORD;
I: LONGINT;
C,CC: CHAR;
FUNCTION UPDATEAUTOTRANS: BOOLEAN;
{ MODIFY RECORD, RETURN TRUE FOR DELETE }
BEGIN
WITH ATR DO
BEGIN
IF UPDATE>0 THEN { ADD REQUIRED NUMBER OF DAYS }
ADJUSTDATE(DATE,UPDATE)
ELSE { OTHERWISE, ADD MONTHS }
WITH DATE DO
BEGIN
M:=M-UPDATE;
WHILE (M>12) DO { ADJ IF PAST END OF YEAR }
BEGIN
INC(Y);
M:=M-12;
END;
{ IF 28 OR LATER, SET LAST DAY OF MONTH }
IF D>=28 THEN
SETLASTDAY(DATE);
END;
UPDATEAUTOTRANS:=FALSE;
IF COUNT<>0 THEN { ZERO FOR UNLIMITED }
IF COUNT=1 THEN { IF LAST ENTRY, FLAG DELETION }
UPDATEAUTOTRANS:=TRUE
ELSE
DEC(COUNT);
END; { WITH ATR }
END; { UPDATEAUTOTRANS }
FUNCTION REQUESTAMOUNT(VAR T: TRANSREC; AC: CHAR): CHAR;
{ SHOW TRANSACTION, GET AMOUNT. RETURNS CR IF ENTERED,
KEYF3 TO SKIP, KEYF4 TO DELETE, ESC TO POSTPONE. }
VAR
DT: DATEREC;
C: CHAR;
HC: BYTE;
BEGIN
PUSHHELPCONTEXT(16);
SHOWOPTIONS('F3','Skip','','Enter amount',
'F4','Delete','ESC','Postpone');
GOTOXY(1,5); TEXTATTR:=TITLECOLOR;
WRITEWINDOW(JUSTC(ACSTATUS[AC].NAME,80));
TEXTATTR:=MAINCOLOR; GOTOXY(1,8);
WORDTODATE(T.DATE,DT);
WITH T DO
WRITEWINDOW(JUSTC(DATESTR(DT)+' '+DETAIL,80));
GOTOXY(32,11);
REPEAT
C:=EDITINT(APMONEYEDIT,T.AMOUNT,0,MAXMONEY);
IF (T.AMOUNT=0) THEN
REQUESTAMOUNT:=ESC
ELSE
REQUESTAMOUNT:=CR;
IF C=KEYF3 THEN
IF GETYESNO('Skip this entry','Are you sure?') THEN
BEGIN
REQUESTAMOUNT:=KEYF3;
C:=CR;
END;
IF C=KEYF4 THEN
IF GETYESNO('Delete all further entries',
'Are you sure?') THEN
BEGIN
REQUESTAMOUNT:=KEYF4;
C:=CR;
END;
UNTIL (C=CR) OR (C=ESC);
POPHELPCONTEXT;
END; { REQUESTAMOUNT }
BEGIN { PROCESSAUTOTRANS }
GETTODAY(DT); D:=DATETOWORD(DT);
WRITEWINDOW(JUSTC('Processing automatic transactions',80));
FOR C:='A' TO 'Z' DO { CHECK AUTO FILE FOR EACH ACCOUNT }
IF ACSTATUS[C].ACTYPE<>UNUSED THEN
BEGIN
{$I-}
ASSIGN(AUTOFILE,DATAFILEPATH+AUTOFN+C+FNEXT);
ASSIGN(TRANSFILE,DATAFILEPATH+TRANSFN+C+FNEXT);
RESET(AUTOFILE); DISKCHECK(IORESULT);
IF FILESIZE(AUTOFILE)<>0 THEN
BEGIN
RESET(TRANSFILE); DISKCHECK(IORESULT);
I:=0; { GET EACH RECORD IN TURN }
WHILE NOT(EOF(AUTOFILE)) DO
BEGIN
READ(AUTOFILE,ATR); DISKCHECK(IORESULT);
WHILE (DATETOWORD(ATR.DATE)<=D) DO
BEGIN { PREPARE IF DUE FOR ENTRY }
T.DATE:=DATETOWORD(ATR.DATE);
T.DETAIL:=ATR.DETAIL;
T.RECON:=UNREC;
T.AMOUNT:=ATR.AMOUNT;
IF T.AMOUNT=0 THEN
CC:=REQUESTAMOUNT(T,C)
ELSE
CC:=CR;
IF ATR.AUTODRCR=DEBIT THEN
T.AMOUNT:=-T.AMOUNT;
IF CC=CR THEN
ADDTRANS(ACSTATUS[C],T);
IF (CC=CR) OR (CC=KEYF3) THEN
IF UPDATEAUTOTRANS THEN
DELETEAUTOTRANSENTRY(I)
ELSE
BEGIN
SEEK(AUTOFILE,I);
DISKCHECK(IORESULT);
WRITE(AUTOFILE,ATR);
DISKCHECK(IORESULT);
END;
IF CC=KEYF4 THEN
DELETEAUTOTRANSENTRY(I);
{ PREVENT LOOP ON POSTPONE/DELETE }
IF (CC=ESC) OR (CC=KEYF4) THEN
WORDTODATE(D+1,ATR.DATE);
END;
INC(I);
END; { WHILE NOT(EOF) }
CLOSE(TRANSFILE); DISKCHECK(IORESULT);
END;
CLOSE(AUTOFILE); DISKCHECK(IORESULT);
{$I+}
END;
UPDATEACSTATFILE;
END; { PROCESSAUTOTRANS }
BEGIN { MAIN CODE }
DATEPARSECURYEAR:=TRUE;
DATEPARSEDELIMS:=REMOVE(DATEPARSEDELIMS,'-');
DEFINECONSOLEIO; { SET UP CONSOLE DISPLAY }
CRITICALERROROWN(ADDR(CRTCLERRHANDLER));
CURSORINSERT:=TRUE;
CONFIGFILENAME:=FILESPECDEFAULT(PARAMSTR(1),'.\','HAC','.CFG');
DATAFILEPATH:='';
ASSIGN(PRN,'LPT1');
READCONFIGURATION; { GET CONFIGURATION DATA }
PURGEALLWINDOWS; { RE-DEFINE CONSOLE FOR NEW COLORS }
DEFINECONSOLEIO;
{$I-}
REWRITE(PRN); DISKCHECK(IORESULT);
{$I+}
ASSIGN(ACSTATFILE,DATAFILEPATH+ACSTATFN+FNEXT);
TEXTATTR:=MAINCOLOR;
CLRSCR;
GOTOXY(1,2);
TEXTATTR:=STATCOLOR;
WRITE(DUPLCHAR(#196,80));
TEXTATTR:=MAINCOLOR;
OPENWINDOW(1);
WRITE('HAC Version 1.1');
GOTOXY(20,1);
WRITEWINDOW(PADL
('Copyright (C) 1992, 1993 Paul Coxwell. All rights reserved',60));
OPENWINDOW(9);
TEXTATTR:=HIGHCOLOR; WRITE('F1');
TEXTATTR:=MAINCOLOR; WRITE(' Help');
OPENWINDOW(7);
OPENWINDOW(2);
WITH ONLINEHELP DO { CONFIGURATION FOR ON-LINE HELP SYSTEM }
BEGIN
WINDOWID:=255;
HELPFILENAME:=HELPFN;
X1:=10; Y1:=7;
X2:=70; Y2:=17;
NORMALATTR:=MAINCOLOR;
INDEXATTR:=MAINCOLOR; SELECTATTR:=HIGHCOLOR;
BORDER:=WBORDER1; BORDERATTR:=HIGHCOLOR;
HDRTEXT:='HELP: '; FTRTEXT:='';
HDRPOS:=WJUSTLEFT; FTRPOS:=WJUSTRIGHT;
HDRATTR:=TITLECOLOR; FTRATTR:=TITLECOLOR;
GENERALKEY:=NUL; CONTEXTKEY:=KEYF1; LASTHELPKEY:=NUL;
MOVEWINDOWKEY:=HMOVESCROLL;
FLAGS:=HFLAGTITLE+HFLAGPAGEIND+HFLAGPAGETEXT;
END;
HELPERROR:=HELPERRHANDLER;
HELPINITIALIZE(ONLINEHELP);
HELPCONTEXT:=1;
IF ACSTATINIT THEN { INITIALIZE STATUS FROM FILE OR CREATE NEW }
BEGIN
PROCESSAUTOTRANS; { PROCESS OUTSTANDING AUTO TRANSACTIONS }
MAINOPT:=NUL;
REPEAT { CALL MAIN MENU/APPROPRIATE ROUTINES }
HELPCONTEXT:=2;
IF NOT(MAINOPT IN ['A'..'Z']) THEN
MAINOPT:=MAINMENU;
HELPCONTEXT:=6;
CASE MAINOPT OF
'A'..'Z':
IF ACSTATUS[MAINOPT].ACTYPE<>UNUSED THEN
CASE ACCESSACCOUNT(MAINOPT) OF
KEYCPGUP:
REPEAT
DEC(MAINOPT);
UNTIL (ACSTATUS[MAINOPT].ACTYPE<>UNUSED) OR
(MAINOPT<'A');
KEYCPGDN:
REPEAT
INC(MAINOPT);
UNTIL (ACSTATUS[MAINOPT].ACTYPE<>UNUSED) OR
(MAINOPT>'Z');
KEYCHOME:
BEGIN
MAINOPT:='A';
WHILE (MAINOPT<='Z') AND
(ACSTATUS[MAINOPT].ACTYPE=UNUSED) DO
INC(MAINOPT);
END;
KEYCEND:
BEGIN
MAINOPT:='Z';
WHILE (MAINOPT>='A') AND
(ACSTATUS[MAINOPT].ACTYPE=UNUSED) DO
DEC(MAINOPT);
END;
ESC: MAINOPT:=NUL;
END
ELSE
BEGIN
DISPLAYERROR('Account '+MAINOPT+
' not in use at present');
MAINOPT:=NUL;
END;
KEYF3:
BEGIN
HELPCONTEXT:=3;
ACCOUNTSUMMARY;
END;
KEYF4:
BEGIN
HELPCONTEXT:=4;
ACCOUNTSETUP;
END;
END; { CASE MAINOPT }
UNTIL MAINOPT=KEYF10;
{$I-}
CLOSE(ACSTATFILE); DISKCHECK(IORESULT);
CLOSE(PRN); DISKCHECK(IORESULT);
{$I+}
END;
SELECTWINDOW(0); { TIDY UP DISPLAY FOR EXIT }
CLRSCR;
END.