3 _EXEC="$(realpath "${0%/*}")"
4 . "$_EXEC/cgilite/cgilite.sh"
5 . "$_EXEC/cgilite/logging.sh"
6 . "$_EXEC/cgilite/storage.sh"
7 . "$_EXEC/cgilite/session.sh"
10 printf 'Content-Type: text/html; charset=utf-8\r\n\r\n'
11 ./cgilite/html-sh.sed <<EOF
13 [meta name="viewport" content="width=device-width"]
14 [link rel="stylesheet" type="text/css" href="/invoices.css"]
18 [a "/invoices/" Invoices]
19 [a "/clients/" Clients]
20 [a "/senders/" Senders]
29 if [ -f "clients/$id" ]; then
30 read -r address hourly <"clients/$id"
32 [ "$address" ] || address="address="
33 [ "$hourly" ] || hourly="hourly="
35 [form method="POST" action="/update_client"
37 <textarea name="address" placeholder="address">
39 [label for=hourly Hourly Rate:]
40 [input #hourly type=number name=hourly value="%s"]
41 [submit "update" "update" Update]
44 "$(UNSTRING "${address#address=}" |HTML)" \
45 "$(UNSTRING "${hourly#hourly=}" |grep -xE '[0-9]+')"
50 if [ -f "senders/$id" ]; then
51 address="$(cat "senders/$id")"
53 [ "$address" ] || address="Name
64 [form method="POST" action="/update_sender"
66 <textarea name="address" placeholder="address">%s</textarea>
67 [submit "update" "update" Update]
70 "$(HTML "${address}")"
74 [ -d clients/ ] && for c in clients/*; do
75 read -r address hourly <"$c"
76 address="$(UNSTRING "${address#address=}")"
77 [ "$address" ] || address="(no address)"
78 printf '[div .client .address <!--
81 [label Hourly Rate:] %s€
82 [a href="/clients/%s" Edit]]
83 ' "$(HTML "$address")" \
84 "$(HTML "${hourly#hourly=}")" \
85 "$(HTML "${c#clients/}")"
90 [ -d senders/ ] && for s in senders/*; do
92 [ "$address" ] || address="(no address)"
93 printf '[div .sender .address <!--
94 -->%s[a href="/senders/%s" Edit]]
95 ' "$(HTML "$address")" "$(HTML "${s#senders/}")"
100 local select="$1" n name
101 [ -d senders/ ] && for n in '' senders/*; do
102 [ "$n" ] && name="$(sed q "$n" |HTML)"
103 [ "${n#senders/}" = "$select" ] \
104 && printf '<option value="%s" selected=selected>%s</option>' "${n#senders/}" "$name" \
105 || printf '<option value="%s">%s</option>' "${n#senders/}" "$name"
110 local select="$1" n address hourly name
111 [ -d clients/ ] && for n in '' clients/*; do
112 [ "$n" ] && read -r address hourly <"$n"
113 name="$(UNSTRING "${address#address=}" |sed q |HTML)"
114 [ "${n#clients/}" = "$select" ] \
115 && printf '<option value="%s" selected=selected>%s</option>' "${n#clients/}" "$name" \
116 || printf '<option value="%s">%s</option>' "${n#clients/}" "$name"
121 [ -d invoices/ ] && for i in invoices/*; do
122 read -r sender client date number vat vatrate<<-EOF
125 [ -f "senders/${sender#sender=}" ] \
126 && sender="$(sed q "senders/${sender#sender=}")" \
128 [ ! -f "clients/${client#client=}" ] \
129 && client="(unset)" \
130 || read -r client hourly <"clients/${client#client=}"
131 [ "${date#date=}" -ge 0 ] 2>&- \
132 && date="$(date -d "@${date#date=}" +%x)" \
135 printf '[div .invoice
138 [label From:] %s [label To:] %s [label on] %s
139 [a href="/invoice/%s" Edit]
140 ]' "$(UNSTRING "${number#number=}" |HTML)" \
141 "$(HTML "$sender")" \
142 "$(UNSTRING "${client#address=}" |sed q |HTML)" "$(HTML "$date")" \
143 "$(HTML ${i#invoices/})"
149 if [ -f "invoices/$id" ]; then
150 read -r sender client date number vat vatrate<<-EOF
151 $(sed q "invoices/$id")
155 [ "${date#date=}" -ge 0 ] 2>&- \
156 && date="$(date -d "@${date#date=}" +%F)" \
157 || date="$(date +%F)"
158 [ "${number#number=}" ] || number="number=$(date +%s)"
159 [ "${vatrate#vatrate=}" -ge 0 ] 2>&- || vatrate="vatrate=19"
162 [form method="POST" action="/update_invoice"
163 [hidden "id" "$(HTML "$id")"]
167 $(sender_list "${sender#sender=}")
172 $(client_list "${client#client=}")
175 [label for=number Invoice Number:]
176 [input #number name=number value="$(UNSTRING "${number#number=}" |HTML)"]
178 [label for=date Date:]
179 [input #date name=date value="${date}" placeholder="YYYY-MM-TT"]
181 [radio "vat" "smallbusiness" #vatsb $([ "${vat#vat=}" = smallbusiness ] && printf checked) ]
182 [label for=vatsb Small business exemption from VAT]
183 [radio "vat" "nett" #vatnett $([ "${vat#vat=}" = nett ] && printf checked)]
184 [label for=vatnett Nett]
185 [radio "vat" "gross" #vatgross $([ "${vat#vat=}" = gross ] && printf checked)]
186 [label for=vatgross Gross]
187 [label for=vatrate VAT Rate: [input type=number name="vatrate" value="${vatrate#vatrate=}"]% ]
190 [tr [th Date] [th Work] [th Hours] [th Price] ]
191 $({ sed 1d "invoices/$id"; printf 'time= work= hours=\n'; } \
192 | while read -r time work hours; do
193 hours="$(UNSTRING "${hours#hours=}" |grep -m1 -xE '[0-9]+' || printf 0)"
195 [td [textarea name=date
197 [td [textarea name=work
199 [td [input type=number name=hours value="%s"] ]
201 ]' "$(UNSTRING "${time#time=}" |HTML)" \
202 "$(UNSTRING "${work#work=}" |HTML)" \
203 "$hours" "$((hours * hourly)) €"
207 [submit "update" "update" Update]
212 info="$(PATH "${PATH_INFO}")"
216 . "$_EXEC/cgilite/file.sh"
217 FILE "$_EXEC/invoices.css"
221 printf '[a .new href="/clients/%s" New]' "$(timeid)"
222 } | yield_page clients
225 edit_client "${info#/clients/}" |yield_page client
228 id="$(POST id |checkid)"
229 if [ "$(POST update)" = update -a "$id" ]; then
231 printf 'address=%s hourly=%s' \
232 "$(POST address |STRING)" "$(POST hourly |STRING)" \
235 echo Invalid Data "$(POST id)" "$(POST update)" >&2
241 printf '[a .new href="/senders/%s" New]' "$(timeid)"
242 } | yield_page senders
245 edit_sender "${info#/senders/}" |yield_page sender
248 id="$(POST id |checkid)"
249 if [ "$(POST update)" = update -a "$id" ]; then
251 POST address >"senders/$id"
257 printf '[a .new href="/invoice/%s" New]' "$(timeid)"
258 } | yield_page invoices
261 edit_invoice "${info#/invoice/}" |yield_page invoice
264 id="$(POST id |checkid)"
265 if [ "$(POST update)" = update -a "$id" ]; then
267 printf 'sender=%s client=%s date=%s number=%s vat=%s vatrate=%s\n' \
268 "$(POST sender)" "$(POST client)" \
269 "$(date -d "$(POST date)" +%s)" \
270 "$(POST number |STRING)" \
271 "$(POST vat |grep -m1 -xE 'smallbusiness|gross|nett')" \
272 "$(POST vatrate |grep -m1 -xE '[0-9]+')" \
275 REDIRECT "/invoice/$id"
277 *) REDIRECT /invoices