Skip to content

Exportación SICORE Retenciones de Ganancias

Módulo: compra Tipo: process Estado: Implementado Fecha: 2026-03-25


Descripción

Proceso de exportación de retenciones de Ganancias al formato SICORE v9.0 de ARCA. Genera un archivo ZIP con dos archivos TXT de posición fija (retenciones.txt y sujetos_retenidos.txt) que el agente de retención debe declarar ante ARCA para el período seleccionado.

La exportación es siempre consolidada: recopila retenciones de todas las sucursales (schemas) del sistema en un único ZIP.


Frontend

Vistas

  • Modal SICORE Retenciones: formulario modal accesible desde el sidebar de Compras → sección Utilidades.
    • Componente: SicoreRetencionesForm (bautista-app/ts/compras/utilidades/views/SicoreRetencionesView.tsx)
    • No es una vista de página — es un modal montado sobre ComprasSidebarApp.

Componentes

  • SicoreRetencionesForm: modal con dos inputs (mes y año). Al exportar, descarga el ZIP automáticamente.
  • Integrado en ComprasSidebarApp.tsx via customHandler['sicore-compras'].

Interacciones del usuario

  1. El usuario abre el sidebar de Compras y hace clic en "Exportación SICORE Retenciones" (sección Utilidades).
  2. Se abre el modal con selección de mes (1-12) y año (YYYY). Por defecto muestra el mes y año actuales.
  3. El usuario presiona "Exportar".
  4. Si la validación local falla (mes fuera de rango, año inválido), se muestra error inline sin llamar al servidor.
  5. Si el servidor devuelve error (período sin datos, proveedores con datos incompletos), se muestra el mensaje textual del backend inline.
  6. Si la operación es exitosa, el ZIP se descarga automáticamente con el nombre sicore_consolidado_MMYYYY.zip.

Permisos

PermisoIDDescripciónAcciones permitidas
COMPRAS_UTILS_EXP-SICORE6023Exportar SICORE Retenciones GananciasAcceder al modal y exportar el ZIP

Backend

Endpoints API

GET /compras/utils/exportar-sicore

Nota: internamente registrado como GET /mod-compra/sicore-retenciones.

  • Descripción: Consolida retenciones de Ganancias del período indicado en todos los schemas y devuelve un ZIP base64 con los TXT SICORE.
  • Permisos: COMPRAS_UTILS_EXP-SICORE (id=6023)
  • Query Params:
    • mes (integer, 1-12): mes del período
    • ano (integer, ej: 2026): año del período
  • Respuesta exitosa (200):
    json
    {
      "data": {
        "retenciones": {
          "file_name": "sicore_consolidado_032026.zip",
          "zip": "<base64>"
        }
      }
    }
  • Errores:
    • 400: parámetros mes o ano inválidos
    • 422: no existen retenciones para el período, o proveedores con datos incompletos (localidad/código postal/provincia faltantes)

Comportamiento consolidado: El endpoint siempre itera todos los schemas que contienen la tabla detgan (vía SchemaService). No existe parámetro modo. Opera 100% sobre la base oficial — nunca usa $db . '_p'.

Archivos que genera el ZIP

ArchivoLongitud de líneaSeparador
retenciones.txt145 chars por líneaCRLF (\r\n)
sujetos_retenidos.txt83 chars por líneaCRLF (\r\n)

El archivo termina con \r\n final. Una línea = una retención (detgan). Un proveedor = una línea en sujetos_retenidos.txt (DISTINCT ON cuit).

Modelos/Entidades

Tablas involucradas en la query principal:

TablaSchemaRol
detgan{schema}Tabla base — una fila = una retención
conganpublicCódigo régimen ARCA (ej: 119)
ordcte (op){schema}Orden de pago — fecha, proveedor, base de cálculo
ordcte (mr){schema}Movimiento de retención — importe
cpdprovpublicProveedor — CUIT, nombre, inscripto, domicilio
localidadespublicLocalidad y código postal (JOIN via p.cpos)
provinciapublicCódigo ARCA de provincia (via localidades.id_prov)
comprobpublicCódigo ARCA del tipo de comprobante
ordcte_subdicom / subdicom{schema}Comprobante vinculado (via LATERAL subquery)
acugan{schema}Contexto acumulado del período (LEFT JOIN)

