February 17, 2015

This function produces a single invoice, stopping input when an empty description is entered:

(define (write-invoice)
  (let-values (((ds qs ps tot) (read-items)))
    (when (pair? ds)
      (format #t "~10a~20a~%" "" "Praxis Grocery Store")
      (format #t "~15a~11a~%~%" "" (date-format (today) "%d %b %Y"))
      (do ((i 1 (+ i 1)) (ds ds (cdr ds)) (qs qs (cdr qs)) (ps ps (cdr ps)))
        ((null? ds))
        (format #t "~3a~20a~3@a~6,2f~8,2f~%" i (car ds) (car qs) (car ps) (* (car qs) (car ps))))
      (format #t "~32a~8,2f~%" " Subtotal" tot)
      (format #t "~32a~8,2f~%" " Tax 5.25%" (* tot 0.0525))
      (format #t "~32a~8,2f~%" " Total" (* tot 1.0525)))))

It calls read-items to input the items and compute the subtotal:

(define (read-items)
  (let loop ((ds (list)) (qs (list)) (ps (list)) (tot 0))
    (display "Description? ")
    (let ((descrip (get-line (current-input-port))))
      (if (zero? (string-length descrip))
          (values (reverse ds) (reverse qs) (reverse ps) tot)
          (begin (display "Quantity? ")
                 (let ((quant (string->number (get-line (current-input-port)))))
                   (display "Unit price? ")
                   (let ((price (string->number (get-line (current-input-port)))))
                     (loop (cons descrip ds) (cons quant qs) (cons price ps)
                           (+ tot (* quant price))))))))))

Here’s an example:

> (write-invoice)
Description? Gallon 2% Milk
Quantity? 2
Unit price? 3.30
Description? Ground Beef 93% lean
Quantity? 1
Unit price? 5.98
Description? Can Clam Chowder
Quantity? 12
Unit price? 1.78
Description? 12oz Jar Honey
Quantity? 1
Unit price? 4.42
Description? Half-Dozen Eggs
Quantity? 1
Unit price? 1.18
          Praxis Grocery Store
               16 Feb 2015

1  Gallon 2% Milk        2  3.30    6.60
2  Ground Beef 93% lean  1  5.98    5.98
3  Can Clam Chowder     12  1.78   21.36
4  12oz Jar Honey        1  4.42    4.42
5  Half-Dozen Eggs       1  1.18    1.18
   Subtotal                        39.54
   Tax 5.25%                        2.08
   Total                           41.62

We used get-line and format from R6RS and date arithmetic from the Standard Prelude. Codepad still doesn’t seem to be able to save programs, so the complete program is assembled at the next page.

Pages: 1 2 3

One Response to “Invoice”

  1. use strict;
    use Date::Format qw(time2str);
    my $c = 0;
    my $t = 0;
    my @Q;
    while(1) {
      print STDERR "Product > "; my $p = <STDIN>; chomp $p;
      last unless $p =~ /\S/;
      print STDERR "Quantity> "; my $q = <STDIN>; chomp $q;
      print STDERR "Price   > "; my $a = <STDIN>; chomp $a;
      push @Q, [$c,$p,$q,$a,$q*$a];
    printf '
               Praxis Grocery Store
       Subtotal                          %7.2f
       Tax 5.25%%                         %7.2f
       Total                             %7.2f
     time2str( "%e %b %Y", time ),
     (join q(), map { sprintf "\n%2d %-20s %2d  %7.2f  %7.2f", @{$_} } @Q ),
     $t, $t*0.0525, $t*1.0525;

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: