Aceptación de dólares por encima del saldo, con vuelto en pesos

POS Becerra, versión 20261014P. Documento para el equipo POS de Tipre y para quienes implementan en Becerra.

Rama: vuelto-dolar Base: port multimoneda 0dd9d2a (20261006P) Pruebas: 2026-10-14/15 y ronda QA 2026-10-19, laboratorio

En una mirada

1. Qué hace y para qué

Hasta la versión 20261006P, el medio de pago multimoneda DOLAR solo admitía USD hasta cubrir el saldo, con tope floor(saldo / cotización). Si el cliente traía un billete de más, el cajero no podía aceptarlo y el resto se pagaba en pesos.

Desde 20261014P, cuando los datos lo habilitan, el POS acepta más USD que el saldo. La diferencia se entrega como vuelto en pesos, con el medio EFECTIVO. El dólar nunca da vuelto en dólares.

Ejemplo resuelto (ticket de prueba 504)

Total del ticket$ 12.490,00
Cotización DOLAR (Pizarra)1520,00
Entrega el clienteUSD 10 = $ 15.200,00
Vuelto en efectivo$ 2.710,00

Cálculo: 10 × 1520 − 12.490 = 2.710.

Rango de USD aceptado

ValorFórmulaEjemplo (saldo 12.490, cot. 1520)
Mínimo que cubre el saldoceil(saldo / cot)ceil(8,217) = 9 → USD 9 = $ 13.680, vuelto $ 1.190
Máximo por vueltofloor((saldo + dLimite) / cot)con dLimite 5.000: floor(17.490 / 1520) = 11
Máximo por importefloor(999.999,99 / cot)floor(657,89) = 657 → $ 998.640
Máximo aceptadoel menor de los doscon dLimite 99.999.999,99 rige 657
Tope anterior (sin habilitar)floor(saldo / cot)floor(8,217) = 8 → máx. $ 12.160
¿De dónde sale el límite? El límite es el vuelto máximo en pesos y sale solo de la fila dM_VmdeP DOLAR→EFECTIVO: su dLimite (o el porcentaje dPorcentaje sobre el total, si no es 0, acotado por dLimite). Es la misma regla que ya usa el POS para el vuelto (VerCruceMdeP).
  • Desde 2026-10-19 dM_MdeP(DOLAR).dPorcCobrar ya no limita: CheckLimites (mensaje 388 al cerrar) exceptúa al medio multimoneda con sobrepago habilitado. dPorcCobrar queda en 100. Antes, con 100, un total de $ 1.000 solo admitía USD 65; ahora un total de $ 1.490 acepta USD 100 con vuelto $ 150.510 (Q1).
  • Tope de importe: USD × cotización ≤ $ 999.999,99. Es el máximo del campo Importe de los diálogos de medio de pago (PCPOS.RES, máscara 999999.99). Un importe mayor se truncaba en silencio al cargarse en el diálogo (probado: USD 65.789 × 1520 quedó como $ 999.992,80). Como el vuelto es menor que el importe, también queda bajo ese tope.
Con dLimite = 99.999.999,99 ("sin límite"), el log muestra MaxVuelto:999999.99. Para limitar el vuelto, se baja dM_VmdeP.dLimite con SETVUELT 9 1 /APPLY <límite> o en el maestro (§3, §4).

Cuándo está activo

El sobrepago se habilita solo si se cumple todo; si falta algo, rige el tope anterior:

Además, con la versión nueva los USD deben ser enteros (billetes) en el tipo billete, haya o no sobrepago.

2. Flujo del cajero paso a paso

