135 lines
5.8 KiB
C#
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);
|
|
}
|
|
}
|