Exemplo n.º 1
0
 /// <summary>
 /// Handles a change to the ExecutionRow table.
 /// </summary>
 /// <param name="sender">The object that originated the event.</param>
 /// <param name="e">The event arguments.</param>
 private void OnExecutionRowChanged(object sender, ExecutionRowChangeEventArgs e)
 {
     // When the merge is completed, this indicates that the document should be refreshed.
     this.isDataChanged = true;
 }
Exemplo n.º 2
0
        /// <summary>
        /// Handler for validating Execution records.
        /// </summary>
        /// <param name="sender">The object that originated the event.</param>
        /// <param name="e">The event arguments.</param>
        internal static void OnExecutionRowValidate(object sender, ExecutionRowChangeEventArgs e)
        {
            DestinationOrderRow  destinationOrderRow;
            Decimal              executedQuantity;
            DataModelTransaction dataModelTransaction;
            Decimal              orderedQuantity;

            // The Business Rules will be enforced on this Execution.  Note that it is locked at the point this handler is called.
            ExecutionRow executionRow = e.Row;

            // The action on the row determines which rule to evaluate.
            switch (e.Action)
            {
            case DataRowAction.Add:

                // This rule will update the status of the owning Destination Order based on the quantity executed.
                dataModelTransaction = DataModelTransaction.Current;

                // The aggregate of the quantities executed will determine whether the Destination Order requires a status change.
                destinationOrderRow = executionRow.DestinationOrderRow;
                destinationOrderRow.AcquireReaderLock(dataModelTransaction);
                if (destinationOrderRow.RowState == DataRowState.Detached)
                {
                    return;
                }

                // This calculates the quantity outstanding on an order and the quantity executed on the order.
                orderedQuantity  = destinationOrderRow.OrderedQuantity - destinationOrderRow.CanceledQuantity;
                executedQuantity = 0.0M;
                foreach (ExecutionRow siblingRow in destinationOrderRow.GetExecutionRows())
                {
                    siblingRow.AcquireReaderLock(dataModelTransaction);
                    executedQuantity += siblingRow.ExecutionQuantity;
                }

                // This rule will set the status on the owning Destination Order based on the amont outstanding and the amount ordered.  First, if the quantity
                // executed is greater than the quantity ordered, the Order goes into an error state.  We can't reject executions as they come from an external
                // source, but the order can be flag and put into an error state.
                if (executedQuantity > orderedQuantity)
                {
                    if (destinationOrderRow.StatusId != StatusMap.FromCode(Status.Error))
                    {
                        UpdateDestinationOrderStatus(destinationOrderRow, Status.Error);
                    }
                }
                else
                {
                    // When the total quantity executed is reduced to zero then the order goes back into the initial state.
                    if (executedQuantity == 0.0m)
                    {
                        if (destinationOrderRow.StatusId != StatusMap.FromCode(Status.New))
                        {
                            UpdateDestinationOrderStatus(destinationOrderRow, Status.New);
                        }
                    }
                    else
                    {
                        // While the executed quantity is still less than the outstanding quantity the order is consdered to be partially filled.  Otherwise,
                        // the order is completely filled.
                        if (executedQuantity < orderedQuantity)
                        {
                            if (destinationOrderRow.StatusId != StatusMap.FromCode(Status.PartiallyFilled))
                            {
                                UpdateDestinationOrderStatus(destinationOrderRow, Status.PartiallyFilled);
                            }
                        }
                        else
                        {
                            if (destinationOrderRow.StatusId != StatusMap.FromCode(Status.Filled))
                            {
                                UpdateDestinationOrderStatus(destinationOrderRow, Status.Filled);
                            }
                        }
                    }
                }

                break;

            case DataRowAction.Delete:

                // A middle tier context is required to lock the rows so the quantities can be aggregated.
                dataModelTransaction = DataModelTransaction.Current;

                // The aggregate of the quantities executed will determine whether the Destination Order requires a status change.
                destinationOrderRow = (DestinationOrderRow)executionRow.GetParentRow(
                    DataModel.Execution.DestinationOrderExecutionRelation,
                    DataRowVersion.Original);
                destinationOrderRow.AcquireReaderLock(dataModelTransaction);
                if (destinationOrderRow.RowState == DataRowState.Detached)
                {
                    return;
                }

                // This calculates the quantity outstanding on an order and the quantity executed on the order.
                orderedQuantity  = destinationOrderRow.OrderedQuantity - destinationOrderRow.CanceledQuantity;
                executedQuantity = 0.0M;
                foreach (ExecutionRow siblingRow in destinationOrderRow.GetExecutionRows())
                {
                    siblingRow.AcquireReaderLock(dataModelTransaction);
                    executedQuantity += siblingRow.ExecutionQuantity;
                }

                // When the total quantity executed is reduced to zero then the order goes back into the initial state.  Note that it is impossible for the
                // order to transition into a error state by deleting an execution.
                if (executedQuantity == 0.0m)
                {
                    if (destinationOrderRow.StatusId != StatusMap.FromCode(Status.New))
                    {
                        UpdateDestinationOrderStatus(destinationOrderRow, Status.New);
                    }
                }
                else
                {
                    // While the executed quantity is still less than the outstanding quantity the order is consdered to be partially filled.  Note that it is
                    // impossible for the order to transition to a filled state by deleting an execution.
                    if (executedQuantity < orderedQuantity)
                    {
                        if (destinationOrderRow.StatusId != StatusMap.FromCode(Status.PartiallyFilled))
                        {
                            UpdateDestinationOrderStatus(destinationOrderRow, Status.PartiallyFilled);
                        }
                    }
                }

                break;
            }
        }