示例#1
0
        LedgerOperationStatus ILedger.RemoveFunds(AccountID accountID, decimal balance)
        {
            LedgerOperationStatus status      = LedgerOperationStatus.Success;
            TransactionLine       transaction = new TransactionLine(accountID,
                                                                    balance,
                                                                    LedgerDatabase.TransactionType.RemoveFunds);

            //find account line, lock it, update
            if (accountsTable.Contains(accountID))
            {
                AccountLine account = accountsTable.Select(accountID);
                lock (account)
                {
                    if (balance > account.Balance)
                    {
                        transaction.Status       = LedgerDatabase.TransactionStatus.Rejected;
                        transaction.RejectReason = TransactionRejectReason.InsufficientFunds;
                        status = LedgerOperationStatus.InsufficientFunds;
                    }
                    else
                    {
                        account.Balance -= balance;
                    }
                }
            }
            else
            {
                transaction.Status       = LedgerDatabase.TransactionStatus.Rejected;
                transaction.RejectReason = TransactionRejectReason.InvalidAccount;
                status = LedgerOperationStatus.InvalidAccount;
            }

            transactionsTable.Insert(transaction);
            return(status);
        }
示例#2
0
 public static bool MatchOnMost(AccountLine item, AccountLine candidate)
 {
     SimpleMoney total = item.ActualAmount + candidate.ActualAmount;
     return item.Date.Equals(candidate.Date)
         && total.Equals(SimpleMoney.Zero)
         && item.Desc.Equals(candidate.Desc);
 }
示例#3
0
        public static bool MatchOnMost(AccountLine item, AccountLine candidate)
        {
            SimpleMoney total = item.ActualAmount + candidate.ActualAmount;

            return(item.Date.Equals(candidate.Date) &&
                   total.Equals(SimpleMoney.Zero) &&
                   item.Desc.Equals(candidate.Desc));
        }
示例#4
0
 private MatchResult FindCandidateMatches(AccountLine item)
 {
     List<AccountLine> foundCandidates = new List<AccountLine>();
     foreach (var candidate in skbRepo.GetAll())
     {
         if (this.match(item, candidate)) foundCandidates.Add(candidate);
     }
     return new MatchResult(foundCandidates);
 }
示例#5
0
        LedgerOperationStatus ILedger.TransferFunds(AccountID srcAccountID, AccountID tgtAccountID, decimal balance)
        {
            LedgerOperationStatus status   = LedgerOperationStatus.Success;
            TransactionLine       srcTrans = new TransactionLine(srcAccountID,
                                                                 balance,
                                                                 LedgerDatabase.TransactionType.RemoveFunds, TransactionSubType.TransferFunds);
            TransactionLine tgtTrans = new TransactionLine(tgtAccountID,
                                                           balance,
                                                           LedgerDatabase.TransactionType.AddFunds, TransactionSubType.TransferFunds);

            lock (transactionsTable)
            {
                srcTrans.TransferId = tgtTrans.TransferId = ++transferID;
            }

            if (accountsTable.Contains(srcAccountID) && accountsTable.Contains(tgtAccountID))
            {
                AccountLine accSrc = accountsTable.Select(srcAccountID);
                AccountLine accTgt = accountsTable.Select(tgtAccountID);

                AccountLine firstAccToLock = accSrc, secondAccToLock = accTgt;
                if (srcAccountID > tgtAccountID) // avoid deadlocks by always locking at the same order
                {
                    firstAccToLock  = accTgt;
                    secondAccToLock = accSrc;
                }

                lock (firstAccToLock)
                {
                    lock (secondAccToLock)
                    {
                        if (balance > accSrc.Balance)
                        {
                            srcTrans.Status       = tgtTrans.Status = LedgerDatabase.TransactionStatus.Rejected;
                            srcTrans.RejectReason = tgtTrans.RejectReason = TransactionRejectReason.InsufficientFunds;
                            status = LedgerOperationStatus.InsufficientFunds;
                        }
                        else
                        {
                            accSrc.Balance -= balance;
                            accTgt.Balance += balance;
                        }
                    }
                }
            }
            else
            {
                srcTrans.Status       = tgtTrans.Status = LedgerDatabase.TransactionStatus.Rejected;
                srcTrans.RejectReason = tgtTrans.RejectReason = TransactionRejectReason.InvalidAccount;
                status = LedgerOperationStatus.InvalidAccount;
            }

            transactionsTable.Insert(srcTrans);
            transactionsTable.Insert(tgtTrans);
            return(status);
        }
