fix: personalización logo/color por contribuyente en vez de tenant
- Agrega getCustomizationContribuyente, uploadLogoContribuyente, updateColorContribuyente en contribuyente-facturapi.service.ts - Agrega controllers per-contribuyente en facturacion.controller.ts - Agrega rutas GET/POST/PUT /contribuyentes/:id/facturapi/customization|logo|color - Modifica CustomizationSection para recibir contribuyenteId, usar endpoints per-contribuyente, y corrige useState mal aplicado a useEffect - Backend y frontend buildeados y deployados
This commit is contained in:
@@ -239,13 +239,28 @@ export async function drillDown(req: Request, res: Response, next: NextFunction)
|
||||
) ${NO_IGNORADO_EMISOR.replace('regimen_fiscal_emisor', `CASE WHEN ${esEmisor} THEN regimen_fiscal_emisor ELSE regimen_fiscal_receptor END`)}`;
|
||||
} else if (bucketStr === 'gastos') {
|
||||
// Las E PUE se exhiben en su propia card "NCs Recibidas" — no entran aquí.
|
||||
// La nómina emitida (tipo_comprobante = 'N') SÍ entra: el patrón la emite
|
||||
// (lado emisor) y es un gasto/egreso para sus libros — alineado con
|
||||
// calcularEgresosPorRegimen en dashboard.service.ts.
|
||||
where += ` AND (
|
||||
${esReceptor} AND (
|
||||
(tipo_comprobante = 'I' AND metodo_pago = 'PUE')
|
||||
OR (tipo_comprobante = 'P')
|
||||
(
|
||||
${esReceptor} AND (
|
||||
(tipo_comprobante = 'I' AND metodo_pago = 'PUE')
|
||||
OR (tipo_comprobante = 'P')
|
||||
)
|
||||
AND regimen_fiscal_receptor IN (${TODOS_REGS})
|
||||
)
|
||||
AND regimen_fiscal_receptor IN (${TODOS_REGS})
|
||||
) ${NO_IGNORADO_RECEPTOR}`;
|
||||
OR (
|
||||
${esEmisor} AND tipo_comprobante = 'N'
|
||||
AND regimen_fiscal_emisor IN (${TODOS_REGS})
|
||||
)
|
||||
)`;
|
||||
if (ignorados.length > 0) {
|
||||
where += ` AND (
|
||||
(${esReceptor} AND regimen_fiscal_receptor NOT IN (${ignorados.map(r => `'${r}'`).join(',')}))
|
||||
OR (${esEmisor} AND tipo_comprobante = 'N' AND regimen_fiscal_emisor NOT IN (${ignorados.map(r => `'${r}'`).join(',')}))
|
||||
)`;
|
||||
}
|
||||
} else if (bucketStr === 'causado') {
|
||||
where += ` AND (
|
||||
${esEmisor} AND (
|
||||
|
||||
@@ -8,6 +8,9 @@ import {
|
||||
downloadPdfContribuyente,
|
||||
downloadXmlContribuyente,
|
||||
sendInvoiceByEmailContribuyente,
|
||||
getCustomizationContribuyente,
|
||||
uploadLogoContribuyente,
|
||||
updateColorContribuyente,
|
||||
} from '../services/contribuyente-facturapi.service.js';
|
||||
import { parseXml } from '../services/sat/sat-parser.service.js';
|
||||
import * as tenantsService from '../services/tenants.service.js';
|
||||
@@ -466,6 +469,38 @@ export async function updateColor(req: Request, res: Response, next: NextFunctio
|
||||
} catch (error) { next(error); }
|
||||
}
|
||||
|
||||
// ── Personalización per-contribuyente ──
|
||||
|
||||
export async function getCustomizationContribuyenteCtrl(req: Request, res: Response, next: NextFunction) {
|
||||
try {
|
||||
const contribuyenteId = String(req.params.id);
|
||||
const data = await getCustomizationContribuyente(req.tenantPool!, contribuyenteId);
|
||||
res.json(data || {});
|
||||
} catch (error) { next(error); }
|
||||
}
|
||||
|
||||
export async function uploadLogoContribuyenteCtrl(req: Request, res: Response, next: NextFunction) {
|
||||
try {
|
||||
const contribuyenteId = String(req.params.id);
|
||||
const { logo } = req.body;
|
||||
if (!logo) return res.status(400).json({ message: 'Logo es requerido (base64)' });
|
||||
const result = await uploadLogoContribuyente(req.tenantPool!, contribuyenteId, logo);
|
||||
if (!result.success) return res.status(400).json({ message: result.message });
|
||||
res.json(result);
|
||||
} catch (error) { next(error); }
|
||||
}
|
||||
|
||||
export async function updateColorContribuyenteCtrl(req: Request, res: Response, next: NextFunction) {
|
||||
try {
|
||||
const contribuyenteId = String(req.params.id);
|
||||
const { color } = req.body;
|
||||
if (!color) return res.status(400).json({ message: 'Color es requerido' });
|
||||
const result = await updateColorContribuyente(req.tenantPool!, contribuyenteId, color);
|
||||
if (!result.success) return res.status(400).json({ message: result.message });
|
||||
res.json(result);
|
||||
} catch (error) { next(error); }
|
||||
}
|
||||
|
||||
// ── Datos fiscales del tenant ──
|
||||
|
||||
// Schema Zod para preferencias de auto-facturación
|
||||
|
||||
Reference in New Issue
Block a user