Nota sobre localidad: El JOIN de localidades usa l.id_loc = p.cpos de forma temporal (BY DESIGN) porque cpdprov.id_localidad no está funcional en la UI de la ficha de proveedor. El campo cpdprov.cloc está vacío en producción y NO debe usarse. Cuando id_localidad sea habilitado en la UI, se debe actualizar el JOIN a l.id_loc = p.id_localidad.

Servicios

SicoreRetenciones.php

Archivo: bautista-backend/models/modulo-compra/SicoreRetenciones.php

Genera los TXT de posición fija y el ZIP base64. Funciones helpers de formato:

FunciónComportamiento
padTexto($val, $len)Alfanumérico — alineado izquierda, relleno con espacios
padEntero($val, $len)Numérico — alineado derecha, relleno con ceros
padImporte($val, $len)Importe con decimales implícitos (1234.56"00000000123456")
formatFechaSICORE($fecha)dd/mm/aaaa (10 chars), o 10 espacios si NULL
limpiarCUIT($cuit)Elimina guiones y no-dígitos
formatNroComprobante($nrocom)Elimina separadores (ej: 0001-12334599000112334599), 16 chars

SicoreRetencionesController.php

Archivo: bautista-backend/controller/modulo-compra/SicoreRetencionesController.php

  • Itera todos los schemas via SchemaService::getSchemasWithTable('detgan').
  • Si no hay retenciones en ningún schema → lanza RuntimeException con mensaje descriptivo.
  • Si hay proveedores con datos incompletos → lanza RuntimeException bloqueante (no genera ZIP).

Validaciones

Validaciones bloqueantes (antes de generar el ZIP)

  1. Datos de proveedor incompletos: Si algún proveedor tiene localidad, cod_postal o provincia_arca faltantes, la exportación se bloquea con RuntimeException listando los proveedores afectados (CUIT + nombre). El usuario debe corregir los datos en la ficha del proveedor antes de poder exportar.
  2. Período sin retenciones: Si $lineasRetenciones === [] tras consolidar todos los schemas, se lanza RuntimeException con mensaje "No existen retenciones de Ganancias registradas para el período MM/YYYY.". No se genera ZIP vacío.
  3. ordcte.zf no numérico: Las filas con zf no numérico se excluyen con WHERE op.zf ~ '^\d+$'.

Reglas de negocio

  1. Consolidación obligatoria: La exportación siempre incluye todas las sucursales del período. No existe exportación por sucursal individual.
  2. Base oficial únicamente: SICORE opera sobre datos reales ($db), no sobre base de prueba.
  3. Período sin datos es error: No se genera ZIP vacío — ausencia de retenciones retorna HTTP 422 con mensaje descriptivo.
  4. Datos incompletos bloquean: Un proveedor con localidad/código postal/provincia faltante impide la exportación. El usuario debe completar la ficha antes de reintentar.
  5. Proveedores sin CUIT son descartados: Si cpdprov.ccui es NULL o vacío, la fila no se incluye en los TXT (no genera error fatal).
  6. Un certificado por retención: Cada registro detgan genera exactamente una línea en retenciones.txt. Cada CUIT único aparece exactamente una vez en sujetos_retenidos.txt.

Casos de uso

Caso 1: Exportación exitosa del período

Actor: Usuario con permiso COMPRAS_UTILS_EXP-SICORE

Precondiciones:

  • Existen retenciones de Ganancias registradas en detgan para el mes/año indicado.
  • Todos los proveedores del período tienen localidad, código postal y provincia mapeados.

Flujo principal:

  1. El usuario abre el modal desde el sidebar de Compras → Utilidades.
  2. Selecciona mes y año.
  3. Presiona "Exportar".
  4. El backend consolida todas las sucursales y genera el ZIP.
  5. El ZIP se descarga automáticamente como sicore_consolidado_MMYYYY.zip.

Postcondiciones:

  • El usuario tiene el ZIP listo para importar en SICORE de ARCA.

Caso 2: Período sin retenciones

Actor: Usuario con permiso COMPRAS_UTILS_EXP-SICORE

