- Agrega columnas id_position e id_area a contracts - Rellena columnas con datos actuales del empleado - Modifica getcontracts, newcontract, updatecontract y reportemployeecontract - Rollback incluido
317 lines
10 KiB
PL/PgSQL
317 lines
10 KiB
PL/PgSQL
-- ============================================================
|
|
-- FIX: Historizar posicion y area en contratos
|
|
-- Fecha: 2026-06-09
|
|
-- Autor: Analisis automatico del sistema
|
|
-- ============================================================
|
|
-- PROBLEMA IDENTIFICADO:
|
|
-- La tabla contracts no guardaba la posicion ni el area del
|
|
-- empleado en el momento del contrato. Todos los reportes de
|
|
-- contratos obtenian estos datos desde la tabla employees,
|
|
-- por lo que al actualizar la posicion/area del empleado,
|
|
-- todos los contratos historicos mostraban la informacion
|
|
-- actual en lugar de la del momento del contrato.
|
|
--
|
|
-- SOLUCION APLICADA:
|
|
-- 1. Se agregan las columnas id_position e id_area a la
|
|
-- tabla contracts.
|
|
-- 2. Se rellenan las columnas nuevas con la posicion/area
|
|
-- actual del empleado (fuente de verdad temporal).
|
|
-- 3. Se modifican newcontract() y updatecontract() para
|
|
-- guardar la posicion/area recibida en el contrato.
|
|
-- 4. Se modifican getcontracts() y reportemployeecontract()
|
|
-- para mostrar la posicion/area del contrato, no la
|
|
-- actual del empleado.
|
|
--
|
|
-- NOTA: Este cambio es reversible. Si algo falla, ejecutar
|
|
-- rollback_contracts_position_area.sql
|
|
-- ============================================================
|
|
|
|
-- ============================================================
|
|
-- 1. AGREGAR COLUMNAS A contracts
|
|
-- ============================================================
|
|
ALTER TABLE contracts
|
|
ADD COLUMN IF NOT EXISTS id_position integer,
|
|
ADD COLUMN IF NOT EXISTS id_area integer;
|
|
|
|
-- ============================================================
|
|
-- 2. RELLENAR COLUMNAS NUEVAS CON DATOS ACTUALES DEL EMPLEADO
|
|
-- ============================================================
|
|
UPDATE contracts c
|
|
SET
|
|
id_position = emp.id_position,
|
|
id_area = emp.id_area
|
|
FROM employees emp
|
|
WHERE c.rfc_employee = emp.rfc_employee;
|
|
|
|
-- ============================================================
|
|
-- 3. AGREGAR FOREIGN KEYS (opcional, recomendado)
|
|
-- ============================================================
|
|
-- Nota: Si ya existen contratos con id_position/id_area NULL
|
|
-- o con valores que no existan en positions/areas, estas FKs
|
|
-- fallaran. Descomentar solo si se valida la consistencia.
|
|
--
|
|
-- ALTER TABLE contracts
|
|
-- ADD CONSTRAINT fk_contracts_position
|
|
-- FOREIGN KEY (id_position) REFERENCES positions(id_position);
|
|
--
|
|
-- ALTER TABLE contracts
|
|
-- ADD CONSTRAINT fk_contracts_area
|
|
-- FOREIGN KEY (id_area) REFERENCES areas(id_area);
|
|
|
|
-- ============================================================
|
|
-- 4. FIX: getcontracts()
|
|
-- ============================================================
|
|
-- Ahora position_employee y area_employee vienen de contracts.
|
|
-- ============================================================
|
|
CREATE OR REPLACE FUNCTION public.getcontracts()
|
|
RETURNS TABLE(
|
|
id_contract integer,
|
|
name_employee character varying,
|
|
position_employee character varying,
|
|
area_employee character varying,
|
|
contratc_start date,
|
|
contratc_end date,
|
|
uniforms jsonb,
|
|
daily_pay numeric,
|
|
status_contract character varying,
|
|
position_entry character varying
|
|
)
|
|
LANGUAGE 'plpgsql'
|
|
COST 100
|
|
VOLATILE PARALLEL UNSAFE
|
|
ROWS 1000
|
|
AS $BODY$
|
|
BEGIN
|
|
RETURN QUERY
|
|
SELECT
|
|
co.id_contract,
|
|
emp.name_employee,
|
|
p.name_position,
|
|
a.name_area,
|
|
co.contratc_start,
|
|
co.contratc_end,
|
|
COALESCE(
|
|
(
|
|
SELECT jsonb_object_agg(u.name_uniform, du.quantity)
|
|
FROM detail_unifor_employee du
|
|
INNER JOIN uniforms u ON du.id_uniform = u.id_uniform
|
|
WHERE du.rfc_employee = emp.rfc_employee
|
|
),
|
|
'{}'::jsonb
|
|
) AS uniforms,
|
|
co.daily_pay,
|
|
stat.name_stat_contract,
|
|
co.entry_position
|
|
FROM contracts co
|
|
INNER JOIN employees emp ON co.rfc_employee = emp.rfc_employee
|
|
INNER JOIN positions p ON co.id_position = p.id_position
|
|
INNER JOIN areas a ON co.id_area = a.id_area
|
|
INNER JOIN status_contract stat ON co.id_contract_status = stat.id_stat_contract;
|
|
END;
|
|
$BODY$;
|
|
|
|
-- ============================================================
|
|
-- 5. FIX: newcontract()
|
|
-- ============================================================
|
|
-- Guarda id_position e id_area en contracts.
|
|
-- ============================================================
|
|
CREATE OR REPLACE FUNCTION public.newcontract(
|
|
rfc_emp character varying,
|
|
id_position_emp integer,
|
|
id_area_emp integer,
|
|
start_contract date,
|
|
end_contract date,
|
|
new_daily_pay numeric,
|
|
boss_rfc character varying,
|
|
boss_name character varying,
|
|
position_entry character varying,
|
|
uniforms jsonb)
|
|
RETURNS integer
|
|
LANGUAGE 'plpgsql'
|
|
COST 100
|
|
VOLATILE PARALLEL UNSAFE
|
|
AS $BODY$
|
|
DECLARE
|
|
new_contract int;
|
|
uniform jsonb;
|
|
BEGIN
|
|
IF EXISTS (SELECT 1 FROM employees WHERE rfc_employee = rfc_emp) THEN
|
|
DELETE FROM detail_unifor_employee
|
|
WHERE rfc_employee = rfc_emp;
|
|
|
|
UPDATE employees
|
|
SET
|
|
id_position = id_position_emp,
|
|
id_area = id_area_emp
|
|
WHERE rfc_employee = rfc_emp;
|
|
|
|
INSERT INTO contracts(
|
|
id_company, id_properties, rfc_employee,
|
|
contratc_start, contratc_end, id_contract_status,
|
|
daily_pay, rfc_boss, name_boss, entry_position,
|
|
id_position, id_area
|
|
)
|
|
VALUES (
|
|
1, 1, rfc_emp,
|
|
start_contract, end_contract, 1,
|
|
new_daily_pay, boss_rfc, boss_name, position_entry,
|
|
id_position_emp, id_area_emp
|
|
)
|
|
RETURNING id_contract INTO new_contract;
|
|
|
|
FOR uniform IN
|
|
SELECT jsonb_array_elements(uniforms)
|
|
LOOP
|
|
INSERT INTO detail_unifor_employee(rfc_employee, id_uniform, id_contract, quantity)
|
|
VALUES (rfc_emp, (uniform->>'id_uniform')::INT, new_contract, (uniform->>'quantity')::INT);
|
|
END LOOP;
|
|
|
|
RETURN 1;
|
|
ELSE
|
|
RETURN -1; -- empleado inexistente
|
|
END IF;
|
|
END;
|
|
$BODY$;
|
|
|
|
-- ============================================================
|
|
-- 6. FIX: updatecontract()
|
|
-- ============================================================
|
|
-- Actualiza id_position e id_area en contracts.
|
|
-- ============================================================
|
|
CREATE OR REPLACE FUNCTION public.updatecontract(
|
|
contract_id integer,
|
|
rfc_emp character varying,
|
|
id_position_emp integer,
|
|
id_area_emp integer,
|
|
start_contract date,
|
|
end_contract date,
|
|
new_daily_pay numeric,
|
|
boss_rfc character varying,
|
|
boss_name character varying,
|
|
reason character varying,
|
|
uniforms jsonb)
|
|
RETURNS integer
|
|
LANGUAGE 'plpgsql'
|
|
COST 100
|
|
VOLATILE PARALLEL UNSAFE
|
|
AS $BODY$
|
|
DECLARE
|
|
new_contract int;
|
|
uniform jsonb;
|
|
final_status int;
|
|
BEGIN
|
|
DELETE FROM detail_unifor_employee
|
|
WHERE id_contract = contract_id;
|
|
|
|
UPDATE employees
|
|
SET
|
|
id_position = id_position_emp,
|
|
id_area = id_area_emp
|
|
WHERE rfc_employee = rfc_emp;
|
|
|
|
IF end_contract < CURRENT_DATE THEN
|
|
final_status := 2; -- Inactivo
|
|
ELSE
|
|
final_status := 1;
|
|
END IF;
|
|
|
|
UPDATE contracts SET
|
|
rfc_employee = rfc_emp,
|
|
contratc_start = start_contract,
|
|
contratc_end = end_contract,
|
|
id_contract_status = final_status,
|
|
daily_pay = new_daily_pay,
|
|
rfc_boss = boss_rfc,
|
|
name_boss = boss_name,
|
|
reasonfordismissal = reason,
|
|
id_position = id_position_emp,
|
|
id_area = id_area_emp
|
|
WHERE id_contract = contract_id;
|
|
|
|
FOR uniform IN
|
|
SELECT jsonb_array_elements(uniforms)
|
|
LOOP
|
|
INSERT INTO detail_unifor_employee(rfc_employee, id_uniform, id_contract, quantity)
|
|
VALUES (rfc_emp, (uniform->>'id_uniform')::INT, contract_id, (uniform->>'quantity')::INT);
|
|
END LOOP;
|
|
|
|
RETURN 1;
|
|
END;
|
|
$BODY$;
|
|
|
|
-- ============================================================
|
|
-- 7. FIX: reportemployeecontract()
|
|
-- ============================================================
|
|
-- Ahora name_position y name_area vienen de contracts.
|
|
-- ============================================================
|
|
CREATE OR REPLACE FUNCTION public.reportemployeecontract()
|
|
RETURNS TABLE(
|
|
name_employee character varying,
|
|
rfc_employee character varying,
|
|
nss_employee bigint,
|
|
name_position character varying,
|
|
spanish_name character varying,
|
|
name_area character varying,
|
|
addres_employee character varying,
|
|
phone_employee character varying,
|
|
email_employee character varying,
|
|
birthday date,
|
|
curp character varying,
|
|
name_study character varying,
|
|
id_contract integer,
|
|
contratc_start date,
|
|
contratc_end date,
|
|
name_status character varying,
|
|
daily_pay numeric,
|
|
rfc_boss character varying,
|
|
name_boss character varying,
|
|
reasonfordismissal character varying,
|
|
name_contact character varying,
|
|
tel_contact character varying,
|
|
name_relationship character varying
|
|
)
|
|
LANGUAGE 'plpgsql'
|
|
COST 100
|
|
VOLATILE PARALLEL UNSAFE
|
|
ROWS 1000
|
|
AS $BODY$
|
|
BEGIN
|
|
RETURN QUERY
|
|
SELECT
|
|
emp.name_employee,
|
|
emp.rfc_employee,
|
|
emp.nss_employee,
|
|
p.name_position,
|
|
p.spanish_name,
|
|
a.name_area,
|
|
emp.addres_employee,
|
|
emp.phone_employee,
|
|
emp.email_employee,
|
|
emp.birthday,
|
|
emp.curp,
|
|
st.name_study,
|
|
c.id_contract,
|
|
c.contratc_start,
|
|
c.contratc_end,
|
|
cs.name_stat_contract,
|
|
c.daily_pay,
|
|
c.rfc_boss,
|
|
c.name_boss,
|
|
c.reasonfordismissal,
|
|
ec.name_contact,
|
|
ec.tel_contact,
|
|
r.name_relationship
|
|
FROM employees emp
|
|
INNER JOIN contracts c ON emp.rfc_employee = c.rfc_employee
|
|
INNER JOIN emergencycontact ec ON emp.rfc_employee = ec.rfc_employee
|
|
INNER JOIN areas a ON c.id_area = a.id_area
|
|
INNER JOIN positions p ON c.id_position = p.id_position
|
|
INNER JOIN degreeofstudy st ON emp.id_study = st.id_study
|
|
INNER JOIN status_contract cs ON c.id_contract_status = cs.id_stat_contract
|
|
INNER JOIN relationship_employee r ON ec.id_relationship = r.id_relationship;
|
|
END;
|
|
$BODY$;
|
|
|
|
-- Confirmacion
|
|
SELECT 'Fix de posicion/area en contratos aplicado correctamente' AS resultado;
|