fix(inventory): treat company on asset as non-owning creation snapshot
This commit is contained in:
+60
-39
@@ -6,8 +6,8 @@ import { MigrationInterface, QueryRunner } from 'typeorm';
|
|||||||
* historical operator/concession truth lives in area_company_relations and is
|
* historical operator/concession truth lives in area_company_relations and is
|
||||||
* frozen separately by each Inspección/Acta.
|
* frozen separately by each Inspección/Acta.
|
||||||
*
|
*
|
||||||
* operator_company_id is tolerated only on pre-F5 rows for backwards-readable
|
* operator_company_id is retained only as a backwards-compatible creation/
|
||||||
* history. New assignments or changes are rejected by the DB guard.
|
* historical snapshot. Runtime ownership and search MUST NOT depend on it.
|
||||||
*/
|
*/
|
||||||
export class F5OperationalContextCompatibility1790087250000 implements MigrationInterface {
|
export class F5OperationalContextCompatibility1790087250000 implements MigrationInterface {
|
||||||
name = 'F5OperationalContextCompatibility1790087250000';
|
name = 'F5OperationalContextCompatibility1790087250000';
|
||||||
@@ -27,6 +27,8 @@ export class F5OperationalContextCompatibility1790087250000 implements Migration
|
|||||||
DECLARE
|
DECLARE
|
||||||
asset_role asset_type_operational_role;
|
asset_role asset_type_operational_role;
|
||||||
area_role asset_type_operational_role;
|
area_role asset_type_operational_role;
|
||||||
|
company_role asset_type_operational_role;
|
||||||
|
active_relation_id uuid;
|
||||||
BEGIN
|
BEGIN
|
||||||
SELECT operational_role INTO asset_role
|
SELECT operational_role INTO asset_role
|
||||||
FROM asset_types WHERE id=NEW.asset_type_id;
|
FROM asset_types WHERE id=NEW.asset_type_id;
|
||||||
@@ -39,28 +41,30 @@ export class F5OperationalContextCompatibility1790087250000 implements Migration
|
|||||||
RETURN NEW;
|
RETURN NEW;
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
-- Historical rows may still contain the old operator snapshot. It remains
|
IF NEW.operator_company_id IS NOT NULL AND NEW.operational_area_id IS NULL THEN
|
||||||
-- readable, but F5 never creates or changes that ownership-like value.
|
|
||||||
IF NEW.operator_company_id IS NOT NULL THEN
|
|
||||||
IF TG_OP='INSERT'
|
|
||||||
OR OLD.operator_company_id IS NULL
|
|
||||||
OR NEW.operator_company_id IS DISTINCT FROM OLD.operator_company_id THEN
|
|
||||||
RAISE EXCEPTION USING ERRCODE='23514',
|
RAISE EXCEPTION USING ERRCODE='23514',
|
||||||
MESSAGE='La Empresa pertenece al contexto temporal del Área/Inspección y no al Inventario';
|
MESSAGE='Un snapshot de Empresa requiere un Área física';
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
|
-- Once written, an old/current company snapshot cannot be repointed to
|
||||||
|
-- simulate physical ownership. Company changes happen in the temporal
|
||||||
|
-- Area↔Empresa relation instead.
|
||||||
|
IF TG_OP='UPDATE'
|
||||||
|
AND NEW.operator_company_id IS DISTINCT FROM OLD.operator_company_id THEN
|
||||||
|
RAISE EXCEPTION USING ERRCODE='23514',
|
||||||
|
MESSAGE='La Empresa se cambia en la relación temporal del Área, no en el Inventario';
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
IF NEW.operational_area_id IS NULL THEN
|
IF NEW.operational_area_id IS NULL THEN
|
||||||
RETURN NEW;
|
RETURN NEW;
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
SELECT t.operational_role INTO area_role
|
SELECT type.operational_role INTO area_role
|
||||||
FROM assets area
|
FROM assets area
|
||||||
JOIN asset_types t ON t.id=area.asset_type_id
|
JOIN asset_types type ON type.id=area.asset_type_id
|
||||||
WHERE area.id=NEW.operational_area_id
|
WHERE area.id=NEW.operational_area_id
|
||||||
AND area.information_status<>'INACTIVE'
|
AND area.information_status<>'INACTIVE'
|
||||||
AND t.is_active=true;
|
AND type.is_active=true;
|
||||||
|
|
||||||
IF area_role IS DISTINCT FROM 'AREA'::asset_type_operational_role THEN
|
IF area_role IS DISTINCT FROM 'AREA'::asset_type_operational_role THEN
|
||||||
RAISE EXCEPTION USING ERRCODE='23514',
|
RAISE EXCEPTION USING ERRCODE='23514',
|
||||||
MESSAGE='operational area must be an active AREA asset';
|
MESSAGE='operational area must be an active AREA asset';
|
||||||
@@ -80,6 +84,35 @@ export class F5OperationalContextCompatibility1790087250000 implements Migration
|
|||||||
MESSAGE='operational area must be an ancestor in the physical hierarchy';
|
MESSAGE='operational area must be an ancestor in the physical hierarchy';
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
|
-- A company value is allowed only as the context snapshot that was valid
|
||||||
|
-- at creation time. It is never used to decide future membership.
|
||||||
|
IF NEW.operator_company_id IS NOT NULL THEN
|
||||||
|
SELECT type.operational_role INTO company_role
|
||||||
|
FROM assets company
|
||||||
|
JOIN asset_types type ON type.id=company.asset_type_id
|
||||||
|
WHERE company.id=NEW.operator_company_id
|
||||||
|
AND company.information_status<>'INACTIVE'
|
||||||
|
AND type.is_active=true;
|
||||||
|
IF company_role IS DISTINCT FROM 'COMPANY'::asset_type_operational_role THEN
|
||||||
|
RAISE EXCEPTION USING ERRCODE='23514',
|
||||||
|
MESSAGE='operator snapshot must reference an active COMPANY-role asset';
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
IF TG_OP='INSERT' THEN
|
||||||
|
SELECT relation.id INTO active_relation_id
|
||||||
|
FROM area_company_relations relation
|
||||||
|
WHERE relation.area_id=NEW.operational_area_id
|
||||||
|
AND relation.company_id=NEW.operator_company_id
|
||||||
|
AND relation.relation_role='OPERATOR'::area_organization_role
|
||||||
|
AND relation.valid_until IS NULL
|
||||||
|
FOR KEY SHARE;
|
||||||
|
IF active_relation_id IS NULL THEN
|
||||||
|
RAISE EXCEPTION USING ERRCODE='23514',
|
||||||
|
MESSAGE='creation operator snapshot must be active for the selected Area';
|
||||||
|
END IF;
|
||||||
|
END IF;
|
||||||
|
END IF;
|
||||||
|
|
||||||
RETURN NEW;
|
RETURN NEW;
|
||||||
END $$;
|
END $$;
|
||||||
`);
|
`);
|
||||||
@@ -104,29 +137,22 @@ export class F5OperationalContextCompatibility1790087250000 implements Migration
|
|||||||
MESSAGE='operational area and organization must be assigned together';
|
MESSAGE='operational area and organization must be assigned together';
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
SELECT operational_role INTO asset_role
|
SELECT operational_role INTO asset_role FROM asset_types WHERE id=NEW.asset_type_id;
|
||||||
FROM asset_types WHERE id=NEW.asset_type_id;
|
|
||||||
IF asset_role <> 'GENERIC'::asset_type_operational_role THEN
|
IF asset_role <> 'GENERIC'::asset_type_operational_role THEN
|
||||||
RAISE EXCEPTION USING ERRCODE='23514',
|
RAISE EXCEPTION USING ERRCODE='23514',MESSAGE='area and organization assets cannot receive an operational assignment';
|
||||||
MESSAGE='area and organization assets cannot receive an operational assignment';
|
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
SELECT t.operational_role INTO area_role
|
SELECT type.operational_role INTO area_role
|
||||||
FROM assets a JOIN asset_types t ON t.id=a.asset_type_id
|
FROM assets area JOIN asset_types type ON type.id=area.asset_type_id
|
||||||
WHERE a.id=NEW.operational_area_id
|
WHERE area.id=NEW.operational_area_id AND area.information_status<>'INACTIVE' AND type.is_active=true;
|
||||||
AND a.information_status<>'INACTIVE' AND t.is_active=true;
|
SELECT type.operational_role INTO company_role
|
||||||
SELECT t.operational_role INTO company_role
|
FROM assets company JOIN asset_types type ON type.id=company.asset_type_id
|
||||||
FROM assets a JOIN asset_types t ON t.id=a.asset_type_id
|
WHERE company.id=NEW.operator_company_id AND company.information_status<>'INACTIVE' AND type.is_active=true;
|
||||||
WHERE a.id=NEW.operator_company_id
|
|
||||||
AND a.information_status<>'INACTIVE' AND t.is_active=true;
|
|
||||||
|
|
||||||
IF area_role IS DISTINCT FROM 'AREA'::asset_type_operational_role THEN
|
IF area_role IS DISTINCT FROM 'AREA'::asset_type_operational_role THEN
|
||||||
RAISE EXCEPTION USING ERRCODE='23514',
|
RAISE EXCEPTION USING ERRCODE='23514',MESSAGE='operational area must be an active AREA asset';
|
||||||
MESSAGE='operational area must be an active AREA asset';
|
|
||||||
END IF;
|
END IF;
|
||||||
IF company_role IS DISTINCT FROM 'COMPANY'::asset_type_operational_role THEN
|
IF company_role IS DISTINCT FROM 'COMPANY'::asset_type_operational_role THEN
|
||||||
RAISE EXCEPTION USING ERRCODE='23514',
|
RAISE EXCEPTION USING ERRCODE='23514',MESSAGE='operator organization must be an active COMPANY-role asset';
|
||||||
MESSAGE='operator organization must be an active COMPANY-role asset';
|
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
SELECT relation.id INTO active_relation_id
|
SELECT relation.id INTO active_relation_id
|
||||||
@@ -137,22 +163,17 @@ export class F5OperationalContextCompatibility1790087250000 implements Migration
|
|||||||
AND relation.valid_until IS NULL
|
AND relation.valid_until IS NULL
|
||||||
FOR KEY SHARE;
|
FOR KEY SHARE;
|
||||||
IF active_relation_id IS NULL THEN
|
IF active_relation_id IS NULL THEN
|
||||||
RAISE EXCEPTION USING ERRCODE='23514',
|
RAISE EXCEPTION USING ERRCODE='23514',MESSAGE='operational area and organization do not have an active OPERATOR relation';
|
||||||
MESSAGE='operational area and organization do not have an active OPERATOR relation';
|
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
IF NEW.parent_id IS NULL OR NOT EXISTS (
|
IF NEW.parent_id IS NULL OR NOT EXISTS (
|
||||||
WITH RECURSIVE ancestors AS (
|
WITH RECURSIVE ancestors AS (
|
||||||
SELECT id,parent_id FROM assets WHERE id=NEW.parent_id
|
SELECT id,parent_id FROM assets WHERE id=NEW.parent_id
|
||||||
UNION ALL
|
UNION ALL
|
||||||
SELECT parent.id,parent.parent_id
|
SELECT parent.id,parent.parent_id FROM assets parent JOIN ancestors child ON parent.id=child.parent_id
|
||||||
FROM assets parent
|
) SELECT 1 FROM ancestors WHERE id=NEW.operational_area_id LIMIT 1
|
||||||
JOIN ancestors child ON parent.id=child.parent_id
|
|
||||||
)
|
|
||||||
SELECT 1 FROM ancestors WHERE id=NEW.operational_area_id LIMIT 1
|
|
||||||
) THEN
|
) THEN
|
||||||
RAISE EXCEPTION USING ERRCODE='23514',
|
RAISE EXCEPTION USING ERRCODE='23514',MESSAGE='operational area must be an ancestor in the physical hierarchy';
|
||||||
MESSAGE='operational area must be an ancestor in the physical hierarchy';
|
|
||||||
END IF;
|
END IF;
|
||||||
RETURN NEW;
|
RETURN NEW;
|
||||||
END $$;
|
END $$;
|
||||||
|
|||||||
Reference in New Issue
Block a user