Compare commits

...
3 Commits
Author SHA1 Message Date
jsoto 073c284449 Merge remote-tracking branch 'origin/main' 2026-10-20 16:05:23 -04:00
jsotoandClaude Opus 5.5 9eb74bbea7 JSOTO veconvierteorden/ccprmt003: evita ordenes duplicadas por cotizacion
Dos usuarios convirtiendo la misma cotizacion a la vez creaban dos ordenes
(cot 340001 -> 262237 y 262238, ticket 12234). La validacion "cotizacion
tiene orden" corria antes del BEGIN WORK; el segundo usuario la pasaba,
esperaba el bloqueo de prtb00020 y al liberarse insertaba otra orden.

- vedir/veconvierteorden: re-valida dentro de la transaccion, ya con el
  bloqueo de prtb00020.
- WEBSERVICES/veconvierteorden: misma re-validacion (no tenia ninguna).
- ccdir/ccprmt003 verifica_orden(): COUNT(*) en vez de SELECT num_oc,
  que daba -284 con ordenes duplicadas.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 16:04:59 -04:00
jsotoandClaude Opus 5.5 7e166ca852 JSOTO MainMenu: lanza cada programa desde su ruta de seg0005 y con el runtime del menu
- Cada programa arranca parado en su ruta de seg0005 (cd /d), como en 3.20: ahi estan
  cert\, filesXML\, net6.0\, tmp\... que la factura electronica busca con rutas relativas,
  y sus .42m. Antes heredaba como directorio de trabajo la carpeta del despliegue del GAR,
  que cambia en cada deploy y llego a tener .42m de 3.20 (-6201 Bad version).
- Usa %FGLDIR%\bin\fglrun (el runtime del menu) en vez del primer fglrun del PATH.
- Ya no imprime usuario y clave en la consola/log del GAS.

