コード例 #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);
            }
        }
コード例 #2
0
        /// <summary>
        /// Creates a new SettlementInfo instance.
        /// </summary>
        public SettlementItem(Guid matchId)
        {
            // Initialize the object.
            this.ChatItemList          = new List <ChatItem>();
            this.CounterPaymentMethods = new List <Guid>();
            this.OfferPaymentMethods   = new List <Guid>();

            // The data model must be locked in order to navigate the data.  The main idea here is to find the chat items and the negotiation elements
            // associated with this match and send that data to the foreground where it can be displayed.
            lock (DataModel.SyncRoot)
            {
                // This dialog will only handle matches that have this identifier.
                MatchRow matchRow = DataModel.Match.MatchKey.Find(matchId);
                if (matchRow == null)
                {
                    this.Status = Status.Deleted;
                }
                else
                {
                    // The status code drives the state of many of the controls in the console.
                    this.Status = matchRow.StatusRow.StatusCode;

                    // The negotiation table has a historical component. Ever time a change is made to the negotiation on either side a completely new record
                    // is created to record the change.  While the earlier versions are useful for a historical context and for reports, this console is only
                    // interested in the current version of the negotiations.
                    Int64 maxVersion = Int64.MinValue;
                    ConsumerDebtNegotiationRow consumerDebtNegotiationRow = null;
                    foreach (ConsumerDebtNegotiationRow versionRow in matchRow.GetConsumerDebtNegotiationRows())
                    {
                        if (versionRow.Version > maxVersion)
                        {
                            maxVersion = versionRow.Version;
                            consumerDebtNegotiationRow = versionRow;
                        }
                    }

                    // At this point the latest version of the negotiations has been found.  Extract the scalar items used in the negotiation of a settlement.
                    this.NegotiationItem = new NegotiationItem(consumerDebtNegotiationRow);

                    // The Offer Payment Methods are a vector and need to be copied iteratively.
                    foreach (ConsumerDebtNegotiationOfferPaymentMethodRow paymentMethod in
                             consumerDebtNegotiationRow.GetConsumerDebtNegotiationOfferPaymentMethodRows())
                    {
                        this.OfferPaymentMethods.Add(paymentMethod.PaymentMethodTypeId);
                    }

                    // The Conter Offer Payment methods are also a vector.
                    foreach (ConsumerDebtNegotiationCounterPaymentMethodRow paymentMethod in
                             consumerDebtNegotiationRow.GetConsumerDebtNegotiationCounterPaymentMethodRows())
                    {
                        this.CounterPaymentMethods.Add(paymentMethod.PaymentMethodTypeId);
                    }

                    // When the console is initialized it is populated with every dialog item that has occurred for this match.
                    foreach (ChatRow chatRow in matchRow.GetChatRows())
                    {
                        ChatItem chatItem = new ChatItem();
                        chatItem.CreatedTime = chatRow.CreatedTime;
                        chatItem.IsReply     = chatRow.IsReply;
                        chatItem.MatchId     = matchId;
                        chatItem.Message     = chatRow.Message;
                        this.ChatItemList.Add(chatItem);
                    }
                }
            }
        }