Teclas Las teclas citadas son las de los datos de prueba (remapeo en EVENTOS4.DAT del laboratorio): F6 Medios de Pago, F7 Total, Ctrl+F9 vuelto automático (evento 8303, kbVUELTO_AUTOMA). El mapa de teclas de producción puede ser distinto: confirmarlo en cada sucursal.
  1. Registrar los artículos como siempre. Total del ejemplo: $ 12.490.
  2. Medios de Pago (F6 en los datos de prueba). Si aparecen promociones, se continúa. Se baja hasta DOLAR y se confirma con Enter.
  3. Consulta de cotización. El POS consulta a Pizarra; la pantalla muestra [MULTIMON] Procesando c/servidor remoto... [0 de 10 seg] Si Pizarra no responde o la cotización está suspendida, el medio no se puede usar: No se puede usar el Medio de Pago
  4. Recuadro de ayuda. Con el sobrepago habilitado, muestra una línea con la cotización y el saldo: Cotiz.DOLAR:1520.00 Saldo $: 12490.00
  5. Ingreso de USD. La línea de ingreso indica los USD mínimos que cubren el saldo y el vuelto en pesos que darían (sin máximo): Dolar con 9 cubre saldo (vuelto $1190): El vuelto se muestra sin decimales si es entero y con 2 decimales si no. El cajero tipea los billetes recibidos, por ejemplo 10, y Enter. El saldo queda negativo (SaldT:-2710.00 en el log). Captura: evidence/…/ingreso-dolar-v2.png.
    • Con decimales (por ejemplo 10.5): se rechaza y vuelve a pedir el monto. DOLAR sin decimales: ingrese solo billetes enteros!
    • Vuelto mayor que el límite (dLimite de la fila 9→1): Vuelto max $5000.00 (max 11 DOLAR), reingrese!
    • Importe mayor que $ 999.999,99: Importe max $999999.99 (max 657 DOLAR), reingrese! Ambos mensajes entran completos en la línea de estado (verificado en pantalla).
    • Vacío: cancela el ingreso de DOLAR.
  6. Vuelto. Se presiona la tecla de vuelto automático (Ctrl+F9 en los datos de prueba). El POS asigna el vuelto a EFECTIVO: diálogo EFECTIVO 2710.00.
  7. Cierre del ticket. Se cierra el ticket (con MODO_TECLA_VUELTO activo, la tecla de vuelto pasa directo al cierre). El ticket impreso muestra:
    TOTAL :                         12490.00
    DOLAR 10.00          15200.00
    SU PAGO:                        15200.00
    EFECTIVO             2710.00
    VUELTO:                          2710.00
  8. Entregar $ 2.710 en efectivo al cliente.

Si el sobrepago está deshabilitado (o los datos no están completos)

El POS vuelve al comportamiento anterior (prueba V5):

Cotiz.DOLAR:1520.00 Maximo monto a cubrir en $: 12160 Ingrese DOLAR (max 8.00): 10 Supera monto maximo permitido, reingrese!

El cajero cobra USD 8 ($ 12.160) y el resto ($ 330) en efectivo u otro medio. Si el saldo es menor que una unidad de USD, sin sobrepago aparece El saldo a pagar es menor al permitido con DOLAR. Con sobrepago, ese caso se acepta con USD 1 y vuelto.

Combinaciones admitidas

3. Configuración: tablas, perfiles y Pizarra

Tablas de medios de pago

Los ids son los de Becerra en laboratorio: DOLAR grupo 9 (detalle 9/10), EFECTIVO 1.

Tabla / registroCampoAntesDespuésNota
dM_MdeP uId 9 (DOLAR)iVuelto10El dólar no da vuelto propio; el vuelto sale por EFECTIVO.
dPorcCobrar100100 (sin cambios)Desde 2026-10-19 no limita el sobrepago: CheckLimites (mensaje 388) exceptúa al medio multimoneda habilitado. Si un POS quedó con 10000 por la versión anterior de SETVUELT, /UNDO lo vuelve a 100.
dM_MdeP uId 9dLimite, dUnidad, dMaxVuelto99999999.99 / 0 / 0sin cambiosNo tocar. Bajar dLimite provoca el mensaje 373. dUnidad y dMaxVuelto deben quedar en 0.
dM_VmdePfila uId 9 → uIdv 1no existe1 fila: dLimite 99999999.99, dPorcentaje 0Es el límite del vuelto. Única fila con uId=9. La fila 3→1 existente no se toca.
dM_DmdeP 9/10iTaxnumber11Requisito: 1 = billetes enteros. Grupo dM_MdeP 9 "DOLAR".
dM_MdeP uId 1 (EFECTIVO)dUnidad, dMaxVuelto0 / 0sin cambiosEn 0, el vuelto en efectivo es exacto (si la cotización tiene centavos, el vuelto también).
¿Por qué no se usa la unidad monetaria para exigir USD enteros? dM_MdeP.dUnidad y dM_UniMo validan el importe en pesos (USD × cotización), que cambia con cada cotización. No pueden expresar "USD entero". Esa regla vive en POS_MMON.DLL. En DOLAR y EFECTIVO, dUnidad y dMaxVuelto deben quedar en 0.

