コード例 #1
0
        public bool IsPayback(long debtDealId)
        {
            DebtDealAnalysisRow ar
                = this.rdbc.DebtDealsAnalysis
                  .Where(dda => dda.DebtDealId == debtDealId)
                  .First();

            return(ar.IsPayback);
        }
コード例 #2
0
        public long Add(DebtDealRow deal)
        {
            /*
             *     *** Notes on parallel execution ***
             *
             * If two debt deals have 4 unique involved people id-s,
             * these same deals may be processed in parallel in this register
             * (but may need serialization while other registers handle
             * DebtDealAdded event).
             *
             * Need to consider validity of initialGiverDebtToTaker.
             *
             * Other cases:
             *  three unique involved id-s:
             *      same giver, different takers: => parallel-ok
             *
             *      different givers, same taker: => parallel-ok
             *
             *  two unique involved id-s:
             *      same giver, same taker => serialize (case a)
             *
             *      D1.giver = D2.taker, D1.taker = D2.giver
             *          => serialize (case b)
             *
             *
             * Here, parallel execution has to be serialized when register
             * has not finished processing two deals which match one of these:
             *     a) if giver and taker are the same for two deals,
             *        later deal must wait till earlier one is fully processed.
             *        (consider small and complete pay-back immediately
             *         followed by a big credit - if D1 is processed after D2
             *         was fully processed, big credit could be considered
             *         as mostly a GIFT, confusing it with a payback)
             *
             *     b) if D1.giver = D2.taker, D1.taker = D2.giver
             *        (consider pay and repay of the same amount -
             *         in case of parallel execution of both deals,
             *         payback could be missed and DB would get corrupt)
             */

            long addedDebtDealId;

            using (var transaction = this.dbc.Database.BeginTransaction()) {
                this.dbc.DebtDeals.Add(deal);
                this.dbc.SaveChanges(); // need deal.Id
                addedDebtDealId = deal.Id;

                decimal initialGiverDebtToTaker = GiverDebtToTaker();
                decimal?repayGiftAmount         = null;
                if (initialGiverDebtToTaker > 0m)
                {
                    repayGiftAmount
                        = Math.Max(0m,
                                   deal.Amount - initialGiverDebtToTaker);
                }

                var analysisRow = new DebtDealAnalysisRow()
                {
                    DebtDealId = deal.Id,
                    IsPayback  = initialGiverDebtToTaker > 0m
                };
                this.dbc.DebtDealsAnalysis.Add(analysisRow);
                this.dbc.SaveChanges();

                DebtDealReceived?.Invoke(this,
                                         new DebtDealReceivedEventData()
                {
                    Deal            = deal,
                    Analysis        = analysisRow,
                    RepayGiftAmount = repayGiftAmount
                });

                transaction.Commit();
            }

            DebtDealAdded?.Invoke(this,
                                  new DebtDealAddedEventData()
            {
                AddedDebtDealId = addedDebtDealId
            });

            return(addedDebtDealId);

            decimal GiverDebtToTaker()
            {
                return(this.dbc.CurrentDebts.Where(cd =>
                                                   cd.CreditorId == deal.TakerId &&
                                                   cd.DebtorId == deal.GiverId
                                                   ).Select(cd => cd.DebtTotal).FirstOrDefault());
            }
        }