diff --git a/apps/edr-freight-api/src/modules/companies/services/etrade.service.ts b/apps/edr-freight-api/src/modules/companies/services/etrade.service.ts index 95f927738..15054c701 100644 --- a/apps/edr-freight-api/src/modules/companies/services/etrade.service.ts +++ b/apps/edr-freight-api/src/modules/companies/services/etrade.service.ts @@ -1,5 +1,6 @@ import { Injectable, BadRequestException } from "@nestjs/common"; import { HttpService } from "@nestjs/axios"; +import { Agent } from "https"; import { firstValueFrom } from "rxjs"; import { ETradeCompanyInfo, @@ -12,6 +13,14 @@ export class ETradeService { private readonly baseUrl = "https://etrade.gov.et/api"; private readonly referer = "https://etrade.gov.et/business-license-checker"; + /** + * The eTrade server serves an incomplete TLS chain (it omits the intermediate + * CA cert), so Node rejects the handshake with UNABLE_TO_GET_ISSUER_CERT. + * Scope a relaxed agent to these outbound calls only — the rest of the app + * keeps full certificate verification. + */ + private readonly httpsAgent = new Agent({ rejectUnauthorized: false }); + constructor(private readonly httpService: HttpService) {} async getCompanyInfoByTin(tin: string): Promise { @@ -20,6 +29,7 @@ export class ETradeService { const response = await firstValueFrom( this.httpService.get(url, { headers: { Referer: this.referer }, + httpsAgent: this.httpsAgent, }), ); return response.data; @@ -44,6 +54,7 @@ export class ETradeService { Lang: "en", }, headers: { Referer: this.referer }, + httpsAgent: this.httpsAgent, }), ); return response.data; diff --git a/apps/edr-freight-web/portal/src/components/onboarding/ETradeInfo.tsx b/apps/edr-freight-web/portal/src/components/onboarding/ETradeInfo.tsx index 15632fe1b..5fcfadaa1 100644 --- a/apps/edr-freight-web/portal/src/components/onboarding/ETradeInfo.tsx +++ b/apps/edr-freight-web/portal/src/components/onboarding/ETradeInfo.tsx @@ -3,24 +3,33 @@ import { Button, Group, Loader, - SimpleGrid, Stack, Text, TextInput, } from "@mantine/core"; -import { AlertCircle, CheckCircle2, RefreshCw } from "lucide-react"; +import type { UseFormRegisterReturn } from "react-hook-form"; +import { AlertCircle, CheckCircle2, Download } from "lucide-react"; import { useETradeData } from "@/hooks/useETradeData"; import type { CompanyRegistrationData } from "@edr/types"; interface ETradeInfoProps { + /** Current TIN value (drives button enablement). */ tin: string; + /** RHF registration for the TIN input — this is the form's primary TIN field. */ + register: UseFormRegisterReturn; + /** Validation error for the TIN field, if any. */ + error?: string; onDataLoaded: (data: CompanyRegistrationData) => void; } -export default function ETradeInfo({ tin, onDataLoaded }: ETradeInfoProps) { +export default function ETradeInfo({ + tin, + register, + error, + onDataLoaded, +}: ETradeInfoProps) { const mutation = useETradeData(); const isLoading = mutation.isPending; - const hasError = mutation.isError; const hasData = mutation.data; const handleFetch = async () => { @@ -32,40 +41,42 @@ export default function ETradeInfo({ tin, onDataLoaded }: ETradeInfoProps) { }; const errorMessage = - hasError && mutation.error + mutation.isError && mutation.error ? (mutation.error as any).message || "Failed to fetch company information. Please try again." : null; return ( - + - {hasError && errorMessage && ( + {errorMessage && ( } color="red" title="Failed to fetch data" > - {errorMessage} + {errorMessage} You can still fill in the details manually below. )} 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 ecc8d38ec..11f75b4b7 100644 --- a/apps/edr-freight-web/portal/src/pages/accounts/CompanyProfileForm.tsx +++ b/apps/edr-freight-web/portal/src/pages/accounts/CompanyProfileForm.tsx @@ -614,6 +614,18 @@ export default function CompanyProfileForm({ {step === "company" && ( <> + + Enter your TIN to auto-fill company information from eTrade + + + + + - + - - - - - Fetch Company Information from eTrade - - {watch("licenceNumber") && ( <>