add custom contrat templates

This commit is contained in:
Marshal
2026-08-04 09:48:49 +00:00
parent aac1175964
commit 7c78a815eb
10 changed files with 366 additions and 58 deletions

View File

@@ -0,0 +1,101 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
import { CONTRACT_TEMPLATE_DEFAULTS } from '../seed/data/contract-template-defaults';
/**
* The codes that gain a customs variant. Intercity is deliberately absent: it
* is a domestic Ethiopian movement that crosses no border, so it has no customs
* leg and keeps its single unsuffixed template.
*/
const SPLIT_CODES = [
'IMPORT_BULK',
'EXPORT_BULK',
'IMPORT_CONTAINER',
'EXPORT_CONTAINER',
];
/**
* Split the four cross-border contract templates into eight — one `_CUSTOMS`
* and one `_NO_CUSTOMS` variant each — so the generated contract document
* reflects whether EDR clears customs on the Client's behalf. Together with the
* two untouched intercity templates the table ends up with ten rows.
*
* The four existing rows are RENAMED to `<code>_NO_CUSTOMS` rather than
* replaced, so any article text staff already edited through the template
* editor survives. The four `_CUSTOMS` rows are then inserted from the seed
* (the same base pack plus the customs-clearing articles).
*
* Idempotent: the rename is guarded on the legacy code still existing, and the
* insert is ON CONFLICT (code) DO NOTHING.
*/
export class SplitContractTemplatesByCustoms3230000000000
implements MigrationInterface
{
public async up(queryRunner: QueryRunner): Promise<void> {
// 1. Carry each legacy row over to its _NO_CUSTOMS code, preserving edits.
// Guarded so a re-run (or a DB already holding the new code) is a no-op.
for (const legacy of SPLIT_CODES) {
await queryRunner.query(
`
UPDATE freight.contract_templates
SET code = $2, updated_at = now()
WHERE code = $1
AND NOT EXISTS (
SELECT 1 FROM freight.contract_templates WHERE code = $2
);
`,
[legacy, `${legacy}_NO_CUSTOMS`],
);
}
// 2. Seed anything still missing — the six _CUSTOMS rows on an existing DB,
// or all twelve on a database that never held the legacy codes.
for (const seed of CONTRACT_TEMPLATE_DEFAULTS) {
const articles = seed.articles.map((article, index) => ({
...article,
order: index + 1,
}));
await queryRunner.query(
`
INSERT INTO freight.contract_templates
(code, name, description, document_title, whereas_clauses, articles)
VALUES ($1, $2, $3, $4, $5::jsonb, $6::jsonb)
ON CONFLICT (code) DO NOTHING;
`,
[
seed.code,
seed.name,
seed.description,
seed.documentTitle,
JSON.stringify(seed.whereasClauses),
JSON.stringify(articles),
],
);
}
}
/**
* Drop the _CUSTOMS rows and fold the _NO_CUSTOMS rows back onto the legacy
* codes, returning the table to six templates. The two intercity rows were
* never touched by up(), so they need no reversal.
*/
public async down(queryRunner: QueryRunner): Promise<void> {
for (const legacy of SPLIT_CODES) {
await queryRunner.query(
`DELETE FROM freight.contract_templates WHERE code = $1;`,
[`${legacy}_CUSTOMS`],
);
await queryRunner.query(
`
UPDATE freight.contract_templates
SET code = $1, updated_at = now()
WHERE code = $2
AND NOT EXISTS (
SELECT 1 FROM freight.contract_templates WHERE code = $1
);
`,
[legacy, `${legacy}_NO_CUSTOMS`],
);
}
}
}