]> git.plutz.net Git - invoices/blob - invoices.sh
functions for pdf export
[invoices] / invoices.sh
1 #!/bin/sh
2
3 sender_list(){
4   local select="$1" n name address iban bic
5   [ -d senders/ ] && for n in '' senders/*; do
6     [ "$n" ] &&  read -r address iban bic <"$n"
7     name="$(UNSTRING "${address#address=}" |sed q |HTML)"
8     [ "${n#senders/}" = "$select" ] \
9     && printf '<option value="%s" selected=selected>%s</option>' "${n#senders/}" "$name" \
10     || printf '<option value="%s">%s</option>' "${n#senders/}" "$name"
11   done
12 }
13
14 client_list(){
15   local select="$1" n address hourly name
16   [ -d clients/ ] && for n in '' clients/*; do
17     [ "$n" ] && read -r address hourly <"$n"
18     name="$(UNSTRING "${address#address=}" |sed q |HTML)"
19     [ "${n#clients/}" = "$select" ] \
20     && printf '<option value="%s" selected=selected>%s</option>' "${n#clients/}" "$name" \
21     || printf '<option value="%s">%s</option>' "${n#clients/}" "$name"
22   done
23 }
24
25 list_invoices(){
26   local sender client date number vat vatrate iban bic hourly
27   [ -d invoices/ ] && for i in invoices/*; do
28     read -r sender client date number vat vatrate<<-EOF
29         $(sed q "$i")
30         EOF
31
32     [ ! -f "senders/${sender#sender=}" ] \
33     && sender="(unset)" \
34     || read -r sender iban bic <"senders/${sender#sender=}"
35
36     [ ! -f "clients/${client#client=}" ] \
37     && client="(unset)" \
38     || read -r client hourly <"clients/${client#client=}"
39
40     [ "${date#date=}" -ge 0 ] 2>&- \
41     && date="$(date -d "@${date#date=}" +%x)" \
42     || date="(unset)"
43
44     printf '[div .invoice
45       [h2
46           %s]
47       [label From:] %s [label To:] %s [label on] %s
48       [label Amount:] %.2f €
49       [a href="/invoices/%s" Edit]
50     ]' "$(UNSTRING "${number#number=}" |HTML)" \
51        "$(UNSTRING "${sender#address=}" |sed q |HTML)" \
52        "$(UNSTRING "${client#address=}" |sed q |HTML)" "$(HTML "$date")" \
53        "$(invoice_total "${i#invoices/}")" \
54        "$(HTML ${i#invoices/})"
55   done
56 }
57
58 edit_invoice(){
59   local id="$1" sender client date number vat vatrate caddress hourly total
60   if [ -f "invoices/$id" ]; then
61     read -r sender client date number vat vatrate<<-EOF
62         $(sed q "invoices/$id")
63         EOF
64   fi
65
66   [ "${date#date=}" -ge 0 ] 2>&- \
67   && date="$(date -d "@${date#date=}" +%F)" \
68   || date="$(date +%F)"
69   [ "${number#number=}" ] \
70   && number="${number#number=}" \
71   || number="$(date +%s)"
72   [ "${vatrate#vatrate=}" -ge 0 ] 2>&- \
73   && vatrate="${vatrate#vatrate=}" \
74   || vatrate=19
75
76   [ -f "clients/${client#client=}" ] \
77   && read -r caddress hourly <"clients/${client#client=}"
78   hourly="${hourly#hourly=}"
79
80   tid="$(tid "invoices/$id")"
81   total=$(invoice_total "$id")
82
83   cat <<-EOF 
84         [form method="POST" action="/update_invoice"
85           [hidden "id" "$(HTML "$id")"]
86         
87           [label Sender:]
88           [select name=sender
89             $(sender_list "${sender#sender=}")
90           ]
91         
92           [label Client:]
93           [select name=client
94             $(client_list "${client#client=}")
95           ]
96         
97           [label for=number Invoice Number:]
98           [input #number name=number value="$(UNSTRING "${number}" |HTML)"]
99         
100           [label for=date Date:]
101           [input #date name=date value="${date}" placeholder="YYYY-MM-TT"]
102         
103           [radio "vat" "smallbusiness" #vatsb $([ "${vat#vat=}" = smallbusiness ] && printf checked) ]
104           [label for=vatsb Small business exemption from VAT]
105           [radio "vat" "nett" #vatnett $([ "${vat#vat=}" = nett ] && printf checked)]
106           [label for=vatnett Nett]
107           [radio "vat" "gross" #vatgross $([ "${vat#vat=}" = gross ] && printf checked)]
108           [label for=vatgross Gross]
109           [label for=vatrate VAT Rate: [input type=number name="vatrate" value="${vatrate}"]% ]
110         
111           [table
112             [tr [th Date] [th Work] [th Hours] [th Price] ]
113 $({ sed 1d "invoices/$id"; printf 'time= work= hours=\n'; } \
114   | while read -r time work hours; do
115     hours="$(UNSTRING "${hours#hours=}" |grep -m1 -xE '[0-9]+' || printf 0)"
116     printf '[tr
117             [td [textarea name=time
118 %s] ]
119             [td [textarea name=work
120 %s] ]
121             [td [input type=number name=hours value="%s"] ]
122             [td %s]
123    ]' "$(UNSTRING "${time#time=}" |HTML)" \
124       "$(UNSTRING "${work#work=}" |HTML)" \
125       "$hours" "$((hours * hourly)) €"
126   done
127 )
128             [tr [td colspan=4 
129             $(case $vat in
130               vat=nett)
131                 awk "BEGIN {
132                   printf \"Sum: %7.2f €<br/> + VAT: %7.2f €<br/> [strong Total:] %7.2f €\",
133                    $total, int($total * $vatrate + .5) / 100,
134                    $total + int($total * $vatrate + .5) / 100
135                 }" ;;
136               vat=gross)
137                 awk "BEGIN {
138                   printf \"[strong Total:] %7.2f €<br/> incl VAT: %7.2f €<br/>+ nett: %7.2f €\",
139                    $total, int($total / (100 + $vatrate) * $vatrate * 100 + .5) / 100,
140                    $total - int($total / (100 + $vatrate) * $vatrate * 100 + .5) / 100
141                 }" ;;
142               *) printf '[strong Total:] %.2f €' "$total" ;;
143             esac)
144             ]]
145           ]
146           [submit "genpdf" "$tid" Export PDF]
147           [submit "update" "$tid" Update]
148         ]
149         EOF
150 }
151
152 invoice_total(){
153   local id="$1" sender client date number vat vatrate \
154         total=0 caddress hourly time work hours
155
156   if [ -f "invoices/$id" ]; then
157     read -r sender client date number vat vatrate<<-EOF
158         $(sed q "invoices/$id")
159         EOF
160
161     [ -f "clients/${client#client=}" ] \
162     && read -r caddress hourly <"clients/${client#client=}"
163     [ "${hourly#hourly=}" -gt 0 ] 2>&- \
164     && hourly="${hourly#hourly=}" \
165     || hourly=0
166
167     sed 1d "invoices/$id" \
168     | { while read -r time work hours; do
169         [ "${hours#hours=}" -gt 0 ] 2>&- \
170         && hours="${hours#hours=}" \
171         || hours=0
172         total=$((total + hours * hourly))
173       done
174       printf %.2f\\n "$total"
175     }
176   else
177     printf %.2f\\n 0
178   fi
179 }
180
181 update_invoice(){
182   local id="$(POST id |checkid)" extra=0 tid
183   tid="$(tid invoices/$id)"
184
185   if [ "$(POST update)" = "$tid" ] || [ "$(POST genpdf)" = "$tid" ]; then
186     mkdir -p invoices
187
188     for n in "$(POST_COUNT time)" "$(POST_COUNT work)" "$(POST_COUNT hours)"; do
189       [ "$n" -gt "$extra" ] && extra="$n"
190     done
191
192     { printf 'sender=%s client=%s       date=%s number=%s       vat=%s  vatrate=%s\n' \
193         "$(POST sender)" "$(POST client)" \
194         "$(date -d "$(POST date)" +%s)" \
195         "$(POST number |STRING)" \
196         "$(POST vat |grep -m1 -xE 'smallbusiness|gross|nett')" \
197         "$(POST vatrate |grep -m1 -xE '[0-9]+')"
198       for n in $(seq 1 $extra); do
199         printf 'time=%s work=%s hours=%s\n' \
200           "$(POST time $n |STRING)" "$(POST work $n |STRING)" \
201           "$(POST hours $n |STRING)" \
202         | grep -xvF 'time=      work=   hours=0'
203       done
204     } >"invoices/$id"
205   fi
206   if [ "$(POST genpdf)" ]; then
207     . $_EXEC/odtgen.sh
208     genodt "$id"
209   fi
210   REDIRECT "/invoices/$id"
211 }