Commit Graph

24 Commits

Author SHA1 Message Date
Nathnael
d261d6ea7c style: inter module integration 2026-08-13 06:54:54 +00:00
Nathnael
068ee49a9f style: invoice 2026-08-12 09:33:21 +00:00
Nathnael
02d9debe1d refactor(freight-backoffice): review one identity and the eTrade owner match
- Replace the general-manager rows with owner rows across the customer
  detail, contract cards, types and service mappings.
- The identity card names its subject ("Verifies for this company") and shows
  whether the asserted owner matches the manager on the eTrade licence:
  amber when it does not, green when it does, dimmed when eTrade named
  nobody. Advisory only, since the comparison is a fuzzy transliteration
  match.
- A missing delegation letter now keys on poaDeclared === "yes".
- Keep the three general-manager labels in the change-request label map so
  historical requests still render readable field names.
2026-08-11 11:54:05 +00:00
Nathnael
7a32bb95ff refactor: rm company profile 2026-08-08 15:06:46 +00:00
Nathnael
c9bb105e94 feat: add nationality indicator to the customer 2026-08-07 12:54:00 +00:00
Marshal
b7dcc1bf0a feat(billing): add PAYMENT_PROCESSING invoice status on payment success redirect (all except CBE bill) 2026-08-05 12:59:37 +00:00
Nathnael
4f81a0bbb8 feat(freight): non-terminal change-request review + unified customer timeline
Backoffice can now "Request changes" on a pending settings change
request without rejecting it outright: a new ChangesRequested status
keeps the row open so the customer's next edit appends into the same
request instead of starting a fresh cycle, and the reviewer's note
persists across that round instead of being cleared on resubmit.

Version History and Review History (previously two separate,
differently-shaped lists) are merged into one chronological timeline
under a new History tab, including document changes shown as a real
previous-vs-current diff (both files openable).

Bug fixes surfaced while wiring this up:
- Replacing a single-file document slot left the old file live
  alongside the new one instead of retiring it (customer settings +
  onboarding uploads).
- The "previous" file in a document diff 404'd once superseded —
  the preview route now also matches soft-deleted records.
- A document replace was recorded twice in the timeline (once at
  upload, once again at change-request approval).
2026-07-31 14:12:30 +00:00
Nathnael
7c5d96795c feat(freight): track onboarding-phase edit history for companies
Ticket #238 — pre-approval edits and document uploads write straight
to the live company row with no approval gate and, until now, no
trace. Adds an append-only company_revisions log (diffed field
changes, document uploads) recorded from updateProfile and
uploadCompanyDocuments, exposed via GET /companies/:id/revisions and
shown as "Version history" on the backoffice customer detail page.
2026-07-31 11:45:09 +00:00
Nathnael
848c0d7768 fix: customer settings fix 2026-07-29 14:30:35 +00:00
Nathnael
dcc94643d0 feat(companies): enforce customers:* permissions on customer endpoints
The customers:* keys were seeded and present in the backoffice constants but
enforced nowhere except reset-password. Customer CRUD sat behind the coarse
edr_freight_app:admin umbrella, and every company read endpoint was unguarded.

Two routes could not be gated on the route alone, because the authority they
need depends on the request BODY, not the path:

  - PATCH /companies/:id carries `status` (UpdateCompanyDto extends
    PartialType(CreateCompanyDto)), so it both edits fields and blacklists.
  - PATCH /company-profiles/:profileId/status is approve, reject, suspend and
    blacklist on one route.

Both now take a one-of route guard and assert per-status against a shared
STATUS_PERM map: approving/reactivating needs customers:verify, suspending or
blacklisting needs customers:deactivate. PATCH /companies/:id additionally
requires customers:update when any non-status field is present, so a caller
holding only deactivate cannot rename a company. The backoffice mirrors the
same map so no button is offered that the server would reject.

GET /companies/:companyId/documents is left authenticated-only with the split
in the handler: it is dual-audience. The portal reads its own documents during
onboarding, and the contract-request detail page (gated on contracts:view)
reads the applicant's. Gating it on customers:view alone would have 403'd
customers on their own documents and blanked the contract reviewer's panel.

The two by-company customer-view reads take a one-of guard for the same reason
— otherwise a staffer granted only customers:view gets a detail page whose tabs
403 individually.

Frontend: the customers routes were sidebar-filtered but not wrapped in
RequirePermission, so direct URL navigation rendered them for anyone.

Verified: freight-api type-check clean; backoffice type-check unchanged from
HEAD (pre-existing errors only); 25 tests pass across the companies and
freight-permission suites. Not exercised against a running API.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 13:48:42 +00:00
Nathnael
649316070d fix(otp): fall back to email for foreign phone numbers
The SMS gateway is domestic-only, but OTP sends fanned out to any phone
on the account - a foreign number meant a code queued into the void
while the response claimed success. isDomesticPhone (+2519/+2517 E.164)
now gates SMS: dual-channel sends with a foreign phone go email-only
(the phone stays on the row so verify still matches it), and a
phone-only foreign target still tries SMS as the only route. The
staff-triggered reset exposes phoneIsDomestic so the backoffice disables
the SMS channel with an explanation, and the API refuses the channel
directly for foreign numbers.

EDRFREIGHT-186
2026-07-21 09:09:45 +00:00
Nathnael
c8f932f5d5 feat(companies): require and deliver a staff message on suspend/reactivate
Staff could suspend or reactivate a customer role with one silent click:
no reason captured, nothing stored, and the customer was never told.
The API now rejects a suspend or reactivate without a non-empty note,
keeps the note in reviewNote while suspended, and sends the customer an
SMS/email/in-app notification quoting the staff message. In the
backoffice the reject-note modal is generalised into a decision modal
shared by reject, suspend and reactivate, so all three force a message.

EDRFREIGHT-188
2026-07-21 09:09:15 +00:00
Nathnael
fd5aedcec7 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.
2026-07-21 07:34:40 +00:00
Nathnael
6420c72e89 feat(auth): implement staff-triggered password-reset links 2026-07-20 11:20:50 +00:00
Marshal
221c49fcda fix issue 2026-07-17 11:38:54 +00:00
Nathnael
ef74bc442a fix: prevent the backoffice from approve the user before he submits 2026-07-17 08:54:24 +00:00
Nathnael
e5fce529fe feat: add poa to the changes approval 2026-07-10 08:45:39 +00:00
Nathnael
e04b513b8f feat: password reset flow 2026-07-09 08:50:08 +00:00
Nathnael
8947ab8614 feat: fix the settings preview for the business licence and changes request to the approval 2026-07-08 10:42:00 +00:00
Nathnael
3bc4514b04 feat: implemented the changes request to the company profile to backoffice 2026-07-08 08:07:10 +00:00
Marshal
f300600bfa changes 2026-07-07 12:28:47 +00:00
Nathnael
3925a11dd4 feat: add invoice to customer detail on backoffice 2026-07-03 07:21:19 +00:00
Nathnael
a6f3fd5643 feat: finish company profile in the backoffice 2026-06-23 06:45:29 +00:00
Nathnael
c6bc636495 feat(customers): implement customer management page with mock data
- Created CustomersPage component to display a list of companies with search and pagination features.
- Added mock data for companies, including various statuses and profiles.
- Implemented a service layer to simulate API calls for fetching company data, bookings, documents, and payments.
- Defined TypeScript types for company and related entities to ensure type safety.
- Integrated Mantine components for UI consistency and improved user experience.
2026-06-22 12:32:52 +00:00