/// <summary> /// Updates the status of the Destination Order. /// </summary> /// <param name="destinationOrderRow">The Working Order to be modified.</param> /// <param name="status">The new status of the Working Order.</param> private static void UpdateDestinationOrderStatus(DestinationOrderRow destinationOrderRow, Status status) { // It is a good idea to have a central method for updating the Destination Order in the event the parameter order changes. Execution.dataModel.UpdateDestinationOrder(null, null, null, null, null, null, null, new object[] { destinationOrderRow.DestinationOrderId }, null, null, null, null, null, null, null, null, null, destinationOrderRow.RowVersion, null, null, null, null, null, StatusMap.FromCode(status), null, null, null, null, null); }
/// <summary> /// Handler for validating Destination Order records. /// </summary> /// <param name="sender">The object that originated the event.</param> /// <param name="e">The event arguments.</param> internal static void OnDestinationOrderRowValidate(object sender, DestinationOrderRowChangeEventArgs e) { Int32 currentStatusCode; Decimal destinationOrderQuantity; DataModelTransaction dataModelTransaction; Int32 previousStatusCode; Decimal sourceOrderQuantity; WorkingOrderRow workingOrderRow; // The Business Rules will be enforced on this Destination Order. Note that it is locked at the point this handler is called. DestinationOrderRow destinationOrderRow = e.Row; // The action on the row determines which rule to evaluate. switch (destinationOrderRow.RowState) { case DataRowState.Added: // This rule will reject the operation if the Working Order is overcommitted with a destination. dataModelTransaction = DataModelTransaction.Current; // This rule will throw an exception if the quantity sent to a destination is greater than the quantity ordered. The quantity ordered and // quantity sent can only be calcuated from the owning Working Order which must be locked in order to carry out the calculations. workingOrderRow = e.Row.WorkingOrderRow; workingOrderRow.AcquireReaderLock(dataModelTransaction); sourceOrderQuantity = WorkingOrder.GetSourceOrderQuantity(dataModelTransaction, workingOrderRow); destinationOrderQuantity = WorkingOrder.GetDestinationOrderQuantity(dataModelTransaction, workingOrderRow); if (sourceOrderQuantity < destinationOrderQuantity) { throw new FaultException <DestinationQuantityFault>( new DestinationQuantityFault(workingOrderRow.WorkingOrderId, sourceOrderQuantity, destinationOrderQuantity)); } break; case DataRowState.Modified: // Reject the operation if the Working Order is overcommitted with a destination. Note that the order of the evaluation is important for // efficiency. There is no need to sum up the source and Destination Orders if the quantity has been reduced as there's no chance it will be // over committed. Decimal originalQuantity = (Decimal)destinationOrderRow[DataModel.DestinationOrder.OrderedQuantityColumn, DataRowVersion.Original]; Decimal currentQuantity = (Decimal)destinationOrderRow[DataModel.DestinationOrder.OrderedQuantityColumn, DataRowVersion.Current]; if (originalQuantity < currentQuantity) { // Once it's determined that the order can be overcommitted, a middle tier context is required to lock the rows so the quantities can be // aggregated. dataModelTransaction = DataModelTransaction.Current; // This rule will throw an exception if the quantity sent to a destination is greater than the quantity ordered. The quantity ordered and // quantity sent can only be calcuated from the owning Working Order which must be locked in order to carry out the calculations. workingOrderRow = e.Row.WorkingOrderRow; workingOrderRow.AcquireReaderLock(dataModelTransaction); sourceOrderQuantity = WorkingOrder.GetSourceOrderQuantity(dataModelTransaction, workingOrderRow); destinationOrderQuantity = WorkingOrder.GetDestinationOrderQuantity(dataModelTransaction, workingOrderRow); if (sourceOrderQuantity < destinationOrderQuantity) { throw new FaultException <DestinationQuantityFault>( new DestinationQuantityFault(workingOrderRow.WorkingOrderId, sourceOrderQuantity, destinationOrderQuantity)); } } // This rule will examine the effects of a state change of the Destination Order. The stateChangeMatrix contains delegates to methods that // will determine what, if any, stats change should be applied to the Working Order due to the change in state of this Destination Order. previousStatusCode = Convert.ToInt32(StatusMap.FromId((Guid)destinationOrderRow[DataModel.DestinationOrder.StatusIdColumn, DataRowVersion.Original])); currentStatusCode = Convert.ToInt32(StatusMap.FromId((Guid)destinationOrderRow[DataModel.DestinationOrder.StatusIdColumn, DataRowVersion.Current])); if (previousStatusCode != currentStatusCode) { DestinationOrder.statusChangeMatrix[previousStatusCode, currentStatusCode](new Object[] { destinationOrderRow.WorkingOrderId }); } break; case DataRowState.Deleted: // This rule will examine the effects of a state change of the Destination Order. The stateChangeMatrix contains delegates to methods that // will determine what, if any, stats change should be applied to the Working Order due to the change in state of this Destination Order. previousStatusCode = Convert.ToInt32(StatusMap.FromId((Guid)destinationOrderRow[DataModel.DestinationOrder.StatusIdColumn, DataRowVersion.Original])); currentStatusCode = (Int32)Status.Deleted; Guid workingOrderId = (Guid)destinationOrderRow[DataModel.DestinationOrder.WorkingOrderIdColumn, DataRowVersion.Original]; DestinationOrder.statusChangeMatrix[previousStatusCode, currentStatusCode](new Object[] { workingOrderId }); break; } }