Flujo principal:

  1. El usuario selecciona un período sin retenciones registradas.
  2. El backend itera todos los schemas y no encuentra registros.
  3. El modal muestra el mensaje: "No existen retenciones de Ganancias registradas para el período MM/YYYY.".

Flujos alternativos: No se genera ningún archivo.

Caso 3: Proveedor con datos incompletos

Actor: Usuario con permiso COMPRAS_UTILS_EXP-SICORE

Flujo principal:

  1. El usuario intenta exportar un período donde algún proveedor no tiene localidad o código postal.
  2. El modal muestra el listado de proveedores afectados con sus CUIT y nombres.
  3. El usuario debe ir a la ficha del proveedor, completar los datos, y reintentar.

Formato de los archivos TXT (SICORE v9.0)

retenciones.txt — 145 chars por línea

PosiciónLong.CampoValor
1-22Código comprobantecomprob.codigo via LATERAL (ej: 01=Factura)
3-1210Fecha emisión comprobantedd/mm/aaaa
13-2816Número comprobanteSin separadores, alineado izquierda
29-4416Importe comprobanteDecimales implícitos (ordcte_subdicom.subdicom.imptot)
45-484Código impuesto0217 (Ganancias, fijo)
49-513Código régimencongan.codgan (ej: 119)
521Código operación1 (Retención, fijo)
53-6614Base de cálculoDecimales implícitos (ordcte.debe)
67-7610Fecha emisión retencióndd/mm/aaaa
77-782Código condición01=inscripto, 02=no inscripto
791Ret. sujetos suspendidos0 (fijo)
80-9314Importe retenciónDecimales implícitos (ordcte.debe del mov. retención)
94-996Porcentaje exclusión000000 (fijo)
100-10910Fecha vigencia10 espacios (fijo)
110-1112Tipo documento retenido80 (CUIT, fijo)
112-13120CUIT retenidoSin guiones, alineado izquierda
132-14514Número certificado originaldetgan.numret

sujetos_retenidos.txt — 83 chars por línea

PosiciónLong.CampoValor
1-1111CUIT retenidoSin guiones, padding con ceros a la izquierda
12-3120Razón socialcpdprov.cnom
32-5120Domicilio fiscalcpdprov.cdom1
52-7120Localidadlocalidades.nombre
72-732Provinciaprovincia.codigo_arca (fallback 00 si NULL)
74-818Código postallocalidades.cod_post
82-832Tipo documento80 (CUIT, fijo)

Reglas generales de formato

  • Campos alfanuméricos: alineados a la izquierda, relleno con espacios
  • Campos numéricos: alineados a la derecha, relleno con ceros
  • Importes: decimales implícitos sin separador (1234.56"00000000123456")
  • Fechas: dd/mm/aaaa (10 chars)
  • CUIT: sin guiones
  • Números de comprobante: sin separadores (ej: 0001-12334599000112334599)
  • Separador de línea: \r\n (CRLF)
  • El archivo termina con \r\n final

Tablas de códigos ARCA (SICORE v9.0)

Códigos de comprobante (pos 1-2 de retenciones.txt)

CódigoDescripciónScope
01FacturaSoportado
02ReciboSoportado
03Nota de CréditoSoportado — ver nota NC
04Nota de DébitoSoportado
05Otro comprobanteSoportado
06Orden de PagoSoportado
07Recibo de SueldoFuera de scope
08Recibo de Sueldo - DevoluciónFuera de scope
09Escritura PúblicaFuera de scope
10C.1116Fuera de scope
11Factura (16 Dígitos)Fuera de scope

El código proviene de comprob.codigo via la LATERAL subquery. Si el LATERAL no encuentra comprobante → 00.

Nota NC: Para Notas de Crédito (código 03), el campo pos 132-145 debe referenciar la retención original que se reversa. La implementación usa detgan.numret, lo cual requiere validación de negocio para flujos de NC.

Códigos de impuesto (pos 45-48 de retenciones.txt)

CódigoDescripciónScope
0217Impuesto a las GananciasSoportado (hardcodeado)
0218Ganancias — Beneficiarios del ExteriorFuera de scope
OtrosVarios impuestosFuera de scope

Códigos de operación (pos 52 de retenciones.txt)

