import {FastifyInstance} from 'fastify'; import {DebtCategoryController} from '../controllers/DebtCategoryController'; import {DebtCategoryService} from '../services/DebtCategoryService'; import {DebtCategoryRepository} from '../repositories/DebtCategoryRepository'; import {DebtAccountController} from '../controllers/DebtAccountController'; import {DebtAccountService} from '../services/DebtAccountService'; import {DebtAccountRepository} from '../repositories/DebtAccountRepository'; import {DebtPaymentController} from '../controllers/DebtPaymentController'; import {DebtPaymentService} from '../services/DebtPaymentService'; import {DebtPaymentRepository} from '../repositories/DebtPaymentRepository'; import {authenticate} from '../middleware/auth'; const categoryRepository = new DebtCategoryRepository(); const categoryService = new DebtCategoryService(categoryRepository); const categoryController = new DebtCategoryController(categoryService); const accountRepository = new DebtAccountRepository(); const accountService = new DebtAccountService(accountRepository, categoryRepository); const accountController = new DebtAccountController(accountService); const paymentRepository = new DebtPaymentRepository(); const paymentService = new DebtPaymentService(paymentRepository, accountRepository); const paymentController = new DebtPaymentController(paymentService); export async function debtRoutes(fastify: FastifyInstance) { // Apply authentication to all routes fastify.addHook('onRequest', authenticate); /** * Get all debt categories */ fastify.get( '/categories', { schema: { description: 'Get all debt categories for the authenticated user', tags: ['Debts'], security: [{bearerAuth: []}], querystring: { type: 'object', properties: { withStats: { type: 'string', enum: ['true', 'false'], description: 'Include statistics for each category' } } }, response: { 200: { description: 'List of debt categories', type: 'object', properties: { categories: { type: 'array', items: { type: 'object', properties: { id: {type: 'string'}, name: {type: 'string'}, description: {type: 'string', nullable: true}, color: {type: 'string', nullable: true}, createdAt: {type: 'string'}, updatedAt: {type: 'string'} } } } } } } } }, categoryController.getAll.bind(categoryController) ); /** * Get single debt category */ fastify.get( '/categories/:id', { schema: { description: 'Get a single debt category by ID', tags: ['Debts'], security: [{bearerAuth: []}], params: { type: 'object', properties: { id: {type: 'string'} } }, response: { 200: { description: 'Debt category details', type: 'object', properties: { category: { type: 'object', properties: { id: {type: 'string'}, name: {type: 'string'}, description: {type: 'string', nullable: true}, color: {type: 'string', nullable: true}, createdAt: {type: 'string'}, updatedAt: {type: 'string'} } } } } } } }, categoryController.getOne.bind(categoryController) ); /** * Create debt category */ fastify.post( '/categories', { schema: { description: 'Create a new debt category', tags: ['Debts'], security: [{bearerAuth: []}], body: { type: 'object', required: ['name'], properties: { name: {type: 'string', minLength: 1, maxLength: 255}, description: {type: 'string'}, color: {type: 'string', pattern: '^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$'} } }, response: { 201: { description: 'Debt category created successfully', type: 'object', properties: { category: {type: 'object'} } } } } }, categoryController.create.bind(categoryController) ); /** * Update debt category */ fastify.put( '/categories/:id', { schema: { description: 'Update a debt category', tags: ['Debts'], security: [{bearerAuth: []}], params: { type: 'object', properties: { id: {type: 'string'} } }, body: { type: 'object', properties: { name: {type: 'string', minLength: 1, maxLength: 255}, description: {type: 'string'}, color: {type: 'string', pattern: '^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$'} } }, response: { 200: { description: 'Debt category updated successfully', type: 'object', properties: { category: {type: 'object'} } } } } }, categoryController.update.bind(categoryController) ); /** * Delete debt category */ fastify.delete( '/categories/:id', { schema: { description: 'Delete a debt category', tags: ['Debts'], security: [{bearerAuth: []}], params: { type: 'object', properties: { id: {type: 'string'} } }, response: { 204: { description: 'Debt category deleted successfully', type: 'null' } } } }, categoryController.delete.bind(categoryController) ); // ===== Debt Account Routes ===== /** * Get all debt accounts */ fastify.get( '/accounts', { schema: { description: 'Get all debt accounts for the authenticated user', tags: ['Debts'], security: [{bearerAuth: []}], querystring: { type: 'object', properties: { withStats: {type: 'string', enum: ['true', 'false']}, categoryId: {type: 'string', description: 'Filter by category ID'} } }, response: { 200: { description: 'List of debt accounts', type: 'object', properties: { accounts: {type: 'array', items: {type: 'object'}} } } } } }, accountController.getAll.bind(accountController) ); /** * Get total debt */ fastify.get( '/accounts/total', { schema: { description: 'Get total debt across all accounts', tags: ['Debts'], security: [{bearerAuth: []}], response: { 200: { description: 'Total debt', type: 'object', properties: { totalDebt: {type: 'number'} } } } } }, accountController.getTotalDebt.bind(accountController) ); /** * Get single debt account */ fastify.get( '/accounts/:id', { schema: { description: 'Get a single debt account by ID', tags: ['Debts'], security: [{bearerAuth: []}], params: { type: 'object', properties: { id: {type: 'string'} } }, response: { 200: { description: 'Debt account details', type: 'object', properties: { account: {type: 'object'} } } } } }, accountController.getOne.bind(accountController) ); /** * Create debt account */ fastify.post( '/accounts', { schema: { description: 'Create a new debt account', tags: ['Debts'], security: [{bearerAuth: []}], body: { type: 'object', required: ['categoryId', 'name', 'creditor', 'originalBalance', 'currentBalance'], properties: { categoryId: {type: 'string', format: 'uuid'}, name: {type: 'string', minLength: 1, maxLength: 255}, creditor: {type: 'string', minLength: 1, maxLength: 255}, accountNumber: {type: 'string', maxLength: 100}, originalBalance: {type: 'number', minimum: 0}, currentBalance: {type: 'number', minimum: 0}, interestRate: {type: 'number', minimum: 0, maximum: 100}, minimumPayment: {type: 'number', minimum: 0}, dueDate: {type: 'string', format: 'date-time'}, notes: {type: 'string'} } }, response: { 201: { description: 'Debt account created successfully', type: 'object', properties: { account: {type: 'object'} } } } } }, accountController.create.bind(accountController) ); /** * Update debt account */ fastify.put( '/accounts/:id', { schema: { description: 'Update a debt account', tags: ['Debts'], security: [{bearerAuth: []}], params: { type: 'object', properties: { id: {type: 'string'} } }, body: { type: 'object', properties: { name: {type: 'string', minLength: 1, maxLength: 255}, creditor: {type: 'string', minLength: 1, maxLength: 255}, accountNumber: {type: 'string', maxLength: 100}, currentBalance: {type: 'number', minimum: 0}, interestRate: {type: 'number', minimum: 0, maximum: 100}, minimumPayment: {type: 'number', minimum: 0}, dueDate: {type: 'string', format: 'date-time'}, notes: {type: 'string'} } }, response: { 200: { description: 'Debt account updated successfully', type: 'object', properties: { account: {type: 'object'} } } } } }, accountController.update.bind(accountController) ); /** * Delete debt account */ fastify.delete( '/accounts/:id', { schema: { description: 'Delete a debt account', tags: ['Debts'], security: [{bearerAuth: []}], params: { type: 'object', properties: { id: {type: 'string'} } }, response: { 204: { description: 'Debt account deleted successfully', type: 'null' } } } }, accountController.delete.bind(accountController) ); // ===== Debt Payment Routes ===== /** * Get all debt payments */ fastify.get( '/payments', { schema: { description: 'Get all debt payments for the authenticated user', tags: ['Debts'], security: [{bearerAuth: []}], querystring: { type: 'object', properties: { accountId: {type: 'string', description: 'Filter by account ID'}, startDate: {type: 'string', format: 'date-time'}, endDate: {type: 'string', format: 'date-time'} } }, response: { 200: { description: 'List of debt payments', type: 'object', properties: { payments: {type: 'array', items: {type: 'object'}} } } } } }, paymentController.getAll.bind(paymentController) ); /** * Get total payments */ fastify.get( '/payments/total', { schema: { description: 'Get total payments made across all accounts', tags: ['Debts'], security: [{bearerAuth: []}], response: { 200: { description: 'Total payments', type: 'object', properties: { totalPayments: {type: 'number'} } } } } }, paymentController.getTotalPayments.bind(paymentController) ); /** * Get single debt payment */ fastify.get( '/payments/:id', { schema: { description: 'Get a single debt payment by ID', tags: ['Debts'], security: [{bearerAuth: []}], params: { type: 'object', properties: { id: {type: 'string'} } }, response: { 200: { description: 'Debt payment details', type: 'object', properties: { payment: {type: 'object'} } } } } }, paymentController.getOne.bind(paymentController) ); /** * Create debt payment */ fastify.post( '/payments', { schema: { description: 'Create a new debt payment', tags: ['Debts'], security: [{bearerAuth: []}], body: { type: 'object', required: ['accountId', 'amount', 'paymentDate'], properties: { accountId: {type: 'string', format: 'uuid'}, amount: {type: 'number', minimum: 0.01}, paymentDate: {type: 'string', format: 'date-time'}, notes: {type: 'string'} } }, response: { 201: { description: 'Debt payment created successfully', type: 'object', properties: { payment: {type: 'object'} } } } } }, paymentController.create.bind(paymentController) ); /** * Delete debt payment */ fastify.delete( '/payments/:id', { schema: { description: 'Delete a debt payment', tags: ['Debts'], security: [{bearerAuth: []}], params: { type: 'object', properties: { id: {type: 'string'} } }, response: { 204: { description: 'Debt payment deleted successfully', type: 'null' } } } }, paymentController.delete.bind(paymentController) ); }