Implement Phase 2 features: roles, assessment groups, budget import, Kanban
- Add hierarchical roles: SuperUser Admin (is_superadmin flag), Tenant Admin, Tenant User with separate /admin route and admin panel - Add Assessment Groups module for property type-based assessment rates (SFHs, Condos, Estate Lots with different regular/special rates) - Enhance Chart of Accounts: initial balance on create (with journal entry), archive/restore accounts, edit all fields including account number & fund type - Add Budget CSV import with downloadable template and account mapping - Add Capital Projects Kanban board with drag-and-drop between year columns, table/kanban view toggle, and PDF export via browser print - Update seed data with assessment groups, second test user, superadmin flag - Create repeatable reseed.sh script for clean database population - Fix AgingReportPage Mantine v7 Table prop compatibility Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { Controller, Get, Put, Body, Param, Query, UseGuards, ParseIntPipe } from '@nestjs/common';
|
||||
import { Controller, Get, Put, Post, Body, Param, Query, Res, UseGuards, ParseIntPipe } from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
|
||||
import { Response } from 'express';
|
||||
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
|
||||
import { BudgetsService } from './budgets.service';
|
||||
import { UpsertBudgetDto } from './dto/upsert-budget.dto';
|
||||
@@ -11,6 +12,38 @@ import { UpsertBudgetDto } from './dto/upsert-budget.dto';
|
||||
export class BudgetsController {
|
||||
constructor(private budgetsService: BudgetsService) {}
|
||||
|
||||
@Post(':year/import')
|
||||
@ApiOperation({ summary: 'Import budget data from parsed CSV/XLSX lines' })
|
||||
importBudget(
|
||||
@Param('year', ParseIntPipe) year: number,
|
||||
@Body() lines: any[],
|
||||
) {
|
||||
return this.budgetsService.importBudget(year, lines);
|
||||
}
|
||||
|
||||
@Get(':year/template')
|
||||
@ApiOperation({ summary: 'Download budget CSV template for a fiscal year' })
|
||||
async getTemplate(
|
||||
@Param('year', ParseIntPipe) year: number,
|
||||
@Res() res: Response,
|
||||
) {
|
||||
const csv = await this.budgetsService.getTemplate(year);
|
||||
res.set({
|
||||
'Content-Type': 'text/csv',
|
||||
'Content-Disposition': `attachment; filename="budget_template_${year}.csv"`,
|
||||
});
|
||||
res.send(csv);
|
||||
}
|
||||
|
||||
@Get(':year/vs-actual')
|
||||
@ApiOperation({ summary: 'Budget vs actual comparison' })
|
||||
budgetVsActual(
|
||||
@Param('year', ParseIntPipe) year: number,
|
||||
@Query('month') month?: string,
|
||||
) {
|
||||
return this.budgetsService.getBudgetVsActual(year, month ? parseInt(month) : undefined);
|
||||
}
|
||||
|
||||
@Get(':year')
|
||||
@ApiOperation({ summary: 'Get budgets for a fiscal year' })
|
||||
findByYear(@Param('year', ParseIntPipe) year: number) {
|
||||
@@ -25,13 +58,4 @@ export class BudgetsController {
|
||||
) {
|
||||
return this.budgetsService.upsert(year, budgets);
|
||||
}
|
||||
|
||||
@Get(':year/vs-actual')
|
||||
@ApiOperation({ summary: 'Budget vs actual comparison' })
|
||||
budgetVsActual(
|
||||
@Param('year', ParseIntPipe) year: number,
|
||||
@Query('month') month?: string,
|
||||
) {
|
||||
return this.budgetsService.getBudgetVsActual(year, month ? parseInt(month) : undefined);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user