예제 #1
0
        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);
        }
예제 #2
0
        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)");
        }
예제 #3
0
        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);
        }