forked from Shared/esg
Introduce plate, chassis, and third-party car endpoints, a wall-clock inquiry deadline with transport-only retries, and ownership-safe no-match errors so another person's identity never leaks. Co-authored-by: Cursor <cursoragent@cursor.com>
150 lines
4.4 KiB
TypeScript
150 lines
4.4 KiB
TypeScript
import { Injectable } from '@nestjs/common';
|
|
import { assertCarPolicyOwnedBy } from '../../common/helpers/car-inquiry-safety.helper';
|
|
import { resolveThirdPartyCarPolicy } from '../../common/helpers/third-party-car-rules.helper';
|
|
import { InquiryType } from '../../common/enums/inquiry-type.enum';
|
|
import { ProviderEnvConfig } from '../../config/configuration';
|
|
import { LegacyInquiryPayload } from './legacy-api.provider.abstract';
|
|
import { CentInsurCarPolicyClient } from './centinsur-car-policy.client';
|
|
|
|
export interface CarPlatePayload extends LegacyInquiryPayload {
|
|
nationalCode?: string;
|
|
plk1?: string;
|
|
plk2?: string;
|
|
plk3?: string;
|
|
plksrl?: string;
|
|
}
|
|
|
|
export interface CarChassisPayload extends LegacyInquiryPayload {
|
|
nationalCode?: string;
|
|
chassisNo?: string;
|
|
}
|
|
|
|
type ErrorFormatter = (
|
|
providerMessage?: string,
|
|
providerCode?: string,
|
|
fallbackMessage?: string,
|
|
extras?: Record<string, unknown>,
|
|
) => Error;
|
|
|
|
@Injectable()
|
|
export class CentInsurCarProviderSupport {
|
|
constructor(private readonly carPolicyClient: CentInsurCarPolicyClient) {}
|
|
|
|
async inquireCarByPlate(
|
|
config: ProviderEnvConfig,
|
|
payload: CarPlatePayload,
|
|
formatError: ErrorFormatter,
|
|
): Promise<{ raw: unknown }> {
|
|
const nationalCode = this.getRequiredString(payload.nationalCode, 'nationalCode', formatError);
|
|
const plate = {
|
|
plk1: this.getRequiredString(payload.plk1, 'plk1', formatError),
|
|
plk2: this.getRequiredString(payload.plk2, 'plk2', formatError),
|
|
plk3: this.getRequiredString(payload.plk3, 'plk3', formatError),
|
|
plksrl: this.getRequiredString(payload.plksrl, 'plksrl', formatError),
|
|
};
|
|
|
|
const policy = await this.carPolicyClient.inquireByPlate(
|
|
config,
|
|
InquiryType.CAR_BY_PLATE,
|
|
plate,
|
|
);
|
|
|
|
assertCarPolicyOwnedBy(nationalCode, policy, formatError);
|
|
|
|
return {
|
|
raw: {
|
|
nationalCode,
|
|
...plate,
|
|
...policy,
|
|
},
|
|
};
|
|
}
|
|
|
|
async inquireCarByChassis(
|
|
config: ProviderEnvConfig,
|
|
payload: CarChassisPayload,
|
|
formatError: ErrorFormatter,
|
|
): Promise<{ raw: unknown }> {
|
|
const nationalCode = this.getRequiredString(payload.nationalCode, 'nationalCode', formatError);
|
|
const chassisNo = this.getRequiredString(payload.chassisNo, 'chassisNo', formatError);
|
|
const policy = await this.carPolicyClient.inquireByChassis(
|
|
config,
|
|
InquiryType.CAR_BY_CHASSIS,
|
|
chassisNo,
|
|
);
|
|
|
|
assertCarPolicyOwnedBy(nationalCode, policy, formatError);
|
|
|
|
return {
|
|
raw: {
|
|
nationalCode,
|
|
chassisNo,
|
|
...policy,
|
|
},
|
|
};
|
|
}
|
|
|
|
async inquireThirdPartyCar(
|
|
config: ProviderEnvConfig,
|
|
payload: CarPlatePayload,
|
|
formatError: ErrorFormatter,
|
|
): Promise<{ raw: unknown }> {
|
|
const input = {
|
|
nationalCode: this.getRequiredString(payload.nationalCode, 'nationalCode', formatError),
|
|
plk1: this.getRequiredString(payload.plk1, 'plk1', formatError),
|
|
plk2: this.getRequiredString(payload.plk2, 'plk2', formatError),
|
|
plk3: this.getRequiredString(payload.plk3, 'plk3', formatError),
|
|
plksrl: this.getRequiredString(payload.plksrl, 'plksrl', formatError),
|
|
};
|
|
|
|
const resolved = await resolveThirdPartyCarPolicy(input, {
|
|
byPlate: async () =>
|
|
this.carPolicyClient.inquireByPlate(config, InquiryType.THIRD_PARTY_CAR, input),
|
|
byNationalCode: async () =>
|
|
this.carPolicyClient.inquireByNationalCode(
|
|
config,
|
|
InquiryType.THIRD_PARTY_CAR,
|
|
input.nationalCode,
|
|
),
|
|
});
|
|
|
|
if (!resolved) {
|
|
throw formatError(
|
|
undefined,
|
|
'INQUIRY_NO_MATCH',
|
|
'Inquiry returned no matching result',
|
|
);
|
|
}
|
|
|
|
return {
|
|
raw: {
|
|
...input,
|
|
...resolved.policy.raw,
|
|
selection: {
|
|
sources: resolved.sources,
|
|
vehicleGroup: resolved.policy.vehicleGroup,
|
|
isActive: resolved.policy.isActive,
|
|
isZeroKm: resolved.policy.isZeroKm,
|
|
},
|
|
},
|
|
};
|
|
}
|
|
|
|
hasCarPolicyConfig(config: ProviderEnvConfig, inquiryType: InquiryType): boolean {
|
|
return this.carPolicyClient.hasSoapCredentials(
|
|
this.carPolicyClient.resolveInquiryConfig(config, inquiryType, InquiryType.POLICY_BY_PLATE),
|
|
);
|
|
}
|
|
|
|
private getRequiredString(
|
|
value: unknown,
|
|
fieldName: string,
|
|
formatError: ErrorFormatter,
|
|
): string {
|
|
if (typeof value !== 'string' || !value.trim()) {
|
|
throw formatError(undefined, undefined, `${fieldName} is required`);
|
|
}
|
|
return value.trim();
|
|
}
|
|
}
|