Después de cambiar dM_VmdeP hay que reiniciar el POS: la tabla se carga en memoria una sola vez al iniciar.

Perfiles

PerfilNombre / usoValor
554MULTIMONEDA_HABILITADO1. El valor -999 es simulación (cotización fija 1200): solo para laboratorio.
555IP del servidor PizarraIP de la sucursal / central (en laboratorio 10.0.2.2)
556Puerto de Pizarra8084
557Timeout de recepción (seg)en laboratorio 10
558Timeout de conexión (seg)en laboratorio 5
237NRO_SUCURSALnúmero de sucursal que se envía a Pizarra (BranchNumber; en laboratorio 13)
200ID_MDEP_VUELTO_DEF0 = efectivo (toma el perfil 22)
22ID_EFECTIVO1
171PERMITE_PROMO_MDEP1

Ningún perfil cambia con esta funcionalidad; la tabla sirve para verificar que estén bien.

Servidor Pizarra

4. Cómo habilitar y deshabilitar

Las tablas se distribuyen desde el servidor dM_MdeP y dM_VmdeP figuran en dE_Tranf. Cuando el servidor publica una versión nueva, el POS baja el archivo y reemplaza el .dat entero. Un cambio local hecho con SETVUELT se pierde con la próxima versión del maestro. El camino definitivo es el maestro central.

A. Camino recomendado: maestro central

  1. En el maestro central de Becerra, confirmar que existe el grupo dM_MdeP 9 "DOLAR" y que dM_DmdeP 9/10 tiene iTaxnumber = 1.
  2. En dM_MdeP uId 9: iVuelto 1 → 0. No tocar dPorcCobrar (100), dLimite, dUnidad ni dMaxVuelto.
  3. En dM_VmdeP: agregar la fila uId 9, uIdv 1, dLimite 99999999.99, dPorcentaje 0 (o el límite que defina el cliente). Que sea la única fila con uId 9.
  4. Publicar ambas tablas con versión nueva para que los POS las descarguen.
  5. Reiniciar cada POS y verificar con SETVUELT 9 1 (solo lectura) y un ticket real tipo V1.

Para deshabilitar: publicar iVuelto = 1 y sin la fila 9→1 (y dPorcCobrar = 100 si había quedado en 10000), con versión nueva.

B. SETVUELT.EXE: piloto, laboratorio o emergencia

Herramienta de consola (misma familia que SETMDTAX e INSMDEP). Se ejecuta con el POS detenido, con DDFDIR y DATADIR definidos y el motor Btrieve cargado.

SETVUELT <uIdMMon> <uIdVuelto>                 ver (solo lectura)
SETVUELT <uIdMMon> <uIdVuelto> /APPLY [lim]    habilitar / cambiar el límite de vuelto ($, default 99999999.99)
SETVUELT <uIdMMon> <uIdVuelto> /UNDO           deshabilitar

Salidas reales (laboratorio)

/UNDO sobre un POS que tenía dPorcCobrar=10000 y /APPLY nuevo (2026-10-19):

---- SETVUELT 9 1 /UNDO
ANTES:
  dM_MdeP uId=9 (DOLAR): iVuelto=0 dPorcCobrar=10000.00 dLimite=99999999.99 dUnidad=0.00 dMaxVuelto=0.00
  dM_VmdeP 9->1: 1 fila(s) dLimite=99999999.99 dPorcentaje=0.00   otras filas uId=9: 0
DESPUES (relectura):
  dM_MdeP uId=9 (DOLAR): iVuelto=1 dPorcCobrar=100.00 dLimite=99999999.99 dUnidad=0.00 dMaxVuelto=0.00
  dM_VmdeP 9->1: 0 fila(s)   otras filas uId=9: 0
OK - GRABADO Y RELEIDO
---- SETVUELT 9 1 /APPLY
DESPUES (relectura):
  dM_MdeP uId=9 (DOLAR): iVuelto=0 dPorcCobrar=100.00 dLimite=99999999.99 dUnidad=0.00 dMaxVuelto=0.00
  dM_VmdeP 9->1: 1 fila(s) dLimite=99999999.99 dPorcentaje=0.00   otras filas uId=9: 0
