{ FUNCION : GeneraEntradaDiario OBJETIVO : REcibir las informaciones desde otros modulos con la finalidad de adicionar los registros necesarios en el mayor de contabilidad relacionado al documento fuente DESARROLLADO : JUAN SOTO FECHA : 7, Noviembre 2025 } FUNCTION GeneraEntradaDiario( usuario, tipoPrograma, idEntrada, cuenta_no_banco, xfecha, valor_bruto, monto_desc, impuesto, tipoCliente, secCliente, moneda, tasa, xnumeroDoc, comision) DEFINE tipoPrograma, usuario, xventas VARCHAR(50), cuenta_no_banco, xcuenta_no_ingreso, xcuenta_no_prima_ingresos, xcuenta_no_ventas, xcuenta_no_prima, xcuenta_comision, xcuenta_no_itbis VARCHAR(8), idEntrada, tipoCliente, secCliente, xdepartamento, xnumeroDoc, idrow, deptoAct INT, xfecha DATE, moneda SMALLINT, valor_bruto, monto_desc, impuesto, tasa, debito, comision, dolares, diferencia DEC(18, 2), tieneDepto_ing, tieneDepto_prima, tieneDepto_ventas, tieneDepto_comision CHAR(1), entra VARCHAR(25), detalle1 VARCHAR(100) DEFINE registroEntrada DYNAMIC ARRAY OF RECORD referenciaEntrada VARCHAR(25), fecha DATE, tipo CHAR(1), cuenta_no VARCHAR(8), departamento INT, detalle VARCHAR(100), debito, credito DEC(12, 2) END RECORD, qcuentas STRING LET idrow = 1 LET deptoAct = NULL DISPLAY "comision entr ", comision CALL registroEntrada.clear() #QUERYS GENERALES PARA TODOS LOS AUXILIARES LET qcuentas = " SELECT DISTINCT a.cuenta_no_ventas,a.cuenta_no_ingresos,a.cuenta_no_prima,a.cuenta_no_prima_ingresos,a.cuenta_comision ,a.departamento,b.descripcion FROM marmotech.dbo.vetb00060 a INNER JOIN marmotech.dbo.vetb00061 b ON b.ventas = a.ventas WHERE a.tipo_cliente = ? " PREPARE scuentas FROM qcuentas EXECUTE scuentas INTO xcuenta_no_ventas, xcuenta_no_ingreso, xcuenta_no_prima, xcuenta_no_prima_ingresos, xcuenta_comision, xdepartamento, xventas USING tipoCliente LET qcuentas = " SELECT ISNULL(a.depto,'N') FROM marmotech.dbo.cgtb00001 a WHERE a.cuenta_no = ?" PREPARE sdepto FROM qcuentas EXECUTE sdepto INTO tieneDepto_ing USING xcuenta_no_ingreso LET qcuentas = " SELECT ISNULL(a.depto,'N') FROM marmotech.dbo.cgtb00001 a WHERE a.cuenta_no = ?" PREPARE cprima FROM qcuentas EXECUTE cprima INTO tieneDepto_prima USING xcuenta_no_prima_ingresos LET qcuentas = " SELECT ISNULL(a.depto,'N') FROM marmotech.dbo.cgtb00001 a WHERE a.cuenta_no = ?" PREPARE sventas FROM qcuentas EXECUTE sventas INTO tieneDepto_ventas USING xcuenta_no_ventas LET qcuentas = " SELECT ISNULL(a.depto,'N') FROM marmotech.dbo.cgtb00001 a WHERE a.cuenta_no = ?" PREPARE sventas FROM qcuentas EXECUTE sventas INTO tieneDepto_comision USING xcuenta_comision #------------------------------------------------------------------------ # RECIBOS INGRESOS #------------------------------------------------------------------------ IF tipoPrograma = 'RECIBOS INGRESOS' THEN LET qcuentas = "SELECT a.tasa-1 FROM marmotech.dbo.cgtb00084 a WHERE a.ano = YEAR(?) AND a.mes = MONTH(?) AND a.tipo_cliente = ?" PREPARE stasa FROM qcuentas EXECUTE stasa INTO tasa USING xfecha, xfecha, tipoCliente IF STATUS = NOTFOUND THEN RETURN FALSE, registroEntrada END IF LET deptoAct = xdepartamento IF tieneDepto_ing = 'N' THEN LET deptoAct = NULL END IF LET detalle1 = 'RECIBO INGRESO ', xventas CLIPPED, " ", xnumeroDoc USING "<<<<<<<<" CALL controlNumericoED(idEntrada, xfecha, usuario) RETURNING entra LET debito = (valor_bruto - monto_desc) LET registroEntrada[1].cuenta_no = xcuenta_no_ingreso CLIPPED LET registroEntrada[1].fecha = xfecha LET registroEntrada[1].referenciaEntrada = entra LET registroEntrada[1].tipo = '1' LET registroEntrada[1].departamento = deptoAct LET registroEntrada[1].detalle = detalle1 CLIPPED LET registroEntrada[1].debito = debito LET registroEntrada[1].credito = 0 IF xcuenta_no_prima_ingresos IS NOT NULL THEN LET deptoAct = xdepartamento IF tieneDepto_prima = 'N' THEN LET deptoAct = NULL END IF LET registroEntrada[2].cuenta_no = xcuenta_no_prima_ingresos CLIPPED LET registroEntrada[2].referenciaEntrada = entra LET registroEntrada[2].fecha = xfecha LET registroEntrada[2].tipo = '1' LET registroEntrada[2].departamento = deptoAct LET registroEntrada[2].detalle = detalle1 CLIPPED LET registroEntrada[2].debito = debito * tasa LET registroEntrada[2].credito = 0 END IF LET deptoAct = xdepartamento IF tieneDepto_ventas = 'N' THEN LET deptoAct = NULL END IF LET registroEntrada[3].cuenta_no = xcuenta_no_ventas CLIPPED LET registroEntrada[3].referenciaEntrada = entra LET registroEntrada[3].fecha = xfecha LET registroEntrada[3].tipo = '1' LET registroEntrada[3].departamento = deptoAct LET registroEntrada[3].detalle = detalle1 CLIPPED LET registroEntrada[3].debito = 0 LET registroEntrada[3].credito = debito IF xcuenta_no_prima IS NOT NULL THEN LET deptoAct = xdepartamento IF tieneDepto_prima = 'N' THEN LET deptoAct = NULL END IF LET registroEntrada[4].cuenta_no = xcuenta_no_prima CLIPPED LET registroEntrada[4].referenciaEntrada = entra LET registroEntrada[4].fecha = xfecha LET registroEntrada[4].tipo = '1' LET registroEntrada[4].departamento = deptoAct LET registroEntrada[4].detalle = detalle1 CLIPPED LET registroEntrada[4].debito = 0 LET registroEntrada[4].credito = debito * tasa END IF RETURN TRUE, registroEntrada END IF #------------------------------------------------------------------------ # DEPOSITOS #------------------------------------------------------------------------ IF tipoPrograma = 'DEPOSITOS' THEN LET idrow = 1 LET qcuentas = "SELECT avg(a.tasa) FROM marmotech.dbo.cgtb00084 a WHERE a.ano = YEAR(?) AND a.mes = MONTH(?) AND a.ventas = ?" PREPARE stasa1 FROM qcuentas EXECUTE stasa1 INTO tasa USING xfecha, xfecha, moneda IF STATUS = NOTFOUND THEN RETURN FALSE, registroEntrada END IF LET qcuentas = " SELECT DISTINCT a.cuenta_no_ventas,a.cuenta_no_ingresos,a.cuenta_no_prima,a.cuenta_no_prima_ingresos,a.cuenta_comision ,a.departamento,b.descripcion,a.cuenta_no_itbis,a.cuenta_comision FROM marmotech.dbo.vetb00060 a INNER JOIN marmotech.dbo.vetb00061 b ON b.ventas = a.ventas WHERE a.ventas = ? " PREPARE scuentasdp FROM qcuentas EXECUTE scuentasdp INTO xcuenta_no_ventas, xcuenta_no_ingreso, xcuenta_no_prima, xcuenta_no_prima_ingresos, xcuenta_comision, xdepartamento, xventas, xcuenta_no_itbis, xcuenta_comision USING moneda LET deptoAct = NULL LET detalle1 = 'DEPOSITOS ', xventas CLIPPED, " ", xnumeroDoc USING "<<<<<<<<" LET usuario = NULL CALL controlNumericoED(idEntrada, xfecha, usuario) RETURNING entra LET debito = valor_bruto IF comision > 0 THEN LET impuesto = (valor_bruto / 1.18) * .02 LET debito = valor_bruto - comision - impuesto END IF DISPLAY "en DEPOSITO: ", detalle1, " debito ", debito, " comision ", comision, " valor Bruto :", valor_bruto, " tasa ", tasa IF tasa = 0 THEN LET tasa = 1 END IF LET registroEntrada[idrow].cuenta_no = cuenta_no_banco CLIPPED LET registroEntrada[idrow].fecha = xfecha LET registroEntrada[idrow].referenciaEntrada = entra LET registroEntrada[idrow].tipo = '1' LET registroEntrada[idrow].departamento = deptoAct LET registroEntrada[idrow].detalle = detalle1 CLIPPED LET registroEntrada[idrow].debito = debito LET registroEntrada[idrow].credito = 0 IF comision > 0 THEN LET idrow = idrow + 1 LET registroEntrada[idrow].cuenta_no = xcuenta_no_itbis CLIPPED LET registroEntrada[idrow].referenciaEntrada = entra LET registroEntrada[idrow].fecha = xfecha LET registroEntrada[idrow].tipo = '1' LET registroEntrada[idrow].departamento = deptoAct LET registroEntrada[idrow].detalle = detalle1 CLIPPED LET registroEntrada[idrow].debito = impuesto LET registroEntrada[idrow].credito = 0 LET idrow = idrow + 1 LET registroEntrada[idrow].cuenta_no = xcuenta_comision CLIPPED LET registroEntrada[idrow].referenciaEntrada = entra LET registroEntrada[idrow].fecha = xfecha LET registroEntrada[idrow].tipo = '1' LET registroEntrada[idrow].departamento = deptoAct LET registroEntrada[idrow].detalle = detalle1 CLIPPED LET registroEntrada[idrow].debito = comision LET registroEntrada[idrow].credito = 0 LET deptoAct = xdepartamento # El credito completo al ingreso solo aplica en depositos locales. # En dolares (moneda > 1) el credito lo arma el bloque de mas abajo (Caja US$ + Prima). IF moneda = 1 THEN LET idrow = idrow + 1 LET registroEntrada[idrow].cuenta_no = xcuenta_no_ingreso CLIPPED LET registroEntrada[idrow].referenciaEntrada = entra LET registroEntrada[idrow].fecha = xfecha LET registroEntrada[idrow].tipo = '1' LET registroEntrada[idrow].departamento = deptoAct LET registroEntrada[idrow].detalle = detalle1 CLIPPED LET registroEntrada[idrow].debito = 0 LET registroEntrada[idrow].credito = valor_bruto END IF END IF IF moneda = 1 AND comision = 0 THEN LET idrow = idrow + 1 LET registroEntrada[idrow].cuenta_no = xcuenta_no_ingreso CLIPPED LET registroEntrada[idrow].referenciaEntrada = entra LET registroEntrada[idrow].fecha = xfecha LET registroEntrada[idrow].tipo = '1' LET registroEntrada[idrow].departamento = deptoAct LET registroEntrada[idrow].detalle = detalle1 CLIPPED LET registroEntrada[idrow].debito = 0 LET registroEntrada[idrow].credito = valor_bruto END IF IF moneda > 1 THEN # DOLARES PAGADOS AL DEPOSITO (guardados en las columnas monto_* de tetb00001) LET dolares = 0 LET qcuentas = "SELECT ISNULL(a.monto_efectivo,0)+ISNULL(a.monto_ck,0)+ISNULL(a.monto_link,0)+ISNULL(a.monto_tarjeta,0) FROM marmotech.dbo.tetb00001 a WHERE a.num_doc = ?" PREPARE sdolares FROM qcuentas EXECUTE sdolares INTO dolares USING xnumeroDoc IF dolares IS NULL THEN LET dolares = 0 END IF LET diferencia = valor_bruto - dolares # 1100-01 CAJA US$ = dolares pagados LET idrow = idrow + 1 LET registroEntrada[idrow].cuenta_no = xcuenta_no_ingreso CLIPPED LET registroEntrada[idrow].referenciaEntrada = entra LET registroEntrada[idrow].fecha = xfecha LET registroEntrada[idrow].tipo = '1' LET registroEntrada[idrow].departamento = deptoAct LET registroEntrada[idrow].detalle = detalle1 CLIPPED LET registroEntrada[idrow].debito = 0 LET registroEntrada[idrow].credito = dolares # 1100-02 PRIMA = valor_bruto - dolares (solo si hubo conversion) IF diferencia <> 0 THEN LET idrow = idrow + 1 LET registroEntrada[idrow].cuenta_no = xcuenta_no_prima_ingresos CLIPPED LET registroEntrada[idrow].referenciaEntrada = entra LET registroEntrada[idrow].fecha = xfecha LET registroEntrada[idrow].tipo = '1' LET registroEntrada[idrow].departamento = deptoAct LET registroEntrada[idrow].detalle = detalle1 CLIPPED LET registroEntrada[idrow].debito = 0 LET registroEntrada[idrow].credito = diferencia END IF END IF RETURN TRUE, registroEntrada END IF #------------------------------------------------------------------------ # VENTAS #------------------------------------------------------------------------ IF tipoPrograma = 'VENTAS' THEN END IF #------------------------------------------------------------------------ # INVENTARIO PRODUCTOS TERMINADOS # Ver GeneraEntradaInventario('P',...) mas abajo: la entrada de # inventario necesita las N lineas del documento (cod_mov/bodega), # que no caben en esta firma de valor unico. #------------------------------------------------------------------------ IF tipoPrograma = 'INV PRODUCTOS' THEN END IF #------------------------------------------------------------------------ # INVENTARIO REPUESTOS -> ver GeneraEntradaInventario('R',...) #------------------------------------------------------------------------ IF tipoPrograma = 'INV REPUESTOS' THEN END IF #------------------------------------------------------------------------ # INVENTARIOS MATERIA PRIMA #------------------------------------------------------------------------ IF tipoPrograma = 'INV MAT PRIMA' THEN END IF #------------------------------------------------------------------------ # ACTIVOS FIJS #------------------------------------------------------------------------ IF tipoPrograma = 'ACTIVOS' THEN END IF END FUNCTION { FUNCION : GeneraEntradaInventario OBJETIVO : Armar las lineas debito/credito del asiento al mayor (cgtb00004) para UN documento de inventario (productos terminados o repuestos), valorizado con costoLiquidacion() y con las cuentas contables definidas por codigo de movimiento, replicando el criterio de EDPRRP080 (terminados) y EDPRRP118 (repuestos). PARAMETROS : usuario - usuario que crea el asiento (NOT NULL = consume secuencia) tipoInv - 'P' productos terminados / 'R' repuestos pnum_doc - num_doc del documento de inventario pcod_mov - codigo de movimiento pbodega - bodega del documento pfecha - fecha del documento RETORNA : generaE BOOLEAN (TRUE si armo al menos una linea), registroEntrada (mismo shape que GeneraEntradaDiario). NOTA : Solo toma las lineas con referenciaentrada IS NULL (idempotente: si se llama dos veces no duplica). El llamador inserta el arreglo en cgtb00004 (agregando numero_documento/cod_mov/bodega/ sistema_auxiliar), y sella .referenciaentrada = ED.xxx. DEBITO/CREDITO (por signo de cantidad_2, igual que los batch): entrada (cantidad >= 0): inventario DEBITO / contrapartida CREDITO salida (cantidad < 0): inventario CREDITO / contrapartida DEBITO CUENTAS : terminados -> iptb00005.cuenta_1/2/3 (material/labor/gasto por cod_mov) contra iptb00022.cuenta_no (por cod_cia). repuestos -> irtb00002.cuenta (por articulo, como EDPRRP118) contra iptb00022.cuenta_no (por cod_n). COSTEO : produccion (es_produccion=1) -> desglose material/labor/gasto de iptb00004. Compra/venta y repuestos -> costo unico costoLiquidacion() aplicado a la cuenta material (cuenta_1). } FUNCTION GeneraEntradaInventario(usuario, tipoInv, pnum_doc, pcod_mov, pbodega, pfecha) DEFINE usuario STRING, tipoInv CHAR(1), pnum_doc, pcod_mov, pbodega INT, pfecha DATE, entra VARCHAR(25), idrow INT, qsql STRING, es_prod SMALLINT, status_mov CHAR(1), cta_mat, cta_lab, cta_gas, cta_inv VARCHAR(14), cta_mat_imp, cta_mat_uso VARCHAR(14), dep_mat, dep_lab, dep_gas, dep_inv CHAR(1), usarCuentaItem SMALLINT, matStd, labStd, gasStd DEC(18, 4), unit, v_mat, v_lab, v_gas, v_total DEC(18, 4), detalle1 VARCHAR(100), depto_cia, dep_uso INT, dep_flag CHAR(1), nc, k, j, m, encontrado INT #--- Candidatos de la linea y acumulador por (cuenta, departamento). #--- Convencion de 'valor': POSITIVO = DEBITO, NEGATIVO = CREDITO. DEFINE cand DYNAMIC ARRAY OF RECORD cuenta_no VARCHAR(14), valor DEC(18, 4) END RECORD, acum DYNAMIC ARRAY OF RECORD cuenta_no VARCHAR(14), departamento INT, valor DEC(18, 4), detalle VARCHAR(100) END RECORD DEFINE lin RECORD cod_n, cod_grupo, cod_tipo, cod_sec INT, cantidad DEC(18, 4), departamento INT, cod_cia INT, descrip VARCHAR(180) END RECORD DEFINE lineas DYNAMIC ARRAY OF RECORD cod_n, cod_grupo, cod_tipo, cod_sec INT, cantidad DEC(18, 4), departamento INT, cod_cia INT, descrip VARCHAR(180) END RECORD, i INT DEFINE registroEntrada DYNAMIC ARRAY OF RECORD referenciaEntrada VARCHAR(25), fecha DATE, tipo CHAR(1), cuenta_no VARCHAR(8), departamento INT, detalle VARCHAR(100), debito, credito DEC(12, 2) END RECORD CALL registroEntrada.clear() LET idrow = 0 #--- Secuencia de la entrada al diario (id 25 = entrada automatica inventario) CALL controlNumericoED(25, pfecha, usuario) RETURNING entra #--- Cuentas contables IF tipoInv = 'P' THEN #--- Terminados: cuentas por codigo de movimiento (iptb00005), como EDPRRP080 LET qsql = "SELECT ISNULL(status_mov,'E'), cuenta_1, cuenta_2, cuenta_3, cuenta_imp_material FROM marmotech.dbo.iptb00005 WHERE cod_mov = ?" PREPARE s_cta FROM qsql EXECUTE s_cta INTO status_mov, cta_mat, cta_lab, cta_gas, cta_mat_imp USING pcod_mov FREE s_cta LET usarCuentaItem = 0 ELSE #--- Repuestos: la cuenta se toma del articulo (irtb00002.cuenta), como EDPRRP118. #--- Compras locales confirmadas; internacionales pendientes de validar con #--- finanzas (se asume el mismo criterio de EDPRRP118). LET cta_mat = NULL LET cta_lab = NULL LET cta_gas = NULL LET cta_mat_imp = NULL LET usarCuentaItem = 1 END IF #--- Preparados reutilizables dentro del ciclo LET qsql = "SELECT ISNULL(a.depto,'N') FROM marmotech.dbo.cgtb00001 a WHERE a.cuenta_no = ?" PREPARE s_dep FROM qsql LET qsql = "SELECT a.cuenta_no, a.departamento FROM marmotech.dbo.iptb00022 a WHERE a.cod_cia = ?" PREPARE s_inv FROM qsql IF tipoInv = 'P' THEN LET qsql = "SELECT TOP 1 ISNULL(a.es_produccion,0) FROM marmotech.dbo.iptb00002 a WHERE a.cod_n=? AND a.cod_grupo=? AND a.cod_tipo=? AND a.cod_sec=?" PREPARE s_esp FROM qsql LET qsql = "SELECT ISNULL(AVG(ISNULL(a.material,0)),0), ISNULL(AVG(ISNULL(a.labor,0)),0), ISNULL(AVG(ISNULL(a.gastos,0)),0) FROM marmotech.dbo.iptb00004 a WHERE a.cod_n=? AND a.cod_grupo=? AND a.cod_tipo=? AND a.cod_sec=? AND a.ano=YEAR(?) AND a.mes_fin=12 AND a.status_t IS NULL" PREPARE s_std FROM qsql ELSE LET qsql = "SELECT a.cuenta FROM marmotech.dbo.irtb00002 a WHERE a.cod_n=? AND a.cod_grupo=? AND a.cod_tipo=? AND a.cod_sec=?" PREPARE s_itemcta FROM qsql END IF #--- Lectura de las lineas del documento (solo las no asentadas) IF tipoInv = 'P' THEN LET qsql = "SELECT c.cod_n,c.cod_grupo,c.cod_tipo,c.cod_sec,SUM(c.cantidad_2), ISNULL(c.departamento,0), MAX(e.cod_cia), MAX(e.descrip_esp) FROM marmotech.dbo.iptb00006 c INNER JOIN marmotech.dbo.iptb00002 e ON c.cod_n=e.cod_n AND c.cod_grupo=e.cod_grupo AND c.cod_tipo=e.cod_tipo AND c.cod_sec=e.cod_sec WHERE c.num_doc=? AND c.cod_mov=? AND c.bodega=? AND c.status_t IS NULL AND c.referenciaentrada IS NULL GROUP BY c.cod_n,c.cod_grupo,c.cod_tipo,c.cod_sec,c.departamento HAVING SUM(c.cantidad_2) <> 0" ELSE LET qsql = "SELECT b.cod_n,b.cod_grupo,b.cod_tipo,b.cod_sec,SUM(b.cantidad_2), ISNULL(b.sec_a,0), b.cod_n, MAX(a.descrip_esp) FROM marmotech.dbo.irtb00006 b INNER JOIN marmotech.dbo.irtb00002 a ON b.cod_n=a.cod_n AND b.cod_grupo=a.cod_grupo AND b.cod_tipo=a.cod_tipo AND b.cod_sec=a.cod_sec WHERE b.num_doc=? AND b.cod_mov=? AND b.bodega=? AND b.status_t IS NULL AND b.referenciaentrada IS NULL GROUP BY b.cod_n,b.cod_grupo,b.cod_tipo,b.cod_sec,b.sec_a,b.cod_n HAVING SUM(b.cantidad_2) <> 0" END IF PREPARE s_lin FROM qsql DECLARE c_lin CURSOR FOR s_lin #--- Cargar las lineas a un arreglo ANTES de procesar, para no mantener el #--- cursor abierto mientras se hacen consultas anidadas (evita "connection busy") CALL lineas.clear() LET i = 0 FOREACH c_lin USING pnum_doc, pcod_mov, pbodega INTO lin.* LET i = i + 1 LET lineas[i].* = lin.* END FOREACH FREE c_lin FOR i = 1 TO lineas.getLength() LET lin.* = lineas[i].* #--- Valuacion segun tipo de producto LET matStd = 0 LET labStd = 0 LET gasStd = 0 LET es_prod = 0 LET unit = 0 IF tipoInv = 'P' THEN EXECUTE s_esp INTO es_prod USING lin.cod_n, lin.cod_grupo, lin.cod_tipo, lin.cod_sec IF es_prod IS NULL THEN LET es_prod = 0 END IF END IF IF tipoInv = 'P' AND es_prod = 1 THEN #--- Produccion: desglose material/labor/gasto del estandard EXECUTE s_std INTO matStd, labStd, gasStd USING lin.cod_n, lin.cod_grupo, lin.cod_tipo, lin.cod_sec, pfecha LET v_mat = matStd * lin.cantidad LET v_lab = labStd * lin.cantidad LET v_gas = gasStd * lin.cantidad ELSE #--- Compra/venta y repuestos: costo unico a la cuenta material LET unit = costoLiquidacion( lin.cod_n, lin.cod_grupo, lin.cod_tipo, lin.cod_sec, pfecha, tipoInv) LET v_mat = unit * lin.cantidad LET v_lab = 0 LET v_gas = 0 END IF LET v_total = v_mat + v_lab + v_gas IF v_total = 0 THEN CONTINUE FOR END IF #--- Cuenta del articulo para repuestos sin cuenta por movimiento IF usarCuentaItem = 1 THEN LET cta_mat = NULL EXECUTE s_itemcta INTO cta_mat USING lin.cod_n, lin.cod_grupo, lin.cod_tipo, lin.cod_sec END IF #--- Cuenta de inventario (contrapartida) y DEPARTAMENTO, por cod_cia. #--- El departamento contable del item sale de iptb00022 segun el cod_cia #--- que tenga en iptb00002; se aplica a TODA cuenta marcada depto='S' #--- en cgtb00001. LET cta_inv = NULL LET depto_cia = NULL EXECUTE s_inv INTO cta_inv, depto_cia USING lin.cod_cia LET detalle1 = 'INV ', tipoInv, ' DOC ', pnum_doc USING "<<<<<<<<", ' MOV ', pcod_mov USING "<<<<", ' ', lin.descrip CLIPPED IF LENGTH(detalle1) > 100 THEN LET detalle1 = detalle1[1, 100] END IF #--- Candidatos de esta linea. Convencion: valor POSITIVO = DEBITO, #--- NEGATIVO = CREDITO. Las contrapartidas aportan el valor invertido y #--- el inventario el total, por lo que la entrada CUADRA POR CONSTRUCCION. CALL cand.clear() LET nc = 0 #--- ORIGEN DEL ARTICULO (iptb00022 via iptb00002.cod_cia): #--- cod_cia 2 = PTOS. MAT.IMPORTADOS y 3 = PRODUCTOS IMPORTADOS llevan la #--- cuenta de material IMPORTADO (iptb00005.cuenta_imp_material) en lugar #--- de la cuenta_1 local. Mismo criterio que EDPRRP080. Labor y gasto NO #--- se cambian: siguen saliendo de cuenta_2 / cuenta_3. LET cta_mat_uso = cta_mat IF tipoInv = 'P' THEN IF lin.cod_cia = 2 OR lin.cod_cia = 3 THEN IF cta_mat_imp IS NOT NULL THEN LET cta_mat_uso = cta_mat_imp END IF END IF END IF IF cta_mat_uso IS NOT NULL AND v_mat <> 0 THEN LET nc = nc + 1 LET cand[nc].cuenta_no = cta_mat_uso CLIPPED LET cand[nc].valor = (0 - v_mat) END IF IF cta_lab IS NOT NULL AND v_lab <> 0 THEN LET nc = nc + 1 LET cand[nc].cuenta_no = cta_lab CLIPPED LET cand[nc].valor = (0 - v_lab) END IF IF cta_gas IS NOT NULL AND v_gas <> 0 THEN LET nc = nc + 1 LET cand[nc].cuenta_no = cta_gas CLIPPED LET cand[nc].valor = (0 - v_gas) END IF IF cta_inv IS NOT NULL AND v_total <> 0 THEN LET nc = nc + 1 LET cand[nc].cuenta_no = cta_inv CLIPPED LET cand[nc].valor = v_total END IF #--- Acumular por (cuenta, departamento): los items con el mismo cod_cia #--- se suman en una sola linea; si hay items con cod_cia distinto, la #--- misma cuenta se repite en la entrada con otro departamento y valor. FOR k = 1 TO nc LET dep_flag = 'N' EXECUTE s_dep INTO dep_flag USING cand[k].cuenta_no IF dep_flag = 'S' THEN LET dep_uso = depto_cia ELSE LET dep_uso = NULL END IF LET encontrado = 0 FOR j = 1 TO acum.getLength() IF acum[j].cuenta_no = cand[k].cuenta_no THEN IF (acum[j].departamento IS NULL AND dep_uso IS NULL) OR (acum[j].departamento = dep_uso) THEN LET acum[j].valor = acum[j].valor + cand[k].valor LET encontrado = 1 EXIT FOR END IF END IF END FOR IF encontrado = 0 THEN LET m = acum.getLength() + 1 LET acum[m].cuenta_no = cand[k].cuenta_no LET acum[m].departamento = dep_uso LET acum[m].valor = cand[k].valor LET acum[m].detalle = detalle1 CLIPPED END IF END FOR END FOR #--- Emitir UNA linea por cada (cuenta, departamento) acumulado FOR j = 1 TO acum.getLength() IF acum[j].valor = 0 THEN CONTINUE FOR END IF LET idrow = idrow + 1 LET registroEntrada[idrow].referenciaEntrada = entra LET registroEntrada[idrow].fecha = pfecha LET registroEntrada[idrow].tipo = '1' LET registroEntrada[idrow].cuenta_no = acum[j].cuenta_no LET registroEntrada[idrow].departamento = acum[j].departamento LET registroEntrada[idrow].detalle = acum[j].detalle IF acum[j].valor > 0 THEN LET registroEntrada[idrow].debito = acum[j].valor LET registroEntrada[idrow].credito = 0 ELSE LET registroEntrada[idrow].debito = 0 LET registroEntrada[idrow].credito = (0 - acum[j].valor) END IF END FOR FREE s_lin FREE s_dep FREE s_inv IF tipoInv = 'P' THEN FREE s_esp FREE s_std ELSE FREE s_itemcta END IF IF idrow = 0 THEN RETURN FALSE, registroEntrada END IF RETURN TRUE, registroEntrada END FUNCTION { FUNCION : registraEntradaInventario OBJETIVO : Registrar en el mayor (cgtb00004) el asiento de UN documento de inventario y sellar la referencia ED en la tabla de movimientos. IMPORTANTE : Se ejecuta DENTRO de la transaccion del programa llamador. NO hace BEGIN WORK ni COMMIT WORK. Si retorna FALSE el llamador debe hacer ROLLBACK WORK. PARAMETROS : usuario, tipoInv ('P'/'R'), num_doc, cod_mov, bodega, fecha RETORNA : ok BOOLEAN, entra VARCHAR(25) con la referencia ED generada (ok = TRUE y entra = NULL significa que no habia nada pendiente por asentar, lo cual no es un error). } FUNCTION registraEntradaInventario(usuario, tipoInv, pnum_doc, pcod_mov, pbodega, pfecha) DEFINE usuario STRING, tipoInv CHAR(1), pnum_doc, pcod_mov, pbodega INT, pfecha DATE, genera BOOLEAN, entra VARCHAR(25), sistema VARCHAR(2), tipodoc VARCHAR(10), tabla STRING, qsql STRING, idx INT, t_debito, t_credito DEC(18, 2) DEFINE registroEntrada DYNAMIC ARRAY OF RECORD referenciaEntrada VARCHAR(25), fecha DATE, tipo CHAR(1), cuenta_no VARCHAR(8), departamento INT, detalle VARCHAR(100), debito, credito DEC(12, 2) END RECORD LET genera = FALSE LET entra = NULL CALL GeneraEntradaInventario( usuario, tipoInv, pnum_doc, pcod_mov, pbodega, pfecha) RETURNING genera, registroEntrada #--- Sin lineas pendientes por asentar: no es error IF NOT genera THEN RETURN TRUE, entra END IF LET entra = registroEntrada[1].referenciaEntrada LET tipodoc = 'INV' #--- Guardian de cuadre (equivalente a verificaCuadre() de los batch). #--- Si falta una cuenta configurada (iptb00022 / iptb00005 / irtb00002) la #--- contrapartida no se genera y el asiento quedaria descuadrado: se aborta #--- para no ensuciar el mayor. LET t_debito = 0 LET t_credito = 0 FOR idx = 1 TO registroEntrada.getLength() IF registroEntrada[idx].cuenta_no IS NULL THEN CONTINUE FOR END IF LET t_debito = t_debito + registroEntrada[idx].debito LET t_credito = t_credito + registroEntrada[idx].credito END FOR IF t_debito <> t_credito THEN DISPLAY "ED FALLO: ASIENTO DESCUADRADO ref=", entra CLIPPED, " debito=", t_debito, " credito=", t_credito, " dif=", (t_debito - t_credito) DISPLAY "ED FALLO: detalle de las lineas armadas ->" FOR idx = 1 TO registroEntrada.getLength() DISPLAY " cta=", registroEntrada[idx].cuenta_no, " depto=", registroEntrada[idx].departamento, " debito=", registroEntrada[idx].debito, " credito=", registroEntrada[idx].credito END FOR DISPLAY "ED FALLO: revise que el cod_mov tenga cuenta_1/2/3 en ", "iptb00005/irtb00005 y que el cod_cia del item tenga cuenta_no en iptb00022" RETURN FALSE, entra END IF IF tipoInv = 'P' THEN LET sistema = 'IP' LET tabla = 'marmotech.dbo.iptb00006' ELSE LET sistema = 'IR' LET tabla = 'marmotech.dbo.irtb00006' END IF #--- Lineas del asiento al mayor LET qsql = "INSERT INTO marmotech.dbo.cgtb00004 (fecha,tipo,ref,cuenta_no,departamento,detalle_1,debito,credito, us_crea,fech_crea,numero_documento,cod_mov,bodega, sistema_auxiliar,tipo_documento) VALUES (?,?,?,?,?,?,?,?,?,GETDATE(),?,?,?,?,?)" PREPARE s_insed FROM qsql FOR idx = 1 TO registroEntrada.getLength() IF registroEntrada[idx].cuenta_no IS NULL THEN CONTINUE FOR END IF EXECUTE s_insed USING registroEntrada[idx].fecha, registroEntrada[idx].tipo, registroEntrada[idx].referenciaEntrada, registroEntrada[idx].cuenta_no, registroEntrada[idx].departamento, registroEntrada[idx].detalle, registroEntrada[idx].debito, registroEntrada[idx].credito, usuario, pnum_doc, pcod_mov, pbodega, sistema, tipodoc IF STATUS < 0 THEN DISPLAY "ED FALLO: INSERT cgtb00004 status=", STATUS, " ", SQLERRMESSAGE DISPLAY " ref=", entra CLIPPED, " cta=", registroEntrada[idx].cuenta_no, " depto=", registroEntrada[idx].departamento, " debito=", registroEntrada[idx].debito, " credito=", registroEntrada[idx].credito DISPLAY " doc=", pnum_doc, " mov=", pcod_mov, " bodega=", pbodega, " sistema=", sistema FREE s_insed RETURN FALSE, entra END IF END FOR FREE s_insed #--- Sellar la referencia en las lineas del documento LET qsql = "UPDATE ", tabla, " SET referenciaentrada = ? WHERE num_doc = ? AND cod_mov = ? AND bodega = ? AND status_t IS NULL AND referenciaentrada IS NULL" PREPARE s_updref FROM qsql EXECUTE s_updref USING entra, pnum_doc, pcod_mov, pbodega IF STATUS < 0 THEN DISPLAY "ED FALLO: UPDATE ", tabla, ".referenciaentrada status=", STATUS, " ", SQLERRMESSAGE DISPLAY " ref=", entra CLIPPED, " doc=", pnum_doc, " mov=", pcod_mov, " bodega=", pbodega FREE s_updref RETURN FALSE, entra END IF FREE s_updref RETURN TRUE, entra END FUNCTION { FUNCION : anulaEntradaPorRef OBJETIVO : Anular en el mayor (cgtb00004) las lineas de UNA entrada ED, marcandolas status_t = 'E'. Mismo criterio que usa ccprmt016 para anular los asientos de CxC. IMPORTANTE : Se ejecuta DENTRO de la transaccion del programa llamador. NO hace BEGIN WORK ni COMMIT WORK. RETORNA : TRUE si anulo o si no habia nada que anular; FALSE si fallo. NOTA : NO se borra la referencia de la tabla de movimientos: el movimiento queda con status_t='E' y conserva su referencia como rastro de cual asiento se anulo. } FUNCTION anulaEntradaPorRef(usuario, refED) DEFINE usuario STRING, refED VARCHAR(25), qsql STRING IF refED IS NULL THEN RETURN TRUE END IF IF LENGTH(refED) = 0 THEN RETURN TRUE END IF LET qsql = "UPDATE marmotech.dbo.cgtb00004 SET status_t = 'E', us_mod = ?, fech_mod = GETDATE() WHERE ref = ? AND status_t IS NULL" PREPARE s_anuED FROM qsql EXECUTE s_anuED USING usuario, refED IF STATUS < 0 THEN DISPLAY "ED FALLO: no se pudo anular el asiento ", refED CLIPPED, " status=", STATUS, " ", SQLERRMESSAGE FREE s_anuED RETURN FALSE END IF FREE s_anuED RETURN TRUE END FUNCTION { FUNCION : anulaEntradaInventario OBJETIVO : Anular el asiento al mayor de UN documento de inventario. Busca la referencia ED sellada en la tabla de movimientos y delega en anulaEntradaPorRef. PARAMETROS : usuario, tipoInv ('P'/'R'), num_doc, cod_mov, bodega (puede venir NULL: entonces no filtra por bodega, que es como anula irprmt066). IMPORTANTE : Dentro de la transaccion del llamador. Si retorna FALSE el llamador debe hacer ROLLBACK WORK. RETORNA : ok BOOLEAN, refED de la entrada anulada (NULL si no habia) } FUNCTION anulaEntradaInventario(usuario, tipoInv, pnum_doc, pcod_mov, pbodega) DEFINE usuario STRING, tipoInv CHAR(1), pnum_doc, pcod_mov, pbodega INT, refED VARCHAR(25), tabla STRING, qsql STRING, ok BOOLEAN IF tipoInv = 'P' THEN LET tabla = 'marmotech.dbo.iptb00006' ELSE LET tabla = 'marmotech.dbo.irtb00006' END IF #--- La referencia se busca SIN filtrar status_t: al momento de llamarnos #--- las lineas del movimiento ya pueden estar marcadas 'E'. LET refED = NULL LET qsql = "SELECT MAX(a.referenciaentrada) FROM ", tabla, " a WHERE a.num_doc = ? AND a.cod_mov = ? AND (a.bodega = ? OR ? IS NULL)" PREPARE s_refanu FROM qsql EXECUTE s_refanu INTO refED USING pnum_doc, pcod_mov, pbodega, pbodega FREE s_refanu IF refED IS NULL THEN #--- Documento sin asiento (anterior al automatico, o costo cero) RETURN TRUE, refED END IF LET ok = anulaEntradaPorRef(usuario, refED) RETURN ok, refED END FUNCTION