Beispiel #1
0
        /// <summary>
        /// Find the owner of a rule. If there isn't one, return Guid.Empty.
        /// </summary>
        /// <param name="ruleId">The DebtRuleId of the rule to get the owner of.</param>
        public Guid GetRuleOwner(Guid ruleId)
        {
            DebtRuleRow rule = DataModel.DebtRule.DebtRuleKey.Find(ruleId);

            if (rule != null)
            {
                return(GetRuleOwner(rule));
            }
            else
            {
                return(Guid.Empty);
            }
        }
        public override ErrorCode Delete(DebtRule record)
        {
            DataModel            dataModel   = new DataModel();
            DataModelTransaction transaction = DataModelTransaction.Current;

            if (record.RowId == null || DataModel.DebtRule.DebtRuleKey.Find(record.RowId) == null)
            {
                return(ErrorCode.RecordNotFound);
            }

            DebtRuleRow debtRuleRow = DataModel.DebtRule.DebtRuleKey.Find(record.RowId);

            return(this.DeleteRow(dataModel, transaction, debtRuleRow));
        }
Beispiel #3
0
        /// <summary>
        /// Create a new item from a table row.
        /// </summary>
        /// <param name="dataRow">A row from the debt rule table.</param>
        /// <returns>A new DebtRule object.</returns>
        protected override DebtRule New(DataRow dataRow)
        {
            DebtRule item = null;

            if (dataRow is DebtRuleRow)
            {
                DebtRuleRow baseRow = dataRow as DebtRuleRow;

                item = new DebtRule(baseRow);
            }
            else
            {
                throw new RowNotHandledException("row isn't the right kind of row");
            }

            return(item);
        }
Beispiel #4
0
        /// <summary>
        /// If the rule has not been modified, update it with an existing debt rule.
        /// </summary>
        /// <param name="rule">The debt rule row to update from.</param>
        public void Update(DebtRuleRow rule)
        {
            if (!this.modified && this.rowVersion != this.RowVersion)
            {
                this.DebtRuleId             = rule.DebtRuleId;
                this.Name                   = rule.Name;
                this.PaymentLength          = rule.PaymentLength;
                this.PaymentStartDateLength = rule.PaymentStartDateLength;
                this.PaymentStartDateUnitId = rule.PaymentStartDateUnitId;
                this.SettlementValue        = rule.SettlementValue;
                this.modified               = false;

                this.UpdatePaymentMethod(this.RetrievePaymentMethods());
            }

            this.rowVersion = rule.RowVersion;
        }
Beispiel #5
0
        /// <summary>
        /// Create a new debt rule based on an already existing debt rule.
        /// </summary>
        /// <param name="debtRuleRow">The debt rule from the DataModel to base this debt rule on.</param>
        public DebtRule(DebtRuleRow debtRuleRow)
        {
            this.isAutoSettled          = debtRuleRow.IsAutoSettled;
            this.modified               = false;
            this.delete                 = false;
            this.debtRuleId             = debtRuleRow.DebtRuleId;
            this.name                   = debtRuleRow.Name;
            this.paymentLength          = debtRuleRow.PaymentLength;
            this.paymentMethod          = new ObservableCollection <Guid>();
            this.paymentStartDateLength = debtRuleRow.PaymentStartDateLength;
            this.paymentStartDateUnitId = debtRuleRow.TimeUnitRow.TimeUnitId;
            this.settlementUnitId       = debtRuleRow.SettlementUnitId;
            this.settlementValue        = debtRuleRow.SettlementValue;
            this.rowVersion             = debtRuleRow.RowVersion;

            this.UpdatePaymentMethod(this.RetrievePaymentMethods());
            this.paymentMethod.CollectionChanged += OnPaymentMethodChanged;
        }
