93 lines
5.4 KiB
TypeScript
93 lines
5.4 KiB
TypeScript
import { MigrationInterface, QueryRunner } from 'typeorm';
|
|
|
|
function quoteIdentifier(identifier: string): string {
|
|
return `"${identifier.replaceAll('"', '""')}"`;
|
|
}
|
|
|
|
export class PhaseD5372RelationalTerritoryPlan1787767200000 implements MigrationInterface {
|
|
name = 'PhaseD5372RelationalTerritoryPlan1787767200000';
|
|
|
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
await queryRunner.query(`
|
|
ALTER TABLE asset_import_plan_items DROP CONSTRAINT chk_asset_import_plan_item_kind
|
|
`);
|
|
await queryRunner.query(`
|
|
ALTER TABLE asset_import_plan_items ADD CONSTRAINT chk_asset_import_plan_item_kind CHECK (
|
|
entity_kind IN (
|
|
'DEPARTMENT','ORGANIZATION','AREA','AREA_DEPARTMENT_RELATION','FIELD','OPERATOR_RELATION',
|
|
'LEGAL_RIGHT','LEGAL_RIGHT_ORGANIZATION','INSTALLATION','TECHNICAL_ASSET'
|
|
)
|
|
)
|
|
`);
|
|
|
|
await queryRunner.query(`
|
|
CREATE TABLE administrative_departments (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
province_code varchar(40) NOT NULL DEFAULT 'MENDOZA',
|
|
code varchar(80) NOT NULL,
|
|
name varchar(160) NOT NULL,
|
|
normalized_name varchar(180) NOT NULL,
|
|
is_active boolean NOT NULL DEFAULT true,
|
|
source_document_id uuid,
|
|
created_by uuid,
|
|
updated_by uuid,
|
|
created_at timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
CONSTRAINT chk_administrative_department_code CHECK (code ~ '^[A-Z0-9][A-Z0-9._/-]{1,79}$'),
|
|
CONSTRAINT chk_administrative_department_name CHECK (length(btrim(name)) >= 2),
|
|
CONSTRAINT chk_administrative_department_normalized CHECK (length(btrim(normalized_name)) >= 2),
|
|
CONSTRAINT fk_administrative_department_source FOREIGN KEY (source_document_id) REFERENCES source_documents(id) ON DELETE SET NULL,
|
|
CONSTRAINT fk_administrative_department_created_by FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE SET NULL,
|
|
CONSTRAINT fk_administrative_department_updated_by FOREIGN KEY (updated_by) REFERENCES users(id) ON DELETE SET NULL,
|
|
CONSTRAINT uq_administrative_department_code UNIQUE (province_code, code),
|
|
CONSTRAINT uq_administrative_department_name UNIQUE (province_code, normalized_name)
|
|
)
|
|
`);
|
|
await queryRunner.query(`CREATE INDEX idx_administrative_departments_active_name ON administrative_departments (is_active, normalized_name)`);
|
|
|
|
await queryRunner.query(`
|
|
CREATE TABLE area_department_relations (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
area_id uuid NOT NULL,
|
|
department_id uuid NOT NULL,
|
|
valid_from date NOT NULL DEFAULT CURRENT_DATE,
|
|
valid_until date,
|
|
source_document_id uuid,
|
|
notes text,
|
|
created_by uuid,
|
|
ended_by uuid,
|
|
created_at timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
CONSTRAINT chk_area_department_relation_dates CHECK (valid_until IS NULL OR valid_until >= valid_from),
|
|
CONSTRAINT fk_area_department_relation_area FOREIGN KEY (area_id) REFERENCES assets(id) ON DELETE RESTRICT,
|
|
CONSTRAINT fk_area_department_relation_department FOREIGN KEY (department_id) REFERENCES administrative_departments(id) ON DELETE RESTRICT,
|
|
CONSTRAINT fk_area_department_relation_source FOREIGN KEY (source_document_id) REFERENCES source_documents(id) ON DELETE SET NULL,
|
|
CONSTRAINT fk_area_department_relation_created_by FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE SET NULL,
|
|
CONSTRAINT fk_area_department_relation_ended_by FOREIGN KEY (ended_by) REFERENCES users(id) ON DELETE SET NULL
|
|
)
|
|
`);
|
|
await queryRunner.query(`CREATE UNIQUE INDEX uq_area_department_relation_active_pair ON area_department_relations (area_id, department_id) WHERE valid_until IS NULL`);
|
|
await queryRunner.query(`CREATE INDEX idx_area_department_relations_area ON area_department_relations (area_id) WHERE valid_until IS NULL`);
|
|
await queryRunner.query(`CREATE INDEX idx_area_department_relations_department ON area_department_relations (department_id) WHERE valid_until IS NULL`);
|
|
|
|
const appRole = process.env.DB_APP_USER;
|
|
if (!appRole) throw new Error('Missing required environment variable: DB_APP_USER');
|
|
const roleRows = (await queryRunner.query('SELECT 1 FROM pg_roles WHERE rolname=$1', [appRole])) as unknown[];
|
|
if (roleRows.length !== 1) throw new Error('Configured DB_APP_USER does not exist');
|
|
const applicationRole = quoteIdentifier(appRole);
|
|
await queryRunner.query(`GRANT SELECT, INSERT, UPDATE ON TABLE administrative_departments, area_department_relations TO ${applicationRole}`);
|
|
await queryRunner.query(`REVOKE DELETE ON TABLE administrative_departments, area_department_relations FROM ${applicationRole}`);
|
|
}
|
|
|
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
await queryRunner.query(`DROP TABLE area_department_relations`);
|
|
await queryRunner.query(`DROP TABLE administrative_departments`);
|
|
await queryRunner.query(`ALTER TABLE asset_import_plan_items DROP CONSTRAINT chk_asset_import_plan_item_kind`);
|
|
await queryRunner.query(`
|
|
ALTER TABLE asset_import_plan_items ADD CONSTRAINT chk_asset_import_plan_item_kind CHECK (
|
|
entity_kind IN ('ORGANIZATION','AREA','FIELD','OPERATOR_RELATION','INSTALLATION','TECHNICAL_ASSET')
|
|
)
|
|
`);
|
|
}
|
|
}
|