CódigoDescripciónScope
1RetenciónSoportado (hardcodeado)
2PercepciónFuera de scope
4Imposibilidad de RetenciónFuera de scope

Tipo de documento del retenido (pos 110-111 / 82-83)

CódigoDescripciónScope
80C.U.I.T.Soportado (hardcodeado)
86C.U.I.L.Fuera de scope
87C.D.I.Fuera de scope
83, 84Documentos del ExteriorFuera de scope

Códigos de provincia (pos 72-73 de sujetos_retenidos.txt)

Código ARCAProvincia
00Capital Federal / Ciudad Autónoma de Bs.As.
01Buenos Aires
02Catamarca
03Córdoba
04Corrientes
05Entre Ríos
06Jujuy
07Mendoza
08La Rioja
09Salta
10San Juan
11San Luis
12Santa Fe
13Santiago del Estero
14Tucumán
16Chaco
17Chubut
18Formosa
19Misiones
20Neuquén
21La Pampa
22Río Negro
23Santa Cruz
24Tierra del Fuego
99No se informa (Beneficiarios del Exterior — fuera de scope)

El código proviene de provincia.codigo_arca (columna codigo_arca en tabla cpro). Fallback: 00 si NULL.


Limitaciones conocidas

IDDescripciónSeveridadEstado
G1Número de comprobante con separadores: Si nrocom contiene 0001-12334599, ARCA requiere 000112334599 (sin guión). El helper formatNroComprobante debe aplicar el strip.AltoPendiente corrección
G2CRLF vs LF: Si la implementación usa implode("\n", ...) via LibroIVA::encodeContent, se debe verificar que convierta LF→CRLF. ARCA SICORE requiere \r\n.MedioVerificar
G3CUIT sin padding en sujetos_retenidos.txt (pos 1-11): Si el CUIT tiene menos de 11 dígitos tras limpiar, la línea queda corta. Debe usarse str_pad($cuit, 11, '0', STR_PAD_LEFT).BajoPendiente corrección
G4NC sin certificado original verificado: Para NC (código 03), el campo pos 132-145 debe referenciar la retención original. El flujo actual usa detgan.numret de la NC, lo cual puede no corresponder al certificado original.MedioVerificar con usuario
G6Sin validación de códigos de comprobante: Si comprob.codigo devuelve un valor fuera de la tabla ARCA (01-11), se emite igualmente. Sin impacto si la tabla comprob está bien configurada.InfoSin acción requerida

Consideraciones técnicas

Multi-tenant

  • El controller itera todos los schemas vía SchemaService::getSchemasWithTable('detgan').
  • Cada schema se conecta individualmente con new Database($db, $schemaActual).
  • El resultado es un único ZIP consolidado de todas las sucursales.

Migración requerida

La feature requiere la columna provincia.codigo_arca (smallint NULL) en la tabla cpro:

  • Migration: migrations/migrations/tenancy/YYYYMMDD_add_codigo_arca_to_provincia.php
  • Nivel: LEVEL_EMPRESA (schema public)
  • Incluye seed con los 24 códigos ARCA de provincias argentinas

LATERAL subquery

El comprobante vinculado a la retención se obtiene via LATERAL subquery buscando por oc2.zf = op.zf (mismo proveedor) con comprob.tipo = 'D' (Débitos: facturas y notas de débito). No usar os2.id_movimiento = op.id — la OP nunca está en ordcte_subdicom.

Seguridad

  • El acceso está protegido por el permiso COMPRAS_UTILS_EXP-SICORE (id=6023).
  • No existe modo de prueba para este endpoint — opera únicamente sobre la base oficial.

Dependencias

Funcionalidades relacionadas

  • Ficha de proveedor (cpdprov) — datos de localidad y código postal via campo cpos (temporal)
  • Tabla de localidades (public.localidades) y provincias (public.cpro) — con columna codigo_arca
  • Módulo de órdenes de pago (ordcte) y retenciones de Ganancias (detgan, congan, acugan)

Documentación oficial ARCA

  • AP_INS_SICORER9.pdf — Instructivo SICORE versión 9.0 (disponible en docs/features/compra/)
  • Versión del formato: SICORE v9.0

Historial de cambios

FechaVersiónDescripción
2026-03-251.0Creación del documento — exportación consolidada multi-schema implementada