{ ----------------------------------------------------------------------------- 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" " Actualiza Registro 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. # ---------------------------------------------------------------------------