fix(expense): open category read to all authed users; statement lookups via FirstOrDefaultAsync
Final-review findings: - ExpenseCategoriesController was finance-only at the class level, but the member self-service reimbursement form reads the category list to populate its dropdown, so members got 403 and could not submit. Open GET to any authenticated user; keep group/subcategory writes finance-only (mirrors MinistriesController). Verified live with a member-role account: reads 200, writes 403, self-submit 200. - MonthlyStatementService Update/Finalize now use FirstOrDefaultAsync for convention consistency with the rest of the service layer. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -51,7 +51,7 @@ public class MonthlyStatementService : IMonthlyStatementService
|
||||
|
||||
public async Task UpdateAsync(int id, UpdateMonthlyStatementRequest r)
|
||||
{
|
||||
var s = await _db.MonthlyStatements.FindAsync(id)
|
||||
var s = await _db.MonthlyStatements.FirstOrDefaultAsync(x => x.Id == id)
|
||||
?? throw new KeyNotFoundException($"MonthlyStatement {id} not found.");
|
||||
if (s.IsFinalized) throw new InvalidOperationException("Statement is finalized and cannot be modified.");
|
||||
s.OpeningBalance = r.OpeningBalance; s.TotalOtherIncome = r.TotalOtherIncome;
|
||||
@@ -62,7 +62,7 @@ public class MonthlyStatementService : IMonthlyStatementService
|
||||
|
||||
public async Task FinalizeAsync(int id)
|
||||
{
|
||||
var s = await _db.MonthlyStatements.FindAsync(id)
|
||||
var s = await _db.MonthlyStatements.FirstOrDefaultAsync(x => x.Id == id)
|
||||
?? throw new KeyNotFoundException($"MonthlyStatement {id} not found.");
|
||||
s.IsFinalized = true; s.FinalizedAt = DateTimeOffset.UtcNow; s.FinalizedBy = CurrentUserId;
|
||||
await _db.SaveChangesAsync();
|
||||
|
||||
Reference in New Issue
Block a user