mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
BuyerDetails Country/Region/City/Wereda now resolve from the Ministry's own EIMS_COUNTRY_REGION_VW master instead of the EIMS_BUYER_*_CODES env maps and the ethiopia-geo-codes table. Both invented their codes and looked names up globally, so KERSA/GORO/BABILE/BURE — each present in several zones with different LOCALITY_NOs — could be filed against the wrong jurisdiction. Resolution is hierarchical and refuses to guess: an unknown or ambiguous address raises a local validation error naming the level that failed, and never selects the first matching row. Spelling differences between EDR and MoR live in a reviewed, parent-scoped alias layer; the dataset itself stays verbatim so it remains traceable to the Ministry sheet. Resolution now runs before the counter reservation in both the single and bulk paths, so a bad company address no longer burns an EIMS sequence number. Adds eims:import-locations to regenerate the dataset from a future workbook, reporting duplicate rows and same-hierarchy code conflicts.
88 lines
2.7 KiB
TypeScript
88 lines
2.7 KiB
TypeScript
import { EimsConfig, EimsInvoiceConfig } from "../../config/eims.config";
|
|
|
|
/**
|
|
* Fixtures shared by the EIMS specs.
|
|
*
|
|
* Deliberately not a `.spec.ts`: importing fixtures from a spec file makes jest execute that
|
|
* file's `describe` blocks inside every importing suite, so the same tests run — and report —
|
|
* twice.
|
|
*/
|
|
|
|
export const EIMS_SYSTEM_NUMBER = "B0360154BA";
|
|
export const EIMS_SYSTEM_TYPE = "SYS";
|
|
|
|
export const eimsInvoiceConfig = (over: Partial<EimsInvoiceConfig> = {}): EimsInvoiceConfig => ({
|
|
sellerLegalName: "Ethio-Djibouti Railway S.C.",
|
|
sellerVatNumber: "0000000000",
|
|
sellerPhone: "0911223344",
|
|
sellerEmail: "finance@example.et",
|
|
sellerRegion: "13",
|
|
sellerWereda: "574",
|
|
sellerCity: null,
|
|
sellerSubCity: null,
|
|
sellerHouseNumber: null,
|
|
sellerLocality: null,
|
|
taxCode: "VAT15",
|
|
taxRatePercent: 15,
|
|
exciseTaxValue: 0,
|
|
incomeWithholdValue: 0,
|
|
transactionWithholdValue: 0,
|
|
transactionType: "B2B",
|
|
natureOfSupplies: "Service",
|
|
paymentMode: "CASH",
|
|
paymentTerm: "IMMIDIATE",
|
|
unitDefault: "PCS",
|
|
taxCodeByChargeType: {},
|
|
taxRateByChargeType: {},
|
|
exciseByChargeType: {},
|
|
discountByChargeType: {},
|
|
cashierName: null,
|
|
salesPersonName: null,
|
|
buyerIdType: null,
|
|
buyerIdNumber: null,
|
|
...over,
|
|
});
|
|
|
|
export const eimsConfig = (over: Partial<EimsConfig> = {}): EimsConfig => ({
|
|
enabled: true,
|
|
baseUrl: "https://core.mor.gov.et",
|
|
clientId: "cid",
|
|
clientSecret: "super-secret-value",
|
|
apiKey: "super-secret-apikey",
|
|
tin: "0000034558",
|
|
systemNumber: EIMS_SYSTEM_NUMBER,
|
|
systemType: EIMS_SYSTEM_TYPE,
|
|
privateKeyPath: "/dev/null",
|
|
certificatePath: "/dev/null",
|
|
privateKeyBase64: "",
|
|
certificateBase64: "",
|
|
privateKeyPem: "",
|
|
certificatePem: "",
|
|
httpTimeoutMs: 30_000,
|
|
tokenSkewMs: 45_000,
|
|
autoSubmit: false,
|
|
autoSubmitCron: "0 */5 * * * *",
|
|
autoSubmitMaxAgeDays: 3,
|
|
invoice: eimsInvoiceConfig(),
|
|
...over,
|
|
});
|
|
|
|
/**
|
|
* A structurally real access token. MoR stamps the source-system identity into the JWT payload and
|
|
* `EimsAuthService` reads it from there; only the payload segment is meaningful, since the token is
|
|
* never verified locally — it is MoR's, signed with MoR's key.
|
|
*
|
|
* Pass a claim as `undefined` to omit it (spreading beats `delete`, which the defaults would undo).
|
|
*/
|
|
export const eimsToken = (claims: Record<string, unknown> = {}): string => {
|
|
const payload = { systemNumber: EIMS_SYSTEM_NUMBER, systemType: EIMS_SYSTEM_TYPE, ...claims };
|
|
for (const [key, value] of Object.entries(payload)) {
|
|
if (value === undefined) delete (payload as Record<string, unknown>)[key];
|
|
}
|
|
return [
|
|
"eyJhbGciOiJSUzI1NiJ9",
|
|
Buffer.from(JSON.stringify(payload)).toString("base64url"),
|
|
"signature",
|
|
].join(".");
|
|
};
|