feat(warehouse): accrual acknowledge/snooze + zone weight fix, handover signer, portal delivery

Accrual dashboard:
- warehouse_accrual_acks table (migration 2140) + acknowledge/unacknowledge
  endpoints; dashboard rows carry acknowledged/snoozeUntil, acked items sink
  and are skipped by the alert cron. Row menu: mark reviewed / snooze 3d / 7d /
  un-acknowledge; acked rows dimmed with a "Reviewed" badge.
- Fix zone weight occupancy: normalise inventory kg vs zone-capacity tonnes.

Handover (rode along, shared files):
- Require signer full name on delivery handover (signature optional);
  migration 2130 adds signer_name.

Portal delivery/docs (rode along, shared files):
- Approve-delivery name capture, booking-scoped GRN/release docs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Hagernesh
2026-07-14 09:35:21 +00:00
parent d9fe79e160
commit a367306565
18 changed files with 362 additions and 33 deletions

View File

@@ -0,0 +1,23 @@
import { MigrationInterface, QueryRunner } from "typeorm";
/**
* The person who signs off a handover must record their full name (a signature
* is optional, especially for self-haul). Stored per handover record.
*/
export class AddHandoverSignerName2130000000000 implements MigrationInterface {
name = "AddHandoverSignerName2130000000000";
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
ALTER TABLE freight.booking_handovers
ADD COLUMN IF NOT EXISTS signer_name varchar(160)
`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
ALTER TABLE freight.booking_handovers
DROP COLUMN IF EXISTS signer_name
`);
}
}

View File

@@ -0,0 +1,29 @@
import { MigrationInterface, QueryRunner } from "typeorm";
/**
* Accrual alert acknowledgements: ops can mark an in-warehouse item's fee
* accrual as reviewed (optionally snoozed until a date) so it stops nudging and
* drops down the accrual dashboard. One row per inventory item.
*/
export class CreateAccrualAcks2140000000000 implements MigrationInterface {
name = "CreateAccrualAcks2140000000000";
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
CREATE TABLE IF NOT EXISTS freight.warehouse_accrual_acks (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
inventory_id uuid NOT NULL UNIQUE,
acknowledged_by uuid,
acknowledged_at timestamptz NOT NULL DEFAULT now(),
snooze_until timestamptz,
note text,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now()
)
`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP TABLE IF EXISTS freight.warehouse_accrual_acks`);
}
}