Probado en .251 (despliegue mbs-20261019-121056): cgprmt001 y cgprmt004 OK.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 12:19:21 -04:00
4 changed files with 46 additions and 7 deletions
+5 -5
View File
@@ -2758,11 +2758,11 @@ REPORT cctb01b(
END REPORT END REPORT
FUNCTION verifica_orden() FUNCTION verifica_orden()
LET tieneorden = TRUE DEFINE cuantas INT
SELECT a.num_oc # COUNT(*) en vez de SELECT num_oc: con ordenes duplicadas daba -284
LET cuantas = 0
SELECT COUNT(*) INTO cuantas
FROM prtb00012 a FROM prtb00012 a
WHERE a.cotizacion_no = recibo_nc.num_orden AND a.status_T IS NULL WHERE a.cotizacion_no = recibo_nc.num_orden AND a.status_T IS NULL
IF STATUS = NOTFOUND THEN LET tieneorden = (cuantas > 0)
LET tieneorden = FALSE
END IF
END FUNCTION END FUNCTION
+18 -2
View File
@@ -96,6 +96,7 @@ END MAIN
FUNCTION show_mbs(d) FUNCTION show_mbs(d)
DEFINE d ui.Dialog DEFINE d ui.Dialog
DEFINE rdir, rmbs INTEGER DEFINE rdir, rmbs INTEGER
DEFINE runtime STRING
DEFINE cmd STRING,file_path VARCHAR(100), DEFINE cmd STRING,file_path VARCHAR(100),
strconect VARCHAR(20) strconect VARCHAR(20)
@@ -116,9 +117,24 @@ FUNCTION show_mbs(d)
a.programa = pprograma a.programa = pprograma
# LET file_path = 'E:\\MARMOTECHC\\BIN320' # LET file_path = 'E:\\MARMOTECHC\\BIN320'
DISPLAY BY NAME file_path,pperfil DISPLAY BY NAME file_path,pperfil
DISPLAY "mainmenu credenciales: ",usuario clipped," ",clave clipped," ",file_path clipped -- (antes imprimia usuario y CLAVE en texto claro en la consola/log)
LET cmd = "fglrun ",file_path CLIPPED, "\\",mbs[rmbs].prog, ".42r " ,usuario CLIPPED," ",clave CLIPPED, DISPLAY "mainmenu ejecuta: ",mbs[rmbs].prog CLIPPED," desde ",file_path CLIPPED
-- Mismo runtime que el menu (no el primer "fglrun" del PATH del servidor)
LET runtime = fgl_getenv("FGLDIR")
IF runtime IS NULL OR runtime.getLength() = 0 THEN
LET runtime = "fglrun"
ELSE
LET runtime = '"', runtime, '\\bin\\fglrun"'
END IF
LET cmd = runtime," ",file_path CLIPPED, "\\",mbs[rmbs].prog, ".42r " ,usuario CLIPPED," ",clave CLIPPED,
" ",pprinter1 ," ",pprinter2, " ",ckprinter," ",file_path," ",strconect " ",pprinter1 ," ",pprinter2, " ",ckprinter," ",file_path," ",strconect
-- El programa arranca parado en su ruta de seg0005 (como en 3.20): ahi estan
-- cert\, filesXML\, net6.0\, tmp\... que la factura electronica busca con rutas
-- relativas, y sus .42m. Sin esto heredaba como directorio de trabajo la carpeta
-- del despliegue del GAR (que cambia en cada deploy y llego a tener .42m de 3.20).
IF file_path IS NOT NULL AND LENGTH(file_path CLIPPED) > 0 THEN
LET cmd = 'cd /d "', file_path CLIPPED, '" && ', cmd
END IF
RUN cmd WITHOUT WAITING RUN cmd WITHOUT WAITING
UPDATE seg0001 SET ultimo_programa_ejecutado = pprograma WHERE seg0001.usuario = usuario UPDATE seg0001 SET ultimo_programa_ejecutado = pprograma WHERE seg0001.usuario = usuario
+12
View File
@@ -126,6 +126,18 @@ FUNCTION convierteorden(
UPDATE prtb00020 UPDATE prtb00020
SET num_oc = ISNULL(num_oc, 0) + 1, us_crea = xusuario, fech_crea = GETDATE() SET num_oc = ISNULL(num_oc, 0) + 1, us_crea = xusuario, fech_crea = GETDATE()
SELECT num_oc INTO ult_numero FROM prtb00020 SELECT num_oc INTO ult_numero FROM prtb00020
# RE-VALIDACION YA CON EL BLOQUEO DE prtb00020: la validacion del inicio
# corre fuera de la transaccion; si otro usuario estaba convirtiendo la
# misma cotizacion, aqui ya vemos su orden confirmada (cot 340001, 20/10/2026)
LET existe_oc = 0
SELECT COUNT(*) INTO existe_oc FROM prtb00012
WHERE cotizacion_no = xcotizacion_no AND status_t IS NULL
IF existe_oc > 0 THEN
ROLLBACK WORK
CALL fgl_winmessage(
"ERROR", "COTIZACION TIENE ORDEN, NO PUEDE CREAR ORDEN", "STOP")
RETURN 0, FALSE
END IF
# AUTOCORRECCION: si el contador quedo por detras de prtb00012 # AUTOCORRECCION: si el contador quedo por detras de prtb00012
# (otro programa creo ordenes sin avanzarlo), salta al siguiente libre # (otro programa creo ordenes sin avanzarlo), salta al siguiente libre
LET existe_oc = 0 LET existe_oc = 0
+11
View File
@@ -139,6 +139,17 @@ BEGIN WORK
us_crea = xusuario, us_crea = xusuario,
fech_crea = GETDATE() fech_crea = GETDATE()
SELECT num_oc INTO ult_numero FROM prtb00020 SELECT num_oc INTO ult_numero FROM prtb00020
# RE-VALIDACION YA CON EL BLOQUEO DE prtb00020: evita dos ordenes para la
# misma cotizacion si dos usuarios convierten a la vez (cot 340001, 20/10/2026)
LET existe_oc = 0
SELECT COUNT(*) INTO existe_oc FROM prtb00012
WHERE cotizacion_no = xcotizacion_no AND status_t IS NULL
IF existe_oc > 0 THEN
LET pmensaje_error =
SFMT("La cotizacion %1 ya tiene orden, no puede crear otra.", xcotizacion_no)
ROLLBACK WORK
RETURN 0,FALSE
END IF
# AUTOCORRECCION: si el contador quedo por detras de prtb00012, salta al siguiente libre # AUTOCORRECCION: si el contador quedo por detras de prtb00012, salta al siguiente libre
LET existe_oc = 0 LET existe_oc = 0
SELECT COUNT(*) INTO existe_oc FROM prtb00012 WHERE num_oc = ult_numero SELECT COUNT(*) INTO existe_oc FROM prtb00012 WHERE num_oc = ult_numero