1<?php
2/* Picking List Maintenance */
3
4/* Session started in session.php for password checking and authorisation level check */
5include('includes/DefineCartClass.php');
6include('includes/DefineSerialItems.php');
7
8include('includes/session.php');
9$Title = _('Picking List Maintenance');
10$ViewTopic = '';
11$BookMark = 'PickingLists';
12
13$ARSecurity = 3;
14
15include('includes/header.php');
16include('includes/SQL_CommonFunctions.inc');
17
18if (empty($_GET['identifier'])) {
19	/*unique session identifier to ensure that there is no conflict with other order entry sessions on the same machine  */
20	$identifier = date('U');
21} else {
22	$identifier = $_GET['identifier'];
23}
24
25if (!isset($_GET['Prid']) and !isset($_SESSION['ProcessingPick'])) {
26	/* This page can only be called with a pick list # */
27	echo '<div class="centre">
28			<a href="' . $RootPath . '/SelectPickingLists.php">' . _('Select a Pick List') . '</a>
29		</div>
30		<br />
31		<br />';
32	prnMsg(_('This page can only be opened if a pick list has been selected Please select a pick list first'), 'error');
33	include('includes/footer.php');
34	exit;
35} elseif (isset($_GET['Prid']) and $_GET['Prid'] > 0) {
36
37	unset($_SESSION['Items' . $identifier]->LineItems);
38	unset($_SESSION['Items' . $identifier]);
39
40	$_SESSION['ProcessingPick'] = (int) $_GET['Prid'];
41	$_GET['Prid'] = (int) $_GET['Prid'];
42	$_SESSION['Items' . $identifier] = new cart;
43
44	/*read in all the guff from the selected order into the Items cart  */
45
46	$OrderHeaderSQL = "SELECT pickreq.prid,
47								pickreq.consignment,
48								pickreq.packages,
49								pickreq.status,
50								pickreq.comments,
51								salesorders.orderno,
52								salesorders.debtorno,
53								debtorsmaster.name,
54								salesorders.branchcode,
55								salesorders.customerref,
56								salesorders.internalcomment,
57								salesorders.orddate,
58								salesorders.ordertype,
59								salesorders.shipvia,
60								salesorders.deliverto,
61								salesorders.deladd1,
62								salesorders.deladd2,
63								salesorders.deladd3,
64								salesorders.deladd4,
65								salesorders.deladd5,
66								salesorders.deladd6,
67								salesorders.contactphone,
68								salesorders.contactemail,
69								salesorders.salesperson,
70								salesorders.freightcost,
71								salesorders.deliverydate,
72								debtorsmaster.currcode,
73								salesorders.fromstkloc,
74								locations.taxprovinceid,
75								custbranch.taxgroupid,
76								currencies.rate as currency_rate,
77								currencies.decimalplaces,
78								custbranch.defaultshipvia,
79								custbranch.specialinstructions
80						FROM pickreq INNER JOIN salesorders
81							ON salesorders.orderno=pickreq.orderno INNER JOIN debtorsmaster
82							ON salesorders.debtorno = debtorsmaster.debtorno
83						INNER JOIN custbranch
84							ON salesorders.branchcode = custbranch.branchcode
85							AND salesorders.debtorno = custbranch.debtorno
86						INNER JOIN currencies
87							ON debtorsmaster.currcode = currencies.currabrev
88						INNER JOIN locations
89							ON locations.loccode=salesorders.fromstkloc
90						INNER JOIN locationusers ON locationusers.loccode=salesorders.fromstkloc AND locationusers.userid='" . $_SESSION['UserID'] . "' AND locationusers.canupd=1
91						WHERE pickreq.prid = '" . $_GET['Prid'] . "'
92							AND pickreq.closed=0";
93
94	if ($_SESSION['SalesmanLogin'] != '') {
95		$OrderHeaderSQL .= " AND salesorders.salesperson='" . $_SESSION['SalesmanLogin'] . "'";
96	}
97
98	$ErrMsg = _('The pick list cannot be retrieved because');
99	$DbgMsg = _('The SQL to get the order header was');
100	$GetOrdHdrResult = DB_query($OrderHeaderSQL, $ErrMsg, $DbgMsg);
101
102	if (DB_num_rows($GetOrdHdrResult) == 1) {
103
104		$MyRow = DB_fetch_array($GetOrdHdrResult);
105
106		$_SESSION['ProcessingPick'] = $MyRow['prid'];
107		$_SESSION['Items' . $identifier]->Status = $MyRow['status'];
108		$_SESSION['Items' . $identifier]->DebtorNo = $MyRow['debtorno'];
109		$_SESSION['Items' . $identifier]->OrderNo = $MyRow['orderno'];
110		$_SESSION['Items' . $identifier]->Branch = $MyRow['branchcode'];
111		$_SESSION['Items' . $identifier]->CustomerName = $MyRow['name'];
112		$_SESSION['Items' . $identifier]->CustRef = $MyRow['customerref'];
113		$_SESSION['Items' . $identifier]->Comments = reverse_escape($MyRow['comments']);
114		$_SESSION['Items' . $identifier]->InternalComments = reverse_escape($MyRow['internalcomment']);
115		$_SESSION['Items' . $identifier]->DefaultSalesType = $MyRow['ordertype'];
116		$_SESSION['Items' . $identifier]->DefaultCurrency = $MyRow['currcode'];
117		$_SESSION['Items' . $identifier]->CurrDecimalPlaces = $MyRow['decimalplaces'];
118		$BestShipper = $MyRow['shipvia'];
119		$_SESSION['Items' . $identifier]->ShipVia = $MyRow['shipvia'];
120		$_SESSION['Items' . $identifier]->Consignment = $MyRow['consignment'];
121		$_SESSION['Items' . $identifier]->Packages = $MyRow['packages'];
122
123		if (is_null($BestShipper)) {
124			$BestShipper = 0;
125		}
126		$_SESSION['Items' . $identifier]->DeliverTo = $MyRow['deliverto'];
127		$_SESSION['Items' . $identifier]->DeliveryDate = ConvertSQLDate($MyRow['deliverydate']);
128		$_SESSION['Items' . $identifier]->BrAdd1 = $MyRow['deladd1'];
129		$_SESSION['Items' . $identifier]->BrAdd2 = $MyRow['deladd2'];
130		$_SESSION['Items' . $identifier]->BrAdd3 = $MyRow['deladd3'];
131		$_SESSION['Items' . $identifier]->BrAdd4 = $MyRow['deladd4'];
132		$_SESSION['Items' . $identifier]->BrAdd5 = $MyRow['deladd5'];
133		$_SESSION['Items' . $identifier]->BrAdd6 = $MyRow['deladd6'];
134		$_SESSION['Items' . $identifier]->PhoneNo = $MyRow['contactphone'];
135		$_SESSION['Items' . $identifier]->Email = $MyRow['contactemail'];
136		$_SESSION['Items' . $identifier]->SalesPerson = $MyRow['salesperson'];
137
138		$_SESSION['Items' . $identifier]->Location = $MyRow['fromstkloc'];
139		$_SESSION['Items' . $identifier]->FreightCost = $MyRow['freightcost'];
140		$_SESSION['Old_FreightCost'] = $MyRow['freightcost'];
141		//		$_POST['ChargeFreightCost'] = $_SESSION['Old_FreightCost'];
142		$_SESSION['Items' . $identifier]->Orig_OrderDate = $MyRow['orddate'];
143		$_SESSION['CurrencyRate'] = $MyRow['currency_rate'];
144		$_SESSION['Items' . $identifier]->TaxGroup = $MyRow['taxgroupid'];
145		$_SESSION['Items' . $identifier]->DispatchTaxProvince = $MyRow['taxprovinceid'];
146		$_SESSION['Items' . $identifier]->GetFreightTaxes();
147		$_SESSION['Items' . $identifier]->SpecialInstructions = $MyRow['specialinstructions'];
148
149		DB_free_result($GetOrdHdrResult);
150
151		/*now populate the line items array with the sales order details records */
152
153		$LineItemsSQL = "SELECT pickreqdetails.detailno,
154								pickreqdetails.qtypicked,
155								pickreqdetails.shipqty,
156								pickreqdetails.detailno,
157								stkcode,
158								stockmaster.description,
159								stockmaster.longdescription,
160								stockmaster.controlled,
161								stockmaster.serialised,
162								stockmaster.volume,
163								stockmaster.grossweight,
164								stockmaster.units,
165								stockmaster.decimalplaces,
166								stockmaster.mbflag,
167								stockmaster.taxcatid,
168								stockmaster.discountcategory,
169								salesorderdetails.unitprice,
170								salesorderdetails.quantity,
171								salesorderdetails.discountpercent,
172								salesorderdetails.actualdispatchdate,
173								salesorderdetails.qtyinvoiced,
174								salesorderdetails.narrative,
175								salesorderdetails.orderlineno,
176								salesorderdetails.poline,
177								salesorderdetails.itemdue,
178								stockmaster.materialcost + stockmaster.labourcost + stockmaster.overheadcost AS standardcost
179							FROM pickreqdetails
180							INNER JOIN pickreq
181								ON pickreq.prid=pickreqdetails.prid
182							INNER JOIN salesorderdetails
183								ON salesorderdetails.orderno = pickreq.orderno
184								AND salesorderdetails.orderlineno=pickreqdetails.orderlineno
185							INNER JOIN stockmaster
186							 	ON salesorderdetails.stkcode = stockmaster.stockid
187							WHERE pickreqdetails.prid ='" . $_GET['Prid'] . "'
188								AND salesorderdetails.quantity - salesorderdetails.qtyinvoiced >0
189							ORDER BY salesorderdetails.orderlineno";
190
191		$ErrMsg = _('The line items of the pick list cannot be retrieved because');
192		$DbgMsg = _('The SQL that failed was');
193		$LineItemsResult = DB_query($LineItemsSQL, $ErrMsg, $DbgMsg);
194
195		if (DB_num_rows($LineItemsResult) > 0) {
196
197			while ($MyRow = DB_fetch_array($LineItemsResult)) {
198
199				$_SESSION['Items' . $identifier]->add_to_cart($MyRow['stkcode'], $MyRow['quantity'], $MyRow['description'], $MyRow['longdescription'], $MyRow['unitprice'], $MyRow['discountpercent'], $MyRow['units'], $MyRow['volume'], $MyRow['grossweight'], 0, $MyRow['mbflag'], $MyRow['actualdispatchdate'], $MyRow['qtyinvoiced'], $MyRow['discountcategory'], $MyRow['controlled'], $MyRow['serialised'], $MyRow['decimalplaces'], htmlspecialchars_decode($MyRow['narrative']), 'No', $MyRow['orderlineno'], $MyRow['taxcatid'], '', $MyRow['itemdue'], $MyRow['poline'], $MyRow['standardcost']);
200				/*NB NO Updates to DB */
201
202				$SerialItemsSQL = "SELECT pickserialdetails.stockid,
203										serialno,
204										moveqty
205									FROM pickserialdetails
206									INNER JOIN pickreqdetails
207										ON pickreqdetails.detailno=pickserialdetails.detailno
208									WHERE pickreqdetails.prid ='" . $_GET['Prid'] . "'
209										AND pickserialdetails.detailno='" . $MyRow['detailno'] . "'";
210
211				$ErrMsg = _('The serial items of the pick list cannot be retrieved because');
212				$DbgMsg = _('The SQL that failed was');
213				$SerialItemsResult = DB_query($SerialItemsSQL, $ErrMsg, $DbgMsg);
214				if (DB_num_rows($SerialItemsResult) > 0) {
215					$InOutModifier = 1;
216					while ($myserial = DB_fetch_array($SerialItemsResult)) {
217						$_SESSION['Items' . $identifier]->LineItems[$MyRow['orderlineno']]->SerialItems[$myserial['serialno']] = new SerialItem($myserial['serialno'], ($InOutModifier > 0 ? 1 : 1) * filter_number_format($myserial['moveqty']));
218					}
219				} else {
220					$_SESSION['Items' . $identifier]->LineItems[$MyRow['orderlineno']]->QtyDispatched = $MyRow['qtypicked'];
221				}
222			}
223			/* line items from sales order details */
224
225		} else {
226			/* there are no line items that have a quantity to deliver */
227			echo '<div class="centre">
228					<a href="' . $RootPath . '/SelectPickingLists.php">' . _('Select a Pick List') . '</a>
229				</div>';
230			prnMsg(_('There are no ordered items with a quantity left to deliver. There is nothing left to invoice'));
231			include('includes/footer.php');
232			exit;
233
234		} //end of checks on returned data set
235		DB_free_result($LineItemsResult);
236
237	} else {
238		/*end if the order was returned sucessfully */
239
240		echo '<div class="centre">
241				<a href="' . $RootPath . '/SelectPickingLists.php">' . _('Select a Pick List') . '</a>
242			</div>';
243		prnMsg(_('This pick list item could not be retrieved. Please select another pick list'), 'warn');
244		include('includes/footer.php');
245		exit;
246	} //valid order returned from the entered pick number
247}
248else {
249	/* if processing, a dispatch page has been called and ${$StkItm->LineNumber} would have been set from the post
250	set all the necessary session variables changed by the POST  */
251	if (isset($_POST['ShipVia'])) {
252		$_SESSION['Items' . $identifier]->ShipVia = $_POST['ShipVia'];
253	}
254
255	if (isset($_POST['InternalComments'])) {
256		$_SESSION['Items' . $identifier]->InternalComments = $_POST['InternalComments'];
257	}
258
259	if (isset($_POST['Comments'])) {
260		$_SESSION['Items' . $identifier]->Comments = $_POST['Comments'];
261	}
262
263	foreach ($_SESSION['Items' . $identifier]->LineItems as $Itm) {
264
265		if (sizeOf($Itm->SerialItems) > 0) {
266			$_SESSION['Items' . $identifier]->LineItems[$Itm->LineNumber]->QtyDispatched = 0; //initialise QtyDispatched
267			foreach ($Itm->SerialItems as $SerialItem) { //calculate QtyDispatched from bundle quantities
268				$_SESSION['Items' . $identifier]->LineItems[$Itm->LineNumber]->QtyDispatched += $SerialItem->BundleQty;
269			}
270		} else if (isset($_POST[$Itm->LineNumber . '_QtyDispatched'])) {
271			if (is_numeric(filter_number_format($_POST[$Itm->LineNumber . '_QtyDispatched'])) and filter_number_format($_POST[$Itm->LineNumber . '_QtyDispatched']) <= ($_SESSION['Items' . $identifier]->LineItems[$Itm->LineNumber]->Quantity - $_SESSION['Items' . $identifier]->LineItems[$Itm->LineNumber]->QtyInv)) {
272
273				$_SESSION['Items' . $identifier]->LineItems[$Itm->LineNumber]->QtyDispatched = round(filter_number_format($_POST[$Itm->LineNumber . '_QtyDispatched']), $Itm->DecimalPlaces);
274			}
275		}
276	} //end foreach lineitem
277
278}
279
280if ($_SESSION['Items' . $identifier]->SpecialInstructions) {
281	prnMsg($_SESSION['Items' . $identifier]->SpecialInstructions, 'warn');
282}
283
284echo '<p class="page_title_text"><img src="' . $RootPath . '/css/' . $_SESSION['Theme'] . '/images/inventory.png" title="' . _('Pick List Maintenance') . '" alt="" />' . ' ' . _('Pick List: ') . str_pad($_SESSION['ProcessingPick'], 10, '0', STR_PAD_LEFT) . _(' for Order No: ') . $_SESSION['Items' . $identifier]->OrderNo . '</p>';
285
286echo '<div class="toplink">
287		<a href="' . $RootPath . '/SelectPickingLists.php">' . _('Back to Pick Lists') . '</a>
288	</div>';
289
290echo '<table class="selection">
291			<tr>
292				<th><img src="' . $RootPath . '/css/' . $_SESSION['Theme'] . '/images/customer.png" title="' . _('Customer') . '" alt="" />' . ' ' . _('Customer Code') . ' :<b> ' . $_SESSION['Items' . $identifier]->DebtorNo . '</b></th>
293				<th>' . _('Customer Name') . ' :<b> ' . $_SESSION['Items' . $identifier]->CustomerName . '</b></th>
294			</tr>
295		</table>';
296
297echo '<form action="' . htmlspecialchars($_SERVER['PHP_SELF'], ENT_QUOTES, 'UTF-8') . '?identifier=' . urlencode($identifier) . '" method="post">';
298echo '<input type="hidden" name="FormID" value="' . $_SESSION['FormID'] . '" />';
299
300/***************************************************************
301Line Item Display
302***************************************************************/
303echo '<table width="90%" cellpadding="2" class="selection">
304	<tr>
305		<th>' . _('Item Code') . '</th>
306		<th>' . _('Item Description') . '</th>
307		<th>' . _('Ordered') . '</th>
308		<th>' . _('Units') . '</th>
309		<th>' . _('Already') . '<br />' . _('Sent') . '</th>
310		<th>' . _('Qty Picked') . '</th>
311	</tr>';
312
313/*show the line items on the order with the quantity being dispatched available for modification */
314
315$j = 0;
316foreach ($_SESSION['Items' . $identifier]->LineItems as $LnItm) {
317	++$j;
318
319	if (sizeOf($LnItm->SerialItems) > 0) {
320		$_SESSION['Items' . $identifier]->LineItems[$LnItm->LineNumber]->QtyDispatched = 0; //initialise QtyDispatched
321		foreach ($LnItm->SerialItems as $SerialItem) { //calculate QtyDispatched from bundle quantities
322			$_SESSION['Items' . $identifier]->LineItems[$LnItm->LineNumber]->QtyDispatched += $SerialItem->BundleQty;
323		}
324	} else if (isset($_POST[$LnItm->LineNumber . '_QtyDispatched'])) {
325		if (is_numeric(filter_number_format($_POST[$LnItm->LineNumber . '_QtyDispatched'])) and filter_number_format($_POST[$LnItm->LineNumber . '_QtyDispatched']) <= ($_SESSION['Items' . $identifier]->LineItems[$LnItm->LineNumber]->Quantity - $_SESSION['Items' . $identifier]->LineItems[$LnItm->LineNumber]->QtyInv)) {
326
327			$_SESSION['Items' . $identifier]->LineItems[$LnItm->LineNumber]->QtyDispatched = round(filter_number_format($_POST[$LnItm->LineNumber . '_QtyDispatched']), $LnItm->DecimalPlaces);
328		}
329	}
330
331	echo '<tr class="striped_row">
332		<td>' . $LnItm->StockID . '</td>
333		<td title="' . $LnItm->LongDescription . '">' . $LnItm->ItemDescription . '</td>
334		<td class="number">' . locale_number_format($LnItm->Quantity, $LnItm->DecimalPlaces) . '</td>
335		<td>' . $LnItm->Units . '</td>
336		<td class="number">' . locale_number_format($LnItm->QtyInv, $LnItm->DecimalPlaces) . '</td>';
337
338	if ($LnItm->Controlled == 1) {
339		if (isset($_POST['ProcessPickList'])) {
340			echo '<td class="number">' . locale_number_format($LnItm->QtyDispatched, $LnItm->DecimalPlaces) . '</td>';
341		} else {
342			echo '<td class="number"><input type="hidden" name="' . $LnItm->LineNumber . '_QtyDispatched"  value="' . $LnItm->QtyDispatched . '" /><a href="' . $RootPath . '/PickingListsControlled.php?identifier=' . $identifier . '&amp;LineNo=' . $LnItm->LineNumber . '">' . locale_number_format($LnItm->QtyDispatched, $LnItm->DecimalPlaces) . '</a></td>';
343		}
344	} else {
345		if (isset($_POST['ProcessPickList'])) {
346			echo '<td class="number">' . locale_number_format($LnItm->QtyDispatched, $LnItm->DecimalPlaces) . '</td>';
347		} else {
348			echo '<td class="number"><input tabindex="' . $j . '" type="text" ' . ($j == 1 ? 'autofocus="autofocus" ' : '') . ' class="number" required="required" title="' . _('Enter the quantity to charge the customer for, that has been dispatched') . '" name="' . $LnItm->LineNumber . '_QtyDispatched" maxlength="12" size="12" value="' . locale_number_format($LnItm->QtyDispatched, $LnItm->DecimalPlaces) . '" /></td>';
349		}
350	}
351
352	echo '<td class="number">' . locale_number_format($_SESSION['Items' . $identifier]->LineItems[$LnItm->LineNumber]->QtyShipped, $LnItm->DecimalPlaces) . '</td>';
353
354	if ($LnItm->Controlled == 1) {
355		if (!isset($_POST['ProcessPickList'])) {
356			echo '<td><a href="' . $RootPath . '/PickingListsControlled.php?identifier=' . $identifier . '&amp;LineNo=' . $LnItm->LineNumber . '">';
357			if ($LnItm->Serialised == 1) {
358				echo _('Enter Serial Numbers');
359			} else {
360				/*Just batch/roll/lot control */
361				echo _('Enter Batch/Roll/Lot #');
362			}
363			echo '</a></td>';
364		}
365	}
366	echo '</tr>';
367
368	if (mb_strlen($LnItm->Narrative) > 1) {
369		$Narrative = str_replace('\r\n', '<br />', $LnItm->Narrative);
370		echo '<tr class="striped_row">
371				<td colspan="6">' . stripslashes($Narrative) . '</td>
372			</tr>';
373	}
374} //end foreach ($line)
375
376if (!isset($_POST['DispatchDate']) or !is_date($_POST['DispatchDate'])) {
377	$DefaultDispatchDate = Date($_SESSION['DefaultDateFormat'], CalcEarliestDispatchDate());
378} else {
379	$DefaultDispatchDate = $_POST['DispatchDate'];
380}
381
382echo '</table>';
383
384if (isset($_POST['ProcessPickList']) and $_POST['ProcessPickList'] != '') {
385
386	if ($_SESSION['ProhibitNegativeStock'] == 1) { // checks for negative stock after processing invoice
387		//sadly this check does not combine quantities occuring twice on and order and each line is considered individually :-(
388		$NegativesFound = false;
389		foreach ($_SESSION['Items' . $identifier]->LineItems as $OrderLine) {
390			$SQL = "SELECT stockmaster.description,
391					   		locstock.quantity,
392					   		stockmaster.mbflag
393		 			FROM locstock
394		 			INNER JOIN stockmaster
395						ON stockmaster.stockid=locstock.stockid
396					WHERE stockmaster.stockid='" . $OrderLine->StockID . "'
397						AND locstock.loccode='" . $_SESSION['Items' . $identifier]->Location . "'";
398
399			$ErrMsg = _('Could not retrieve the quantity left at the location once this order is invoiced (for the purposes of checking that stock will not go negative because)');
400			$Result = DB_query($SQL, $ErrMsg);
401			$CheckNegRow = DB_fetch_array($Result);
402			if (($CheckNegRow['mbflag'] == 'B' or $CheckNegRow['mbflag'] == 'M') and mb_substr($OrderLine->StockID, 0, 4) != 'ASSET') {
403				if ($CheckNegRow['quantity'] < $OrderLine->QtyDispatched) {
404					prnMsg(_('Invoicing the selected order would result in negative stock. The system parameters are set to prohibit negative stocks from occurring. This invoice cannot be created until the stock on hand is corrected.'), 'error', $OrderLine->StockID . ' ' . $CheckNegRow['description'] . ' - ' . _('Negative Stock Prohibited'));
405					$NegativesFound = true;
406				}
407			} elseif ($CheckNegRow['mbflag'] == 'A') {
408
409				/*Now look for assembly components that would go negative */
410				$SQL = "SELECT bom.component,
411							   stockmaster.description,
412							   locstock.quantity-(" . $OrderLine->QtyDispatched . "*bom.quantity) AS qtyleft
413						FROM bom
414						INNER JOIN locstock
415							ON bom.component=locstock.stockid
416						INNER JOIN stockmaster
417							ON stockmaster.stockid=bom.component
418						WHERE bom.parent='" . $OrderLine->StockID . "'
419							AND locstock.loccode='" . $_SESSION['Items' . $identifier]->Location . "'
420							AND effectiveafter <'" . Date('Y-m-d') . "'
421							AND effectiveto >='" . Date('Y-m-d') . "'";
422
423				$ErrMsg = _('Could not retrieve the component quantity left at the location once the assembly item on this order is invoiced (for the purposes of checking that stock will not go negative because)');
424				$Result = DB_query($SQL, $ErrMsg);
425				while ($NegRow = DB_fetch_array($Result)) {
426					if ($NegRow['qtyleft'] < 0) {
427						prnMsg(_('Invoicing the selected order would result in negative stock for a component of an assembly item on the order. The system parameters are set to prohibit negative stocks from occurring. This invoice cannot be created until the stock on hand is corrected.'), 'error', $NegRow['component'] . ' ' . $NegRow['description'] . ' - ' . _('Negative Stock Prohibited'));
428						$NegativesFound = true;
429					} // end if negative would result
430				} //loop around the components of an assembly item
431			} //end if its an assembly item - check component stock
432
433		} //end of loop around items on the order for negative check
434
435		if ($NegativesFound) {
436			echo '</form>';
437			echo '<div class="centre">
438					<input type="submit" name="Update" value="' . _('Update') . '" />
439				</div>';
440			include('includes/footer.php');
441			exit;
442		}
443	} //end of testing for negative stocks
444
445	/* Now Get the area where the sale is to from the branches table */
446
447	$SQL = "SELECT area,
448					defaultshipvia
449			FROM custbranch
450			WHERE custbranch.debtorno ='" . $_SESSION['Items' . $identifier]->DebtorNo . "'
451			AND custbranch.branchcode = '" . $_SESSION['Items' . $identifier]->Branch . "'";
452
453	$ErrMsg = _('We were unable to load Area where the Sale is to from the BRANCHES table') . '. ' . _('Please remedy this');
454	$Result = DB_query($SQL, $ErrMsg);
455	$MyRow = DB_fetch_row($Result);
456	$Area = $MyRow[0];
457	$DefaultShipVia = $MyRow[1];
458	DB_free_result($Result);
459
460	/*company record read in on login with info on GL Links and debtors GL account*/
461
462	if ($_SESSION['CompanyRecord'] == 0) {
463		/*The company data and preferences could not be retrieved for some reason */
464		prnMsg(_('The company information and preferences could not be retrieved') . ' - ' . _('see your system administrator'), 'error');
465		include('includes/footer.php');
466		exit;
467	}
468
469	/*Now need to check that the order details are the same as they were when they were read into the Items array. If they've changed then someone else may have invoiced them */
470
471	$SQL = "SELECT stkcode,
472					quantity,
473					qtyinvoiced,
474					pickreqdetails.orderlineno
475				FROM pickreqdetails
476				INNER JOIN pickreq
477					ON pickreq.prid=pickreqdetails.prid
478				INNER JOIN salesorderdetails
479					ON salesorderdetails.orderno=pickreq.orderno
480					AND salesorderdetails.orderlineno=pickreqdetails.orderlineno
481					AND salesorderdetails.completed=0 AND salesorderdetails.quantity-salesorderdetails.qtyinvoiced > 0
482				WHERE pickreqdetails.prid = '" . $_SESSION['ProcessingPick'] . "'";
483
484	$Result = DB_query($SQL);
485
486	if (DB_num_rows($Result) != count($_SESSION['Items' . $identifier]->LineItems)) {
487		/*there should be the same number of items returned from this query as there are lines on the invoice - if  not 	then someone has already invoiced or credited some lines */
488
489		if ($debug == 1) {
490			echo '<br />' . $SQL;
491			echo '<br />' . _('Number of rows returned by SQL') . ':' . DB_num_rows($Result);
492			echo '<br />' . _('Count of items in the session') . ' ' . count($_SESSION['Items' . $identifier]->LineItems);
493		}
494
495		echo '<br />';
496		prnMsg(_('This order has been changed or invoiced since this delivery was started to be confirmed') . '. ' . _('Processing halted') . '. ' . _('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'), 'error');
497
498		unset($_SESSION['Items' . $identifier]->LineItems);
499		unset($_SESSION['Items' . $identifier]);
500		unset($_SESSION['ProcessingPick']);
501		include('includes/footer.php');
502		exit;
503	}
504
505	while ($MyRow = DB_fetch_array($Result)) {
506		$TotalQtyInv += $_SESSION['Items' . $identifier]->LineItems[$MyRow['orderlineno']]->QtyDispatched; //need total qty later to distribute freight equally
507		if ($_SESSION['Items' . $identifier]->LineItems[$MyRow['orderlineno']]->Quantity != $MyRow['quantity'] or $_SESSION['Items' . $identifier]->LineItems[$MyRow['orderlineno']]->QtyInv != $MyRow['qtyinvoiced']) {
508
509			echo '<br />' . _('Orig order for') . ' ' . $MyRow['orderlineno'] . ' ' . _('has a quantity of') . ' ' . $MyRow['quantity'] . ' ' . _('and an invoiced qty of') . ' ' . $MyRow['qtyinvoiced'] . ' ' . _('the session shows quantity of') . ' ' . $_SESSION['Items' . $identifier]->LineItems[$MyRow['orderlineno']]->Quantity . ' ' . _('and quantity invoice of') . ' ' . $_SESSION['Items' . $identifier]->LineItems[$MyRow['orderlineno']]->QtyInv;
510
511			prnMsg(_('This order has been changed or invoiced since this delivery was started to be confirmed') . ' ' . _('Processing halted.') . ' ' . _('To enter and confirm this dispatch, it must be re-selected and re-read again to update the changes made by the other user'), 'error');
512
513			echo '<div class="centre"><a href="' . $RootPath . '/SelectPickiingLists.php">' . _('Select a pick list to maintain') . '</a></div>';
514
515			unset($_SESSION['Items' . $identifier]->LineItems);
516			unset($_SESSION['Items' . $identifier]);
517			unset($_SESSION['ProcessingPick']);
518			include('includes/footer.php');
519			exit;
520		}
521	}
522	/*loop through all line items of the order to ensure none have been invoiced since started looking at this order*/
523
524	DB_free_result($Result);
525
526	// *************************************************************************
527	//   S T A R T   O F   S Q L   P R O C E S S I N G
528	// *************************************************************************
529
530	/*Start an SQL transaction */
531
532	DB_Txn_Begin();
533
534	$DefaultDispatchDate = FormatDateForSQL($DefaultDispatchDate);
535
536/*remove existing pickserialdetails records*/
537	$SQL = "DELETE pickserialdetails
538				FROM pickserialdetails
539				INNER JOIN pickreqdetails
540					ON pickreqdetails.detailno=pickserialdetails.detailno
541				WHERE prid='" . $_SESSION['ProcessingPick'] . "'";
542	$ErrMsg = _('CRITICAL ERROR') . ' ' . _('NOTE DOWN THIS ERROR AND SEEK ASSISTANCE') . ': ' . _('The pickserialdetails could not be deleted');
543	$DbgMsg = _('The following SQL to delete them was used');
544	$Result = DB_query($SQL, $ErrMsg, $DbgMsg, true);
545
546	/*Update order header for invoice charged on */
547	$ExtraUpdSQL = '';
548	if ($_POST['Status'] == 'Shipped') {
549		$ExtraUpdSQL = ",shippedby='" . $_SESSION['UserID'] . "',
550					shipdate='" . $DefaultDispatchDate . "'";
551		$ExtraLineSQL = ",shipqty=qtypicked";
552	} else {
553		$ExtraUpdSQL = ",shippedby='',
554					shipdate='0000-00-00'";
555		$ExtraLineSQL = ",shipqty=0";
556	}
557
558	if ($_POST['Status'] == 'Cancelled') {
559		$ExtraUpdSQL .= ",closed='1'";
560	}
561
562	$SQL = "UPDATE salesorders, pickreq
563			SET internalcomment = '" . $_POST['InternalComments'] . "',
564				pickreq.comments= '" . $_POST['Comments'] . "',
565				status = '" . $_POST['Status'] . "',
566				consignment = '" . $_POST['Consignment'] . "',
567				packages = '" . $_POST['Packages'] . "'
568				" . $ExtraUpdSQL . "
569			WHERE prid= '" . $_SESSION['ProcessingPick'] . "'
570			AND salesorders.orderno=pickreq.orderno";
571
572	$ErrMsg = _('CRITICAL ERROR') . ' ' . _('NOTE DOWN THIS ERROR AND SEEK ASSISTANCE') . ': ' . _('The sales order header could not be updated with the internal comments');
573	$DbgMsg = _('The following SQL to update the order was used');
574	$Result = DB_query($SQL, $ErrMsg, $DbgMsg, true);
575
576	foreach ($_SESSION['Items' . $identifier]->LineItems as $OrderLine) {
577		$LineItemsSQL = "SELECT pickreqdetails.detailno
578						FROM pickreqdetails INNER JOIN pickreq ON pickreq.prid=pickreqdetails.prid
579						INNER JOIN salesorderdetails
580							ON salesorderdetails.orderno = pickreq.orderno
581							AND salesorderdetails.orderlineno=pickreqdetails.orderlineno
582						WHERE pickreqdetails.prid ='" . $_SESSION['ProcessingPick'] . "'
583						AND salesorderdetails.orderlineno='" . $OrderLine->LineNumber . "'";
584
585		$ErrMsg = _('The line items of the pick list cannot be retrieved because');
586		$DbgMsg = _('The SQL that failed was');
587		$LineItemsResult = DB_query($LineItemsSQL, $ErrMsg, $DbgMsg);
588		$MyLine = DB_fetch_array($LineItemsResult);
589		$DetailNo = $MyLine['detailno'];
590		$SQL = "UPDATE pickreqdetails
591				SET qtypicked='" . $OrderLine->QtyDispatched . "'
592				" . $ExtraLineSQL . "
593				WHERE detailno='" . $DetailNo . "'";
594
595		$ErrMsg = _('CRITICAL ERROR') . '! ' . _('NOTE DOWN THIS ERROR AND SEEK ASSISTANCE') . ': ' . _('The pickreqdetail record could not be inserted because');
596		$DbgMsg = _('The following SQL to insert the pickreqdetail records was used');
597		$Result = DB_query($SQL, $ErrMsg, $DbgMsg, true);
598
599		if ($OrderLine->Controlled == 1) {
600			foreach($OrderLine->SerialItems as $Item) {
601				/* now insert the serial records */
602				$SQL = "INSERT INTO pickserialdetails (detailno,
603													stockid,
604													serialno,
605													moveqty)
606								VALUES ('" . $DetailNo . "',
607										'" . $OrderLine->StockID . "',
608										'" . $Item->BundleRef . "',
609										'" . $Item->BundleQty . "')";
610
611				$ErrMsg = _('CRITICAL ERROR') . '! ' . _('NOTE DOWN THIS ERROR AND SEEK ASSISTANCE') . ': ' . _('The serial stock movement record could not be inserted because');
612				$DbgMsg = _('The following SQL to insert the serial stock movement records was used');
613				$Result = DB_query($SQL, $ErrMsg, $DbgMsg, true);
614			}/* foreach controlled item in the serialitems array */
615		} /*end if the orderline is a controlled item */
616
617	}
618	/*end of OrderLine loop */
619
620	DB_Txn_Commit();
621	// *************************************************************************
622	//   E N D   O F  S Q L   P R O C E S S I N G
623	// *************************************************************************
624	echo prnMsg(_('PickList ') . ' ' . $_SESSION['ProcessingPick'] . ' ' . _('processed'), 'success');
625
626	if ($_SESSION['PackNoteFormat'] == 1) {
627		/*Laser printed A4 default */
628		$PrintDispatchNote = $RootPath . '/PrintCustOrder_generic.php?TransNo=' . $_SESSION['Items' . $identifier]->OrderNo;
629	} else {
630		/*pre-printed stationery default */
631		$PrintDispatchNote = $RootPath . '/PrintCustOrder.php?TransNo=' . $_SESSION['Items' . $identifier]->OrderNo;
632	}
633
634	$PrintLabels = $RootPath . '/PDFShipLabel.php?Type=Sales&ORD=' . $_SESSION['Items' . $identifier]->OrderNo;
635	unset($_SESSION['Items' . $identifier]->LineItems);
636	unset($_SESSION['Items' . $identifier]);
637	unset($_SESSION['ProcessingPick']);
638
639	echo '<br /><div class="centre">';
640
641	echo '<a target="_blank" href="' . $PrintDispatchNote . '">' . _('Print Packing Slip') . '<img src="' . $RootPath . '/css/' . $_SESSION['Theme'] . '/images/pdf.png" title="' . _('Click for PDF') . '" alt="" /></a><br />
642		<a target="_blank" href="' . $PrintLabels . '">' . _('Print Customer Labels') . '</a><br /><br />';
643
644	echo '<a href="' . $RootPath . '/SelectPickingLists.php">' . _('Select another pick list for processing') . '</a><br /><br />';
645	/*end of process invoice */
646}
647else {
648	/*Process Invoice not set so allow input of invoice data */
649
650	if (!isset($_POST['Consignment'])) {
651		$_POST['Consignment'] = $_SESSION['Items' . $identifier]->Consignment;
652	}
653	if (!isset($_POST['Packages'])) {
654		$_POST['Packages'] = $_SESSION['Items' . $identifier]->Packages;
655	}
656	if (!isset($_POST['InvoiceText'])) {
657		$_POST['InvoiceText'] = '';
658	}
659	if (!isset($_POST['Status'])) {
660		$_POST['Status'] = $_SESSION['Items' . $identifier]->Status;
661	}
662
663	++$j;
664
665	echo '<table class="selection"
666		<tr>
667			<td>' . _('Pick List Status') . ':</td>
668			<td><select name="Status">';
669
670	if (($_SESSION['Items' . $identifier]->Status != 'Shipped') or (in_array($ARSecurity, $_SESSION['AllowedPageSecurityTokens']))) {
671		//only allow A/R to change status on an already shipped Pick, we expect to invoice, we need A/R intervention to prevent ship, cancel, no invoice, lost money
672		if ($_POST['Status'] == 'Picked') {
673			echo '<option selected="selected" value="Picked">' . _('Picked') . '</option>';
674		} else {
675			echo '<option value="Picked">' . _('Picked') . '</option>';
676		}
677	}
678
679	if ($_POST['Status'] == 'Shipped') {
680		echo '<option selected="selected" value="Shipped">' . _('Shipped') . '</option>';
681	} else {
682		echo '<option value="Shipped">' . _('Shipped') . '</option>';
683	}
684
685	if (($_SESSION['Items' . $identifier]->Status != 'Shipped') or (in_array($ARSecurity, $_SESSION['AllowedPageSecurityTokens']))) {
686		//only allow A/R to cancel an already shipped Pick, we expect to invoice, we need A/R intervention to prevent ship, cancel, no invoice, lost money
687		if ($_POST['Status'] == 'Cancelled') {
688			echo '<option selected="selected" value="Cancelled">' . _('Cancelled') . '</option>';
689		} else {
690			echo '<option value="Cancelled">' . _('Cancelled') . '</option>';
691		}
692	}
693
694	echo '</select></td></tr>';
695	echo '<tr>
696			<td>' . _('Consignment Note Ref') . ':</td>
697			<td><input tabindex="' . $j . '" type="text" data-type="no-illegal-chars" title="' . _('Enter the consignment note reference to enable tracking of the delivery in the event of customer proof of delivery issues') . '" maxlength="15" size="15" name="Consignment" value="' . $_POST['Consignment'] . '" /></td>
698		</tr>';
699	++$j;
700
701	echo '<tr>
702			<td>' . _('No Of Packages in Delivery') . ':</td>
703			<td><input tabindex="' . $j . '" type="number" maxlength="6" size="6" class="integer" name="Packages" value="' . $_POST['Packages'] . '" /></td>
704		</tr>';
705
706	++$j;
707	echo '<tr>
708			<td>' . _('Pick List Comments') . ':</td>
709			<td><textarea tabindex="' . $j . '" name="Comments" pattern=".{0,20}" cols="31" rows="5">' . reverse_escape($_SESSION['Items' . $identifier]->Comments) . '</textarea></td>
710		</tr>';
711
712	++$j;
713	echo '<tr>
714			<td>' . _('Order Internal Comments') . ':</td>
715			<td><textarea tabindex="' . $j . '" name="InternalComments" pattern=".{0,20}" cols="31" rows="5">' . reverse_escape($_SESSION['Items' . $identifier]->InternalComments) . '</textarea></td>
716		</tr>';
717
718	++$j;
719	echo '</table>';
720
721	if (($_SESSION['Items' . $identifier]->Status != 'Shipped') or (in_array($ARSecurity, $_SESSION['AllowedPageSecurityTokens']))) {
722		//only allow A/R to change status on an already shipped Pick, we expect to invoice, we need A/R intervention to prevent ship, cancel, no invoice, lost money
723		echo '<div class="centre">
724				<input type="submit" tabindex="' . $j . '" name="Update" value="' . _('Update') . '" />
725				<br />';
726		++$j;
727		echo '<br />
728				<input type="submit" tabindex="' . $j . '" name="ProcessPickList" value="' . _('Process Pick List') . '" />
729			</div>
730			<input type="hidden" name="ShipVia" value="' . $_SESSION['Items' . $identifier]->ShipVia . '" />';
731	}
732}
733echo '</form>';
734
735include('includes/footer.php');
736?>
737