Beispiel #6
0
        /// <summary>
        /// Find the owner of a rule. If there isn't one, return null.
        /// </summary>
        /// <param name="rule">The debt rule to find the owner of, or Guid.Empty if no proper owner can be found.</param>
        public Guid GetRuleOwner(DebtRuleRow rule)
        {
            Guid debtClassId = Guid.Empty;

            if (rule != null)
            {
                DebtClassRow   debtClass = null;
                DebtRuleMapRow map       = DataModel.DebtRuleMap.FirstOrDefault(row => row.DebtRuleId == rule.DebtRuleId);

                if (map != null)
                {
                    debtClass   = DataModel.DebtClass.DebtClassKey.Find(map.DebtClassId);
                    debtClassId = debtClass.DebtClassId;
                }
            }

            return(debtClassId);
        }
        /// <summary>
        /// Delete a debt holder
        /// </summary>
        /// <returns>True for sucess</returns>
        public override ErrorCode Delete(ConsumerTrust record)
        {
            DataModel            dataModel   = new DataModel();
            DataModelTransaction transaction = DataModelTransaction.Current;

            if (record.RowId == null || DataModel.ConsumerTrust.ConsumerTrustKey.Find(record.RowId) == null)
            {
                return(ErrorCode.RecordNotFound);
            }

            ConsumerTrustRow consumerTrust = DataModel.ConsumerTrust.ConsumerTrustKey.Find(record.RowId);

            consumerTrust.AcquireReaderLock(transaction);
            Guid        debtId   = consumerTrust.ConsumerTrustId;
            ConsumerRow consumer = consumerTrust.ConsumerRow;
            DebtRuleRow debtRule = consumerTrust.DebtRuleRow;

            consumerTrust.ReleaseReaderLock(transaction.TransactionId);

#if false   // If we switch from explicitly deleting the working order to explicitly deleting the security, then we need this.
            if (!TradingSupport.HasAccess(transaction, debtId, AccessRight.Write))
            {
                return(ErrorCode.AccessDenied);
            }
#endif

            consumerTrust.AcquireWriterLock(transaction);
            if (consumerTrust.RowState != DataRowState.Deleted && consumerTrust.RowState != DataRowState.Detached)
            {
                dataModel.DestroyConsumerTrust(new object[] { consumerTrust.ConsumerTrustId }, record.RowVersion);
            }
            consumerTrust.ReleaseWriterLock(transaction.TransactionId);

            consumer.AcquireWriterLock(transaction);
            if (consumer.RowState != DataRowState.Deleted && consumer.RowState != DataRowState.Detached)
            {
                dataModel.DestroyConsumer(new object[] { consumer.ConsumerId }, consumer.RowVersion);
            }
            consumer.ReleaseWriterLock(transaction.TransactionId);

            if (debtRule != null)
            {
                debtRule.AcquireReaderLock(transaction);
                if (debtRule.RowState != DataRowState.Deleted && debtRule.RowState != DataRowState.Detached && debtRule.GetDebtRuleMapRows().Length == 0)
                {
                    DebtRulePersistence debtRulePersistence = new DebtRulePersistence();
                    Guid debtRuleId = debtRule.DebtRuleId;
                    long rowVersion = debtRule.RowVersion;
                    debtRule.ReleaseReaderLock(transaction.TransactionId);
                    debtRulePersistence.Delete(new Records.DebtRule {
                        RowId = debtRuleId, RowVersion = rowVersion
                    });
                }
                else
                {
                    debtRule.ReleaseReaderLock(transaction.TransactionId);
                }
            }

            return(ErrorCode.Success);
        }