示例#6
0
        private ProcessResult ProcessItem(AccountLine item)
        {
            bool anythingChanged = false;
            MatchResult result = FindCandidateMatches(item);
            if (result.HasMultipleCandidates) return new ProcessResult(item, false);
            if (result.HasNoResults) return ProcessResult.End;

            TransferInternal(item, result.BestCandidate);
            return ProcessResult.SomethingChanged;
        }
示例#7
0
        LedgerOperationStatus ILedger.CreateAccount(out AccountID id)
        {
            AccountLine accLine = new AccountLine
            {
                Balance = 0
            };

            id = accountsTable.Insert(accLine);

            return(LedgerOperationStatus.Success);
        }
示例#8
0
        private static AccountLine FromCsv(string csvLine)
        {
            var values      = csvLine.Split(',');
            var accountLine = new AccountLine
            {
                AccountId = values[0],
                FirstName = values[1],
                LastName  = values[2]
            };

            return(accountLine);
        }
示例#9
0
        private void StripDesc(AccountLine item, Regex regex)
        {
            string original = item.Desc;
            string updated  = regex.Replace(original, "");

            AccountLine res = new AccountLine(item.Date, item.Reference, item.Type, updated, item.Amount, item.ActualAmount, item.AccountName);

            //Reporter.WriteLine("{0}\n{1}\n", item.Desc, res.Desc);
            //Reporter.WriteLine("{0}", res.Desc);
            SkbRepo.Remove(item);
            SkbRepo.Add(res);
        }
示例#10
0
        private MatchResult FindCandidateMatches(AccountLine item)
        {
            List <AccountLine> foundCandidates = new List <AccountLine>();

            foreach (var candidate in skbRepo.GetAll())
            {
                if (this.match(item, candidate))
                {
                    foundCandidates.Add(candidate);
                }
            }
            return(new MatchResult(foundCandidates));
        }
示例#11
0
        LedgerOperationStatus ILedger.UnfreezeFunds(AccountID accountID, out decimal balance, UInt64 freezeID)
        {
            LedgerOperationStatus status = LedgerOperationStatus.Success;
            //prepare AddFunds/Unfreeze transaction
            TransactionLine transaction = new TransactionLine(accountID,
                                                              0,
                                                              LedgerDatabase.TransactionType.AddFunds, TransactionSubType.Unfreeze);

            if (accountsTable.Contains(accountID))
            {
                AccountLine account = accountsTable.Select(accountID);
                lock (account)
                {
                    if (frozenBalancesTable.Contains(freezeID))
                    {
                        FrozenBalanceLine frozenBalance = frozenBalancesTable.Select(freezeID);
                        balance = frozenBalance.Balance;
                        if (frozenBalance.AccountId != accountID)
                        {
                            transaction.Status       = LedgerDatabase.TransactionStatus.Rejected;
                            transaction.RejectReason = TransactionRejectReason.InvalidAccount;
                            status = LedgerOperationStatus.InvalidAccount;
                        }
                        else
                        {
                            //update account balance and delete freeze record
                            account.Balance += frozenBalance.Balance;
                            frozenBalancesTable.Delete(freezeID);
                        }
                    }
                    else
                    {
                        balance                  = 0;
                        transaction.Status       = LedgerDatabase.TransactionStatus.Rejected;
                        transaction.RejectReason = TransactionRejectReason.InvalidFreezeID;
                        status = LedgerOperationStatus.InvalidFreezeID;
                    }
                }
            }
            else
            {
                balance                  = 0;
                transaction.Status       = LedgerDatabase.TransactionStatus.Rejected;
                transaction.RejectReason = TransactionRejectReason.InvalidAccount;
                status = LedgerOperationStatus.InvalidAccount;
            }

            transactionsTable.Insert(transaction);
            return(status);
        }
示例#12
0
        private ProcessResult ProcessItem(AccountLine item)
        {
            bool        anythingChanged = false;
            MatchResult result          = FindCandidateMatches(item);

            if (result.HasMultipleCandidates)
            {
                return(new ProcessResult(item, false));
            }
            if (result.HasNoResults)
            {
                return(ProcessResult.End);
            }

            TransferInternal(item, result.BestCandidate);
            return(ProcessResult.SomethingChanged);
        }
