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); }
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); }
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)); }
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); }
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); }
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; }
LedgerOperationStatus ILedger.CreateAccount(out AccountID id) { AccountLine accLine = new AccountLine { Balance = 0 }; id = accountsTable.Insert(accLine); return(LedgerOperationStatus.Success); }
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); }
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); }
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)); }
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); }
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); }
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); }
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); }
private void TransferInternal(AccountLine item, AccountLine candidate) { skbRepo.Remove(item); skbRepo.Remove(candidate); internalRepo.Add(item, candidate); }
public static bool MatchOnAll(AccountLine item, AccountLine candidate) { return(MatchOnMost(item, candidate) && item.Reference.Equals(candidate.Reference)); }
public ProcessResult(AccountLine item, bool anyChange) { this.list = new List <AccountLine>(); this.list.Add(item); this.AnyChange = anyChange; }
internal void Remove(AccountLine item) { lines.Remove(item); }
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)); }
public static bool MatchOnAll(AccountLine item, AccountLine candidate) { return MatchOnMost(item, candidate) && item.Reference.Equals(candidate.Reference); }
public ProcessResult(AccountLine item, bool anyChange) { this.list = new List<AccountLine>(); this.list.Add(item); this.AnyChange = anyChange; }