/xenix: A Simple Accounting
System
©1987 - Richard A. Bilancia - All Rights
Reserved
to be published first in the July 1987 issue of
UNIX/World
Those of you that read my column regularly know that I am an accountant. Because of that background, a long time ago I built simple accounting system using XENIX relational database tools. This month I’d like to share that simple accounting system with you, fully describe how to use it and completely analyze each line of code in the system.
My simple accounting system is written in the Bourne shell programming language (the same interactive command interpreter that you use to execute simple XENIX commands) and uses the following XENIX relational database tools:
awk pattern scanning & processing language cat catenate & print echo echo arguments join relational database operator lpr line printer spooler pr print file rm remove (unlink) files sed stream editor sort sort or merge files
Some Background.
But before we start, what exactly is a relational database
system? In the early 1970’s Dr. E. F. Codd of IBM
proposed an alternative to the traditional hierarchical
& network database systems. His main reasoning for
describing this new database alternative was two-fold.
First, for the first time there could be a solid theoretical
mathematically based foundation for data base design. In
addition, it was Dr. Codd’s contention that system
development would be substantially easier using a relational
system because the programmer could be relieved from the
burdensome coding normally required for both the
hierarchical and network systems. In February of 1982, Dr.
Codd published a complete outline of his ideas in
"Relational Database: A Practical Foundation for
Productivity," in Communications of the ACM. If
you have the time, I strongly recommend that you read the
article.
If you’ve done any development on your XENIX system you’ve probably used most of the tools listed above, with the possible exceptions being ’awk’ and ’join.’ While ’awk’ is described in the manuals as a pattern scanning and recognition language, it can better be described as a report writing program. But even that description only touches upon it power and potential. After reading this article you may want more information about ’awk.’ If so, you can find a detailed description in Appendix A.3 of the "Text Processing Guide" of your XENIX reference manuals as well as Dale Dougherty’s 3 part tutorial concluding in this issue of UNIX/World.
The other tool, ’join’ is simply a program that matches records based upon common fields.
You may have also already discovered that XENIX (and UNIX) rely quite heavily on the use of field separators, with the tab character being the most common field separator. Conforming with that standard practice, the accounting system below uses the tab character as its field separator.
The simple accounting system presented here has only two procedures "CLOSE_MONTH" and "POST_ENTRIES." However, the user must also be able to use either of the XENIX editors, ’ed’ or ’vi,’ in order to create the various files.
Installing the system.
The system is very easy to install and to use. Only three
data files and two program files need to be created. In
order to install the system simply follow these
steps:
1. Using either of the XENIX editors, ’ed’ or ’vi,’ enter and save the two programs POST_ENTRIES and CLOSE_MONTH exactly as shown in figures A and B. Wherever you see the characters ’<tab>’ simply type a single tab character using the tab key. After creating and saving the files type the following shell commands to make the files executable:
chmod 755 POST_ENTRIES
chmod 755 CLOSE_MONTH
2. Next you will need to create a file called CHART_OF_ACCOUNTS. This file has three fields, the account number, a category code, and the account description. Use one of the XENIX editors to create this file separating each field in each record with a single tab character. I recommend that the account number be a three or four digit number while the category code should be an A, L, I or E symbolizing an asset account, a liability account, an income account, or an expense account. A suggested chart of accounts for personal use appears in figure C.
3. Finally you’ll need to create a file that contains the opening balances for each asset and liability account. Each record in this file should have three fields likewise separated by a single tab character. The fields are, the account number, the opening balance amount (preceded by a minus sign if a credit number), and the Julian date of the balance (i.e., the date the books were last closed). Name the file BALANCES and be sure that the total of column two equals zero and the file is in ascending sequence by account number. You can use the ’sort’ command to sequence the file by typing the following command:
sort -o BALANCES BALANCES
Using the system.
Using the system is just as easy! Just follow these
steps:
1. Each month you will need to create a file of accounting entries (or journal vouchers) named ENTRIES. Each record in this file should have four fields with each field separated by a single tab character. The fields are, the account number, the entry amount (preceded by a minus sign if a credit number), the Julian date of the transaction, and finally a description of the transaction. Be sure that the total of column two (the entry amount) equals zero and the file is in ascending sequence by account number.
2. In order to post these entries to the previous balances just type "POST_ENTRIES" and the program created above will be executed. This will result in a report named "Trial Balance Report" and a file titled "TRIAL_BALANCE" that will be used in the final posting process. If any errors are detected while reviewing the output of this program, simply make changes to either the "BALANCES" or "ENTRIES" file and rerun this program. It can be rerun as many times as you wish.
3. When the output of the previous step is completely correct the accounting month can be closed-out by typing "CLOSE_MONTH". Be careful before executing this program as the previous month’s BALANCES file will be automatically deleted.
That’s all there is to it!
Understanding the Code:
"POST_ENTRIES"
lines 1-3: These are comment lines. The pound sign prevents
the remainder of the line from being
executed.
lines 4-5: An ’awk’ program. The portion enclosed within the single quotes is the actual program. The ’BEGIN {FS=OFS="\t"}’ is executed on at the beginning of the processing and sets the field separator and the output field separator to the tab character.
The portion of line 5 enclosed within braces instructs the ’awk’ program to print the contents of the first, second and third columns of the input file, followed by the text in double quotes, to the standard output. The input is taken from the file "BALANCES" and the output is diverted through a pipe to the commands on line 6.
line 6: The ’cat’ command is used to concatenate the contents of the "ENTRIES" file to the end of the output of the previous pipe and redirected through a pipe to the ’sort’ program. The ’sort’ program uses the ’-t’ option to set the tab character as the field separator and uses columns 1 and 3 as the major and minor sort fields. The output is then diverted through a pipe to the commands on line 7.
line 7: The ’join’ command is used to match on the first columns of the output of the previous pipe’ and the file "CHART_OF_ACCOUNTS" to create the file "TRIAL_BALANCE". The ’-a1’ option ensures that every line of file 1 (the output of the previous pipe indicated by the solitary ’-’) is written to the output file. The ’-t’ option once again sets the field separator as the tab character.
lines 8-9: The ’echo’ command is used to create the column headings for the trial balance report that is being created in the file "TB".
line 10: The ’cat’ command is used to append the contents of the file "TRIAL_BALANCE" created on line 7 above to the file "TB".
line 11: The ’echo’ command is used to append a line of dashes (to signify that a total follows) to the file "TB".
lines 12-14: An ’awk’ program to computed the sum of all transactions in the "TRIAL_BALANCE" file and append that number to "TB". Line 12 once again sets the field separators. Line 13 adds the values of column 2 in every record to a variable named "total". And in line 14 the instruction within the braces following the word "END" send a tab character followed by the value of "total" when the input file is exhausted to the standard output which is finally diverted to the file "TB".
line 15: Uses the ’pr’ and ’lpr’ commands piped together to send the contents of "TB" to the printer as a report. The ’-h’ option is used to add a description to the standard ’pr’ header.
line 16: Deletes the "TB" file using the ’rm’ command.
Understanding the Code:
"CLOSE_MONTH"
lines 1-3: These are the comment
lines.
line 4: The ’echo’ command is used to display a message on the screen that indicates the user should enter a date.
line 5: The ’read’ command of the Bourne shell programming language is used to retrieve the characters entered by the user, and stores that response in a shell variable named ’date.’
line 6: The stream editor program ’sed’ is now used to insert the value stored in the variable ’date’ in the beginning of every record in the file "TRIAL_BALANCE". Note that the ’sed’ program is contained within the double quotes (to allow the ’$’ to be interpreted by the ’shell’), and the output is redirected through a pipe to the command on the next line. The ’sed’ program is actually a substitute command, as indicated by the ’s’, and is to substitute at the beginning of every line, as indicated by the ’^’, the value in the variable ’date’ immediately followed by a tab character. Note the convention of preceding a shell variable with a ’$’ to indicate the value of the variable name immediately following.
lines 7-11: The remaining lines are another ’awk’ program that takes as its input the ’piped’ output from line 6 and sends its output to replace the file "BALANCES" with the new updates balances for each account. The ’awk’ program creates and uses two new variables -- ’prev’ to check for a break or change in the account number, and ’amt’ to store the accumulated net balance in each account. Line 7 once again sets the field separators. In line 8 if the account number in column 2 is not equal to the previous account number stored in the variable ’prev’ then print a record with three fields, the previous account number ’prev’, the accumulated amount in ’amt’, and the date from column 1. Also on the same condition in line 9, reinitialize the value in the variable ’amt’ to zero. For every input record, line 10 sets the value in the variable ’prev’ with the account number from column 2, and adds the amount from column 3 to the variable ’amt’. And lastly after the input file has been completely exhausted, line 11 prints a final record with the remaining values in ’prev’ and ’amt’ appending the value stored in the shell variable ’date’.
FIGURE ’A’ - POST_ENTRIES
1 # ’POST_ENTRIES’
2 # ’Copyright (c) 1983, 1987 - Richard A. Bilancia’
3 #
4 awk ’BEGIN {FS=OFS="\t"}
5 {print $1,$2,$3,"OPENING BALANCE"}’ < BALANCES |\
6 cat - ENTRIES | sort -t’\t’ +0 +2 |\
7 join -a1 -t’<tab>’ - CHART_OF_ACCOUNTS > TRIAL_BALANCE
8 /bin/echo "ACCOUNT\tAMOUNT\tDATE\tEXPLANATION\tCATEGORY\tDESCRIPTION" > TB
9 cat TRIAL_BALANCE >> TB
10 /bin/echo "\t--------" >> TB
11 awk ’BEGIN {FS=OFS="\t"}
12 {total += $2}
13 END {print "\t", total}’ < TRIAL_BALANCE >> TB
14 pr -h "Trial Balance Report" < TB | lpr
15 rm TB
FIGURE ’B’ - CLOSE_MONTH
1 # ’CLOSE_MONTH’
2 # ’Copyright (c) 1983, 1987 - Richard A. Bilancia’
3 #
4 echo ’Enter the closing date (e.g., 861231) ’
5 read date
6 sed "s/^/$date<tab>/" < TRIAL_BALANCE |\
7 awk ’BEGIN {OFS=FS="\t"}
8 prev != $2 {print prev, amt, $1}
9 prev != $2 {amt = 0}
10 {prev = $2; amt += $3}
11 END {print prev, amt, "’$date’"}’ > BALANCES
FIGURE ’C’ - CHART_OF_ACCOUNTS
1000 A CASH IN CURRENCY 6050 E Electricity
1100 A CHECKING A/C 6080 E Snow Removal
1150 A CASH FUND A/C 6110 E Retirement Insurance
1300 A A/R - MISCELLANEOUS 6120 E Homeowner’s Insurance
1350 A CASH VALUE OF INSURANCE 6130 E Auto Insurance
1400 A I.R.A. 6140 E Life Insurance
1500 A LAND 6210 E Medical: Doctors
1510 A BUILDINGS 6220 E Medical: Dental
1520 A Improvements 6230 E Medical: Drugs
1530 A Landscaping 6310 E Real Estate Taxes
1549 A Unrealized Gain on House 6320 E Auto Licenses
1600 A Furniture & Fixtures 6330 E Sales & Use Tax
1705 A Auto #1 6340 E Federal Income Tax W/H
1710 A Auto #2 6350 E State Tax W/H
1910 A Retirement Contributions 6360 E F.I.C.A. TAXES
1960 A Jewelry 6410 E Mortgage Interest
2000 L Personal Loan 6430 E Credit Card Interest Exp.
2010 L Loan - Auto #1 6440 E Other Interest Exp.
2020 L Loan - Auto #2 6530 E Contributions
2100 L Accounts Payable 6710 E Subscriptions
2510 L Mortgage Payable 6750 E Business Expenses
3900 L Deferred Capital Gains 7010 E Food & Groceries
3999 L Net Worth 7020 E Alcoholic Beverages
4010 I Gross Salary 7030 E Milk
4101 I Dividends 7040 E Entertainment
4121 I Interest Income 7050 E Clothing
4205 I Gifts received 7060 E Auto Parts & Repairs
4299 I Miscellaneous Income 7070 E Cleaning & Laundry
4310 I Equity Inc/[loss] 7080 E Postage
4410 I Capital Gains 7090 E Gasoline
4490 I Federal Tax Refunds 7100 E Gift Expense
6010 E Telephone 7110 E Haircuts
6020 E Water & Sewer 7500 E Travel & Vacation
6030 E Trash Collection 7600 E Education
6040 E Natural Gas 7999 E Miscellaneous
I hope that you’ve found my example interesting!