Untitled
unknown
sql
2 years ago
6.5 kB
4
Indexable
Never
-- disparador que actualiza el stock de un producto en la tabla PRODUCTO -- TRIGGER CREATE OR REPLACE TRIGGER tr_stock AFTER INSERT OR DELETE OR UPDATE OF cantidad ON detalle_boleta FOR EACH ROW DECLARE BEGIN IF INSERTING THEN UPDATE producto SET totalstock = totalstock - :NEW.cantidad WHERE codproducto = :NEW.codproducto; ELSIF DELETING THEN UPDATE producto SET totalstock = totalstock + :OLD.cantidad WHERE codproducto = :OLD.codproducto; ELSE UPDATE producto SET totalstock = totalstock - (:NEW.cantidad - :OLD.cantidad) WHERE codproducto = :NEW.codproducto; END IF; END; / -- consultamos el estado de los datos antes de las operaciones select * from detalle_boleta where numboleta = 1200; SELECT CODPRODUCTO, TOTALSTOCK FROM PRODUCTO WHERE CODPRODUCTO IN (10, 7, 20, 3); -- bloque anonimo con las transacciones BEGIN INSERT INTO DETALLE_BOLETA VALUES (1200, 10, (SELECT VUNITARIO FROM PRODUCTO WHERE CODPRODUCTO = 10), 4, (SELECT VUNITARIO FROM PRODUCTO WHERE CODPRODUCTO = 10) * 4); DELETE FROM DETALLE_BOLETA WHERE numboleta = 1200 AND CODPRODUCTO = 7; UPDATE DETALLE_BOLETA SET cantidad = 2, totallinea = 5000 where numboleta = 1200 and codproducto = 20; UPDATE DETALLE_BOLETA SET cantidad = 15, totallinea = 150000 where numboleta = 1200 and codproducto = 3; END; / -- consultamos el estado de los datos despu�s de las operaciones select * from detalle_boleta where numboleta = 1200; SELECT CODPRODUCTO, TOTALSTOCK FROM PRODUCTO WHERE CODPRODUCTO IN (10, 7, 20, 3); CREATE OR REPLACE PACKAGE pkg_admelect AS vp_ventas NUMBER(8) := 0; FUNCTION fn_ventas (p_run VARCHAR2, p_fec VARCHAR2) RETURN NUMBER; END pkg_admelect; / --PACKAGE CREATE OR REPLACE PACKAGE BODY pkg_admelect AS FUNCTION fn_ventas ( p_run VARCHAR2, p_fec VARCHAR2 ) RETURN NUMBER AS v_montoventas NUMBER(8); BEGIN SELECT SUM(db.totallinea) INTO v_montoventas FROM boleta bo JOIN detalle_boleta db ON bo.numboleta = db.numboleta WHERE TO_CHAR(bo.fecha, 'yyyymm') = p_fec AND bo.run_empleado = p_run; RETURN v_montoventas; END fn_ventas; END pkg_admelect; / EXEC dbms_output.put_line(pkg_admelect.fn_ventas('12456778-1', '202104')); --FUNCION CREATE OR REPLACE FUNCTION fn_asigantiguedad ( p_anti NUMBER, p_ventas NUMBER ) RETURN NUMBER AS v_pct NUMBER; v_sql VARCHAR2(300); v_msg VARCHAR2(300); BEGIN BEGIN EXECUTE IMMEDIATE 'SELECT porc_antiguedad / 100 FROM porc_antiguedad_empleado WHERE :1 BETWEEN annos_antiguedad_inf AND annos_antiguedad_sup' INTO v_pct USING p_anti; EXCEPTION WHEN OTHERS THEN v_msg := sqlerrm; v_pct := 0; INSERT INTO error_calc VALUES (seq_error.NEXTVAL, 'Error en la funcion FN_anti al recuperar el porcentaje asociado a ' || p_anti || ' anios de antiguedad ', v_msg); END; RETURN round(p_ventas * v_pct); END fn_asigantiguedad; / EXEC dbms_output.put_line(fn_asigantiguedad(3, 200000)); / --PROCEDIMIENTO CREATE OR REPLACE PROCEDURE sp_procesaremun ( p_fec VARCHAR2, p_colacion NUMBER, p_mov NUMBER, p_salud NUMBER ) AS -- cursor que recupera a todos los empleados CURSOR c_empleados IS SELECT e.*, pa.porcafp / 100 PCTAFP FROM empleado e JOIN prevision_afp pa on e.codafp = pa.codafp ORDER BY paterno, materno, nombre; -- variables escalares v_nom VARCHAR2(50); v_mov NUMBER(8) := 0; v_asiespecial number(8) := 0; v_anti number(3) := 0; v_pctcomis porcentaje_comision_venta.porc_comision%TYPE; v_comisventas number(8) := 0; v_imponible number(8) := 0; v_descuentos NUMBER(8) := 0; v_msg_oracle error_calc.descrip_error%TYPE; BEGIN -- TRUNCAMOS LAS TABLAS EXECUTE IMMEDIATE 'TRUNCATE TABLE detalle_pago_mensual'; EXECUTE IMMEDIATE 'TRUNCATE TABLE error_calc'; FOR r_emp IN c_empleados LOOP v_nom := r_emp.paterno || ' ' || r_emp.materno || ' ' || r_emp.nombre; v_anti := EXTRACT(YEAR FROM SYSDATE) - EXTRACT(YEAR FROM r_emp.fecha_contrato); -- calculamos el monto adicional de movilizacion dependiendo de la comuna v_mov := CASE WHEN r_emp.codcomuna IN(1,7) THEN ROUND(r_emp.sueldo_base * 0.10) WHEN r_emp.codcomuna IN(2,4,8) THEN ROUND(r_emp.sueldo_base * 0.12) WHEN r_emp.codcomuna IN(3,5,6) THEN ROUND(r_emp.sueldo_base * 0.14) ELSE ROUND(r_emp.sueldo_base * 0.16) END; v_mov := v_mov + p_mov; -- calculamos la asignacion especial usando la funcion almacenada y la funcion del package v_asiespecial := fn_asigantiguedad(v_anti, pkg_admelect.fn_ventas(r_emp.run_empleado, p_fec)); -- recuperamos porcentaje de comision dependiendo de las ventas -- y calculamos comision por ventas BEGIN SELECT porc_comision / 100 INTO v_pctcomis FROM porcentaje_comision_venta WHERE pkg_admelect.fn_ventas(r_emp.run_empleado, p_fec) BETWEEN venta_inf and venta_sup; v_comisventas := ROUND(pkg_admelect.fn_ventas(r_emp.run_empleado, p_fec) * v_pctcomis); EXCEPTION WHEN NO_DATA_FOUND THEN v_msg_oracle := SQLERRM; v_comisventas := 0; INSERT INTO error_calc VALUES (seq_error.NEXTVAL, 'Error al recuperar la comision por ventas', v_msg_oracle); END; -- calculamos el sueldo imponible v_imponible := r_emp.sueldo_base + p_colacion + v_mov + v_asiespecial + v_comisventas; -- calculamos los descuentos v_descuentos := ROUND(v_imponible * r_emp.pctafp) + ROUND(v_imponible * p_salud / 100); -- Guarda los resultados en la tabla INSERT INTO detalle_pago_mensual VALUES(SUBSTR(p_fec,-2),SUBSTR(p_fec,1,4),r_emp.run_empleado,v_nom,r_emp.sueldo_base,p_colacion,v_mov, v_asiespecial,v_comisventas,v_imponible,v_descuentos,(v_imponible - v_descuentos)); END LOOP; -- salvamos los datos COMMIT; END sp_procesaremun; / BEGIN sp_procesaremun('202104', 75000, 60000, 7); EXECUTE IMMEDIATE 'DROP SEQUENCE seq_error'; EXECUTE IMMEDIATE 'CREATE SEQUENCE seq_error'; END;