mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-09 07:08:18 +00:00
feat(companies): onboard co-operative unions and farms
They hold a TIN but no business licence, so there is no eTrade record to look their registration up in. A checkbox on the first wizard step marks them, and everything that assumed a trade licence bends around it: - The company step replaces the eTrade lookup with typed registration details — name, region, zone, woreda, kebele, house number — required exactly because they are now on screen. applyEtradeSourcedFields skips the lookup rather than failing it, so what the customer sends is what is stored. - No freight-forwarder role. Forwarding is licensed work, so the option is not offered, and the API refuses it at start-onboarding and at every later role-add rather than letting approval fail on a document they cannot produce. - No per-role business-licence upload, client-side or in the completion gate. - Their own document set (company_onboarding_documents_cooperative) merges on top of the nationality one, admin-managed like every other set. Nationality wins a fileKey collision so no slot renders twice, and the DARS paper is not injected into it — the set it merges onto already carries one. - The owner is typed in full; with no eTrade manager on file the licence comparison reports "nothing to compare against", which backoffice now explains rather than leaving as a bare dash. Stored as an attributes flag, not a column: everything it changes is behavioural, and nothing queries or joins on it.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Checkbox,
|
||||
Group,
|
||||
Modal,
|
||||
ScrollArea,
|
||||
@@ -164,6 +165,15 @@ export default function OnboardingWizardDialog({
|
||||
const [roles, setRoles] = useState<string[]>(
|
||||
existingProfiles.map((p) => p.type),
|
||||
);
|
||||
const [cooperative, setCooperative] = useState<boolean>(
|
||||
company?.company?.attributes?.cooperative === true,
|
||||
);
|
||||
// Ticking the box drops a role the company can no longer hold, rather than
|
||||
// letting Continue fail on a selection the API refuses.
|
||||
const handleCooperativeChange = useCallback((checked: boolean) => {
|
||||
setCooperative(checked);
|
||||
if (checked) setRoles((prev) => prev.filter((r) => r !== "freight_forwarder"));
|
||||
}, []);
|
||||
const [documentFiles, setDocumentFiles] = useState<
|
||||
Record<string, File | File[] | null>
|
||||
>({});
|
||||
@@ -214,6 +224,7 @@ export default function OnboardingWizardDialog({
|
||||
companyType: string;
|
||||
roles: ProfileTypeValue[];
|
||||
nationality?: CompanyNationality;
|
||||
cooperative?: boolean;
|
||||
}) => api.companies.startOnboarding.call(vars),
|
||||
onSuccess: async () => {
|
||||
// Nationality drives the server-resolved identity requirements (Fayda vs
|
||||
@@ -296,6 +307,7 @@ export default function OnboardingWizardDialog({
|
||||
resumedRef.current = true;
|
||||
setRoles(existingProfiles.map((p) => p.type));
|
||||
setNationality(savedNationality);
|
||||
setCooperative(company?.company?.attributes?.cooperative === true);
|
||||
// Resume into the form only when profiles exist; otherwise send the user to
|
||||
// role selection so the missing operational profiles get created.
|
||||
setPhase(hasOperationalProfiles ? "form" : "nationality-role");
|
||||
@@ -310,8 +322,9 @@ export default function OnboardingWizardDialog({
|
||||
companyType: companyTypeForRoles(roles),
|
||||
roles: roles as ProfileTypeValue[],
|
||||
nationality: nationality ?? undefined,
|
||||
cooperative,
|
||||
});
|
||||
}, [roles, nationality, startMutation]);
|
||||
}, [roles, nationality, cooperative, startMutation]);
|
||||
|
||||
// Back from the form's first step returns to nationality/role selection.
|
||||
// Safe to re-enter: startOnboarding is idempotent — it reuses the existing
|
||||
@@ -463,6 +476,15 @@ export default function OnboardingWizardDialog({
|
||||
// mandatory for an Ethiopian company; a foreign one may instead type a
|
||||
// passport number for the same person.
|
||||
identity: requirementsQuery.data?.identity,
|
||||
// Server-confirmed, not the local checkbox: the flag is only real once
|
||||
// startOnboarding has persisted it, and the form's whole company step
|
||||
// branches on it.
|
||||
cooperative: requirementsQuery.data?.cooperative ?? cooperative,
|
||||
extraDocumentSettingCode:
|
||||
requirementsQuery.data?.cooperativeDocumentSettingCode ?? null,
|
||||
// A freight forwarder cannot answer the power-of-attorney question — the
|
||||
// API forces "yes" — so the step offers no way to change it.
|
||||
declarationLocked: requirementsQuery.data?.poa?.locked ?? false,
|
||||
onIdentityChange: () => {
|
||||
void profileQuery.refetch();
|
||||
void requirementsQuery.refetch();
|
||||
@@ -530,6 +552,16 @@ export default function OnboardingWizardDialog({
|
||||
onChange={setNationality}
|
||||
embedded
|
||||
/>
|
||||
{/* A co-operative union or farm registers on a TIN alone. It
|
||||
changes what the next step asks for (typed registration, no
|
||||
eTrade lookup), which documents apply, and which roles are on
|
||||
offer — so it is answered here, alongside the other two. */}
|
||||
<Checkbox
|
||||
checked={cooperative}
|
||||
onChange={(e) => handleCooperativeChange(e.currentTarget.checked)}
|
||||
label="We're a co-operative union or farm"
|
||||
description="For members with a TIN but no business licence. You'll type your registration details instead of us pulling them from eTrade, and upload your co-operative papers in place of a trade licence."
|
||||
/>
|
||||
<Text fw={600} size="lg" c="edr-text">
|
||||
What does your company do?(multiple)
|
||||
</Text>
|
||||
@@ -537,6 +569,9 @@ export default function OnboardingWizardDialog({
|
||||
value={roles}
|
||||
onChange={setRoles}
|
||||
embedded
|
||||
// Forwarding is licensed work — a co-op holds no licence, so
|
||||
// the role is not offered rather than refused later.
|
||||
excludeTypes={cooperative ? ["freight_forwarder"] : undefined}
|
||||
/>
|
||||
{startError && (
|
||||
<Text size="sm" c="red">
|
||||
|
||||
Reference in New Issue
Block a user