Add cumulative balance tracking with editable overrides
All checks were successful
Deploy to VPS / deploy (push) Successful in 21s

- New BalanceOverride table for manual balance adjustments per month
- Cumulative balance computation with cross-year carryover
- Three new columns: Acum. Anterior, Neto Mes, Balance Acum.
- Inline editing on Balance Acum. cell (pencil icon for overrides)
- Year navigation clamped to 2026–2030, fresh start at March 2026
- PUT/DELETE /budget/balance-override/{year}/{month} endpoints

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Carlos Escalante
2026-03-30 12:03:43 -06:00
parent 99d0c4ebd7
commit b68129a171
7 changed files with 343 additions and 7 deletions

View File

@@ -18,8 +18,11 @@ const MONTH_NAMES = [
'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre',
];
const MIN_YEAR = 2026;
const MAX_YEAR = 2030;
export default function Budget() {
const currentYear = new Date().getFullYear();
const currentYear = Math.max(MIN_YEAR, new Date().getFullYear());
const {
year,
setYear,
@@ -33,6 +36,8 @@ export default function Budget() {
addItem,
updateItem,
deleteItem,
saveBalanceOverride,
clearBalanceOverride,
refresh,
} = useBudget(currentYear);
@@ -81,11 +86,11 @@ export default function Budget() {
<h1 className="text-2xl font-bold tracking-tight">Presupuesto</h1>
</div>
<div className="flex items-center gap-1">
<Button variant="outline" size="icon" onClick={() => setYear(year - 1)}>
<Button variant="outline" size="icon" disabled={year <= MIN_YEAR} onClick={() => setYear(year - 1)}>
<ChevronLeft className="w-4 h-4" />
</Button>
<span className="w-16 text-center font-semibold tabular-nums">{year}</span>
<Button variant="outline" size="icon" onClick={() => setYear(year + 1)}>
<Button variant="outline" size="icon" disabled={year >= MAX_YEAR} onClick={() => setYear(year + 1)}>
<ChevronRight className="w-4 h-4" />
</Button>
</div>
@@ -194,10 +199,17 @@ export default function Budget() {
<YearlyOverview
months={projection.months}
selectedMonth={selectedMonth}
year={year}
onSelectMonth={(m) => {
setSelectedMonth(m);
setSubTab('detail');
}}
onSaveOverride={async (month, value) => {
await saveBalanceOverride(year, month, value);
}}
onClearOverride={async (month) => {
await clearBalanceOverride(year, month);
}}
/>
</CardContent>
</Card>