Beispiel #8
0
        public ConsumerTrustMatchInfo(DataModelTransaction dataModelTransaction, WorkingOrderRow workingOrderRow)
        {
            // Initialize the object
            this.PaymentMethodTypes = new List <Guid>();

            // These rows are required for navigating through the asset.  Locks are acquired temporarily for them and released as soon as the Consumer Debt
            // information is collected.
            BlotterRow       blotterRow       = null;
            SecurityRow      securityRow      = null;
            ConsumerTrustRow consumerTrustRow = null;

            // The working order row is where everything starts. This is the asset that is to be matched against another.
            workingOrderRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);

            try
            {
                // The working order identifier is used when creating matches.
                this.WorkingOrderId = workingOrderRow.WorkingOrderId;
                // The underlying security is a Consumer Debt record.
                securityRow = workingOrderRow.SecurityRowByFK_Security_WorkingOrder_SecurityId;

                // The blotter row needs to be examined for this cross.
                blotterRow = workingOrderRow.BlotterRow;
            }
            finally
            {
                workingOrderRow.ReleaseReaderLock(dataModelTransaction.TransactionId);
            }


            securityRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);
            try
            {
                consumerTrustRow = securityRow.GetConsumerTrustRows()[0];
            }
            finally
            {
                securityRow.ReleaseReaderLock(dataModelTransaction.TransactionId);
            }


            DebtRuleRow debtRuleRow = null;

            // This row contains the actual asset that is to be matched.
            consumerTrustRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);
            try
            {
                // The savings balance is used when calculating the status of the match (whether there is enough funds in the account).
                this.SavingsBalance = consumerTrustRow.SavingsBalance;

                if (consumerTrustRow.IsDebtRuleIdNull() == false)
                {
                    // At this point a rule override was found on an asset and there's no need to search the Entity hierarchy.
                    debtRuleRow = consumerTrustRow.DebtRuleRow;
                }
            }
            finally
            {
                consumerTrustRow.ReleaseReaderLock(dataModelTransaction.TransactionId);
            }

            // This will attempt to find the debt rule associated with this credit card.  If there is no rule explicitly associated with the asset,
            // then the entity hierarchy is searched until a debt class is found that contains a rule.  When the rule is found, the values in that rule
            // will become the opening bid.
            DebtClassRow[] blotterRowDebtClassRows = null;
            blotterRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);
            try
            {
                // The blotter is required for adding matches to the data model once they are found.
                this.BlotterId = blotterRow.BlotterId;

                if (debtRuleRow == null)
                {
                    blotterRowDebtClassRows = blotterRow.GetDebtClassRows();
                }
            }
            finally
            {
                blotterRow.ReleaseReaderLock(dataModelTransaction.TransactionId);
            }

            if (debtRuleRow == null)
            {
                // At this point, the asset hasn't got an explicit rule, so the hierarchy will need to be searched.  There is only going to be one Debt
                // Class element associated with this blotter, but the iteration is an easier construct to work with than the equivalent array logic
                // for a single element.
                foreach (DebtClassRow debtClassRow in blotterRowDebtClassRows)
                {
                    // This variable will keep track of our current location as we crawl up the hierarchy.
                    DebtClassRow currentDebtClassRow = debtClassRow;
                    DebtClassRow nextDebtClassRow    = null;

                    // This will crawl up the hierarchy until a Debt Class is found with a rule.  This rule will provide the opening values for the
                    // bid on this negotiation.
                    do
                    {
                        // This will lock the current item in the hierarchy so it can be examined for a rule or, failing that, a parent element.
                        currentDebtClassRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);
                        Guid currentDebtClassRowDebtClassId;
                        try
                        {
                            currentDebtClassRowDebtClassId = currentDebtClassRow.DebtClassId;
                            if (currentDebtClassRow.IsDebtRuleIdNull() == false)
                            {
                                // At this point we have finally found a debt rule that can be used to start the negotiations.
                                debtRuleRow = currentDebtClassRow.DebtRuleRow;
                            }
                        }
                        finally
                        {
                            // The current Debt Class can be released.  At this point, every record that was locked to read the hiearchy has been
                            // released and the loop can either exit (when a rule is found) or move on to the parent Debt Class.
                            currentDebtClassRow.ReleaseReaderLock(dataModelTransaction.TransactionId);
                        }
                        // If the current Debt Class has no rule then the Entity Hierarchy is used to find the parent element.
                        if (debtRuleRow == null)
                        {
                            EntityTreeRow[] entityTreeRows;
                            // The entity is the root of all objects in the hierarchy.  From this object the path to the parent Debt Class can be
                            // navigated.
                            EntityRow entityRow = DataModel.Entity.EntityKey.Find(currentDebtClassRowDebtClassId);

                            // Each entity needs to be locked before the relation can be used.
                            entityRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);
                            try
                            {
                                entityTreeRows = entityRow.GetEntityTreeRowsByFK_Entity_EntityTree_ChildId();
                            }
                            finally
                            {
                                // Finaly, the current entity is released.  This allows us to finally move on to the next level of the hierarchy
                                // without having to hold the locks for the entire transaction.
                                entityRow.ReleaseReaderLock(dataModelTransaction.TransactionId);
                            }

                            // This will find each relation in the hierarchy which uses the current node as a child.
                            foreach (EntityTreeRow entityTreeRow in entityTreeRows)
                            {
                                EntityRow parentEntityRow;
                                // Lock the relation down before navigating to the parent.
                                entityTreeRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);
                                try
                                {
                                    // This is the parent entity of the current entity in the crawl up the hierarchy.
                                    parentEntityRow = entityTreeRow.EntityRowByFK_Entity_EntityTree_ParentId;
                                }
                                finally
                                {
                                    // The relationship record is released after each level of the hierarchy is examined for a parent.
                                    entityTreeRow.ReleaseReaderLock(dataModelTransaction.TransactionId);
                                }

                                BlotterRow[] blotterRows;
                                // The parent entity must be locked befor it can be checked for blotters and then, in turn, debt
                                // classes.
                                parentEntityRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);
                                try
                                {
                                    blotterRows = parentEntityRow.GetBlotterRows();
                                }
                                finally
                                {
                                    // The parent Entity record is released after each level of the hiearchy is examined for a parent.
                                    parentEntityRow.ReleaseReaderLock(dataModelTransaction.TransactionId);
                                }


                                // In practice, there will be zero or one blotter rows.  The iteration makes it easier to check both
                                // conditions.
                                foreach (BlotterRow parentBlotterRow in blotterRows)
                                {
                                    DebtClassRow[] parentBlotterRowDebtClassRows;
                                    // The blotter must be locked before iterating through the Debt Classes that may be associated
                                    // with the blotter.
                                    parentBlotterRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);
                                    try
                                    {
                                        parentBlotterRowDebtClassRows = parentBlotterRow.GetDebtClassRows();
                                    }
                                    finally
                                    {
                                        // The locks are released after the each level of the hierarchy is checked.
                                        parentBlotterRow.ReleaseReaderLock(dataModelTransaction.TransactionId);
                                    }

                                    // Each blotter can have zero or one Debt Classes associated with it.  This is a long an
                                    // tortuous way to finally get to the parent Debt Class.
                                    foreach (DebtClassRow parentDebtClassRow in parentBlotterRowDebtClassRows)
                                    {
                                        // Now that we've finally found the parent Debt Class, it will become the parent on
                                        // the next pass through the hierarchy.  Note that the locks are released each time we
                                        // pass through a level of the hierarchy.
                                        nextDebtClassRow = parentDebtClassRow;
                                    }
                                }
                            }
                        }

                        // Now that all the locks are released, the parent Debt Class becomes the current one for the next level up in the hierarchy.
                        // This algorithm will keep on climbing through the levels until a rule is found or the hierarchy is exhausted.
                        currentDebtClassRow = nextDebtClassRow;
                    } while(debtRuleRow == null && currentDebtClassRow != null);
                }
            }

            // The data is copied out of the Debt Rule when one is found in the Entity hierarchy.
            if (debtRuleRow != null)
            {
                DebtRulePaymentMethodRow[] debtRuleRowDebtRulePaymentMethodRows;
                // At this point we found a rule that can be used for the opening bid of a settlement.
                debtRuleRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);
                try
                {
                    // These values are used in the opening bid of a negotiated settlement.
                    this.PaymentLength          = debtRuleRow.PaymentLength;
                    this.PaymentStartDateLength = debtRuleRow.PaymentStartDateLength;
                    this.PaymentStartDateUnitId = debtRuleRow.PaymentStartDateUnitId;
                    this.SettlementValue        = debtRuleRow.SettlementValue;
                    this.SettlementUnitId       = debtRuleRow.SettlementUnitId;

                    debtRuleRowDebtRulePaymentMethodRows = debtRuleRow.GetDebtRulePaymentMethodRows();
                }
                finally
                {
                    // A lock on the Debt Rule is no longer required.
                    debtRuleRow.ReleaseReaderLock(dataModelTransaction.TransactionId);
                }


                // This will copy each of the payment methods that are available for this settlement.  Note that the table rows are locked only long
                // enough to acquire the item, then released.
                foreach (DebtRulePaymentMethodRow debtRulePaymentMethodRow in debtRuleRowDebtRulePaymentMethodRows)
                {
                    debtRulePaymentMethodRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);
                    try
                    {
                        this.PaymentMethodTypes.Add(debtRulePaymentMethodRow.PaymentMethodTypeId);
                    }
                    finally
                    {
                        debtRulePaymentMethodRow.ReleaseReaderLock(dataModelTransaction.TransactionId);
                    }
                }
            }
        }
        public override void Update(DebtRule record)
        {
            DataModel            dataModelClient = new DataModel();
            DataModelTransaction transaction     = DataModelTransaction.Current;
            DebtRuleRow          debtRuleRow     = DataModel.DebtRule.DebtRuleKey.Find(record.RowId);

            DebtRuleMapRow[] debtRuleMapRows;
            List <Guid>      paymentMethod = record.PaymentMethod.ToList();

            if (record.RowId == null || debtRuleRow == null)
            {
                throw new FaultException <RecordNotFoundFault>(new RecordNotFoundFault("DebtRule", new object[] { record.RowId }), "DebtRule could not be found");
            }

            debtRuleRow.AcquireReaderLock(transaction);
            debtRuleMapRows = debtRuleRow.GetDebtRuleMapRows();

            // There really should be at most one of these, but there may be none.
            foreach (DebtRuleMapRow debtRuleMapRow in debtRuleMapRows)
            {
                debtRuleMapRow.AcquireReaderLock(transaction);
                if (!DataModelFilters.HasAccess(transaction, TradingSupport.UserId, debtRuleMapRow.DebtClassId, AccessRight.Write))
                {
                    throw new SecurityAccessDeniedException("Current user does not have right access to the debt class that owns this debt rule");
                }
                debtRuleMapRow.ReleaseLock(transaction.TransactionId);
            }

            foreach (DebtRulePaymentMethodRow methodRow in debtRuleRow.GetDebtRulePaymentMethodRows())
            {
                methodRow.AcquireReaderLock(transaction);
                if (paymentMethod.Contains(methodRow.PaymentMethodTypeId))
                {
                    paymentMethod.Remove(methodRow.PaymentMethodTypeId);
                }
                else
                {
                    dataModelClient.DestroyDebtRulePaymentMethod(new object[] { methodRow.DebtRulePaymentMethodId }, methodRow.RowVersion);
                }
                methodRow.ReleaseLock(transaction.TransactionId);
            }

            foreach (Guid method in paymentMethod)
            {
                dataModelClient.CreateDebtRulePaymentMethod(record.RowId, Guid.NewGuid(), method);
            }

            debtRuleRow.ReleaseLock(transaction.TransactionId);

            dataModelClient.UpdateDebtRule(
                null,
                new object[] { record.RowId },
                null,
                record.IsAutoSettled,
                record.Name,
                record.PaymentLength,
                record.PaymentStartDateLength,
                record.PaymentStartDateUnitId,
                record.RowVersion,
                record.SettlementUnitId,
                record.SettlementValue);
            debtRuleRow.ReleaseLock(transaction.TransactionId);
        }
        public ErrorCode DeleteRow(DataModel dataModel, DataModelTransaction transaction, DebtRuleRow debtRuleRow)
        {
            debtRuleRow.AcquireReaderLock(transaction);
            DebtRuleMapRow[] debtRuleMaps = debtRuleRow.GetDebtRuleMapRows();

            if (debtRuleRow.GetDebtClassRows().Length != 0)
            {
                return(ErrorCode.AccessDenied);
            }
            debtRuleRow.ReleaseReaderLock(transaction.TransactionId);

            foreach (DebtRuleMapRow debtRuleMapRow in debtRuleMaps)
            {
                debtRuleMapRow.AcquireReaderLock(transaction);
                if (!DataModelFilters.HasAccess(transaction, TradingSupport.UserId, debtRuleMapRow.DebtClassId, AccessRight.Write))
                {
                    return(ErrorCode.AccessDenied);
                }
                debtRuleMapRow.ReleaseReaderLock(transaction.TransactionId);
            }

            debtRuleRow.AcquireWriterLock(transaction);
            dataModel.DestroyDebtRule(new object[] { debtRuleRow.DebtRuleId }, debtRuleRow.RowVersion);
            debtRuleRow.ReleaseLock(transaction.TransactionId);

            return(ErrorCode.Success);
        }