life-manager/codebase/features/finance/backend/finance.controller.ts

179 lines
6.7 KiB
TypeScript

import {
Body,
Controller,
Delete,
Get,
HttpCode,
HttpStatus,
Param,
Patch,
Post,
Query,
} from '@nestjs/common';
import { ApiOperation, ApiTags } from '@nestjs/swagger';
import { FinanceService, FinancialEntryResponse } from './finance.service';
import { RecurringTransactionService, RecurringTransactionResponse } from './recurring-transaction.service';
import { BudgetTargetService, BudgetTargetResponse } from './budget-target.service';
import { FinanceSummaryService } from './finance-summary.service';
import { BillableService } from './billable.service';
import { BillableEntry } from './entities/billable-entry.entity';
import { CreateFinancialEntryDto } from './dto/create-financial-entry.dto';
import { UpdateFinancialEntryDto } from './dto/update-financial-entry.dto';
import { QueryFinancialEntryDto, FinanceSummaryQueryDto } from './dto/query-financial-entry.dto';
import { CreateRecurringTransactionDto } from './dto/create-recurring-transaction.dto';
import { UpdateRecurringTransactionDto } from './dto/update-recurring-transaction.dto';
import { CreateBudgetTargetDto } from './dto/create-budget-target.dto';
import { UpdateBudgetTargetDto } from './dto/update-budget-target.dto';
import { CreateBillableDto } from './dto/create-billable.dto';
import { UpdateBillableDto } from './dto/update-billable.dto';
import { QueryBillableDto } from './dto/query-billable.dto';
import { PaginatedResponse } from '@common/pagination.dto';
import type { FinanceSummary } from '@life-platform/shared';
@ApiTags('Finance')
@Controller('finance')
export class FinanceController {
constructor(
private readonly financeService: FinanceService,
private readonly recurringService: RecurringTransactionService,
private readonly budgetTargetService: BudgetTargetService,
private readonly summaryService: FinanceSummaryService,
private readonly billableService: BillableService,
) {}
// ── Summary & Projections ──
@Get('summary')
@ApiOperation({ summary: 'Get unified finance summary for a month' })
getSummary(@Query() query: FinanceSummaryQueryDto): Promise<FinanceSummary> {
return this.summaryService.getSummary(query.month, query.domainId);
}
@Get('projection')
@ApiOperation({ summary: 'Get cash flow projection' })
getProjection(@Query('months') months?: string) {
return this.summaryService.getMonthlyTrend(parseInt(months ?? '3', 10));
}
@Get('trend')
@ApiOperation({ summary: 'Get monthly trend data' })
getTrend(@Query('months') months?: string) {
return this.summaryService.getMonthlyTrend(parseInt(months ?? '6', 10));
}
// ── Financial Entries ──
@Get('entries')
@ApiOperation({ summary: 'List financial entries (paginated)' })
findAllEntries(@Query() query: QueryFinancialEntryDto): Promise<PaginatedResponse<FinancialEntryResponse>> {
return this.financeService.findAll(query);
}
@Post('entries')
@ApiOperation({ summary: 'Create financial entry' })
createEntry(@Body() dto: CreateFinancialEntryDto): Promise<FinancialEntryResponse> {
return this.financeService.create(dto);
}
@Patch('entries/:id')
@ApiOperation({ summary: 'Update financial entry' })
updateEntry(@Param('id') id: string, @Body() dto: UpdateFinancialEntryDto): Promise<FinancialEntryResponse> {
return this.financeService.update(id, dto);
}
@Delete('entries/:id')
@HttpCode(HttpStatus.NO_CONTENT)
@ApiOperation({ summary: 'Delete financial entry' })
removeEntry(@Param('id') id: string): Promise<void> {
return this.financeService.remove(id);
}
// ── Recurring Transactions ──
@Get('recurring')
@ApiOperation({ summary: 'List recurring transactions' })
findAllRecurring(@Query('type') type?: string): Promise<RecurringTransactionResponse[]> {
return this.recurringService.findAll(type);
}
@Post('recurring')
@ApiOperation({ summary: 'Create recurring transaction' })
createRecurring(@Body() dto: CreateRecurringTransactionDto): Promise<RecurringTransactionResponse> {
return this.recurringService.create(dto);
}
@Patch('recurring/:id')
@ApiOperation({ summary: 'Update recurring transaction' })
updateRecurring(@Param('id') id: string, @Body() dto: UpdateRecurringTransactionDto): Promise<RecurringTransactionResponse> {
return this.recurringService.update(id, dto);
}
@Delete('recurring/:id')
@HttpCode(HttpStatus.NO_CONTENT)
@ApiOperation({ summary: 'Delete recurring transaction' })
removeRecurring(@Param('id') id: string): Promise<void> {
return this.recurringService.remove(id);
}
@Post('recurring/:id/mark-paid')
@ApiOperation({ summary: 'Create entry from recurring for given month' })
markPaid(@Param('id') id: string, @Body('month') month: string): Promise<void> {
return this.recurringService.markPaid(id, month);
}
// ── Budget Targets ──
@Get('targets')
@ApiOperation({ summary: 'List budget targets' })
findAllTargets(@Query('month') month?: string): Promise<BudgetTargetResponse[]> {
return month
? this.budgetTargetService.getTargetsForMonth(month)
: this.budgetTargetService.findAll();
}
@Post('targets')
@ApiOperation({ summary: 'Create budget target' })
createTarget(@Body() dto: CreateBudgetTargetDto): Promise<BudgetTargetResponse> {
return this.budgetTargetService.create(dto);
}
@Patch('targets/:id')
@ApiOperation({ summary: 'Update budget target' })
updateTarget(@Param('id') id: string, @Body() dto: UpdateBudgetTargetDto): Promise<BudgetTargetResponse> {
return this.budgetTargetService.update(id, dto);
}
@Delete('targets/:id')
@HttpCode(HttpStatus.NO_CONTENT)
@ApiOperation({ summary: 'Delete budget target' })
removeTarget(@Param('id') id: string): Promise<void> {
return this.budgetTargetService.remove(id);
}
// ── Billable Entries (moved from income) ──
@Get('billable')
@ApiOperation({ summary: 'List billable entries' })
findAllBillable(@Query() query: QueryBillableDto): Promise<PaginatedResponse<BillableEntry>> {
return this.billableService.findAll(query as QueryBillableDto & Record<string, unknown>);
}
@Post('billable')
@ApiOperation({ summary: 'Create billable entry' })
createBillable(@Body() dto: CreateBillableDto): Promise<BillableEntry> {
return this.billableService.createBillable(dto);
}
@Patch('billable/:id')
@ApiOperation({ summary: 'Update billable entry' })
updateBillable(@Param('id') id: string, @Body() dto: UpdateBillableDto): Promise<BillableEntry> {
return this.billableService.updateBillable(id, dto);
}
@Delete('billable/:id')
@HttpCode(HttpStatus.NO_CONTENT)
@ApiOperation({ summary: 'Delete billable entry' })
deleteBillable(@Param('id') id: string): Promise<void> {
return this.billableService.remove(id);
}
}