Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 | import { Controller, Get, Post, Body, Param, Query, Req, UseGuards, BadRequestException } from '@nestjs/common'; import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger'; import { ChartOfAccountsService } from '../services/chart-of-accounts.service'; import { PostingEngineService } from '../services/posting-engine.service'; import { AccountsPayableService } from '../services/accounts-payable.service'; import { AccountsReceivableService } from '../services/accounts-receivable.service'; import { BankingService } from '../services/banking.service'; import { TaxEngineService } from '../services/tax-engine.service'; import { BudgetService } from '../services/budget.service'; import { AllocationService } from '../services/allocation.service'; import { FinancialStatementService } from '../services/financial-statement.service'; import { FinanceSeederService } from '../services/finance-seeder.service'; import { ReconciliationService } from '../services/reconciliation.service'; import { InjectModel } from '@nestjs/mongoose'; import { Model, Types } from 'mongoose'; import { JournalEntry, JournalLine } from '../schemas/journal-entry.schema'; @ApiTags('Finance') @Controller('api/v1/finance') export class FinanceController { constructor( private readonly coaSvc: ChartOfAccountsService, private readonly postingSvc: PostingEngineService, private readonly apSvc: AccountsPayableService, private readonly arSvc: AccountsReceivableService, private readonly bankSvc: BankingService, private readonly taxSvc: TaxEngineService, private readonly budgetSvc: BudgetService, private readonly allocationSvc: AllocationService, private readonly statementSvc: FinancialStatementService, private readonly seederSvc: FinanceSeederService, private readonly reconciliationSvc: ReconciliationService, @InjectModel(JournalEntry.name) private readonly journalModel: Model<JournalEntry>, @InjectModel(JournalLine.name) private readonly lineModel: Model<JournalLine>, ) {} @Post('seed') @ApiOperation({ summary: 'Seed basic Chart of Accounts and Fiscal Calendar' }) async seed(@Req() req: any) { const tenantId = req.headers['x-tenant-id'] || '60c72b2f9b1d8b23c4d5e6f1'; return this.seederSvc.seed(tenantId); } @Get('accounts') @ApiOperation({ summary: 'List all accounts' }) async listAccounts(@Req() req: any, @Query('legalEntityId') legalEntityId?: string) { const tenantId = req.headers['x-tenant-id'] || '60c72b2f9b1d8b23c4d5e6f1'; return this.coaSvc.listAccounts(tenantId, legalEntityId); } @Post('accounts') @ApiOperation({ summary: 'Create new ledger account' }) async createAccount(@Req() req: any, @Body() body: any) { const tenantId = req.headers['x-tenant-id'] || '60c72b2f9b1d8b23c4d5e6f1'; return this.coaSvc.createAccount(tenantId, body); } @Get('statements/trial-balance') @ApiOperation({ summary: 'Calculate Trial Balance' }) async getTrialBalance(@Req() req: any, @Query('legalEntityId') legalEntityId?: string) { const tenantId = req.headers['x-tenant-id'] || '60c72b2f9b1d8b23c4d5e6f1'; return this.statementSvc.getTrialBalance(tenantId, legalEntityId); } @Get('statements/profit-loss') @ApiOperation({ summary: 'Calculate Profit and Loss' }) async getProfitAndLoss(@Req() req: any) { const tenantId = req.headers['x-tenant-id'] || '60c72b2f9b1d8b23c4d5e6f1'; return this.statementSvc.getProfitAndLoss(tenantId); } @Get('statements/balance-sheet') @ApiOperation({ summary: 'Calculate Balance Sheet' }) async getBalanceSheet(@Req() req: any) { const tenantId = req.headers['x-tenant-id'] || '60c72b2f9b1d8b23c4d5e6f1'; return this.statementSvc.getBalanceSheet(tenantId); } @Get('ap/ageing') @ApiOperation({ summary: 'AP Ageing Report' }) async getApAgeing(@Req() req: any) { const tenantId = req.headers['x-tenant-id'] || '60c72b2f9b1d8b23c4d5e6f1'; return this.apSvc.getAgeingReport(tenantId); } @Get('ar/ageing') @ApiOperation({ summary: 'AR Ageing Report' }) async getArAgeing(@Req() req: any) { const tenantId = req.headers['x-tenant-id'] || '60c72b2f9b1d8b23c4d5e6f1'; return this.arSvc.getAgeingReport(tenantId); } @Post('journals') @ApiOperation({ summary: 'Create manual journal draft' }) async createJournal(@Req() req: any, @Body() body: any) { const tenantId = req.headers['x-tenant-id'] || '60c72b2f9b1d8b23c4d5e6f1'; const journal = new this.journalModel({ tenantId: new Types.ObjectId(tenantId), legalEntityId: new Types.ObjectId(body.legalEntityId), accountingBookId: new Types.ObjectId(body.accountingBookId), journalNumber: body.journalNumber || `JV-${Date.now()}`, postingDate: body.postingDate || new Date(), status: 'draft', journalSource: 'Manual', currency: body.currency || 'INR', exchangeRate: body.exchangeRate || 1.0 }); await journal.save(); if (body.lines && Array.isArray(body.lines)) { for (const line of body.lines) { await this.lineModel.create({ journalEntryId: journal._id, ledgerAccountId: new Types.ObjectId(line.ledgerAccountId), debitAmountMinor: line.debitAmountMinor || 0, creditAmountMinor: line.creditAmountMinor || 0, baseDebitAmountMinor: line.debitAmountMinor || 0, baseCreditAmountMinor: line.creditAmountMinor || 0, description: line.description, dimensions: line.dimensions || {} }); } } return journal; } @Post('journals/:id/post') @ApiOperation({ summary: 'Post journal entry' }) async postJournal(@Req() req: any, @Param('id') id: string) { const tenantId = req.headers['x-tenant-id'] || '60c72b2f9b1d8b23c4d5e6f1'; const userId = req.headers['x-user-id'] || '60c72b2f9b1d8b23c4d5e6f2'; return this.postingSvc.postJournalEntry(tenantId, id, userId); } @Post('journals/:id/reverse') @ApiOperation({ summary: 'Reverse journal entry' }) async reverseJournal(@Req() req: any, @Param('id') id: string, @Body() body: any) { const tenantId = req.headers['x-tenant-id'] || '60c72b2f9b1d8b23c4d5e6f1'; const userId = req.headers['x-user-id'] || '60c72b2f9b1d8b23c4d5e6f2'; return this.postingSvc.createReversalJournal(tenantId, id, body.reason || 'Correction', userId); } @Get('journals') @ApiOperation({ summary: 'List journals' }) async listJournals(@Req() req: any) { const tenantId = req.headers['x-tenant-id'] || '60c72b2f9b1d8b23c4d5e6f1'; return this.journalModel.find({ tenantId }).sort({ createdAt: -1 }).exec(); } @Post('bank-accounts') @ApiOperation({ summary: 'Create bank account' }) async createBankAccount(@Req() req: any, @Body() body: any) { const tenantId = req.headers['x-tenant-id'] || '60c72b2f9b1d8b23c4d5e6f1'; return this.bankSvc.createBankAccount(tenantId, body); } @Get('bank-accounts') @ApiOperation({ summary: 'List bank accounts' }) async listBankAccounts(@Req() req: any) { const tenantId = req.headers['x-tenant-id'] || '60c72b2f9b1d8b23c4d5e6f1'; return this.bankSvc.listBankAccounts(tenantId); } @Get('reconciliation/ap-control') @ApiOperation({ summary: 'Reconcile AP Control account' }) async reconcileAPControl(@Req() req: any) { const tenantId = req.headers['x-tenant-id'] || '60c72b2f9b1d8b23c4d5e6f1'; return this.reconciliationSvc.reconcileAPControl(tenantId); } @Get('reconciliation/ar-control') @ApiOperation({ summary: 'Reconcile AR Control account' }) async reconcileARControl(@Req() req: any) { const tenantId = req.headers['x-tenant-id'] || '60c72b2f9b1d8b23c4d5e6f1'; return this.reconciliationSvc.reconcileARControl(tenantId); } @Get('reconciliation/inventory-control') @ApiOperation({ summary: 'Reconcile Inventory Control account' }) async reconcileInventoryControl(@Req() req: any) { const tenantId = req.headers['x-tenant-id'] || '60c72b2f9b1d8b23c4d5e6f1'; return this.reconciliationSvc.reconcileInventoryControl(tenantId); } @Get('reconciliation/payroll-control') @ApiOperation({ summary: 'Reconcile Payroll Control account' }) async reconcilePayrollControl(@Req() req: any) { const tenantId = req.headers['x-tenant-id'] || '60c72b2f9b1d8b23c4d5e6f1'; return this.reconciliationSvc.reconcilePayrollControl(tenantId); } @Get('reconciliation/tax-control') @ApiOperation({ summary: 'Reconcile Tax Control account' }) async reconcileTaxControl(@Req() req: any) { const tenantId = req.headers['x-tenant-id'] || '60c72b2f9b1d8b23c4d5e6f1'; return this.reconciliationSvc.reconcileTaxControl(tenantId); } } |