- Step-by-step prompts for solution skeleton, domain model, DbContext mappings, application services, UI shell/pages, PDF export, and tests/validation
58 lines
3.1 KiB
Markdown
58 lines
3.1 KiB
Markdown
---
|
|
description: "Define and implement application service interfaces and implementations for accounts, years, entries, transfers, balance queries, and file operations"
|
|
agent: "agent"
|
|
---
|
|
|
|
# Step 4: Application Services
|
|
|
|
## Interfaces (in `src/Duempelkas.App/Services/`)
|
|
|
|
### IAccountService
|
|
- `Task<List<AccountSummaryDto>> GetAllAccountsAsync()` — returns each account with its current total balance across all years.
|
|
- `Task<AccountSummaryDto> CreateAccountAsync(string name)`
|
|
- `Task RenameAccountAsync(int accountId, string newName)`
|
|
- `Task DeleteAccountAsync(int accountId)`
|
|
|
|
### IAccountYearService
|
|
- `Task<List<AccountYearDto>> GetYearsForAccountAsync(int accountId)`
|
|
- `Task<AccountYearDto> CreateYearAsync(int accountId, int year, decimal openingBalance)`
|
|
- `Task<decimal> SuggestCarryoverAsync(int accountId, int year)` — calculates prior year's closing balance as suggestion.
|
|
- `Task UpdateOpeningBalanceAsync(int accountYearId, decimal openingBalance)`
|
|
|
|
### IEntryService
|
|
- `Task<List<EntryDto>> GetEntriesAsync(int accountYearId)`
|
|
- `Task<EntryDto> CreateEntryAsync(int accountYearId, EntryType type, DateTime date, string title, decimal amount)`
|
|
- `Task CreateTransferAsync(int sourceAccountYearId, int targetAccountYearId, DateTime date, string title, decimal amount)` — atomically creates two entries + TransferLink.
|
|
- `Task DeleteEntryAsync(int entryId)` — if linked transfer, deletes both sides atomically.
|
|
- `Task UpdateEntryAsync(int entryId, DateTime date, string title, decimal amount)`
|
|
|
|
### IBalanceQueryService
|
|
- `Task<decimal> GetAccountTotalBalanceAsync(int accountId)` — OpeningBalance + sum(Income) - sum(Expense) across all years.
|
|
- `Task<YearlySummaryDto> GetYearlySummaryAsync(int accountYearId)` — returns opening balance, total income, total expense, yearly movement, closing balance.
|
|
|
|
### IPdfStatementService
|
|
- `Task<byte[]> GenerateYearlyStatementAsync(int accountYearId)`
|
|
|
|
### IFileSaveService
|
|
- `Task<string?> SaveFileAsync(byte[] content, string suggestedFileName)` — abstracts native file-save dialog.
|
|
|
|
## DTOs (in `src/Duempelkas.App/Services/Models/`)
|
|
- `AccountSummaryDto` { Id, Name, TotalBalance, CreatedUtc }
|
|
- `AccountYearDto` { Id, AccountId, Year, OpeningBalance }
|
|
- `EntryDto` { Id, AccountYearId, Type, Date, Title, Amount, IsTransfer, TransferLinkId, LinkedAccountName }
|
|
- `YearlySummaryDto` { OpeningBalance, TotalIncome, TotalExpense, YearlyMovement, ClosingBalance }
|
|
|
|
## Implementations (in `src/Duempelkas.Infrastructure/Services/`)
|
|
- Implement each interface using `FinanceDbContext`.
|
|
- All balance calculations use the single formula: `OpeningBalance + sum(Income) - sum(Expense)`.
|
|
- Transfer creation must be wrapped in a transaction.
|
|
- Entry deletion must check for TransferLink and delete both sides if linked.
|
|
|
|
## DI Registration
|
|
- Create `src/Duempelkas.Infrastructure/DependencyInjection.cs` with `AddInfrastructure(this IServiceCollection, string connectionString)` extension method that registers DbContext and all services.
|
|
|
|
## Conventions
|
|
- File-scoped namespaces.
|
|
- Async/await throughout.
|
|
- No business logic in entities; all in services.
|