Add backend API for personal finance management application
- Introduced a comprehensive backend API using TypeScript, Fastify, and PostgreSQL. - Added essential files including architecture documentation, environment configuration, and Docker setup. - Implemented RESTful routes for managing assets, liabilities, clients, invoices, and cashflow. - Established a robust database schema with Prisma for data management. - Integrated middleware for authentication and error handling. - Created service and repository layers to adhere to SOLID principles and clean architecture. - Included example environment variables for development, staging, and production setups.
This commit is contained in:
89
backend-api/src/controllers/DebtCategoryController.ts
Normal file
89
backend-api/src/controllers/DebtCategoryController.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import {FastifyRequest, FastifyReply} from 'fastify';
|
||||
import {DebtCategoryService} from '../services/DebtCategoryService';
|
||||
import {getUserId} from '../middleware/auth';
|
||||
import {z} from 'zod';
|
||||
|
||||
const createCategorySchema = z.object({
|
||||
name: z.string().min(1).max(255),
|
||||
description: z.string().optional(),
|
||||
color: z.string().regex(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/).optional(),
|
||||
});
|
||||
|
||||
const updateCategorySchema = z.object({
|
||||
name: z.string().min(1).max(255).optional(),
|
||||
description: z.string().optional(),
|
||||
color: z.string().regex(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/).optional(),
|
||||
});
|
||||
|
||||
/**
|
||||
* Controller for DebtCategory endpoints
|
||||
* Implements Single Responsibility Principle - handles only HTTP layer
|
||||
*/
|
||||
export class DebtCategoryController {
|
||||
constructor(private categoryService: DebtCategoryService) {}
|
||||
|
||||
/**
|
||||
* Create a new debt category
|
||||
*/
|
||||
async create(request: FastifyRequest, reply: FastifyReply) {
|
||||
const userId = getUserId(request);
|
||||
const data = createCategorySchema.parse(request.body);
|
||||
|
||||
const category = await this.categoryService.create(userId, data);
|
||||
|
||||
return reply.status(201).send({category});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all debt categories
|
||||
*/
|
||||
async getAll(request: FastifyRequest, reply: FastifyReply) {
|
||||
const userId = getUserId(request);
|
||||
const {withStats} = request.query as {withStats?: string};
|
||||
|
||||
if (withStats === 'true') {
|
||||
const categories = await this.categoryService.getWithStats(userId);
|
||||
return reply.send({categories});
|
||||
}
|
||||
|
||||
const categories = await this.categoryService.getAllByUser(userId);
|
||||
return reply.send({categories});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single debt category
|
||||
*/
|
||||
async getOne(request: FastifyRequest, reply: FastifyReply) {
|
||||
const userId = getUserId(request);
|
||||
const {id} = request.params as {id: string};
|
||||
|
||||
const category = await this.categoryService.getById(id, userId);
|
||||
|
||||
return reply.send({category});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a debt category
|
||||
*/
|
||||
async update(request: FastifyRequest, reply: FastifyReply) {
|
||||
const userId = getUserId(request);
|
||||
const {id} = request.params as {id: string};
|
||||
const data = updateCategorySchema.parse(request.body);
|
||||
|
||||
const category = await this.categoryService.update(id, userId, data);
|
||||
|
||||
return reply.send({category});
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a debt category
|
||||
*/
|
||||
async delete(request: FastifyRequest, reply: FastifyReply) {
|
||||
const userId = getUserId(request);
|
||||
const {id} = request.params as {id: string};
|
||||
|
||||
await this.categoryService.delete(id, userId);
|
||||
|
||||
return reply.status(204).send();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user