foreach ($objInventoryLocationArray as $objInventoryLocation) { $SourceLocationId = $objInventoryLocation->LocationId; // LocationId = 3 - 'Taken Out' $DestinationLocationId = 3; // Remove the inventory quantity from the source for moves and take outs //$objInventoryLocation->Quantity = $objInventoryLocation->Quantity - $objInventoryLocation->intTransactionQuantity; $objInventoryLocation->Quantity = $objInventoryLocation->GetVirtualAttribute('actual_quantity') - $objInventoryLocation->intTransactionQuantity; $objInventoryLocation->Save(); // Create the new InventoryTransaction object and save it $objInventoryTransaction = new InventoryTransaction(); $objInventoryTransaction->InventoryLocationId = $objInventoryLocation->InventoryLocationId; $objInventoryTransaction->TransactionId = $objTransaction->TransactionId; $objInventoryTransaction->Quantity = $objInventoryLocation->intTransactionQuantity; $objInventoryTransaction->SourceLocationId = $SourceLocationId; $objInventoryTransaction->DestinationLocationId = $DestinationLocationId; $objInventoryTransaction->Save(); } $strWarning .= "Your transaction has successfully completed<br /><a href='index.php'>Main Menu</a> | <a href='inventory_menu.php'>Inventory Menu</a><br />"; //Remove that flag when transaction is compelete or exists some errors unset($_SESSION['intUserAccountId']); $blnTransactionComplete = true; $arrCheckedInventoryCodeLocationQuantity = ""; } } if ($blnError) { $strWarning .= "This transaction has not been completed.<br />"; } if (is_array($arrCheckedInventoryCodeLocationQuantity)) { foreach ($arrCheckedInventoryCodeLocationQuantity as $strInventoryCodeLocationQuantity) { list($strInventoryModelCode, $strSourceLocation, $intQuantity) = explode('|', $strInventoryCodeLocationQuantity, 3); $strJavaScriptCode .= "AddInventoryPost('" . $strInventoryModelCode . "','" . $strSourceLocation . "','" . $intQuantity . "');";
public function btnReceiveInventoryTransaction_Click($strFormId, $strControlId, $strParameter) { $blnError = false; $this->dtgInventoryTransact->Warning = ''; $intInventoryTransactionId = $strParameter; if ($this->objInventoryTransactionArray) { try { // Get an instance of the database $objDatabase = QApplication::$Database[1]; // Begin a MySQL Transaction to be either committed or rolled back $objDatabase->TransactionBegin(); // This bool later tells us if we need to flip the ReceivedFlag for the entire Receipt $blnAllInventoryReceived = true; foreach ($this->objInventoryTransactionArray as &$objInventoryTransaction) { // If the button pressed is for this InventoryTransaction if ($objInventoryTransaction->InventoryTransactionId == $intInventoryTransactionId) { // Get the user submitted Location value selected for this row $lstLocationInventoryReceived = $this->GetControl('lstLocationInventoryReceived' . $objInventoryTransaction->InventoryTransactionId); if ($lstLocationInventoryReceived && $lstLocationInventoryReceived->SelectedValue) { // Get the user submitted Quantity value provided for this InventoryTransaction $txtQuantityReceived = $this->GetControl('txtQuantityReceived' . $objInventoryTransaction->InventoryTransactionId); // Error check the Quantity Value if ($txtQuantityReceived && $txtQuantityReceived->Text && ctype_digit($txtQuantityReceived->Text) && $txtQuantityReceived->Text >= 0 && $txtQuantityReceived->Text <= $objInventoryTransaction->Quantity) { // Set local values for user inputs $intQuantity = $txtQuantityReceived->Text; $intDestinationLocationId = $lstLocationInventoryReceived->SelectedValue; // Split the InventoryTransaction into two if it is only a partial receipt if ($objInventoryTransaction->Quantity > $intQuantity) { $objNewInventoryTransaction = new InventoryTransaction(); $objNewInventoryTransaction->InventoryLocationId = $objInventoryTransaction->InventoryLocationId; $objNewInventoryTransaction->TransactionId = $this->objReceipt->TransactionId; $objNewInventoryTransaction->Quantity = $intQuantity; $objNewInventoryTransaction->SourceLocationId = $objInventoryTransaction->SourceLocationId; $objNewInventoryTransaction->DestinationLocationId = $intDestinationLocationId; $objNewInventoryTransaction->Save(); // Add the new InventoryTransaction to the InvetnoryTransaction array for immediate display in the datagrid $this->objInventoryTransactionArray[] = $objNewInventoryTransaction; // Subtract the partial receipt quantity from the original InventoryTransaction $objInventoryTransaction->Quantity -= $intQuantity; // If a partial receipt has taken place, then all inventory has not been received $blnAllInventoryReceived = false; } else { $objInventoryTransaction->DestinationLocationId = $intDestinationLocationId; } // See if the InventoryLocation already exists $objNewInventoryLocation = InventoryLocation::LoadByLocationIdInventoryModelId($intDestinationLocationId, $objInventoryTransaction->InventoryLocation->InventoryModelId); // Create a new InventoryLocation if it doesn't exist already if (!$objNewInventoryLocation) { $objNewInventoryLocation = new InventoryLocation(); $objNewInventoryLocation->LocationId = $intDestinationLocationId; $objNewInventoryLocation->InventoryModelId = $objInventoryTransaction->InventoryLocation->InventoryModelId; $objNewInventoryLocation->Quantity = 0; } // The problem here is that two different InventoryTransactions have the same InventoryLocation // So if you receive two of the same InventoryModels without a reload, it generates an OLE // So we were reloading one here, but not the other one, and that's the one that is changed the next time // So now I reload before, and if it's a genuine OLE, then the InventoryTransaction will catch it // It also reloads after // Remove the inventory from the 'To Be Received' Location $objInventoryTransaction->InventoryLocation = InventoryLocation::Load($objInventoryTransaction->InventoryLocationId); $objInventoryTransaction->InventoryLocation->Quantity -= $intQuantity; $objInventoryTransaction->InventoryLocation->Save(); $objInventoryTransaction->InventoryLocation = InventoryLocation::Load($objInventoryTransaction->InventoryLocationId); // Add the inventory that came from 'TBR' into the new location $objNewInventoryLocation->Quantity += $intQuantity; $objNewInventoryLocation->Save(); $objInventoryTransaction->Save(); // Reload the InventoryTransaction to get the new timestamp so that it doesn't generate an optimistic locking exception $objInventoryTransaction = InventoryTransaction::Load($objInventoryTransaction->InventoryTransactionId); } else { $blnError = true; $this->dtgInventoryTransact->Warning = "Please enter a valid quantity."; } } else { $blnError = true; $this->dtgInventoryTransact->Warning = "Please Select a Location."; } } if (!$objInventoryTransaction->DestinationLocationId) { $blnAllInventoryReceived = false; } } // If all Inventory is received, check to see if all assets have been received if ($blnAllInventoryReceived) { $blnAllAssetsReceived = true; if ($this->objAssetTransactionArray) { foreach ($this->objAssetTransactionArray as $objAssetTransaction) { if (!$objAssetTransaction->DestinationLocationId) { $blnAllAssetsReceived = false; } } } // If all Inventory and Assets have been received if ($blnAllAssetsReceived) { // Flip the received flag for the entire Receipt $this->objReceipt->ReceivedFlag = true; $this->objReceipt->ReceiptDate = new QDateTime(QDateTime::Now); $this->objReceipt->Save(); // Reload to get new timestamp to avoid optimistic locking if edited/saved again without reload $this->objReceipt = Receipt::Load($this->objReceipt->ReceiptId); // Update labels (specifically we want to update Received Date) $this->UpdateReceiptLabels(); } } // Commit all of the transactions to the database $objDatabase->TransactionCommit(); $this->dtgInventoryTransact->Refresh(); } catch (QExtendedOptimisticLockingException $objExc) { // Rollback the database transactions if an exception was thrown $objDatabase->TransactionRollback(); if ($objExc->Class == 'InventoryTransaction' || $objExc->Class == 'InventoryLocation') { $this->dtgInventoryTransact->Warning = sprintf('That inventory has been added, removed, or received by another user. You must <a href="receipt_edit.php?intReceiptId=%s">Refresh</a> to edit this receipt.%s', $this->objReceipt->ReceiptId, $objExc->Class . $objExc->EntityId); } else { throw new QOptimisticLockingException($objExc->Class); } } } }
protected function btnCompleteShipment_Click($strFormId, $strControlId, $strParameter) { $blnError = false; if ($this->objAssetTransactionArray && $this->objInventoryTransactionArray) { $intEntityQtypeId = EntityQtype::AssetInventory; } elseif ($this->objAssetTransactionArray) { $intEntityQtypeId = EntityQtype::Asset; } elseif ($this->objInventoryTransactionArray) { $intEntityQtypeId = EntityQtype::Inventory; } else { $blnError = true; $this->btnCompleteShipment->Warning = 'There are no assets or inventory in this shipment.'; } if ($this->objAssetTransactionArray) { foreach ($this->objAssetTransactionArray as $objAssetTransaction) { if ($objAssetTransaction->Asset instanceof Asset) { $arrAssetTransactions = AssetTransaction::LoadArrayByAssetId($objAssetTransaction->Asset->AssetId, array(QQ::OrderBy(QQN::AssetTransaction()->CreationDate, false))); if (count($arrAssetTransactions) > 0) { $intLastTransactionId = $arrAssetTransactions[0]->TransactionId; $transaction = Transaction::load($intLastTransactionId); if ($transaction->TransactionTypeId == 6 && $transaction->Shipment->ShippedFlag) { $blnError = true; $this->btnCompleteShipment->Warning = $objAssetTransaction->Asset->__toStringWithLink() . ' already shipped.'; } } } } } if (!$blnError) { try { // Get an instance of the database $objDatabase = QApplication::$Database[1]; // Begin a MySQL Transaction to be either committed or rolled back $objDatabase->TransactionBegin(); if (!$this->blnEditMode) { // this is a new shipment so save the transaction & shipment before completing // Create the new transaction object and save it $this->objTransaction = new Transaction(); $this->objTransaction->EntityQtypeId = $intEntityQtypeId; $this->objTransaction->TransactionTypeId = 6; $this->objTransaction->Note = $this->txtNote->Text; $this->objTransaction->Save(); $this->UpdateShipmentFields(); $this->objShipment->Save(true); if ($this->arrCustomFields) { // Save the values from all of the custom field controls to save the shipment CustomField::SaveControls($this->objShipment->objCustomFieldArray, $this->blnEditMode, $this->arrCustomFields, $this->objShipment->ShipmentId, 10); } } // Create receipt transaction for internal shipment if ($this->objShipment->ToCompanyId == $this->objShipment->FromCompanyId) { $this->receiveInternalShipmentTransaction = new Transaction(); $this->receiveInternalShipmentTransaction->EntityQtypeId = $intEntityQtypeId; $this->receiveInternalShipmentTransaction->TransactionTypeId = 7; $note = sprintf('This receipt was automatically created when creating internal shipment Number %s. ', $this->objShipment->ShipmentNumber); $this->receiveInternalShipmentTransaction->Note = $note . $this->txtNote->Text; $this->receiveInternalShipmentTransaction->Save(); // Create a new receipt $objInternalReceipt = new Receipt(); $objInternalReceipt->TransactionId = $this->receiveInternalShipmentTransaction->TransactionId; // The receipt will mimic the shipment information $objInternalReceipt->FromCompanyId = $this->objShipment->FromCompanyId; $objInternalReceipt->FromContactId = $this->objShipment->FromContactId; $objInternalReceipt->ToContactId = $this->objShipment->ToContactId; $objInternalReceipt->ToAddressId = $this->objShipment->ToAddressId; $objInternalReceipt->ReceivedFlag = 0; $objInternalReceipt->ReceiptNumber = Receipt::LoadNewReceiptNumber(); $objInternalReceipt->Save(); } if ($intEntityQtypeId == EntityQtype::AssetInventory || $intEntityQtypeId == EntityQtype::Asset) { $objTransaction = ''; $objReceipt = ''; $objNewAssetTransactionArray = array(); foreach ($this->objAssetTransactionArray as $objAssetTransaction) { $objNewAssetTransactionArray[$objAssetTransaction->Asset->AssetCode] = $objAssetTransaction; } // Assign a destinationLocation to the AssetTransaction, and change the Location of the asset foreach ($this->objAssetTransactionArray as $objAssetTransaction) { if ($objAssetTransaction->Asset instanceof Asset) { // LocationId #2 == Shipped $DestinationLocationId = 2; if ($objAssetTransaction->ScheduleReceiptFlag && $objAssetTransaction->Asset->LinkedFlag) { $objAssetTransaction = $objNewAssetTransactionArray[$objAssetTransaction->Asset->AssetCode]; } $objAssetTransaction->Asset->LocationId = $DestinationLocationId; $objAssetTransaction->Asset->Save(); if (!$this->blnEditMode) { // Assign the TransactionId $objAssetTransaction->TransactionId = $this->objTransaction->TransactionId; } $objAssetTransaction->DestinationLocationId = $DestinationLocationId; // No any actions with linked items (LinkedFlag = 1) which have been scheduled for receipt if ($objAssetTransaction->ScheduleReceiptFlag && !$objAssetTransaction->Asset->LinkedFlag) { if ($objAssetTransaction->NewAsset && $objAssetTransaction->NewAsset instanceof Asset && $objAssetTransaction->NewAsset->AssetId == null) { // We have to create the new asset before we can $objReceiptAsset = new Asset(); $objReceiptAsset->AssetModelId = $objAssetTransaction->NewAsset->AssetModelId; $objReceiptAsset->LocationId = $objAssetTransaction->NewAsset->LocationId; if ($objAssetTransaction->NewAsset->AssetCode == '') { $objReceiptAsset->AssetCode = Asset::GenerateAssetCode(); } else { $objReceiptAsset->AssetCode = $objAssetTransaction->NewAsset->AssetCode; } $objReceiptAsset->Save(); // Assign any default custom field values CustomField::AssignNewEntityDefaultValues(1, $objReceiptAsset->AssetId); // Associate the new Asset with the AssetTransaction $objAssetTransaction->NewAsset = $objReceiptAsset; } // If it doesn't exist, create a new transaction object and receipt object if (!$objTransaction instanceof Transaction && !$objReceipt instanceof Receipt) { $objTransaction = new Transaction(); // Transaction is asset only $objTransaction->EntityQtypeId = 1; // Transaction is a receipt $objTransaction->TransactionTypeId = 7; // Set a note showing how this receipt was created if (!$objAssetTransaction->NewAssetId) { $strTransactionType = 'return'; } else { $strTransactionType = 'exchange'; } $objTransaction->Note = sprintf('This %s receipt was automatically created when creating Shipment Number %s.', $strTransactionType, $this->objShipment->ShipmentNumber); // Save the transaction $objTransaction->Save(); // Create a new receipt $objReceipt = new Receipt(); $objReceipt->TransactionId = $objTransaction->TransactionId; // The receipt will be coming from the company that was shipped to $objReceipt->FromCompanyId = $this->objShipment->ToCompanyId; $objReceipt->FromContactId = $this->objShipment->ToContactId; $objReceipt->ToContactId = $this->objShipment->FromContactId; $objReceipt->ToAddressId = $this->objShipment->FromAddressId; $objReceipt->ReceivedFlag = 0; $objReceipt->ReceiptNumber = Receipt::LoadNewReceiptNumber(); if ($objAssetTransaction->ScheduleReceiptDueDate) { $objReceipt->DueDate = $objAssetTransaction->ScheduleReceiptDueDate; } $objReceipt->Save(); } $objReceiptAssetTransaction = new AssetTransaction(); // If this is a return if (!$objAssetTransaction->NewAssetId) { $objReceiptAssetTransaction->AssetId = $objAssetTransaction->AssetId; } else { // Both the shipmentAssetTranscation (objAssetTransaction and the objReceiptAssetTransaction were involved in creating a new asset // Asset Transactions where NewAssetFlag = true but AssetId is NULL are receipt asset transactions for exchanges. $objReceiptAssetTransaction->AssetId = $objAssetTransaction->NewAssetId; $objReceiptAssetTransaction->NewAssetFlag = true; $objAssetTransaction->NewAssetFlag = true; $objAssetTransaction->Save(); } $objReceiptAssetTransaction->TransactionId = $objTransaction->TransactionId; $objReceiptAssetTransaction->SourceLocationId = $objAssetTransaction->DestinationLocationId; // This is not right. NewAssetFlag should be set only if a new asset was created when creating this AssetTransaction // It should not be true on the new AssetTransaction, but only on the AssetTransaction that caused the new asset to be created. // $objReceiptAssetTransaction->NewAssetFlag = true; $objReceiptAssetTransaction->Save(); // Load all child assets if ($objLinkedAssetCodeArray = Asset::LoadChildLinkedArrayByParentAssetId($objAssetTransaction->Asset->AssetId)) { foreach ($objLinkedAssetCodeArray as $objLinkedAssetCode) { $objLinkedAssetTransaction = $objNewAssetTransactionArray[$objLinkedAssetCode->AssetCode]; $objLinkedReceiptAssetTransaction = new AssetTransaction(); // If this is a return if (!$objAssetTransaction->NewAssetId) { $objLinkedReceiptAssetTransaction->AssetId = $objLinkedAssetTransaction->AssetId; $objLinkedReceiptAssetTransaction->TransactionId = $objTransaction->TransactionId; $objLinkedReceiptAssetTransaction->SourceLocationId = $objAssetTransaction->DestinationLocationId; $objLinkedReceiptAssetTransaction->Save(); } else { // Both the shipmentAssetTranscation (objAssetTransaction and the objReceiptAssetTransaction were involved in creating a new asset // Asset Transactions where NewAssetFlag = true but AssetId is NULL are receipt asset transactions for exchanges. $objLinkedReceiptAssetTransaction->AssetId = $objAssetTransaction->NewAssetId; } $objNewAssetTransactionArray[$objLinkedAssetCode->AssetCode] = $objLinkedAssetTransaction; } } } $objAssetTransaction->Save(); if ($objAssetTransaction->ScheduleReceiptFlag) { // Set the Receipt Asset Transaction as child of the Shipment Asset Transaction $objAssetTransaction->AssociateChildAssetTransaction($objReceiptAssetTransaction); } if ($this->objShipment->ToCompanyId == $this->objShipment->FromCompanyId && !$objAssetTransaction->Asset->LinkedFlag) { $objReceiptAssetTransaction = new AssetTransaction(); $objReceiptAssetTransaction->AssetId = $objAssetTransaction->AssetId; $objReceiptAssetTransaction->TransactionId = $this->receiveInternalShipmentTransaction->TransactionId; $objReceiptAssetTransaction->SourceLocationId = $objAssetTransaction->SourceLocationId; $objReceiptAssetTransaction->Save(); // Load all child assets if ($objLinkedAssetCodeArray = Asset::LoadChildLinkedArrayByParentAssetId($objAssetTransaction->Asset->AssetId)) { foreach ($objLinkedAssetCodeArray as $objLinkedAssetCode) { $objLinkedAssetTransaction = $objNewAssetTransactionArray[$objLinkedAssetCode->AssetCode]; $objLinkedReceiptAssetTransaction = new AssetTransaction(); // add data to linked asset $objLinkedReceiptAssetTransaction->AssetId = $objLinkedAssetTransaction->AssetId; $objLinkedReceiptAssetTransaction->TransactionId = $this->receiveInternalShipmentTransaction->TransactionId; $objLinkedReceiptAssetTransaction->SourceLocationId = $objAssetTransaction->SourceLocationId; $objLinkedReceiptAssetTransaction->Save(); } } } $objReceipt = null; $objTransaction = null; } } } if ($intEntityQtypeId == EntityQtype::AssetInventory || $intEntityQtypeId == EntityQtype::Inventory) { // Assign different source and destinations depending on transaction type foreach ($this->objInventoryTransactionArray as $objInventoryTransaction) { // LocationId #2 == Shipped $DestinationLocationId = 2; if (!$this->blnEditMode) { $objInventoryTransaction->TransactionId = $this->objTransaction->TransactionId; } // Remove the inventory quantity from the source $objInventoryTransaction->InventoryLocation->Quantity = $objInventoryTransaction->InventoryLocation->Quantity - $objInventoryTransaction->Quantity; $objInventoryTransaction->InventoryLocation->Save(); // Finish the InventoryTransaction and save it $objInventoryTransaction->DestinationLocationId = $DestinationLocationId; $objInventoryTransaction->Save(); // Add Inventory to receipt if this is an internal shipment if ($this->objShipment->ToCompanyId == $this->objShipment->FromCompanyId) { $objReceiptInventoryLocation = InventoryLocation::LoadByLocationIdInventoryModelId(5, $objInventoryTransaction->InventoryLocation->InventoryModelId); if (!$objReceiptInventoryLocation) { // First create the inventory location if it doesn't exist $objReceiptInventoryLocation = new InventoryLocation(); $objReceiptInventoryLocation->InventoryModelId = $objInventoryTransaction->InventoryLocation->InventoryModelId; $objReceiptInventoryLocation->LocationId = 5; $objReceiptInventoryLocation->Quantity = 0; } // Set the To Be Received quantity $objReceiptInventoryLocation->Quantity += $objInventoryTransaction->Quantity; $objReceiptInventoryLocation->Save(); // Create the inventory transaction $objReceiptInventoryTransaction = new InventoryTransaction(); $objReceiptInventoryTransaction->TransactionId = $this->receiveInternalShipmentTransaction->TransactionId; $objReceiptInventoryTransaction->InventoryLocationId = $objReceiptInventoryLocation->InventoryLocationId; $objReceiptInventoryTransaction->Quantity = $objInventoryTransaction->Quantity; $objReceiptInventoryTransaction->SourceLocationId = 5; $objReceiptInventoryTransaction->Save(); } } } if ($this->blnEditMode) { $this->UpdateShipmentFields(); } $this->objShipment->ShippedFlag = true; // $this->objShipment->Save(false, true); $this->objShipment->Save(); $objDatabase->TransactionCommit(); QApplication::Redirect(sprintf('../shipping/shipment_edit.php?intShipmentId=%s', $this->objShipment->ShipmentId)); } catch (QExtendedOptimisticLockingException $objExc) { $objDatabase->TransactionRollback(); if ($objExc->Class == 'Shipment') { $this->btnCancelShipment->Warning = sprintf('This shipment has been modified by another user. You must <a href="shipment_edit.php?intShipmentId=%s">Refresh</a> to complete this shipment.', $this->objShipment->ShipmentId); } else { throw new QOptimisticLockingException($objExc->Class); } } } }