feat(companies): per-document change requests and resubmission review queue

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.
This commit is contained in:
Nathnael
2026-07-21 07:34:40 +00:00
parent 1cfc0f0fa8
commit fd5aedcec7
22 changed files with 948 additions and 60 deletions

View File

@@ -2645,6 +2645,25 @@ export const api = {
],
),
/**
* Ask the customer to correct one document. Invalidates the documents list
* and the company itself, since an open request blocks role approval.
*/
requestDocumentChange: endpoint<
{ companyId: string; fileId: string; note: string },
CustomerDocument
>(
"customers",
"requestDocumentChange",
({ fileId, note }) =>
customersService.requestDocumentChange(fileId, note),
undefined,
({ companyId }) => [
QUERY_KEYS.CUSTOMERS.documents(companyId),
QUERY_KEYS.CUSTOMERS.byId(companyId),
],
),
setCompanyStatus: endpoint<{ companyId: string; status: string }, unknown>(
"customers",
"setCompanyStatus",

View File

@@ -164,4 +164,21 @@ export const customersService = {
)
.then((r) => r.data);
},
/**
* Ask the customer to correct one uploaded document. Narrower than rejecting
* the whole role: the customer keeps their other documents and only re-uploads
* this one, but the role cannot be approved until they do.
*/
requestDocumentChange(
fileId: string,
note: string,
): Promise<CustomerDocument> {
return apiClient
.post<CustomerDocument>(
URL_CONSTANTS.COMPANIES.DOCUMENT_REQUEST_CHANGE(fileId),
{ note },
)
.then((r) => r.data);
},
};