public static IBalance Subtract(this IBalance endBalance, IBalance startBalance) { // Performance.MarkStart("BalanceHelper.Subtract"); var balance = new Balance(); balance.Index = endBalance.Index; balance.Book = endBalance.Book; foreach (var endBalanceItem in endBalance.Items) { var startBalanceItem = startBalance.Items.GetBalanceItem(endBalanceItem.Account); var balanceItem = new BalanceItem(); if (startBalanceItem != null) { if (!endBalanceItem.Asset.Equals(startBalanceItem.Asset)) { throw new ValidationException("Assets not equal."); } balanceItem.Asset = endBalanceItem.Asset; balanceItem.Account = endBalanceItem.Account; balanceItem.Balance = endBalance; var totalDebit = endBalanceItem.TotalDebit - startBalanceItem.TotalDebit; var totalCredit = endBalanceItem.TotalCredit - startBalanceItem.TotalCredit; if (totalDebit < 0) { totalCredit -= totalDebit; totalDebit = 0; } if (totalCredit < 0) { totalDebit -= totalCredit; totalCredit = 0; } balanceItem.TotalDebit = totalDebit; balanceItem.TotalCredit = totalCredit; } else { balanceItem = (BalanceItem)endBalanceItem; } balance.Items.Add(balanceItem); } // Performance.MarkEnd("BalanceHelper.Subtract"); return(balance); }
public static void Copy(this IBalance sourceBalance, IBalance destinationBalance, IAccountMap accountMap) { // Performance.MarkStart("BalanceHelper.Copy(balance)"); var sourceAccounts = new List <IAccount>(sourceBalance.Items.Select(balanceItem => balanceItem.Account)); var selectedAccounts = new List <IAccount>(); foreach (var accountMapItem in accountMap.Items) { if (!accountMapItem.Book.Equals(sourceBalance.Book)) { continue; } var balanceItems = sourceBalance.Items.GetBalanceItems(accountMapItem.AccountPredicate); if (!balanceItems.Any()) { continue; } var newBalanceItem = new BalanceItem(); newBalanceItem.Balance = destinationBalance; newBalanceItem.Account = accountMapItem.Account; newBalanceItem.Asset = balanceItems.First().Asset; newBalanceItem.TotalDebit = balanceItems.Sum(balanceItem => balanceItem.TotalDebit); newBalanceItem.TotalCredit = balanceItems.Sum(balanceItem => balanceItem.TotalCredit); destinationBalance.Items.Add(newBalanceItem); selectedAccounts.AddRange(balanceItems.Select(balanceItem => balanceItem.Account)); } // Performance.MarkStart("BalanceHelper.Copy(balance):Validate"); var missedSourceAccounts = sourceAccounts.Except(selectedAccounts).ToList(); if (missedSourceAccounts.Any()) { throw new ValidationException($"Missed accounts:{Environment.NewLine}{string.Join(Environment.NewLine, missedSourceAccounts)}"); } var duplicateSelectedSourceAccounts = selectedAccounts.GroupBy(account => account).Where(group => group.Count() > 1).Select(group => group.Key).ToList(); if (duplicateSelectedSourceAccounts.Any()) { throw new ValidationException($"Duplicate selected accounts:{Environment.NewLine}{string.Join(Environment.NewLine, duplicateSelectedSourceAccounts)}"); } // Performance.MarkEnd("BalanceHelper.Copy(balance):Validate"); // Performance.MarkEnd("BalanceHelper.Copy(balance)"); }
public IEnumerable <IBalance> AddEntry(IEntry entry) { // Performance.MarkStart("Ledger.AddEntry"); // Performance.MarkStart("Ledger.AddEntry:Validate(entry)"); foreach (var entryValidator in EntryValidators) { entryValidator.Validate(entry); } // Performance.MarkEnd("Ledger.AddEntry:Validate(entry)"); var lastEntry = _store.GetLastEntry(); if (lastEntry != null && entry.Index.CompareTo(_store.GetLastEntry().Index) <= 0) { throw new ValidationException($"Entry ({entry}) cannot occur on or before the last entry ({lastEntry})."); } var balances = new List <IBalance>(); foreach (var entryItem in entry.Items) { var balance = balances.SingleOrDefault(x => x.Book.Equals(entryItem.Book)); if (balance == null) { balance = CreateBalance(entryItem.Book, entry.Index); balances.Add(balance); } var balanceItem = new BalanceItem(); balanceItem.Balance = balance; balanceItem.Account = entryItem.Account; balanceItem.Asset = entryItem.Asset; balanceItem.TotalDebit = entryItem.Debit; balanceItem.TotalCredit = entryItem.Credit; var existingBalanceItem = balance.Items.GetBalanceItem(entryItem.Account, entryItem.Asset); if (existingBalanceItem != null) { balanceItem.TotalDebit += existingBalanceItem.TotalDebit; balanceItem.TotalCredit += existingBalanceItem.TotalCredit; } balance.Items.AddOrUpdate(balanceItem, existingBalanceItem); } // Performance.MarkStart("Ledger.AddEntry:Validate(balance)"); foreach (var balance in balances) { foreach (var balanceValidator in BalanceValidators) { balanceValidator.Validate(balance); } } // Performance.MarkEnd("Ledger.AddEntry:Validate(balance)"); // Performance.MarkStart("Ledger.AddEntry:Store"); _store.Store(entry, balances); // Performance.MarkEnd("Ledger.AddEntry:Store"); // Performance.MarkEnd("Ledger.AddEntry"); return(balances); }