2 //---------------------------------------------------------------------------
4 // Entry/Modify Sales Invoice against single delivery
5 // Entry/Modify Batch Sales Invoice against batch of deliveries
9 include_once($path_to_root . "/sales/includes/cart_class.inc");
10 include_once($path_to_root . "/includes/session.inc");
11 include_once($path_to_root . "/includes/data_checks.inc");
12 include_once($path_to_root . "/includes/manufacturing.inc");
13 include_once($path_to_root . "/sales/includes/sales_db.inc");
14 include_once($path_to_root . "/sales/includes/sales_ui.inc");
15 include_once($path_to_root . "/reporting/includes/reporting.inc");
16 include_once($path_to_root . "/taxes/tax_calc.inc");
19 if ($use_popup_windows) {
20 $js .= get_js_open_window(900, 500);
22 if ($use_date_picker) {
23 $js .= get_js_date_picker();
26 if (isset($_GET['ModifyInvoice'])) {
27 $_SESSION['page_title'] = sprintf(_("Modifying Sales Invoice # %d.") ,$_GET['ModifyInvoice']);
28 $help_page_title = _("Modifying Sales Invoice");
29 } elseif (isset($_GET['DeliveryNumber'])) {
30 $_SESSION['page_title'] = _("Issue an Invoice for Delivery Note");
31 } elseif (isset($_GET['BatchInvoice'])) {
32 $_SESSION['page_title'] = _("Issue Batch Invoice for Delivery Notes");
35 page($_SESSION['page_title'], false, false, "", $js);
37 //-----------------------------------------------------------------------------
39 if (isset($_GET['AddedID'])) {
41 $invoice_no = $_GET['AddedID'];
43 print_hidden_script(10);
45 display_notification(_("Selected deliveries has been processed"), true);
47 display_note(get_customer_trans_view_str($trans_type, $invoice_no, _("View This Invoice")), 0, 1);
49 display_note(print_document_link($invoice_no, _("Print This Invoice"), true, 10));
51 display_note(get_gl_view_str($trans_type, $invoice_no, _("View the GL Journal Entries for this Invoice")),1);
53 hyperlink_params("$path_to_root/sales/inquiry/sales_deliveries_view.php", _("Select Another Delivery For Invoicing"), "OutstandingOnly=1");
55 display_footer_exit();
57 } elseif (isset($_GET['UpdatedID'])) {
59 $invoice_no = $_GET['UpdatedID'];
60 print_hidden_script(10);
62 display_notification_centered(sprintf(_('Sales Invoice # %d has been updated.'),$invoice_no));
64 display_note(get_trans_view_str(10, $invoice_no, _("View This Invoice")));
66 display_note(print_document_link($invoice_no, _("Print This Invoice"), true, 10));
68 hyperlink_no_params($path_to_root . "/sales/inquiry/customer_inquiry.php", _("Select A Different Invoice to Modify"));
70 display_footer_exit();
72 } elseif (isset($_GET['RemoveDN'])) {
74 for($line_no = 0; $line_no < count($_SESSION['Items']->line_items); $line_no++) {
75 $line = &$_SESSION['Items']->line_items[$line_no];
76 if ($line->src_no == $_GET['RemoveDN']) {
77 $line->quantity = $line->qty_done;
78 $line->qty_dispatched=0;
84 //-----------------------------------------------------------------------------
86 if ( (isset($_GET['DeliveryNumber']) && ($_GET['DeliveryNumber'] > 0) )
87 || isset($_GET['BatchInvoice'])) {
91 if (isset($_GET['BatchInvoice'])) {
92 $src = $_SESSION['DeliveryBatch'];
93 unset($_SESSION['DeliveryBatch']);
95 $src = array($_GET['DeliveryNumber']);
97 /*read in all the selected deliveries into the Items cart */
98 $dn = new Cart(13, $src, true);
100 if ($dn->count_items() == 0) {
101 hyperlink_params($path_to_root . "/sales/inquiry/sales_deliveries_view.php",
102 _("Select a different delivery to invoice"), "OutstandingOnly=1");
103 die ("<br><b>" . _("There are no delivered items with a quantity left to invoice. There is nothing left to invoice.") . "</b>");
106 $dn->trans_type = 10;
107 $dn->src_docs = $dn->trans_no;
109 $dn->reference = references::get_next(10);
110 $dn->due_date = get_invoice_duedate($dn->customer_id, $dn->document_date);
112 $_SESSION['Items'] = $dn;
115 } elseif (isset($_GET['ModifyInvoice']) && $_GET['ModifyInvoice'] > 0) {
117 if ( get_parent_trans(10, $_GET['ModifyInvoice']) == 0) { // 1.xx compatibility hack
118 echo"<center><br><b>" . _("There in no delivery notes for this invoice.<br>
119 Most likely this invoice was created in Front Accounting version prior to 2.0
120 and therefore can not be modified.") . "</b></center>";
121 display_footer_exit();
124 $_SESSION['Items'] = new Cart(10, $_GET['ModifyInvoice']);
126 if ($_SESSION['Items']->count_items() == 0) {
127 echo"<center><br><b>" . _("All quantities on this invoice has been credited. There is nothing to modify on this invoice") . "</b></center>";
128 display_footer_exit();
131 } elseif (!processing_active()) {
132 /* This page can only be called with a delivery for invoicing or invoice no for edit */
133 display_error(_("This page can only be opened after delivery selection. Please select delivery to invoicing first."));
135 hyperlink_no_params("$path_to_root/sales/inquiry/sales_deliveries_view.php", _("Select Delivery to Invoice"));
139 } elseif (!check_quantities()) {
140 display_error(_("Selected quantity cannot be less than quantity credited nor more than quantity not invoiced yet."));
142 if (isset($_POST['Update'])) {
143 $Ajax->activate('Items');
145 //-----------------------------------------------------------------------------
146 function check_quantities()
149 foreach ($_SESSION['Items']->line_items as $line_no=>$itm) {
150 if (isset($_POST['Line'.$line_no])) {
151 if($_SESSION['Items']->trans_no) {
152 $min = $itm->qty_done;
153 $max = $itm->quantity;
156 $max = $itm->quantity - $itm->qty_done;
158 if (check_num('Line'.$line_no, $min, $max)) {
159 $_SESSION['Items']->line_items[$line_no]->qty_dispatched =
160 input_num('Line'.$line_no);
168 if (isset($_POST['Line'.$line_no.'Desc'])) {
169 $line_desc = $_POST['Line'.$line_no.'Desc'];
170 if (strlen($line_desc) > 0) {
171 $_SESSION['Items']->line_items[$line_no]->item_description = $line_desc;
178 function copy_to_cart()
180 $cart = &$_SESSION['Items'];
181 $cart->ship_via = $_POST['ship_via'];
182 $cart->freight_cost = input_num('ChargeFreightCost');
183 $cart->document_date = $_POST['InvoiceDate'];
184 $cart->due_date = $_POST['due_date'];
185 $cart->Comments = $_POST['Comments'];
187 //-----------------------------------------------------------------------------
189 function copy_from_cart()
191 $cart = &$_SESSION['Items'];
192 $_POST['ship_via'] = $cart->ship_via;
193 $_POST['ChargeFreightCost'] = price_format($cart->freight_cost);
194 $_POST['InvoiceDate']= $cart->document_date;
195 $_POST['due_date'] = $cart->due_date;
196 $_POST['Comments']= $cart->Comments;
199 //-----------------------------------------------------------------------------
201 function check_data()
203 if (!isset($_POST['InvoiceDate']) || !is_date($_POST['InvoiceDate'])) {
204 display_error(_("The entered invoice date is invalid."));
205 set_focus('InvoiceDate');
209 if (!is_date_in_fiscalyear($_POST['InvoiceDate'])) {
210 display_error(_("The entered invoice date is not in fiscal year."));
211 set_focus('InvoiceDate');
215 if (!isset($_POST['due_date']) || !is_date($_POST['due_date'])) {
216 display_error(_("The entered invoice due date is invalid."));
217 set_focus('due_date');
221 if ($_SESSION['Items']->trans_no == 0) {
222 if (!references::is_valid($_POST['ref'])) {
223 display_error(_("You must enter a reference."));
228 if (!is_new_reference($_POST['ref'], 10)) {
229 display_error(_("The entered reference is already in use."));
235 if ($_POST['ChargeFreightCost'] == "") {
236 $_POST['ChargeFreightCost'] = price_format(0);
239 if (!check_num('ChargeFreightCost', 0)) {
240 display_error(_("The entered shipping value is not numeric."));
241 set_focus('ChargeFreightCost');
245 if ($_SESSION['Items']->has_items_dispatch() == 0 && input_num('ChargeFreightCost') == 0) {
246 display_error(_("There are no item quantities on this invoice."));
250 if (!check_quantities()) {
251 display_error(_("Selected quantity cannot be less than quantity credited nor more than quantity not invoiced yet."));
258 //-----------------------------------------------------------------------------
259 if (isset($_POST['process_invoice']) && check_data()) {
261 $newinvoice= $_SESSION['Items']->trans_no == 0;
263 $invoice_no = $_SESSION['Items']->write();
267 meta_forward($_SERVER['PHP_SELF'], "AddedID=$invoice_no");
269 meta_forward($_SERVER['PHP_SELF'], "UpdatedID=$invoice_no");
273 // find delivery spans for batch invoice display
275 $lastdn = ''; $spanlen=1;
277 for ($line_no = 0; $line_no < count($_SESSION['Items']->line_items); $line_no++) {
278 $line = $_SESSION['Items']->line_items[$line_no];
279 if ($line->quantity == $line->qty_done) {
282 if ($line->src_no == $lastdn) {
286 $dspans[] = $spanlen;
290 $lastdn = $line->src_no;
292 $dspans[] = $spanlen;
294 //-----------------------------------------------------------------------------
296 $is_batch_invoice = count($_SESSION['Items']->src_docs) > 1;
297 $is_edition = $_SESSION['Items']->trans_type == 10 && $_SESSION['Items']->trans_no != 0;
298 start_form(false, true);
300 start_table("$table_style2 width=80%", 5);
303 label_cells(_("Customer"), $_SESSION['Items']->customer_name, "class='tableheader2'");
304 label_cells(_("Branch"), get_branch_name($_SESSION['Items']->Branch), "class='tableheader2'");
305 label_cells(_("Currency"), $_SESSION['Items']->customer_currency, "class='tableheader2'");
309 if ($_SESSION['Items']->trans_no == 0) {
310 ref_cells(_("Reference"), 'ref', '', $_SESSION['Items']->reference, "class='tableheader2'");
312 label_cells(_("Reference"), $_SESSION['Items']->reference, "class='tableheader2'");
315 label_cells(_("Delivery Notes:"),
316 get_customer_trans_view_str(systypes::cust_dispatch(), array_keys($_SESSION['Items']->src_docs)), "class='tableheader2'");
318 label_cells(_("Sales Type"), $_SESSION['Items']->sales_type_name, "class='tableheader2'");
323 if (!isset($_POST['ship_via'])) {
324 $_POST['ship_via'] = $_SESSION['Items']->ship_via;
326 label_cell(_("Shipping Company"), "class='tableheader2'");
327 shippers_list_cells(null, 'ship_via', $_POST['ship_via']);
329 if (!isset($_POST['InvoiceDate']) || !is_date($_POST['InvoiceDate'])) {
330 $_POST['InvoiceDate'] = Today();
331 if (!is_date_in_fiscalyear($_POST['InvoiceDate'])) {
332 $_POST['InvoiceDate'] = end_fiscalyear();
336 date_cells(_("Date"), 'InvoiceDate', '', $_POST['InvoiceDate'], 0, 0, 0, "class='tableheader2'");
338 if (!isset($_POST['due_date']) || !is_date($_POST['due_date'])) {
339 $_POST['due_date'] = get_invoice_duedate($_SESSION['Items']->customer_id, $_POST['InvoiceDate']);
342 date_cells(_("Due Date"), 'due_date', '', $_POST['due_date'], 0, 0, 0, "class='tableheader2'");
347 display_heading(_("Invoice Items"));
350 start_table("$table_style width=80%");
351 $th = array(_("Item Code"), _("Item Description"), _("Delivered"), _("Units"), _("Invoiced"),
352 _("This Invoice"), _("Price"), _("Tax Type"), _("Discount"), _("Total"));
354 if ($is_batch_invoice) {
360 $th[4] = _("Credited");
370 foreach ($_SESSION['Items']->line_items as $line=>$ln_itm) {
371 if ($ln_itm->quantity == $ln_itm->qty_done) {
372 continue; // this line was fully invoiced
374 alt_table_row_color($k);
375 view_stock_status_cell($ln_itm->stock_id);
377 text_cells(null, 'Line'.$line.'Desc', $ln_itm->item_description, 30, 50);
378 $dec = get_qty_dec($ln_itm->stock_id);
379 qty_cell($ln_itm->quantity, false, $dec);
380 label_cell($ln_itm->units);
381 qty_cell($ln_itm->qty_done, false, $dec);
383 if ($is_batch_invoice) {
384 // for batch invoices we can only remove whole deliveries
385 echo '<td nowrap align=right>';
386 hidden('Line' . $line, $ln_itm->qty_dispatched );
387 echo number_format2($ln_itm->qty_dispatched, $dec).'</td>';
389 small_qty_cells(null, 'Line'.$line, qty_format($ln_itm->qty_dispatched, $ln_itm->stock_id, $dec), null, null, $dec);
391 $display_discount_percent = percent_format($ln_itm->discount_percent*100) . " %";
393 $line_total = ($ln_itm->qty_dispatched * $ln_itm->price * (1 - $ln_itm->discount_percent));
395 amount_cell($ln_itm->price);
396 label_cell($ln_itm->tax_type_name);
397 label_cell($display_discount_percent, "nowrap align=right");
398 amount_cell($line_total);
400 if ($is_batch_invoice) {
401 if ($dn_line_cnt == 0) {
402 $dn_line_cnt = $dspans[0];
403 $dspans = array_slice($dspans, 1);
404 label_cell($ln_itm->src_no, "rowspan=$dn_line_cnt class=oddrow");
405 label_cell("<a href='" . $_SERVER['PHP_SELF'] . "?RemoveDN=".
406 $ln_itm->src_no."'>" . _("Remove") . "</a>", "rowspan=$dn_line_cnt class=oddrow");
413 /*Don't re-calculate freight if some of the order has already been delivered -
414 depending on the business logic required this condition may not be required.
415 It seems unfair to charge the customer twice for freight if the order
416 was not fully delivered the first time ?? */
418 if (!isset($_POST['ChargeFreightCost']) || $_POST['ChargeFreightCost'] == "") {
419 if ($_SESSION['Items']->any_already_delivered() == 1) {
420 $_POST['ChargeFreightCost'] = price_format(0);
422 $_POST['ChargeFreightCost'] = price_format($_SESSION['Items']->freight_cost);
425 if (!check_num('ChargeFreightCost')) {
426 $_POST['ChargeFreightCost'] = price_format(0);
432 small_amount_cells(_("Shipping Cost"), 'ChargeFreightCost', null, "colspan=9 align=right");
433 if ($is_batch_invoice) {
434 label_cell('', 'colspan=2');
438 $inv_items_total = $_SESSION['Items']->get_items_total_dispatch();
440 $display_sub_total = price_format($inv_items_total + input_num('ChargeFreightCost'));
442 label_row(_("Sub-total"), $display_sub_total, "colspan=9 align=right","align=right", $is_batch_invoice ? 2 : 0);
444 $taxes = $_SESSION['Items']->get_taxes(input_num('ChargeFreightCost'));
445 $tax_total = display_edit_tax_items($taxes, 9, $_SESSION['Items']->tax_included, $is_batch_invoice ? 2:0);
447 $display_total = price_format(($inv_items_total + input_num('ChargeFreightCost') + $tax_total));
449 label_row(_("Invoice Total"), $display_total, "colspan=9 align=right","align=right", $is_batch_invoice ? 2 : 0);
454 start_table($table_style2);
455 textarea_row(_("Memo"), 'Comments', null, 50, 4);
459 submit_center_first('Update', _("Update"),
460 _('Refresh document page'), true);
461 submit_center_last('process_invoice', _("Process Invoice"),
462 _('Check entered data and save document'), true);