Initial commit - Horux Despachos NL
This commit is contained in:
92
apps/api/src/controllers/plan-catalogo.controller.ts
Normal file
92
apps/api/src/controllers/plan-catalogo.controller.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
import type { Request, Response, NextFunction } from 'express';
|
||||
import { z } from 'zod';
|
||||
import * as planService from '../services/plan-catalogo.service.js';
|
||||
import { prisma } from '../config/database.js';
|
||||
import { invalidateDespachoPlanCache } from '../services/plan-catalogo.service.js';
|
||||
import { canEditPrices } from '../utils/platform-admin.js';
|
||||
import { AppError } from '../middlewares/error.middleware.js';
|
||||
|
||||
export async function getPlans(req: Request, res: Response, next: NextFunction) {
|
||||
try {
|
||||
const vertical = req.query.vertical as string | undefined;
|
||||
const plans = await planService.listPlans(vertical);
|
||||
return res.json({ data: plans });
|
||||
} catch (err) { return next(err); }
|
||||
}
|
||||
|
||||
export async function getAddons(req: Request, res: Response, next: NextFunction) {
|
||||
try {
|
||||
const vertical = req.query.vertical as string | undefined;
|
||||
const addons = await planService.listAddons(vertical);
|
||||
return res.json({ data: addons });
|
||||
} catch (err) { return next(err); }
|
||||
}
|
||||
|
||||
export async function getPlan(req: Request, res: Response, next: NextFunction) {
|
||||
try {
|
||||
const plan = await planService.getPlanByCodename(String(req.params.codename));
|
||||
if (!plan) return res.status(404).json({ message: 'Plan no encontrado' });
|
||||
return res.json(plan);
|
||||
} catch (err) { return next(err); }
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Catálogo despacho — limits + precios editables por admin global
|
||||
// ============================================================================
|
||||
|
||||
/** GET /api/planes/despacho — devuelve los 6 planes con limits + precios. */
|
||||
export async function listDespachoCatalogo(_req: Request, res: Response, next: NextFunction) {
|
||||
try {
|
||||
const plans = await planService.getAllDespachoPlanLimits();
|
||||
return res.json({ data: plans });
|
||||
} catch (err) { return next(err); }
|
||||
}
|
||||
|
||||
const updateSchema = z.object({
|
||||
nombre: z.string().min(1).max(50).optional(),
|
||||
monthly: z.number().nullable().optional(),
|
||||
firstYear: z.number().nullable().optional(),
|
||||
renewal: z.number().nullable().optional(),
|
||||
permiteMonthly: z.boolean().optional(),
|
||||
maxRfcs: z.number().int().optional(),
|
||||
maxUsers: z.number().int().optional(),
|
||||
timbresIncluidosMes: z.number().int().nonnegative().optional(),
|
||||
dbMode: z.enum(['BYO', 'MANAGED']).optional(),
|
||||
permiteServidorBackup: z.boolean().optional(),
|
||||
permiteSatIncremental: z.boolean().optional(),
|
||||
});
|
||||
|
||||
/** PATCH /api/planes/despacho/:plan — actualiza precios/limits. Solo admin con canEditPrices. */
|
||||
export async function updateDespachoCatalogo(req: Request, res: Response, next: NextFunction) {
|
||||
try {
|
||||
if (!req.user || !(await canEditPrices(req.user.userId))) {
|
||||
throw new AppError(403, 'Solo admin global puede editar el catálogo');
|
||||
}
|
||||
const plan = String(req.params.plan);
|
||||
const data = updateSchema.parse(req.body);
|
||||
|
||||
const existing = await prisma.despachoPlanPrice.findUnique({ where: { plan } });
|
||||
if (!existing) throw new AppError(404, `Plan '${plan}' no encontrado`);
|
||||
|
||||
const updated = await prisma.despachoPlanPrice.update({ where: { plan }, data });
|
||||
invalidateDespachoPlanCache();
|
||||
|
||||
return res.json({
|
||||
plan: updated.plan,
|
||||
nombre: updated.nombre,
|
||||
monthly: updated.monthly !== null ? Number(updated.monthly) : null,
|
||||
firstYear: updated.firstYear !== null ? Number(updated.firstYear) : null,
|
||||
renewal: updated.renewal !== null ? Number(updated.renewal) : null,
|
||||
permiteMonthly: updated.permiteMonthly,
|
||||
maxRfcs: updated.maxRfcs,
|
||||
maxUsers: updated.maxUsers,
|
||||
timbresIncluidosMes: updated.timbresIncluidosMes,
|
||||
dbMode: updated.dbMode,
|
||||
permiteServidorBackup: updated.permiteServidorBackup,
|
||||
permiteSatIncremental: updated.permiteSatIncremental,
|
||||
});
|
||||
} catch (err) {
|
||||
if (err instanceof z.ZodError) return next(new AppError(400, err.errors[0].message));
|
||||
return next(err);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user