5 include_once($path_to_root . "/sales/includes/cart_class.inc");
6 include_once($path_to_root . "/includes/session.inc");
8 include_once($path_to_root . "/includes/data_checks.inc");
10 include_once($path_to_root . "/includes/manufacturing.inc");
11 include_once($path_to_root . "/sales/includes/sales_db.inc");
12 include_once($path_to_root . "/sales/includes/sales_ui.inc");
14 include_once($path_to_root . "/taxes/tax_calc.inc");
17 if ($use_popup_windows)
18 $js .= get_js_open_window(900, 500);
20 $js .= get_js_date_picker();
21 page(_("Issue an Invoice for Delivery Note(s)"), false, false, "", $js);
23 //---------------------------------------------------------------------------------------------------------------
25 if (isset($_GET['AddedID']))
27 $invoice_no = $_GET['AddedID'];
30 display_notification(_("Selected deliveries has been processed"), true);
32 display_note(get_customer_trans_view_str($trans_type, $invoice_no, _("View this invoice")), 0, 1);
34 display_note(get_gl_view_str($trans_type, $invoice_no, _("View the GL Journal Entries for this Invoice")));
36 hyperlink_params("$path_to_root/sales/inquiry/sales_deliveries_view.php", _("Select Another Delivery For Invoicing"), "OutstandingOnly=1");
38 display_footer_exit();
41 //---------------------------------------------------------------------------------------------------------------
43 if (!isset($_GET['DeliveryNumber']) && !isset($_SESSION['ProcessingDelivery']) &&
44 !isset($_GET['BatchInvoice']) && !isset($_GET['process_invoice']))
46 /* This page can only be called with a delivery for invoicing*/
47 display_error(_("This page can only be opened after delivery selection. Please select delivery to invoicing first."));
49 hyperlink_no_params("$path_to_root/sales/inquiry/sales_deliveries_view.php", _("Select Delivery to Invoice"));
54 elseif (isset($_GET['DeliveryNumber'])|| isset($_GET['BatchInvoice']))
58 if (isset($_SESSION['Items']))
60 unset($_SESSION['Items']->line_items);
61 unset ($_SESSION['Items']);
64 if(isset($_GET['BatchInvoice'])) {
65 $_SESSION['ProcessingDelivery'] = $_SESSION['DeliveryBatch'];
66 unset($_SESSION['DeliveryBatch']);
69 $_SESSION['ProcessingDelivery'] = array($_GET['DeliveryNumber']);
71 $_SESSION['Items'] = new cart('delivery');
72 $_SESSION['Items']->trans_no = $_SESSION['ProcessingDelivery'];
74 /*read in all the selected deliveries into the Items cart */
75 if (read_sales_delivery($_SESSION['ProcessingDelivery'], $_SESSION['Items']))
77 if ($_SESSION['Items']->count_items() == 0)
79 hyperlink_params($path_to_root . "/sales/inquiry/sales_deliveries_view.php", _("Select a different delivery to invoice"), "OutstandingOnly=1");
80 die ("<br><b>" . _("There are no delivered items with a quantity left to invoice. There is nothing left to invoice.") . "</b>");
85 hyperlink_no_params("/sales_deliveries_view.php", _("Select a delivery note to invoice"));
86 die ("<br><b>" . _("This delivery note could not be retrieved. Please select another delivery.") . "</b>");
91 foreach ($_SESSION['Items']->line_items as $line=>$itm)
93 if(isset($_POST['Line'.$line])) {
94 $line_qty = $_POST['Line'.$line];
95 if (is_numeric($line_qty) && $_POST['Line'.$line] <= ($itm->quantity - $itm->qty_done))
97 $_SESSION['Items']->line_items[$line]->qty_dispatched = $line_qty;
101 if(isset($_POST['Line'.$line.'Desc'])) {
102 $line_desc = $_POST['Line'.$line.'Desc'];
103 if (strlen($line_desc) > 0)
105 $_SESSION['Items']->line_items[$line]->item_description = $line_desc;
111 //---------------------------------------------------------------------------------------------------------------
113 function delivery_changed_error()
115 global $path_to_root;
116 display_note(_("This delivery note has been changed or invoiced since this invoice was started to be confirmed. Processing halted."), 1, 0);
117 display_note(_("To enter and confirm this invoice the order must be re-selected and re-read again to update the changes made by the other user."), 1, 0);
119 hyperlink_no_params("$path_to_root/sales/inquiry/sales_deliveries_view.php", _("Select a sales order for invoicing"));
121 unset($_SESSION['ProcessingDelivery']);
125 //---------------------------------------------------------------------------------------------------------------
127 function check_delivery_changed()
131 /*Now need to check that the delivery note details are the same
132 as they were when they were read into the Items array.
133 If they've changed then someone else may have invoiced them */
135 $sql = "SELECT id, stock_id, quantity, qty_done FROM "
136 .TB_PREF."debtor_trans_details WHERE
137 debtor_trans_type = 13 AND (";
139 foreach($_SESSION['Items']->trans_no as $key=>$num) {
140 if($key!=0) $sql .= ' OR ';
141 $sql .= 'debtor_trans_no =' . $num;
143 $sql .= ') ORDER BY id';
144 $result = db_query($sql,"while checking delivery changes");
146 if (db_num_rows($result) != count($_SESSION['Items']->line_items))
149 /*there should be the same number of items returned from this query as there are lines on the invoice -
150 if not then someone has already invoiced or credited some lines */
153 display_note($sql, 1, 0);
154 display_note("No rows returned by sql:" . db_num_rows($result), 1, 0);
155 display_note("Count of items in the session " . count($_SESSION['Items']->line_items), 1, 0);
161 while ($myrow = db_fetch($result))
163 $stk_itm = $myrow["stock_id"];
165 if ($_SESSION['Items']->line_items[$line]->quantity != -$myrow["quantity"] ||
166 $_SESSION['Items']->line_items[$line]->qty_done != -$myrow["qty_done"])
168 display_note(_("Original delivery for line #") . $line+1 . ' '.
169 _("has a quantity of") . " " . -$myrow["quantity"] . " " .
170 _("and an delivered quantity of") . " " . -$myrow["qty_done"] . "." .
171 _("Now the quantity of") . " " .
172 $_SESSION['Items']->line_items[$line]->quantity . " " .
173 _("and invoiced quantity of") . " " .
174 $_SESSION['Items']->line_items[$line]->qty_done, 1, 0);
179 } /*loop through all line items of the order to ensure none have been invoiced */
184 //---------------------------------------------------------------------------------------------------------------
186 function check_data()
188 if (!isset($_POST['InvoiceDate']) || !is_date($_POST['InvoiceDate']))
190 display_error(_("The entered invoice date is invalid."));
193 if (!is_date_in_fiscalyear($_POST['InvoiceDate']))
195 display_error(_("The entered invoice date is not in fiscal year."));
198 if (!isset($_POST['due_date']) || !is_date($_POST['due_date']))
200 display_error(_("The entered invoice due date is invalid."));
204 if (!references::is_valid($_POST['ref']))
206 display_error(_("You must enter a reference."));
210 if (!is_new_reference($_POST['ref'], 10))
212 display_error(_("The entered reference is already in use."));
215 if ($_POST['ChargeFreightCost'] == "")
216 $_POST['ChargeFreightCost'] = 0;
217 if (!is_numeric($_POST['ChargeFreightCost']) || $_POST['ChargeFreightCost'] < 0)
219 display_error(_("The entered shipping value is not numeric."));
223 if ($_SESSION['Items']->has_items_dispatch() == 0 && $_POST['ChargeFreightCost'] == 0)
225 display_error(_("There are no item quantities on this invoice."));
232 //---------------------------------------------------------------------------------------------------------------
234 function process_invoice($invoicing=false)
238 read_sales_delivery($_SESSION['Items']->trans_no, $_SESSION['Items']);
239 $duedate = get_invoice_duedate($_SESSION['Items']->customer_id, $_SESSION['Items']->delivery_date);
240 $invoice_no = add_sales_invoice($_SESSION['Items'],
241 $_SESSION['Items']->delivery_date, $duedate,
242 $_SESSION['Items']->tax_group_id, $_SESSION['Items']->freight_cost,
243 $_SESSION['Items']->Location, $_SESSION['Items']->ship_via,
244 $_SESSION['Items']->default_sales_type, references::get_next(10),
245 $_SESSION['Items']->memo_);
253 if (!check_delivery_changed())
254 delivery_changed_error();
256 $invoice_no = add_sales_invoice($_SESSION['Items'],
257 $_POST['InvoiceDate'], $_POST['due_date'],
258 $_SESSION['Items']->tax_group_id,
259 $_POST['ChargeFreightCost'],
260 $_SESSION['Items']->Location,
261 $_POST['ship_via'], $_POST['sales_type_id'], $_POST['ref'],
262 $_POST['InvoiceText']);
263 unset($_SESSION['ProcessingDelivery']);
265 meta_forward($_SERVER['PHP_SELF'], "AddedID=$invoice_no");
268 //---------------------------------------------------------------------------------------------------------------
269 if (isset($_GET['process_invoice']))
270 process_invoice(true);
271 elseif (isset($_POST['process_invoice']))
274 //-------------------------------------------------------------------------------------------------
276 start_form(false, true);
278 start_table("$table_style2 width=80%", 5);
279 //echo "<tr><td>"; // outer table
281 //start_table("$table_style width=100%");
283 label_cells(_("Customer"), $_SESSION['Items']->customer_name, "class='tableheader2'");
284 label_cells(_("Branch"), get_branch_name($_SESSION['Items']->Branch), "class='tableheader2'");
285 label_cells(_("Currency"), $_SESSION['Items']->customer_currency, "class='tableheader2'");
289 if (!isset($_POST['ref']))
290 $_POST['ref'] = references::get_next(10);
292 ref_cells(_("Reference"), 'ref', null, "class='tableheader2'");
294 label_cells(_("Delivery Notes:"), get_customer_trans_view_str(systypes::cust_dispatch(), $_SESSION['ProcessingDelivery']), "class='tableheader2'");
297 if (!isset($_POST['sales_type_id']))
298 $_POST['sales_type_id'] = $_SESSION['Items']->default_sales_type;
299 label_cell(_("Sales Type"), "class='tableheader2'");
300 sales_types_list_cells(null, 'sales_type_id', $_POST['sales_type_id']);
305 if (!isset($_POST['ship_via']))
306 $_POST['ship_via'] = $_SESSION['Items']->ship_via;
307 label_cell(_("Shipping Company"), "class='tableheader2'");
308 shippers_list_cells(null, 'ship_via', $_POST['ship_via']);
310 if (!isset($_POST['InvoiceDate']) || !is_date($_POST['InvoiceDate']))
312 $_POST['InvoiceDate'] = Today();
313 if (!is_date_in_fiscalyear($_POST['InvoiceDate']))
314 $_POST['InvoiceDate'] = end_fiscalyear();
317 date_cells(_("Date"), 'InvoiceDate', $_POST['InvoiceDate'], 0, 0, 0, "class='tableheader'");
320 //echo "</td><td>";// outer table
322 //start_table("$table_style width=90%");
324 if (!isset($_POST['due_date']) || !is_date($_POST['due_date']))
326 $_POST['due_date'] = get_invoice_duedate($_SESSION['Items']->customer_id, $_POST['InvoiceDate']);
328 date_cells(_("Due Date"), 'due_date', $_POST['due_date'], 0, 0, 0, "class='tableheader'");
333 end_table(); // outer table
335 display_heading(_("Invoice Items"));
337 start_table("$table_style width=80%");
338 $th = array(_("Item Code"), _("Item Description"), _("Delivered"), _("Units"), _("Invoiced"),
339 _("This Invoice"), _("Price"), _("Tax Type"), _("Discount"), _("Total"));
345 foreach ($_SESSION['Items']->line_items as $line=>$ln_itm)
347 if($ln_itm->quantity==$ln_itm->qty_done) continue; //this line is fully delivered
348 alt_table_row_color($k);
350 view_stock_status_cell($ln_itm->stock_id); // ?
352 text_cells(null, 'Line'.$line.'Desc', $ln_itm->item_description, 30, 50);
353 qty_cell($ln_itm->quantity);
354 label_cell($ln_itm->units);
355 qty_cell($ln_itm->qty_done);
357 if(count($_SESSION['Items']->trans_no)>1) {
358 // for batch invoices we can process only whole deliveries
359 qty_cell($ln_itm->qty_dispatched);
360 hidden('Line'.$line,$ln_itm->qty_dispatched );
362 text_cells(null, 'Line'.$line, $ln_itm->qty_dispatched, 10, 10);
364 $display_discount_percent = number_format2($ln_itm->discount_percent*100,user_percent_dec()) . "%";
366 $line_total = ($ln_itm->qty_dispatched * $ln_itm->price * (1 - $ln_itm->discount_percent));
368 amount_cell($ln_itm->price);
369 label_cell($ln_itm->tax_type_name);
370 label_cell($display_discount_percent, "nowrap align=right");
371 amount_cell($line_total);
376 /*Don't re-calculate freight if some of the order has already been delivered -
377 depending on the business logic required this condition may not be required.
378 It seems unfair to charge the customer twice for freight if the order
379 was not fully delivered the first time ?? */
381 if (!isset($_POST['ChargeFreightCost']) || $_POST['ChargeFreightCost'] == "")
383 if ($_SESSION['Items']->any_already_delivered() == 1)
385 $_POST['ChargeFreightCost'] = 0;
389 $_POST['ChargeFreightCost'] = $_SESSION['Items']->freight_cost;
391 if (!is_numeric($_POST['ChargeFreightCost']))
393 $_POST['ChargeFreightCost'] = 0;
399 small_amount_cells(_("Shipping Cost"), 'ChargeFreightCost', null, "colspan=9 align=right");
401 $inv_items_total = $_SESSION['Items']->get_items_total_dispatch();
403 $display_sub_total = number_format2($inv_items_total + $_POST['ChargeFreightCost'],user_price_dec());
405 label_row(_("Sub-total"), $display_sub_total, "colspan=9 align=right","align=right");
407 $taxes = $_SESSION['Items']->get_taxes($_SESSION['Items']->tax_group_id, $_POST['ChargeFreightCost']);
408 $tax_total = display_edit_tax_items($taxes, 9);
410 $display_total = number_format2(($inv_items_total + $_POST['ChargeFreightCost'] + $tax_total), user_price_dec());
412 label_row(_("Invoice Total"), $display_total, "colspan=9 align=right","align=right");
417 // display_note(_("Marked items have insufficient quantities in stock."), 0, 1, "class='red'");
419 start_table($table_style2);
421 textarea_row(_("Memo"), 'InvoiceText', null, 50, 4);
425 submit_center_first('Update', _("Update"));
426 submit_center_last('process_invoice', _("Process Invoice"));
430 //---------------------------------------------------------------------------------------------