#! /bin/sh

# Poor man's checkbook program

cp register.txt register.bak

case $# in
2)  case "$1" in
    "-t"|"-tax") awk 'BEGIN{FS="\t";t=0}
	(("-"==$2)&&("T"==$5)){
	    printf "%s %5d.%02d   %s\n",$1,int($3/100),$3%100,$6; t+=$3
	}END{
	    printf "Total:   %5d.%02d\n",int(t/100),t%100}' <$2
	exit;;
    *) echo "usage: `basename "$0"` <bankbalance> or -tax <filename> or -names"
	exit;;
    esac;;

1)  case "$1" in
    "-n"|"-names") awk 'BEGIN{FS="\t"}{print $6}' register.txt |
	sort | uniq -c; exit;;
    "-h"|"-help") x=`basename "$0"`
 	echo "usage: $x               (regular transaction stuff)"
	echo "       $x <bankbal>     (reconcile statement)"
	echo "       $x -names        (print summary of payee names)"
	echo "       $x -tax <file>   (extract tax-deductable payments)"
	exit;;
    *)  B=`echo "$1" | awk '
	    /^[0-9][0-9]*$/{print 100*$0}
	    /^[0-9]*\.[0-9][0-9]$/{split($0,a,".");print 100*a[1]+a[2]}'`
	case "$B" in
	"") echo "Could not extract bank balance from $1"; exit;;
	esac;;
    esac;;

0);;

*) echo "usage: `basename "$0"` <bankbalance> or -tax <filename> or -names"
   exit;;
esac


