mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-08 21:48:18 +00:00
feat(warehouses): delete yards/zones and inspect zone contents
Yard and zone soft-delete, refused with 409 while a yard still has zones or a zone still holds inventory. warehouse_zones:delete was missing from the catalog — the role presets spread every zone key, so its absence crashes FreightPositionsSeeder at boot; a migration seeds it everywhere. Clicking a zone opens its contents as a datatable. Container identity comes from booking_container_units for booked cargo and from containers for backlog registrations; bulk cargo keeps its row with no container number rather than disappearing from the zone.
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
/**
|
||||
* Seed `edr_freight_app:warehouse_zones:delete` — the zone counterpart of the
|
||||
* warehouse and yard delete permissions, which already exist.
|
||||
*
|
||||
* `ROLE_PERMISSION_PRESETS` spreads `Object.values(FREIGHT_PERMS.warehouseZones)`
|
||||
* into the warehouse positions, so the moment the key is added to the registry
|
||||
* `FreightPositionsSeeder.loadPermissionIds` resolves it against `iam.permissions`
|
||||
* at boot — and throws `missing_permissions:<key>` if the row is absent. The
|
||||
* catalog is otherwise written by `EdrOrgSeeder`, which skips itself unless
|
||||
* `SEED_EDR_ORG` is set, so a migration is the only path that runs everywhere.
|
||||
*
|
||||
* Idempotent on `key`; keeps the registry's fixed uuid so every environment
|
||||
* lands on the same id. Skips silently when the freight application row is
|
||||
* absent, since there is nothing to attach to.
|
||||
*/
|
||||
export class WarehouseZoneDeletePermission3810000000000 implements MigrationInterface {
|
||||
private static readonly KEY = 'edr_freight_app:warehouse_zones:delete';
|
||||
private static readonly ID = 'f1c00001-0001-4000-8000-000000000004';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`INSERT INTO iam.permissions (id, key, name, application_id)
|
||||
SELECT $2::uuid,
|
||||
$1::varchar,
|
||||
'{"am": "Delete warehouse zone", "en": "Delete warehouse zone"}'::jsonb,
|
||||
a.id
|
||||
FROM iam.application a
|
||||
WHERE a.key = 'edr_freight_app'
|
||||
AND NOT EXISTS (SELECT 1 FROM iam.permissions p WHERE p.key = $1::varchar)`,
|
||||
[WarehouseZoneDeletePermission3810000000000.KEY, WarehouseZoneDeletePermission3810000000000.ID],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Grants go first, or the delete trips the position/role permission foreign
|
||||
* keys — a half-removed permission is worse than one left in place.
|
||||
*/
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`DELETE FROM iam.position_permissions
|
||||
WHERE permission_id IN (SELECT id FROM iam.permissions WHERE key = $1)`,
|
||||
[WarehouseZoneDeletePermission3810000000000.KEY],
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DELETE FROM iam.role_permissions
|
||||
WHERE permission_id IN (SELECT id FROM iam.permissions WHERE key = $1)`,
|
||||
[WarehouseZoneDeletePermission3810000000000.KEY],
|
||||
);
|
||||
await queryRunner.query(`DELETE FROM iam.permissions WHERE key = $1`, [
|
||||
WarehouseZoneDeletePermission3810000000000.KEY,
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user