Example #1
0
 public Task closing_an_open_period(YearMonth openedOn, EquityAccount retainedEarnings,
                                    GeneralLedgerEntryIdentifier[] generalLedgerEntryIdentifiers,
                                    GeneralLedgerEntryIdentifier closingGeneralLedgerEntryIdentifier) =>
 new Scenario()
 .Given(ChartOfAccounts.Identifier, new AccountDefined {
     AccountNumber = retainedEarnings.AccountNumber.ToInt32(),
     AccountName   = retainedEarnings.AccountName.ToString()
 })
 .Given(GeneralLedger.Identifier, new GeneralLedgerOpened {
     OpenedOn = Time.Format.LocalDate(openedOn.OnDayOfMonth(1))
 })
 .When(new BeginClosingAccountingPeriod {
     GeneralLedgerEntryIds =
         ImmutableArray <Guid> .Empty.AddRange(Array.ConvertAll(generalLedgerEntryIdentifiers,
                                                                x => x.ToGuid())),
     ClosingOn = openedOn.OnDayOfMonth(2).AtMidnight().ToDateTimeUnspecified(),
     RetainedEarningsAccountNumber = retainedEarnings.AccountNumber.ToInt32(),
     ClosingGeneralLedgerEntryId   = closingGeneralLedgerEntryIdentifier.ToGuid()
 })
 .Then(GeneralLedger.Identifier, new AccountingPeriodClosing {
     Period = AccountingPeriod.Open(openedOn.OnDayOfMonth(1)).ToString(),
     GeneralLedgerEntryIds         = Array.ConvertAll(generalLedgerEntryIdentifiers, x => x.ToGuid()),
     ClosingOn                     = Time.Format.LocalDateTime(openedOn.OnDayOfMonth(2).AtMidnight()),
     RetainedEarningsAccountNumber = retainedEarnings.AccountNumber.ToInt32(),
     ClosingGeneralLedgerEntryId   = closingGeneralLedgerEntryIdentifier.ToGuid()
 })
 .Assert(_handler, _facts);
 public Task when_a_general_ledger_entry_was_created(GeneralLedgerEntryIdentifier generalLedgerEntryIdentifier,
                                                     Period period) => new NpgsqlProjectionScenario(new BalanceSheetReportProjection())
 .Given(new CreateSchema())
 .Given(new GeneralLedgerEntryCreated {
     GeneralLedgerEntryId = generalLedgerEntryIdentifier.ToGuid(),
     Period = period.ToString()
 })
 .Then(_schema, "balance_sheet_general_ledger_entry_period", new BalanceSheetReportProjection.GeneralLedgerEntryPeriod {
     PeriodMonth          = period.Month,
     PeriodYear           = period.Year,
     GeneralLedgerEntryId = generalLedgerEntryIdentifier.ToGuid()
 })
 .Assert();
        public Task entry_not_in_balance_throws(GeneralLedgerEntryIdentifier generalLedgerEntryIdentifier,
                                                int sequenceNumber, LocalDate openedOn, AccountName accountName, AccountNumber accountNumber)
        {
            var scenario = new Scenario()
                           .Given(GeneralLedger.Identifier,
                                  new GeneralLedgerOpened {
                OpenedOn = Time.Format.LocalDate(openedOn)
            })
                           .Given(ChartOfAccounts.Identifier,
                                  new AccountDefined {
                AccountName   = accountName.ToString(),
                AccountNumber = accountNumber.ToInt32()
            })
                           .When(new PostGeneralLedgerEntry {
                Period = AccountingPeriod.Open(openedOn).ToString(),
                BusinessTransaction = new BadTransaction {
                    Account         = accountNumber,
                    ReferenceNumber = sequenceNumber
                },
                CreatedOn            = openedOn.ToDateTimeUnspecified(),
                GeneralLedgerEntryId = generalLedgerEntryIdentifier.ToGuid()
            })
                           .Throws(new GeneralLedgerEntryNotInBalanceException(generalLedgerEntryIdentifier));

            _writer.Write(scenario.Build());
            return(scenario.Assert(new GeneralLedgerEntryHandlers(new GeneralLedgerTestRepository(_facts),
                                                                  new GeneralLedgerEntryTestRepository(_facts),
                                                                  _ => false), _facts));
        }
Example #4
0
        public Task entry_not_in_balance_throws(GeneralLedgerEntryIdentifier generalLedgerEntryIdentifier,
                                                int sequenceNumber, DateTimeOffset openedOn, AccountName accountName, AccountNumber accountNumber)
        {
            var scenario = new Scenario()
                           .Given("generalLedger",
                                  new GeneralLedgerOpened {
                OpenedOn = openedOn
            })
                           .Given("chartOfAccounts",
                                  new AccountDefined {
                AccountName   = accountName.ToString(),
                AccountNumber = accountNumber.ToInt32()
            })
                           .When(new PostGeneralLedgerEntry {
                Period = Period.Open(openedOn).ToString(),
                BusinessTransaction = new BadTransaction {
                    Account         = accountNumber,
                    ReferenceNumber = sequenceNumber
                },
                CreatedOn            = openedOn,
                GeneralLedgerEntryId = generalLedgerEntryIdentifier.ToGuid()
            })

                           .Throws(new GeneralLedgerEntryNotInBalanceException(generalLedgerEntryIdentifier));

            _writer.Write(scenario.Build());
            return(scenario.Assert(_handler, _facts));
        }
Example #5
0
 public Task closing_a_closed_period(Period period,
                                     GeneralLedgerEntryIdentifier closingGeneralLedgerEntryIdentifier) =>
 new Scenario()
 .Given("generalLedger", new GeneralLedgerOpened {
     OpenedOn = new DateTimeOffset(new DateTime(period.Year, period.Month, 1))
 },
        new AccountingPeriodClosing {
     Period    = period.ToString(),
     ClosingOn = new DateTimeOffset(new DateTime(period.Year, period.Month, 2)),
     RetainedEarningsAccountNumber = _retainedEarnings.ToInt32(),
     ClosingGeneralLedgerEntryId   = closingGeneralLedgerEntryIdentifier.ToGuid()
 })
 .When(new BeginClosingAccountingPeriod {
     ClosingOn = new DateTimeOffset(new DateTime(period.Year, period.Month, 2)),
     RetainedEarningsAccountNumber = _retainedEarnings.ToInt32(),
     ClosingGeneralLedgerEntryId   = closingGeneralLedgerEntryIdentifier.ToGuid()
 })
 .Throws(new PeriodClosingInProcessException(period))
 .Assert(_handler, _facts);
 public Task when_the_general_ledger_entry_was_posted(
     GeneralLedgerEntryIdentifier generalLedgerEntryIdentifier,
     Period period,
     AccountNumber credit,
     AccountNumber debit,
     Money amount,
     int iterations) => new NpgsqlProjectionScenario(new BalanceSheetReportProjection())
 .Given(new CreateSchema())
 .Given(new GeneralLedgerEntryCreated {
     GeneralLedgerEntryId = generalLedgerEntryIdentifier.ToGuid(),
     Period = period.ToString()
 })
 .Given(Enumerable.Range(0, iterations).Select(_ => new DebitApplied {
     Amount               = amount.ToDecimal(),
     AccountNumber        = debit.ToInt32(),
     GeneralLedgerEntryId = generalLedgerEntryIdentifier.ToGuid()
 }))
 .Given(Enumerable.Range(0, iterations).Select(_ => new CreditApplied {
     Amount               = amount.ToDecimal(),
     AccountNumber        = credit.ToInt32(),
     GeneralLedgerEntryId = generalLedgerEntryIdentifier.ToGuid()
 }))
 .Given(new GeneralLedgerEntryPosted {
     GeneralLedgerEntryId = generalLedgerEntryIdentifier.ToGuid(),
     Period = period.ToString()
 })
 .Then(_schema, "balance_sheet_general_ledger_entry_period",
       Array.Empty <BalanceSheetReportProjection.GeneralLedgerEntryPeriod>())
 .Then(_schema, "balance_sheet_items_unposted",
       Array.Empty <BalanceSheetReportProjection.UnpostedGeneralLedgerEntryLine>())
 .Then(_schema, "balance_sheet_report", new BalanceSheetReportProjection.Item {
     Balance       = amount.ToDecimal() * iterations,
     PeriodMonth   = period.Month,
     PeriodYear    = period.Year,
     AccountNumber = debit.ToInt32()
 }, new BalanceSheetReportProjection.Item {
     Balance       = -amount.ToDecimal() * iterations,
     PeriodMonth   = period.Month,
     PeriodYear    = period.Year,
     AccountNumber = credit.ToInt32()
 })
 .Assert();
Example #7
0
 public Task closing_an_open_period(Period period,
                                    GeneralLedgerEntryIdentifier[] generalLedgerEntryIdentifiers,
                                    GeneralLedgerEntryIdentifier closingGeneralLedgerEntryIdentifier) =>
 new Scenario()
 .Given("generalLedger", new GeneralLedgerOpened {
     OpenedOn = new DateTimeOffset(new DateTime(period.Year, period.Month, 2))
 })
 .When(new BeginClosingAccountingPeriod {
     GeneralLedgerEntryIds         = Array.ConvertAll(generalLedgerEntryIdentifiers, x => x.ToGuid()),
     ClosingOn                     = new DateTimeOffset(new DateTime(period.Year, period.Month, 2)),
     RetainedEarningsAccountNumber = _retainedEarnings.ToInt32(),
     ClosingGeneralLedgerEntryId   = closingGeneralLedgerEntryIdentifier.ToGuid()
 })
 .Then("generalLedger", new AccountingPeriodClosing {
     Period = period.ToString(),
     GeneralLedgerEntryIds         = Array.ConvertAll(generalLedgerEntryIdentifiers, x => x.ToGuid()),
     ClosingOn                     = new DateTimeOffset(new DateTime(period.Year, period.Month, 2)),
     RetainedEarningsAccountNumber = _retainedEarnings.ToInt32(),
     ClosingGeneralLedgerEntryId   = closingGeneralLedgerEntryIdentifier.ToGuid()
 })
 .Assert(_handler, _facts);
Example #8
0
 public Task closing_the_period_before_the_period_has_started(DateTimeOffset openedOn,
                                                              GeneralLedgerEntryIdentifier closingGeneralLedgerEntryIdentifier) =>
 new Scenario()
 .Given("generalLedger", new GeneralLedgerOpened {
     OpenedOn = openedOn
 })
 .When(new BeginClosingAccountingPeriod {
     ClosingOn = openedOn.AddMonths(-1),
     RetainedEarningsAccountNumber = _retainedEarnings.ToInt32(),
     ClosingGeneralLedgerEntryId   = closingGeneralLedgerEntryIdentifier.ToGuid()
 })
 .Throws(new ClosingDateBeforePeriodException(Period.Open(openedOn), openedOn.AddMonths(-1)))
 .Assert(_handler, _facts);
