Files
ERP-core/Backend/ERPCore.Tests/CashInHandServiceTests.cs
T

135 lines
5.8 KiB
C#

using ERPCore.Domain.Entities;
using ERPCore.Domain.Enums;
using static ERPCore.Tests.TestSupport.BankDepositTestSupport;
namespace ERPCore.Tests;
/// <summary>Till cash in hand (docs/BANK_DEPOSIT_MODULE_PLAN.md §2, §11).</summary>
public class CashInHandServiceTests
{
private static readonly DateOnly Today = Clock.Today;
private static readonly DateOnly Start = Today.AddDays(-10);
[Fact]
public async Task OnlyCashIsCounted()
{
await using var db = CreateContext();
var day = Today.AddDays(-2);
db.SalesSlips.AddRange(
CashSlip(day, cash: 300, card: 200), // only the 300 is till cash
CashSlip(day, cash: 0, card: 900));
db.SalesInvoices.Add(new SalesInvoice
{
SalesInvoiceId = 1, InvoiceNo = "INV-1", InvoiceDate = At(day.AddDays(-5)), Status = SalesInvoiceStatus.Posted, BranchId = Branch1
});
db.SalesInvoicePayments.AddRange(
new SalesInvoicePayment { SalesInvoicePaymentId = 1, SalesInvoiceId = 1, PaymentDate = At(day), PaymentMethod = SalesPaymentMethod.Cash, Amount = 150 },
new SalesInvoicePayment { SalesInvoicePaymentId = 2, SalesInvoiceId = 1, PaymentDate = At(day), PaymentMethod = SalesPaymentMethod.Card, Amount = 500 },
new SalesInvoicePayment { SalesInvoicePaymentId = 3, SalesInvoiceId = 1, PaymentDate = At(day), PaymentMethod = SalesPaymentMethod.Cheque, Amount = 70 });
db.Expenses.Add(new Expense { ExpenseId = 1, DocNo = "EXP-1", BranchId = Branch1, ExpenseDate = day, Amount = 100, Status = ExpenseStatus.Posted });
db.ExpensePayments.AddRange(
new ExpensePayment { ExpensePaymentId = 1, ExpenseId = 1, PaymentDate = At(day), PaymentMethod = ExpensePaymentMethod.Cash, Amount = 40 },
new ExpensePayment { ExpensePaymentId = 2, ExpenseId = 1, PaymentDate = At(day), PaymentMethod = ExpensePaymentMethod.BankTransfer, Amount = 60 });
await db.SaveChangesAsync();
var p = (await CashService(db, Start).GetPositionAsync(day, Branch1)).Position;
Assert.Equal(450m, p.CashIn);
Assert.Equal(40m, p.CashOut);
Assert.Equal(410m, p.NetCash);
Assert.Equal(410m, p.Closing);
}
[Fact]
public async Task UndepositedCash_CarriesToTheNextDay_AndDepositsReduceIt()
{
await using var db = CreateContext();
var d1 = Today.AddDays(-3);
var d2 = Today.AddDays(-2);
db.SalesSlips.AddRange(CashSlip(d1, 1000), CashSlip(d2, 500));
db.BankDeposits.AddRange(
Deposit(d1, 600),
Deposit(d1, 999, status: BankDepositStatus.Cancelled)); // ignored
await db.SaveChangesAsync();
var days = (await CashService(db, Start).GetDailyAsync(d1, d2, Branch1)).Days;
Assert.Equal((0m, 1000m, 600m, 400m), (days[0].Opening, days[0].NetCash, days[0].Deposited, days[0].Closing));
Assert.Equal((400m, 500m, 0m, 900m), (days[1].Opening, days[1].NetCash, days[1].Deposited, days[1].Closing));
}
[Fact]
public async Task Opening_IsCarriedInFromBeforeTheWindow()
{
await using var db = CreateContext();
db.SalesSlips.AddRange(CashSlip(Today.AddDays(-6), 700), CashSlip(Today.AddDays(-5), 300));
db.BankDeposits.Add(Deposit(Today.AddDays(-5), 200));
await db.SaveChangesAsync();
var day = (await CashService(db, Start).GetPositionAsync(Today.AddDays(-1), Branch1)).Position;
Assert.Equal(800m, day.Opening);
Assert.Equal(800m, day.Closing);
}
[Fact]
public async Task CashBeforeTheTrackingStart_IsNotCarried()
{
await using var db = CreateContext();
db.SalesSlips.AddRange(CashSlip(Start.AddDays(-1), 5000), CashSlip(Start, 100));
await db.SaveChangesAsync();
var days = (await CashService(db, Start).GetDailyAsync(Start.AddDays(-1), Start, Branch1)).Days;
Assert.Equal(5000m, days[0].NetCash); // still reported for the day itself
Assert.Equal(0m, days[1].Opening); // but not carried into tracking
Assert.Equal(100m, days[1].Closing);
}
[Fact]
public async Task Available_IsTheLowestClosingFromThatDayToToday()
{
await using var db = CreateContext();
var d1 = Today.AddDays(-2);
db.SalesSlips.Add(CashSlip(d1, 1000));
db.BankDeposits.Add(Deposit(Today.AddDays(-1), 800)); // already took most of it the next day
await db.SaveChangesAsync();
var position = await CashService(db, Start).GetPositionAsync(d1, Branch1);
Assert.Equal(1000m, position.Position.Closing);
Assert.Equal(200m, position.AvailableToDeposit);
}
[Fact]
public async Task Branches_AreKeptApart()
{
await using var db = CreateContext();
var day = Today.AddDays(-1);
db.SalesSlips.AddRange(CashSlip(day, 100, warehouseId: Warehouse1), CashSlip(day, 900, warehouseId: Warehouse2));
await db.SaveChangesAsync();
var service = CashService(db, Start);
Assert.Equal(100m, (await service.GetPositionAsync(day, Branch1)).Position.Closing);
Assert.Equal(900m, (await service.GetPositionAsync(day, Branch2)).Position.Closing);
Assert.Equal(1000m, (await service.GetPositionAsync(day, null)).Position.Closing);
}
[Fact]
public async Task LateEveningSale_CountsOnTheLocalDay()
{
await using var db = CreateContext();
var day = Today.AddDays(-1);
var slip = CashSlip(day, 250);
slip.SlipDate = Clock.ToUtc(day.AddDays(1)).AddMinutes(-30); // 23:30 local
db.SalesSlips.Add(slip);
await db.SaveChangesAsync();
var days = (await CashService(db, Start).GetDailyAsync(day, day.AddDays(1), Branch1)).Days;
Assert.Equal(250m, days[0].CashIn);
Assert.Equal(0m, days[1].CashIn);
}
}