feat(companies): attach an eTrade business to each company profile

A TIN holds many business licences split by activity — export of coffee,
freight forwarding, import of vehicles — but the company picked one for
its whole record, so every operational role shared it. Each profile now
names the business it actually operates as.

Stored on `company_profiles.etrade_business` as a snapshot (licence
number, trade name, activity, renewal) rather than a bare licence number,
so the portal and backoffice can show it without an eTrade round-trip —
that API is slow, serves a broken TLS chain and is regularly down. Not
unique: one business may legitimately back several roles.

The licence number is a client input, so it is never stored as sent —
`ETradeService.findBusinessOption` looks it up under the company's own
TIN and persists eTrade's record, which makes another company's licence
simply unfindable.

Choosing one is required wherever the customer adds a role with a TIN
already on file. The onboarding wizard is the exception by necessity: it
picks roles on its first step, before a TIN exists, so there is nothing
to choose from yet. There it is enforced through
`getOnboardingRequirements` instead — an unattached role is reported
outstanding and blocks submission — and the picker sits on the documents
step beside that role's licence upload.

Lifted entirely for a co-operative or investment-licence company: eTrade
holds no record for its TIN, so the requirement would be unsatisfiable.
This commit is contained in:
Nathnael
2026-08-27 09:29:15 +00:00
parent 1f5e6296b1
commit 604710bd25
26 changed files with 922 additions and 55 deletions

View File

@@ -383,3 +383,19 @@ export function expectProfileActive(companyName: string, type = "importer") {
expect(rows[0].company_status).to.eq("active");
});
}
/**
* Attach one of the TIN's eTrade businesses to a role, on the documents step.
*
* Which one does not matter to these flows — only that a company with an eTrade
* record cannot submit onboarding until every role names one. A co-operative or
* investor-licence company has no list, so its flows never call this.
*/
export function chooseRoleBusiness(role = "Importer") {
cy.contains("label", `Which business is your ${role} profile?`)
.parents(".mantine-InputWrapper-root")
.first()
.find("input")
.click();
cy.get("[role='option']").first().click();
}

View File

@@ -33,6 +33,7 @@ import {
vatNumber,
wizardClick,
SIGNUP_PASSWORD,
chooseRoleBusiness,
} from "./onboarding-utils";
const stamp = Date.now();
@@ -128,6 +129,7 @@ describe("onboarding — Ethiopian company, eTrade verified", { retries: 0 }, ()
cy.contains("Upload Importer Business license file(s)", {
timeout: 20000,
}).should("be.visible");
chooseRoleBusiness();
attachNextFile();
attachNextFile();
wizardClick("Submit for review");

View File

@@ -26,6 +26,7 @@ import {
signupIdentity,
wizardClick,
SIGNUP_PASSWORD,
chooseRoleBusiness,
} from "./onboarding-utils";
const stamp = Date.now();
@@ -133,6 +134,7 @@ describe("onboarding — switching back to eTrade registration", { retries: 0 },
cy.contains("Upload Importer Business license file(s)", {
timeout: 20000,
}).should("be.visible");
chooseRoleBusiness();
wizardClick("Submit for review");
cy.contains("You're all set", { timeout: 30000 }).should("be.visible");