Example #9
0
 public Task closing_a_closed_period(YearMonth openedOn, EquityAccount retainedEarnings,
                                     GeneralLedgerEntryIdentifier closingGeneralLedgerEntryIdentifier) =>
 new Scenario()
 .Given(ChartOfAccounts.Identifier, new AccountDefined {
     AccountNumber = retainedEarnings.AccountNumber.ToInt32(),
     AccountName   = retainedEarnings.AccountName.ToString()
 })
 .Given(GeneralLedger.Identifier, new GeneralLedgerOpened {
     OpenedOn = Time.Format.LocalDate(openedOn.OnDayOfMonth(1))
 },
        new AccountingPeriodClosing {
     Period    = AccountingPeriod.Open(openedOn.OnDayOfMonth(1)).ToString(),
     ClosingOn = Time.Format.LocalDateTime(openedOn.OnDayOfMonth(2).AtMidnight()),
     RetainedEarningsAccountNumber = retainedEarnings.AccountNumber.ToInt32(),
     ClosingGeneralLedgerEntryId   = closingGeneralLedgerEntryIdentifier.ToGuid()
 })
 .When(new BeginClosingAccountingPeriod {
     ClosingOn = openedOn.OnDayOfMonth(2).AtMidnight().ToDateTimeUnspecified(),
     RetainedEarningsAccountNumber = retainedEarnings.AccountNumber.ToInt32(),
     ClosingGeneralLedgerEntryId   = closingGeneralLedgerEntryIdentifier.ToGuid()
 })
 .Throws(new PeriodClosingInProcessException(AccountingPeriod.Open(openedOn.OnDayOfMonth(1))))
 .Assert(_handler, _facts);
        public Task unposted_entry_throws(LocalDate openedOn, GeneralLedgerEntryNumber generalLedgerEntryNumber,
                                          EquityAccount retainedEarnings, GeneralLedgerEntryIdentifier generalLedgerEntryIdentifier,
                                          GeneralLedgerEntryIdentifier closingGeneralLedgerEntryIdentifier)
        {
            var period    = AccountingPeriod.Open(openedOn);
            var closingOn = openedOn.AtMidnight();

            var accountingPeriodClosing = new AccountingPeriodClosing {
                Period    = period.ToString(),
                ClosingOn = Time.Format.LocalDateTime(closingOn),
                RetainedEarningsAccountNumber = retainedEarnings.AccountNumber.ToInt32(),
                ClosingGeneralLedgerEntryId   = closingGeneralLedgerEntryIdentifier.ToGuid(),
                GeneralLedgerEntryIds         = new[] { generalLedgerEntryIdentifier.ToGuid() }
            };

            return(new Scenario()
                   .Given(GeneralLedger.Identifier,
                          new GeneralLedgerOpened {
                OpenedOn = Time.Format.LocalDate(openedOn)
            },
                          accountingPeriodClosing)
                   .Given(ChartOfAccounts.Identifier,
                          new AccountDefined {
                AccountName = retainedEarnings.AccountName.ToString(),
                AccountNumber = retainedEarnings.AccountNumber.ToInt32()
            })
                   .Given(GeneralLedgerEntry.FormatStreamIdentifier(generalLedgerEntryIdentifier),
                          new GeneralLedgerEntryCreated {
                GeneralLedgerEntryId = generalLedgerEntryIdentifier.ToGuid(),
                Number = generalLedgerEntryNumber.ToString(),
                Period = period.ToString(),
                CreatedOn = Time.Format.LocalDateTime(openedOn.AtMidnight())
            })
                   .When(accountingPeriodClosing)
                   .Throws(new GeneralLedgerEntryWasNotPostedException(generalLedgerEntryIdentifier))
                   .Assert(_handler, _facts));
        }
 public Task when_a_debit_was_applied(
     GeneralLedgerEntryIdentifier generalLedgerEntryIdentifier,
     Period period,
     Credit credit) => new NpgsqlProjectionScenario(new BalanceSheetReportProjection())
 .Given(new CreateSchema())
 .Given(new GeneralLedgerEntryCreated {
     GeneralLedgerEntryId = generalLedgerEntryIdentifier.ToGuid(),
     Period = period.ToString()
 }, new DebitApplied {
     Amount               = credit.Amount.ToDecimal(),
     AccountNumber        = credit.AccountNumber.ToInt32(),
     GeneralLedgerEntryId = generalLedgerEntryIdentifier.ToGuid()
 })
 .Then(_schema, "balance_sheet_general_ledger_entry_period", new BalanceSheetReportProjection.GeneralLedgerEntryPeriod {
     PeriodMonth          = period.Month,
     PeriodYear           = period.Year,
     GeneralLedgerEntryId = generalLedgerEntryIdentifier.ToGuid()
 })
 .Then(_schema, "balance_sheet_items_unposted", new BalanceSheetReportProjection.UnpostedGeneralLedgerEntryLine {
     AccountNumber        = credit.AccountNumber.ToInt32(),
     GeneralLedgerEntryId = generalLedgerEntryIdentifier.ToGuid(),
     Debit = credit.Amount.ToDecimal()
 })
 .Assert();
