mirror of
https://origin.cursor.com/mrdevmx/panels.git
synced 2026-10-09 11:23:18 +00:00
Reutiliza el catálogo de proveedores y agrega carga de facturas, conceptos de la semana, préstamos editables, finiquitos, dispersión, historial de personal, reportes y jornal de cotización. Co-authored-by: alberto.martinez <alberto.martinez@mrdev.mx>
104 lines
5 KiB
PL/PgSQL
104 lines
5 KiB
PL/PgSQL
--liquibase formatted sql
|
|
-- PANELS · core · historial de alta, baja y reingreso
|
|
|
|
--changeset panel:core-048a-table endDelimiter:; splitStatements:true
|
|
ALTER TABLE core.workers ADD COLUMN IF NOT EXISTS imss_daily_wage NUMERIC(12,2);
|
|
CREATE TABLE IF NOT EXISTS core.worker_movements (
|
|
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
|
tenant_id INTEGER,
|
|
worker_id BIGINT NOT NULL REFERENCES core.workers(id) ON DELETE CASCADE,
|
|
kind TEXT NOT NULL CHECK (kind IN ('alta', 'baja', 'reingreso', 'alta_imss', 'baja_imss', 'modificacion_salario')),
|
|
movement_date DATE NOT NULL,
|
|
note TEXT NOT NULL DEFAULT '',
|
|
actor_name TEXT NOT NULL DEFAULT '',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_core_worker_movements_worker ON core.worker_movements (worker_id, movement_date, id);
|
|
GRANT SELECT, INSERT, UPDATE, DELETE ON core.worker_movements TO panels_core_app;
|
|
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA core TO panels_core_app;
|
|
|
|
--changeset panel:core-048b-backfill endDelimiter:; splitStatements:true
|
|
INSERT INTO core.worker_movements (tenant_id, worker_id, kind, movement_date, note)
|
|
SELECT w.tenant_id, w.id, 'alta', COALESCE(w.created_at::date, CURRENT_DATE), 'Alta de padrón'
|
|
FROM core.workers w
|
|
WHERE NOT EXISTS (
|
|
SELECT 1 FROM core.worker_movements m WHERE m.worker_id = w.id AND m.kind = 'alta'
|
|
);
|
|
INSERT INTO core.worker_movements (tenant_id, worker_id, kind, movement_date, note)
|
|
SELECT w.tenant_id, w.id, 'reingreso', w.last_rehire_at, 'Reingreso'
|
|
FROM core.workers w
|
|
WHERE w.last_rehire_at IS NOT NULL
|
|
AND NOT EXISTS (
|
|
SELECT 1 FROM core.worker_movements m WHERE m.worker_id = w.id AND m.kind = 'reingreso' AND m.movement_date = w.last_rehire_at
|
|
);
|
|
INSERT INTO core.worker_movements (tenant_id, worker_id, kind, movement_date, note)
|
|
SELECT w.tenant_id, w.id, 'baja', COALESCE(w.updated_at::date, CURRENT_DATE), 'Baja de padrón'
|
|
FROM core.workers w
|
|
WHERE w.status = 'baja'
|
|
AND NOT EXISTS (SELECT 1 FROM core.worker_movements m WHERE m.worker_id = w.id AND m.kind = 'baja');
|
|
|
|
--changeset panel:core-048c-trigger splitStatements:false
|
|
CREATE OR REPLACE FUNCTION core.trg_worker_movement()
|
|
RETURNS trigger
|
|
LANGUAGE plpgsql
|
|
SET search_path = core
|
|
AS $$
|
|
BEGIN
|
|
IF TG_OP = 'INSERT' THEN
|
|
INSERT INTO worker_movements (tenant_id, worker_id, kind, movement_date, note)
|
|
VALUES (NEW.tenant_id, NEW.id, 'alta', COALESCE(NEW.created_at::date, CURRENT_DATE), 'Alta de padrón');
|
|
RETURN NEW;
|
|
END IF;
|
|
IF OLD.status IS DISTINCT FROM 'baja' AND NEW.status = 'baja' THEN
|
|
INSERT INTO worker_movements (tenant_id, worker_id, kind, movement_date, note)
|
|
VALUES (NEW.tenant_id, NEW.id, 'baja', CURRENT_DATE, 'Baja de padrón');
|
|
ELSIF OLD.status = 'baja' AND NEW.status = 'activo' THEN
|
|
INSERT INTO worker_movements (tenant_id, worker_id, kind, movement_date, note)
|
|
VALUES (NEW.tenant_id, NEW.id, 'reingreso', COALESCE(NEW.last_rehire_at, CURRENT_DATE), 'Reingreso');
|
|
END IF;
|
|
IF OLD.imss_status IS DISTINCT FROM 'alta' AND NEW.imss_status = 'alta' THEN
|
|
INSERT INTO worker_movements (tenant_id, worker_id, kind, movement_date, note)
|
|
VALUES (NEW.tenant_id, NEW.id, 'alta_imss', COALESCE(NEW.imss_alta_at, CURRENT_DATE), 'Alta IMSS');
|
|
ELSIF OLD.imss_status IS DISTINCT FROM 'baja_imss' AND NEW.imss_status = 'baja_imss' THEN
|
|
INSERT INTO worker_movements (tenant_id, worker_id, kind, movement_date, note)
|
|
VALUES (NEW.tenant_id, NEW.id, 'baja_imss', COALESCE(NEW.imss_baja_at, CURRENT_DATE), 'Baja IMSS');
|
|
END IF;
|
|
IF NEW.imss_daily_wage IS NOT NULL AND NEW.imss_daily_wage IS DISTINCT FROM OLD.imss_daily_wage THEN
|
|
INSERT INTO worker_movements (tenant_id, worker_id, kind, movement_date, note)
|
|
VALUES (NEW.tenant_id, NEW.id, 'modificacion_salario', CURRENT_DATE,
|
|
format('Jornal IMSS %s', NEW.imss_daily_wage));
|
|
END IF;
|
|
RETURN NEW;
|
|
END;
|
|
$$;
|
|
|
|
DROP TRIGGER IF EXISTS trg_worker_movement ON core.workers;
|
|
CREATE TRIGGER trg_worker_movement
|
|
AFTER INSERT OR UPDATE OF status, imss_status, imss_daily_wage ON core.workers
|
|
FOR EACH ROW EXECUTE FUNCTION core.trg_worker_movement();
|
|
|
|
--changeset panel:core-048d-fn-list splitStatements:false
|
|
CREATE OR REPLACE FUNCTION core.fn_worker_movement_list(payload jsonb)
|
|
RETURNS jsonb
|
|
LANGUAGE plpgsql
|
|
SECURITY INVOKER
|
|
SET search_path = core
|
|
AS $$
|
|
DECLARE
|
|
v_worker_id bigint := NULLIF(payload->>'worker_id', '')::bigint;
|
|
v_rows jsonb;
|
|
BEGIN
|
|
SELECT COALESCE(jsonb_agg(to_jsonb(m) ORDER BY m.movement_date, m.id), '[]'::jsonb)
|
|
INTO v_rows
|
|
FROM worker_movements m
|
|
WHERE m.worker_id = v_worker_id;
|
|
RETURN core.rpc_ok(jsonb_build_object('movements', v_rows), 'Historial de movimientos',
|
|
jsonb_build_object('fn', 'fn_worker_movement_list', 'worker_id', v_worker_id));
|
|
EXCEPTION WHEN OTHERS THEN
|
|
RETURN core.rpc_from_exception('fn_worker_movement_list', SQLSTATE, SQLERRM);
|
|
END;
|
|
$$;
|
|
|
|
--changeset panel:core-048e-grants endDelimiter:; splitStatements:true
|
|
GRANT EXECUTE ON FUNCTION core.trg_worker_movement() TO panels_core_app;
|
|
GRANT EXECUTE ON FUNCTION core.fn_worker_movement_list(jsonb) TO panels_core_app;
|