feat: add eTrade fields to company entity and onboarding process

- Added new fields to the Company entity: licenceNumber, statusDescription, dateRegistered, renewedFrom, renewalDate, renewedTo, region, zone, woreda, kebele, houseNo, and etradePhone.
- Updated onboarding wizard to include a new contact step and fetch company information from eTrade using TIN.
- Created ETradeInfo component to handle fetching and displaying eTrade data.
- Implemented ETradeService to interact with eTrade API and extract relevant company registration data.
- Added new DTOs for fetching eTrade data and handling responses.
- Updated CompanyProfileForm to integrate new fields and handle eTrade data.
- Created hooks for managing eTrade data fetching and error handling.
This commit is contained in:
Marshal
2026-06-20 10:27:41 +00:00
parent 4a0085ef57
commit 1f92a04ecf
19 changed files with 1088 additions and 75 deletions

View File

@@ -0,0 +1,102 @@
import { Injectable, BadRequestException } from "@nestjs/common";
import { HttpService } from "@nestjs/axios";
import { firstValueFrom } from "rxjs";
import {
ETradeCompanyInfo,
ETradeBusinessInfo,
CompanyRegistrationData,
} from "@edr/types";
@Injectable()
export class ETradeService {
private readonly baseUrl = "https://etrade.gov.et/api";
private readonly referer = "https://etrade.gov.et/business-license-checker";
constructor(private readonly httpService: HttpService) {}
async getCompanyInfoByTin(tin: string): Promise<ETradeCompanyInfo> {
const url = `${this.baseUrl}/Registration/GetRegistrationInfoByTin/${tin}/en`;
try {
const response = await firstValueFrom(
this.httpService.get<ETradeCompanyInfo>(url, {
headers: { Referer: this.referer },
}),
);
return response.data;
} catch (error: any) {
throw new BadRequestException(
`Failed to fetch company info from eTrade: ${error.message}`,
);
}
}
async getBusinessByLicenseNo(
licenseNo: string,
tin: string,
): Promise<ETradeBusinessInfo> {
const url = `${this.baseUrl}/BusinessMain/GetBusinessByLicenseNo`;
try {
const response = await firstValueFrom(
this.httpService.get<ETradeBusinessInfo>(url, {
params: {
LicenseNo: licenseNo,
Tin: tin,
Lang: "en",
},
headers: { Referer: this.referer },
}),
);
return response.data;
} catch (error: any) {
throw new BadRequestException(
`Failed to fetch business info from eTrade: ${error.message}`,
);
}
}
async resolveCompanyData(tin: string): Promise<{
companyInfo: ETradeCompanyInfo;
businessInfo: ETradeBusinessInfo | null;
}> {
const companyInfo = await this.getCompanyInfoByTin(tin);
if (!companyInfo.Businesses || companyInfo.Businesses.length === 0) {
return { companyInfo, businessInfo: null };
}
const latestBusiness = companyInfo.Businesses[0];
try {
const businessInfo = await this.getBusinessByLicenseNo(
latestBusiness.LicenceNumber,
tin,
);
return { companyInfo, businessInfo };
} catch {
return { companyInfo, businessInfo: null };
}
}
extractRegistrationData(
businessInfo: ETradeBusinessInfo,
): CompanyRegistrationData {
const primaryManager = businessInfo.AssociateShortInfos?.[0];
return {
licenceNumber: businessInfo.LicenceNumber,
statusDescription: businessInfo.StatusDescription,
dateRegistered: businessInfo.DateRegistered,
renewedFrom: businessInfo.RenewedFrom,
renewalDate: businessInfo.RenewalDate,
renewedTo: businessInfo.RenewedTo,
region: businessInfo.AddressInfo?.Region || "",
zone: businessInfo.AddressInfo?.Zone || "",
woreda: businessInfo.AddressInfo?.Woreda || "",
kebele: businessInfo.AddressInfo?.Kebele || "",
houseNo: businessInfo.AddressInfo?.HouseNo || "",
mobilePhone: businessInfo.AddressInfo?.MobilePhone || "",
regularPhone: businessInfo.AddressInfo?.RegularPhone || "",
managerName: primaryManager?.ManagerNameEng || "",
managerPhone: primaryManager?.RegularPhone || "",
};
}
}