40 lines
2.2 KiB
Markdown
40 lines
2.2 KiB
Markdown
# Variable Pool Rebalance / Transfer Feature
|
|
|
|
## Summary
|
|
- Allow users to redistribute current variable pool (BudgetSession.availableCents) by setting per-category dollar targets, without changing future percent-based allocations.
|
|
- Enforce guards: sum = available, savings floor confirm, non-negative, no single category >80%, warnings when lowering savings.
|
|
- New backend endpoint performs atomic balance updates and audit logging; fixed expenses unaffected.
|
|
|
|
## API
|
|
- `POST /variable-categories/manual-rebalance`
|
|
- Body: `{ targets: [{ id, targetCents }], forceLowerSavings?: boolean }`
|
|
- Uses latest BudgetSession by periodStart; availableCents is the pool to balance.
|
|
- Validations: targets cover every category; non-negative; sum(targets)=available; each ≤80% of available; lowering savings or savings <20% requires `forceLowerSavings`.
|
|
- Transaction: update category balanceCents to targets; insert transaction(kind=`rebalance`, note snapshot); fixed plans untouched.
|
|
- Response: `{ ok: true, availableCents, categories: [{ id, balanceCents }] }`.
|
|
|
|
## UI/UX
|
|
- New Rebalance page (Settings → Expenses tab entry point) showing availableCents and per-category balances.
|
|
- Editable dollar inputs with live total meter and inline errors for rule violations.
|
|
- Savings floor warning/confirm; optional helper to adjust one category and auto-scale others respecting floors.
|
|
- Confirmation modal summarizing before/after deltas.
|
|
|
|
## Data / Logic
|
|
- Active session = latest BudgetSession for user.
|
|
- Rebalance acts on current variable pool only; future income remains percent-based.
|
|
- Savings floor default 20% of available; lowering requires confirmation flag.
|
|
|
|
## Tests
|
|
- Sum=available happy path; savings unchanged.
|
|
- Lowering savings w/out flag → 400; with flag → OK.
|
|
- Savings total <20% w/out flag → 400; with flag → OK.
|
|
- >80% single category → 400.
|
|
- Sum mismatch → 400; negative target → 400.
|
|
- Negative existing balance allowed only if target >=0 (ending non-negative).
|
|
- Adjust-one helper unit: scaling respects floors.
|
|
- Audit entry created; fixed plans and percents unchanged.
|
|
|
|
## Assumptions
|
|
- availableCents equals dashboard “Available” variable pool.
|
|
- No localization requirements for new errors.
|