OK - GRABADO Y RELEIDO
---- SETVUELT 9 1 /APPLY 5000
DESPUES (relectura):
  dM_VmdeP 9->1: 1 fila(s) dLimite=5000.00 dPorcentaje=0.00   otras filas uId=9: 0
OK - GRABADO Y RELEIDO

/UNDO repetido (idempotencia):

---- SETVUELT 9 1 /UNDO
ANTES:
  dM_MdeP uId=9 (DOLAR): iVuelto=1 dPorcCobrar=100.00 dLimite=99999999.99 dUnidad=0.00 dMaxVuelto=0.00
  dM_VmdeP 9->1: 0 fila(s)   otras filas uId=9: 0
  ...
SIN CAMBIOS: ya esta deshabilitado

Línea de SETVUELT.BAK:

Wed Oct 14 23:29:47 2026 accion=APPLY uIdMMon=9 uIdVuelto=1 | dM_MdeP existe=1 iVuelto=1 dPorcCobrar=100.00 dLimite=99999999.99 dUnidad=0.00 dMaxVuelto=0.00 | dM_VmdeP filas=0 dLimite=0.00 dPorcentaje=0.00 otras=0
Corrección incluida (d306e1e) La primera versión de /UNDO borraba con DDF::del(), que solo marca el registro, y la fila 9→1 seguía presente. Ahora borra con Btrieve Remove(). Usar el SETVUELT.EXE de md5 b21eba88… (2026-10-19) o posterior.

5. Binarios y fuentes modificados

Commits

CommitFechaDescripción
0dd9d2a2026-10-06Port multimoneda (Pizarra/USD) desde DINO_20260902; versión 20261006P/F. Base de este cambio.
31f714e2026-10-14feat(multimoneda): sobrepago en USD con vuelto en efectivo (20261014P).
d306e1e2026-10-15fix(setvuelt): borra filas de dM_VmdeP con Btrieve Remove.
0172b802026-10-15docs: plan y estado.
ab5a6542026-10-15fix(multimoneda): recuadro de ayuda compactado (primer intento).
a2e772c2026-10-15fix(multimoneda): el vuelto pasa a la línea de ingreso y el recuadro queda en una línea, porque la ventana de ingreso tapaba las líneas 2 y 3. Verificado en pantalla.
0f72adb2026-10-19feat(multimoneda): dM_VmdeP.dLimite es el único límite del vuelto (excepción en CheckLimites, VerificarDMP ya no acota por dPorcCobrar); línea de ingreso Dolar con N cubre saldo (vuelto $X):; mensajes de vuelto e importe máximos; SETVUELT sin dPorcCobrar.
56dde9d2026-10-19fix(multimoneda): con 0f72adb POS_MAIN no cargaba las DLL (Phar Lap GP 286.3360: DGROUP llegó a 0xFE2C); helpers internos (static) y sin la constante double en POS_MAIN (DGROUP 0xFE1C, arranca). Tope del pago en USD = $ 999.999,99 (campo Importe).

Cambios por archivo (0dd9d2a..vuelto-dolar, +457/−13)

