chore: import DH V2 D5.6.4 production baseline
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
const permissions = [
|
||||
['inspection_reports.revise', 'Cargar versiones corregidas del informe para revisión directiva'],
|
||||
['inspection_reports.review', 'Aprobar la versión vigente del informe'],
|
||||
['inspection_reports.sign_final', 'Firmar electrónicamente el informe final aprobado'],
|
||||
] as const;
|
||||
|
||||
export class PhaseD5322DirectorReportReview1788631200000 implements MigrationInterface {
|
||||
name = 'PhaseD5322DirectorReportReview1788631200000';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE inspection_reports
|
||||
ADD COLUMN review_status varchar(32) NOT NULL DEFAULT 'PENDING_REVIEW',
|
||||
ADD COLUMN current_revision_number integer NOT NULL DEFAULT 0,
|
||||
ADD COLUMN approved_revision_id uuid,
|
||||
ADD COLUMN approved_by uuid,
|
||||
ADD COLUMN approved_at timestamptz,
|
||||
ADD COLUMN review_note varchar(1000),
|
||||
ADD COLUMN signed_at timestamptz,
|
||||
ADD CONSTRAINT chk_inspection_reports_review_status CHECK (review_status IN ('PENDING_REVIEW','APPROVED','SIGNED')),
|
||||
ADD CONSTRAINT chk_inspection_reports_revision_number CHECK (current_revision_number >= 0),
|
||||
ADD CONSTRAINT fk_inspection_reports_approved_by FOREIGN KEY (approved_by) REFERENCES users(id) ON DELETE SET NULL
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
CREATE TABLE inspection_report_revisions (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
report_id uuid NOT NULL,
|
||||
revision_number integer NOT NULL,
|
||||
source varchar(24) NOT NULL,
|
||||
original_name varchar(255) NOT NULL,
|
||||
stored_name varchar(255) NOT NULL,
|
||||
mime_type varchar(120) NOT NULL,
|
||||
size_bytes integer NOT NULL,
|
||||
sha256 char(64) NOT NULL,
|
||||
change_summary varchar(1000),
|
||||
created_by uuid NOT NULL,
|
||||
created_at timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT fk_inspection_report_revisions_report FOREIGN KEY (report_id) REFERENCES inspection_reports(id) ON DELETE CASCADE,
|
||||
CONSTRAINT fk_inspection_report_revisions_created_by FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE RESTRICT,
|
||||
CONSTRAINT uq_inspection_report_revision_number UNIQUE (report_id, revision_number),
|
||||
CONSTRAINT chk_inspection_report_revision_number CHECK (revision_number > 0),
|
||||
CONSTRAINT chk_inspection_report_revision_source CHECK (source IN ('AUTO','DIRECTOR_UPLOAD')),
|
||||
CONSTRAINT chk_inspection_report_revision_file CHECK (
|
||||
mime_type = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
|
||||
AND size_bytes > 0
|
||||
AND sha256 ~ '^[0-9a-f]{64}$'
|
||||
)
|
||||
)
|
||||
`);
|
||||
await queryRunner.query(`CREATE INDEX idx_inspection_report_revisions_report_created ON inspection_report_revisions (report_id, revision_number DESC)`);
|
||||
await queryRunner.query(`
|
||||
INSERT INTO inspection_report_revisions (
|
||||
report_id, revision_number, source, original_name, stored_name, mime_type,
|
||||
size_bytes, sha256, change_summary, created_by, created_at
|
||||
)
|
||||
SELECT
|
||||
id, 1, 'AUTO', word_original_name, word_stored_name, word_mime_type,
|
||||
word_size_bytes, word_sha256, 'Versión automática inicial', generated_by,
|
||||
COALESCE(word_generated_at, generated_at)
|
||||
FROM inspection_reports
|
||||
WHERE word_status = 'READY'
|
||||
AND word_original_name IS NOT NULL
|
||||
AND word_stored_name IS NOT NULL
|
||||
AND word_mime_type = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
|
||||
AND word_size_bytes > 0
|
||||
AND word_sha256 ~ '^[0-9a-f]{64}$'
|
||||
ON CONFLICT (report_id, revision_number) DO NOTHING
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
UPDATE inspection_reports report
|
||||
SET current_revision_number = 1
|
||||
WHERE EXISTS (
|
||||
SELECT 1 FROM inspection_report_revisions revision
|
||||
WHERE revision.report_id = report.id AND revision.revision_number = 1
|
||||
)
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE inspection_reports
|
||||
ADD CONSTRAINT fk_inspection_reports_approved_revision
|
||||
FOREIGN KEY (approved_revision_id) REFERENCES inspection_report_revisions(id) ON DELETE RESTRICT
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
CREATE TABLE inspection_report_signatures (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
report_id uuid NOT NULL UNIQUE,
|
||||
revision_id uuid NOT NULL UNIQUE,
|
||||
signed_by uuid NOT NULL,
|
||||
signed_at timestamptz NOT NULL,
|
||||
confirmation_text varchar(500) NOT NULL,
|
||||
signature_payload jsonb NOT NULL,
|
||||
signature_sha256 char(64) NOT NULL,
|
||||
created_at timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT fk_inspection_report_signatures_report FOREIGN KEY (report_id) REFERENCES inspection_reports(id) ON DELETE CASCADE,
|
||||
CONSTRAINT fk_inspection_report_signatures_revision FOREIGN KEY (revision_id) REFERENCES inspection_report_revisions(id) ON DELETE RESTRICT,
|
||||
CONSTRAINT fk_inspection_report_signatures_user FOREIGN KEY (signed_by) REFERENCES users(id) ON DELETE RESTRICT,
|
||||
CONSTRAINT chk_inspection_report_signature_sha CHECK (signature_sha256 ~ '^[0-9a-f]{64}$')
|
||||
)
|
||||
`);
|
||||
await queryRunner.query(`CREATE INDEX idx_inspection_report_signatures_signed_at ON inspection_report_signatures (signed_at DESC)`);
|
||||
for (const [code, description] of permissions) {
|
||||
await queryRunner.query(
|
||||
`INSERT INTO permissions (code, description) VALUES ($1, $2) ON CONFLICT (code) DO UPDATE SET description = EXCLUDED.description`,
|
||||
[code, description],
|
||||
);
|
||||
}
|
||||
await queryRunner.query(`
|
||||
WITH mapping(role_code, permission_code) AS (VALUES
|
||||
('director', 'inspection_reports.revise'),
|
||||
('director', 'inspection_reports.review'),
|
||||
('director', 'inspection_reports.sign_final')
|
||||
)
|
||||
INSERT INTO role_permissions (role_id, permission_id)
|
||||
SELECT role.id, permission.id
|
||||
FROM mapping
|
||||
JOIN roles role ON role.code = mapping.role_code
|
||||
JOIN permissions permission ON permission.code = mapping.permission_code
|
||||
ON CONFLICT (role_id, permission_id) DO NOTHING
|
||||
`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DELETE FROM role_permissions rp USING permissions p WHERE rp.permission_id = p.id AND p.code IN ('inspection_reports.revise','inspection_reports.review','inspection_reports.sign_final')`);
|
||||
await queryRunner.query(`DELETE FROM permissions WHERE code IN ('inspection_reports.revise','inspection_reports.review','inspection_reports.sign_final')`);
|
||||
await queryRunner.query(`DROP TABLE IF EXISTS inspection_report_signatures`);
|
||||
await queryRunner.query(`ALTER TABLE inspection_reports DROP CONSTRAINT IF EXISTS fk_inspection_reports_approved_revision`);
|
||||
await queryRunner.query(`DROP TABLE IF EXISTS inspection_report_revisions`);
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE inspection_reports
|
||||
DROP CONSTRAINT IF EXISTS fk_inspection_reports_approved_by,
|
||||
DROP CONSTRAINT IF EXISTS chk_inspection_reports_revision_number,
|
||||
DROP CONSTRAINT IF EXISTS chk_inspection_reports_review_status,
|
||||
DROP COLUMN IF EXISTS signed_at,
|
||||
DROP COLUMN IF EXISTS review_note,
|
||||
DROP COLUMN IF EXISTS approved_at,
|
||||
DROP COLUMN IF EXISTS approved_by,
|
||||
DROP COLUMN IF EXISTS approved_revision_id,
|
||||
DROP COLUMN IF EXISTS current_revision_number,
|
||||
DROP COLUMN IF EXISTS review_status
|
||||
`);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user