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 . '&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 . '&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