Resumen
En Autoservicio, el precio final de una compra con tarjeta lo fija el plan de cuotas que el cliente elige en el PINPAD. TsTicket registra la diferencia contra el total del ticket como un descuento o recargo global, asignado a cada ítem del ledger, y el ticket cierra exactamente por lo cobrado.
- El monto se define antes de autorizar. Después de autorizar no se recalculan promociones.
- Total del ticket = importe autorizado por APICARD = suma de los movimientos PAGO.
- El ajuste es una línea normal del ledger, por ítem y con su propio tipo. No es una "compensación de diferencias".
- Hay dos formas de calcular el ajuste: con el UltraHost (camino A) o con TsPromos (camino B). B es el destino; A, el mínimo viable.
Alcance: consumidor final (Factura B), sin percepciones, un único pago con tarjeta por ticket, sin cashback.
Cómo es hoy el pago con tarjeta en el kiosco
Según el documento de referencia previo (changeset del 29/10, "compensación pospago"), el pago con tarjeta sigue estos pasos:
- El PINPAD lee la tarjeta.
- El BIN va al UltraHost, que devuelve el emisor y sus planes de cuotas, cada uno con su recargo o descuento.
- El cliente elige un plan. Ese es el monto real que va a pagar.
- Se autoriza ese monto con APICARD, vía TsTicket y TsPagos.
- Ya aprobado el cobro, TsTicket recalcula las promociones con TsPromos. Si el total cambia, absorbe la diferencia con una promoción compensatoria "pospago", imputa el PAGO y cierra el ticket.
Ese enfoque trata el ajuste como una contingencia y confunde dos cosas:
- El ajuste por plan no es una anomalía: ocurre en casi todo pago con cuotas o con promo bancaria.
- "Pospago" en el POS nombra otro concepto (el beneficio de billetera QR que se conoce después de cobrar). Acá el monto se conoce antes de autorizar.
Este documento plantea dos opciones en su lugar, y en ambas el ajuste se trata como ajuste por plan de tarjeta:
- Camino A: el UltraHost define el ajuste y TsTicket lo reparte por ítem.
- Camino B: TsPromos cotiza cada plan antes de autorizar y TsTicket aplica esa cotización.
Concepto: el ajuste vive en el ledger, por ítem
El ajuste por plan es una promoción más del ticket, de alcance global, repartida entre los ítems elegibles. Cada ítem termina con su parte, igual que con cualquier otra promo asociada.
Por qué repartirlo por ítem y no dejarlo como una línea suelta:
- IVA: cada parte toma la alícuota de su ítem, así que neto e IVA contenido cierran sin cálculos por diferencia. En el POS, el recargo de tarjeta clásico quedaba fuera de las alícuotas y terminaba informado a ARCA como impuestos internos.
- Devoluciones: devolver un ítem devuelve su parte, sin recalcular nada.
- Reportes: la línea queda identificada por tipo, emisor y plan.
Qué lleva cada línea de ajuste:
| Atributo | Contenido |
|---|---|
| Tipo | PLAN_TARJETA (camino A) o PROMO_MEDIO_PAGO (camino B) |
| Origen | UltraHost o TsPromos |
| Emisor, plan, cuotas | Lo que eligió el cliente |
| Importe | Con signo: negativo = descuento, positivo = recargo |
| Referencia | Autorización de APICARD y, en B, la cotización aplicada |
Reglas del reparto global (las aplica TsTicket en el camino A; en B el reparto ya viene de TsPromos):
- Base: sólo ítems elegibles. Los rubros que no admiten planes ni promos bancarias quedan afuera (lista a definir).
- Proporción: según el importe final de cada ítem, después de sus promos propias.
- Redondeo: a 2 decimales; el centavo sobrante va al ítem de mayor importe.
- Cierre: la suma de las partes es exactamente el ajuste.
Camino A: el UltraHost define el ajuste
El ajuste sale del plan del emisor que devuelve el UltraHost. Después de aprobar, TsTicket lo reparte en forma proporcional entre los ítems.
- El UltraHost devuelve los planes, cada uno con su recargo o descuento.
- El cliente elige un plan y el PINPAD autoriza ese monto.
- TsTicket calcula
ajuste = importe autorizado − total del ticket, crea la líneaPLAN_TARJETAy la reparte con las reglas de la sección anterior. - TsTicket imputa el PAGO y cierra el ticket.
A favor: no cambia el apidriver ni TsPromos, no agrega latencia en el kiosco y el pago no depende de que TsPromos responda.
En contra:
- El UltraHost no conoce ítems, tipo de cliente ni vigencias: un plan aplica igual a todo el ticket.
- El reparto proporcional es una aproximación. Sólo puede excluir ítems con una lista fija en TsTicket.
- Si TsPromos también aplica promos por banco, hay doble descuento. En este camino, TsPromos no debe aplicar promos por medio de pago.
Camino B: TsPromos cotiza por medio de pago
Antes de mostrar los planes, el apidriver pide al backend una cotización por plan. TsPromos calcula el descuento o recargo con toda su selectividad, y TsTicket aplica esa cotización tal cual después de aprobar.
- El UltraHost devuelve emisor y planes.
- El apidriver pide a TsTicket "cotizar medio de pago", con el ticket, el emisor y los planes.
- TsPromos calcula cada plan con las promos vigentes por ítem, rubro, tipo de cliente y topes. Devuelve el total y la asignación por ítem.
- TsTicket guarda la cotización con un identificador y un vencimiento, y la devuelve.
- El kiosco muestra cada plan con su monto real y el cliente elige.
- El PINPAD autoriza el monto cotizado para ese plan.
- TsTicket aplica la cotización sin volver a llamar a TsPromos, imputa el PAGO y cierra.
Condiciones del diseño:
- Cotización congelada: lo que se muestra es lo que se aplica. Si cambia el ticket (se agrega o quita un ítem), la cotización se invalida.
- Vencimiento: si vence antes de autorizar, se recotiza. Todavía no se cobró nada.
- Coherencia: si el importe autorizado no coincide con la cotización, es un error explícito, no una compensación.
- TsPromos sin respuesta: falla antes de cobrar. Se reintenta o se ofrecen los planes sin promo (decisión pendiente).
A favor: selectividad completa, asignación exacta por ítem, y los fallos de promos ocurren antes de cobrar. Desaparece el recálculo después de aprobar.
En contra: cambia el apidriver, TsTicket (cotización y su guardado) y TsPromos (cálculo por plan). Suma una llamada antes de mostrar los planes, y las promos bancarias dependen de que TsPromos esté disponible.
Comparación y recomendación
Recomendación: empezar por A si hace falta salir rápido, y apuntar a B como diseño final.
| Aspecto | A · UltraHost | B · TsPromos |
|---|---|---|
| Selectividad | Sólo emisor y plan de cuotas | Ítems, rubros, tipo de cliente, vigencias, topes |
| Asignación en el ledger | Reparto proporcional (aproximado) | Por ítem, calculada por TsPromos |
| Cuándo se define el monto | Al elegir el plan, en el Host | Al cotizar, antes de mostrar los planes |
| Recálculo después de aprobar | No | No: se aplica la cotización congelada |
| Si TsPromos no responde | No afecta | Falla antes de cobrar |
| Latencia en el kiosco | Sin cambio | Una llamada más |
| Componentes que cambian | TsTicket | Apidriver, TsTicket y TsPromos |
| Devoluciones | Devuelve la parte prorrateada | Devuelve la parte asignada al ítem |
Cada concepto tiene un solo dueño. Si el plan del Host ya trae un descuento bancario, TsPromos no aplica otro por el mismo banco.
Mejora frente al changeset del 29/10
El Plan B mueve la llamada a TsPromos a antes del cobro. En el changeset actual, todo lo que puede fallar o cambiar el monto pasa después de que APICARD aprobó; en el Plan B pasa cuando todavía no se cobró nada.
| Situación | Actual (changeset 29/10) | Plan B |
|---|---|---|
| TsPromos da timeout | Se conserva el ticket original y se compensa contra él | Se reintenta o se ofrecen planes sin promo. No se cobró nada |
| TsPromos da HTTP 500 | Cobrado y sin cerrar: hay que recuperar la orden | Error antes de mostrar los planes. No se cobró nada |
| El recálculo da otro monto | Se absorbe con una promo compensatoria | No pasa: lo cotizado es lo que se cobra |
| El cliente ve un monto y paga otro | Posible: cotizado sin plan, cobrado con plan | No: ve el monto del plan con sus promos |
| Promo bancaria selectiva por ítem | No se puede: el Host no conoce ítems | TsPromos la calcula por ítem |
| IVA del ajuste en el ledger | Prorrateado, aproximado | Asignado por TsPromos a cada ítem |
| Complejidad después de cobrar | Copia del ticket, clasificar errores, contingencia, compensación | Aplicar la cotización N |
El costo del viaje extra es chico. La llamada a TsPromos ya existe en el flujo actual; el Plan B no la suma, la cambia de lugar. Lo que se agrega es una espera mientras el kiosco muestra los planes, en un momento en que el cliente igual está mirando la pantalla del PINPAD. A cambio desaparecen los casos de "cobrado y sin cerrar" por fallas de promos, que en un kiosco sin cajero son los más caros de resolver.
Lo que se mantiene del changeset: la recuperación de una orden aprobada (ajuste pendiente → aplicado). Sigue haciendo falta por si falla el cierre fiscal o la red después de aprobar.
Ciclo de vida del pago
Los dos caminos comparten los mismos estados; sólo cambia cómo se cotizan los planes y cómo se aplica el ajuste. Todo lo que puede cambiar el monto pasa antes de autorizar.
Cómo se manejan los fallos:
- Denegado: el cliente elige otro plan. No se registró nada en el ledger.
- Cotización vencida o ticket modificado (B): se recotiza antes de autorizar.
- TsPromos sin respuesta (B): pasa antes de cobrar, así que no hay plata en juego.
- Falla después de aprobar (al aplicar el ajuste, imputar o pedir el CAE): la orden queda pagada y el ajuste pendiente queda persistido. Se recupera esa misma orden; nunca se inicia otro cobro. Este mecanismo se mantiene del diseño anterior.
- En el kiosco no hay cajero: la pantalla confirma que el pago quedó registrado, y si la recuperación no termina se avisa al supervisor.
Ejemplo por ítem
Un mismo ticket de $10.000 con cuatro artículos, resuelto por cada camino. Montos ilustrativos.
Camino A. El cliente elige 3 cuotas con 6 % de recargo; el UltraHost cotiza $10.600. El ajuste de +$600 se reparte en proporción al importe de cada ítem, y cada parte toma la alícuota de su ítem.
| Ítem | IVA | Importe ($) | Ajuste ($) | Final ($) | Neto ($) | IVA contenido ($) |
|---|---|---|---|---|---|---|
| Artículo 1 | 21 % | 4.000,00 | +240,00 | 4.240,00 | 3.504,13 | 735,87 |
| Artículo 2 | 10,5 % | 3.000,00 | +180,00 | 3.180,00 | 2.877,83 | 302,17 |
| Artículo 3 | 21 % | 2.000,00 | +120,00 | 2.120,00 | 1.752,07 | 367,93 |
| Artículo 4 | Exento | 1.000,00 | +60,00 | 1.060,00 | 1.060,00 | 0,00 |
| Total | 10.000,00 | +600,00 | 10.600,00 | 9.194,03 | 1.405,97 |
Total del ticket = importe autorizado = $10.600; neto + IVA contenido = $10.600.
Camino B. El Banco X tiene 20 % de descuento en los rubros de los artículos 1 y 2, con tope de $1.000, en 3 cuotas sin interés. El artículo 4 no participa de promos bancarias. TsPromos calcula 20 % de $7.000 = $1.400, aplica el tope de $1.000 y lo asigna sólo a los ítems de la promo.
| Ítem | Importe ($) | Promo Banco X ($) | Final ($) |
|---|---|---|---|
| Artículo 1 | 4.000,00 | −571,43 | 3.428,57 |
| Artículo 2 | 3.000,00 | −428,57 | 2.571,43 |
| Artículo 3 | 2.000,00 | 0,00 | 2.000,00 |
| Artículo 4 | 1.000,00 | 0,00 | 1.000,00 |
| Total | 10.000,00 | −1.000,00 | 9.000,00 |
El kiosco muestra "3 cuotas: $9.000" y el PINPAD autoriza $9.000. Con el camino A, ese mismo descuento de $1.000 se repartiría también sobre los artículos 3 y 4, que no participan de la promo, y el IVA de cada ítem quedaría mal asignado.
Reglas fiscales y de comprobante
Lo informado a ARCA y lo impreso tienen que coincidir con lo cobrado. Como el ajuste ya está asignado por ítem, eso sale sin cálculos por diferencia.
- CAE: importe total = importe autorizado, y neto + IVA + tributos = importe total. Sin percepciones (consumidor final).
- Transparencia fiscal: el IVA contenido y los impuestos internos se calculan por ítem, con su parte del ajuste incluida.
- Redondeo: el residuo de centavos va al neto del ítem de mayor importe; nunca se descarta. En el POS, descartarlo dejaba el CAE desbalanceado en un centavo.
- Recargo financiero: lo habitual es que siga el tratamiento de IVA de la operación principal. A confirmar con el contador, sobre todo para ítems con impuestos internos.
- Comprobante impreso: una sola línea por ajuste, con leyenda clara ("Descuento Banco X 3 cuotas", "Recargo financiero 6 cuotas"). En el POS hubo un caso de línea duplicada que hacía que el ticket no sumara a la vista.
- Devoluciones: se devuelve el importe final del ítem, con su parte del ajuste.
Decisiones pendientes
- Camino a implementar: A o B, y en qué orden.
- Dueño de cada concepto: quién define recargo financiero, descuento bancario y promos por ítem.
- Rubros excluidos de planes y promos bancarias.
- En B, qué se ofrece si TsPromos no responde: reintentar o planes sin promo.
- En B, vencimiento de la cotización.
- Tratamiento fiscal del recargo financiero, confirmado con el contador.
- Leyendas del comprobante y si corresponde informar el costo financiero del plan.
- Qué parte del diseño anterior (copia del ticket, contingencia por timeout) se mantiene.