1<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 2 "http://www.w3.org/TR/html4/loose.dtd"> 3<?scm 4(let ((x 42)) ; only here to allow (define)s 5 ; i.e. to avoid "Bad define placement" error 6 7;; taxinvoice.eguile.scm 0.03 8;; GnuCash report template called from taxinvoice.scm 0.02 9;; (c) 2009 Chris Dennis chris@starsoftanalysis.co.uk 10;; © 2012 Dmitry Smirnov <onlyjob@member.fsf.org> 11;; 12;; $Author: chris $ $Date: 2009/07/23 10:42:08 $ $Revision: 1.33 $ 13;; Modified by Dmitry Smirnov <onlyjob@member.fsf.org> 16 Feb 2012 14;; 15;; This file is a mixture of HTML and Guile -- 16;; see eguile-gnc.scm for details. 17;; 18;; This program is free software; you can redistribute it and/or 19;; modify it under the terms of the GNU General Public License as 20;; published by the Free Software Foundation; either version 2 of the 21;; License, or (at your option) any later version. 22;; 23;; This program is distributed in the hope that it will be useful, 24;; but WITHOUT ANY WARRANTY; without even the implied warranty of 25;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 26;; General Public License for more details. 27;; 28;; You should have received a copy of the GNU General Public License 29;; along with this program; if not, write to the Free Software 30;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 31;; 02111-1307 USA 32 (define (display-report opt-invoice) 33 34 (define (date<? s1 s2) 35 (< (xaccTransGetDate (xaccSplitGetParent s1)) 36 (xaccTransGetDate (xaccSplitGetParent s2)))) 37 38 ;; Main function that creates the tax invoice report 39 (let* (; invoice and company details 40 (invoiceid (gncInvoiceGetID opt-invoice)) 41 (credit-note? (gncInvoiceGetIsCreditNote opt-invoice)) 42 (book (gncInvoiceGetBook opt-invoice)) 43 (isposted (gncInvoiceIsPosted opt-invoice)) 44 (postdate (gncInvoiceGetDatePosted opt-invoice)) 45 (duedate (gncInvoiceGetDateDue opt-invoice)) 46 (billingid (gncInvoiceGetBillingID opt-invoice)) 47 (notes (gncInvoiceGetNotes opt-invoice)) 48 (terms (gncInvoiceGetTerms opt-invoice)) 49 (termsdesc (gncBillTermGetDescription terms)) 50 (lot (gncInvoiceGetPostedLot opt-invoice)) 51 (txn (gncInvoiceGetPostedTxn opt-invoice)) 52 (currency (gncInvoiceGetCurrency opt-invoice)) 53 (entries (gncInvoiceGetEntries opt-invoice)) 54 (splits (sort (gnc-lot-get-split-list lot) date<?)) 55 (dateformat (gnc:options-fancy-date book)) 56 (coyname (gnc:company-info book gnc:*company-name*)) 57 (coycontact (gnc:company-info book gnc:*company-contact*)) 58 (coyaddr (gnc:company-info book gnc:*company-addy*)) 59 (coyid (gnc:company-info book gnc:*company-id*)) 60 (coyphone (gnc:company-info book gnc:*company-phone*)) 61 (coyfax (gnc:company-info book gnc:*company-fax*)) 62 (coyurl (gnc:company-info book gnc:*company-url*)) 63 (coyemail (gnc:company-info book gnc:*company-email*)) 64 (owner (gncInvoiceGetOwner opt-invoice)) 65 (owneraddr (gnc:owner-get-address-dep owner)) 66 (ownername (gnc:owner-get-name-dep owner)) 67 (jobnumber (gncJobGetID (gncOwnerGetJob (gncInvoiceGetOwner opt-invoice)))) 68 (jobname (gncJobGetName (gncOwnerGetJob (gncInvoiceGetOwner opt-invoice)))) 69 (billcontact (gncAddressGetName (gnc:owner-get-address owner))) 70 (cust-doc? (eqv? (gncInvoiceGetType opt-invoice) GNC-INVOICE-CUST-INVOICE)) 71 (reverse-payments? (not (gncInvoiceAmountPositive opt-invoice))) 72 ; flags and counters 73 (discount? #f) ; any discounts on this invoice? 74 (tax? #f) ; any taxable entries on this invoice? 75 (payments? #f) ; have any payments been made on this invoice? 76 (units? #f) ; does any row specify units? 77 (qty? #f) ; does any row have qty <> 1? 78 (tbl_cols 0)) ; number of columns for 'colspan' attributes 79 80 ;; pre-scan invoice entries to look for discounts and taxes 81 (for-each 82 (lambda (entry) 83 (unless (string-null? (gncEntryGetAction entry)) (set! units? #t)) 84 (unless (= 1 (gncEntryGetDocQuantity entry credit-note?)) (set! qty? #t)) 85 (cond 86 (cust-doc? 87 (unless (zero? (gncEntryGetInvDiscount entry)) (set! discount? #t)) 88 (unless (null? (gncEntryGetInvTaxTable entry)) (set! tax? #t))) 89 (else 90 (unless (null? (gncEntryGetBillTaxTable entry)) (set! tax? #t))))) 91 entries) 92 93 ;; pre-scan invoice splits to see if any payments have been made 94 (let lp ((splits splits)) 95 (cond 96 ((null? splits) #f) 97 ((equal? (xaccSplitGetParent (car splits)) txn) (lp (cdr splits))) 98 (else (set! payments? #t)))) 99?> 100 101<!-- ====================================================================== --> 102<!-- The HTML for the invoice starts here --> 103<html dir='auto'> 104<head> 105<meta http-equiv="Content-Type" content="text/html;charset=utf-8" > 106<title><?scm:d (G_ "Invoice") ?> <?scm:d invoiceid ?></title> 107 108<link rel="stylesheet" href="<?scm:d (make-file-url opt-css-file) ?>" type="text/css"> 109<!-- Note that the external stylesheet file is overridden by this following: --> 110<style type="text/css"> 111 body { 112 <?scm:d opt-text-font ?> 113 } 114 table { /* table does not inherit font */ 115 <?scm:d opt-text-font ?> 116 <?scm:d opt-css-border-collapse ?> 117 } 118 table[border="1"] th { 119 border-color:<?scm:d opt-css-border-color-th ?>; 120 } 121 table[border="1"] td { 122 border-color:<?scm:d opt-css-border-color-td ?>; 123 } 124 125 h1.coyname { 126 <?scm:d opt-heading-font ?> 127 } 128 <?scm:d opt-extra-css ?> 129</style> 130 131</head> 132<body> 133 134<div class="main"> 135 136<!-- company info --> 137<table class="coytable" border="0" width="100%"> 138<tr valign="top" style="vertical-align: top"> 139 <?scm (if (access? opt-logofile R_OK) (begin ?> 140 <td align="left"> 141 <img align="left" src="<?scm:d (make-file-url opt-logofile) ?>" alt="logo" class="logo" 142 <?scm (if opt-logo-width (begin ?> 143 style="width: <?scm:d opt-logo-width ?>" 144 <?scm )) ?> 145 > 146 </td> 147 <?scm )) ?> 148 <td align="left"> 149 <h1 class="coyname"><?scm:d (or coyname (G_ "Company Name")) ?></h1> 150 </td> 151 <td align="right"><h2 class="invoice"><?scm:d opt-report-title ?> 152 <?scm (if opt-invnum-next-to-title (begin ?><?scm:d (nbsp invoiceid) ?><?scm )) ?> 153 </h2></td> 154</tr> 155</table> 156<table border="0" width="100%"> 157<tr valign="top"> 158 <td align="left"> 159 <?scm (if (and opt-row-address coyaddr) (begin ?> 160 <?scm:d (nl->br coyaddr) ?><br> 161 <?scm )) ?> 162 <?scm (if coyid (begin ?> 163 <strong><?scm:d coyid ?></strong><br> 164 <?scm )) ?> 165 </td> 166 <td align="right"> 167 <table border="0"> 168 <?scm (if (and opt-row-contact coycontact) (begin ?> 169 <tr> 170 <th colspan="2" align="right"><?scm:d coycontact ?></th> 171 </tr> 172 <?scm )) ?> 173 <?scm (if coyphone (begin ?> 174 <tr> 175 <td align="right"><?scm:d (G_ "Phone") ?>: </td> 176 <td align="right"><?scm:d coyphone ?></td> 177 </tr> 178 <?scm )) ?> 179 <?scm (if coyfax (begin ?> 180 <tr> 181 <td align="right"><?scm:d (G_ "Fax") ?>: </td> 182 <td align="right"><?scm:d coyfax ?></td> 183 </tr> 184 <?scm )) ?> 185 <?scm (if coyemail (begin ?> 186 <tr> 187 <td align="right"><?scm:d (G_ "Email") ?>: </td> 188 <td align="right"><?scm:d coyemail ?></td> 189 </tr> 190 <?scm )) ?> 191 <?scm (if coyurl (begin ?> 192 <tr> 193 <td align="right"><?scm:d (G_ "Website") ?>: </td> 194 <td align="right"><?scm:d coyurl ?></td> 195 </tr> 196 <?scm )) ?> 197 </table> 198</tr> 199</table> 200<hr> 201 202<table border="0" width="100%"> 203<tr valign="top"> 204 <!-- customer info --> 205 <th align="right" width="1%"><?scm:d opt-to-text ?></th> 206 <td align="left"> 207 <?scm (if (and opt-row-company-name (not (string=? ownername ""))) (begin ?> 208 <?scm:d ownername ?><br> 209 <?scm )) ?> 210 <?scm (if (not (string=? owneraddr "")) (begin ?> 211 <?scm:d (nl->br owneraddr) ?> 212 <?scm )) ?> 213 </td> 214 <!-- invoice number etc. --> 215 <td align="right"> 216 <table border="0"> 217 <?scm (if opt-row-invoice-number (begin ?> 218 <tr> 219 <td align="right" class="invnum"><big><strong><?scm:d (nbsp opt-invoice-number-text) ?></strong></big></td> 220 <td align="right" class="invnum"><big><strong><?scm:d invoiceid ?></strong></big></td> 221 </tr> 222 <?scm )) ?> 223 <?scm (if (not isposted) (begin ?> 224 <tr> 225 <td colspan="2" align="right"><?scm:d (G_ "Invoice in progress...") ?></td> 226 </tr> 227 <?scm ) (begin ?> 228 <tr> 229 <td align="right"><?scm:d (nbsp (G_ "Invoice Date")) ?>: </td> 230 <td align="right"><?scm:d (nbsp (gnc-print-time64 postdate dateformat)) ?></td> 231 </tr> 232 <tr> 233 <td align="right"><?scm:d (nbsp (G_ "Due Date")) ?>: </td> 234 <td align="right"><?scm:d (nbsp (gnc-print-time64 duedate dateformat)) ?></td> 235 </tr> <?scm )) ?> 236 <?scm (if (not (string=? billingid "")) (begin ?> 237 <tr> 238 <td align="right"><?scm:d opt-ref-text ?></td> 239 <td align="right"><?scm:d billingid ?></td> 240 </tr> 241 <?scm )) ?> 242 <?scm (if (and opt-jobname-show (not (string=? jobname ""))) (begin ?> 243 <tr> 244 <td align="right"><?scm:d opt-jobname-text ?></td> 245 <td align="right"><?scm:d jobname ?></td> 246 </tr> 247 <?scm )) ?> 248 <?scm (if (and opt-jobnumber-show (not (string=? jobnumber ""))) (begin ?> 249 <tr> 250 <td align="right"><?scm:d opt-jobnumber-text ?></td> 251 <td align="right"><?scm:d jobnumber ?></td> 252 </tr> 253 <?scm )) ?> 254 <?scm (if (not (string=? termsdesc "")) (begin ?> 255 <tr><td colspan="2" align="right"><?scm:d termsdesc ?></td></tr> 256 <?scm )) ?> 257 </table> 258 </td> 259</tr> 260</table> 261 262<!-- invoice lines table --> 263<p> 264<table border="1" width="100%" cellpadding="4" class="entries"> 265 <thead> 266 <tr bgcolor="#ccc" valign="bottom"> 267 <?scm (if opt-col-date (begin ?> 268 <th align="center" ><?scm:d (G_ "Date") ?></th> 269 <?scm (set! tbl_cols (+ tbl_cols 1)) )) ?> 270 <th align="left" width="80%"><?scm:d (G_ "Description") ?></th> 271 <?scm (if (and units? opt-col-units) (begin ?> 272 <th align="left"><?scm:d opt-units-heading ?></th> 273 <?scm (set! tbl_cols (+ tbl_cols 1)) )) ?> 274 <?scm (if (or units? qty?) (begin ?> 275 <th align="right"><?scm:d opt-qty-heading ?></th> 276 <?scm (set! tbl_cols (+ tbl_cols 1)) )) ?> 277 <?scm (if (or units? qty? discount?) (begin ?> 278 <th align="right"><?scm:d opt-unit-price-heading ?></th> 279 <?scm (set! tbl_cols (+ tbl_cols 1)) )) ?> 280 <?scm (if discount? (begin ?> 281 <th align="right"><?scm:d opt-disc-rate-heading ?></th> 282 <th align="right"><?scm:d opt-disc-amount-heading ?></th> 283 <?scm (set! tbl_cols (+ tbl_cols 2)) )) ?> 284 <?scm (if tax? (begin ?> 285 <th align="right"><?scm:d opt-net-price-heading ?></th> 286 <?scm (set! tbl_cols (+ tbl_cols 1)) ?> 287 <?scm (if opt-col-taxrate (begin ?> 288 <th align="right"><?scm:d opt-tax-rate-heading ?></th> 289 <?scm (set! tbl_cols (+ tbl_cols 1)) )) ?> 290 <th align="right"><?scm:d opt-tax-amount-heading ?></th> 291 <?scm (set! tbl_cols (+ tbl_cols 1)) )) ?> 292 <th align="right"><?scm:d opt-total-price-heading ?></th> 293 </tr> 294 </thead> 295 296 <tbody> <!-- display invoice entry lines, keeping running totals --> 297 <?scm 298 (let* ((inv-total (gncInvoiceGetTotal opt-invoice)) 299 (tax-total (gncInvoiceGetTotalTax opt-invoice)) 300 (sub-total (gncInvoiceGetTotalSubtotal opt-invoice)) 301 (dsc-total (- inv-total tax-total sub-total)) 302 (total-col (gnc:make-commodity-collector))) 303 (total-col 'add currency inv-total) 304 (for-each 305 (lambda (entry) 306 (let ((qty (gncEntryGetDocQuantity entry credit-note?)) 307 (each (gncEntryGetPrice entry cust-doc? opt-netprice)) 308 (action (gncEntryGetAction entry)) 309 (rval (gncEntryGetDocValue entry #t cust-doc? credit-note?)) 310 (rdiscval (gncEntryGetDocDiscountValue entry #t cust-doc? credit-note?)) 311 (rtaxval (gncEntryGetDocTaxValue entry #t cust-doc? credit-note?)) 312 (disc (if cust-doc? (gncEntryGetInvDiscount entry))) 313 (disctype (gncEntryGetInvDiscountType entry)) 314 (acc (if cust-doc? (gncEntryGetInvAccount entry)(gncEntryGetBillAccount entry))) 315 (taxable (if cust-doc? (gncEntryGetInvTaxable entry)(gncEntryGetBillTaxable entry))) 316 (taxtable (if cust-doc? (gncEntryGetInvTaxTable entry)(gncEntryGetBillTaxTable entry)))) 317 ?> 318 <tr valign="top"> 319 <?scm (if opt-col-date (begin ?> 320 <td align="center" ><?scm:d (nbsp (qof-print-date (gncEntryGetDate entry))) ?></td> 321 <?scm )) ?> 322 <td align="left"><?scm:d (gncEntryGetDescription entry) ?></td> 323 <!-- td align="left">< ?scm:d (gncEntryGetNotes entry) ?></td --> 324 <?scm (if opt-col-units (begin ?> 325 <?scm (if units? (begin ?> 326 <td align="left"><?scm:d action ?></td> 327 <?scm )) ?> 328 <?scm )) ?> 329 <?scm (if (or units? qty?) (begin ?> 330 <td align="right"><?scm:d (fmtnumeric qty) ?></td> 331 <?scm )) ?> 332 <?scm (if (or units? qty? discount?) (begin ?> 333 <td align="right"><?scm:d (fmtmoney currency each) ?></td> 334 <?scm )) ?> 335 <?scm (if discount? (begin ?> 336 <?scm (if (equal? disctype GNC-AMT-TYPE-VALUE) (begin ?> 337 <td align="right"><?scm:d (gnc:monetary->string (gnc:make-gnc-monetary currency disc)) ?></td> 338 <?scm ) (begin ?> 339 <td align="right"><?scm:d (fmtnumeric disc) ?>%</td> 340 <?scm )) ?> 341 <td align="right"><?scm:d (fmtmoney currency rdiscval) ?></td> 342 <?scm )) ?> 343 <?scm (if tax? (begin ?> 344 <td align="right"><?scm:d (fmtmoney currency rval) ?></td> 345 <?scm (if opt-col-taxrate (begin ?> 346 <td align="right"><?scm (taxrate taxable taxtable currency) ?></td> 347 <?scm )) ?> 348 <td align="right"><?scm:d (fmtmoney currency rtaxval) ?></td> 349 <?scm )) ?> 350 <!-- TO DO: need an option about whether to display the tax-inclusive total? --> 351 <td align="right"><?scm:d (fmtmoney currency (gnc-numeric-add rval rtaxval GNC-DENOM-AUTO GNC-RND-ROUND)) ?></td> 352 </tr> 353 <?scm )) 354 entries) ?> 355 356 <!-- subtotals row --> 357 <?scm (if (or tax? discount? payments?) (begin ?> 358 <tr valign="top"> 359 <td align="left" class="subtotal" colspan="<?scm:d 360 (- tbl_cols (if (and tax? opt-col-taxrate) 1 0) 361 (if tax? 1 -1) 362 (if (and discount?) 1 0) 363 ) ?>"><strong><?scm:d opt-subtotal-heading ?></strong></td> 364 <?scm (if discount? (begin ?> 365 <td align="right" class="subtotal"><strong><?scm:d (fmtmoney currency dsc-total) ?></strong></td> 366 <?scm )) ?> 367 <?scm (if tax? (begin ?> 368 <td align="right" class="subtotal"><strong><?scm:d (fmtmoney currency sub-total) ?></strong></td> 369 <?scm (if opt-col-taxrate (begin ?> 370 <td> </td> 371 <?scm )) ?> 372 <td align="right" class="subtotal"><strong><?scm:d (fmtmoney currency tax-total) ?></strong></td> 373 <?scm )) ?> 374 <td align="right" class="subtotal"><strong><?scm:d (fmtmoney currency inv-total) ?></strong></td> 375 </tr> 376 <?scm )) ?> 377 378 <!-- payments row --> 379 <?scm 380 (when payments? 381 (for-each 382 (lambda (split) 383 (let ((t (xaccSplitGetParent split))) 384 (unless (equal? t txn) ; don't process the entry itself as a split ;' 385 (let ((c (xaccTransGetCurrency t)) 386 (a (if reverse-payments? 387 (- (xaccSplitGetValue split)) 388 (xaccSplitGetValue split)))) 389 (total-col 'add c a) 390 ?> 391 <tr valign="top"> 392 <?scm (when opt-col-date ?> 393 <td align="center"><?scm:d (qof-print-date (xaccTransGetDate t)) ?></td> 394 <?scm ) ?> 395 <td align="left" colspan="<?scm:d (+ tbl_cols (if opt-col-date 0 1)) ?>"><?scm:d opt-payment-recd-heading ?></td> 396 <td align="right"><?scm:d (fmtmoney c a) ?></td> 397 </tr> 398 <?scm )))) 399 splits)) ?> 400 401 <!-- total row --> 402 <tr valign="top"> 403 <td align="left" class="total" colspan="<?scm:d (+ tbl_cols 1) ?>"><strong> 404 <?scm:d opt-amount-due-heading ?><?scm (if (not (string=? (gnc-commodity-get-mnemonic opt-invoice-currency) "")) (begin ?>, 405 <?scm:d (gnc-commodity-get-mnemonic opt-invoice-currency) ?><?scm )) ?></strong></td> 406 <td align="right" class="total"><strong><?scm (display-comm-coll-total total-col #f) ?></strong></td> 407 </tr> 408 409 </tbody> 410 <?scm ) ?> <!-- end of (let) surrounding table body --> 411</table> 412 413<p><?scm:d (nl->br notes) ?> 414<p><?scm:d (nl->br opt-extra-notes) ?> 415 416<?scm )) ; end of display-report function 417 418 ;; 'mainline' code: check for a valid invoice, then display the report 419 420 421 (cond 422 ((null? opt-invoice) 423 (display (string-append "<h2>" (G_ "Tax Invoice") "</h2>")) 424 (display (string-append "<p>" (G_ "No invoice has been selected -- please use the Options menu to select one.") "</p>"))) 425 426 (else 427 (display-report opt-invoice))) 428 429?> 430</div> 431</body> 432</html> 433<?scm 434) ; end of enclosing let 435?> 436