diff --git a/apps/edr-freight-api/src/modules/billing/billing.service.ts b/apps/edr-freight-api/src/modules/billing/billing.service.ts index 8ede56f69..88ef92b3d 100644 --- a/apps/edr-freight-api/src/modules/billing/billing.service.ts +++ b/apps/edr-freight-api/src/modules/billing/billing.service.ts @@ -1130,20 +1130,20 @@ export class BillingService { // An OTP intent (CAC Bank) is NOT paid yet — the payer still has to enter the // code — so the demo shortcut must never fire for it. Same for CBE_BILL: its // bill must stay open until CBE actually settles it via /cbe/payment. - if ( - !result.immediateSuccess && - result.response.clientAction?.type !== "COLLECT_OTP" && - opts.method !== "CBE_BILL" - ) { - await this.payment.handlePaymentEvent({ - eventType: "payment.succeeded", - eventId: `demo-${result.intentId}`, - referenceId: invoice.sourceId, - intentId: result.intentId, - providerTxnId: result.providerTxnId, - paidAt: (result.paidAt ?? new Date()).toISOString(), - }); - } + // if ( + // !result.immediateSuccess && + // result.response.clientAction?.type !== "COLLECT_OTP" && + // opts.method !== "CBE_BILL" + // ) { + // await this.payment.handlePaymentEvent({ + // eventType: "payment.succeeded", + // eventId: `demo-${result.intentId}`, + // referenceId: invoice.sourceId, + // intentId: result.intentId, + // providerTxnId: result.providerTxnId, + // paidAt: (result.paidAt ?? new Date()).toISOString(), + // }); + // } if (result.immediateSuccess) { await this.settleByPaymentId( diff --git a/apps/edr-freight-api/src/modules/payment/payment.service.ts b/apps/edr-freight-api/src/modules/payment/payment.service.ts index 0f628e39c..985b4f53f 100644 --- a/apps/edr-freight-api/src/modules/payment/payment.service.ts +++ b/apps/edr-freight-api/src/modules/payment/payment.service.ts @@ -232,10 +232,15 @@ export class PaymentService { referenceType: PaymentReferenceType.SHIPMENT, referenceId: input.referenceId, orderRef: input.orderRef, - // amountMinor: input.amountMinor, // CBE_BILL must carry the REAL amount: /cbe/payment verifies what the customer was - // debited against the intent amount, so the 1-birr dev shortcut would break it. - amountMinor: isCbeBill ? input.amountMinor : 1, + // debited against the intent amount, so the dev shortcut would break it. + // CAC bank rejects amounts below 10 (DJF bounds 10–100,000), so its dev + // shortcut floor is 10, not 1. + amountMinor: isCbeBill + ? input.amountMinor + : input.method === ProviderMethod.CAC_BANK + ? 10 + : 1, currency: input.currency, provider: input.method as ProviderMethod, platform: input.platform, diff --git a/apps/edr-freight-web/portal/src/pages/accounts/CompanyProfileForm.tsx b/apps/edr-freight-web/portal/src/pages/accounts/CompanyProfileForm.tsx index b12fb19eb..0dc02eaa4 100644 --- a/apps/edr-freight-web/portal/src/pages/accounts/CompanyProfileForm.tsx +++ b/apps/edr-freight-web/portal/src/pages/accounts/CompanyProfileForm.tsx @@ -197,6 +197,7 @@ export default function CompanyProfileForm({ companyEmail: "", companyPhone: "", companyAddress: "", + etradePhone: "", tinNumber: "", vatNumber: "", ownerPassportNumber: "", @@ -279,6 +280,14 @@ export default function CompanyProfileForm({ // setting region/zone/woreda/kebele/houseNo above is enough — no need to // compose it here. companyPhone is derived below (identity → eTrade → // account), not set directly here. + // etradePhone is the raw number eTrade returned for this TIN — kept as its + // own field (distinct from companyPhone, which prefers the Fayda-verified + // owner's phone) so the backend's "matches eTrade's current record" check + // always compares against what eTrade actually said, not the owner's phone. + setValue( + "etradePhone", + data.managerPhone || data.regularPhone || data.mobilePhone, + ); setEtradeOwner({ name: data.managerName, @@ -303,6 +312,7 @@ export default function CompanyProfileForm({ setValue("woreda", ""); setValue("kebele", ""); setValue("houseNo", ""); + setValue("etradePhone", ""); setEtradeOwner(null); }; diff --git a/apps/edr-freight-web/portal/src/pages/accounts/companyProfileForm/helpers.ts b/apps/edr-freight-web/portal/src/pages/accounts/companyProfileForm/helpers.ts index f1a9f4301..a3aad0ee2 100644 --- a/apps/edr-freight-web/portal/src/pages/accounts/companyProfileForm/helpers.ts +++ b/apps/edr-freight-web/portal/src/pages/accounts/companyProfileForm/helpers.ts @@ -70,7 +70,7 @@ export function stepPayload( woreda: d.woreda, kebele: d.kebele, houseNo: d.houseNo, - etradePhone: d.companyPhone, + etradePhone: d.etradePhone, }; case "personnel": return { @@ -101,6 +101,7 @@ export function toFormValues(p: ProfileResponse): FormData { companyEmail: p.companyEmail ?? "", companyPhone: p.companyPhone ?? "", companyAddress: p.companyAddress ?? "", + etradePhone: p.etradePhone ?? "", tinNumber: tin, vatNumber: p.vatNumber ?? "", ownerPassportNumber: p.identity?.owner.passportNumber ?? "", diff --git a/apps/edr-freight-web/portal/src/pages/accounts/companyProfileForm/schema.ts b/apps/edr-freight-web/portal/src/pages/accounts/companyProfileForm/schema.ts index 2cd06ef8f..e2842dbe6 100644 --- a/apps/edr-freight-web/portal/src/pages/accounts/companyProfileForm/schema.ts +++ b/apps/edr-freight-web/portal/src/pages/accounts/companyProfileForm/schema.ts @@ -21,6 +21,10 @@ export const onboardingSchema = z.object({ // Derived from the eTrade address parts (kebele/woreda/zone/region); no // standalone input — the granular fields live in the registration section. companyAddress: z.string().optional(), + // Raw phone from the eTrade lookup itself — kept separate from companyPhone + // (which shows the Fayda-verified owner's phone once verified) so the two + // can diverge without the backend's eTrade-authenticity check misfiring. + etradePhone: z.string().optional(), tinNumber: z.string().regex(/^\d{10}$/, "TIN must be exactly 10 digits"), vatNumber: z .string() @@ -124,6 +128,7 @@ export const stepFields: Record = { "companyEmail", "companyPhone", "companyAddress", + "etradePhone", "tinNumber", "vatNumber", "ownerPassportNumber",