ArchivoMóduloQué cambió
pos_mmon.cppPOS_MMON.DLLRecibe de POS_MAIN el vuelto máximo en pesos (en multimon.dMontoResPesos; 0 = sin sobrepago). Si es mayor que 0 y el tipo es billete, calcula mínimo ceil(saldo/cot) y máximo min(floor((saldo+límite)/cot), floor(999999.99/cot)). Recuadro de ayuda de una línea y prompt Dolar con N cubre saldo (vuelto $X):; mensajes Vuelto max … e Importe max …. Rechaza USD con decimales en tipo billete. El log [MULTIMON] agrega MaxVuelto.
pos_mppo.cppPOS_MAIN.EXENueva función MMonMaxVueltoPesos(): devuelve el límite solo si el tipo es billete, iVuelto=0 y existe la fila dM_VmdeP DOLAR → vuelto por defecto; usa la regla de VerCruceMdeP (helper interno MMonLimiteVMdeP). VerificarDMP pasa ese límite a la DLL sin acotarlo por dPorcCobrar. CheckLimites no aplica dPorcCobrar al medio multimoneda habilitado (helper interno MMonSobrepagoHabilitado: perfil 554, iVuelto=0, fila 9→1 y algún dM_DmdeP del grupo con iTaxnumber=1). No cambia ninguna estructura.
pos_mis2.cppPOS_MAIN.EXEExcepción al mensaje 373 (cerca de la línea 3905, IngresoMdeP_ConPromoMdeP): el medio multimoneda puede dejar saldo negativo dentro del mismo límite.
pcpos.hPOS_MAIN.EXEVersión 20261014P / 20261014F (las DLL informan la versión exportada por POS_MAIN).
setvuelt.cpp, _CSETVLT.BATSETVUELT.EXEHerramienta nueva para ver, habilitar (con límite opcional) o deshabilitar (§4). No toca dPorcCobrar salvo para deshacer el 10000 de la versión anterior. Se compila con _CSETVLT.BAT (bcc286 + btr.lib).

El port previo (dff468b..0dd9d2a, +77/−23) tocó pos_mmon.cpp, pos_mppo.cpp, pos_valo.cpp, pos_defi.h y pcpos.h: quitó la cotización simulada fija, agregó el modo de redondeo por iTaxnumber, el orden de vData con 61= primero y el arqueo en USD.

md5 de los binarios (build CO.BAT del 2026-10-19, 20261014P, commit 56dde9d)

Binariomd5Contiene el cambio
POS_MAIN.EXEeec307c925ccc6ebabfbe2835cf71504Sí
POS_MMON.DLL9904f47034e72f97026eb43e9fc005eeSí
SETVUELT.EXEb21eba88cc85248ca92f10f10b1511d0Herramienta

La distribución mínima es POS_MAIN.EXE + POS_MMON.DLL. Se recomienda distribuir el set completo de un mismo CO.BAT (las 16 DLL, listadas con md5 en built_binaries.md5 de la evidencia) para que coincidan versiones y md5. Al arrancar, el log debe mostrar Inicia POS=20261014P y todas las DLL en 20261014P.

Matriz de compatibilidad

POS_MAIN.EXEPOS_MMON.DLLDatosResultado
NuevoNuevaHabilitadosSobrepago con vuelto en efectivo; USD enteros.
NuevoNuevaViejosTope anterior; USD enteros obligatorios.
ViejoNuevaCualquieraTope anterior: POS_MAIN viejo limpia la estructura (multimon.Clear()) y la DLL recibe 0. USD enteros obligatorios (lo valida la DLL).
NuevoViejaCualquieraTope anterior: la DLL vieja ignora el valor de entrada. Admite decimales como antes.
ViejoViejaHabilitadosTope anterior; seguro (la DLL no deja superar el saldo).
CualquieraCualquieraA medio aplicarTope anterior (falta alguna condición). No dejar datos a medio aplicar.

6. Registro y arqueo

Cada pago genera filas en dE_DDMP. El vuelto es una fila EFECTIVO negativa (marcada como recibo de vuelto, bRecVuelto) sin vData. La fila DOLAR guarda el importe en pesos y, en vData, los USD, la cotización y el transactionId de Pizarra.

Ejemplo: ticket 504 (volcado de dE_DDMP)

uIduIdIdcDescripciondImportecComprobantevData
910DOLAR15200.00136861=10.00;60=1520.00;62=13687374;
110EFECTIVO−2710.0013001000017(vacío)

Cómo cuenta el arqueo por moneda

Cálculo sobre las filas volcadas de los tickets 504–510 (no se imprimió cierre X/Y en laboratorio):

DOLAR (USD)10+9+5+9+10+8 = 51
EFECTIVO de esos tickets ($)−2.580
Por qué existe la condición iVuelto = 0 Con iVuelto = 1 el vuelto saldría en DOLAR, en pesos y sin 61=, y el arqueo restaría pesos del acumulador de USD. Por eso el código exige iVuelto = 0 para habilitar el sobrepago.

7. Pruebas realizadas

Laboratorio con DOSBox-X y Pizarra local, cotización 1520 (versión 10345). Ticket base: 4 × COCA COLA + 1 PINZA = $ 12.490. Todas las consultas a Pizarra quedaron auditadas con HTTP 200.

