import type { FastifyPluginAsync } from 'fastify'; import { ZodError } from 'zod'; import { createIncomeSchema, incomeParamsSchema, incomeQuerySchema, incomeUserParamsSchema, updateIncomeSchema, } from './incomes.schema'; import * as incomesService from './incomes.service'; const incomesRoutes: FastifyPluginAsync = async (fastify) => { /** * GET /users/:userId/incomes * Lista todas as rendas de um usuário. * Query params: ?month=6&year=2025 */ fastify.get<{ Params: { userId: string }; Querystring: Record }>( '/users/:userId/incomes', async (request, reply) => { const { userId } = incomeUserParamsSchema.parse(request.params); const query = incomeQuerySchema.parse(request.query); const result = await incomesService.findIncomesByUser(userId, query); return reply.send({ data: result }); }, ); /** GET /users/:userId/incomes/:id — Busca uma renda específica */ fastify.get<{ Params: { userId: string; id: string } }>( '/users/:userId/incomes/:id', async (request, reply) => { const { userId, id } = incomeParamsSchema.parse(request.params); const income = await incomesService.findIncomeById(userId, id); if (!income) { return reply.status(404).send({ error: 'Renda não encontrada.' }); } return reply.send({ data: income }); }, ); /** POST /users/:userId/incomes — Registra a renda de um mês */ fastify.post<{ Params: { userId: string } }>( '/users/:userId/incomes', async (request, reply) => { try { const { userId } = incomeUserParamsSchema.parse(request.params); const body = createIncomeSchema.parse(request.body); const income = await incomesService.createIncome(userId, body); return reply.status(201).send({ data: income }); } catch (err) { if (err instanceof ZodError) { return reply.status(400).send({ error: 'Dados inválidos.', details: err.errors }); } throw err; } }, ); /** PUT /users/:userId/incomes/:id — Atualiza uma renda */ fastify.put<{ Params: { userId: string; id: string } }>( '/users/:userId/incomes/:id', async (request, reply) => { try { const { userId, id } = incomeParamsSchema.parse(request.params); const body = updateIncomeSchema.parse(request.body); const income = await incomesService.updateIncome(userId, id, body); if (!income) { return reply.status(404).send({ error: 'Renda não encontrada.' }); } return reply.send({ data: income }); } catch (err) { if (err instanceof ZodError) { return reply.status(400).send({ error: 'Dados inválidos.', details: err.errors }); } throw err; } }, ); /** DELETE /users/:userId/incomes/:id — Remove uma renda */ fastify.delete<{ Params: { userId: string; id: string } }>( '/users/:userId/incomes/:id', async (request, reply) => { const { userId, id } = incomeParamsSchema.parse(request.params); const deleted = await incomesService.deleteIncome(userId, id); if (!deleted) { return reply.status(404).send({ error: 'Renda não encontrada.' }); } return reply.status(200).send({ data: deleted, message: 'Renda removida com sucesso.' }); }, ); }; export default incomesRoutes;