public function cancel_grn() { $flash = Flash::Instance(); $errors = array(); if (!$this->CheckParams('gr_number')) { sendBack(); } $poreceivedline = DataObjectFactory::Factory('POReceivedLine'); $cc = new ConstraintChain(); $cc->add(new Constraint('gr_number', '=', $this->_data['gr_number'])); $poreceivedlines = $poreceivedline->getAll($cc); $db = DB::Instance(); $db->StartTrans(); foreach ($poreceivedlines as $poreceivedline_id => $value) { $poreceivedline = DataObjectFactory::Factory('POReceivedLine'); $poreceivedline->load($poreceivedline_id); // Update the order line to reverse the GRN $porderline = DataObjectFactory::Factory('POrderLine'); $porderline->load($poreceivedline->orderline_id); if (!is_null($porderline->stitem_id)) { $stitem = DataObjectFactory::Factory('STItem'); $stitem->load($porderline->stitem_id); $qty_decimals = $stitem->qty_decimals; } else { $qty_decimals = maxdp($porderline->os_qty, $porderline->del_qty, $poreceivedline->received); } // get the received quantity for this orderline, excluding lines in the GRN $received_qty = $poreceivedline->getReceivedQty($porderline->id, $poreceivedline->gr_number); $porderline->os_qty = BCSUB($porderline->revised_qty, $received_qty, $qty_decimals); $porderline->del_qty = $received_qty; if ($porderline->del_qty > 0) { $porderline->status = $porderline->partReceivedStatus(); } else { $porderline->status = $porderline->awaitingDeliveryStatus(); } // Load the PO Header and save the orderline // to ensure header status is updated if required $porder = DataObjectFactory::Factory('POrder'); $porder->load($porderline->order_id); if (!$porderline->save($porder)) { $errors[] = 'Error updating PO line ' . $db->ErrorMsg(); } // Finally update the po received line $poreceivedline->status = $poreceivedline->cancelStatus(); if (!$poreceivedline->save()) { $errors[] = 'Error updating GRN ' . $db->ErrorMsg(); } } if (count($errors) === 0) { // Now get the transactions for the GRN // Note each GRN line has two transactions linked by transfer_id $sttransaction = DataObjectFactory::Factory('STTransaction'); $sttransaction->identifierField = 'transfer_id'; $cc = new ConstraintChain(); $cc->add(new Constraint('process_name', '=', 'GR')); $cc->add(new Constraint('process_id', '=', $this->_data['gr_number'])); $sttransactions = $sttransaction->getAll($cc); // Need to link new transfer ids to existing transactions transfer_ids $transfer_ids = array(); $transferrule = DataObjectFactory::Factory('WHTransferrule'); foreach ($sttransactions as $sttransaction_id => $value) { if (!isset($transfer_ids[$value])) { $transfer_ids[$value] = $transferrule->getTransferId()->transfer_id; } } // Reverse each of the transaction pairs associated with the GRN lines foreach ($sttransactions as $sttransaction_id => $value) { $sttransaction = DataObjectFactory::Factory('STTransaction'); $sttransaction->load($sttransaction_id); // create new transaction by setting new id value $test = $sttransaction->autoHandle($sttransaction->idField); if ($test !== false) { $sttransaction->{$sttransaction->idField} = $test; } else { $errors[] = 'Error getting identifier for new item'; } // Reverse the quantity and save $sttransaction->transfer_id = $transfer_ids[$sttransaction->transfer_id]; $sttransaction->created = $sttransaction->autoHandle('created'); $sttransaction->createdby = EGS_USERNAME; $sttransaction->qty = $sttransaction->qty * -1; $sttransaction->save($errors); } } // Check for errors if (count($errors) > 0) { $flash->addErrors($errors); $flash->addError('Error cancelling GRN ' . $this->_data['gr_number']); $db->FailTrans(); } else { $flash->addMessage('GRN ' . $this->_data['gr_number'] . ' Cancelled'); } $db->CompleteTrans(); sendTo($this->name, 'index', $this->_modules); }
public static function getItemDetail($stitem) { // Get the current stock level for the item $in_stock = $stitem->currentBalance(); $balance = $in_stock; $orders = array(); // Get any Purchase Orders for the item, by date $porders = $stitem->getPOrderLines(); foreach ($porders as $porder) { if (isset($orders[$porder->due_delivery_date . 'PO' . $porder->order_id])) { $orders[$porder->due_delivery_date . 'PO' . $porder->order_id]['on_order'] += round($stitem->convertToUoM($porder->stuom_id, $stitem->uom_id, $porder->os_qty), $stitem->qty_decimals); } else { $orders[$porder->due_delivery_date . 'PO' . $porder->order_id] = array('due_date' => un_fix_date($porder->due_delivery_date), 'order_type' => 'PO', 'reference' => $porder->order_number, 'reference_id' => $porder->order_id, 'stitem_id' => $porder->stitem_id, 'stitem' => $porder->stitem, 'uom_name' => $porder->uom_name, 'decimals' => $stitem->qty_decimals, 'on_order' => round($stitem->convertToUoM($porder->stuom_id, $stitem->uom_id, $porder->os_qty), $stitem->qty_decimals), 'required' => 0); } } // Get any Works Orders to make this item, by date $worders = $stitem->getWorkOrders(); foreach ($worders as $worder) { $orders[$worder->required_by . 'WO' . $worder->id] = array('due_date' => un_fix_date($worder->required_by), 'order_type' => 'WO', 'reference' => $worder->wo_number, 'reference_id' => $worder->id, 'stitem_id' => $worder->stitem_id, 'stitem' => $worder->stitem, 'uom_name' => $stitem->uom_name, 'decimals' => $stitem->qty_decimals, 'on_order' => round($worder->outstandingQty(), $stitem->qty_decimals), 'required' => 0); } // Get any Sales Orders by date for the item $sorders = $stitem->getSOrderLines(); foreach ($sorders as $sorder) { if (isset($orders[$sorder->due_despatch_date . 'SO' . $sorder->order_id])) { $orders[$sorder->due_despatch_date . 'SO' . $sorder->order_id]['required'] += round($stitem->convertToUoM($sorder->stuom_id, $stitem->uom_id, $sorder->os_qty), $stitem->qty_decimals); } else { $orders[$sorder->due_despatch_date . 'SO' . $sorder->order_id] = array('due_date' => un_fix_date($sorder->due_despatch_date), 'order_type' => 'SO', 'reference' => $sorder->order_number, 'reference_id' => $sorder->order_id, 'stitem_id' => $sorder->stitem_id, 'stitem' => $sorder->stitem, 'uom_name' => $sorder->uom_name, 'decimals' => $stitem->qty_decimals, 'on_order' => 0, 'required' => round($stitem->convertToUoM($sorder->stuom_id, $stitem->uom_id, $sorder->os_qty), $stitem->qty_decimals)); } } // Get any Works Orders that use this item, by date $wostructures = $stitem->getWOStructures(); foreach ($wostructures as $wostructure) { $orders[$wostructure->required_by . 'WO' . $wostructure->work_order_id] = array('due_date' => un_fix_date($wostructure->required_by), 'order_type' => 'WO', 'reference' => $wostructure->wo_number, 'reference_id' => $wostructure->work_order_id, 'stitem_id' => $wostructure->stitem_id, 'stitem' => $wostructure->ststructure, 'stitem_code' => $wostructure->stitem_code, 'uom_name' => $wostructure->uom, 'decimals' => $stitem->qty_decimals, 'on_order' => 0, 'required' => round($stitem->convertToUoM($wostructure->uom_id, $stitem->uom_id, $wostructure->outstandingQty()), $stitem->qty_decimals)); } // Get any Purchase Orders for items that use this item, by date $porders = $stitem->getPOStructures(); foreach ($porders as $porder) { $structure = DataObjectFactory::Factory('STitem'); $structure->load($porder->ststructure_id); $mfstructure = DataObjectFactory::Factory('MFStructure'); $mfstructure->loadBy(array('stitem_id', 'ststructure_id'), array($porder->stitem_id, $porder->ststructure_id)); $required = $porder->required * 100 / (100 - $mfstructure->waste_pc); if (isset($orders[$porder->due_delivery_date . 'PO' . $porder->order_id])) { $orders[$porder->due_delivery_date . 'PO' . $porder->order_id]['required'] += round($structure->convertToUoM($porder->uom_id, $structure->uom_id, $required), $stitem->qty_decimals); } else { $orders[$porder->due_delivery_date . 'PO' . $porder->id] = array('due_date' => un_fix_date($porder->due_delivery_date), 'order_type' => 'PO', 'reference' => $porder->order_number, 'reference_id' => $porder->order_id, 'stitem_id' => $porder->stitem_id, 'stitem' => $porder->stitem, 'stitem_code' => $porder->item_code, 'uom_name' => $porder->uom_name, 'decimals' => $stitem->qty_decimals, 'on_order' => 0, 'required' => round($structure->convertToUoM($porder->uom_id, $structure->uom_id, $required), $stitem->qty_decimals)); } } ksort($orders); // Now build the manufacturing plan for the order dates foreach ($orders as $key => $row) { $required = BCADD(sprintf('%0' . $row['decimals'] . 'f', $row['required']), 0, $row['decimals']); $on_order = BCADD(sprintf('%0' . $row['decimals'] . 'f', $row['on_order']), 0, $row['decimals']); $orders[$key]['required'] = $required; $orders[$key]['on_order'] = $on_order; $balance = BCSUB(BCADD($balance, $on_order, $row['decimals']), $required, $row['decimals']); $orders[$key]['in_stock'] = $balance; if ($orders[$key]['in_stock'] < 0) { $orders[$key]['in_stock'] = sprintf('%0.' . $row['decimals'] . 'f', 0); } $orders[$key]['shortfall'] = sprintf('%0.' . $row['decimals'] . 'f', 0); if ($balance < 0) { $orders[$key]['shortfall'] = bcsub(0, $balance, $row['decimals']); } } return $orders; }