1 #ident "Kalopa: $Id: acctview.c,v 1.16 2008/10/15 15:11:13 dtynan Exp $"
2 
3 /*
4  * $Id: acctview.c,v 1.16 2008/10/15 15:11:13 dtynan Exp $
5  *
6  * Copyright (c) 2004, Kalopa Media Limited.  All rights reserved.
7  * Copyright (c) 2005, Kalopa Research Limited.  All rights reserved.
8  * This is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published
10  * by the Free Software Foundation; either version 2, or (at your
11  * option) any later version.
12  *
13  * It is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
16  * License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this product; see the file COPYING.  If not, write to
20  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
21  * USA.
22  *
23  * THIS SOFTWARE IS PROVIDED BY KALOPA RESEARCH LIMITED "AS IS" AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
26  * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL KALOPA
27  * RESEARCH LIMITED BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
30  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
32  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
34  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  *
36  * ABSTRACT
37  *
38  * $Log: acctview.c,v $
39  * Revision 1.16  2008/10/15 15:11:13  dtynan
40  * Mammoth change to convert from old-style database configuration to new
41  * schema where an RC file defines the database access.
42  *
43  * Revision 1.15  2008/10/13 20:59:38  dtynan
44  * Extensive changes (part 1) for change to database configuration.
45  *
46  * Revision 1.14  2008/01/15 18:10:43  dtynan
47  * Changed to use new company name and copyright, also fixed a few old
48  * files with the wrong license.
49  *
50  * Revision 1.13  2008/01/15 15:33:01  dtynan
51  * Extensive changes for new DBOW version (due out soon...)
52  *
53  * Revision 1.12  2007/10/29 17:24:34  dtynan
54  * Various tweaks and fixes.
55  *
56  * Revision 1.11  2006/07/31 10:17:51  dtynan
57  * Massive changeover to a more Ruby/Rails primary key naming convention.
58  *
59  * Revision 1.10  2005/03/22 09:41:23  dtynan
60  * Extensive upgrade to make sure the copyright block was
61  * consistent and GPL'ed.
62  *
63  * Revision 1.9  2005/03/08 16:38:59  dtynan
64  * Added the journal ID number to the report outputs.
65  *
66  * Revision 1.8  2005/02/17 17:25:27  dtynan
67  * Fixed some compiler warnings.
68  *
69  * Revision 1.7  2005/01/13 21:57:09  dtynan
70  * Use nominal account table from main database.
71  *
72  * Revision 1.6  2004/12/09 20:23:39  dtynan
73  * Cleaned up include mechanisms.
74  *
75  * Revision 1.5  2004/12/09 19:19:57  dtynan
76  * Added a folio field to the output data.
77  *
78  * Revision 1.4  2004/09/08 10:43:12  dtynan
79  * Fix a bug where 0.0 was shown as a negative balance and add a
80  * "Closing Balance" line to all accounts.
81  *
82  * Revision 1.3  2004/09/03 13:46:43  dtynan
83  * Created a text format for use without groff and made it the default.
84  *
85  * Revision 1.2  2004/08/26 17:15:35  dtynan
86  * New version will display the transactions for any account.
87  *
88  * Revision 1.1  2004/08/07 15:31:24  dtynan
89  * New program to produce a pro-forma bank statement.
90  */
91 #include <stdio.h>
92 #include <stdlib.h>
93 #include <unistd.h>
94 #include <string.h>
95 #include <time.h>
96 #include <math.h>
97 
98 #include "beanie.h"
99 
100 int	verbose;
101 int	troff;
102 int	lineno;
103 char	*title;
104 double	bals[10000];
105 struct db_company *comp;
106 
107 extern	int	optind, opterr;
108 extern	char	*optarg;
109 
110 void	acctview(struct db_nomacct *, int);
111 void	heading(int, int);
112 void	usage();
113 
114 struct	db_journal	*findjournalentries(dbow_conn *);
115 struct	db_journal_item	*findjournalitems(dbow_conn *, int);
116 struct	db_nomacct	*findnomaccts(dbow_conn *);
117 
118 char	*month[12] = {
119 	"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
120 };
121 
122 /*
123  *
124  */
125 int
main(int argc,char * argv[])126 main(int argc, char *argv[])
127 {
128 	int i, aflag, year, acctno;
129 	char *cname;
130 	struct tm *tmp;
131 	struct db_nomacct *np;
132 	dbow_conn *dbp;
133 	time_t now;
134 
135 	/*
136 	 * Process command-line options.
137 	 */
138 	cname = NULL;
139 	time(&now);
140 	if ((tmp = localtime(&now)) != NULL)
141 		year = tmp->tm_year;
142 	else
143 		year = 104;
144 	opterr = verbose = aflag = troff = 0;
145 	while ((i = getopt(argc, argv, "ac:y:vt")) != EOF) {
146 		switch (i) {
147 		case 'a':
148 			/*
149 			 * Do all the accounts...
150 			 */
151 			aflag = 1;
152 			break;
153 
154 		case 'c':
155 			cname = optarg;
156 			break;
157 
158 		case 'y':
159 			if ((i = atoi(optarg)) < 1990 || i > 2099) {
160 				fprintf(stderr, "?Error - invalid year.\n");
161 				exit(2);
162 			}
163 			year = i - 1900;
164 			break;
165 
166 		case 't':
167 			troff = 1;
168 			break;
169 
170 		case 'v':
171 			verbose = 1;
172 			break;
173 
174 		default:
175 			usage();
176 			break;
177 		}
178 	}
179 	if (!aflag && (argc - optind) != 1)
180 		usage();
181 	loadconfig(cname);
182 	dbp = getdbase();
183 	if ((comp = db_findcompanyfirst(dbp)) == NULL) {
184 		fprintf(stderr, "?Error - cannot find specified company.\n");
185 		exit(1);
186 	}
187 	if (!aflag) {
188 		acctno = atoi(argv[optind]);
189 		if ((np = db_findnomacctbyid(dbp, acctno)) == NULL) {
190 			fprintf(stderr, "?Invalid nominal account number.\n");
191 			exit(1);
192 		}
193 		acctview(np, year);
194 	} else {
195 		for (np = findnomaccts(dbp); np != NULL;
196 					np = db_findnomacctnext(dbp, np)) {
197 			heading(-1, -1);
198 			acctview(np, year);
199 		}
200 	}
201 	exit(0);
202 }
203 
204 /*
205  *
206  */
207 void
acctview(struct db_nomacct * np,int year)208 acctview(struct db_nomacct *np, int year)
209 {
210 	int sawflag = 0;
211 	struct db_journal *jp;
212 	struct db_journal_item *jip;
213 	struct tm *tmp;
214 	char tmpbal[20];
215 	double tot;
216 	dbow_conn *dbp = getdbase();
217 
218 	title = strdup(np->aname);
219 	lineno = 0;
220 	tot = 0.0;
221 	for (jp = findjournalentries(dbp); jp != NULL;
222 				jp = db_findjournalnext(dbp, jp)) {
223 		if ((tmp = localtime((time_t *)&jp->jdate)) == NULL)
224 			continue;
225 		if (tmp->tm_year != year)
226 			continue;
227 		for (jip = findjournalitems(dbp, jp->id);
228 				jip != NULL;
229 				jip = db_findjournal_itemnext(dbp, jip)) {
230 			if (jip->nomacct_id != np->id)
231 				continue;
232 			heading(0, year);
233 			sawflag = 1;
234 			if (troff) {
235 				printf("%d-%s:", tmp->tm_mday,
236 							month[tmp->tm_mon]);
237 				if (jp->folio != NULL)
238 					printf("%s", jp->folio);
239 				printf(":%s:", jp->descr);
240 				if (jip->drcrf) {
241 					printf(":%.2f:", jip->amount);
242 					tot += jip->amount;
243 				} else {
244 					printf("%.2f::", jip->amount);
245 					tot -= jip->amount;
246 				}
247 				if (tot < 0.0)
248 					printf("(%.2f)\n", -tot);
249 				else
250 					printf("%.2f\n", tot);
251 				lineno++;
252 			} else {
253 				printf("|%2d-%s|%4d|", tmp->tm_mday,
254 							month[tmp->tm_mon],
255 							jp->id);
256 				if (jp->folio != NULL)
257 					printf("%4.4s|", jp->folio);
258 				else
259 					printf("    |");
260 				printf("%-28.28s|", jp->descr);
261 				if (jip->drcrf) {
262 					printf("         |%9.2f|", jip->amount);
263 					tot += jip->amount;
264 				} else {
265 					printf("%9.2f|         |", jip->amount);
266 					tot -= jip->amount;
267 				}
268 				if (tot < 0.0)
269 					sprintf(tmpbal, "(%.2f)", -tot);
270 				else
271 					sprintf(tmpbal, "%.2f ", tot);
272 				printf("%12s|\n", tmpbal);
273 			}
274 		}
275 	}
276 	if (!sawflag && tot == 0.0)
277 		return;
278 	heading(0, year);
279 	if (troff) {
280 		printf("::Balance Brought Forward:::");
281 		if (tot < 0.0)
282 			printf("(%.2f)\n", -tot);
283 		else
284 			printf("%.2f\n", tot);
285 		lineno++;
286 	} else {
287 		printf("|      |    |    |Balance Brought Forward     |         |         |");
288 		if (tot < 0.0)
289 			sprintf(tmpbal, "(%.2f)", -tot);
290 		else
291 			sprintf(tmpbal, "%.2f ", tot);
292 		printf("%12s|\n", tmpbal);
293 	}
294 	heading(-1, year);
295 	putchar('\n');
296 }
297 
298 /*
299  *
300  */
301 void
heading(int type,int year)302 heading(int type, int year)
303 {
304 	static int htype = -1, pageno = 0;
305 
306 	if (year == -1) {
307 		htype = -1;
308 		return;
309 	}
310 	if (!troff) {
311 		if (htype == -1) {
312 			printf("%s for %s", title, comp->cname);
313 			if (year != 0)
314 				printf(" -- %d", year + 1900);
315 			putchar('\n');
316 		}
317 		if (type == -1 || htype == -1) {
318 			printf("+------+-------------------------------------");
319 			printf("-+---------+---------+------------+\n");
320 		}
321 		htype = 0;
322 		return;
323 	}
324 	if (type >= 0 && htype == -1) {
325 		printf(".nr PS 12\n.nr VS 14\n.sp 2c\n");
326 		htype = 0;
327 	}
328 	if (htype == type && lineno > 0 && lineno < 50) {
329 		lineno++;
330 		return;
331 	}
332 	if (lineno > 0)
333 		printf(".TE\n");
334 	if (type < 0)
335 		return;
336 	if (lineno > 0)
337 		printf(".bp\n.sp 2.5c\n");
338 	if (htype != type) {
339 		lineno = pageno = 0;
340 		htype = type;
341 	}
342 	printf("%s for %s", title, comp->cname);
343 	printf(" (Page %d)\n.sp\n.TS\n", ++pageno);
344 	switch (type) {
345 	case 0:
346 		printf("center box tab(:);\nc | c | c | c | c\n");
347 		printf("ri | lw4ib | r | r | r.\n");
348 		printf("Date:Details:Debit:Credit:Balance\n_\n");
349 		break;
350 	}
351 	lineno = 1;
352 }
353 
354 /*
355  *
356  */
357 void
usage()358 usage()
359 {
360 	fprintf(stderr, "Usage: acctview [-a][-v][-c <comp>] [-y year] [acctno]\n");
361 	exit(2);
362 }
363