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