From 2a3a2316657e14a58b88aed7cf6e0dbb10ff4647 Mon Sep 17 00:00:00 2001 From: Nathnael Date: Wed, 12 Aug 2026 08:25:39 +0000 Subject: [PATCH 1/3] fix: auto select ethiopian when chosing the coop option --- .../src/components/onboarding/OnboardingWizardDialog.tsx | 3 ++- .../portal/src/pages/settings/NationalitySelect.tsx | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/edr-freight-web/portal/src/components/onboarding/OnboardingWizardDialog.tsx b/apps/edr-freight-web/portal/src/components/onboarding/OnboardingWizardDialog.tsx index 998f733da..d5a87a4ee 100644 --- a/apps/edr-freight-web/portal/src/components/onboarding/OnboardingWizardDialog.tsx +++ b/apps/edr-freight-web/portal/src/components/onboarding/OnboardingWizardDialog.tsx @@ -169,7 +169,8 @@ export default function OnboardingWizardDialog({ setCooperative(checked); if (checked) { setRoles((prev) => prev.filter((r) => r !== "freight_forwarder")); - setNationality((prev) => (prev === "foreign" ? "ethiopian" : prev)); + // Ethiopian is then the only answer left, so it is made rather than asked. + setNationality("ethiopian"); } }, []); const [documentFiles, setDocumentFiles] = useState< diff --git a/apps/edr-freight-web/portal/src/pages/settings/NationalitySelect.tsx b/apps/edr-freight-web/portal/src/pages/settings/NationalitySelect.tsx index 99569e748..3eb7fd87e 100644 --- a/apps/edr-freight-web/portal/src/pages/settings/NationalitySelect.tsx +++ b/apps/edr-freight-web/portal/src/pages/settings/NationalitySelect.tsx @@ -29,7 +29,11 @@ export default function NationalitySelect({ } selected={value === "ethiopian"} onClick={() => onChange("ethiopian")} From abeb296157e8f6dfe858bd187ae0a2ba48311c94 Mon Sep 17 00:00:00 2001 From: Nathnael Date: Wed, 12 Aug 2026 08:39:54 +0000 Subject: [PATCH 2/3] fix: file upload seeder --- .../src/seed/file-upload-settings.seeder.ts | 79 ++++++++++++------- 1 file changed, 51 insertions(+), 28 deletions(-) diff --git a/apps/edr-freight-api/src/seed/file-upload-settings.seeder.ts b/apps/edr-freight-api/src/seed/file-upload-settings.seeder.ts index 4f314453a..dd8f9bd20 100644 --- a/apps/edr-freight-api/src/seed/file-upload-settings.seeder.ts +++ b/apps/edr-freight-api/src/seed/file-upload-settings.seeder.ts @@ -1,6 +1,7 @@ import { Injectable, Logger } from "@nestjs/common"; import { DataSource } from "typeorm"; +import { FileUploadField } from "../modules/file-upload-settings/entities/file-upload-field.entity"; import { FileUploadSetting } from "../modules/file-upload-settings/entities/file-upload-setting.entity"; import { poaDelegationField } from "../modules/file-upload-settings/poa-delegation.constants"; @@ -165,10 +166,13 @@ const FOREIGN_ONBOARDING_FIELDS: OnboardingField[] = [ * actually produce is a backoffice decision, edited in the file-settings editor. */ const COOPERATIVE_ONBOARDING_FIELDS: OnboardingField[] = [ + // First on purpose: only the first field of a new set is seeded, and this is + // the paper that distinguishes a co-operative from every other company. { - fileKey: "tin_certificate", - fileLabel: "TIN Certificate", - helpText: "Verified against the TIN registry during registration.", + fileKey: "cooperative_registration_certificate", + fileLabel: "Co-operative Union / Farm Registration Certificate", + helpText: + "Certificate issued by the co-operative promotion agency that registered the union or farm.", isRequired: true, isMultiple: false, maxFiles: 1, @@ -177,10 +181,9 @@ const COOPERATIVE_ONBOARDING_FIELDS: OnboardingField[] = [ displayOrder: 1, }, { - fileKey: "cooperative_registration_certificate", - fileLabel: "Co-operative Union / Farm Registration Certificate", - helpText: - "Certificate issued by the co-operative promotion agency that registered the union or farm.", + fileKey: "tin_certificate", + fileLabel: "TIN Certificate", + helpText: "Verified against the TIN registry during registration.", isRequired: true, isMultiple: false, maxFiles: 1, @@ -662,16 +665,15 @@ export class FileUploadSettingsSeeder { async run() { const settingRepository = this.dataSource.getRepository(FileUploadSetting); - // Seed only into an empty table: any existing rows (including - // soft-deleted ones, which would still conflict on the unique `code`) - // mean the data is admin-managed, so leave it untouched. - const existing = await settingRepository.count({ withDeleted: true }); - if (existing > 0) { - this.logger.log( - `file_upload_settings already has ${existing} rows — skipping seed`, - ); - return; - } + // Seed per CODE, not "only into an empty table". An existing row is + // admin-managed and never touched — including a soft-deleted one, which + // means the set was removed on purpose (and would still conflict on the + // unique `code`). What the table-wide check got wrong is the other half: a + // set added to this file after the first boot could never reach a database + // that already held the others, so it existed in code and nowhere else. + const existingCodes = new Set( + (await settingRepository.find({ withDeleted: true })).map((s) => s.code), + ); const allSettings: Array< OnboardingDocumentSetting & { description: string } @@ -701,20 +703,41 @@ export class FileUploadSettingsSeeder { })), ]; - // Insert setting rows only — no FileUploadField rows. Fields start empty - // and are configured from the backoffice file-settings editor; the field - // definitions above are kept as reference defaults. - await settingRepository.insert( - allSettings.map((documentSetting) => ({ - code: documentSetting.code, - label: documentSetting.label, - description: documentSetting.description, - entity: documentSetting.entity, - })), + const missing = allSettings.filter((s) => !existingCodes.has(s.code)); + if (missing.length === 0) { + this.logger.log("file upload settings up to date — nothing to seed"); + return; + } + + const inserted = await settingRepository.save( + missing.map((documentSetting) => + settingRepository.create({ + code: documentSetting.code, + label: documentSetting.label, + description: documentSetting.description, + entity: documentSetting.entity, + }), + ), ); + // A brand-new set gets exactly ONE field: its first reference default. The + // rest of the list above stays documentation — what a set actually asks for + // is a backoffice decision, edited in the file-settings editor. Seeding one + // means a set is never born empty (an empty set silently requires nothing), + // while leaving the admin a single row to extend rather than a list to prune. + const fieldRepository = this.dataSource.getRepository(FileUploadField); + const firstFields = inserted.flatMap((setting) => { + const reference = missing.find((s) => s.code === setting.code)?.fields[0]; + return reference + ? [fieldRepository.create({ ...reference, settingId: setting.id })] + : []; + }); + if (firstFields.length > 0) await fieldRepository.save(firstFields); + this.logger.log( - `Seeded ${allSettings.length} file upload settings with empty fields`, + `Seeded ${missing.length} file upload settings (${firstFields.length} with a default field): ${missing + .map((s) => s.code) + .join(", ")}`, ); } } From 879f0b890da66ae1a828b0a7cabf4dd0f4309c00 Mon Sep 17 00:00:00 2001 From: Nathnael Date: Wed, 12 Aug 2026 08:42:16 +0000 Subject: [PATCH 3/3] fix: file size limit --- .../portal/src/components/onboarding/RoleLicenseStep.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/edr-freight-web/portal/src/components/onboarding/RoleLicenseStep.tsx b/apps/edr-freight-web/portal/src/components/onboarding/RoleLicenseStep.tsx index a485d40c1..8270bce74 100644 --- a/apps/edr-freight-web/portal/src/components/onboarding/RoleLicenseStep.tsx +++ b/apps/edr-freight-web/portal/src/components/onboarding/RoleLicenseStep.tsx @@ -50,7 +50,7 @@ function buildLicenseSetting( isMultiple: true, maxFiles: 10, allowedExtensions: ["pdf", "png", "jpg", "jpeg"], - maxSizeMb: 10, + maxSizeMb: 25, order: 1, }, ],