feat(warehouses): gate double-handling fee on a per-booking Yes/No

Double handling billed every import with a matching rule. Add
bookings.double_handling (+ set_at/by), charge only when Yes, expose a
PATCH endpoint (import-only, locked after invoicing, audited) and Yes/No
items in the inventory row menu.
This commit is contained in:
Hagernesh
2026-07-25 10:44:41 +00:00
parent 43b053bf71
commit 6983645347
10 changed files with 280 additions and 2 deletions

View File

@@ -0,0 +1,39 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
/**
* Double handling becomes an explicit per-booking decision instead of an
* implicit "every import" charge. Warehouse staff record Yes/No after
* unloading (whether the goods actually had to be re-handled); the
* DOUBLE_HANDLING_FEE rule only bills when the answer is Yes.
*
* NULL = not decided yet → no charge, and the UI shows "not set" so the
* operator is prompted. Existing rows stay NULL deliberately: back-billing a
* fee nobody confirmed would be wrong.
*/
export class AddBookingDoubleHandling2850000000000 implements MigrationInterface {
name = 'AddBookingDoubleHandling2850000000000';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE freight.bookings ADD COLUMN IF NOT EXISTS double_handling boolean;`,
);
await queryRunner.query(
`ALTER TABLE freight.bookings ADD COLUMN IF NOT EXISTS double_handling_set_at timestamptz;`,
);
await queryRunner.query(
`ALTER TABLE freight.bookings ADD COLUMN IF NOT EXISTS double_handling_set_by varchar(160);`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE freight.bookings DROP COLUMN IF EXISTS double_handling_set_by;`,
);
await queryRunner.query(
`ALTER TABLE freight.bookings DROP COLUMN IF EXISTS double_handling_set_at;`,
);
await queryRunner.query(
`ALTER TABLE freight.bookings DROP COLUMN IF EXISTS double_handling;`,
);
}
}