import type { FastifyPluginAsync } from 'fastify'; import { ZodError } from 'zod'; import { createOneTimeExpenseSchema, oneTimeExpenseParamsSchema, oneTimeExpenseQuerySchema, oneTimeExpenseUserParamsSchema, updateOneTimeExpenseSchema, } from './one-time-expenses.schema'; import * as oneTimeService from './one-time-expenses.service'; const oneTimeExpensesRoutes: FastifyPluginAsync = async (fastify) => { /** * GET /users/:userId/one-time-expenses * Lista gastos avulsos do usuário. * Query params: ?month=6&year=2025 */ fastify.get<{ Params: { userId: string }; Querystring: Record }>( '/users/:userId/one-time-expenses', async (request, reply) => { const { userId } = oneTimeExpenseUserParamsSchema.parse(request.params); const query = oneTimeExpenseQuerySchema.parse(request.query); const result = await oneTimeService.findOneTimeExpensesByUser(userId, query); return reply.send({ data: result }); }, ); /** GET /users/:userId/one-time-expenses/:id — Busca um gasto avulso específico */ fastify.get<{ Params: { userId: string; id: string } }>( '/users/:userId/one-time-expenses/:id', async (request, reply) => { const { userId, id } = oneTimeExpenseParamsSchema.parse(request.params); const expense = await oneTimeService.findOneTimeExpenseById(userId, id); if (!expense) { return reply.status(404).send({ error: 'Gasto avulso não encontrado.' }); } return reply.send({ data: expense }); }, ); /** POST /users/:userId/one-time-expenses — Adiciona um gasto avulso */ fastify.post<{ Params: { userId: string } }>( '/users/:userId/one-time-expenses', async (request, reply) => { try { const { userId } = oneTimeExpenseUserParamsSchema.parse(request.params); const body = createOneTimeExpenseSchema.parse(request.body); const expense = await oneTimeService.createOneTimeExpense(userId, body); return reply.status(201).send({ data: expense }); } catch (err) { if (err instanceof ZodError) { return reply.status(400).send({ error: 'Dados inválidos.', details: err.errors }); } throw err; } }, ); /** PUT /users/:userId/one-time-expenses/:id — Atualiza um gasto avulso */ fastify.put<{ Params: { userId: string; id: string } }>( '/users/:userId/one-time-expenses/:id', async (request, reply) => { try { const { userId, id } = oneTimeExpenseParamsSchema.parse(request.params); const body = updateOneTimeExpenseSchema.parse(request.body); const expense = await oneTimeService.updateOneTimeExpense(userId, id, body); if (!expense) { return reply.status(404).send({ error: 'Gasto avulso não encontrado.' }); } return reply.send({ data: expense }); } catch (err) { if (err instanceof ZodError) { return reply.status(400).send({ error: 'Dados inválidos.', details: err.errors }); } throw err; } }, ); /** DELETE /users/:userId/one-time-expenses/:id — Remove um gasto avulso */ fastify.delete<{ Params: { userId: string; id: string } }>( '/users/:userId/one-time-expenses/:id', async (request, reply) => { const { userId, id } = oneTimeExpenseParamsSchema.parse(request.params); const deleted = await oneTimeService.deleteOneTimeExpense(userId, id); if (!deleted) { return reply.status(404).send({ error: 'Gasto avulso não encontrado.' }); } return reply.status(200).send({ data: deleted, message: 'Gasto avulso removido com sucesso.' }); }, ); }; export default oneTimeExpensesRoutes;