Files
MBS/PROYECTO/PRDIR/prprmt003.4gl
T

2399 lines
87 KiB
Plaintext

{
-----------------------------------------------------------------------------
PROGRAMA : prprmt003
OBJETIVO : Mantenimiento de Produccion por Centro de Costos
REALIZADO POR : Ing. Juan F. Soto.
FECHA : Junio 17, 1993
-----------------------------------------------------------------------------
}
GLOBALS "prprgb000.4gl"
DEFINE dep_ant,p_codigo,sidx SMALLINT
DEFINE medida,nomb1,nomb2 CHAR(20)
DEFINE descrip2,nombre,descrip_ant,descripcion CHAR(30)
DEFINE hoy,fecha1 DATE
DEFINE tiene,modifica CHAR(1)
DEFINE temporero RECORD LIKE adtb00036.*,
tmpnumero INT,
usuario_c CHAR(40),
fecha_c LIKE cttb00003.fech_crea,
cherror STRING
DEFINE datos_c RECORD
num_doc INTEGER,
fecha DATE,
#factor DEC(12,2),
departamento SMALLINT,
cod_mov SMALLINT
END RECORD
DEFINE arr_costos DYNAMIC ARRAY OF RECORD
tipo LIKE cttb00003.cod_mq,
codigo INT,
emp_no LIKE cttb00003.emp_no,
h_directa LIKE cttb00003.h_directa,
h_indirecta LIKE cttb00003.h_indirecta,
e_directa LIKE cttb00003.e_directa,
e_indirecta LIKE cttb00003.e_indirecta,
cod_prod LIKE cttb00011.cod_prod,
lado2,lado1,lado3 DEC(12,5),
cantidad LIKE cttb00003.cantidad,
medida1 DEC(18,5),
codigo_bloque LIKE cttb00003.codigo_bloque,
turno SMALLINT,
depto_receptor SMALLINT,
ref INT,
num_oc INT
END RECORD
DEFINE estadomov SMALLINT
DEFINE pendientes DYNAMIC ARRAY OF RECORD
num_doc INT,
departamento INT,
cod_prod INT,
cantidad NUMERIC(12,2),
Cantidad_Total_Enviada,Cantidad_Ya_Recibida, Pendiente_Por_Entrar DECIMAL(18,5),
CHECK BOOLEAN
END RECORD
DEFINE controlExistencia_entrada DYNAMIC ARRAY OF RECORD
num_doc INT,
cod_prod INT,
cantidad NUMERIC(12,2), medida DECIMAL(18,5)
END RECORD
DEFINE detalles DYNAMIC ARRAY OF STRING, query STRING
DEFINE check_existencia DECIMAL(18,5)
DEFINE continuar BOOLEAN
# Lista de documentos (pagina "Documentos" de prfmmt003, screen record s_docs)
DEFINE arr_docs DYNAMIC ARRAY OF RECORD
d_num_doc INTEGER,
d_fecha STRING,
d_departamento STRING,
d_movimiento STRING,
d_estado STRING,
d_bloques STRING
END RECORD
# num_doc pre-seleccionado desde la pagina Documentos para modificar directo
DEFINE g_num_preselect INTEGER
# guarda one-time del PREPARE/DECLARE de la lista de documentos (evita -404 al recargar)
DEFINE g_docs_prep SMALLINT
# marca si el foco esta en el detalle (para el F10 del editor DIALOG)
DEFINE g_in_detail SMALLINT
# flags de PREPARE de la ventana de orden de pedido / tabla hija
DEFINE m_items_prep SMALLINT
DEFINE m_oc_prep SMALLINT
# items de orden asociados al documento en edicion (tabla hija cttb00003oc)
DEFINE arr_oc DYNAMIC ARRAY OF RECORD
num_oc INT,
cod_n SMALLINT,
cod_grupo SMALLINT,
cod_tipo SMALLINT,
cod_sec SMALLINT,
cantidad DECIMAL(12,2),
descrip CHAR(60)
END RECORD
MAIN
DEFER INTERRUPT
CALL ARG_VAL(1) RETURNING usuarios
CALL ARG_VAL(2) RETURNING clave
CONNECT to "smarmotech" USER usuarios USING clave
CALL prprmt003()
END MAIN
FUNCTION prprmt003()
OPTIONS
FORM LINE 5,
ERROR LINE 24,
PROMPT LINE 1
CLEAR SCREEN
OPEN FORM prfmmt003 FROM "prfmmt003"
DISPLAY FORM prfmmt003
DISPLAY "Registro de Produccion Diaria" AT 4,25
DISPLAY "prprmt003" AT 4,3
# CALL pantalla1()
# La pagina "Documentos" es la pantalla principal: se muestra de una vez.
CALL documentos()
END FUNCTION
# ---------------------------------------------------------------------------
# Pagina "Documentos": lista los documentos de produccion, el mas reciente
# primero (NUM_DOC descendente), con Departamento, Movimiento y Estado
# (ACTIVO/ANULADO). Permite reimprimir el documento seleccionado.
# ---------------------------------------------------------------------------
FUNCTION documentos()
DEFINE accion STRING, p_sel INT
DEFINE bloque_def CHAR(25), bloque_in STRING
DEFINE f1_in, f2_in STRING
# Loop principal del programa: siempre muestra la lista de documentos.
# Las acciones que cambian datos regresan aqui y la lista se recarga.
WHILE TRUE
CALL cargar_documentos()
LET accion = ""
LET p_sel = 0
DISPLAY ARRAY arr_docs TO s_docs.* ATTRIBUTES(ACCEPT = FALSE, CANCEL = FALSE)
ON ACTION nuevo
LET accion = "nuevo"
EXIT DISPLAY
ON ACTION buscar
LET accion = "buscar"
EXIT DISPLAY
ON ACTION anular
LET accion = "anular"
EXIT DISPLAY
ON ACTION ver ATTRIBUTES(TEXT = "Ver Detalle", IMAGE = "detail")
IF arr_docs.getLength() > 0 THEN
LET accion = "ver"
LET p_sel = arr_docs[arr_curr()].d_num_doc
EXIT DISPLAY
END IF
ON ACTION modificar ATTRIBUTES(TEXT = "Modificar", IMAGE = "edit")
IF arr_docs.getLength() > 0 THEN
LET accion = "mod"
LET p_sel = arr_docs[arr_curr()].d_num_doc
EXIT DISPLAY
END IF
ON ACTION imprimir ATTRIBUTES(TEXT = "Imprimir", IMAGE = "print")
IF arr_docs.getLength() > 0 THEN
CALL reimprime_doc(arr_docs[arr_curr()].d_num_doc)
END IF
ON ACTION traza
IF arr_docs.getLength() > 0 THEN
LET p_sel = arr_docs[arr_curr()].d_num_doc
END IF
LET accion = "traza"
EXIT DISPLAY
ON ACTION documentos -- refrescar la lista
EXIT DISPLAY
ON ACTION salir
LET accion = "salir"
EXIT DISPLAY
ON ACTION close
LET accion = "salir"
EXIT DISPLAY
END DISPLAY
CASE accion
WHEN "nuevo"
LET modifica = "N"
CALL prpradd()
WHEN "buscar"
LET modifica = "S"
CALL prprmod()
WHEN "anular"
CALL prpranula()
WHEN "ver"
CALL ver_documento(p_sel)
WHEN "mod"
CALL editar_documento(p_sel) -- editor DIALOG (encabezado + detalle, un solo OK)
WHEN "traza"
# Pre-llena con el bloque del documento seleccionado (si tiene)
LET bloque_def = ""
IF p_sel > 0 THEN
SELECT MAX(codigo_bloque) INTO bloque_def
FROM cttb00003
WHERE num_doc = p_sel AND codigo_bloque IS NOT NULL
END IF
LET bloque_in = fgl_winprompt(0, 0,
"Codigo de bloque (deje en blanco para reporte por rango de fechas):",
bloque_def CLIPPED, 25, 0)
# NULL = Cancel -> retornar sin hacer nada
IF bloque_in IS NOT NULL THEN
IF LENGTH(bloque_in CLIPPED) > 0 THEN
CALL trazabilidad_bloque(bloque_in)
ELSE
# Bloque en blanco -> reporte de bloques (fechas opcionales).
LET f1_in = fgl_winprompt(0, 0, "Fecha DESDE (en blanco = sin limite):", "", 10, 0)
IF f1_in IS NOT NULL THEN # Cancel en DESDE -> abortar
LET f2_in = fgl_winprompt(0, 0, "Fecha HASTA (en blanco = sin limite):", "", 10, 0)
IF f2_in IS NOT NULL THEN # Cancel en HASTA -> abortar
CALL trazabilidad_rango(f1_in, f2_in)
END IF
END IF
END IF
END IF
WHEN "salir"
EXIT WHILE
OTHERWISE
# imprimir / refrescar: el loop recarga la lista
END CASE
END WHILE
END FUNCTION
# Carga la lista de documentos (mas reciente primero, TOP 100) en arr_docs
FUNCTION cargar_documentos()
DEFINE i INT
CALL arr_docs.clear()
IF g_docs_prep = 0 THEN
LET query =
"SELECT TOP 100 a.num_doc,",
" CONVERT(VARCHAR(10), MAX(a.fecha), 103),",
" '(' + CAST(a.departamento AS VARCHAR) + ') ' + ISNULL(MAX(d.nom_dpto),''),",
" '(' + CAST(a.cod_mov AS VARCHAR) + ') ' + ISNULL(MAX(m.descrip_mov),''),",
" CASE WHEN COUNT(CASE WHEN a.status_t IS NULL THEN 1 END) > 0",
" THEN 'ACTIVO' ELSE 'ANULADO' END,",
" ISNULL(CAST(STUFF((SELECT DISTINCT ', ' + RTRIM(b.codigo_bloque)",
" FROM cttb00003 b",
" WHERE b.num_doc = a.num_doc AND b.codigo_bloque IS NOT NULL",
" FOR XML PATH('')), 1, 2, '') AS VARCHAR(500)), '')",
" FROM cttb00003 a",
" LEFT JOIN adtb00001 d ON d.departamento = a.departamento",
" LEFT JOIN cttb00005 m ON m.cod_mov = a.cod_mov",
" GROUP BY a.num_doc, a.departamento, a.cod_mov",
" ORDER BY a.num_doc DESC"
PREPARE p_docs FROM query
DECLARE c_docs CURSOR FOR p_docs
LET g_docs_prep = 1
END IF
LET i = 1
FOREACH c_docs INTO arr_docs[i].*
LET i = i + 1
END FOREACH
END FUNCTION
# Muestra (solo lectura) encabezado + detalle de un documento en la pagina Produccion
FUNCTION ver_documento(p_num INT)
DEFINE i INT
INITIALIZE datos_c.* TO NULL
CALL arr_costos.clear()
SELECT UNIQUE a.num_doc, a.fecha, a.departamento, a.cod_mov
INTO datos_c.num_doc, datos_c.fecha, datos_c.departamento, datos_c.cod_mov
FROM cttb00003 a
WHERE a.num_doc = p_num
DECLARE c_ver CURSOR FOR
SELECT a.cod_tipo,a.cod_mq,a.emp_no,a.h_directa,a.h_indirecta,a.e_directa,a.e_indirecta,
a.cod_prod,a.lado2,a.lado1,a.lado3,a.cantidad,a.medida,a.codigo_bloque,a.turno,
a.depto_receptor,a.ref,
a.num_oc
FROM cttb00003 a
WHERE a.num_doc = p_num
LET i = 1
FOREACH c_ver INTO arr_costos[i].*
LET i = i + 1
END FOREACH
IF arr_costos.getLength() = 0 THEN
LET numero_msg = 3
CALL msg(numero_msg)
RETURN
END IF
CALL cargar_oc(p_num) -- items de orden del documento
# Llenar combos para que se muestren las descripciones
CALL departamentos_produccion()
CALL movimientos()
DISPLAY BY NAME datos_c.num_doc, datos_c.fecha, datos_c.departamento, datos_c.cod_mov
DISPLAY ARRAY arr_costos TO scr_costos.* ATTRIBUTES(ACCEPT = FALSE, CANCEL = FALSE)
BEFORE DISPLAY
CALL coperacion()
CALL cturno()
CALL maquinas(datos_c.departamento)
CALL departamentos_receptores()
ON ACTION regresar ATTRIBUTES(TEXT = "Regresar")
EXIT DISPLAY
ON ACTION close
EXIT DISPLAY
END DISPLAY
END FUNCTION
# Recarga un documento desde cttb00003 y lo reimprime con el .4rp
FUNCTION reimprime_doc(p_num INT)
DEFINE i INT
INITIALIZE datos_c.* TO NULL
CALL arr_costos.clear()
SELECT UNIQUE a.num_doc, a.fecha, a.departamento, a.cod_mov
INTO datos_c.num_doc, datos_c.fecha, datos_c.departamento, datos_c.cod_mov
FROM cttb00003 a
WHERE a.num_doc = p_num
DECLARE c_reimp CURSOR FOR
SELECT a.cod_tipo,a.cod_mq,a.emp_no,a.h_directa,a.h_indirecta,a.e_directa,a.e_indirecta,
a.cod_prod,a.lado2,a.lado1,a.lado3,a.cantidad,a.medida,a.codigo_bloque,a.turno,
a.depto_receptor,a.ref,
a.num_oc
FROM cttb00003 a
WHERE a.num_doc = p_num
LET i = 1
FOREACH c_reimp INTO arr_costos[i].*
LET i = i + 1
END FOREACH
IF arr_costos.getLength() > 0 THEN
CALL imprime(datos_c.*, arr_costos)
END IF
END FUNCTION
# ---------------------------------------------------------------------------
# Editor maestro-detalle (DIALOG) para MODIFICAR un documento desde la lista.
# Une el encabezado (INPUT) y el detalle (INPUT ARRAY) en un solo dialogo, de
# modo que el usuario se mueve libre entre ambos y guarda con un solo OK.
# Preserva las validaciones y el guardado del flujo de modificacion clasico.
# ---------------------------------------------------------------------------
FUNCTION editar_documento(p_num INT)
DEFINE i INT
LET modifica = "S" -- para que medidas() cargue cttb00012
# --- Encabezado ---
INITIALIZE datos_c.* TO NULL
SELECT UNIQUE a.num_doc, a.fecha, a.departamento, a.cod_mov
INTO datos_c.num_doc, datos_c.fecha, datos_c.departamento, datos_c.cod_mov
FROM cttb00003 a
WHERE a.num_doc = p_num
IF status = NOTFOUND THEN
LET numero_msg = 3
CALL msg(numero_msg)
RETURN
END IF
# --- Detalle (a magnitud absoluta para editar en positivo) ---
CALL arr_costos.clear()
DECLARE c_edita CURSOR FOR
SELECT a.cod_tipo,a.cod_mq,a.emp_no,a.h_directa,a.h_indirecta,a.e_directa,a.e_indirecta,
a.cod_prod,a.lado2,a.lado1,a.lado3,a.cantidad,a.medida,a.codigo_bloque,a.turno,
a.depto_receptor,a.ref,
a.num_oc
FROM cttb00003 a
WHERE a.num_doc = p_num AND a.status_t IS NULL
LET i = 1
FOREACH c_edita INTO arr_costos[i].*
IF arr_costos[i].cantidad < 0 THEN LET arr_costos[i].cantidad = arr_costos[i].cantidad * -1 END IF
IF arr_costos[i].medida1 < 0 THEN LET arr_costos[i].medida1 = arr_costos[i].medida1 * -1 END IF
LET i = i + 1
END FOREACH
CALL cargar_oc(p_num) -- items de orden del documento
IF arr_costos.getLength() = 0 THEN
LET numero_msg = 3
CALL msg(numero_msg)
RETURN
END IF
# --- Llenar combos (encabezado + detalle) y mostrar ---
CALL departamentos_produccion()
CALL movimientos()
CALL coperacion()
CALL cturno()
CALL maquinas(datos_c.departamento)
CALL departamentos_receptores()
DISPLAY BY NAME datos_c.*
# --- DIALOG: encabezado + detalle en un solo bloque interactivo ---
LET g_in_detail = 0
DIALOG ATTRIBUTES(UNBUFFERED)
INPUT BY NAME datos_c.fecha, datos_c.departamento ATTRIBUTES(WITHOUT DEFAULTS)
BEFORE INPUT
LET g_in_detail = 0
AFTER FIELD fecha
IF datos_c.fecha IS NULL THEN
LET numero_msg = 16
CALL msg(numero_msg)
NEXT FIELD fecha
END IF
IF datos_c.fecha > today THEN
LET numero_msg = 189
CALL msg(numero_msg)
NEXT FIELD fecha
END IF
END INPUT
INPUT ARRAY arr_costos FROM scr_costos.* ATTRIBUTES(WITHOUT DEFAULTS)
BEFORE INPUT
LET g_in_detail = 1
BEFORE ROW
LET g_in_detail = 1
LET curr = arr_curr()
LET scr_l = scr_line()
AFTER FIELD codigo_bloque
IF arr_costos[curr].codigo_bloque IS NOT NULL THEN
CALL verificar(arr_costos[curr].codigo_bloque) RETURNING existe
IF existe = 'N' THEN
CALL msg(3)
NEXT FIELD codigo_bloque
END IF
END IF
AFTER FIELD num_oc
IF arr_costos[curr].num_oc IS NOT NULL AND arr_costos[curr].num_oc > 0 THEN
SELECT status_t INTO tiene FROM prtb00012
WHERE num_oc = arr_costos[curr].num_oc
IF status = NOTFOUND THEN
CALL fgl_winmessage("Orden de pedido", "La orden no existe.", "exclamation")
NEXT FIELD num_oc
END IF
IF tiene IS NOT NULL THEN
CALL fgl_winmessage("Orden de pedido", "La orden no esta activa.", "exclamation")
NEXT FIELD num_oc
END IF
END IF
AFTER FIELD emp_no
IF arr_costos[curr].emp_no IS NOT NULL THEN
SELECT a.nom1_emp,a.apell1_emp INTO nomb1,nomb2
FROM adtb00003 a WHERE a.num_emp = arr_costos[curr].emp_no
IF status = notfound THEN
SELECT * INTO temporero.* FROM adtb00036 WHERE num_emp = arr_costos[curr].emp_no
IF status = notfound THEN
LET numero_msg = 3
CALL msg(numero_msg)
NEXT FIELD emp_no
END IF
LET nomb1 = temporero.nom1_emp
LET nomb2 = temporero.apell1_emp
END IF
LET nombre = nomb1 CLIPPED," ",nomb2 CLIPPED
DISPLAY BY NAME nombre ATTRIBUTE(BOLD)
END IF
AFTER FIELD cod_prod
IF arr_costos[curr].cod_prod IS NOT NULL THEN
SELECT UNIQUE a.cod_prod,a.descripcion,a.unidad_med
INTO p_codigo,descripcion,medida
FROM cttb00001 a
WHERE a.cod_prod = arr_costos[curr].cod_prod AND a.status_t IS NULL
IF status >= 0 THEN
IF status = notfound THEN
LET numero_msg = 3
CALL msg(numero_msg)
NEXT FIELD cod_prod
END IF
ELSE
CALL integridad()
IF bandera = 1 THEN
LET bandera = 0
EXIT DIALOG
END IF
END IF
DISPLAY BY NAME medida
DISPLAY BY NAME descripcion
LET selec =
"SELECT CONVERT(CHAR(10),MAX(a.fecha),103) ",
" FROM cttb00034 a ",
" WHERE CONVERT(DATE,a.fecha,103) < ? "," AND ",
" a.cod_prod = ? and ",
" a.status_t IS NULL"
PREPARE busca_fecha_e FROM selec
EXECUTE busca_fecha_e USING datos_c.fecha,arr_costos[curr].cod_prod INTO fecha1
LET pcosto_labor[curr] = 0
SELECT AVG(a.costo_lab) INTO pcosto_labor[curr] FROM cttb00034 a
WHERE a.fecha = fecha1 AND a.cod_prod = arr_costos[curr].cod_prod AND a.status_t IS NULL
IF pcosto_labor[curr] IS NULL THEN LET pcosto_labor[curr] = 0 END IF
LET pcosto_gasto[curr] = 0
SELECT AVG(a.costo_ga) INTO pcosto_gasto[curr] FROM cttb00034 a
WHERE a.fecha = fecha1 AND a.cod_prod = arr_costos[curr].cod_prod AND a.status_t IS NULL
IF pcosto_gasto[curr] IS NULL THEN LET pcosto_gasto[curr] = 0 END IF
END IF
IF arr_costos[curr].cantidad IS NULL THEN
LET arr_costos[curr].cantidad = 0
END IF
IF medida = "MT2" THEN
LET arr_costos[curr].medida1 = arr_costos[curr].cantidad * (arr_costos[curr].lado1 * arr_costos[curr].lado2)
END IF
IF medida = "MT3" THEN
LET arr_costos[curr].medida1 = arr_costos[curr].cantidad * (arr_costos[curr].lado1 * arr_costos[curr].lado2 * arr_costos[curr].lado3)
END IF
IF medida = "ML" THEN
LET arr_costos[curr].medida1 = arr_costos[curr].cantidad * arr_costos[curr].lado1
LET arr_costos[curr].lado2 = 0
END IF
IF medida = "UND" OR medida = "GL" THEN
LET arr_costos[curr].medida1 = arr_costos[curr].cantidad
END IF
DISPLAY arr_costos[curr].medida1 TO scr_costos[scr_l].medida1
END INPUT
ON KEY(F10)
IF g_in_detail = 1 THEN
LET curr = arr_curr()
LET scr_l = scr_line()
IF arr_costos[curr].cod_prod IS NOT NULL THEN
IF arr_costos[curr].codigo_bloque IS NULL THEN
LET numero_msg = 16
CALL msg(numero_msg)
NEXT FIELD codigo_bloque
END IF
CALL medidas()
DISPLAY arr_costos[curr].cantidad TO scr_costos[scr_l].cantidad
END IF
END IF
ON ACTION imprimir ATTRIBUTES(TEXT = "Imprimir", IMAGE = "print")
CALL imprime(datos_c.*, arr_costos)
ON ACTION ordenped
LET curr = arr_curr()
IF arr_costos[curr].num_oc IS NOT NULL AND arr_costos[curr].num_oc > 0 THEN
CALL escoge_items_orden(arr_costos[curr].num_oc)
ELSE
CALL fgl_winmessage("Orden de pedido", "Digite primero el numero de orden.", "information")
END IF
ON ACTION accept
CALL guardar_documento()
LET numero_msg = 13
CALL msg(numero_msg)
EXIT DIALOG
ON ACTION cancel
LET numero_msg = 2
CALL msg(numero_msg)
EXIT DIALOG
END DIALOG
CLEAR FORM
END FUNCTION
# Guarda el documento en edicion: borra las lineas y las re-inserta con el
# signo correcto (SALIDA => negativo en cantidad y medida). No toca la
# secuencia (conserva el mismo num_doc).
FUNCTION guardar_documento()
DEFINE idx INT
BEGIN WORK
DELETE FROM cttb00003 WHERE num_doc = datos_c.num_doc
LET estadomov = 0 -- default entrada (positivo) si el doc no tiene cod_mov mapeado
SELECT estado_mov INTO estadomov FROM cttb00005
WHERE cod_mov = datos_c.cod_mov AND status_t IS NULL
IF estadomov = 2 THEN
FOR idx = 1 TO arr_costos.getLength()
LET arr_costos[idx].cantidad = arr_costos[idx].cantidad * -1
LET arr_costos[idx].medida1 = arr_costos[idx].medida1 * -1
END FOR
END IF
FOR idx = 1 TO arr_costos.getLength()
IF arr_costos[idx].cod_prod IS NOT NULL THEN
INSERT INTO cttb00003
( num_doc, fecha, departamento, emp_no, cod_tipo, cod_mq, detalle,
h_directa, h_indirecta, e_directa, e_indirecta, cod_prod,
lado2, lado1, lado3, cantidad, medida, codigo_bloque,
costo_lab, costo_gasto, turno, us_crea, fech_crea, depto_receptor, cod_mov, ref,
num_oc)
VALUES
(datos_c.num_doc, datos_c.fecha, datos_c.departamento,
arr_costos[idx].emp_no, arr_costos[idx].tipo, arr_costos[idx].codigo, NULL,
arr_costos[idx].h_directa, arr_costos[idx].h_indirecta,
arr_costos[idx].e_directa, arr_costos[idx].e_indirecta,
arr_costos[idx].cod_prod, arr_costos[idx].lado2, arr_costos[idx].lado1, arr_costos[idx].lado3,
arr_costos[idx].cantidad, arr_costos[idx].medida1, arr_costos[idx].codigo_bloque,
pcosto_labor[idx], pcosto_gasto[idx], arr_costos[idx].turno,
SUSER_SNAME(), GETDATE(), arr_costos[idx].depto_receptor, datos_c.cod_mov, arr_costos[idx].ref,
arr_costos[idx].num_oc)
END IF
END FOR
CALL guardar_oc(datos_c.num_doc) -- items de orden (tabla hija)
COMMIT WORK
END FUNCTION
# ---------------------------------------------------------------------------
# Ventana para elegir un item de produccion de una orden de pedido.
# Lista prtb00013 (lineas de la orden) JOIN iptb00002 con es_produccion = 1.
# Devuelve: found(1/0) + los 4 codigos del item + la descripcion.
# ---------------------------------------------------------------------------
FUNCTION escoge_items_orden(p_oc)
DEFINE p_oc INT
# arreglo visible (5 campos = screen record sr_items)
DEFINE items DYNAMIC ARRAY OF RECORD
marca CHAR(3),
i_cod CHAR(20),
i_desc CHAR(60),
i_cant DECIMAL(12,2),
i_uni CHAR(4)
END RECORD
# arreglo paralelo con los 4 codigos del item (mismo indice que items)
DEFINE item_codes DYNAMIC ARRAY OF RECORD
cod_n SMALLINT,
cod_grupo SMALLINT,
cod_tipo SMALLINT,
cod_sec SMALLINT
END RECORD
DEFINE k, j, pos INT
DEFINE t_cod, t_uni CHAR(20)
DEFINE t_desc CHAR(60)
DEFINE t_cant DECIMAL(12,2)
DEFINE t_cn, t_cg, t_ct, t_cs INT
IF p_oc IS NULL OR p_oc = 0 THEN
RETURN
END IF
IF m_items_prep = 0 THEN
LET query =
"SELECT RTRIM(CAST(a.cod_n AS VARCHAR)) + '-' + RTRIM(CAST(a.cod_grupo AS VARCHAR))",
" + '-' + RTRIM(CAST(a.cod_tipo AS VARCHAR)) + '-' + RTRIM(CAST(a.cod_sec AS VARCHAR)),",
" ISNULL(b.descrip_esp,''), a.cantidad, ISNULL(b.unidad_med,''),",
" a.cod_n, a.cod_grupo, a.cod_tipo, a.cod_sec",
" FROM prtb00013 a",
" INNER JOIN iptb00002 b ON a.cod_n = b.cod_n AND a.cod_grupo = b.cod_grupo",
" AND a.cod_tipo = b.cod_tipo AND a.cod_sec = b.cod_sec",
" WHERE a.num_oc = ? AND b.es_produccion = 1 AND a.status_t IS NULL",
" ORDER BY a.secuencia"
PREPARE s_items FROM query
DECLARE c_items CURSOR FOR s_items
LET m_items_prep = 1
END IF
CALL items.clear()
CALL item_codes.clear()
LET k = 1
FOREACH c_items USING p_oc INTO t_cod, t_desc, t_cant, t_uni, t_cn, t_cg, t_ct, t_cs
LET items[k].i_cod = t_cod
LET items[k].i_desc = t_desc
LET items[k].i_cant = t_cant
LET items[k].i_uni = t_uni
LET item_codes[k].cod_n = t_cn
LET item_codes[k].cod_grupo = t_cg
LET item_codes[k].cod_tipo = t_ct
LET item_codes[k].cod_sec = t_cs
# marca los items que ya estan asociados a esta orden en arr_oc
LET items[k].marca = ""
FOR j = 1 TO arr_oc.getLength()
IF arr_oc[j].num_oc = p_oc AND arr_oc[j].cod_n = t_cn
AND arr_oc[j].cod_grupo = t_cg AND arr_oc[j].cod_tipo = t_ct
AND arr_oc[j].cod_sec = t_cs THEN
LET items[k].marca = " X "
EXIT FOR
END IF
END FOR
LET k = k + 1
END FOREACH
IF items.getLength() = 0 THEN
CALL fgl_winmessage("Orden de pedido",
"La orden no tiene items de produccion (es_produccion) o no esta activa.",
"information")
RETURN
END IF
OPEN WINDOW w_ordenped WITH FORM "prfmordenped"
DISPLAY p_oc TO f_oc
DISPLAY ARRAY items TO sr_items.* ATTRIBUTES(UNBUFFERED, ACCEPT = FALSE, CANCEL = FALSE)
ON ACTION agregar ATTRIBUTES(TEXT = "Agregar / Quitar", IMAGE = "ok")
LET k = arr_curr()
LET pos = 0
FOR j = 1 TO arr_oc.getLength()
IF arr_oc[j].num_oc = p_oc
AND arr_oc[j].cod_n = item_codes[k].cod_n
AND arr_oc[j].cod_grupo = item_codes[k].cod_grupo
AND arr_oc[j].cod_tipo = item_codes[k].cod_tipo
AND arr_oc[j].cod_sec = item_codes[k].cod_sec THEN
LET pos = j
EXIT FOR
END IF
END FOR
IF pos > 0 THEN
CALL arr_oc.deleteElement(pos)
LET items[k].marca = ""
ELSE
LET pos = arr_oc.getLength() + 1
LET arr_oc[pos].num_oc = p_oc
LET arr_oc[pos].cod_n = item_codes[k].cod_n
LET arr_oc[pos].cod_grupo = item_codes[k].cod_grupo
LET arr_oc[pos].cod_tipo = item_codes[k].cod_tipo
LET arr_oc[pos].cod_sec = item_codes[k].cod_sec
LET arr_oc[pos].cantidad = items[k].i_cant
LET arr_oc[pos].descrip = items[k].i_desc
LET items[k].marca = " X "
END IF
ON ACTION cerrar ATTRIBUTES(TEXT = "Cerrar")
EXIT DISPLAY
ON ACTION close
EXIT DISPLAY
END DISPLAY
CLOSE WINDOW w_ordenped
END FUNCTION
# Prepara (una vez) los SQL dinamicos de la tabla hija cttb00003oc.
# Se usa SQL dinamico porque la tabla es nueva y puede no estar en el .sch.
FUNCTION prep_oc()
IF m_oc_prep = 0 THEN
PREPARE p_del_oc FROM "DELETE FROM cttb00003oc WHERE num_doc = ?"
PREPARE p_ins_oc FROM
"INSERT INTO cttb00003oc (num_doc,num_oc,cod_n,cod_grupo,cod_tipo,cod_sec,cantidad,status_t,us_crea,fech_crea)"
|| " VALUES (?,?,?,?,?,?,?,NULL,SUSER_SNAME(),GETDATE())"
PREPARE p_sel_oc FROM
"SELECT o.num_oc,o.cod_n,o.cod_grupo,o.cod_tipo,o.cod_sec,o.cantidad,"
|| " ISNULL((SELECT MAX(b.descrip_esp) FROM iptb00002 b WHERE b.cod_n=o.cod_n AND b.cod_grupo=o.cod_grupo"
|| " AND b.cod_tipo=o.cod_tipo AND b.cod_sec=o.cod_sec),'')"
|| " FROM cttb00003oc o WHERE o.num_doc = ?"
DECLARE c_oc CURSOR FOR p_sel_oc
LET m_oc_prep = 1
END IF
END FUNCTION
# Guarda los items de orden (arr_oc) del documento en la tabla hija cttb00003oc.
FUNCTION guardar_oc(p_num_doc)
DEFINE p_num_doc INT, j, i2 INT, conservar SMALLINT
CALL prep_oc()
# Borra los items previos del documento y re-inserta el set vigente.
EXECUTE p_del_oc USING p_num_doc
FOR j = 1 TO arr_oc.getLength()
# Ignora elementos vacios (sin item ni orden)
IF arr_oc[j].cod_n IS NULL AND arr_oc[j].num_oc IS NULL THEN
CONTINUE FOR
END IF
# Poda: conserva el item solo si su num_oc sigue en alguna linea del
# documento (asi, al quitar/sustituir la orden de una linea, sus items
# asociados se eliminan solos).
LET conservar = 0
FOR i2 = 1 TO arr_costos.getLength()
IF arr_costos[i2].num_oc = arr_oc[j].num_oc THEN
LET conservar = 1
EXIT FOR
END IF
END FOR
IF conservar = 1 THEN
EXECUTE p_ins_oc USING p_num_doc, arr_oc[j].num_oc, arr_oc[j].cod_n,
arr_oc[j].cod_grupo, arr_oc[j].cod_tipo, arr_oc[j].cod_sec, arr_oc[j].cantidad
END IF
END FOR
END FUNCTION
# Carga en arr_oc los items de orden de un documento (para modificar/ver).
FUNCTION cargar_oc(p_num_doc)
DEFINE p_num_doc INT, k INT
CALL prep_oc()
CALL arr_oc.clear()
LET k = 1
FOREACH c_oc USING p_num_doc INTO arr_oc[k].*
LET k = k + 1
END FOREACH
# Quita el elemento vacio que a veces deja el FOREACH ... INTO arr[k].*
IF arr_oc.getLength() > 0 THEN
IF arr_oc[arr_oc.getLength()].cod_n IS NULL
AND arr_oc[arr_oc.getLength()].num_oc IS NULL THEN
CALL arr_oc.deleteElement(arr_oc.getLength())
END IF
END IF
END FUNCTION
FUNCTION prpradd()
LET hoy = null
LET datos_c.num_doc = 0
LABEL volver:
LET nombre = null
DISPLAY BY NAME nombre
INITIALIZE datos_c.* TO NULL
LET idx = 1
INPUT BY NAME datos_c.* WITHOUT DEFAULTS
BEFORE INPUT
CALL departamentos_produccion()
CALL movimientos()
SELECT MAX(a.semana_al) INTO datos_c.fecha FROM prtb00002 a WHERE a.semana_al <= today
DISPLAY BY NAME datos_c.fecha
CALL Dialog.setFieldActive('num_doc', FALSE)
AFTER FIELD fecha
IF datos_c.fecha is null THEN
LET numero_msg = 16
CALL msg(numero_msg)
NEXT FIELD fecha
END IF
IF datos_c.fecha > today THEN
LET numero_msg = 189
CALL msg(numero_msg)
NEXT FIELD fecha
END IF
{
# Control del registro de produccion diaria para la no duplicidad
SELECT UNIQUE a. fecha FROM cttb00003 a
WHERE a.fecha = datos_c.fecha and
a.num_doc = datos_c.num_doc
IF status != notfound THEN
LET numero_msg = 12
CALL msg(numero_msg)
NEXT FIELD fecha
END IF
}
{ SELECT DISTINCT a.mes FROM prtb00002 a WHERE
datos_c.fecha BETWEEN a.semana_del AND a.semana_al
IF STATUS = NOTFOUND THEN
CALL fgl_winmessage("INFO","NO EXISTEN PERIODOS PARA CONTROLAR ESTA FECHA, DEBE DIGITAR PERIODO PARA ESTA FECHA","INFO")
NEXT FIELD fecha
END IF }
AFTER INPUT
IF int_flag THEN
LET numero_msg = 2
CALL msg(numero_msg)
LET int_flag = false
RETURN
END IF
CALL arr_costos.clear()
CALL arr_oc.clear() -- documento nuevo: sin items de orden aun
END INPUT
# Arreglo para la captura de la produccion
INPUT ARRAY arr_costos FROM scr_costos.* ATTRIBUTES(WITHOUT DEFAULTS, UNBUFFERED)
BEFORE INPUT
IF datos_c.cod_mov = 1 THEN
CALL dialog.setFieldActive("depto_receptor",FALSE)
END IF
IF datos_c.cod_mov = 2 THEN
CALL pendientes()
CALL dialog.setFieldActive("cod_prod",FALSE)
CALL dialog.setFieldActive("lado1",FALSE)
CALL dialog.setFieldActive("lado2",FALSE)
CALL dialog.setFieldActive("lado3",FALSE)
CALL dialog.setFieldActive("codigo_bloque",FALSE)
CALL dialog.setFieldActive("depto_receptor",FALSE)
END IF
CALL coperacion()
CALL cturno()
DISPLAY "depto: ",datos_c.departamento
CALL maquinas(datos_c.departamento)
CALL departamentos_receptores()
ON KEY(F10)
LET curr = arr_curr()
LET scr_l = scr_line()
IF arr_costos[curr].cod_prod IS NOT NULL THEN
IF arr_costos[curr].codigo_bloque IS NULL THEN
LET numero_msg =16
CALL msg(numero_msg)
NEXT FIELD codigo_bloque
END IF
# CALL medidas()
DISPLAY arr_costos[curr].cantidad TO scr_costos[scr_l].cantidad
END IF
AFTER FIELD codigo_bloque
IF arr_costos[curr].codigo_bloque IS NOT NULL THEN
CALL verificar(arr_costos[curr].codigo_bloque) RETURNING existe
IF existe = 'N' THEN
CALL msg(3)
NEXT FIELD codigo_bloque
END IF
END IF
AFTER FIELD num_oc
IF arr_costos[curr].num_oc IS NOT NULL AND arr_costos[curr].num_oc > 0 THEN
SELECT status_t INTO tiene FROM prtb00012
WHERE num_oc = arr_costos[curr].num_oc
IF status = NOTFOUND THEN
CALL fgl_winmessage("Orden de pedido", "La orden no existe.", "exclamation")
NEXT FIELD num_oc
END IF
IF tiene IS NOT NULL THEN
CALL fgl_winmessage("Orden de pedido", "La orden no esta activa.", "exclamation")
NEXT FIELD num_oc
END IF
END IF
ON ACTION semielaborado
LET curr = arr_curr()
CALL buscaProd()
DISPLAY BY NAME descripcion,medida
DISPLAY arr_costos[curr].cod_prod TO scr_costos[scr_l].cod_prod
ON ACTION ordenped
LET curr = arr_curr()
IF arr_costos[curr].num_oc IS NOT NULL AND arr_costos[curr].num_oc > 0 THEN
CALL escoge_items_orden(arr_costos[curr].num_oc)
ELSE
CALL fgl_winmessage("Orden de pedido", "Digite primero el numero de orden.", "information")
END IF
ON ACTION empleado ATTRIBUTE(IMAGE="find")
CALL buscaemp()
DISPLAY BY NAME nombre
DISPLAY arr_costos[curr].emp_no TO scr_costos[scr_l].emp_no
BEFORE ROW
# Variables para controlar el indice del vector
LET curr = arr_curr()
LET scr_l = scr_line()
IF arr_costos[curr].cod_prod is not null THEN
# Busca la descripcion de la pila de la formula que se introdujo
# anteriormente
SELECT unique a.cod_prod,a.descripcion,a.unidad_med
INTO p_codigo,descripcion,medida
FROM cttb00001 a
WHERE
a.cod_prod = arr_costos[curr].cod_prod and
a.status_t is null
IF status >= 0 THEN
IF status = notfound THEN
LET numero_msg = 3
CALL msg(numero_msg)
NEXT FIELD cod_prod
END IF
ELSE
CALL integridad()
IF bandera = 1 THEN
LET bandera = 0
RETURN
END IF
END IF
DISPLAY BY NAME medida
DISPLAY BY NAME descripcion
# BUSCA COSTO SEMI-ELABORADO
LET selec =
"SELECT CONVERT(CHAR(10),MAX(a.fecha),103) ",
" FROM cttb00034 a ",
" WHERE CONVERT(DATE,a.fecha,103) < ? "," AND ",
" a.cod_prod = ? and ",
" a.status_t IS NULL"
PREPARE busca_fecha FROM selec
EXECUTE busca_fecha USING datos_c.fecha,arr_costos[curr].cod_prod INTO fecha1
LET pcosto_labor[curr] = 0
SELECT AVG(a.costo_lab) INTO pcosto_labor[curr]
FROM cttb00034 a
WHERE a.fecha = fecha1 and
a.cod_prod = arr_costos[curr].cod_prod and
a.status_t is null
IF pcosto_labor[curr] is null THEN
LET pcosto_labor[curr] = 0
END IF
LET pcosto_gasto[curr] = 0
SELECT AVG(a.costo_ga) INTO pcosto_gasto[curr]
FROM cttb00034 a
WHERE a.fecha = fecha1 AND
a.cod_prod = arr_costos[curr].cod_prod and
a.status_t IS NULL
IF pcosto_gasto[curr] is null THEN
LET pcosto_gasto[curr] = 0
END IF
END IF
# Busca el nombre del empleado
AFTER FIELD emp_no
IF arr_costos[curr].emp_no is not null THEN
SELECT a.nom1_emp,a.apell1_emp INTO nomb1,nomb2
FROM adtb00003 a
WHERE a.num_emp = arr_costos[curr].emp_no
# and a.nomina = "S"
IF status = notfound THEN
SELECT * INTO temporero.* FROM adtb00036
WHERE num_emp = arr_costos[curr].emp_no
IF status = notfound THEN
LET numero_msg = 3
CALL msg(numero_msg)
NEXT FIELD emp_no
END IF
LET nomb1 = temporero.nom1_emp
LET nomb2 = temporero.apell1_emp
END IF
LET nombre = nomb1 clipped,",",nomb2 clipped
DISPLAY BY NAME NOMBRE ATTRIBUTE (BOLD)
END IF
# Control del codigo de la produccion que estan acumulando
AFTER FIELD cod_prod
IF arr_costos[curr].cod_prod is not null THEN
# Busca la descripcion de la pila de la formula que se introdujo
# anteriormente
SELECT unique a.cod_prod,a.descripcion,a.unidad_med
INTO p_codigo,descripcion,medida
FROM cttb00001 a
WHERE
a.cod_prod = arr_costos[curr].cod_prod and
a.status_t is null
IF status >= 0 THEN
IF status = notfound THEN
LET numero_msg = 3
CALL msg(numero_msg)
NEXT FIELD cod_prod
END IF
ELSE
CALL integridad()
IF bandera = 1 THEN
LET bandera = 0
RETURN
END IF
END IF
DISPLAY BY NAME medida
DISPLAY BY NAME descripcion
# BUSCA COSTO SEMI-ELABORADO
LET selec =
"SELECT CONVERT(CHAR(10),MAX(a.fecha),103) ",
" FROM cttb00034 a ",
" WHERE CONVERT(DATE,a.fecha,103) < ? "," AND ",
" a.cod_prod = ? and ",
" a.status_t IS NULL"
PREPARE busca_fecha FROM selec
EXECUTE busca_fecha USING datos_c.fecha,arr_costos[curr].cod_prod INTO fecha1
LET pcosto_labor[curr] = 0
SELECT AVG(a.costo_lab) INTO pcosto_labor[curr]
FROM cttb00034 a
WHERE a.fecha = fecha1 and
a.cod_prod = arr_costos[curr].cod_prod and
a.status_t is null
IF pcosto_labor[curr] is null THEN
LET pcosto_labor[curr] = 0
END IF
LET pcosto_gasto[curr] = 0
SELECT AVG(a.costo_ga) INTO pcosto_gasto[curr]
FROM cttb00034 a
WHERE a.fecha = fecha1 AND
a.cod_prod = arr_costos[curr].cod_prod and
a.status_t IS NULL
IF pcosto_gasto[curr] is null THEN
LET pcosto_gasto[curr] = 0
END IF
END IF
#--------------------------------------------------------------------------
AFTER FIELD cantidad
IF arr_costos[curr].cantidad is null THEN
LET arr_costos[curr].cantidad = 0
END IF
# IF datos_c.factor > 0 THEN
# LET arr_costos[curr].h_directa =
# datos_c.factor / arr_costos[curr].cantidad
# DISPLAY arr_costos[curr].h_directa TO scr_costos[scr_l].h_directa
# END IF
IF medida = "MT2" THEN
LET arr_costos[curr].medida1 =
arr_costos[curr].cantidad * (arr_costos[curr].lado1 * arr_costos[curr].lado2)
END IF
IF medida= "MT3" THEN
LET arr_costos[curr].medida1 =
arr_costos[curr].cantidad * (arr_costos[curr].lado1 * arr_costos[curr].lado2 * arr_costos[curr].lado3)
END IF
IF medida= "ML" THEN
LET arr_costos[curr].medida1 =
arr_costos[curr].cantidad * arr_costos[curr].lado1
LET arr_costos[curr].lado2 = 0
END IF
IF medida= "UND" OR medida= "GL" THEN
LET arr_costos[curr].medida1 = arr_costos[curr].cantidad
END IF
DISPLAY arr_costos[curr].medida1 TO scr_costos[scr_l].medida1
{ AFTER FIELD depto_receptor
IF arr_costos[curr].depto_receptor IS NULL THEN
CALL dialog.setFieldActive('cantidad_enviada', FALSE)
--LET numero_msg = 16
--CALL msg(numero_msg)
--NEXT FIELD depto_receptor
ELSE
CALL dialog.setFieldActive('cantidad_enviada', TRUE)
END IF
AFTER FIELD cantidad_enviada
IF arr_costos[curr].cantidad_enviada > arr_costos[curr].medida1 THEN
LET numero_msg = 1677
CALL msg(numero_msg)
NEXT FIELD cantidad_enviada
ELSE
LET arr_costos[curr].diferencia = arr_costos[curr].medida1 - arr_costos[curr].cantidad_enviada
DISPLAY arr_costos[curr].diferencia TO scr_costos[scr_l].diferencia
END IF }
AFTER INPUT
# Control de la cancelacion de la operacion que se esta realizando en
# el momento.
IF int_flag THEN
LET numero_msg = 2
CALL msg(numero_msg)
LET int_flag = FALSE
CLEAR FORM
RETURN
END IF
FOR idx = 1 TO arr_costos.getlength()
IF datos_c.cod_mov = 2 THEN
IF controlExistencia_entrada[idx].num_doc =
arr_costos[idx].ref AND
controlExistencia_entrada[idx].cod_prod = arr_costos[idx].cod_prod THEN
IF controlExistencia_entrada[idx].medida < arr_costos[idx].medida1 THEN
LET numero_msg = 30
CALL msg(numero_msg)
NEXT FIELD cantidad
END IF
END IF
END IF
IF datos_c.cod_mov = 3 THEN
IF arr_costos[idx].depto_receptor IS NULL THEN
LET numero_msg = 16
CALL msg(numero_msg)
NEXT FIELD depto_receptor
END IF
END IF
IF arr_costos[idx].cod_prod IS NULL THEN
LET numero_msg = 16
CALL msg(numero_msg)
NEXT FIELD cod_prod
END IF
END FOR
# CONTROL SECUENCIAL
# La obtencion del num_doc se hace ATOMICA dentro de la transaccion:
# el UPDATE ... ult_num + 1 toma un bloqueo exclusivo sobre la fila de
# cttb00010 hasta el COMMIT/ROLLBACK, serializando a productores
# concurrentes y evitando num_doc duplicado (misma clase de carrera que
# se corrigio en iptb00007). Si luego se hace ROLLBACK, el numero se
# libera automaticamente (sin hueco).
BEGIN WORK
UPDATE cttb00010 SET ult_num = ult_num + 1
SELECT ult_num INTO datos_c.num_doc FROM cttb00010
DISPLAY BY NAME datos_c.num_doc
UPDATE cttb00012 SET documento = datos_c.num_doc WHERE documento = tmpnumero
# Control para chequeo de las informaciones si estan correctas
# da oportunidad al usuario de arreglar en el momento errores
LABEL atras:
SELECT estado_mov INTO estadomov FROM cttb00005
WHERE cod_mov = datos_c.cod_mov AND status_t IS NULL
LET continuar = TRUE
IF estadomov = 2 THEN
FOR idx = 1 TO arr_count()
LET arr_costos[idx].cantidad = arr_costos[idx].cantidad * -1
LET arr_costos[idx].medida1 = arr_costos[idx].medida1 * -1
END FOR
END IF
FOR idx = 1 to arr_count()
# Se inserta toda linea con producto (no solo las que tienen empleado).
# Las entradas por transferencia (cod_mov=2) traen emp_no NULL desde
# p_seleccionado_data; con el guard viejo (emp_no) se perdian.
IF arr_costos[idx].cod_prod IS NOT NULL THEN
IF arr_costos[idx].h_directa is null THEN
LET arr_costos[idx].h_directa = 0
END IF
IF arr_costos[idx].h_indirecta is null THEN
LET arr_costos[idx].h_indirecta = 0
END IF
IF arr_costos[idx].e_directa is null THEN
LET arr_costos[idx].e_directa = 0
END IF
IF arr_costos[idx].e_indirecta is null THEN
LET arr_costos[idx].e_indirecta = 0
END IF
INITIALIZE check_existencia TO NULL
INSERT INTO cttb00003
( num_doc
, fecha
, departamento
, emp_no
, cod_tipo
, cod_mq
, detalle
, h_directa
, h_indirecta
, e_directa
, e_indirecta
, cod_prod
, lado2
, lado1
, lado3
, cantidad
, medida
, codigo_bloque
, costo_lab
, costo_gasto
, turno
, us_crea
, fech_crea
, depto_receptor
, cod_mov
, ref
, num_oc)
VALUES
(datos_c.num_doc,datos_c.fecha,datos_c.departamento,
arr_costos[idx].emp_no,arr_costos[idx].tipo,arr_costos[idx].codigo,NULL,
arr_costos[idx].h_directa,arr_costos[idx].h_indirecta,
arr_costos[idx].e_directa,arr_costos[idx].e_indirecta,
arr_costos[idx].cod_prod,arr_costos[idx].lado2,arr_costos[idx].lado1,
arr_costos[idx].lado3,
arr_costos[idx].cantidad,arr_costos[idx].medida1, arr_costos[idx].codigo_bloque,
pcosto_labor[idx],pcosto_gasto[idx],arr_costos[idx].turno,
SUSER_SNAME(),GETDATE(),arr_costos[idx].depto_receptor, datos_c.cod_mov, arr_costos[idx].ref,
arr_costos[idx].num_oc )
LET query = 'SELECT SUM(medida) FROM cttb00003 WHERE status_t IS NULL
AND departamento = ? AND cod_prod = ?'
PREPARE existencia FROM query
EXECUTE existencia INTO check_existencia USING datos_c.departamento, arr_costos[idx].cod_prod
DISPLAY "existencia: ", check_existencia
IF check_existencia < 0 THEN
LET continuar = FALSE
ROLLBACK WORK
LET numero_msg = 30
CALL msg(numero_msg)
IF estadomov = 2 THEN
FOR idx = 1 TO arr_count()
LET arr_costos[idx].cantidad = arr_costos[idx].cantidad * -1
LET arr_costos[idx].medida1 = arr_costos[idx].medida1 * -1
END FOR
END IF
NEXT FIELD cantidad
EXIT FOR
END IF
END IF
END FOR
IF continuar THEN
# cttb00014 es el inventario mensual (lo mantiene ctprmt012); NO es
# libro de movimientos. El movimiento ya queda en cttb00003.
# CALL InsertarTabla14() -- removido: cttb00014 no tiene esas columnas
# ult_num ya fue incrementado atomicamente al abrir la transaccion.
DISPLAY BY NAME datos_c.num_doc
CALL guardar_oc(datos_c.num_doc) -- items de orden (tabla hija)
CALL imprime(datos_c.*, arr_costos)
COMMIT WORK
LET numero_msg = 1
CALL msg(numero_msg)
# Vuelve hacia el campo inicial de la pantalla para proseguir con el
# siguiente documento
RETURN
GOTO volver
END IF
#----------------------------------------------------------------------------
EXIT INPUT
END INPUT
#---------------------------------------------------------------------------
END FUNCTION
# -------------------------- FUNCION DE ENTRADA --------------------
FUNCTION pendientes()
DEFINE idx INT
DEFINE query STRING
INITIALIZE pendientes TO NULL
LET query = "SELECT
Salida.num_doc AS Documento_Salida,
Salida.departamento AS Depto_Origen,
Salida.cod_prod AS Producto,
((Salida.cantidad*-1) - ISNULL(Entrada.Total_Cantidad,0)) as Cantidad_Pendiente,
(Salida.medida*-1) AS Cantidad_Total_Enviada,
ISNULL(Entrada.Total_Recibido, 0) AS Cantidad_Ya_Recibida,
((Salida.medida*-1) - ISNULL(Entrada.Total_Recibido, 0)) AS Medida_Pendiente,
0
FROM
cttb00003 Salida
LEFT JOIN (
SELECT
ref,
SUM(cantidad) as Total_Cantidad,
SUM(medida) AS Total_Recibido
FROM
cttb00003
WHERE
cod_mov = 2
and status_t is null
GROUP BY
ref
) Entrada ON Salida.num_doc = Entrada.ref
WHERE
Salida.cod_mov = 3
AND Salida.depto_receptor = ",datos_c.departamento,"
AND salida.status_t is null
AND ((Salida.medida*-1) - ISNULL(Entrada.Total_Recibido, 0)) > 0; "
DECLARE buscar_pendientes CURSOR FROM query
LET idx = 1
FOREACH buscar_pendientes INTO pendientes[idx].num_doc,
pendientes[idx].departamento,
pendientes[idx].cod_prod,
pendientes[idx].cantidad,
pendientes[idx].Cantidad_Total_Enviada,
pendientes[idx].Cantidad_Ya_Recibida,
pendientes[idx].Pendiente_Por_Entrar,
pendientes[idx].CHECK
DISPLAY "Medida: ", pendientes[idx].Pendiente_Por_Entrar
LET idx = idx + 1
END FOREACH
IF pendientes[1].num_doc IS NOT NULL THEN
OPEN WINDOW wpendiente WITH FORM 'pendientes'
INPUT ARRAY pendientes FROM pendiente_record.* ATTRIBUTES(WITHOUT DEFAULTS, UNBUFFERED, INSERT ROW = FALSE,
DELETE ROW = FALSE,
APPEND ROW = FALSE)
BEFORE INPUT
CALL departamentos_produccion()
ON ACTION CANCEL ATTRIBUTES(TEXT = 'Cancelar')
EXIT INPUT
ON CHANGE CHECK
FOR idx = 1 TO pendientes.getLength()
IF idx <> arr_curr() THEN
LET pendientes[idx].check = 0
END IF
END FOR
ON ACTION ACCEPT ATTRIBUTES(TEXT = "Seleccionar")
LET idx = 1
FOR idx = 1 TO pendientes.getLength()
IF pendientes[idx].CHECK THEN
CALL p_seleccionado_data(pendientes[idx].num_doc)
EXIT FOR
END IF
END FOR
EXIT INPUT
END INPUT
CLOSE WINDOW wpendiente
END IF
END FUNCTION
FUNCTION p_seleccionado_data(documento INT)
DEFINE idx INT, query STRING
INITIALIZE controlExistencia_entrada TO NULL
LET query = "SELECT
NULL,NULL,NULL,
Salida.h_directa,
Salida.h_indirecta,
Salida.e_directa,
Salida.e_indirecta,
Salida.cod_prod,
Salida.lado1,
Salida.lado2,
Salida.lado3,
((Salida.cantidad*-1) - ISNULL(Entrada.Total_Cantidad,0)) as Cantidad_Pendiente,
((Salida.medida*-1) - ISNULL(Entrada.Total_Recibido, 0)) AS Medida_Pendiente,
Salida.codigo_bloque,
NULL,NULL,
Salida.num_doc,
NULL
FROM
cttb00003 Salida
LEFT JOIN (
SELECT
ref,
SUM(cantidad) as Total_Cantidad,
SUM(medida) AS Total_Recibido
FROM
cttb00003
WHERE
cod_mov = 2
and ref = ",documento,"
and status_t is null
GROUP BY
ref
) Entrada ON Salida.num_doc = Entrada.ref
WHERE
Salida.cod_mov = 3
AND Salida.num_doc = ",documento,"
AND salida.status_t is null
AND ((Salida.medida*-1) - ISNULL(Entrada.Total_Recibido, 0)) > 0; "
DECLARE pendiente_seleccionado CURSOR FROM query
LET idx = 1
FOREACH pendiente_seleccionado INTO arr_costos[idx].*
LET controlExistencia_entrada[idx].num_doc = documento
LET controlExistencia_entrada[idx].cod_prod = arr_costos[idx].cod_prod
LET controlExistencia_entrada[idx].cantidad = arr_costos[idx].cantidad
LET controlExistencia_entrada[idx].medida = arr_costos[idx].medida1
LET idx = idx + 1
END FOREACH
END FUNCTION
# -------------------------- FUNCION DE MODIFICACION --------------------
FUNCTION prprmod()
# Si viene un documento pre-seleccionado desde la pagina "Documentos",
# se omite el criterio de busqueda y se carga ese documento directo.
IF g_num_preselect > 0 THEN
LET criterio = "a.num_doc = ", g_num_preselect USING "<<<<<<<<<"
LET g_num_preselect = 0
# Llenar los combos (antes se hacia en BEFORE CONSTRUCT, que aqui se omite)
CALL departamentos_produccion()
CALL movimientos()
ELSE
CONSTRUCT BY NAME criterio ON a.num_doc,a.fecha,a.departamento, a.cod_mov
BEFORE CONSTRUCT
CALL departamentos_produccion()
CALL movimientos()
AFTER CONSTRUCT
IF int_flag THEN
LET int_flag = FALSE
RETURN
END IF
EXIT CONSTRUCT
END CONSTRUCT
END IF
LET selec =
"SELECT UNIQUE a.num_doc,CONVERT(CHAR(10),a.fecha,103),a.departamento, a.cod_mov ",
"FROM cttb00003 a ",
"WHERE ",criterio clipped, " And a.status_t is null",
" ORDER BY a.num_doc,CONVERT(CHAR(10),a.fecha,103),a.departamento, a.cod_mov"
DISPLAY selec
IF int_flag THEN
LET numero_msg = 2
CALL msg(numero_msg)
LET int_flag = false
RETURN
END IF
PREPARE comando FROM selec
DECLARE buscate SCROLL CURSOR FOR comando
OPEN buscate
IF int_flag THEN
LET numero_msg = 2
CALL msg(numero_msg)
LET int_flag = false
RETURN
END IF
FETCH FIRST buscate INTO datos_c.*
IF status = notfound THEN
LET numero_msg = 3
CALL msg(numero_msg)
RETURN
END IF
SELECT a.nom_dpto INTO descrip2 FROM adtb00001 a
WHERE a.departamento = datos_c.departamento and
a.status_t is NULL
DISPLAY BY NAME datos_c.* #,descrip2
MENU "OPCIONES "
COMMAND "Siguiente"
"Presenta en pantalla el proximo registro encontrado"
FETCH NEXT buscate INTO datos_c.*
IF STATUS = NOTFOUND THEN
LET numero_msg = 4
CALL msg(numero_msg)
END IF
SELECT a.nom_dpto INTO descrip2 FROM adtb00001 a
WHERE a.departamento = datos_c.departamento and
a.status_t is null
# DISPLAY BY NAME descrip2 ATTRIBUTE (BOLD)
DISPLAY BY NAME datos_c.*
COMMAND "Anterior"
"Presenta en pantalla el registro anterior encontrado"
FETCH PREVIOUS buscate INTO datos_c.*
IF STATUS = NOTFOUND THEN
LET numero_msg = 5
CALL msg(numero_msg)
END IF
SELECT a.nom_dpto INTO descrip2 FROM adtb00001 a
WHERE a.departamento = datos_c.departamento and
a.status_t is null
# DISPLAY BY NAME descrip2 ATTRIBUTE (BOLD)
DISPLAY BY NAME datos_c.*
COMMAND "Primero"
"Presenta en pantalla el primer registro encontrado"
FETCH FIRST buscate INTO datos_c.*
DISPLAY BY NAME datos_c.*
SELECT a.nom_dpto INTO descrip2 FROM adtb00001 a
WHERE a.departamento = datos_c.departamento and
a.status_t is null
#DISPLAY BY NAME descrip2 ATTRIBUTE (BOLD)
LET numero_msg = 5
CALL msg(numero_msg)
COMMAND "Ultimo"
"Presenta en pantalla el ultimo registro encontrado"
FETCH LAST buscate INTO datos_c.*
DISPLAY BY NAME datos_c.*
LET numero_msg = 4
SELECT a.nom_dpto INTO descrip2 FROM adtb00001 a
WHERE a.departamento = datos_c.departamento and
a.status_t is null
# DISPLAY BY NAME descrip2 ATTRIBUTE (BOLD)
COMMAND "Escoger"
"<Esc> Actualiza Registro <Ctrl-C> Cancela Operacion"
SELECT a.nom_dpto INTO descrip2 FROM adtb00001 a
WHERE a.departamento = datos_c.departamento and
a.status_t is null
#DISPLAY BY NAME descrip2 ATTRIBUTE (BOLD)
INPUT BY NAME datos_c.fecha THRU datos_c.departamento
WITHOUT DEFAULTS
AFTER FIELD fecha
IF datos_c.fecha is null THEN
LET numero_msg = 16
CALL msg(numero_msg)
NEXT FIELD fecha
END IF
IF datos_c.fecha > today THEN
LET numero_msg = 189
CALL msg(numero_msg)
NEXT FIELD fecha
END IF
{ SELECT DISTINCT a.mes FROM prtb00002 a WHERE
datos_c.fecha BETWEEN a.semana_del AND a.semana_al
IF STATUS = NOTFOUND THEN
CALL fgl_winmessage("INFO","NO EXISTEN PERIODOS PARA CONTROLAR ESTA FECHA, DEBE DIGITAR PERIODO PARA ESTA FECHA","INFO")
NEXT FIELD fecha
END IF }
AFTER INPUT
IF int_flag THEN
LET int_flag = false
LET numero_msg = 2
CALL msg(numero_msg)
RETURN
END IF
EXIT INPUT
END INPUT
DECLARE busca10 CURSOR FOR
SELECT a.cod_tipo,a.cod_mq,a.emp_no,a.h_directa,a.h_indirecta,a.e_directa,a.e_indirecta,
a.cod_prod,a.lado2,a.lado1,a.lado3,a.cantidad,a.medida,a.codigo_bloque,a.turno,
a.depto_receptor,a.ref,
a.num_oc
FROM cttb00003 a
WHERE a.num_doc = datos_c.num_doc AND a.status_t IS NULL
LET idx = 1
FOREACH busca10 INTO arr_costos[idx].*
# Se normaliza a magnitud absoluta para mostrar/editar en positivo (igual
# que en el alta). El signo se re-aplica segun el concepto al re-insertar,
# dejando cantidad y medida siempre con el mismo signo.
IF arr_costos[idx].cantidad < 0 THEN
LET arr_costos[idx].cantidad = arr_costos[idx].cantidad * -1
END IF
IF arr_costos[idx].medida1 < 0 THEN
LET arr_costos[idx].medida1 = arr_costos[idx].medida1 * -1
END IF
LET idx = idx + 1
END FOREACH
CALL cargar_oc(datos_c.num_doc) -- items de orden del documento
CALL set_count(idx-1)
# Arreglo para la captura de la produccion
INPUT ARRAY arr_costos WITHOUT DEFAULTS FROM scr_costos.*
BEFORE INPUT
CALL coperacion()
CALL cturno()
CALL maquinas(datos_c.departamento)
CALL departamentos_receptores()
ON KEY(F10)
LET curr = arr_curr()
LET scr_l = scr_line()
IF arr_costos[curr].cod_prod IS NOT NULL THEN
IF arr_costos[curr].codigo_bloque IS NULL THEN
LET numero_msg =16
CALL msg(numero_msg)
NEXT FIELD codigo_bloque
END IF
CALL medidas()
DISPLAY arr_costos[curr].cantidad TO scr_costos[scr_l].cantidad
END IF
ON ACTION imprimir
CALL imprime(datos_c.*, arr_costos)
ON ACTION ordenped
LET curr = arr_curr()
IF arr_costos[curr].num_oc IS NOT NULL AND arr_costos[curr].num_oc > 0 THEN
CALL escoge_items_orden(arr_costos[curr].num_oc)
ELSE
CALL fgl_winmessage("Orden de pedido", "Digite primero el numero de orden.", "information")
END IF
BEFORE ROW
# Variables para controlar el indice del vector
LET curr = arr_curr()
LET scr_l = scr_line()
AFTER FIELD codigo_bloque
IF arr_costos[curr].codigo_bloque IS NOT NULL THEN
CALL verificar(arr_costos[curr].codigo_bloque) RETURNING existe
IF existe = 'N' THEN
CALL msg(3)
NEXT FIELD codigo_bloque
END IF
END IF
AFTER FIELD num_oc
IF arr_costos[curr].num_oc IS NOT NULL AND arr_costos[curr].num_oc > 0 THEN
SELECT status_t INTO tiene FROM prtb00012
WHERE num_oc = arr_costos[curr].num_oc
IF status = NOTFOUND THEN
CALL fgl_winmessage("Orden de pedido", "La orden no existe.", "exclamation")
NEXT FIELD num_oc
END IF
IF tiene IS NOT NULL THEN
CALL fgl_winmessage("Orden de pedido", "La orden no esta activa.", "exclamation")
NEXT FIELD num_oc
END IF
END IF
{ AFTER FIELD turno
IF arr_costos[curr].turno IS NOT NULL THEN
SELECT a.descripcion INTO tdescripcion FROM cttb00018 a
WHERE a.turno = arr_costos[curr].turno
IF STATUS = NOTFOUND THEN
LET numero_msg = 3
CALL msg(numero_msg)
NEXT FIELD turno
END IF
DISPLAY BY NAME tdescripcion
END IF
# Busca descripcion de la maquina
AFTER FIELD tipo
IF arr_costos[curr].tipo is not null THEN
SELECT a.descripcion INTO nombre_mq FROM prtb00005 a
WHERE a.codigo = arr_costos[curr].tipo and a.status_t is null
IF STATUS = NOTFOUND THEN
LET numero_msg = 3
CALL msg(numero_msg)
NEXT FIELD tipo
END IF
DISPLAY BY NAME nombre_mq
LET nomb_mq[curr] = nombre_mq
END IF }
# Busca el nombre del empleado
AFTER FIELD emp_no
IF arr_costos[curr].emp_no is not null THEN
SELECT a.nom1_emp,a.apell1_emp INTO nomb1,nomb2
FROM adtb00003 a
WHERE a.num_emp = arr_costos[curr].emp_no
# and a.nomina = "S"
IF status = notfound THEN
SELECT * INTO temporero.* FROM adtb00036
WHERE num_emp = arr_costos[curr].emp_no
IF status = notfound THEN
LET numero_msg = 3
CALL msg(numero_msg)
NEXT FIELD emp_no
END IF
LET nomb1 = temporero.nom1_emp
LET nomb2 = temporero.apell1_emp
END IF
LET nombre = nomb1 clipped," ",nomb2 clipped
DISPLAY BY NAME NOMBRE ATTRIBUTE (BOLD)
END IF
# Control del codigo de la produccion que estan acumulando
AFTER FIELD cod_prod
IF arr_costos[curr].cod_prod is not null THEN
# Busca la descripcion de la pila de la formula que se introdujo
# anteriormente
SELECT unique a.cod_prod,a.descripcion,a.unidad_med
INTO p_codigo,descripcion,medida
FROM cttb00001 a
WHERE
a.cod_prod = arr_costos[curr].cod_prod and
a.status_t is null
IF status >= 0 THEN
IF status = notfound THEN
LET numero_msg = 3
CALL msg(numero_msg)
NEXT FIELD cod_prod
END IF
ELSE
CALL integridad()
IF bandera = 1 THEN
LET bandera = 0
RETURN
END IF
END IF
DISPLAY BY NAME medida
DISPLAY BY NAME descripcion
# BUSCA COSTO SEMI-ELABORADO
LET selec =
"SELECT CONVERT(CHAR(10),MAX(a.fecha),103) ",
" FROM cttb00034 a ",
" WHERE CONVERT(DATE,a.fecha,103) < ? "," AND ",
" a.cod_prod = ? and ",
" a.status_t IS NULL"
PREPARE busca_fecha1 FROM selec
EXECUTE busca_fecha1 USING datos_c.fecha,arr_costos[curr].cod_prod INTO fecha1
LET pcosto_labor[curr] = 0
SELECT AVG(a.costo_lab) INTO pcosto_labor[curr]
FROM cttb00034 a
WHERE a.fecha = fecha1 and
a.cod_prod = arr_costos[curr].cod_prod and
a.status_t is null
IF pcosto_labor[curr] is null THEN
LET pcosto_labor[curr] = 0
END IF
LET pcosto_gasto[curr] = 0
SELECT AVG(a.costo_ga) INTO pcosto_gasto[curr]
FROM cttb00034 a
WHERE a.fecha = fecha1 AND
a.cod_prod = arr_costos[curr].cod_prod and
a.status_t IS NULL
IF pcosto_gasto[curr] is null THEN
LET pcosto_gasto[curr] = 0
END IF
END IF
#--------------------------------------------------------------------------
IF arr_costos[curr].cantidad is null THEN
LET arr_costos[curr].cantidad = 0
END IF
#IF datos_c.factor > 0 THEN
# LET arr_costos[curr].h_directa =
# datos_c.factor / arr_costos[curr].cantidad
# DISPLAY arr_costos[curr].h_directa TO scr_costos[scr_l].h_directa
#END IF
IF medida = "MT2" THEN
LET arr_costos[curr].medida1 =
arr_costos[curr].cantidad * (arr_costos[curr].lado1 * arr_costos[curr].lado2)
END IF
IF medida= "MT3" THEN
LET arr_costos[curr].medida1 =
arr_costos[curr].cantidad * (arr_costos[curr].lado1 * arr_costos[curr].lado2 * arr_costos[curr].lado3)
END IF
IF medida= "ML" THEN
LET arr_costos[curr].medida1 =
arr_costos[curr].cantidad * arr_costos[curr].lado1
LET arr_costos[curr].lado2 = 0
END IF
IF medida= "UND" OR medida= "GL" THEN
LET arr_costos[curr].medida1 = arr_costos[curr].cantidad
END IF
DISPLAY arr_costos[curr].medida1 TO scr_costos[scr_l].medida1
{ AFTER FIELD depto_receptor
IF arr_costos[curr].depto_receptor IS NULL THEN
CALL dialog.setFieldActive('cantidad_enviada', FALSE)
--LET numero_msg = 16
--CALL msg(numero_msg)
--NEXT FIELD depto_receptor
ELSE
CALL dialog.setFieldActive('cantidad_enviada', TRUE)
END IF
AFTER FIELD cantidad_enviada
IF arr_costos[curr].cantidad_enviada > arr_costos[curr].medida1 THEN
LET numero_msg = 1677
CALL msg(numero_msg)
NEXT FIELD cantidad_enviada
ELSE
LET arr_costos[curr].diferencia = arr_costos[curr].medida1 - arr_costos[curr].cantidad_enviada
DISPLAY arr_costos[curr].diferencia TO scr_costos[scr_l].diferencia
END IF }
AFTER INPUT
# Control de la cancelacion de la operacion que se esta realizando en
# el momento.
IF int_flag THEN
LET numero_msg = 2
CALL msg(numero_msg)
LET int_flag = FALSE
CLEAR FORM
RETURN
END IF
#----------------------------------------------------------------------------
EXIT INPUT
END INPUT
{
# REALIZA UNA COPIA DE LOS REGISTROS ANTES DE BORRARLOS
FOR idx = 1 to arr_count()
IF arr_costos[idx].emp_no is not null THEN
INSERT INTO cttb00017 values
(datos_c.num_doc,datos_c.fecha,datos_c.departamento,
arr_costos[idx].emp_no,arr_costos[idx].tipo,nomb_mq[idx],
arr_costos[idx].h_directa,arr_costos[idx].h_indirecta,
arr_costos[idx].e_directa,arr_costos[idx].e_indirecta,
arr_costos[idx].cod_prod,arr_costos[idx].cantidad,arr_costos[idx].codigo_bloque,
pcosto_labor[idx],pcosto_gasto[idx],
arr_costos[idx].turno,null,usuario_c,fecha_c,SUSER_SNAME(),GETDATE())
END IF
END FOR
}
BEGIN WORK
DELETE FROM cttb00003 WHERE num_doc = datos_c.num_doc
SELECT estado_mov INTO estadomov FROM cttb00005
WHERE cod_mov = datos_c.cod_mov AND status_t IS NULL
# Los valores en arr_costos estan en magnitud absoluta. Para una SALIDA
# (estado_mov = 2) se aplica el signo negativo a cantidad Y medida por
# igual, para que ambos queden consistentes (mismo criterio que el alta).
IF estadomov = 2 THEN
FOR idx = 1 TO arr_count()
LET arr_costos[idx].cantidad = arr_costos[idx].cantidad * -1
LET arr_costos[idx].medida1 = arr_costos[idx].medida1 * -1
END FOR
END IF
FOR idx = 1 to arr_count()
IF arr_costos[idx].cod_prod IS NOT NULL THEN
INSERT INTO cttb00003
( num_doc
, fecha
, departamento
, emp_no
, cod_tipo
, cod_mq
, detalle
, h_directa
, h_indirecta
, e_directa
, e_indirecta
, cod_prod
,lado2
,lado1
,lado3
, cantidad
,medida
, codigo_bloque
, costo_lab
, costo_gasto
, turno
, us_crea
, fech_crea
, depto_receptor
, cod_mov
, ref
, num_oc)
values
(datos_c.num_doc,datos_c.fecha,datos_c.departamento,
arr_costos[idx].emp_no,arr_costos[idx].tipo,arr_costos[idx].codigo, NULL,
arr_costos[idx].h_directa,arr_costos[idx].h_indirecta,
arr_costos[idx].e_directa,arr_costos[idx].e_indirecta,
arr_costos[idx].cod_prod,arr_costos[idx].lado2,arr_costos[idx].lado1,arr_costos[idx].lado3,
arr_costos[idx].cantidad,arr_costos[idx].medida1, arr_costos[idx].codigo_bloque,
pcosto_labor[idx],pcosto_gasto[idx], arr_costos[idx].turno,
SUSER_SNAME(),GETDATE(), arr_costos[idx].depto_receptor, datos_c.cod_mov, arr_costos[idx].ref,
arr_costos[idx].num_oc)
END IF
END FOR
# CALL InsertarTabla14() -- removido: cttb00014 no lleva columnas de movimiento
CALL guardar_oc(datos_c.num_doc) -- items de orden (tabla hija)
COMMIT WORK
CALL integridad()
IF bandera = "1" THEN
LET bandera = 0
RETURN
END IF
LET numero_msg = 13
CALL msg(numero_msg)
CLEAR FORM
COMMAND "Retornar"
"Retorna al menu Anterior"
EXIT MENU
END MENU
END FUNCTION
{
FUNCTION repite()
DEFINE producto,codigo SMALLINT
LET codigo = arr_costos[curr].departamento
LET producto = arr_costos[curr].cod_prod
FOR idx = 1 TO arr_count()
IF idx != curr THEN
IF arr_costos[idx].departamento IS NOT NULL THEN
IF arr_costos[idx].departamento = codigo and
arr_costos[idx].cod_prod = producto THEN
LET numero_msg = 21
CALL msg(numero_msg)
LET existe = "S"
ELSE
IF existe != "S" THEN
LET existe = "N"
END IF
END IF
END IF
END IF
END FOR
END FUNCTION
}
FUNCTION prpranula()
INPUT BY NAME datos_c.num_doc,datos_c.fecha WITHOUT DEFAULTS
# Permanece la ultima fecha que el introdujo
BEFORE INPUT
CALL Dialog.setFieldActive('num_doc', TRUE)
BEFORE FIELD fecha
LET datos_c.fecha = TODAY
DISPLAY BY NAME datos_c.fecha
AFTER FIELD fecha
LET hoy = datos_c.fecha
IF datos_c.fecha is null THEN
LET numero_msg = 16
CALL msg(numero_msg)
NEXT FIELD fecha
END IF
SELECT unique a.departamento INTO datos_c.departamento FROM cttb00003 a
WHERE a.fecha = datos_c.fecha and
a.num_doc = datos_c.num_doc and
a.status_t is null
IF status = notfound THEN
LET numero_msg = 12
CALL msg(numero_msg)
NEXT FIELD num_doc
END IF
SELECT a.nom_dpto INTO descrip2 FROM adtb00001 a
WHERE a.departamento = datos_c.departamento and
a.status_t is null
DISPLAY BY NAME datos_c.departamento #,descrip2
AFTER INPUT
IF int_flag THEN
LET numero_msg = 2
CALL msg(numero_msg)
LET int_flag = false
RETURN
END IF
IF datos_c.fecha is null THEN
LET numero_msg = 16
CALL msg(numero_msg)
NEXT FIELD fecha
END IF
EXIT INPUT
END INPUT
LET opcion = fgl_winquestion("PREGUNTA","DESA ANULAR ESTE DOCUMENTO?","no","yes|no","QUESTION",0)
LET opcion = upshift (opcion)
IF opcion = "YES" THEN
UPDATE cttb00003 SET status_t = "E",
us_mod = SUSER_SNAME(),
fech_mod = GETDATE()
WHERE fecha = datos_c.fecha and
num_doc = datos_C.num_doc and
departamento = datos_c.departamento
# cttb00014 (inventario mensual) no tiene num_doc; la anulacion solo
# aplica al movimiento en cttb00003. Se removio el UPDATE a cttb00014.
LET numero_msg = 82
CALL msg(numero_msg)
END IF
END FUNCTION
FUNCTION buscaProd()
DEFINE aproducto DYNAMIC ARRAY OF RECORD
cod_prod INT,
descripcion CHAR(40),
unidad_med CHAR(3)
END RECORD
OPEN WINDOW prfmwd010 AT 8,7 WITH FORM "prfmwd010" ATTRIBUTE (BORDER)
CONSTRUCT BY NAME criterio ON a.descripcion
LET selec = "SELECT a.cod_prod,a.descripcion,a.unidad_med FROM cttb00001 a WHERE ",criterio CLIPPED,
" AND a.status_t IS NULL ORDER BY a.descripcion"
PREPARE comando10 FROM selec
DECLARE buscap10 CURSOR FOR comando10
LET idx = 1
FOREACH buscap10 INTO aproducto[idx].*
LET idx = idx + 1
END FOREACH
CALL set_count(idx-1)
DISPLAY ARRAY aproducto TO sprod.*
LET idx = arr_curr()
IF int_flag THEN
LET int_flag = FALSE
END IF
LET arr_costos[curr].cod_prod = aproducto[idx].cod_prod
LET descripcion = aproducto[idx].descripcion
LET medida = aproducto[idx].unidad_med
CLOSE WINDOW prfmwd010
END FUNCTION
FUNCTION buscaEMP()
DEFINE aempleado ARRAY[500] OF RECORD
num_emp INT,
nom1_emp CHAR(40),
apell1_emp CHAR(40)
END RECORD
OPEN WINDOW prfmwd011 AT 8,7 WITH FORM "prfmwd011" ATTRIBUTE (BORDER)
CONSTRUCT BY NAME criterio ON a.nom1_emp,a.apell1_emp
LET selec = "SELECT a.num_emp,a.nom1_emp,a.apell1_emp FROM adtb00003 a WHERE ",criterio CLIPPED,
" AND a.status_t IS NULL ORDER BY a.nom1_emp"
PREPARE comando11 FROM selec
DECLARE buscap11 CURSOR FOR comando11
LET idx = 1
FOREACH buscap11 INTO aempleado[idx].*
LET idx = idx + 1
END FOREACH
CALL set_count(idx-1)
DISPLAY ARRAY aempleado TO sficha.*
AFTER DISPLAY
LET idx = arr_curr()
IF int_flag THEN
EXIT DISPLAY
LET int_flag = FALSE
END IF
LET arr_costos[curr].emp_no = aempleado[idx].num_emp
LET nombre = aempleado[idx].nom1_emp CLIPPED," ",aempleado[idx].apell1_emp CLIPPED
DISPLAY "EMPLE ",aempleado[idx].nom1_emp," ",aempleado[idx].apell1_emp
END DISPLAY
CLOSE WINDOW prfmwd011
END FUNCTION
FUNCTION medidas()
DEFINE arrmedida ARRAY[20] OF RECORD
ancho1 DEC(12,5),
largo1 DEC(12,5),
espesor1 DEC(12,5),
medida1 DEC(12,5),
ancho2 DEC(12,5),
largo2 DEC(12,5),
espesor2 DEC(12,5),
medida2 DEC(12,5),
cantidad DEC(12,5)
END RECORD,
total_medida DEC(12,5)
OPEN WINDOW prfmwd012 AT 8,3 WITH FORM "prfmwd012" ATTRIBUTE (BORDER)
DISPLAY arr_costos[curr].cod_prod TO cod_prod
DISPLAY arr_costos[curr].codigo_bloque TO codigo_bloque
DISPLAY BY NAME descripcion,medida
IF modifica = "S" THEN
DECLARE busca_m CURSOR FOR
SELECT a.ancho1,a.largo1,a.espesor1,a.medida1,
a.ancho2,a.largo2,a.espesor2,a.medida2,a.cantidad
FROM cttb00012 a
WHERE a.documento = datos_c.num_doc AND
a.cod_prod = arr_costos[curr].cod_prod and
a.codigo_bloque = arr_costos[curr].codigo_bloque
LET idx = 1
FOREACH busca_m INTO arrmedida[idx].*
LET idx = idx + 1
END FOREACH
CALL set_count(idx-1)
END IF
SELECT MAX(numero) INTO tmpnumero FROM cttb00016
IF tmpnumero IS NULL THEN
LET tmpnumero = 9999999
END IF
LET tmpnumero = tmpnumero + 1
INSERT INTO cttb00016 values (SUSER_SNAME(),tmpnumero,GETDATE())
FOR idx = 1 TO 10
LET arrmedida[idx].ancho1 = 0
LET arrmedida[idx].largo1 = 0
LET arrmedida[idx].espesor1 = 0
LET arrmedida[idx].ancho2 = 0
LET arrmedida[idx].largo2 = 0
LET arrmedida[idx].espesor2 = 0
END FOR
INPUT ARRAY arrmedida WITHOUT DEFAULTS FROM sdespiece.*
BEFORE ROW
LET idx = arr_curr()
LET sidx = scr_line()
AFTER FIELD cantidad
IF arrmedida[idx].espesor1 = 0 THEN
LET arrmedida[idx].medida1 = arrmedida[idx].ancho1 * arrmedida[idx].largo1
END IF
IF arrmedida[idx].espesor1 <> 0 THEN
LET arrmedida[idx].medida1 = arrmedida[idx].ancho1 * arrmedida[idx].largo1 *
arrmedida[idx].espesor1
END IF
IF arrmedida[idx].espesor2 = 0 THEN
LET arrmedida[idx].medida2 = arrmedida[idx].ancho2 * arrmedida[idx].largo2
END IF
IF arrmedida[idx].espesor2 <> 0 THEN
LET arrmedida[idx].medida2 = arrmedida[idx].ancho2 * arrmedida[idx].largo2 *
arrmedida[idx].espesor2
END IF
DISPLAY arrmedida[idx].medida1 TO sdespiece[sidx].medida1
DISPLAY arrmedida[idx].medida2 TO sdespiece[sidx].medida2
AFTER INPUT
IF int_flag THEN
LET numero_msg = 2
CALL msg(numero_msg)
EXIT INPUT
END IF
END INPUT
IF int_flag THEN
CLOSE WINDOW prfmwd012
RETURN
END IF
LET total_medida = 0
IF modifica = "N" THEN
FOR idx =1 TO arr_count()
IF arrmedida[idx].cantidad IS NOT NULL THEN
INSERT INTO cttb00012 VALUES (tmpnumero,datos_c.fecha,arr_costos[idx].codigo_bloque,
arr_costos[idx].cod_prod,arrmedida[idx].ancho1,arrmedida[idx].largo1,
arrmedida[idx].espesor1,arrmedida[idx].medida1,
arrmedida[idx].largo2,arrmedida[idx].ancho2,arrmedida[idx].espesor2,
arrmedida[idx].medida2,arrmedida[idx].cantidad)
LET total_medida = arrmedida[idx].medida1 + total_medida
END IF
END FOR
ELSE
DELETE FROM cttb00012
WHERE documento = datos_c.num_doc AND cod_prod = arr_costos[curr].cod_prod and
codigo_bloque = arr_costos[curr].codigo_bloque
FOR idx =1 TO arr_count()
IF arrmedida[idx].cantidad IS NOT NULL THEN
INSERT INTO cttb00012 VALUES (datos_c.num_doc,datos_c.fecha,arr_costos[curr].codigo_bloque,
arr_costos[curr].cod_prod,arrmedida[idx].ancho1,arrmedida[idx].largo1,
arrmedida[idx].espesor1,arrmedida[idx].medida1,
arrmedida[idx].largo2,arrmedida[idx].ancho2,arrmedida[idx].espesor2,
arrmedida[idx].medida2,arrmedida[idx].cantidad)
LET total_medida = arrmedida[idx].medida1 + total_medida
END IF
END FOR
END IF
LET arr_costos[curr].cantidad = total_medida
CLOSE WINDOW prfmwd012
END FUNCTION
FUNCTION departamentos_receptores()
DEFINE pdepartamento SMALLINT,pdescripcion CHAR(30),
kdepto ui.ComboBox
LET kdepto = ui.ComboBox.forName("formonly.depto_receptor")
CALL kdepto.clear()
DECLARE busca_dpto1 CURSOR FOR
SELECT a.departamento,a.nom_dpto FROM adtb00001 a
WHERE a.status_t IS NULL AND a.departamento > 6000
ORDER BY a.nom_dpto
FOREACH busca_dpto1 INTO pdepartamento,pdescripcion
CALL kdepto.additem(pdepartamento,pdescripcion)
END FOREACH
END FUNCTION
FUNCTION departamentos_produccion()
DEFINE pdepartamento SMALLINT,pdescripcion CHAR(30),
kdepto ui.ComboBox
LET kdepto = ui.ComboBox.forName("formonly.departamento")
CALL kdepto.clear()
DECLARE busca_dpto2 CURSOR FOR
SELECT a.departamento,a.nom_dpto FROM adtb00001 a
WHERE a.status_t IS NULL AND a.tipo_departamento = 'PRODUCCION'
ORDER BY a.nom_dpto
FOREACH busca_dpto2 INTO pdepartamento,pdescripcion
CALL kdepto.additem(pdepartamento,pdescripcion)
END FOREACH
END FUNCTION
FUNCTION movimientos()
DEFINE pmovimientos SMALLINT,pdescripmov CHAR(30),
kcodmov ui.ComboBox
LET kcodmov = ui.ComboBox.forName("formonly.cod_mov")
CALL kcodmov.clear()
DECLARE busca_mov CURSOR FOR
SELECT a.cod_mov, CONCAT('(',a.cod_mov,') ',a.descrip_mov) FROM cttb00005 a
WHERE a.status_t IS NULL
ORDER BY a.descrip_mov
FOREACH busca_mov INTO pmovimientos,pdescripmov
CALL kcodmov.additem(pmovimientos,pdescripmov)
END FOREACH
END FUNCTION
# ---------------------------------------------------------------------------
# InsertarTabla14() REMOVIDA (2026-08-03).
# Intentaba escribir movimientos en cttb00014, pero esa tabla es el inventario
# mensual de semielaborados (cod_prod, ano, mes, cantidad) que mantiene
# ctprmt012 y leen los reportes de costo. No tiene columnas de movimiento
# (departamento, num_doc, cod_mov, depto_receptor, ref) -> causaba SQL -207.
# El libro mayor de movimientos es cttb00003, que ya registra todo el flujo.
# ---------------------------------------------------------------------------