10 acc_nr::acc_nr(String &s)
14 std::cerr << "Account number from " << s;
18 std::cerr << " : " << *this << "\n";
21 acc_nr::operator String()
24 sprintf(_buf, "%03d.%02d", group, nr);
30 std::istream &operator>>(std::istream &s, acc_nr &a)
34 s >> a.group >> c >> a.nr;
38 std::ostream &operator<<(std::ostream &s, acc_nr a)
44 std::istream &operator>>(std::istream &s, amount &a)
49 s >> hundreds >> c >> a.value;
50 a.value += hundreds * 100;
55 std::ostream &operator<<(std::ostream &s, amount a)
61 //s << form("%8d.%02d",a / 100, a % 100);
62 s << std::setw(8) << a / 100 << ".";
63 s << std::setw(2) << std::setfill('0') << a % 100;
64 s << std::setw(0) << std::setfill(' ');
70 String amount::to_string()
73 sprintf(_buf, "%8lu.%02lu", value / 100, value % 100);
85 std::ostream &operator<<(std::ostream &s, balance b)
87 s << b.Debit << " " << b.Credit;
92 std::istream &operator>>(std::istream &s, Booking &b)
96 s >> b.Bnumber >> b.booked;
104 std::ostream &operator<<(std::ostream &s, Booking &b)
106 //s << form("#%03d ",b.Bnumber) << b.booked << " " << b.comment;
107 //s << form("%.*s", 58 - ~b.comment, " ");
108 s << "#" << std::setw(4) << std::setfill('0') << b.Bnumber;
109 s << std::setw(0) << std::setfill(' ');
110 s << " " << b.booked << " ";
111 s << std::setfill(' ') << std::setw(58) << std::left << b.comment;
112 s << std::setw(0) << std::right ;
117 std::istream &operator>>(std::istream &s, Mutation &m)
123 while (s.get(c), c == ' ')
132 //std::istringstream amnt(buf+strlen(buf)-10);
140 while (p > 0 && amnt[p] == ' ')
144 while (p > 0 && amnt[p] != ' ')
149 amnt = amnt(p, ~amnt - p);
150 int dot = amnt.index('.');
151 String cents = amnt(dot+1, 2);
152 a = long(amnt) * 100 + cents.dec();
155 m.bal = balance(a, 0);
157 m.bal = balance(0, a);
162 std::ostream &operator<<(std::ostream &s, Mutation &m)
164 s << "#" << std::setw(4) << std::setfill('0') << m.booking_nr;
165 s << std::setw(0) << std::setfill(' ');
166 s << " " << m.account << m.bal;
172 std::istream &operator>>(std::istream &s, Account &acc)
174 char kind, name[128];
176 s >> acc.Anumber >> kind >> std::ws;
190 std::ostream &operator<<(std::ostream &s, Account &acc)
192 s << acc.Anumber << " " << std::setw(44) << std::left << acc.name;
193 s << std::setw(0) << std::right << " ";
194 //s << form("%.*s", 45 - ~acc.name, " ");
200 std::ostream& operator<<(std::ostream &s, Ledger &l)
203 balance total, saldi;
204 balance EndBalance, Result;
206 s << l.nr_accs << " accounts in ledger:\n\n";
207 for (i=0; i<l.nr_accs; i++)
210 saldi += ~balance(l.accs[i]);
211 s << l.accs[i] << ~balance(l.accs[i]);
214 s << " " << ~balance(l.accs[i]);
215 EndBalance += ~balance(l.accs[i]);
219 s << ~balance(l.accs[i]);
220 Result += ~balance(l.accs[i]);
230 s << -profit << profit << "\n";
233 EndBalance += profit;
236 s << total << saldi << Result << EndBalance << "\n";
241 void PostScript_balans_layout(PostScript &ps, String header)
243 ps.Line(16, 595, 755, 595);
244 ps.Line(16, 580, 755, 580);
245 ps.Line(16, 40, 755, 40);
246 ps.Text(200, 582, header);
248 ps.Line( 16, 595, 16, 40);
249 ps.Line(755, 595, 755, 40);
251 ps.LineAttributes(0.2, 1.0, 0.0);
252 ps.Line(195, 580, 195, 40);
253 ps.Line(335, 580, 335, 40);
254 ps.Line(475, 580, 475, 40);
255 ps.Line(615, 580, 615, 40);
257 ps.LineAttributes(0.2, 2.0, 2.0);
258 ps.Line(265, 580, 265, 40);
259 ps.Line(405, 580, 405, 40);
260 ps.Line(545, 580, 545, 40);
261 ps.Line(685, 580, 685, 40);
264 void Ledger::accounts_report(const char * filename)
268 PostScript ps(filename);
271 for (i=0; i<nr_accs; i++)
273 accs[i].Postscript_sheet(ps);
276 catch (psexception &e)
278 std::cerr << "Error creating postscript output: " << e.what() << "\n";
282 void Ledger::saldi_report(const char * filename, date period_begin, date period_end)
286 PostScript ps(filename);
287 balance total, saldi;
288 balance EndBalance, Result;
293 String header("Saldibalans");
295 header += " " + companyname;
296 header += " van " + period_begin.format("%e %B %Y") + " tot " + period_end.format("%e %B %Y");
298 ps.NewPage(842, 595);
302 for (i=0; i<nr_accs; i++)
304 balance saldo(accs[i]);
306 if (saldo.debit() != 0 || saldo.credit() != 0)
311 PostScript_balans_layout(ps, header);
312 ps.NewPage(842, 595);
320 ps.Rectangle(16, y-2, 739, 7);
324 saldi += ~balance(accs[i]);
326 ps.Text(20, y, String(accs[i].Number()));
327 ps.Text(50, y, accs[i].Name());
329 balance saldo(accs[i]);
331 ps.Text(200, y, saldo.debit().to_string());
332 ps.Text(270, y, saldo.credit().to_string());
334 ps.Text(340, y, saldo.debit().to_string());
335 ps.Text(410, y, saldo.credit().to_string());
339 EndBalance += ~balance(accs[i]);
341 ps.Text(620, y, saldo.debit().to_string());
342 ps.Text(690, y, saldo.credit().to_string());
346 Result += ~balance(accs[i]);
348 ps.Text(480, y, saldo.debit().to_string());
349 ps.Text(550, y, saldo.credit().to_string());
358 PostScript_balans_layout(ps, header);
363 EndBalance += profit;
365 ps.LineAttributes(0.5, 1.0, 0.0);
366 ps.Line(16, 60, 755, 60);
368 ps.Text(50, y, "Resultaat");
369 ps.Text(480, y, (-profit).debit().to_string());
370 ps.Text(550, y, (-profit).credit().to_string());
371 ps.Text(620, y, profit.debit().to_string());
372 ps.Text(690, y, profit.credit().to_string());
374 ps.Line(16, 50, 755, 50);
376 ps.Text(50, y, "Totaal");
377 ps.Text(200, y, total.debit().to_string());
378 ps.Text(270, y, total.credit().to_string());
379 ps.Text(340, y, saldi.debit().to_string());
380 ps.Text(410, y, saldi.credit().to_string());
381 ps.Text(480, y, Result.debit().to_string());
382 ps.Text(550, y, Result.credit().to_string());
383 ps.Text(620, y, EndBalance.debit().to_string());
384 ps.Text(690, y, EndBalance.credit().to_string());
386 catch (psexception &e)
388 std::cerr << "Error creating postscript output: " << e.what() << "\n";
392 void Ledger::XML_saldi(std::ostream &s, date period_begin, date period_end)
396 s << "<?xml version='1.0'?>\n";
397 s << "<accounting companyname='" << companyname << "'>\n";
398 s << "<balance-sheet begin='" << period_begin << "' end='" << period_end << "'>\n";
399 for (i=0; i<nr_accs; i++)
401 balance saldo = ~balance(accs[i]);
403 if (saldo.debit() != 0 || saldo.credit() != 0)
406 s << " <number>" << accs[i].Number() << "</number>\n";
407 s << " <name>" << accs[i].Name() << "</name>\n";
410 s << " <type>BALANCE</type>\n";
414 s << " <type>COST</type>\n";
416 if (saldo.debit() == 0)
418 s << " <balance>CREDIT</balance>\n";
419 s << " <amount>" << saldo.credit() << "</amount>\n";
423 s << " <balance>DEBIT</balance>\n";
424 s << " <amount>" << saldo.debit() << "</amount>\n";
426 s << " </account>\n";
430 s << "</balance-sheet>\n";
431 s << "</accounting>\n";
434 Account & Ledger::operator[](acc_nr Anr)
438 for (i=0; accs[i] != Anr && i<nr_accs; i++);
440 std::cerr << "Account " << Anr << " not found.\n";
448 void PostScript_account_layout(PostScript &ps)
450 ps.LineAttributes(1.0, 1.0, 0.0);
451 ps.Line(30, 770, 580, 770);
452 ps.Line(30, 740, 580, 740);
453 ps.Line(30, 20, 580, 20);
455 ps.Line(30, 770, 30, 20);
456 ps.Line(580, 770, 580, 20);
458 ps.LineAttributes(0.2, 1.0, 0.0);
459 ps.Line(400, 740, 400, 20);
460 ps.LineAttributes(0.2, 2.0, 2.0);
461 ps.Line(480, 740, 480, 20);
464 void Account::Postscript_sheet(PostScript &ps)
471 bool page_started = false;
475 /* Go through all mutations, selecting for each account */
477 for (M = 0; M < n_m; M++)
479 std::ostringstream bookstr;
481 if (acc_nr(m[M]) == Anumber)
487 PostScript_account_layout(ps);
490 ps.NewPage(596, 842);
493 ps.Text(40, 750, String(Anumber));
494 ps.Text(100, 750, name);
506 ps.Rectangle(30, y-2, 550, 9);
508 /* Search the booking date and description */
510 for (B = 0; b[B].number() != m[M].number(); B++);
512 ps.Text(40, y, bookstr.str().c_str());
514 ps.Text(400, y, saldo.debit().to_string());
515 ps.Text(480, y, saldo.credit().to_string());
519 //s << b[B] << "|" << balance(m[M]) << " |\n";
523 /* Print the footer with the totals */
527 s << " |" << -~total << " |\n";
528 s << "----------------------------------------------------------------";
529 s << "-----------+-------------+-----------+\n";
532 s << " |" << total << " |\n";
533 s << "----------------------------------------------------------------";
534 s << "-----------+-------------+-----------+\n";
539 ps.Text(100, 50, "SALDO");
541 ps.Text(400, 50, saldo.debit().to_string());
542 ps.Text(480, 50, saldo.credit().to_string());
543 ps.Line(30, 40, 580, 40);
545 ps.Text(100, 30, "TOTAAL");
546 ps.Text(400, 30, total.debit().to_string());
547 ps.Text(480, 30, total.credit().to_string());
548 PostScript_account_layout(ps);
552 void Account::sheet(std::ostream &s)
557 s << "\n\n " << Anumber << " " << name << "\n";
558 s << "================================================================";
559 s << "===========+=============+===========+\n";
561 /* Go through all mutations, selecting for each account */
563 for (M = 0; M < n_m; M++)
565 if (acc_nr(m[M]) == Anumber)
569 /* Search the booking date and description */
571 for (B = 0; b[B].number() != m[M].number(); B++);
572 s << b[B] << "|" << balance(m[M]) << " |\n";
576 /* Print the footer with the totals */
579 s << " |" << -~total << " |\n";
580 s << "----------------------------------------------------------------";
581 s << "-----------+-------------+-----------+\n";
584 s << " |" << total << " |\n";
585 s << "----------------------------------------------------------------";
586 s << "-----------+-------------+-----------+\n";
589 void Ledger::read(char *filename)
591 std::ifstream in(filename);
597 std::cerr << "Cannot read ledger file" << filename << "\n";
605 if (isdigit(line_begin))
607 in.putback(line_begin);
611 else if (line_begin == '$')
613 // Optional attributes
615 String a_name, a_value;
619 int separator = attribute.index('=');
624 while (isspace(attribute[separator]));
625 a_name = attribute(0, separator+1);
627 separator = attribute.index('=');
632 while (isspace(attribute[separator]));
634 a_value(0, separator) = "";
636 if (a_name == "companyname")
638 companyname = a_value;
642 std::cerr << "Unrecognized attribute in Ledger: " << a_name << "\n";
645 else if (line_begin == '\n')
647 // Ignore empty lines
651 // Anything else is comment: eat it.
657 accs[nr_accs].Name() = String("Rekening bestaat niet");