Skip to content

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:

  1. Calcula base imponible por concepto: Obtiene automáticamente los conceptos de ganancia y sus montos base desde los items y conceptos del comprobante

  2. Rastrea pagos anteriores: Consulta todas las órdenes de pago anteriores del mismo comprobante para determinar cuánto se ha pagado previamente

  3. 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

  4. 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

  5. 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:

  1. Comprobante de compra registrado: Debe existir un comprobante activo (factura o nota de débito)
  2. Comprobante con conceptos retenibles: Debe tener al menos un item o concepto sujeto a retención
  3. Conceptos de ganancia configurados: Las cuentas contables deben estar vinculadas a conceptos de ganancia
  4. Proveedor con inscripción: El proveedor debe tener configurada su condición de inscripción en ganancias (Inscripto o No Inscripto)
  5. Conceptos de ganancia activos: Los conceptos de retención referenciados deben estar activos
  6. 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 ASC

Ejemplo:

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: $200

RN-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 completar

Ejemplo:

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] = 0

Ejemplo:

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 disponibles

RN-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] = 0

Ejemplo:

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 calculado

Ejemplo 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.00

Ejemplo 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:

  1. Extraer mes y año de la fecha del comprobante
  2. Consultar acumulados por:
    • Proveedor
    • Mes
    • Año
  3. 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:

  1. Buscar el acumulado existente
  2. Si existe:
    • Incrementar monto acumulado con el neto del comprobante
    • Incrementar monto retenido con la retención calculada
  3. 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 = :ano

Ejemplo:

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 comprobante

Ejemplo:

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.48

Validaciones:

  • 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: $0

Solicitud 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.00

Resultado 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.00

Caso 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.00

Resultado 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.00

Caso 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: $200

Solicitud 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.00

Resultado 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.00

Resumen 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: $80

Caso 4: Monto menor al mínimo no imponible

Contexto:

Comprobante con:
  - Concepto 1: $100 base
  - Concepto 1: mínimo $50, porcentaje 10%

Pago actual: $30

Solicitud 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 = $0

Resultado 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

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íodo
  • MovimientoGananciaService: Obtención de conceptos del comprobante
  • ConceptoGananciaService: Configuración de conceptos

Historial de cambios

FechaVersiónAutorDescripción
2025-12-151.0SistemaCreación del documento de requerimientos
2025-12-162.0SistemaActualizació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.