mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-28 05:30:55 +00:00
Two review-workflow gaps for freight customer onboarding: Request for change per document. Backoffice can now flag a single uploaded document (company document, profile licence, or POA delegation letter) with a note the customer sees, instead of rejecting the whole role over it. Adds review_status/review_note/reviewed_by/reviewed_at to freight.files (migration AddFileReviewStatus, partial index for the gate), a POST documents/:fileId/request-change endpoint, the backoffice action + modal, and a portal banner/badge so the customer knows what to re-upload. Re-uploading clears the flag. Approving a role is blocked while any of its documents has an open correction; the gate check and the status write share a pessimistic write lock on the company row (as does the change-request write) so a correction can never slip in between the check and the profile going Active. Resubmission is visible to reviewers. When a customer resubmits a rejected role or amends a change request, backoffice staff are notified (allBackoffice inbox item, deep-linked to the customer) and the resubmission surfaces in a new "Pending changes" list view + KPI, since such companies are status = active and never matched the pending-approval filter.
50 lines
2.0 KiB
TypeScript
50 lines
2.0 KiB
TypeScript
import { MigrationInterface, QueryRunner } from 'typeorm';
|
|
|
|
/**
|
|
* Per-document review state, so a backoffice reviewer can request a correction
|
|
* on one specific onboarding document instead of rejecting the whole role.
|
|
*
|
|
* Until now `freight.files` carried no status at all: the `pending_add` /
|
|
* `pending_remove` badges the portal shows are derived by diffing live rows
|
|
* against an open company change request, which says nothing about whether a
|
|
* reviewer is happy with a given document. `review_status` is that missing
|
|
* verdict — NULL means never reviewed, which is the state every existing row
|
|
* correctly starts in, so no backfill is needed.
|
|
*
|
|
* The partial index serves the approval gate, which asks "does this company (or
|
|
* profile) still have any document with an open change request?" on every
|
|
* role-status write.
|
|
*/
|
|
export class AddFileReviewStatus2430000000000 implements MigrationInterface {
|
|
name = 'AddFileReviewStatus2430000000000';
|
|
|
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
await queryRunner.query(`
|
|
ALTER TABLE freight.files
|
|
ADD COLUMN IF NOT EXISTS review_status varchar(32) NULL,
|
|
ADD COLUMN IF NOT EXISTS review_note text NULL,
|
|
ADD COLUMN IF NOT EXISTS reviewed_by uuid NULL,
|
|
ADD COLUMN IF NOT EXISTS reviewed_at timestamptz NULL
|
|
`);
|
|
|
|
await queryRunner.query(`
|
|
CREATE INDEX IF NOT EXISTS "IDX_files_open_change_request"
|
|
ON freight.files (resource, resource_id)
|
|
WHERE review_status = 'change_requested' AND deleted_at IS NULL
|
|
`);
|
|
}
|
|
|
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
await queryRunner.query(
|
|
`DROP INDEX IF EXISTS freight."IDX_files_open_change_request"`,
|
|
);
|
|
await queryRunner.query(`
|
|
ALTER TABLE freight.files
|
|
DROP COLUMN IF EXISTS review_status,
|
|
DROP COLUMN IF EXISTS review_note,
|
|
DROP COLUMN IF EXISTS reviewed_by,
|
|
DROP COLUMN IF EXISTS reviewed_at
|
|
`);
|
|
}
|
|
}
|