update detail.
ci-cd-vm / ci-cd (push) Successful in 4m27s

This commit is contained in:
Chris Chen
2026-06-25 09:33:49 -07:00
parent 609ce6a439
commit 8bdb942a49
23 changed files with 698 additions and 271 deletions
@@ -67,14 +67,20 @@ public class ExpenseServiceTests
private static CreateExpenseRequest Reimb() => new()
{
Type = "StaffReimbursement", MinistryId = 1, CategoryGroupId = 1, SubCategoryId = 1,
Amount = 45.50m, Description = "Batteries", ExpenseDate = new DateOnly(2026, 5, 28),
Type = "StaffReimbursement", MinistryId = 1,
Lines = { new ExpenseLineInput { CategoryGroupId = 1, SubCategoryId = 1, Amount = 45.50m } },
Description = "Batteries", ExpenseDate = new DateOnly(2026, 5, 28),
};
private static UpdateExpenseRequest CloneToUpdate(CreateExpenseRequest r) => new()
{
Type = r.Type, MinistryId = r.MinistryId, CategoryGroupId = r.CategoryGroupId,
SubCategoryId = r.SubCategoryId, Amount = r.Amount, Description = r.Description,
Type = r.Type, MinistryId = r.MinistryId,
Lines = r.Lines.Select(l => new ExpenseLineInput
{
CategoryGroupId = l.CategoryGroupId, SubCategoryId = l.SubCategoryId,
Amount = l.Amount, FunctionalClass = l.FunctionalClass, Description = l.Description,
}).ToList(),
Description = r.Description,
VendorName = r.VendorName, MemberId = r.MemberId, CheckNumber = r.CheckNumber,
ExpenseDate = r.ExpenseDate, Notes = r.Notes,
};
@@ -207,7 +213,7 @@ public class ExpenseServiceTests
Assert.Equal("PendingApproval", (await db.Expenses.FindAsync(id))!.Status);
var edit = CloneToUpdate(Reimb());
edit.Amount = 99.99m;
edit.Lines[0].Amount = 99.99m;
await svc.UpdateAsync(id, edit, isFinance: false);
var e = await db.Expenses.FindAsync(id);
@@ -260,13 +266,70 @@ public class ExpenseServiceTests
var id = await svc.CreateAsync(new CreateExpenseRequest
{
Type = "VendorPayment", MinistryId = 1, CategoryGroupId = 1, SubCategoryId = 1,
Amount = 50m, Description = "x", ExpenseDate = new DateOnly(2026, 5, 1),
FunctionalClass = "ManagementGeneral",
Type = "VendorPayment", MinistryId = 1,
Lines = { new ExpenseLineInput { CategoryGroupId = 1, SubCategoryId = 1, Amount = 50m, FunctionalClass = "ManagementGeneral" } },
Description = "x", ExpenseDate = new DateOnly(2026, 5, 1),
}, isFinance: true);
var dto = await svc.GetByIdAsync(id);
Assert.Equal("ManagementGeneral", dto!.FunctionalClass);
Assert.Equal("ManagementGeneral", dto!.Lines.Single().FunctionalClass);
}
[Fact]
public async Task Create_MultiLine_SetsHeaderTotal_AndRoundTripsLines()
{
var (svc, db, _) = Build("u1");
db.ExpenseCategoryGroups.Add(new ExpenseCategoryGroup { Id = 2, Name_en = "Food & Beverage" });
db.ExpenseSubCategories.Add(new ExpenseSubCategory { Id = 2, GroupId = 2, Name_en = "Snacks" });
await db.SaveChangesAsync();
var r = new CreateExpenseRequest
{
Type = "VendorPayment", MinistryId = 1, VendorName = "Costco",
Description = "Mixed invoice", ExpenseDate = new DateOnly(2026, 5, 1),
Lines =
{
new ExpenseLineInput { CategoryGroupId = 1, SubCategoryId = 1, Amount = 30m },
new ExpenseLineInput { CategoryGroupId = 2, SubCategoryId = 2, Amount = 12.50m },
},
};
var id = await svc.CreateAsync(r, isFinance: true);
Assert.Equal(42.50m, (await db.Expenses.FindAsync(id))!.Amount);
var dto = await svc.GetByIdAsync(id);
Assert.Equal(2, dto!.Lines.Count);
Assert.Equal(42.50m, dto.Amount);
Assert.Equal(2, dto.LineCount);
}
[Fact]
public async Task Create_WithNoLines_Throws()
{
var (svc, _, _) = Build("u1");
var r = Reimb(); r.Lines.Clear();
await Assert.ThrowsAsync<InvalidOperationException>(() => svc.CreateAsync(r, isFinance: false));
}
[Fact]
public async Task Update_ReplacesLines_AndRecomputesTotal()
{
var (svc, db, _) = Build("alice");
db.ExpenseCategoryGroups.Add(new ExpenseCategoryGroup { Id = 2, Name_en = "Food & Beverage" });
db.ExpenseSubCategories.Add(new ExpenseSubCategory { Id = 2, GroupId = 2, Name_en = "Snacks" });
await db.SaveChangesAsync();
var id = await svc.CreateAsync(Reimb(), isFinance: false);
var edit = CloneToUpdate(Reimb());
edit.Lines = new()
{
new ExpenseLineInput { CategoryGroupId = 1, SubCategoryId = 1, Amount = 10m },
new ExpenseLineInput { CategoryGroupId = 2, SubCategoryId = 2, Amount = 5m },
};
await svc.UpdateAsync(id, edit, isFinance: false);
Assert.Equal(15m, (await db.Expenses.FindAsync(id))!.Amount);
Assert.Equal(2, await db.ExpenseLines.CountAsync(l => l.ExpenseId == id));
}
[Fact]