import type { Request, Response, NextFunction } from 'express'; import { AppError } from '../middlewares/error.middleware.js'; import * as fielService from '../services/contribuyente-fiel.service.js'; import * as facturapiService from '../services/contribuyente-facturapi.service.js'; import { getContribuyenteById } from '../services/contribuyente.service.js'; // ========== FIEL ========== export async function uploadFiel(req: Request, res: Response, next: NextFunction) { try { const { cerFile, keyFile, password } = req.body; if (!cerFile || !keyFile || !password) { return next(new AppError(400, 'cerFile, keyFile y password son requeridos')); } const contribuyenteId = String(req.params.id); const contrib = await getContribuyenteById(req.tenantPool!, contribuyenteId); if (!contrib) return next(new AppError(404, 'Contribuyente no encontrado')); const result = await fielService.uploadFielContribuyente(req.tenantPool!, contribuyenteId, cerFile, keyFile, password); if (!result.success) { console.error('[FIEL Upload] Failed:', result.message); return res.status(400).json({ message: result.message }); } return res.json(result); } catch (err: any) { console.error('[FIEL Upload] Exception:', err.message || err); return next(err); } } export async function fielStatus(req: Request, res: Response, next: NextFunction) { try { const contribuyenteId = String(req.params.id); const status = await fielService.getFielStatusContribuyente(req.tenantPool!, contribuyenteId); return res.json(status); } catch (err) { return next(err); } } export async function deleteFiel(req: Request, res: Response, next: NextFunction) { try { const contribuyenteId = String(req.params.id); // Delete from per-contribuyente table (tenant BD) await req.tenantPool!.query( 'UPDATE fiel_contribuyente SET is_active = false WHERE contribuyente_id = $1', [contribuyenteId] ); // Also try to deactivate legacy FIEL if it matches this contribuyente's RFC const { rows } = await req.tenantPool!.query('SELECT rfc FROM contribuyentes WHERE entidad_id = $1', [contribuyenteId]); if (rows[0]?.rfc) { const { prisma } = await import('../config/database.js'); await prisma.fielCredential.updateMany({ where: { rfc: rows[0].rfc }, data: { isActive: false }, }).catch(() => {}); } return res.json({ message: 'FIEL eliminada' }); } catch (err) { return next(err); } } // ========== FACTURAPI ========== export async function createOrg(req: Request, res: Response, next: NextFunction) { try { const contribuyenteId = String(req.params.id); const contrib = await getContribuyenteById(req.tenantPool!, contribuyenteId); if (!contrib) return next(new AppError(404, 'Contribuyente no encontrado')); const result = await facturapiService.createOrgContribuyente(req.tenantPool!, contribuyenteId, contrib.nombre); return res.status(201).json(result); } catch (err: any) { if (err.message?.includes('ya tiene')) return next(new AppError(409, err.message)); return next(err); } } export async function orgStatus(req: Request, res: Response, next: NextFunction) { try { const contribuyenteId = String(req.params.id); const status = await facturapiService.getOrgStatusContribuyente(req.tenantPool!, contribuyenteId); return res.json(status); } catch (err) { return next(err); } } export async function uploadCsd(req: Request, res: Response, next: NextFunction) { try { const { cerFile, keyFile, password } = req.body; if (!cerFile || !keyFile || !password) { return next(new AppError(400, 'cerFile, keyFile y password son requeridos')); } const contribuyenteId = String(req.params.id); const result = await facturapiService.uploadCsdContribuyente(req.tenantPool!, contribuyenteId, cerFile, keyFile, password); if (!result.success) return res.status(400).json({ message: result.message }); return res.json(result); } catch (err) { return next(err); } }