Appearance
Retenciones de Ganancias sobre Pagos Parciales
Módulo: Compra / CtaCte Tipo: Feature Estado: Implementado Fecha: 2025-12-16 Versión: 2.0 (Con acumulados del período)
Descripción
Problema que resuelve
Al realizar pagos parciales sucesivos de comprobantes de compra que tienen retenciones de ganancias asociadas, es fundamental calcular correctamente sobre qué porción de la base imponible de cada concepto se debe aplicar la retención en cada pago.
Sin un sistema que rastree los montos pagados anteriormente por concepto de retención, se presentan los siguientes problemas:
- Cálculo incorrecto de retenciones: Aplicar retenciones sobre montos ya retenidos en pagos anteriores
- Incumplimiento fiscal: Retener de más o de menos según la normativa vigente
- Falta de trazabilidad: No poder determinar cuánto queda por pagar de cada concepto
- Imposibilidad de validar: No se puede verificar si el cálculo de retención es correcto en pagos parciales
- Complejidad en el frontend: El frontend necesita conocer la lógica compleja de distribución de pagos
Solución propuesta
Se implementa un sistema de cálculo de retenciones sobre pagos parciales que:
Calcula base imponible por concepto: Obtiene automáticamente los conceptos de ganancia y sus montos base desde los items y conceptos del comprobante
Rastrea pagos anteriores: Consulta todas las órdenes de pago anteriores del mismo comprobante para determinar cuánto se ha pagado previamente
Distribuye en orden de prioridad: Aplica los pagos anteriores y el pago actual siguiendo un orden establecido por concepto (código ascendente), completando cada concepto antes de pasar al siguiente
Calcula retención precisa: Aplica la retención solo sobre el monto que realmente se está pagando de cada concepto en la orden de pago actual
Permite consulta previa: El usuario puede consultar en cualquier momento cuánto se debe retener según el monto que decide pagar
Valor de negocio
- Cumplimiento fiscal: Garantiza retenciones correctas según montos reales pagados por concepto
- Precisión: Evita retener de más o de menos en pagos parciales sucesivos
- Transparencia: El usuario ve claramente cuánto se retendrá antes de confirmar el pago
- Flexibilidad: Soporta múltiples pagos parciales del mismo comprobante
- Trazabilidad: Permite auditar cómo se distribuyeron los pagos entre conceptos
- Automatización: El usuario solo indica el monto a pagar, el sistema calcula todo automáticamente
Contexto del sistema
Esta funcionalidad forma parte del módulo de Compras y se relaciona con:
- Conceptos de Ganancia: Configuración de retenciones, porcentajes y mínimos
- Comprobantes de Compra: Facturas y notas de débito de proveedores
- Órdenes de Pago: Registros de pagos realizados a proveedores
- Retenciones Aplicadas: Registro histórico de retenciones por cada pago
- Acumulados de Ganancia: Totales mensuales por proveedor y concepto para informes fiscales
Proceso de Negocio
Flujo principal de cálculo de retenciones en pago parcial
┌─────────────────────────────────────────────────────────────────────────────────┐
│ FLUJO DE CÁLCULO DE RETENCIONES EN PAGOS PARCIALES │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. USUARIO SELECCIONA COMPROBANTE A PAGAR │
│ └── Usuario indica el comprobante y el monto que desea pagar │
│ │ │
│ ▼ │
│ 2. SOLICITUD DE CÁLCULO │
│ └── Usuario solicita calcular cuánto se retendrá │
│ │ │
│ ▼ │
│ 3. VALIDACIONES INICIALES │
│ ├── Comprobante existe y está activo │
│ ├── Monto de pago es positivo │
│ ├── Monto de pago no excede el saldo pendiente │
│ └── Proveedor tiene configuración de inscripción en ganancias │
│ │ │
│ ▼ │
│ 4. OBTENER BASE IMPONIBLE POR CONCEPTO │
│ └── Identificar conceptos de retención del comprobante │
│ Calcular monto base de cada concepto desde items/conceptos │
│ Ordenar conceptos por código (ascendente) │
│ │ │
│ ▼ │
│ 5. CONSULTAR PAGOS ANTERIORES │
│ └── Buscar todas las órdenes de pago anteriores del comprobante │
│ Sumar total pagado anteriormente │
│ │ │
│ ▼ │
│ 6. DISTRIBUIR PAGOS ANTERIORES POR CONCEPTO │
│ └── Aplicar monto pagado anteriormente a conceptos en orden: │
│ - Completar concepto 1 hasta agotar su base │
│ - Luego concepto 2, y así sucesivamente │
│ - Determinar cuánto queda disponible de cada concepto │
│ │ │
│ ▼ │
│ 7. DISTRIBUIR PAGO ACTUAL POR CONCEPTO │
│ └── Aplicar monto del pago actual a conceptos en orden: │
│ - Para cada concepto: disponible = base - pagado_anterior │
│ - Aplicar lo que se pueda del pago actual al concepto │
│ - Pasar al siguiente concepto si aún queda monto por distribuir │
│ │ │
│ ▼ │
│ 8. OBTENER CONFIGURACIÓN DE CONCEPTOS │
│ └── Para cada concepto con monto aplicado: │
│ Obtener porcentajes (inscriptos y no inscriptos) │
│ Obtener mínimo no imponible │
│ │ │
│ ▼ │
│ 9. CONSULTAR ACUMULADOS DEL PERÍODO │
│ └── Extraer mes/año de la fecha del comprobante │
│ Buscar acumulados del proveedor para ese período │
│ Mapear montos acumulados por concepto │
│ │ │
│ ▼ │
│ 10. CALCULAR RETENCIÓN POR CADA CONCEPTO │
│ └── Para cada concepto con monto aplicado > 0: │
│ ├── Calcular: total_acumulado = acumulado + neto │
│ ├── Si total_acumulado < mínimo → No retener │
│ ├── Calcular excedente: total_acumulado - mínimo │
│ ├── Monto imponible: MIN(excedente, monto_aplicado) │
│ ├── Seleccionar porcentaje según inscripción del proveedor │
│ └── Calcular: retención = monto_imponible × (porcentaje / 100) │
│ │ │
│ ▼ │
│ 11. PRESENTAR RESULTADOS AL USUARIO │
│ └── Mostrar: │
│ - Total a retener │
│ - Detalle por concepto (base, porcentaje, retención) │
│ - Distribución del pago entre conceptos │
│ - Información adicional (pagado anteriormente, disponible) │
│ │ │
│ ▼ │
│ 12. USUARIO REVISA Y PUEDE AJUSTAR │
│ └── Usuario ve cuánto se retendrá y puede cambiar el monto a pagar │
│ Si cambia el monto, se recalcula todo el flujo │
│ │ │
│ ▼ │
│ 13. USUARIO CONFIRMA Y SE REGISTRA PAGO │
│ └── Al confirmar, se registra la orden de pago │
│ Se guardan las retenciones calculadas │
│ Se actualizan los acumulados mensuales (monacu y monret) │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘Condiciones previas para el cálculo
Para que se pueda calcular retenciones sobre un pago parcial, deben cumplirse:
- Comprobante de compra registrado: Debe existir un comprobante activo (factura o nota de débito)
- Comprobante con conceptos retenibles: Debe tener al menos un item o concepto sujeto a retención
- Conceptos de ganancia configurados: Las cuentas contables deben estar vinculadas a conceptos de ganancia
- Proveedor con inscripción: El proveedor debe tener configurada su condición de inscripción en ganancias (Inscripto o No Inscripto)
- Conceptos de ganancia activos: Los conceptos de retención referenciados deben estar activos
- Monto de pago válido: El monto a pagar debe ser mayor a 0 y no exceder el saldo pendiente del comprobante
Reglas de Negocio
RN-001: Base imponible por concepto de retención
Descripción: La base imponible de cada concepto de retención se calcula automáticamente desde los items y conceptos del comprobante de compra.
Fundamento: Cada item o concepto de un comprobante tiene asociada una cuenta contable, y esta cuenta puede tener vinculado un concepto de ganancia. La suma de los importes de items/conceptos con el mismo concepto de ganancia determina la base imponible de ese concepto.
Cálculo:
Para cada item del comprobante:
1. Obtener cuenta_contable del item
- Si tiene producto: usar cuenta de compras del producto
- Si no tiene producto: usar cuenta directa del item
2. Buscar concepto de ganancia de la cuenta
3. Si cuenta tiene id_concepto_ganancia:
base_imponible[id_concepto_ganancia] += item.importe
Para cada concepto del comprobante:
1. Obtener cuenta_contable del concepto
2. Buscar concepto de ganancia de la cuenta
3. Si cuenta tiene id_concepto_ganancia:
base_imponible[id_concepto_ganancia] += concepto.importe
Resultado: Array ordenado por código de concepto ASCEjemplo:
COMPROBANTE #1234 - Total: $1000
Items:
- Item 1: $400 → Cuenta 1001 → Concepto Ganancia 1 (Honorarios)
- Item 2: $400 → Cuenta 1002 → Concepto Ganancia 2 (Servicios)
- Item 3: $200 → Cuenta 1003 → Sin concepto de ganancia
Resultado:
[
GananciaAgrupada(id_ganancia: 1, neto: 400.00),
GananciaAgrupada(id_ganancia: 2, neto: 400.00)
]
Base imponible total: $800
Monto sin retención: $200RN-002: Orden de prioridad de conceptos de retención
Descripción: Los conceptos de retención se priorizan por su código de régimen en orden ascendente.
Fundamento: Debe haber un orden determinístico y consistente para distribuir los pagos parciales entre conceptos. El orden por código de régimen (ascendente) garantiza que siempre se aplique la misma lógica.
Regla:
Al distribuir un pago entre conceptos:
1. Ordenar conceptos por código de régimen (ASCENDENTE)
2. Aplicar el pago en ese orden, completando cada concepto antes de pasar al siguiente
3. Nunca pagar parcialmente un concepto si hay conceptos anteriores sin completarEjemplo:
Conceptos del comprobante (ordenados):
- Concepto 1 (Código 100): base $400
- Concepto 2 (Código 200): base $400
- Concepto 3 (Código 300): base $200
Pago de $500:
1. Concepto 1: se asigna $400 (completo)
2. Concepto 2: se asigna $100 (parcial, quedan $300)
3. Concepto 3: se asigna $0 (sin tocar)RN-003: Distribución de pagos anteriores por concepto
Descripción: Antes de calcular retenciones del pago actual, se debe determinar cuánto se pagó de cada concepto en órdenes de pago anteriores del mismo comprobante.
Fundamento: Para saber cuánto queda por pagar de cada concepto, primero debemos saber cuánto ya se pagó.
Proceso:
1. Buscar todas las órdenes de pago anteriores del comprobante:
- Ordenar por fecha ascendente
- Obtener el monto entregado de cada una
2. Sumar total pagado anteriormente:
total_pagado = suma de todos los montos entregados
3. Distribuir ese total entre conceptos siguiendo orden de prioridad:
monto_restante = total_pagado
Para cada concepto en orden:
Si monto_restante > 0:
monto_aplicado = MIN(monto_restante, concepto.neto)
pagado_por_concepto[concepto.id] = monto_aplicado
monto_restante -= monto_aplicado
Sino:
pagado_por_concepto[concepto.id] = 0Ejemplo:
Comprobante con:
- Concepto 1: $600 base
- Concepto 2: $400 base
Órdenes anteriores:
- Orden 1: $300 entregado
- Orden 2: $200 entregado
Total pagado anteriormente: $500
Distribución:
- Concepto 1: MIN(500, 600) = $500 → quedan $100 disponibles
- Concepto 2: MIN(0, 400) = $0 → quedan $400 disponiblesRN-004: Distribución del pago actual por concepto
Descripción: El monto del pago actual se distribuye entre los conceptos siguiendo el orden de prioridad, considerando solo lo que queda disponible de cada concepto.
Fundamento: El pago actual debe aplicarse sobre el monto que REALMENTE queda por pagar de cada concepto, no sobre el monto base original.
Proceso:
1. Calcular disponible por concepto:
Para cada concepto:
disponible[concepto.id] = concepto.neto - pagado_anterior[concepto.id]
2. Distribuir pago actual:
monto_restante = monto_pago_actual
Para cada concepto en orden:
Si monto_restante > 0 AND disponible[concepto.id] > 0:
monto_aplicado = MIN(monto_restante, disponible[concepto.id])
aplicado_por_concepto[concepto.id] = monto_aplicado
monto_restante -= monto_aplicado
Sino:
aplicado_por_concepto[concepto.id] = 0Ejemplo:
Estado después de pagos anteriores:
- Concepto 1: base $600, pagado $500, disponible $100
- Concepto 2: base $400, pagado $0, disponible $400
Pago actual: $250
Distribución:
1. Concepto 1: MIN(250, 100) = $100 (se completa)
Restante: $150
2. Concepto 2: MIN(150, 400) = $150
Restante: $0
Resultado:
aplicado_por_concepto = [1 => 100.00, 2 => 150.00]RN-005: Cálculo de retención con acumulados del período
Descripción: La retención de cada concepto se calcula considerando los acumulados del período (mes/año) para determinar si se alcanzó el mínimo no imponible y sobre qué monto aplicar la retención.
Fundamento: Las retenciones de ganancias se aplican considerando el total acumulado del período. La retención se calcula siempre sobre el excedente del mínimo no imponible, no sobre el neto completo del comprobante.
Proceso:
Para cada concepto donde aplicado_por_concepto[concepto.id] > 0:
1. Obtener configuración del concepto:
- porcentaje_inscripto
- porcentaje_no_inscripto
- monto_minimo (o primera escala si tiene escalas)
2. Obtener acumulado del período:
acumulado_anterior = acumulados[concepto.id] ?? 0.0
(del mes/año del comprobante)
3. Calcular total acumulado:
total_acumulado = acumulado_anterior + concepto.neto
4. Validar mínimo no imponible:
Si total_acumulado < monto_minimo:
→ No retener (retención = 0)
→ Motivo: "Total acumulado no alcanza el mínimo"
→ Continuar con siguiente concepto
5. Determinar método de cálculo según inscripción y configuración del concepto:
**Referencia normativa**: RG AFIP 5423/2023 - Código de Régimen 119
- Inscriptos: Retención según escala específica
- No inscriptos: Retención fija (típicamente 28%)
Si proveedor.insgana = 'S' (INSCRIPTO):
SI concepto tiene escalas configuradas:
→ Aplicar escala progresiva sobre el total_acumulado
→ Buscar escala donde: desde <= total_acumulado <= hasta
**Fórmula de escalas** (ver RG_5423_Codigo_119_Calculo_Retenciones.md):
1. monto_fijo = retención acumulada del tramo anterior (NO se recalcula)
2. excedente_del_tramo = total_acumulado - campo_"S/exc.de$"
3. retención = monto_fijo + (porcentaje / 100) × excedente_del_tramo
Nota: El "monto fijo" es la suma de retenciones de todos los tramos anteriores.
Por ejemplo: $9,940 = $3,550 (tramo 1) + $6,390 (tramo 2)
SI concepto NO tiene escalas:
→ Calcular excedente: excedente = total_acumulado - monto_minimo
→ monto_imponible = MIN(excedente, monto_aplicado)
→ porcentaje = concepto.porcentaje_inscripto
→ Aplicar porcentaje simple sobre excedente
Si proveedor.insgana = 'N' (NO INSCRIPTO):
⚠️ IMPORTANTE: NO INSCRIPTOS NUNCA USAN ESCALAS
→ IGNORAR escalas aunque estén configuradas en el concepto
→ Calcular excedente: excedente = total_acumulado - monto_minimo
→ monto_imponible = MIN(excedente, monto_aplicado)
→ porcentaje = concepto.porcentaje_no_inscripto (típicamente 28%)
→ Aplicar porcentaje fijo sobre excedente
6. Calcular retención:
retencion = monto_imponible * (porcentaje / 100)
8. Registrar resultado del cálculo:
- Concepto de retención
- Monto base sobre el que se retuvo
- Porcentaje aplicado
- Monto de retención calculadoEjemplo sin acumulado previo:
Concepto 1:
- Acumulado anterior: $0
- Neto comprobante: $600
- Total acumulado: $0 + $600 = $600
- Mínimo: $50
- Excedente: $600 - $50 = $550
- Monto aplicado en pago: $300
- Monto imponible: MIN($550, $300) = $300
- Porcentaje: 10%
- Retención: $300 * 10% = $30.00Ejemplo con acumulado que alcanza el mínimo (INSCRIPTO):
Concepto 1:
- Acumulado anterior: $1000
- Neto comprobante: $300
- Total acumulado: $1000 + $300 = $1300
- Mínimo: $1200
- Excedente: $1300 - $1200 = $100
- Monto aplicado en pago: $300
- Monto imponible: MIN($100, $300) = $100
- Proveedor: INSCRIPTO (insgana='S')
- Porcentaje: 10% (porcentaje_inscripto)
- Retención: $100 * 10% = $10.00
⚠️ Se retiene sobre $100 (el excedente), NO sobre $300 (el neto)Ejemplo con proveedor NO INSCRIPTO:
Concepto 1:
- Acumulado anterior: $1000
- Neto comprobante: $300
- Total acumulado: $1000 + $300 = $1300
- Mínimo: $1200
- Excedente: $1300 - $1200 = $100
- Monto aplicado en pago: $300
- Monto imponible: MIN($100, $300) = $100
- Proveedor: NO INSCRIPTO (insgana='N')
- Porcentaje: 28% (porcentaje_no_inscripto, según RG 5423)
- Retención: $100 * 28% = $28.00
⚠️ Aunque el concepto tenga escalas configuradas, NO se usan para no inscriptos
⚠️ SIEMPRE se aplica el porcentaje fijo de 28%RN-006: Validación de monto de pago
Descripción: El monto del pago actual no debe exceder el saldo disponible del comprobante.
Fundamento: No se puede pagar más de lo que se debe.
Validación:
1. Obtener saldo del comprobante:
saldo_comprobante = movimiento.saldo
2. Validar:
Si monto_pago > saldo_comprobante:
→ Error: "Monto de pago excede el saldo disponible del comprobante"RN-007: Acumulados del período
Descripción: Los acumulados de ganancia son montos totales retenidos por proveedor, concepto y período (mes/año). Se utilizan para validar si se alcanzó el mínimo no imponible considerando el historial del período.
Fundamento: Las retenciones de ganancias son acumulativas dentro del período fiscal. El mínimo no imponible se valida contra el total del período, no contra cada comprobante individual.
Estructura:
Registro: Acumulado de Ganancia
Contiene:
- Código de Proveedor: Identificación del proveedor
- Mes: Mes del período (1-12)
- Año: Año del período (ej: 2024)
- Código de Concepto: Referencia al concepto de ganancia
- Monto Acumulado: Suma de montos netos pagados en el período
- Monto Retenido: Total de retenciones aplicadas en el período
Proceso de consulta:
- Extraer mes y año de la fecha del comprobante
- Consultar acumulados por:
- Proveedor
- Mes
- Año
- Mapear resultados indicando:
- Monto acumulado para cada concepto
- Monto retenido para cada concepto
Proceso de actualización (cuando se confirma el pago):
Para cada concepto con retención:
- Buscar el acumulado existente
- Si existe:
- Incrementar monto acumulado con el neto del comprobante
- Incrementar monto retenido con la retención calculada
- Si no existe:
- Crear nuevo registro con los valores iniciales
RN-008: Retención sobre el excedente
Descripción: Las retenciones se aplican siempre sobre el excedente del mínimo no imponible, no sobre el neto completo del comprobante.
Fundamento: La normativa fiscal establece que las retenciones solo se aplican cuando el total acumulado supera el mínimo establecido, y únicamente sobre la porción que excede dicho mínimo.
Regla de cálculo:
total_acumulado = acumulado_período + neto_comprobante_actual
SI total_acumulado >= mínimo_no_imponible:
excedente = total_acumulado - mínimo_no_imponible
monto_imponible = MIN(excedente, monto_pago_actual)
retención = monto_imponible × porcentaje
SINO:
retención = 0 (no se alcanzó el mínimo)Ejemplo ilustrativo:
Proveedor con acumulado de $1,000 en el mes actual
Mínimo no imponible: $1,200
Nuevo comprobante: $300
Cálculo INCORRECTO (sin acumulados):
300 < 1200 → No retiene ❌
Cálculo CORRECTO (con acumulados):
total = 1000 + 300 = 1300
1300 >= 1200 → Sí retiene ✓
excedente = 1300 - 1200 = 100
retención = 100 × 10% = $10 ✓
La retención es sobre $100 (el excedente), NO sobre $300 (el neto)Casos especiales:
- Acumulado = 0: Se calcula sobre el excedente del comprobante actual
- Acumulado cercano al mínimo: Se retiene solo sobre la parte que supera el mínimo
- Acumulado ya superó el mínimo: Se retiene sobre todo el neto del comprobante (todo es excedente)
RN-009: Fecha del período para acumulados
Descripción: El período (mes/año) para consultar acumulados se determina a partir de la fecha del comprobante o fecha del pago, no de la fecha actual del sistema.
Fundamento: Los acumulados deben corresponder al período fiscal del comprobante que se está pagando, no al momento en que se consulta o registra el pago.
Regla:
Input del endpoint:
- fecha: string (formato YYYY-MM-DD)
Extracción del período:
mes = extraer_mes(fecha)
ano = extraer_año(fecha)
Consulta de acumulados:
WHERE mes = :mes AND ano = :anoEjemplo:
Comprobante con fecha: 2024-11-15
Se paga el 2024-12-20
Los acumulados a consultar son de:
mes = 11 (noviembre, mes del comprobante)
ano = 2024
NO del mes 12 (diciembre, mes del pago)RN-010: Cálculo sin persistencia
Descripción: La consulta de cálculo de retenciones NO guarda las retenciones en el sistema, solo las calcula y las muestra al usuario.
Fundamento: El usuario puede consultar múltiples veces con diferentes montos antes de confirmar el pago. El registro definitivo de las retenciones ocurre solo cuando el usuario confirma la orden de pago.
Comportamiento:
- Consulta de cálculo: Solo lectura, calcula y muestra resultados
- Confirmación de pago: Guarda las retenciones y actualiza acumulados
RN-011: Distribución de retenciones por comprobante
Descripción: Cuando se pagan múltiples comprobantes en una misma orden de pago, el sistema informa cuánto de retención corresponde a cada comprobante individual.
Fundamento: El usuario necesita saber exactamente cuánto se retiene de cada factura para poder ajustar el monto de entrega (pago efectivo) de cada comprobante. Sin esta información, no puede determinar cuánto dinero efectivamente llegará al proveedor por cada factura.
Necesidad de negocio:
Cuando el usuario paga por ejemplo:
- Factura A: Quiere pagar $150,000
- Factura B: Quiere pagar $80,000
- Total orden: $230,000
Y el sistema calcula una retención total de $20,000, el usuario necesita saber:
- ¿Cuánto de esos $20,000 corresponde a la Factura A?
- ¿Cuánto corresponde a la Factura B?
Para poder informar al proveedor:
- Por Factura A recibirá: $150,000 - retención factura A
- Por Factura B recibirá: $80,000 - retención factura B
Distribución proporcional:
El sistema distribuye el total de retenciones entre los comprobantes de manera proporcional al monto de pago de cada uno:
Proporción comprobante = Monto pago comprobante / Total pagos orden
Retención comprobante = Total retención × Proporción comprobanteEjemplo:
Orden de pago:
- Comprobante 1: Pago $150,000 (65.2% del total)
- Comprobante 2: Pago $80,000 (34.8% del total)
- Total: $230,000
Retención total calculada: $20,000
Distribución:
- Retención Comprobante 1: $20,000 × 65.2% = $13,043.48
- Retención Comprobante 2: $20,000 × 34.8% = $6,956.52
Montos netos a entregar:
- Comprobante 1: $150,000 - $13,043.48 = $136,956.52
- Comprobante 2: $80,000 - $6,956.52 = $73,043.48Validaciones:
- La suma de retenciones por comprobante debe ser exactamente igual al total de retenciones
- La suma de montos netos debe ser igual al total de pagos menos el total de retenciones
- Cada comprobante debe mostrar su retención individual y su monto neto
Valor de negocio:
- El usuario puede ajustar automáticamente el campo "entrega" de cada comprobante
- Mayor transparencia al ver el desglose exacto de retenciones por factura
- Facilita la comunicación con el proveedor sobre cuánto recibirá por cada factura
- Simplifica la conciliación factura por factura
Ejemplos Detallados
Caso 1: Primera orden de pago parcial
Contexto:
Comprobante de Compra #1234:
- Total: $1000
- Fecha: 01/11/2024
- Proveedor: ABC SA (inscripto en ganancias)
Items:
- Item 1: $600 → Cuenta 1001 → Concepto 1 (Honorarios Profesionales)
- Item 2: $400 → Cuenta 1002 → Concepto 2 (Servicios Técnicos)
Base imponible:
- Concepto 1 (Código 100): $600
- Concepto 2 (Código 200): $400
Configuración de conceptos:
- Concepto 1: 10% inscriptos, $50 mínimo
- Concepto 2: 5% inscriptos, $50 mínimo
Estado inicial:
- Saldo: $1000
- Pagos anteriores: $0Solicitud del usuario:
- Comprobante: #1234
- Monto a pagar: $300
- Proveedor: ABC SA (inscripto)
Proceso de cálculo:
Paso 1: Obtener base imponible
[
GananciaAgrupada(id_ganancia: 1, neto: 600.00),
GananciaAgrupada(id_ganancia: 2, neto: 400.00)
]
Paso 2: Consultar pagos anteriores
recfac WHERE id_comprobante = 'uuid-1234'
→ Sin resultados
→ Total pagado anteriormente: $0
Paso 3: Distribuir pagos anteriores
pagado_por_concepto = [1 => 0.00, 2 => 0.00]
disponible_por_concepto = [1 => 600.00, 2 => 400.00]
Paso 4: Distribuir pago actual ($300)
Monto restante: $300
Concepto 1:
disponible = $600
aplicado = MIN(300, 600) = $300
restante = $0
Concepto 2:
disponible = $400
aplicado = MIN(0, 400) = $0
aplicado_por_concepto = [1 => 300.00, 2 => 0.00]
Paso 5: Calcular retenciones
Concepto 1:
monto_base = $300
minimo = $50
300 >= 50 → Aplica retención
porcentaje = 10% (inscripto)
retencion = 300 * 0.10 = $30.00
Concepto 2:
monto_base = $0
→ No aplica (no se pagó nada de este concepto)
Total retenciones: $30.00Resultado mostrado al usuario:
Total a retener: $30.00
Detalle por concepto:
- Concepto 1 (Honorarios Profesionales):
• Monto base: $300.00 (de $600.00 disponibles)
• Porcentaje: 10%
• Retención: $30.00
• Aplica: Sí
- Concepto 2 (Servicios Técnicos):
• Monto base: $0.00 (de $400.00 disponibles)
• Porcentaje: 5%
• Retención: $0.00
• Aplica: No (no se pagó nada de este concepto)
Distribución del pago entre conceptos:
- Concepto 1: $300.00
- Concepto 2: $0.00
Resumen:
- Base imponible total: $1000.00
- Pagado anteriormente: $0.00
- Disponible total: $1000.00
- Monto pago actual: $300.00Caso 2: Segunda orden de pago (completa concepto 1)
Contexto:
Mismo comprobante #1234 después de primera orden:
Pagos registrados anteriormente:
- Orden #101: $300 pagado el 15/11/2024
Estado actual:
- Saldo: $700
- Base imponible: misma (Concepto 1: $600, Concepto 2: $400)Solicitud del usuario:
- Comprobante: #1234 (mismo comprobante)
- Monto a pagar: $500
- Proveedor: ABC SA (inscripto)
Proceso de cálculo:
Paso 1: Base imponible (sin cambios)
[
GananciaAgrupada(id_ganancia: 1, neto: 600.00),
GananciaAgrupada(id_ganancia: 2, neto: 400.00)
]
Paso 2: Consultar pagos anteriores
recfac WHERE id_comprobante = 'uuid-1234'
→ [{ entregado: 300.00 }]
→ Total pagado anteriormente: $300
Paso 3: Distribuir pagos anteriores ($300)
Concepto 1:
aplicado = MIN(300, 600) = $300
restante = $0
pagado_por_concepto = [1 => 300.00, 2 => 0.00]
disponible_por_concepto = [1 => 300.00, 2 => 400.00]
Paso 4: Distribuir pago actual ($500)
Monto restante: $500
Concepto 1:
disponible = $300
aplicado = MIN(500, 300) = $300 (se completa)
restante = $200
Concepto 2:
disponible = $400
aplicado = MIN(200, 400) = $200
restante = $0
aplicado_por_concepto = [1 => 300.00, 2 => 200.00]
Paso 5: Calcular retenciones
Concepto 1:
monto_base = $300
retencion = 300 * 0.10 = $30.00
Concepto 2:
monto_base = $200
retencion = 200 * 0.05 = $10.00
Total: $30.00 + $10.00 = $40.00Resultado mostrado al usuario:
Total a retener: $40.00
Detalle por concepto:
- Concepto 1 (Honorarios Profesionales):
• Monto base: $300.00 (de $300.00 disponibles)
• Porcentaje: 10%
• Retención: $30.00
• Aplica: Sí (completa el concepto)
- Concepto 2 (Servicios Técnicos):
• Monto base: $200.00 (de $400.00 disponibles)
• Porcentaje: 5%
• Retención: $10.00
• Aplica: Sí
Distribución del pago entre conceptos:
- Concepto 1: $300.00 (se completa el concepto)
- Concepto 2: $200.00
Resumen:
- Base imponible total: $1000.00
- Pagado anteriormente: $300.00
- Disponible total: $700.00
- Monto pago actual: $500.00Caso 3: Tercera orden de pago (cancela factura)
Contexto:
Mismo comprobante #1234 después de dos órdenes:
Pagos registrados anteriormente:
- Orden #101: $300
- Orden #102: $500
Estado actual:
- Saldo: $200Solicitud del usuario:
- Comprobante: #1234 (mismo comprobante, pago final)
- Monto a pagar: $200
- Proveedor: ABC SA (inscripto)
Proceso de cálculo:
Paso 2: Consultar pagos anteriores
→ [{ entregado: 300.00 }, { entregado: 500.00 }]
→ Total pagado anteriormente: $800
Paso 3: Distribuir pagos anteriores ($800)
Concepto 1 (base $600):
aplicado = MIN(800, 600) = $600 (completo)
restante = $200
Concepto 2 (base $400):
aplicado = MIN(200, 400) = $200
restante = $0
pagado_por_concepto = [1 => 600.00, 2 => 200.00]
disponible_por_concepto = [1 => 0.00, 2 => 200.00]
Paso 4: Distribuir pago actual ($200)
Concepto 1:
disponible = $0 → No aplica
Concepto 2:
disponible = $200
aplicado = MIN(200, 200) = $200 (se completa)
aplicado_por_concepto = [1 => 0.00, 2 => 200.00]
Paso 5: Calcular retenciones
Concepto 1:
monto_base = $0 → No retener
Concepto 2:
monto_base = $200
retencion = 200 * 0.05 = $10.00
Total: $10.00Resultado mostrado al usuario:
Total a retener: $10.00
Detalle por concepto:
- Concepto 1 (Honorarios Profesionales):
• Monto base: $0.00 (de $0.00 disponibles)
• Porcentaje: 10%
• Retención: $0.00
• Aplica: No (concepto ya completado en pagos anteriores)
- Concepto 2 (Servicios Técnicos):
• Monto base: $200.00 (de $200.00 disponibles)
• Porcentaje: 5%
• Retención: $10.00
• Aplica: Sí (completa el concepto y cancela la factura)
Distribución del pago entre conceptos:
- Concepto 1: $0.00 (ya completado)
- Concepto 2: $200.00 (se completa)
Resumen:
- Base imponible total: $1000.00
- Pagado anteriormente: $800.00
- Disponible total: $200.00
- Monto pago actual: $200.00Resumen de las 3 órdenes:
Total factura: $1000
- Concepto 1 base: $600
- Concepto 2 base: $400
Orden 1 ($300):
Concepto 1: $300 → Retención $30
Total retenido: $30
Orden 2 ($500):
Concepto 1: $300 (completa los $600) → Retención $30
Concepto 2: $200 → Retención $10
Total retenido: $40
Orden 3 ($200):
Concepto 2: $200 (completa los $400) → Retención $10
Total retenido: $10
TOTALES:
Pagado: $1000
Retenido en Concepto 1: $60 (sobre $600, 10%)
Retenido en Concepto 2: $20 (sobre $400, 5%)
Total retenciones: $80Caso 4: Monto menor al mínimo no imponible
Contexto:
Comprobante con:
- Concepto 1: $100 base
- Concepto 1: mínimo $50, porcentaje 10%
Pago actual: $30Solicitud del usuario:
- Comprobante: #5678
- Monto a pagar: $30
- Proveedor: XYZ SRL
Proceso de cálculo:
Paso 4: Distribuir pago actual ($30)
Concepto 1:
aplicado = $30
Paso 5: Calcular retenciones
Concepto 1:
monto_base = $30
minimo = $50
30 < 50 → NO APLICA RETENCIÓN
aplica = false
retencion = $0Resultado mostrado al usuario:
Total a retener: $0.00
Detalle por concepto:
- Concepto 1 (Honorarios Profesionales):
• Monto base: $30.00 (de $100.00 disponibles)
• Porcentaje: 10%
• Retención: $0.00
• Aplica: No
• Motivo: Monto menor al mínimo no imponible ($50.00)
Distribución del pago entre conceptos:
- Concepto 1: $30.00
Resumen:
- Base imponible total: $100.00
- Pagado anteriormente: $0.00
- Disponible total: $100.00
- Monto pago actual: $30.00
Nota: El usuario puede aumentar el monto a pagar si desea que se aplique
la retención (debe ser mayor a $50.00).Referencias y Documentación Relacionada
Documentación técnica
- Acumulados de Ganancia: Explicación detallada de la lógica de acumulados, reglas RN-007 y RN-008, ejemplos de cálculo sobre excedente.
- Orden de Pago - Retenciones: Proceso completo de registro de órdenes de pago con retenciones.
Implementación
Endpoint: POST /ctacte/retenciones/calcular
Archivos principales:
- Domain:
Domain/CtaCte/Retencion/CalculadorRetenciones.php - Service:
service/CtaCte/RetencionGananciaPagoService.php - Controller:
controller/modulo-ctacte/RetencionGananciaPagoController.php - Tests:
Tests/Unit/CtaCte/RetencionGananciaPagoServiceTest.php
Dependencias:
AcumuladoGananciaService: Gestión de acumulados del períodoMovimientoGananciaService: Obtención de conceptos del comprobanteConceptoGananciaService: Configuración de conceptos
Historial de cambios
| Fecha | Versión | Autor | Descripción |
|---|---|---|---|
| 2025-12-15 | 1.0 | Sistema | Creación del documento de requerimientos |
| 2025-12-16 | 2.0 | Sistema | Actualización con lógica de acumulados del período (RN-007, RN-008, RN-009). Modificación de RN-005 para incluir cálculo sobre excedente. Actualización del flujo de negocio. |