Пример #1
0
        /// <summary>
        /// Reset the negotiation to a "in negotiation" state.
        /// </summary>
        /// <param name="consumerDebtNegotiations">The the negotiations to reset.</param>
        internal static void Reject(ConsumerDebtNegotiationInfo[] consumerDebtNegotiations)
        {
            // An instance of the shared data model is required to use its methods.
            DataModel dataModel = new DataModel();

            // The business logic requires the current time and the user identifier for auditing.
            Guid     createUserId   = TradingSupport.UserId;
            DateTime createDateTime = DateTime.UtcNow;
            DateTime modifiedTime   = createDateTime;
            Guid     modifiedUserId = createUserId;


            // This Web Method comes with an implicit transaction that is linked to its execution.
            DataModelTransaction dataModelTransaction = DataModelTransaction.Current;

            // This method can handle a batch of updates in a single transaction.
            foreach (ConsumerDebtNegotiationInfo consumerDebtNegotiationInfo in consumerDebtNegotiations)
            {
                // The blotter is not passed in from the client but is used
                Guid   blotterId = Guid.Empty;
                Status negotiationStatus;
                DebtNegotiationInfo debtNegotiationInfo = null;
                // This is the next negotiation in the batch to be updated.
                ConsumerDebtNegotiationRow consumerDebtNegotiationRow =
                    DataModel.ConsumerDebtNegotiation.ConsumerDebtNegotiationKey.Find(consumerDebtNegotiationInfo.ConsumerDebtNegotiationId);

                // The payment methods available to this negotiation is a vector.  Rather than delete everything and re-add it anytime an update is made, a
                // list of changes is constructed: new payment methods are added, obsolete payment methods are deleted and the ones that haven't changed are
                // left alone.  These list help to work out the differences.
                List <ConsumerDebtNegotiationPaymentMethodTypeInfo> counterItems = new List <ConsumerDebtNegotiationPaymentMethodTypeInfo>();

                try
                {
                    // Lock the current negotation record for reading.  The data model doesn't support reader lock promotion, so the programming model is to
                    // lock the database, collect the data, release the locks and then write.  This model is especially important when iterating through a
                    // large batch to prevent the number of locks from growing to large.
                    consumerDebtNegotiationRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);

                    // The blotter identifier is used for access control and is not passed in by the client.
                    blotterId           = consumerDebtNegotiationRow.BlotterId;
                    debtNegotiationInfo = new DebtNegotiationInfo(consumerDebtNegotiationRow);
                    negotiationStatus   = StatusMap.FromId(consumerDebtNegotiationRow.StatusId);

                    // Determine whether the client has the right to modify this record.
                    if (!TradingSupport.HasAccess(dataModelTransaction, blotterId, AccessRight.Write))
                    {
                        throw new FaultException <FluidTrade.Core.SecurityFault>(new SecurityFault("You do not have write access to the selected object."));
                    }

                    MatchRow matchRow = DataModel.Match.MatchKey.Find(debtNegotiationInfo.MatchId);
                    try
                    {
                        matchRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);
                        debtNegotiationInfo.MatchRowVersion = matchRow.RowVersion;
                        debtNegotiationInfo.ContraMatchId   = matchRow.ContraMatchId;
                    }
                    finally
                    {
                        matchRow.ReleaseReaderLock(dataModelTransaction.TransactionId);
                    }

                    MatchRow contraMatchRow = DataModel.Match.MatchKey.Find(debtNegotiationInfo.ContraMatchId);
                    try
                    {
                        contraMatchRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);
                        debtNegotiationInfo.ContraMatchRowVersion = contraMatchRow.RowVersion;
                    }
                    finally
                    {
                        contraMatchRow.ReleaseReaderLock(dataModelTransaction.TransactionId);
                    }

                    // The payment methods are maintained as a vector associated with the negotiation record.  This will lock each of the records and read the
                    // payment methods into a data structure so the locks don't need to be held when it is time to write.
                    foreach (var consumerDebtNegotiationOfferPaymentMethodRow
                             in consumerDebtNegotiationRow.GetConsumerDebtNegotiationCounterPaymentMethodRows())
                    {
                        try
                        {
                            // Temporarily lock the record containing the payment method.
                            consumerDebtNegotiationOfferPaymentMethodRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);

                            // This will construct a mask of items that are already part of this negotiation.  The mask is used to prevent an item from being
                            // added if it's already there.
                            // This list is used to delete the payment methods that are no longer part of this negotiation.
                            counterItems.Add(
                                new ConsumerDebtNegotiationPaymentMethodTypeInfo(
                                    consumerDebtNegotiationOfferPaymentMethodRow.PaymentMethodTypeId,
                                    consumerDebtNegotiationOfferPaymentMethodRow.ConsumerDebtNegotiationCounterPaymentMethodId,
                                    consumerDebtNegotiationOfferPaymentMethodRow.RowVersion));
                        }
                        finally
                        {
                            // At this point the payment method isn't needed.
                            consumerDebtNegotiationOfferPaymentMethodRow.ReleaseReaderLock(dataModelTransaction.TransactionId);
                        }
                    }
                }
                finally
                {
                    // At this point, the negotiation record isn't needed.  It is critical to release the reader locks before attempting a write.
                    consumerDebtNegotiationRow.ReleaseReaderLock(dataModelTransaction.TransactionId);
                }


                // At this point, all the data for this operation has been collected and the CRUD operations can be invoked to finish the update.  Note that
                // the counter party information is not modified here, but is done through the Chinese wall.
                Guid newConsureDebtNegotiationId = Guid.NewGuid();
                dataModel.CreateConsumerDebtNegotiation(
                    debtNegotiationInfo.AccountBalance,
                    debtNegotiationInfo.BlotterId,
                    newConsureDebtNegotiationId,
                    debtNegotiationInfo.CounterPaymentLength,
                    debtNegotiationInfo.CounterPaymentStartDateLength,
                    debtNegotiationInfo.CounterPaymentStartDateUnitId,
                    debtNegotiationInfo.CounterSettlementUnitId,
                    debtNegotiationInfo.CounterSettlementValue,
                    modifiedTime,
                    modifiedUserId,
                    debtNegotiationInfo.IsRead,
                    debtNegotiationInfo.IsReply,
                    debtNegotiationInfo.MatchId,
                    modifiedTime,
                    modifiedUserId,
                    consumerDebtNegotiationInfo.PaymentLength,
                    consumerDebtNegotiationInfo.PaymentStartDateLength,
                    consumerDebtNegotiationInfo.PaymentStartDateUnitId,
                    consumerDebtNegotiationInfo.SettlementUnitId,
                    consumerDebtNegotiationInfo.SettlementValue,
                    StatusMap.FromCode(Status.Rejected),
                    out debtNegotiationInfo.Version);

                // This will add the payment methods to the negotiation that are not already there.
                foreach (Guid paymentMethodTypeId in consumerDebtNegotiationInfo.PaymentMethodTypes)
                {
                    dataModel.CreateConsumerDebtNegotiationOfferPaymentMethod(
                        blotterId,
                        newConsureDebtNegotiationId,
                        Guid.NewGuid(),
                        paymentMethodTypeId);
                }

                //This will delete those payment methods that are no longer part of the negotiation.
                foreach (ConsumerDebtNegotiationPaymentMethodTypeInfo consumerDebtNegotiationPaymentMethodTypeInfo in counterItems)
                {
                    dataModel.UpdateConsumerDebtNegotiationCounterPaymentMethod(blotterId,
                                                                                null,
                                                                                new Object[] { consumerDebtNegotiationPaymentMethodTypeInfo.ConsumerDebtNegotiationOfferPaymentMethodId },
                                                                                newConsureDebtNegotiationId,
                                                                                null,
                                                                                consumerDebtNegotiationPaymentMethodTypeInfo.RowVersion);
                }

                //Reset the Match Status Id.  This is required so the match engine will redo the match.  The
                //match engine does not recalculate if it is not in the initial three stages of - Valid, Partial, ValidwithFunds
                dataModel.UpdateMatch(
                    null,
                    null,
                    null,
                    null,
                    null,
                    null,
                    null,
                    new object[] { debtNegotiationInfo.MatchId },
                    debtNegotiationInfo.MatchRowVersion,
                    StatusMap.FromCode(Status.ValidMatch),
                    null);

                //Reset the Contra Match Status Id
                dataModel.UpdateMatch(
                    null,
                    null,
                    null,
                    null,
                    null,
                    null,
                    null,
                    new object[] { debtNegotiationInfo.ContraMatchId },
                    debtNegotiationInfo.ContraMatchRowVersion,
                    StatusMap.FromCode(Status.ValidMatch),
                    null);
            }
        }