Example #12
0
        public async Task when_an_entry_is_posted(
            GeneralLedgerEntryIdentifier generalLedgerEntryIdentifier, LocalDateTime createdOn, Money[] amounts)
        {
            var period   = AccountingPeriod.Open(createdOn.Date);
            var thru     = createdOn.Date.PlusDays(1).AtMidnight();
            var accounts = await OpenBooks(createdOn).ToArrayAsync();

            var debits = Array.ConvertAll(amounts, amount =>
                                          new Debit(accounts.OrderBy(_ => Guid.NewGuid()).First().accountNumber, amount));

            var credits = Array.ConvertAll(amounts, amount =>
                                           new Credit(accounts.OrderBy(_ => Guid.NewGuid()).First().accountNumber, amount));

            var journalEntry = new JournalEntry {
                ReferenceNumber = 1,
                Credits         = Array.ConvertAll(credits, credit => new JournalEntry.Item {
                    Amount        = credit.Amount.ToDecimal(),
                    AccountNumber = credit.AccountNumber.Value
                }),
                Debits = Array.ConvertAll(debits, debit => new JournalEntry.Item {
                    Amount        = debit.Amount.ToDecimal(),
                    AccountNumber = debit.AccountNumber.ToInt32()
                })
            };

            var command = new PostGeneralLedgerEntry {
                GeneralLedgerEntryId = generalLedgerEntryIdentifier.ToGuid(),
                CreatedOn            = createdOn.ToDateTimeUnspecified(),
                BusinessTransaction  = journalEntry,
                Period = period.ToString()
            };

            var expected = new BalanceSheetReport {
                Thru      = thru.ToDateTimeUnspecified(),
                LineItems = journalEntry.Debits.Concat(journalEntry.Credits.Select(c => new JournalEntry.Item()
                {
                    Amount        = -c.Amount,
                    AccountNumber = c.AccountNumber
                })).Aggregate(ImmutableDictionary <int, LineItem> .Empty, (items, item) => items.SetItem(
                                  item.AccountNumber,
                                  new LineItem {
                    AccountNumber = item.AccountNumber,
                    Name          = accounts.Single(x => x.accountNumber.ToInt32() == item.AccountNumber).accountName
                                    .ToString(),
                    Balance = items.TryGetValue(item.AccountNumber, out var existing)
                                                        ? existing.Balance + item.Amount
                                                        : new () { DecimalValue = item.Amount }
                })).Values.OrderBy(x => x.AccountNumber).ToImmutableArray(),
Example #13
0
 public Task closing_the_period_before_the_period_has_started(LocalDate openedOn, EquityAccount retainedEarnings,
                                                              GeneralLedgerEntryIdentifier closingGeneralLedgerEntryIdentifier) =>
 new Scenario()
 .Given(ChartOfAccounts.Identifier, new AccountDefined {
     AccountNumber = retainedEarnings.AccountNumber.ToInt32(),
     AccountName   = retainedEarnings.AccountName.ToString()
 })
 .Given(GeneralLedger.Identifier, new GeneralLedgerOpened {
     OpenedOn = Time.Format.LocalDate(openedOn)
 })
 .When(new BeginClosingAccountingPeriod {
     ClosingOn = openedOn.PlusMonths(-1).ToDateTimeUnspecified(),
     RetainedEarningsAccountNumber = retainedEarnings.AccountNumber.ToInt32(),
     ClosingGeneralLedgerEntryId   = closingGeneralLedgerEntryIdentifier.ToGuid()
 })
 .Throws(new ClosingDateBeforePeriodException(AccountingPeriod.Open(openedOn), openedOn.PlusMonths(-1)))
 .Assert(_handler, _facts);
 public Task applying_credit_to_non_existing_account_throws(
     GeneralLedgerEntryIdentifier generalLedgerEntryIdentifier, int sequenceNumber, LocalDate openedOn,
     AccountNumber accountNumber) => new Scenario()
 .Given(GeneralLedger.Identifier,
        new GeneralLedgerOpened {
     OpenedOn = Time.Format.LocalDate(openedOn)
 })
 .When(new PostGeneralLedgerEntry {
     GeneralLedgerEntryId = generalLedgerEntryIdentifier.ToGuid(),
     Period = AccountingPeriod.Open(openedOn).ToString(),
     BusinessTransaction = new TestTransaction(new GeneralLedgerEntryNumber("t", sequenceNumber),
                                               credits: new[] { new Credit(accountNumber, Money.Zero) }),
     CreatedOn = openedOn.ToDateTimeUnspecified()
 })
 .Throws(new AccountDeactivatedException(accountNumber))
 .Assert(new GeneralLedgerEntryHandlers(new GeneralLedgerTestRepository(_facts),
                                        new GeneralLedgerEntryTestRepository(_facts), _ => true), _facts);
Example #15
0
        public async Task when_an_entry_is_posted(
            GeneralLedgerEntryIdentifier generalLedgerEntryIdentifier, DateTimeOffset createdOn, Money[] amounts)
        {
            var period   = Period.Open(createdOn);
            var accounts = await OpenBooks(createdOn).ToArrayAsync();

            var debits = Array.ConvertAll(amounts, amount =>
                                          new Debit(accounts.OrderBy(_ => Guid.NewGuid()).First().accountNumber, amount));

            var credits = Array.ConvertAll(amounts, amount =>
                                           new Credit(accounts.OrderBy(_ => Guid.NewGuid()).First().accountNumber, amount));

            var command = new PostGeneralLedgerEntry {
                GeneralLedgerEntryId = generalLedgerEntryIdentifier.ToGuid(),
                CreatedOn            = createdOn,
                BusinessTransaction  = new JournalEntry {
                    ReferenceNumber = 1,
                    Credits         = Array.ConvertAll(credits, credit => new JournalEntry.Item {
                        Amount        = credit.Amount.ToDecimal(),
                        AccountNumber = credit.AccountNumber.Value
                    }),
                    Debits = Array.ConvertAll(debits, debit => new JournalEntry.Item {
                        Amount        = debit.Amount.ToDecimal(),
                        AccountNumber = debit.AccountNumber.ToInt32()
                    })
                },
                Period = period.ToString()
            };

            await HttpClient.SendCommand("/general-ledger/entries", command,
                                         TransactoSerializerOptions.BusinessTransactions(typeof(JournalEntry)));

            await Task.Delay(TimeSpan.FromSeconds(2));

            using var response = await HttpClient.GetAsync($"/balance-sheet/{createdOn.AddDays(1):O}");

            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
            var json = await response.Content.ReadAsStringAsync();

            var balanceSheet = JsonSerializer.Deserialize <BalanceSheetReport>(json, TransactoSerializerOptions.Events);
        }
        public Task entry_date_not_in_current_or_next_period_throws(
            GeneralLedgerEntryIdentifier generalLedgerEntryIdentifier, GeneralLedgerEntryNumber generalLedgerEntryNumber,
            LocalDate openedOn)
        {
            var createdOn = openedOn.PlusMonths(2).AtMidnight();

            return(new Scenario()
                   .Given(GeneralLedger.Identifier,
                          new GeneralLedgerOpened {
                OpenedOn = Time.Format.LocalDate(openedOn)
            })
                   .When(new PostGeneralLedgerEntry {
                GeneralLedgerEntryId = generalLedgerEntryIdentifier.ToGuid(),
                Period = AccountingPeriod.Open(openedOn).Next().Next().ToString(),
                BusinessTransaction = new TestTransaction(generalLedgerEntryNumber),
                CreatedOn = createdOn.ToDateTimeUnspecified()
            })
                   .Throws(new GeneralLedgerEntryNotInPeriodException(generalLedgerEntryNumber, createdOn,
                                                                      AccountingPeriod.Open(openedOn).Next()))
                   .Assert(new GeneralLedgerEntryHandlers(new GeneralLedgerTestRepository(_facts),
                                                          new GeneralLedgerEntryTestRepository(_facts), _ => false), _facts));
        }
        public Task period_closing_started(LocalDate openedOn, EquityAccount retainedEarnings,
                                           AssetAccount cashAccount, IncomeAccount incomeAccount, ExpenseAccount expenseAccount,
                                           GeneralLedgerEntryIdentifier[] generalLedgerEntryIdentifiers,
                                           GeneralLedgerEntryIdentifier closingGeneralLedgerEntryIdentifier, Money income, Money expense)
        {
            var period = AccountingPeriod.Open(openedOn);

            var closingOn = openedOn.AtMidnight();

            var accountingPeriodClosing = new AccountingPeriodClosing {
                Period    = period.ToString(),
                ClosingOn = Time.Format.LocalDateTime(closingOn),
                RetainedEarningsAccountNumber = retainedEarnings.AccountNumber.ToInt32(),
                ClosingGeneralLedgerEntryId   = closingGeneralLedgerEntryIdentifier.ToGuid(),
                GeneralLedgerEntryIds         =
                    Array.ConvertAll(generalLedgerEntryIdentifiers, identifier => identifier.ToGuid())
            };
            var net = income - expense;
            var generalLedgerEntryFacts = generalLedgerEntryIdentifiers.SelectMany(
                (identifier, index) => Array.ConvertAll(new object[] {
                new GeneralLedgerEntryCreated {
                    Number               = $"sale-{index}",
                    Period               = period.ToString(),
                    CreatedOn            = Time.Format.LocalDate(openedOn),
                    GeneralLedgerEntryId = identifier.ToGuid()
                },
                new CreditApplied {
                    Amount               = income.ToDecimal(),
                    AccountNumber        = incomeAccount.AccountNumber.ToInt32(),
                    GeneralLedgerEntryId = identifier.ToGuid()
                },
                new DebitApplied {
                    Amount               = expense.ToDecimal(),
                    AccountNumber        = expenseAccount.AccountNumber.ToInt32(),
                    GeneralLedgerEntryId = identifier.ToGuid()
                },
                net > Money.Zero
                                                        ? new DebitApplied {
                    Amount               = net.ToDecimal(),
                    AccountNumber        = cashAccount.AccountNumber.ToInt32(),
                    GeneralLedgerEntryId = identifier.ToGuid()
                }
                                                        : new CreditApplied {
                    Amount               = -net.ToDecimal(),
                    AccountNumber        = cashAccount.AccountNumber.ToInt32(),
                    GeneralLedgerEntryId = identifier.ToGuid()
                },
                new GeneralLedgerEntryPosted {
                    Period = period.ToString(),
                    GeneralLedgerEntryId = identifier.ToGuid()
                },
            }, e => new Fact(GeneralLedgerEntry.FormatStreamIdentifier(identifier), e)))
                                          .ToArray();

            return(new Scenario()
                   .Given(ChartOfAccounts.Identifier,
                          new AccountDefined {
                AccountName = cashAccount.AccountName.ToString(),
                AccountNumber = cashAccount.AccountNumber.ToInt32()
            },
                          new AccountDefined {
                AccountName = incomeAccount.AccountName.ToString(),
                AccountNumber = incomeAccount.AccountNumber.ToInt32()
            },
                          new AccountDefined {
                AccountName = expenseAccount.AccountName.ToString(),
                AccountNumber = expenseAccount.AccountNumber.ToInt32()
            },
                          new AccountDefined {
                AccountName = retainedEarnings.AccountName.ToString(),
                AccountNumber = retainedEarnings.AccountNumber.ToInt32()
            })
                   .Given(GeneralLedger.Identifier,
                          new GeneralLedgerOpened {
                OpenedOn = Time.Format.LocalDate(openedOn)
            },
                          accountingPeriodClosing)
                   .Given(generalLedgerEntryFacts)
                   .When(accountingPeriodClosing)
                   .Then(GeneralLedger.Identifier,
                         new GeneralLedgerEntryCreated {
                CreatedOn = Time.Format.LocalDateTime(closingOn),
                GeneralLedgerEntryId = closingGeneralLedgerEntryIdentifier.ToGuid(),
                Number = $"jec-{period}",
                Period = period.ToString()
            },
                         new DebitApplied {
                Amount = income.ToDecimal() * generalLedgerEntryIdentifiers.Length,
                AccountNumber = incomeAccount.AccountNumber.ToInt32(),
                GeneralLedgerEntryId = closingGeneralLedgerEntryIdentifier.ToGuid()
            },
                         new CreditApplied {
                Amount = expense.ToDecimal() * generalLedgerEntryIdentifiers.Length,
                AccountNumber = expenseAccount.AccountNumber.ToInt32(),
                GeneralLedgerEntryId = closingGeneralLedgerEntryIdentifier.ToGuid()
            },
                         net < Money.Zero
                                                ? new DebitApplied {
                Amount = -net.ToDecimal() * generalLedgerEntryIdentifiers.Length,
                AccountNumber = retainedEarnings.AccountNumber.ToInt32(),
                GeneralLedgerEntryId = closingGeneralLedgerEntryIdentifier.ToGuid()
            }
                                                : new CreditApplied {
                Amount = net.ToDecimal() * generalLedgerEntryIdentifiers.Length,
                AccountNumber = retainedEarnings.AccountNumber.ToInt32(),
                GeneralLedgerEntryId = closingGeneralLedgerEntryIdentifier.ToGuid()
            },
                         new GeneralLedgerEntryPosted {
                Period = period.ToString(),
                GeneralLedgerEntryId = closingGeneralLedgerEntryIdentifier.ToGuid()
            },
                         new AccountingPeriodClosed {
                Period = period.ToString(),
                GeneralLedgerEntryIds = Array.ConvertAll(generalLedgerEntryIdentifiers,
                                                         identifier => identifier.ToGuid()),
                ClosingGeneralLedgerEntryId = closingGeneralLedgerEntryIdentifier.ToGuid(),
                Balance = new[] {
                    new BalanceLineItem {
                        AccountNumber = cashAccount.AccountNumber.ToInt32(),
                        Amount = net.ToDecimal() * generalLedgerEntryIdentifiers.Length
                    },
                    new BalanceLineItem {
                        AccountNumber = retainedEarnings.AccountNumber.ToInt32(),
                        Amount = net.ToDecimal() * generalLedgerEntryIdentifiers.Length
                    },
                    new BalanceLineItem {
                        AccountNumber = incomeAccount.AccountNumber.ToInt32(),
                        Amount = Money.Zero.ToDecimal()
                    },
                    new BalanceLineItem {
                        AccountNumber = expenseAccount.AccountNumber.ToInt32(),
                        Amount = Money.Zero.ToDecimal()
                    }
                }
            })
                   .Assert(_handler, _facts));
        }
Example #18
0
        public Task period_closing_started(DateTimeOffset openedOn,
                                           GeneralLedgerEntryIdentifier[] generalLedgerEntryIdentifiers,
                                           GeneralLedgerEntryIdentifier closingGeneralLedgerEntryIdentifier,
                                           Money amount)
        {
            var period              = Period.Open(openedOn);
            var cashAccountNumber   = new AccountNumber(new Random().Next(1000, 1999));
            var incomeAccountNumber = new AccountNumber(new Random().Next(4000, 4999));

            var closingOn = new DateTimeOffset(new DateTime(period.Year, period.Month, 2));

            var accountingPeriodClosing = new AccountingPeriodClosing {
                Period    = period.ToString(),
                ClosingOn = closingOn,
                RetainedEarningsAccountNumber = _retainedEarnings.ToInt32(),
                ClosingGeneralLedgerEntryId   = closingGeneralLedgerEntryIdentifier.ToGuid(),
                GeneralLedgerEntryIds         =
                    Array.ConvertAll(generalLedgerEntryIdentifiers, identifier => identifier.ToGuid())
            };
            var generalLedgerEntryFacts = generalLedgerEntryIdentifiers.SelectMany(
                (identifier, index) => Array.ConvertAll(new object[] {
                new GeneralLedgerEntryCreated {
                    Number               = $"sale-{index}",
                    Period               = period.ToString(),
                    CreatedOn            = openedOn,
                    GeneralLedgerEntryId = identifier.ToGuid()
                },
                new DebitApplied {
                    Amount               = amount.ToDecimal(),
                    AccountNumber        = cashAccountNumber.ToInt32(),
                    GeneralLedgerEntryId = identifier.ToGuid()
                },
                new CreditApplied {
                    Amount               = amount.ToDecimal(),
                    AccountNumber        = incomeAccountNumber.ToInt32(),
                    GeneralLedgerEntryId = identifier.ToGuid()
                },
                new GeneralLedgerEntryPosted {
                    Period = period.ToString(),
                    GeneralLedgerEntryId = identifier.ToGuid()
                },
            }, e => new Fact($"generalLedgerEntry-{identifier}", e)))
                                          .ToArray();

            return(new Scenario()
                   .Given("chartOfAccounts",
                          new AccountDefined {
                AccountName = "Cash on Hand",
                AccountNumber = cashAccountNumber.ToInt32()
            },
                          new AccountDefined {
                AccountName = "Income",
                AccountNumber = incomeAccountNumber.ToInt32()
            },
                          new AccountDefined {
                AccountName = "Retained Earnings",
                AccountNumber = _retainedEarnings.ToInt32()
            })
                   .Given("generalLedger",
                          new GeneralLedgerOpened {
                OpenedOn = openedOn
            },
                          accountingPeriodClosing)
                   .Given(generalLedgerEntryFacts)
                   .When(accountingPeriodClosing)
                   .Then("generalLedger",
                         new GeneralLedgerEntryCreated {
                CreatedOn = closingOn,
                GeneralLedgerEntryId = closingGeneralLedgerEntryIdentifier.ToGuid(),
                Number = $"jec-{period}",
                Period = period.ToString()
            },
                         new DebitApplied {
                Amount = amount.ToDecimal() * generalLedgerEntryIdentifiers.Length,
                AccountNumber = incomeAccountNumber.ToInt32(),
                GeneralLedgerEntryId = closingGeneralLedgerEntryIdentifier.ToGuid()
            },
                         new CreditApplied {
                Amount = amount.ToDecimal() * generalLedgerEntryIdentifiers.Length,
                AccountNumber = _retainedEarnings.ToInt32(),
                GeneralLedgerEntryId = closingGeneralLedgerEntryIdentifier.ToGuid()
            },
                         new GeneralLedgerEntryPosted {
                Period = period.ToString(),
                GeneralLedgerEntryId = closingGeneralLedgerEntryIdentifier.ToGuid()
            },
                         new AccountingPeriodClosed {
                Period = period.ToString(),
                GeneralLedgerEntryIds = Array.ConvertAll(generalLedgerEntryIdentifiers,
                                                         identifier => identifier.ToGuid()),
                ClosingGeneralLedgerEntryId = closingGeneralLedgerEntryIdentifier.ToGuid(),
                Balance = new Dictionary <int, decimal> {
                    [cashAccountNumber.ToInt32()] = amount.ToDecimal() * generalLedgerEntryIdentifiers.Length,
                    [incomeAccountNumber.ToInt32()] = Money.Zero.ToDecimal(),
                    [_retainedEarnings.ToInt32()] = -(amount.ToDecimal() * generalLedgerEntryIdentifiers.Length)
                }
            })
                   .Assert(_handler, _facts));
        }