while true; do

    awk 'BEGIN{FS="\t"; b=0; x=0; B="'"$B"'"
	    print "Num    Date   Typ  Amount   Balance  C  T  Description"
	}{
	    C = T = " "; amt = $3
	    if ("-" == $2) amt = -amt
	    b += amt
	    if ("*" == $4) {C = "*"; x += amt}
	    if ("T" == $5) T = "T"
	    printf "%-4d %s  %s %5d.%02d  %5d.%02d  %s  %s  %s\n",\
		NR,$1,$2,int($3/100),$3%100,int(b/100),b%100,C,T,$6
	}END{ if ("" != B) {
		c = B + x
		printf "Checkbook balance should be %d.%02d\n",int(c/100),c%100
		if (b != c) {
		    d = c - b
		    if (0 > d) d = -d
		    printf "Discrepancy %d.%02d\n",int(d/100),d%100
		}
	    }
	}' <register.txt

    while true; do
	# because we cannot depend on echo -n
	echo "cbook (pdctuqh?): " | awk '{printf $0}'
	if read cmd first rest; then
	    case "$cmd" in

	    p|pay|payment)
		case "$first" in
		"") while true; do
		    awk 'BEGIN{printf "Pay how much: ";exit}'
		    if read first; then
			case "$first" in
			""|"?") echo "How much is payment (e.g., 123.45)";;
			*)break;;
			esac
		    else
			echo "EOF!"; exit
		    fi
		    done;;
		*);;
		esac
		amt=`echo $first | awk '
		    /^[0-9][0-9]*$/{print 100*$0}
		    /^[0-9]*\.[0-9][0-9]$/{split($0,a,".")
			print 100*a[1]+a[2]}'`
		case "$amt" in
		"") echo "Did not understand amount $first";;
		*)
		    damt=`echo $amt | awk '{
			printf "%d.%02d",int($0/100),$0%100
		    }'`
		    case "$rest" in
		    "")
			while true; do
			    echo "Pay \$$damt to: " | awk '{printf $0}'
			    if read rest; then
				case "$rest" in
				"?") echo "Pay \$$damt to whom?";;
				"");; *)break;;
				esac
			    else
				echo "EOF!"; exit
			    fi
			done;;
		    esac
		    echo "Pay \$$damt to $rest"
		    while true; do
			echo "`date +%Y%m%d`? " | awk '{printf $0}'
			if read date; then
			    case "$date" in
			    [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]) break;;
			    [0-9][0-9][0-9][0-9]) date="`date +%Y`$date";
				break;;
			    [0-9][0-9]) date="`date +%Y%m`$date"; break;;
			    "") date="`date +%Y%m%d`"; break;;
			    q|quit) break 2;;
			    "?")
				echo "blank line accepts suggested date"
				echo "two digits replace day of month"
				echo "four digits replace month and day"
				echo "eight digits replace entire date"
				echo "q to abort entry of payment";;
			    *)  echo "Input \"$date\" unknown (? for help)";;
			    esac
			else
			    echo "EOF!"; exit
			fi
		    done
		    mv register.txt register.undo
		    awk '{print}END{
			printf "'"$date"'\t-\t'"$amt"'\t*\t\t%s\n","'"$rest"'"
			}' register.undo | sort >register.txt
		    break;;
		esac;;

	    d|dep|deposit)
		case "$first" in
		"") while true; do
		    awk 'BEGIN{printf "Deposit how much: ";exit}'
		    if read first; then
			case "$first" in
			""|"?") echo "How much is deposit (e.g., 123.45)";;
			*)break;;
			esac
		    else
			echo "EOF!"; exit
		    fi
		    done;;
		*);;
		esac
		amt=`echo $first | awk '
		    /^[0-9][0-9]*$/{print 100*$0}
		    /^[0-9]*\.[0-9][0-9]$/{split($0,a,".")
			print 100*a[1]+a[2]}'`
		case "$amt" in
		"") echo "Did not understand amount $first";;
		*)
		    damt=`echo $amt | awk '{
			printf "%d.%02d",int($0/100),$0%100
		    }'`
		    case "$rest" in
		    "")
			while true; do
			    echo "Deposit \$$damt from: " | awk '{printf $0}'
			    if read rest; then
				case "$rest" in
				"?") echo "Deposit \$$damt from whom?";;
				"");; *)break;;
				esac
			    else
				echo "EOF!"; exit
			    fi
			done;;
		    esac
		    echo "Deposit \$$damt from $rest"
		    while true; do
			echo "`date +%Y%m%d`? " | awk '{printf $0}'
			if read date; then
			    case "$date" in
			    [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]) break;;
			    [0-9][0-9][0-9][0-9]) date="`date +%Y`$date";
				break;;
			    [0-9][0-9]) date="`date +%Y%m`$date"; break;;
			    "") date="`date +%Y%m%d`"; break;;
			    q|quit) break 2;;
			    "?")
				echo "blank line accepts suggested date"
				echo "two digits replace day of month"
				echo "four digits replace month and day"
				echo "eight digits replace entire date"
				echo "q to abort entry of deposit";;
			    *)  echo "Input \"$date\" unknown (? for help)";;
			    esac
			else
			    echo "EOF!"; exit
			fi
		    done
		    mv register.txt register.undo
		    awk '{print}END{
			printf "'"$date"'\t+\t'"$amt"'\t*\t\t%s\n","'"$rest"'"
			}' register.undo | sort >register.txt
		    break;;
		esac;;

	    c|clear)first="$first $rest"
		case "$first" in
		" ") while true; do
		    echo "Mark which transactions as clear: " |
			awk '{printf $0}'
		    if read first; then
			case "$first" in
			""|"?") echo "Which transaction nums to mark clear?";;
			*) break;;
			esac
		    else
			echo "EOF!"; exit
		    fi
		    done;;
		esac
		nums=`echo "$first" | awk '/^[0-9 ]*$/{print}'`
		case "$nums" in
		"") echo "Could not get trans num list from $first";;
		*)  mv register.txt register.undo
		    awk 'BEGIN{FS="\t";OFS="\t";a="'"$nums"'";n=split(a,b," ")
			    for(i=1;i<=n;i++)x[b[i]]="*"
			}("*"!=x[NR]){print;next
			}{print $1,$2,$3,"",$5,$6;x[NR]=""
			  printf "%s\t%s\n",$3,$6|"cat 1>&2"
			}END{for(i in x)if("*"==x[i])
			    print "Not ",i|"cat 1>&2"
			}' <register.undo >register.txt
		    break;;
		esac;;

	    t|tax)first="$first $rest"
		case "$first" in
		" ") while true; do
		    echo "Mark which transactions as tax-deductable: " |
			awk '{printf $0}'
		    if read first; then
			case "$first" in
			""|"?") echo "Which transaction nums to mark tax?";;
			*) break;;
			esac
		    else
			echo "EOF!"; exit
		    fi
		    done;;
		esac
		nums=`echo "$first" | awk '/^[0-9 ]*$/{print}'`
		case "$nums" in
		"") echo "Could not get trans num list from $first";;
		*)  mv register.txt register.undo
		    awk 'BEGIN{FS="\t";OFS="\t";a="'"$nums"'";n=split(a,b," ")
			    for(i=1;i<=n;i++)x[b[i]]="*"
			}("*"!=x[NR]){print;next
			}{print $1,$2,$3,$4,"T",$6;x[NR]=""
			  printf "%s\t%s\n",$3,$6|"cat 1>&2"
			}END{for(i in x)if("*"==x[i])
			    print "Not ",i|"cat 1>&2"
			}' <register.undo >register.txt
		    break;;
		esac;;

	    u|undo)
		if [ -w register.undo ]; then
		    while true; do
			diff register.undo register.txt
			while true; do
			    echo "REALLY want to undo this change (yn?h) " |
				awk '{printf $0}'
			    if read yn; then
				case "$yn" in
				y|yes)
				    rm register.txt
				    mv register.undo register.txt
				    break 3;;
				n|no) break 3;;
				?|h|help) echo "Undo this change?";;
				 *) break;;
				esac
			    else
				echo "EOF!"; exit
			    fi
			done
		    done
		else
		    echo "There is no change to undo"
		fi;;

	    q|quit) exit;;

	    "?") echo "pay, deposit, clear, tax, undo, quit, help";;

	    h|he|hel|help)
		echo "commands:"
		echo "pay <amount> <towhom>             (enter payment)"
		echo "deposit <amount> <fromwhom>       (enter deposit)"
		echo "clear <transnum>                  (mark as cleared)"
		echo "tax <transnum>                    (mark as deductible)"
		echo "undo                              (undo last change)"
		echo "quit"
		echo "<transnum> may be space-separated list of nums"
		echo "When pay or deposit prompt with date, responses are:"
		echo "<blank line>    accept date as-is"
		echo "two digits      replace day"
		echo "four digits     replace month and day"
		echo "eight digits    replace entire date"
		echo "use `basename "$0"` -help for command line usage";;

	    *) echo "Command $cmd not understood, enter ? for help";;

	    esac
	else
	    echo "EOF!"; exit
	fi
    done
    echo "command completed"
done
exit

# commands are listed in help block

# command line parameters are listed at top

# The register.txt file is tab-separated:
# date type amount clear tax description

# 1 date - standard 20020509 yyyymmdd form for sorting
# 2 type - "+" for deposit "-" for payment
# 3 amount - integer pennies
# 4 clear - flag item has cleared "*" if not "" if so
# 5 tax - flag item is tax deductable "T" if so "" if not
# 6 description - who or what

# Free softwear, July 2002, Charles B. Cranston <zben@umd.edu>