#TicketCasoObtenidoResultado
V1504USD 10 sobre 12.490Prompt cubre con 9, max 821; SaldT:-2710.00; vuelto $ 2.710 en efectivo; filas DOLAR 15200 + EFECTIVO −2710.PASS
V2505USD 9 = mínimo que cubreVuelto $ 1.190; EFECTIVO −1190.PASS
V3506USD 5 + efectivo 4.890Sin vuelto, igual que antes.PASS
V3B507Efectivo 2.000 primero, después USD 9Su pago 15.680, vuelto $ 3.190; sin mensaje 388.PASS
V4504Tipear USD 10.5DOLAR sin decimales: ingrese solo billetes enteros! y vuelve a pedir.PASS
V5510Deshabilitado con SETVUELT /UNDOIngrese DOLAR (max 8.00); USD 10 → Supera monto maximo permitido; log MaxVuelto:0.00; pagó USD 8 + $ 330.PASS
V6B509Sobrepago ingresado y anulación del ticket en curso (autoriza supervisor)Ticket anulado; sin filas en dE_DDMP.PASS
V6508Anular un ticket ya cerradoLa operación no existe en Becerra: un ticket cerrado no se cancela.No aplica

Ronda QA 2026-10-19 (reglas nuevas: dLimite único límite, tope de importe, textos)

Datos: dPorcCobrar(9)=100, fila 9→1 con dLimite 99.999.999,99 salvo Q2 (5.000). Todas las consultas auditadas (HTTP 200, versión 10345).

#TicketCasoObtenidoResultado
Q1512Total $ 1.490, USD 100Vuelto $ 150.510 en efectivo; F7 cierra sin 388. Filas DOLAR 152000 61=100.00;… + EFECTIVO −150510.PASS
Q1B513Efectivo $ 100 primero, después USD 100 (orden que antes daba 388 con dPorcCobrar 100)Su pago 152.100, vuelto $ 150.610; sin 388.PASS
Q2515SETVUELT 9 1 /APPLY 5000; total 12.490USD 12 (vuelto 5.750) → Vuelto max $5000.00 (max 11 DOLAR), reingrese!; USD 11 → vuelto $ 4.230 aceptado.PASS
Q3518Tope de importe (total 1.490)USD 658 ($ 1.000.160) → Importe max $999999.99 (max 657 DOLAR), reingrese!; USD 657 ($ 998.640) aceptado, vuelto $ 997.150, ticket cerrado.PASS
Q3a514Con el tope de 99.999.999 pedido: USD 65.790 rechazado, USD 65.789 aceptadoEl mensaje salió bien, pero el importe $ 99.999.280 se cargó en el diálogo como $ 999.992,80 (máscara 999999.99). Pago cancelado y ticket anulado. Motivó el tope de $ 999.999,99.Hallazgo
Q4512Texto de la línea de ingresoDolar con 1 cubre saldo (vuelto $30): completo, sin cortes (ingreso-dolar-v2.png).PASS
Q5-V1/V4516USD 10.5 y USD 10 sobre 12.49010.5 rechazado; USD 10 → vuelto $ 2.710.PASS
Q5-V3517USD 5 + efectivo 4.890Sin vuelto.PASS
Q5-V5519SETVUELT /UNDOIngrese DOLAR (max 8.00), USD 10 rechazado, pagó USD 8 + $ 330.PASS

Al final se restauró SETVUELT 9 1 /APPLY (dLimite 99.999.999,99, dPorcCobrar 100).

Pendientes sugeridos para el piloto: reimpresión del ticket, cierre X/Y/Z por moneda y Pizarra caída con la versión nueva (con la versión 20261006P ya se probó, T4).

Pruebas previas del port multimoneda (20261006P)

#TicketCasoResultado
T1499Camino feliz, cotización 1520: USD 10 = $ 15.200 + efectivo; vData 61=10.00;60=1520.00;62=…; auditado.PASS
T2500Cotización nueva 1530 publicada en Pizarra; el POS la toma en la siguiente consulta.PASS
T3501Cotización suspendida: HTTP 404, el POS rechaza el medio; se paga en efectivo.PASS
T4502Servidor inalcanzable: error de recepción, el medio no se usa; no hay cobro con cotización fija.PASS
T5503Simulación (perfil 554 = −999): cotización 1200 aun con el servidor caído; sin auditoría.PASS

