fix(sat,conciliacion): propagar contribuyenteId en sync SAT y campos faltantes en visor de conciliacion

- sat-sync.job.ts: cron diario e incremental ahora iteran contribuyentes
  por tenant y pasan contribuyenteId a startSync(). Evita que CFDIs
  importados del SAT queden con contribuyente_id = NULL.

- sat.service.ts: retryJob() ahora reintenta con job.contribuyenteId.

- conciliacion.service.ts: agrega campos faltantes al SELECT de CFDIs:
  status, formaPago, serie, folio, usoCfdi, subtotal, descuento,
  moneda, tipoCambio, ivaTraslado, ivaRetencion, isrRetencion,
  fechaCertSat. Antes el visor mostraba 'CANCELADO' para todos los
  CFDIs (status era undefined) y faltaban datos de forma de pago,
  impuestos, serie/folio, etc.

Refs: docs/CAMBIOS-2026-05-09.md secciones 6 y 7
This commit is contained in:
Horux Dev
2026-05-11 03:58:53 +00:00
parent 9f11a0ba39
commit e21ccd6860
4 changed files with 237 additions and 25 deletions

View File

@@ -6,6 +6,8 @@ export interface ConciliacionCfdi {
id: number;
uuid: string;
type: string;
serie: string | null;
folio: string | null;
fechaEmision: string;
rfcEmisor: string;
nombreEmisor: string;
@@ -13,7 +15,19 @@ export interface ConciliacionCfdi {
nombreReceptor: string;
total: number;
totalMxn: number;
subtotal: number;
descuento: number;
moneda: string;
tipoCambio: number;
tipoComprobante: string | null;
metodoPago: string | null;
formaPago: string | null;
usoCfdi: string | null;
status: string | null;
fechaCertSat: string | null;
ivaTraslado: number;
ivaRetencion: number;
isrRetencion: number;
conciliado: string | null;
idConciliacion: number | null;
conciliacion: {
@@ -78,13 +92,23 @@ export async function getCfdisConConciliacion(
const { rows } = await pool.query(`
SELECT
c.id, c.uuid, c.type,
c.serie, c.folio,
c.fecha_emision as "fechaEmision",
c.rfc_emisor as "rfcEmisor", c.nombre_emisor as "nombreEmisor",
c.rfc_receptor as "rfcReceptor", c.nombre_receptor as "nombreReceptor",
c.total, c.total_mxn as "totalMxn",
c.subtotal, c.descuento,
c.moneda, c.tipo_cambio as "tipoCambio",
c.tipo_comprobante as "tipoComprobante",
c.monto_pago_mxn as "montoPagoMxn",
c.metodo_pago as "metodoPago",
c.forma_pago as "formaPago",
c.uso_cfdi as "usoCfdi",
c.status,
c.fecha_cert_sat as "fechaCertSat",
c.iva_traslado as "ivaTraslado",
c.iva_retencion as "ivaRetencion",
c.isr_retencion as "isrRetencion",
c.conciliado,
c.id_conciliacion as "idConciliacion",
con.id as "conId",
@@ -102,6 +126,8 @@ export async function getCfdisConConciliacion(
id: r.id,
uuid: r.uuid,
type: r.type,
serie: r.serie,
folio: r.folio,
fechaEmision: r.fechaEmision,
rfcEmisor: r.rfcEmisor,
nombreEmisor: r.nombreEmisor,
@@ -109,6 +135,10 @@ export async function getCfdisConConciliacion(
nombreReceptor: r.nombreReceptor,
total: Number(r.total),
totalMxn: Number(r.totalMxn),
subtotal: Number(r.subtotal || 0),
descuento: Number(r.descuento || 0),
moneda: r.moneda || 'MXN',
tipoCambio: Number(r.tipoCambio || 1),
tipoComprobante: r.tipoComprobante,
montoPagoMxn: Number(r.montoPagoMxn || 0),
// P usa monto_pago_mxn, PPD conciliada no suma (evitar duplicar con su P), resto usa total_mxn
@@ -116,6 +146,13 @@ export async function getCfdisConConciliacion(
? Number(r.montoPagoMxn || 0)
: (r.metodoPago === 'PPD' && r.conciliado === 'true') ? 0 : Number(r.totalMxn || 0),
metodoPago: r.metodoPago,
formaPago: r.formaPago,
usoCfdi: r.usoCfdi,
status: r.status,
fechaCertSat: r.fechaCertSat,
ivaTraslado: Number(r.ivaTraslado || 0),
ivaRetencion: Number(r.ivaRetencion || 0),
isrRetencion: Number(r.isrRetencion || 0),
conciliado: r.conciliado,
idConciliacion: r.idConciliacion,
conciliacion: r.conId ? {

View File

@@ -1511,5 +1511,5 @@ export async function retryJob(jobId: string): Promise<string> {
throw new Error('Solo se pueden reintentar jobs fallidos');
}
return startSync(job.tenantId, job.type, job.dateFrom, job.dateTo);
return startSync(job.tenantId, job.type, job.dateFrom, job.dateTo, job.contribuyenteId ?? undefined);
}