feat(expense): add ExpenseService with state machine + receipt storage + tests
TDD: wrote 8 tests first (red), then implemented IExpenseService + ExpenseService covering CRUD, Draft→PendingApproval→Approved→Paid state machine, soft-delete, per-owner access guards, and receipt blob round-trip via IFileStorage. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
using ROLAC.API.DTOs.Expense;
|
||||
using ROLAC.API.DTOs.Shared;
|
||||
namespace ROLAC.API.Services;
|
||||
|
||||
public interface IExpenseService
|
||||
{
|
||||
Task<PagedResult<ExpenseListItemDto>> GetPagedAsync(
|
||||
int page, int pageSize, string? search, int? ministryId,
|
||||
int? categoryGroupId, string? status, DateOnly? from, DateOnly? to);
|
||||
Task<PagedResult<ExpenseListItemDto>> GetMineAsync(string userId, string? status, int page, int pageSize);
|
||||
Task<ExpenseDto?> GetByIdAsync(int id);
|
||||
Task<int> CreateAsync(CreateExpenseRequest r, bool isFinance);
|
||||
Task UpdateAsync(int id, UpdateExpenseRequest r, bool isFinance);
|
||||
Task DeleteAsync(int id, bool isFinance);
|
||||
Task SubmitAsync(int id);
|
||||
Task ApproveAsync(int id);
|
||||
Task RejectAsync(int id, string? reviewNotes);
|
||||
Task PayAsync(int id, string? checkNumber, DateOnly? paidAt);
|
||||
Task SaveReceiptAsync(int id, Stream content, string fileName, bool isFinance);
|
||||
Task<(Stream stream, string contentType)?> OpenReceiptAsync(int id, bool isFinance);
|
||||
}
|
||||
Reference in New Issue
Block a user