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();
22 if(isset($_GET['ModifyDelivery'])) {
23 $_SESSION['page_title'] = _("Modifying Delivery Note") . " #".$_GET['ModifyDelivery'];
26 $_SESSION['page_title'] = _("Deliver Items for a Sales Order");
29 page($_SESSION['page_title'], false, false, "", $js);
31 if (isset($_GET['AddedID']))
33 $dispatch_no = $_GET['AddedID'];
36 display_notification(_("Dispatch processed:") . ' '.$_GET['AddedID'], true);
38 display_note(get_customer_trans_view_str($trans_type, $dispatch_no, _("View this dispatch")), 0, 1);
40 display_note(get_gl_view_str($trans_type, $dispatch_no, _("View the GL Journal Entries for this Dispatch")));
42 hyperlink_params("$path_to_root/sales/customer_invoice.php", _("Invoice This Delivery"), "DeliveryNumber=$dispatch_no");
44 if ($_SESSION['Items']->trans_type=='invoice')
45 hyperlink_params("$path_to_root/sales/sales_order_entry.php", _("Make Another Dispatch"), "NewDispatch=Yes");
47 hyperlink_params("$path_to_root/sales/inquiry/sales_orders_view.php", _("Select Another Order For Dispatch"), "OutstandingOnly=1");
49 display_footer_exit();
52 //---------------------------------------------------------------------------------------------------------------
54 if (!isset($_GET['OrderNumber']) && !isset($_SESSION['ProcessingOrder']) &&
55 !isset($_GET['ModifyDelivery']) && !isset($_GET['process_delivery']))
57 /* This page can only be called with an order number for invoicing*/
58 display_error(_("This page can only be opened if an order or delivery note has been selected. Please select it first."));
60 hyperlink_params("$path_to_root/sales/inquiry/sales_orders_view.php", _("Select a Sales Order to Delivery"), "OutstandingOnly=1");
66 elseif (isset($_GET['OrderNumber']) && $_GET['OrderNumber'] > 0)
69 if (isset($_SESSION['Items']))
71 unset($_SESSION['Items']->line_items);
72 unset ($_SESSION['Items']);
75 $_SESSION['ProcessingOrder'] = $_GET['OrderNumber'];
76 $_SESSION['Items'] = new cart;
78 /*read in all the selected order into the Items cart */
80 if (read_sales_order($_SESSION['ProcessingOrder'], $_SESSION['Items']))
82 if ($_SESSION['Items']->count_items() == 0)
84 hyperlink_params($path_to_root . "/sales/inquiry/sales_orders_view.php", _("Select a different sales order to delivery"), "OutstandingOnly=1");
85 die ("<br><b>" . _("This order has no items. There is nothing to delivery.") . "</b>");
90 hyperlink_no_params("/sales_orders_view.php", _("Select a sales order to dispatch"));
91 die ("<br><b>" . _("This order items could not be retrieved. Please select another order.") . "</b>");
95 elseif (isset($_GET['ModifyDelivery']) && $_GET['ModifyDelivery'] > 0) {
96 if (isset($_SESSION['Items']))
98 unset($_SESSION['Items']->line_items);
99 unset ($_SESSION['Items']);
101 $_SESSION['Items'] = new cart;
103 if(read_sales_delivery($_GET['ModifyDelivery'],$_SESSION['Items'] ))
105 if ($_SESSION['Items']->count_items() == 0)
107 hyperlink_params($path_to_root . "/sales/inquiry/sales_orders_view.php", _("Select a different delivery"), "OutstandingOnly=1");
108 die ("<br><b>" . _("This delivery has all items invoiced. There is nothing to modify.") . "</b>");
113 hyperlink_no_params("/sales_orders_view.php", _("Select a sales order to dispatch"));
114 die ("<br><b>" . _("This sales delivery item could not be retrieved. Please select another delivery.") . "</b>");
117 $_SESSION['ProcessingOrder'] = $_SESSION['Items']->order_no;
120 // Update cart delivery quantities/descriptions
121 foreach ($_SESSION['Items']->line_items as $line=>$itm)
123 if(isset($_POST['Line'.$line])) {
124 $line_qty = $_POST['Line'.$line];
125 if (is_numeric($line_qty) && $_POST['Line'.$line] <= ($itm->quantity - $itm->qty_done))
127 $_SESSION['Items']->line_items[$line]->qty_dispatched = $line_qty;
131 if(isset($_POST['Line'.$line.'Desc'])) {
132 $line_desc = $_POST['Line'.$line.'Desc'];
133 if (strlen($line_desc) > 0)
135 $_SESSION['Items']->line_items[$line]->item_description = $line_desc;
141 //---------------------------------------------------------------------------------------------------------------
143 function order_changed_error()
145 global $path_to_root;
146 display_note(_("This order has been changed or invoiced since this delivery was started to be confirmed. Processing halted."), 1, 0);
147 display_note(_("To enter and confirm this dispatch the order must be re-selected and re-read again to update the changes made by the other user."), 1, 0);
149 hyperlink_no_params("$path_to_root/sales/inquiry/sales_orders_view.php", _("Select a sales order for confirming deliveries"));
151 unset($_SESSION['ProcessingOrder']);
155 //---------------------------------------------------------------------------------------------------------------
157 function check_order_changed()
161 /*Now need to check that the order details are the same as they were when
162 they were read into the Items array.
163 If they've changed then someone else may have dispatch them */
165 $sql = "SELECT id, stk_code, quantity, qty_sent FROM ".TB_PREF."sales_order_details WHERE
166 order_no = " . $_SESSION['ProcessingOrder']. " ORDER BY id";
168 $result = db_query($sql,"retreive sales order details");
170 if (db_num_rows($result) != count($_SESSION['Items']->line_items))
173 /*there should be the same number of items returned from this query as
174 count of lines on the delivery notes - if not then someone has
175 already invoiced or credited some lines */
178 display_note($sql, 1, 0);
179 display_note("No rows returned by sql:" . db_num_rows($result), 1, 0);
180 display_note("Count of items in the cart " . count($_SESSION['Items']->line_items), 1, 0);
186 while ($myrow = db_fetch($result))
188 $stk_itm = $myrow["stk_code"];
189 if ($_SESSION['Items']->line_items[$line]->quantity != $myrow["quantity"] ||
190 $_SESSION['Items']->line_items[$line]->qty_done != $myrow["qty_sent"])
192 display_note(_("Original order for") . " '" . $myrow["stk_code"] . "' " .
193 _("has a quantity of") . " " . $myrow["quantity"] . " " .
194 _("and an delivered quantity of") . " " . $myrow["qty_sent"] . " " .
195 _("the cart shows quantity of") . " " .
196 $_SESSION['Items']->line_items[$line]->quantity . " " .
197 _("and delivered quantity of") . " " .
198 $_SESSION['Items']->line_items[$line]->qty_done, 1, 0);
203 } /*loop through all line items of the order to ensure none have been invoiced */
207 //---------------------------------------------------------------------------------------------------------------
209 function check_data()
211 if (!isset($_POST['DispatchDate']) || !is_date($_POST['DispatchDate']))
213 display_error(_("The entered date of delivery is invalid."));
216 if (!is_date_in_fiscalyear($_POST['DispatchDate']))
218 display_error(_("The entered date of delivery is not in fiscal year."));
221 if (!isset($_POST['due_date']) || !is_date($_POST['due_date']))
223 display_error(_("The entered dead-line for invoice is invalid."));
227 if (!references::is_valid($_POST['ref']))
229 display_error(_("You must enter a reference."));
233 if (!is_new_reference($_POST['ref'], 13))
235 display_error(_("The entered reference is already in use."));
238 if ($_POST['ChargeFreightCost'] == "")
239 $_POST['ChargeFreightCost'] = 0;
240 if (!is_numeric($_POST['ChargeFreightCost']) || $_POST['ChargeFreightCost'] < 0)
242 display_error(_("The entered shipping value is not numeric."));
246 if ($_SESSION['Items']->has_items_dispatch() == 0 && $_POST['ChargeFreightCost'] == 0)
248 display_error(_("There are no item quantities on this delivery note."));
255 //---------------------------------------------------------------------------------------------------------------
259 if (!sys_prefs::allow_negative_stock())
261 foreach ($_SESSION['Items']->line_items as $itm)
264 if ($itm->qty_dispatched && has_stock_holding($itm->mb_flag))
266 $qoh = get_qoh_on_date($itm->stock_id, $_POST['Location'], $_POST['DispatchDate']);
268 if ($itm->qty_dispatched > $qoh)
270 display_error(_("The delivery cannot be processed because there is an insufficient quantity for item:") .
271 " " . $itm->stock_id . " - " . $itm->item_description);
281 //---------------------------------------------------------------------------------------------------------------
283 function process_delivery($get_from_order=false)
286 { // entry point for direct delivery - cart contains completed order;
287 // we should have qty_dispatched and standard cost set anyway
288 unset($_SESSION['Items']->line_items);
289 read_sales_order($_SESSION['Items']->order_no, $_SESSION['Items']);
291 $duedate = get_invoice_duedate($_SESSION['Items']->customer_id, $_SESSION['Items']->delivery_date);
292 $delivery_no = add_sales_delivery($_SESSION['Items'],
293 $_SESSION['Items']->delivery_date, $duedate, $_SESSION['Items']->order_no,
294 $_SESSION['Items']->tax_group_id, $_SESSION['Items']->freight_cost,
295 $_SESSION['Items']->Location, $_SESSION['Items']->ship_via,
296 $_SESSION['Items']->default_sales_type, references::get_next(13),
297 $_SESSION['Items']->memo_,0);
305 if (!check_order_changed())
306 order_changed_error();
311 if ($_POST['bo_policy'])
316 $delivery_no = add_sales_delivery($_SESSION['Items'],
317 $_POST['DispatchDate'], $_POST['due_date'], $_SESSION['ProcessingOrder'],
318 $_SESSION['Items']->tax_group_id,$_POST['ChargeFreightCost'], $_POST['Location'],
319 $_POST['ship_via'], $_POST['sales_type_id'], $_POST['ref'],
320 $_POST['InvoiceText'], $bo_policy);
321 unset($_SESSION['ProcessingOrder']);
323 meta_forward($_SERVER['PHP_SELF'], "AddedID=$delivery_no");
326 //---------------------------------------------------------------------------------------------------------------
327 if (isset($_GET['process_delivery']))
328 process_delivery(true);
329 elseif (isset($_POST['process_delivery']))
332 //-------------------------------------------------------------------------------------------------
334 start_form(false, true);
336 start_table("$table_style2 width=80%", 5);
337 echo "<tr><td>"; // outer table
339 start_table("$table_style width=100%");
341 label_cells(_("Customer"), $_SESSION['Items']->customer_name, "class='tableheader2'");
342 label_cells(_("Branch"), get_branch_name($_SESSION['Items']->Branch), "class='tableheader2'");
343 label_cells(_("Currency"), $_SESSION['Items']->customer_currency, "class='tableheader2'");
347 if (!isset($_POST['ref']))
348 $_POST['ref'] = references::get_next(13);
350 ref_cells(_("Reference"), 'ref', null, "class='tableheader2'");
352 label_cells(_("For Sales Order"), get_customer_trans_view_str(systypes::sales_order(), $_SESSION['ProcessingOrder']), "class='tableheader2'");
354 if (!isset($_POST['sales_type_id']))
355 $_POST['sales_type_id'] = $_SESSION['Items']->default_sales_type;
356 label_cell(_("Sales Type"), "class='tableheader2'");
357 sales_types_list_cells(null, 'sales_type_id', $_POST['sales_type_id']);
362 if (!isset($_POST['Location']))
363 $_POST['Location'] = $_SESSION['Items']->Location;
364 label_cell(_("Delivery From"), "class='tableheader2'");
365 locations_list_cells(null, 'Location', $_POST['Location'], false, true);
367 if (!isset($_POST['ship_via']))
368 $_POST['ship_via'] = $_SESSION['Items']->ship_via;
369 label_cell(_("Shipping Company"), "class='tableheader2'");
370 shippers_list_cells(null, 'ship_via', $_POST['ship_via']);
372 // set this up here cuz it's used to calc qoh
373 if (!isset($_POST['DispatchDate']) || !is_date($_POST['DispatchDate']))
375 $_POST['DispatchDate'] = Today();
376 if (!is_date_in_fiscalyear($_POST['DispatchDate']))
377 $_POST['DispatchDate'] = end_fiscalyear();
379 date_cells(_("Date"), 'DispatchDate', $_POST['DispatchDate'], 0, 0, 0, "class='tableheader'");
384 echo "</td><td>";// outer table
386 start_table("$table_style width=90%");
388 if (!isset($_POST['due_date']) || !is_date($_POST['due_date']))
390 $_POST['due_date'] = get_invoice_duedate($_SESSION['Items']->customer_id, $_POST['DispatchDate']);
392 date_row(_("Invoice Dead-line"), 'due_date', $_POST['due_date'], 0, 0, 0, "class='tableheader'");
396 end_table(1); // outer table
398 display_heading(_("Invoice Items"));
400 start_table("$table_style width=80%");
401 $th = array(_("Item Code"), _("Item Description"), _("Ordered"), _("Units"), _("Delivered"),
402 _("This Delivery"), _("Price"), _("Tax Type"), _("Discount"), _("Total"));
408 foreach ($_SESSION['Items']->line_items as $line=>$ln_itm)
410 if($ln_itm->quantity==$ln_itm->qty_done) continue; //this line is fully delivered
411 // if it's a non-stock item (eg. service) don't show qoh
412 if (sys_prefs::allow_negative_stock() || !has_stock_holding($ln_itm->mb_flag) ||
413 $ln_itm->qty_dispatched == 0)
417 $qoh = get_qoh_on_date($ln_itm->stock_id, $_POST['Location'], $_POST['DispatchDate']);
419 if ($show_qoh && ($ln_itm->qty_dispatched > $qoh))
421 // oops, we don't have enough of one of the component items
422 start_row("class='stockmankobg'");
426 alt_table_row_color($k);
428 view_stock_status_cell($ln_itm->stock_id);
430 text_cells(null, 'Line'.$line.'Desc', $ln_itm->item_description, 30, 50);
431 qty_cell($ln_itm->quantity);
432 label_cell($ln_itm->units);
433 qty_cell($ln_itm->qty_done);
435 text_cells(null, 'Line'.$line, $ln_itm->qty_dispatched, 10, 10);
437 $display_discount_percent = number_format2($ln_itm->discount_percent*100,user_percent_dec()) . "%";
439 $line_total = ($ln_itm->qty_dispatched * $ln_itm->price * (1 - $ln_itm->discount_percent));
441 amount_cell($ln_itm->price);
442 label_cell($ln_itm->tax_type_name);
443 label_cell($display_discount_percent, "nowrap align=right");
444 amount_cell($line_total);
449 $_POST['ChargeFreightCost'] = $_SESSION['Items']->freight_cost;
451 if (!is_numeric($_POST['ChargeFreightCost']))
453 $_POST['ChargeFreightCost'] = 0;
458 small_amount_cells(_("Shipping Cost"), 'ChargeFreightCost', null, "colspan=9 align=right");
460 $inv_items_total = $_SESSION['Items']->get_items_total_dispatch();
462 $display_sub_total = number_format2($inv_items_total + $_POST['ChargeFreightCost'],user_price_dec());
464 label_row(_("Sub-total"), $display_sub_total, "colspan=9 align=right","align=right");
466 $taxes = $_SESSION['Items']->get_taxes($_SESSION['Items']->tax_group_id, $_POST['ChargeFreightCost']);
467 $tax_total = display_edit_tax_items($taxes, 9);
469 $display_total = number_format2(($inv_items_total + $_POST['ChargeFreightCost'] + $tax_total), user_price_dec());
471 label_row(_("Amount Total"), $display_total, "colspan=9 align=right","align=right");
476 display_note(_("Marked items have insufficient quantities in stock."), 0, 1, "class='red'");
478 start_table($table_style2);
480 policy_list_row(_("Action For Balance"), "bo_policy", null);
482 textarea_row(_("Memo"), 'InvoiceText', null, 50, 4);
486 submit_center_first('Update', _("Update"));
487 submit_center_last('process_delivery', _("Process Dispatch"));
491 //---------------------------------------------------------------------------------------------