5bebcb7498ec398b67bc67d25fe315ee9ea3f385
[fa-stable.git] / sales / customer_invoice.php
1 <?php
2 /**********************************************************************
3     Copyright (C) FrontAccounting, LLC.
4         Released under the terms of the GNU General Public License, GPL, 
5         as published by the Free Software Foundation, either version 3 
6         of the License, or (at your option) any later version.
7     This program is distributed in the hope that it will be useful,
8     but WITHOUT ANY WARRANTY; without even the implied warranty of
9     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
10     See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
11 ***********************************************************************/
12 //---------------------------------------------------------------------------
13 //
14 //      Entry/Modify Sales Invoice against single delivery
15 //      Entry/Modify Batch Sales Invoice against batch of deliveries
16 //
17 $page_security = 'SA_SALESINVOICE';
18 $path_to_root = "..";
19 include_once($path_to_root . "/sales/includes/cart_class.inc");
20 include_once($path_to_root . "/includes/session.inc");
21 include_once($path_to_root . "/includes/data_checks.inc");
22 include_once($path_to_root . "/includes/manufacturing.inc");
23 include_once($path_to_root . "/sales/includes/sales_db.inc");
24 include_once($path_to_root . "/sales/includes/sales_ui.inc");
25 include_once($path_to_root . "/reporting/includes/reporting.inc");
26 include_once($path_to_root . "/taxes/tax_calc.inc");
27
28 $js = "";
29 if ($use_popup_windows) {
30         $js .= get_js_open_window(900, 500);
31 }
32 if ($use_date_picker) {
33         $js .= get_js_date_picker();
34 }
35
36 if (isset($_GET['ModifyInvoice'])) {
37         $_SESSION['page_title'] = sprintf(_("Modifying Sales Invoice # %d.") ,$_GET['ModifyInvoice']);
38         $help_context = "Modifying Sales Invoice";
39 } elseif (isset($_GET['DeliveryNumber'])) {
40         $_SESSION['page_title'] = _($help_context = "Issue an Invoice for Delivery Note");
41 } elseif (isset($_GET['BatchInvoice'])) {
42         $_SESSION['page_title'] = _($help_context = "Issue Batch Invoice for Delivery Notes");
43 }
44
45 page($_SESSION['page_title'], false, false, "", $js);
46
47 //-----------------------------------------------------------------------------
48 check_edit_conflicts();
49
50 if (isset($_GET['AddedID'])) {
51
52         $invoice_no = $_GET['AddedID'];
53         $trans_type = ST_SALESINVOICE;
54
55         display_notification(_("Selected deliveries has been processed"), true);
56
57         display_note(get_customer_trans_view_str($trans_type, $invoice_no, _("&View This Invoice")), 0, 1);
58
59         display_note(print_document_link($invoice_no."-".$trans_type, _("&Print This Invoice"), true, ST_SALESINVOICE));
60         display_note(print_document_link($invoice_no."-".$trans_type, _("&Email This Invoice"), true, ST_SALESINVOICE, false, "printlink", "", 1),1);
61
62         display_note(get_gl_view_str($trans_type, $invoice_no, _("View the GL &Journal Entries for this Invoice")),1);
63
64         hyperlink_params("$path_to_root/sales/inquiry/sales_deliveries_view.php", _("Select Another &Delivery For Invoicing"), "OutstandingOnly=1");
65
66         hyperlink_params("$path_to_root/admin/attachments.php", _("Add an Attachment"), "filterType=$trans_type&trans_no=$invoice_no");
67
68         display_footer_exit();
69
70 } elseif (isset($_GET['UpdatedID']))  {
71
72         $invoice_no = $_GET['UpdatedID'];
73         $trans_type = ST_SALESINVOICE;
74
75         display_notification_centered(sprintf(_('Sales Invoice # %d has been updated.'),$invoice_no));
76
77         display_note(get_trans_view_str(ST_SALESINVOICE, $invoice_no, _("&View This Invoice")));
78         echo '<br>';
79         display_note(print_document_link($invoice_no."-".$trans_type, _("&Print This Invoice"), true, ST_SALESINVOICE));
80         display_note(print_document_link($invoice_no."-".$trans_type, _("&Email This Invoice"), true, ST_SALESINVOICE, false, "printlink", "", 1),1);
81
82         hyperlink_no_params($path_to_root . "/sales/inquiry/customer_inquiry.php", _("Select Another &Invoice to Modify"));
83
84         display_footer_exit();
85
86 } elseif (isset($_GET['RemoveDN'])) {
87
88         for($line_no = 0; $line_no < count($_SESSION['Items']->line_items); $line_no++) {
89                 $line = &$_SESSION['Items']->line_items[$line_no];
90                 if ($line->src_no == $_GET['RemoveDN']) {
91                         $line->quantity = $line->qty_done;
92                         $line->qty_dispatched=0;
93                 }
94         }
95         unset($line);
96
97     // Remove also src_doc delivery note
98     $sources = &$_SESSION['Items']->src_docs;
99     unset($sources[$_GET['RemoveDN']]);
100 }
101
102 //-----------------------------------------------------------------------------
103
104 if ( (isset($_GET['DeliveryNumber']) && ($_GET['DeliveryNumber'] > 0) )
105 || isset($_GET['BatchInvoice'])) {
106
107         processing_start();
108
109         if (isset($_GET['BatchInvoice'])) {
110                 $src = $_SESSION['DeliveryBatch'];
111                 unset($_SESSION['DeliveryBatch']);
112         } else {
113                 $src = array($_GET['DeliveryNumber']);
114         }
115
116         /*read in all the selected deliveries into the Items cart  */
117         $dn = new Cart(ST_CUSTDELIVERY, $src, true);
118
119         if ($dn->count_items() == 0) {
120                 hyperlink_params($path_to_root . "/sales/inquiry/sales_deliveries_view.php",
121                         _("Select a different delivery to invoice"), "OutstandingOnly=1");
122                 die ("<br><b>" . _("There are no delivered items with a quantity left to invoice. There is nothing left to invoice.") . "</b>");
123         }
124
125         $_SESSION['Items'] = $dn;
126         copy_from_cart();
127
128 } elseif (isset($_GET['ModifyInvoice']) && $_GET['ModifyInvoice'] > 0) {
129
130         check_is_closed(ST_SALESINVOICE, $_GET['ModifyInvoice']);
131
132         if ( get_sales_parent_numbers(ST_SALESINVOICE, $_GET['ModifyInvoice']) == 0) { // 1.xx compatibility hack
133                 echo"<center><br><b>" . _("There are no delivery notes for this invoice.<br>
134                 Most likely this invoice was created in Front Accounting version prior to 2.0
135                 and therefore can not be modified.") . "</b></center>";
136                 display_footer_exit();
137         }
138         processing_start();
139         $_SESSION['Items'] = new Cart(ST_SALESINVOICE, $_GET['ModifyInvoice']);
140
141         if ($_SESSION['Items']->count_items() == 0) {
142                 echo"<center><br><b>" . _("All quantities on this invoice has been credited. There is nothing to modify on this invoice") . "</b></center>";
143                 display_footer_exit();
144         }
145         copy_from_cart();
146 } elseif (!processing_active()) {
147         /* This page can only be called with a delivery for invoicing or invoice no for edit */
148         display_error(_("This page can only be opened after delivery selection. Please select delivery to invoicing first."));
149
150         hyperlink_no_params("$path_to_root/sales/inquiry/sales_deliveries_view.php", _("Select Delivery to Invoice"));
151
152         end_page();
153         exit;
154 } elseif (!isset($_POST['process_invoice']) && !check_quantities()) {
155         display_error(_("Selected quantity cannot be less than quantity credited nor more than quantity not invoiced yet."));
156 }
157 if (isset($_POST['Update'])) {
158         $Ajax->activate('Items');
159 }
160 if (isset($_POST['_InvoiceDate_changed'])) {
161         $_POST['due_date'] = get_invoice_duedate($_SESSION['Items']->payment, $_POST['InvoiceDate']);
162         $Ajax->activate('due_date');
163 }
164 if (list_updated('payment')) {
165         $_SESSION['Items']->payment = get_post('payment');
166         $_POST['due_date'] = get_invoice_duedate($_SESSION['Items']->payment, $_POST['InvoiceDate']);
167         $Ajax->activate('due_date');
168 }
169
170 //-----------------------------------------------------------------------------
171 function check_quantities()
172 {
173         $ok =1;
174         foreach ($_SESSION['Items']->line_items as $line_no=>$itm) {
175                 if (isset($_POST['Line'.$line_no])) {
176                         if($_SESSION['Items']->trans_no) {
177                                 $min = $itm->qty_done;
178                                 $max = $itm->quantity;
179                         } else {
180                                 $min = 0;
181                                 $max = $itm->quantity - $itm->qty_done;
182                         }
183                         if (check_num('Line'.$line_no, $min, $max)) {
184                                 $_SESSION['Items']->line_items[$line_no]->qty_dispatched =
185                                     input_num('Line'.$line_no);
186                         }
187                         else {
188                                 $ok = 0;
189                         }
190                                 
191                 }
192
193                 if (isset($_POST['Line'.$line_no.'Desc'])) {
194                         $line_desc = $_POST['Line'.$line_no.'Desc'];
195                         if (strlen($line_desc) > 0) {
196                                 $_SESSION['Items']->line_items[$line_no]->item_description = $line_desc;
197                         }
198                 }
199         }
200  return $ok;
201 }
202
203 function set_delivery_shipping_sum($delivery_notes) 
204 {
205     
206     $shipping = 0;
207     
208     foreach($delivery_notes as $delivery_num) 
209     {
210         $myrow = get_customer_trans($delivery_num, 13);
211         //$branch = get_branch($myrow["branch_code"]);
212         //$sales_order = get_sales_order_header($myrow["order_"]);
213         
214         //$shipping += $sales_order['freight_cost'];
215         $shipping += $myrow['ov_freight'];
216     }
217     $_POST['ChargeFreightCost'] = price_format($shipping);
218 }
219
220
221 function copy_to_cart()
222 {
223         $cart = &$_SESSION['Items'];
224         $cart->ship_via = $_POST['ship_via'];
225         $cart->freight_cost = input_num('ChargeFreightCost');
226         $cart->document_date =  $_POST['InvoiceDate'];
227         $cart->due_date =  $_POST['due_date'];
228         if ($cart->pos['cash_sale'] || $cart->pos['credit_sale']) {
229                 $cart->payment = $_POST['payment'];
230                 $cart->payment_terms = get_payment_terms($_POST['payment']);
231         }
232         $cart->Comments = $_POST['Comments'];
233         if ($_SESSION['Items']->trans_no == 0)
234                 $cart->reference = $_POST['ref'];
235         $cart->dimension_id =  $_POST['dimension_id'];
236         $cart->dimension2_id =  $_POST['dimension2_id'];
237
238 }
239 //-----------------------------------------------------------------------------
240
241 function copy_from_cart()
242 {
243         $cart = &$_SESSION['Items'];
244         $_POST['ship_via'] = $cart->ship_via;
245         $_POST['ChargeFreightCost'] = price_format($cart->freight_cost);
246         $_POST['InvoiceDate']= $cart->document_date;
247         $_POST['due_date'] = $cart->due_date;
248         $_POST['Comments']= $cart->Comments;
249         $_POST['cart_id'] = $cart->cart_id;
250         $_POST['ref'] = $cart->reference;
251         $_POST['payment'] = $cart->payment;
252         $_POST['dimension_id'] = $cart->dimension_id;
253         $_POST['dimension2_id'] = $cart->dimension2_id;
254 }
255
256 //-----------------------------------------------------------------------------
257
258 function check_data()
259 {
260         global $Refs;
261
262         if (!isset($_POST['InvoiceDate']) || !is_date($_POST['InvoiceDate'])) {
263                 display_error(_("The entered invoice date is invalid."));
264                 set_focus('InvoiceDate');
265                 return false;
266         }
267
268         if (!is_date_in_fiscalyear($_POST['InvoiceDate'])) {
269                 display_error(_("The entered date is out of fiscal year or is closed for further data entry."));
270                 set_focus('InvoiceDate');
271                 return false;
272         }
273
274         if (!isset($_POST['due_date']) || !is_date($_POST['due_date'])) {
275                 display_error(_("The entered invoice due date is invalid."));
276                 set_focus('due_date');
277                 return false;
278         }
279
280         if ($_SESSION['Items']->trans_no == 0) {
281                 if (!$Refs->is_valid($_POST['ref'])) {
282                         display_error(_("You must enter a reference."));
283                         set_focus('ref');
284                         return false;
285                 }
286
287                 if (!is_new_reference($_POST['ref'], 10)) {
288                         display_error(_("The entered reference is already in use."));
289                         set_focus('ref');
290                         return false;
291                 }
292         }
293
294         if ($_POST['ChargeFreightCost'] == "") {
295                 $_POST['ChargeFreightCost'] = price_format(0);
296         }
297
298         if (!check_num('ChargeFreightCost', 0)) {
299                 display_error(_("The entered shipping value is not numeric."));
300                 set_focus('ChargeFreightCost');
301                 return false;
302         }
303
304         if ($_SESSION['Items']->has_items_dispatch() == 0 && input_num('ChargeFreightCost') == 0) {
305                 display_error(_("There are no item quantities on this invoice."));
306                 return false;
307         }
308
309         if (!check_quantities()) {
310                 display_error(_("Selected quantity cannot be less than quantity credited nor more than quantity not invoiced yet."));
311                 return false;
312         }
313
314         return true;
315 }
316
317 //-----------------------------------------------------------------------------
318 if (isset($_POST['process_invoice']) && check_data()) {
319
320         $newinvoice=  $_SESSION['Items']->trans_no == 0;
321         copy_to_cart();
322         if ($newinvoice) new_doc_date($_SESSION['Items']->document_date);
323
324         $invoice_no = $_SESSION['Items']->write();
325         processing_end();
326
327         if ($newinvoice) {
328                 meta_forward($_SERVER['PHP_SELF'], "AddedID=$invoice_no");
329         } else {
330                 meta_forward($_SERVER['PHP_SELF'], "UpdatedID=$invoice_no");
331         }
332 }
333
334 if(list_updated('payment')) {
335         $order = &$_SESSION['Items'];
336         $order->payment = get_post('payment');
337         $order->payment_terms = get_payment_terms($order->payment);
338         $order->due_date = get_invoice_duedate($order->payment, $order->document_date);
339         if ($order->payment_terms['cash_sale']) {
340                 $_POST['Location'] = $order->Location = $order->pos['pos_location'];
341                 $order->location_name = $order->pos['location_name'];
342         }
343 }
344 // find delivery spans for batch invoice display
345 $dspans = array();
346 $lastdn = ''; $spanlen=1;
347
348 for ($line_no = 0; $line_no < count($_SESSION['Items']->line_items); $line_no++) {
349         $line = $_SESSION['Items']->line_items[$line_no];
350         if ($line->quantity == $line->qty_done) {
351                 continue;
352         }
353         if ($line->src_no == $lastdn) {
354                 $spanlen++;
355         } else {
356                 if ($lastdn != '') {
357                         $dspans[] = $spanlen;
358                         $spanlen = 1;
359                 }
360         }
361         $lastdn = $line->src_no;
362 }
363 $dspans[] = $spanlen;
364
365 //-----------------------------------------------------------------------------
366
367 $is_batch_invoice = count($_SESSION['Items']->src_docs) > 1;
368
369 $is_edition = $_SESSION['Items']->trans_type == ST_SALESINVOICE && $_SESSION['Items']->trans_no != 0;
370 start_form();
371 hidden('cart_id');
372
373 start_table(TABLESTYLE2, "width=80%", 5);
374
375 start_row();
376 $colspan = 1;
377 $dim = get_company_pref('use_dimension');
378 if ($dim > 0) 
379         $colspan = 3;
380 label_cells(_("Customer"), $_SESSION['Items']->customer_name, "class='tableheader2'");
381 label_cells(_("Branch"), get_branch_name($_SESSION['Items']->Branch), "class='tableheader2'");
382 if ($_SESSION['Items']->pos['credit_sale'] || $_SESSION['Items']->pos['cash_sale']) {
383         $paymcat = !$_SESSION['Items']->pos['cash_sale'] ? PM_CREDIT :
384                 (!$_SESSION['Items']->pos['credit_sale'] ? PM_CASH : PM_ANY);
385         label_cells(_("Payment terms:"), sale_payment_list('payment', $paymcat),
386                 "class='tableheader2'", "colspan=$colspan");
387 } else
388         label_cells(_('Payment:'), $_SESSION['Items']->payment_terms['terms'], "class='tableheader2'", "colspan=$colspan");
389
390 end_row();
391 start_row();
392
393 if ($_SESSION['Items']->trans_no == 0) {
394         ref_cells(_("Reference"), 'ref', '', null, "class='tableheader2'");
395 } else {
396         label_cells(_("Reference"), $_SESSION['Items']->reference, "class='tableheader2'");
397 }
398
399 //label_cells(_("Delivery Notes:"),
400 //get_customer_trans_view_str(ST_CUSTDELIVERY, array_keys($_SESSION['Items']->src_docs)), "class='tableheader2'");
401
402 label_cells(_("Sales Type"), $_SESSION['Items']->sales_type_name, "class='tableheader2'");
403
404 label_cells(_("Currency"), $_SESSION['Items']->customer_currency, "class='tableheader2'");
405 // 2010-09-03 Joe Hunt
406 //if ($dim > 0) 
407 //      label_cells(_("Dimension"), get_dimension_string($_SESSION['Items']->dimension_id), "class='tableheader2'");
408 if ($dim > 0) {
409         label_cell(_("Dimension").":", "class='tableheader2'");
410         $_POST['dimension_id'] = $_SESSION['Items']->dimension_id;
411         dimensions_list_cells(null, 'dimension_id', null, true, ' ', false, 1, false);
412 }               
413 else
414         hidden('dimension_id', 0);
415
416 end_row();
417 start_row();
418
419 if (!isset($_POST['ship_via'])) {
420         $_POST['ship_via'] = $_SESSION['Items']->ship_via;
421 }
422 label_cell(_("Shipping Company"), "class='tableheader2'");
423 shippers_list_cells(null, 'ship_via', $_POST['ship_via']);
424
425 if (!isset($_POST['InvoiceDate']) || !is_date($_POST['InvoiceDate'])) {
426         $_POST['InvoiceDate'] = new_doc_date();
427         if (!is_date_in_fiscalyear($_POST['InvoiceDate'])) {
428                 $_POST['InvoiceDate'] = end_fiscalyear();
429         }
430 }
431
432 date_cells(_("Date"), 'InvoiceDate', '', $_SESSION['Items']->trans_no == 0, 
433         0, 0, 0, "class='tableheader2'", true);
434
435 if (!isset($_POST['due_date']) || !is_date($_POST['due_date'])) {
436         $_POST['due_date'] = get_invoice_duedate($_SESSION['Items']->payment, $_POST['InvoiceDate']);
437 }
438
439 date_cells(_("Due Date"), 'due_date', '', null, 0, 0, 0, "class='tableheader2'");
440 /*
441 if ($dim > 1) 
442         label_cells(_("Dimension"). " 2", get_dimension_string($_SESSION['Items']->dimension2_id), "class='tableheader2'");
443 else if ($dim > 0)
444         label_cell("&nbsp;", "colspan=2");
445 */
446 if ($dim > 1) {
447         label_cell(_("Dimension")." 2:", "class='tableheader2'");
448         $_POST['dimension2_id'] = $_SESSION['Items']->dimension2_id;
449         dimensions_list_cells(null, 'dimension2_id', null, true, ' ', false, 2, false);
450 }               
451 else
452         hidden('dimension2_id', 0);
453 end_row();
454 end_table();
455
456 $row = get_customer_to_order($_SESSION['Items']->customer_id);
457 if ($row['dissallow_invoices'] == 1)
458 {
459         display_error(_("The selected customer account is currently on hold. Please contact the credit control personnel to discuss."));
460         end_form();
461         end_page();
462         exit();
463 }       
464
465 display_heading(_("Invoice Items"));
466
467 div_start('Items');
468 start_table(TABLESTYLE, "width=80%");
469 $th = array(_("Item Code"), _("Item Description"), _("Delivered"), _("Units"), _("Invoiced"),
470         _("This Invoice"), _("Price"), _("Tax Type"), _("Discount"), _("Total"));
471
472 if ($is_batch_invoice) {
473     $th[] = _("DN");
474     $th[] = "";
475 }
476
477 if ($is_edition) {
478     $th[4] = _("Credited");
479 }
480
481 table_header($th);
482 $k = 0;
483 $has_marked = false;
484 $show_qoh = true;
485
486 $dn_line_cnt = 0;
487
488 foreach ($_SESSION['Items']->line_items as $line=>$ln_itm) {
489         if ($ln_itm->quantity == $ln_itm->qty_done) {
490                 continue; // this line was fully invoiced
491         }
492         alt_table_row_color($k);
493         view_stock_status_cell($ln_itm->stock_id);
494
495         text_cells(null, 'Line'.$line.'Desc', $ln_itm->item_description, 30, 50);
496         $dec = get_qty_dec($ln_itm->stock_id);
497         qty_cell($ln_itm->quantity, false, $dec);
498         label_cell($ln_itm->units);
499         qty_cell($ln_itm->qty_done, false, $dec);
500
501         if ($is_batch_invoice) {
502                 // for batch invoices we can only remove whole deliveries
503                 echo '<td nowrap align=right>';
504                 hidden('Line' . $line, $ln_itm->qty_dispatched );
505                 echo number_format2($ln_itm->qty_dispatched, $dec).'</td>';
506         } else {
507                 small_qty_cells(null, 'Line'.$line, qty_format($ln_itm->qty_dispatched, $ln_itm->stock_id, $dec), null, null, $dec);
508         }
509         $display_discount_percent = percent_format($ln_itm->discount_percent*100) . " %";
510
511         $line_total = ($ln_itm->qty_dispatched * $ln_itm->price * (1 - $ln_itm->discount_percent));
512
513         amount_cell($ln_itm->price);
514         label_cell($ln_itm->tax_type_name);
515         label_cell($display_discount_percent, "nowrap align=right");
516         amount_cell($line_total);
517
518         if ($is_batch_invoice) {
519                 if ($dn_line_cnt == 0) {
520                         $dn_line_cnt = $dspans[0];
521                         $dspans = array_slice($dspans, 1);
522                         label_cell($ln_itm->src_no, "rowspan=$dn_line_cnt class=oddrow");
523                         label_cell("<a href='" . $_SERVER['PHP_SELF'] . "?RemoveDN=".
524                                 $ln_itm->src_no."'>" . _("Remove") . "</a>", "rowspan=$dn_line_cnt class=oddrow");
525                 }
526                 $dn_line_cnt--;
527         }
528         end_row();
529 }
530
531 /*Don't re-calculate freight if some of the order has already been delivered -
532 depending on the business logic required this condition may not be required.
533 It seems unfair to charge the customer twice for freight if the order
534 was not fully delivered the first time ?? */
535
536 if (!isset($_POST['ChargeFreightCost']) || $_POST['ChargeFreightCost'] == "") {
537         if ($_SESSION['Items']->any_already_delivered() == 1) {
538                 $_POST['ChargeFreightCost'] = price_format(0);
539         } else {
540                 $_POST['ChargeFreightCost'] = price_format($_SESSION['Items']->freight_cost);
541         }
542
543         if (!check_num('ChargeFreightCost')) {
544                 $_POST['ChargeFreightCost'] = price_format(0);
545         }
546 }
547
548 $accumulate_shipping = get_company_pref('accumulate_shipping');
549 if ($is_batch_invoice && $accumulate_shipping)
550         set_delivery_shipping_sum(array_keys($_SESSION['Items']->src_docs));
551
552 $colspan = 9;
553 start_row();
554 label_cell(_("Shipping Cost"), "colspan=$colspan align=right");
555 small_amount_cells(null, 'ChargeFreightCost', null);
556 if ($is_batch_invoice) {
557 label_cell('', 'colspan=2');
558 }
559
560 end_row();
561 $inv_items_total = $_SESSION['Items']->get_items_total_dispatch();
562
563 $display_sub_total = price_format($inv_items_total + input_num('ChargeFreightCost'));
564
565 label_row(_("Sub-total"), $display_sub_total, "colspan=$colspan align=right","align=right", $is_batch_invoice ? 2 : 0);
566
567 $taxes = $_SESSION['Items']->get_taxes(input_num('ChargeFreightCost'));
568 $tax_total = display_edit_tax_items($taxes, $colspan, $_SESSION['Items']->tax_included, $is_batch_invoice ? 2:0);
569
570 $display_total = price_format(($inv_items_total + input_num('ChargeFreightCost') + $tax_total));
571
572 label_row(_("Invoice Total"), $display_total, "colspan=$colspan align=right","align=right", $is_batch_invoice ? 2 : 0);
573
574 end_table(1);
575 div_end();
576
577 start_table(TABLESTYLE2);
578 textarea_row(_("Memo"), 'Comments', null, 50, 4);
579
580 end_table(1);
581
582 submit_center_first('Update', _("Update"),
583   _('Refresh document page'), true);
584 submit_center_last('process_invoice', _("Process Invoice"),
585   _('Check entered data and save document'), 'default');
586
587 end_form();
588
589 end_page();
590
591 ?>