示例#13
0
        LedgerOperationStatus ILedger.GetAccountBalance(AccountID accountID, out decimal balance)
        {
            LedgerOperationStatus status = LedgerOperationStatus.Success;

            if (accountsTable.Contains(accountID))
            {
                AccountLine account = accountsTable.Select(accountID);
                lock (account)
                {
                    balance = account.Balance;
                }
            }
            else
            {
                balance = 0;
                status  = LedgerOperationStatus.InvalidAccount;
            }
            return(status);
        }
示例#14
0
        LedgerOperationStatus ILedger.FreezeFunds(AccountID accountID, decimal balance, out FreezeID freezeID)
        {
            LedgerOperationStatus status = LedgerOperationStatus.Success;
            //prepare RemoveFunds/Freeze transaction
            TransactionLine transaction = new TransactionLine(accountID,
                                                              balance,
                                                              LedgerDatabase.TransactionType.RemoveFunds, TransactionSubType.Freeze);

            if (accountsTable.Contains(accountID))
            {
                AccountLine account = accountsTable.Select(accountID);
                lock (account)
                {
                    if (balance > account.Balance)
                    {
                        freezeID                 = 0;
                        transaction.Status       = LedgerDatabase.TransactionStatus.Rejected;
                        transaction.RejectReason = TransactionRejectReason.InsufficientFunds;
                        status = LedgerOperationStatus.InsufficientFunds;
                    }
                    else
                    {
                        //update account balance and add freeze record
                        account.Balance -= balance;
                        FrozenBalanceLine frozenBalance = new FrozenBalanceLine(accountID, balance);
                        freezeID = frozenBalancesTable.Insert(frozenBalance);
                    }
                }
            }
            else
            {
                freezeID                 = 0;
                transaction.Status       = LedgerDatabase.TransactionStatus.Rejected;
                transaction.RejectReason = TransactionRejectReason.InvalidAccount;
                status = LedgerOperationStatus.InvalidAccount;
            }

            transactionsTable.Insert(transaction);
            return(status);
        }
示例#15
0
 private void TransferInternal(AccountLine item, AccountLine candidate)
 {
     skbRepo.Remove(item);
     skbRepo.Remove(candidate);
     internalRepo.Add(item, candidate);
 }
示例#16
0
 private void TransferInternal(AccountLine item, AccountLine candidate)
 {
     skbRepo.Remove(item);
     skbRepo.Remove(candidate);
     internalRepo.Add(item, candidate);
 }
示例#17
0
 public static bool MatchOnAll(AccountLine item, AccountLine candidate)
 {
     return(MatchOnMost(item, candidate) && item.Reference.Equals(candidate.Reference));
 }
示例#18
0
 public ProcessResult(AccountLine item, bool anyChange)
 {
     this.list = new List <AccountLine>();
     this.list.Add(item);
     this.AnyChange = anyChange;
 }
示例#19
0
 internal void Remove(AccountLine item)
 {
     lines.Remove(item);
 }
示例#20
0
 internal void Add(AccountLine line)
 {
     lines.Add(line);
 }
 internal InternalTransaction(AccountLine item1, AccountLine item2)
 {
     Item1 = item1;
     Item2 = item2;
 }
 internal void Add(AccountLine item, AccountLine candidate)
 {
     lines.Add(new InternalTransaction(item, candidate));
 }
 internal void Add(AccountLine item, AccountLine candidate)
 {
     lines.Add(new InternalTransaction(item, candidate));
 }
示例#24
0
 internal void Add(AccountLine line)
 {
     lines.Add(line);
 }
示例#25
0
 internal void Remove(AccountLine item)
 {
     lines.Remove(item);
 }
示例#26
0
 public static bool MatchOnAll(AccountLine item, AccountLine candidate)
 {
     return MatchOnMost(item, candidate) && item.Reference.Equals(candidate.Reference);
 }
 internal InternalTransaction(AccountLine item1, AccountLine item2)
 {
     Item1 = item1;
     Item2 = item2;
 }
示例#28
0
 public ProcessResult(AccountLine item, bool anyChange)
 {
     this.list = new List<AccountLine>();
     this.list.Add(item);
     this.AnyChange = anyChange;
 }