Evidencia: SistemaBiMonetarismo/docs/evidence/pos-becerra-vuelto-20261014/ (logs, tickets impresos, volcados, salidas de SETVUELT, auditorías) y …/pos-becerra-mmon-20261006/ (port, T1–T5).

8. Despliegue en un cliente

Orden: primero el código en todos los POS (es inerte con los datos viejos), después los datos, que funcionan como interruptor.

Checklist

Rollback

  1. Primera opción, por datos: publicar en el maestro iVuelto=1, dPorcCobrar=100 y sin la fila 9→1, y reiniciar. En emergencia, SETVUELT 9 1 /UNDO en el POS (con el POS detenido). El código queda con el tope anterior.
  2. Solo si hace falta, por binarios: volver a POS_MAIN.EXE + DLL de 20261006P. Es seguro con cualquier estado de datos (matriz §5).

9. Notas, límites y riesgos

Regulatorio Entregar vuelto en pesos por un pago en divisas puede considerarse operación cambiaria. Validarlo con el contador del cliente antes de habilitar.
TemaDetalle
Tablas distribuidas centralmentedM_MdeP y dM_VmdeP se reemplazan completas cuando el servidor publica una versión nueva. El cambio se hace en el maestro; SETVUELT local es transitorio.
Mapa de teclasF6, F7 y Ctrl+F9 son de los datos de prueba. Confirmar las teclas de producción (eventos 2011, 8301 y 8303).
Cierre inmediato tras el vueltoCon MODO_TECLA_VUELTO activo, la tecla de vuelto cierra el ticket. Un ticket cerrado no se puede cancelar en Becerra (esperado); antes de esa tecla, el ticket en curso sí se puede anular.
Impresora fiscalNo se usa en Becerra: no hay riesgo fiscal asociado al pago mayor que el total.
Solo billetes enterosCon iTaxnumber=1 no se aceptan USD con decimales (también sin sobrepago). El tipo 2 (centavos) no admite sobrepago.
Vuelto exactoEl vuelto en efectivo no se redondea: con cotización con centavos, el vuelto tiene centavos.
Límite del vueltoSe regula con dM_VmdeP.dLimite (fila 9→1). No con dM_MdeP(9).dLimite: bajarlo provoca el mensaje 373. dUnidad y dMaxVuelto deben quedar en 0.
Máximo de importeEl pago en USD se limita a $ 999.999,99 (USD × cotización), el máximo del campo Importe de los diálogos de medio de pago. Un importe mayor se truncaría al cargarse en el diálogo (Q3a). Si se amplía la máscara en PCPOS.RES, hay que subir MMON_MAX_IMPORTE en pos_mmon.cpp.
DGROUP de POS_MAIN casi llenoEl segmento de datos DGROUP de POS_MAIN.EXE está en 0xFE1C de 0x10000. Con 16 bytes más (0xFE2C) POS_MAIN no carga sus DLL (Phar Lap GP 286.3360 tras "TCP Init OK"). Todo cambio futuro en POS_MAIN debe evitar datos en DGROUP (constantes double, literales) o verificar el arranque.
Recuadro de ayudaCorregido y verificado en pantalla: la ventana de ingreso tapaba las líneas 2 y 3 del recuadro, así que el recuadro quedó en una línea (cotización y saldo) y el vuelto pasó a la línea de ingreso.
Mensajes 357 / 377Si al dar el vuelto aparecen, la fórmula del límite y la del vuelto divergieron. Son una red de defensa: no deberían aparecer. Revisar los datos de la fila 9→1.
Defectos previos (no introducidos por este cambio)ControlDeMdeP::CheckLimites indexa vueltos[n] en lugar de vueltos[m]; desde 2026-10-19 el medio multimoneda habilitado queda fuera de ese chequeo. Ticket.Update acumula el importe antes del chequeo del mensaje 373 y no lo revierte si lo rechaza (igual que en DolarEAN).
Versiones viejas20260807P, 20260824P y 20260917P simulan la cotización (1200) y no consultan Pizarra. Requisito: 20261006P o posterior.

Preguntas abiertas para el cliente