erp-retail-backend-v2/src/modules/branches/controllers/branch.controller.ts
rckrdmrd a6186c4022 Migración desde erp-retail/backend - Estándar multi-repo v2
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 08:11:34 -06:00

237 lines
6.7 KiB
TypeScript

import { Response, NextFunction } from 'express';
import { BaseController } from '../../../shared/controllers/base.controller';
import { AuthenticatedRequest } from '../../../shared/types';
import { branchService } from '../services/branch.service';
import { BranchStatus, BranchType } from '../entities/branch.entity';
class BranchController extends BaseController {
/**
* GET /branches - List all branches
*/
async list(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<Response | void> {
try {
const tenantId = this.getTenantId(req);
const pagination = this.parsePagination(req.query);
const { status, type, search } = req.query;
const result = await branchService.findAll(tenantId, {
pagination,
filters: [
...(status ? [{ field: 'status', operator: 'eq' as const, value: status }] : []),
...(type ? [{ field: 'type', operator: 'eq' as const, value: type }] : []),
],
search: search
? {
fields: ['name', 'code', 'city'],
term: search as string,
}
: undefined,
});
return this.paginated(res, result);
} catch (error) {
next(error);
}
}
/**
* GET /branches/active - List active branches
*/
async listActive(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<Response | void> {
try {
const tenantId = this.getTenantId(req);
const branches = await branchService.findActiveBranches(tenantId);
return this.success(res, branches);
} catch (error) {
next(error);
}
}
/**
* GET /branches/:id - Get branch by ID
*/
async getById(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<Response | void> {
try {
const tenantId = this.getTenantId(req);
const { id } = req.params;
const branch = await branchService.findById(tenantId, id, ['cashRegisters']);
if (!branch) {
return this.notFound(res, 'Branch');
}
return this.success(res, branch);
} catch (error) {
next(error);
}
}
/**
* GET /branches/code/:code - Get branch by code
*/
async getByCode(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<Response | void> {
try {
const tenantId = this.getTenantId(req);
const { code } = req.params;
const branch = await branchService.findByCode(tenantId, code);
if (!branch) {
return this.notFound(res, 'Branch');
}
return this.success(res, branch);
} catch (error) {
next(error);
}
}
/**
* POST /branches - Create branch
*/
async create(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<Response | void> {
try {
const tenantId = this.getTenantId(req);
const userId = this.getUserId(req);
const result = await branchService.createWithRegister(tenantId, req.body, userId);
if (!result.success) {
if (result.error.code === 'DUPLICATE_CODE') {
return this.conflict(res, result.error.message);
}
return this.error(res, result.error.code, result.error.message);
}
return this.success(res, result.data, 201);
} catch (error) {
next(error);
}
}
/**
* PUT /branches/:id - Update branch
*/
async update(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<Response | void> {
try {
const tenantId = this.getTenantId(req);
const userId = this.getUserId(req);
const { id } = req.params;
const result = await branchService.update(tenantId, id, req.body, userId);
if (!result.success) {
if (result.error.code === 'NOT_FOUND') {
return this.notFound(res, 'Branch');
}
return this.error(res, result.error.code, result.error.message);
}
return this.success(res, result.data);
} catch (error) {
next(error);
}
}
/**
* PATCH /branches/:id/status - Update branch status
*/
async updateStatus(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<Response | void> {
try {
const tenantId = this.getTenantId(req);
const userId = this.getUserId(req);
const { id } = req.params;
const { status } = req.body;
if (!Object.values(BranchStatus).includes(status)) {
return this.validationError(res, { status: 'Invalid status value' });
}
const result = await branchService.updateStatus(tenantId, id, status, userId);
if (!result.success) {
if (result.error.code === 'NOT_FOUND') {
return this.notFound(res, 'Branch');
}
return this.error(res, result.error.code, result.error.message);
}
return this.success(res, result.data);
} catch (error) {
next(error);
}
}
/**
* DELETE /branches/:id - Delete branch
*/
async delete(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<Response | void> {
try {
const tenantId = this.getTenantId(req);
const { id } = req.params;
const result = await branchService.delete(tenantId, id);
if (!result.success) {
if (result.error.code === 'NOT_FOUND') {
return this.notFound(res, 'Branch');
}
return this.error(res, result.error.code, result.error.message);
}
return this.success(res, { deleted: true });
} catch (error) {
next(error);
}
}
/**
* GET /branches/:id/stats - Get branch statistics
*/
async getStats(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<Response | void> {
try {
const tenantId = this.getTenantId(req);
const { id } = req.params;
const exists = await branchService.exists(tenantId, id);
if (!exists) {
return this.notFound(res, 'Branch');
}
const stats = await branchService.getBranchStats(tenantId, id);
return this.success(res, stats);
} catch (error) {
next(error);
}
}
/**
* GET /branches/nearby - Find nearby branches
*/
async findNearby(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<Response | void> {
try {
const tenantId = this.getTenantId(req);
const { lat, lng, radius } = req.query;
if (!lat || !lng) {
return this.validationError(res, { lat: 'Required', lng: 'Required' });
}
const branches = await branchService.findNearby(
tenantId,
parseFloat(lat as string),
parseFloat(lng as string),
radius ? parseFloat(radius as string) : 10
);
return this.success(res, branches);
} catch (error) {
next(error);
}
}
}
export const branchController = new BranchController();