PCPOS — CYRE · pos_prom.cpp · función TICKET::PromocionesMdeP
Cuando el cliente paga una parte del ticket con un medio de pago que tiene recargo o descuento porcentual (ej. VISA/CORDOBESA), el sistema calculaba mal el porcentaje y el total cobrado (DDMP) no coincidía con el total fiscal del ticket (Tresu/Tdeta). Eso generaba el descuadre de las ~45 zetas de agosto/septiembre. El fix corrige el cálculo en 3 puntos encadenados de la misma función y quedó validado corriendo el POS real.
El recargo/descuento es un porcentaje. Aplicar el % sobre un bruto que ya lo contiene da un valor inflado. Ejemplo con recargo del 10% y un bruto de 100000 que el cajero pone en la tarjeta:
Trata el bruto como si fuera la base:
recargo = bruto × p/100
= 100000 × 10/100
= 10000 (inflado)
100000 no es la base: ya trae el recargo adentro.
Extrae la base contenida en el bruto:
base = bruto / (1 + p/100)
= 100000 / 1.10 = 90909.09
recargo = base × p/100
= 9090.91 (correcto)
Equivale a bruto × p/(100+p).
Aunque se corrigiera el cálculo, más abajo en la misma función eproCons.getPromoySugerido() volvía a pisar el valor con la fórmula vieja (×/100). Por eso el fix necesita, además, neutralizar ese override para el caso del parcial. Este punto es el que solo se ve corriendo el código (no compilando) — el binario del laboratorio simplificado no tenía eproCons y por eso al principio "daba bien" y en producción no.
// una sola linea, sin distinguir bruto
_dTmpMontoPromocion =
(dMontoAPromo * Porcentaje) / 100L;
// ... mas abajo:
if(!eproCons.getPromoySugerido(...)){
_dTmpMontoPromocion = dPromo; // re-pisa
}
// guarda del caso (conservadora)
int iParcialBrutoPorcentaje =
(iPromoIngresoMdeP==1) && !iIngresoLoSugerido
&& (Porcentaje>-100) && (Action==MA_PORCENTAJE)
&& !VALIDAR(Ticket.Percepcion)
&& eproCons.isSinglePromo(IdPromo);
// extraccion de base + topeo
if(iParcialBrutoPorcentaje){
base = dMontoIngresado/(1.0+Porcentaje/100.0);
if(base>dMontoDisponibleParaPromo) base=...;
if(base>dTotalDelTicket) base=...;
_dTmpMontoPromocion = (base*Porcentaje)/100L;
}
// fiscal alineado (Tresu = DDMP)
// eproCons NO pisa si iParcialBrutoPorcentaje
Bruto de 100000 a la tarjeta, resto en EFECTIVO. Base del ticket = 183000 (caso de laboratorio validado).
| Concepto | ANTES (bug) | DESPUÉS (fix) |
|---|---|---|
| Bruto a la tarjeta | 100000.00 | 100000.00 |
| Base cubierta | 90000.00 | 90909.09 |
| Recargo (RecD) | 10000.00 | 9090.91 |
| Saldo restante | 93000.00 | 92090.91 |
| DDMP vs Tresu | ≠ (descuadre) | = 201300... OK |
| Concepto | ANTES (bug) | DESPUÉS (fix) |
|---|---|---|
| Bruto a la tarjeta | 100000.00 | 100000.00 |
| Base cubierta | 114000.00 | 116279.07 |
| Descuento (RecD) | -14000.00 | -16279.07 |
| Saldo restante | 69000.00 | 66720.93 |
| DDMP vs Tresu | ≠ (descuadre) | = 166720.93 OK |
pos_prom.cppeproCons::isSinglePromo() — método nuevo: confirma que hay una sola promo cacheada (evita mezclar bases con multi-promo).iParcialBrutoPorcentaje — conservadora: solo modo 1, promo porcentual (MA_PORCENTAJE), sin percepción, promo única, %>-100 (evita división por cero), y el cajero tipeó el monto.base = bruto/(1+p/100), topeada a lo disponible y al total del ticket, luego recargo = base×p/100.eproCons — se saltea el override para que el valor extraído sobreviva al total.Corrido con el árbol de producción completo (con eproCons) compilado en el entorno DOSBox del kit, con las bases Btrieve reales:
| Caso | DIAG FIX | DIAG FINAL | RecD final | Reconciliación |
|---|---|---|---|---|
| Recargo 10% | 9090.91 | 9090.91 | 9090.91 | DDMP=Tresu |
| Descuento 14% | -16279.07 | -16279.07 | -16279.07 | DDMP=Tresu |
DIAG FIX == DIAG FINAL confirma que eproCons ya no pisa. Parc=1 confirma que la guarda conservadora dispara en los casos reales. CAE OK.
eproCons — validación cruzada fuerte. La versión fusionada adopta además sus guardas de robustez. Y comparando con la versión previa (2025-10-14): el código del recargo es idéntico → no hubo regresión, el bug estaba latente.
Tradeoff conservador: casos con percepción, multi-promo o promo no-porcentual quedan en el camino original (el bug reportado no es de esos: consumidor final, % único, sin percepción). Ampliable si aparecen.
srcs/pos_prom.cpp → .releases/20260728/CYRE/ → CO.BAT → cajas.PCPOS CYRE · fix recargo/descuento en pago parcial · pos_prom.cpp · generado 16/09/2026