Commit Graph

14 Commits

Author SHA1 Message Date
marshal
1eb9f10354 feat(companies): add Transit Agent service linked to transit-agent roster; forwarder/agent onboarding step, assigned-bookings tab, booking assignment + notify, drop agent validity window 2026-09-06 21:41:29 +00:00
Nathnael
cbcc9a02e6 fix: approval window 2026-08-18 12:44:02 +00:00
Nathnael
0f11d9518f feat(backoffice): flag customers whose registration was typed, not fetched
Two kinds of customer reach approval with a registration nobody checked: a
co-operative union or farm, which holds no trade licence, and a foreign
investor, whose licence comes from the Investment Commission rather than the
trade registry. Both were reviewed on screens that read exactly like an
eTrade-verified company's, with only a small Registration field naming the
difference.

They now carry an orange "Manual entry" badge in the customers list and beside
the company name, and their overview opens with an alert saying the name,
registration and address below are the customer's own statement — pointing the
reviewer at the paper that stands in for the licence (the co-operative
certificate, or the investment licence) before approving. Approval itself is
not blocked.
2026-08-18 08:45:38 +00:00
Nathnael
89cdc0ad06 style: ui fixes 2026-08-13 13:46: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
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
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
ef74bc442a fix: prevent the backoffice from approve the user before he submits 2026-07-17 08:54:24 +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