final update on moallm client

This commit is contained in:
2026-06-15 10:23:00 +03:30
parent fac6142483
commit 1b7f678538
17 changed files with 394 additions and 70 deletions

View File

@@ -0,0 +1,72 @@
import { InquiryType } from '../enums/inquiry-type.enum';
export interface CentInsurApiResponse {
IsSucceed?: boolean;
Result?: {
Result?: boolean;
ErrorMessage?: string | null;
[key: string]: unknown;
};
TrackingCode?: string;
message?: string;
code?: string;
success?: boolean;
}
export interface CentInsurProviderError {
message: string;
code: string;
providerTrackingCode?: string;
}
function getNoMatchMessage(inquiryType?: InquiryType): string {
switch (inquiryType) {
case InquiryType.REAL_ESTATE:
return 'No property ownership found for the provided national code and postal code';
default:
return 'Inquiry returned no matching result';
}
}
export function getCentInsurProviderError(
body: CentInsurApiResponse,
inquiryType?: InquiryType,
): CentInsurProviderError | null {
if (!('IsSucceed' in body)) {
return null;
}
const providerTrackingCode = body.TrackingCode?.trim() || undefined;
if (body.IsSucceed === false) {
return {
message: body.Result?.ErrorMessage?.trim() || 'Request failed',
code: 'API_ERROR',
providerTrackingCode,
};
}
if (body.Result?.Result === false) {
return {
message: body.Result?.ErrorMessage?.trim() || getNoMatchMessage(inquiryType),
code: 'INQUIRY_NO_MATCH',
providerTrackingCode,
};
}
return null;
}
export function describeCentInsurResponse(body: CentInsurApiResponse): string {
const innerResult =
body.Result && 'Result' in body.Result ? String(body.Result.Result) : 'undefined';
return [
`IsSucceed=${String(body.IsSucceed)}`,
`Result.Result=${innerResult}`,
`ErrorMessage=${body.Result?.ErrorMessage ?? 'none'}`,
body.TrackingCode ? `TrackingCode=${body.TrackingCode}` : null,
]
.filter(Boolean)
.join(' | ');
}

View File

@@ -0,0 +1,32 @@
import { BaseInquiryResponseDto } from '../dto/base-inquiry-response.dto';
import { NormalizedErrorDto } from '../dto/normalized-error.dto';
export function buildInquiryResponse<T = Record<string, unknown>>(params: {
success: boolean;
provider: string;
trackingCode: string;
message: string;
duration: number;
data?: T | null;
error?: NormalizedErrorDto | null;
}): BaseInquiryResponseDto<T> {
return {
success: params.success,
provider: params.provider,
trackingCode: params.trackingCode,
message: params.message,
duration: params.duration,
data: params.success ? (params.data ?? null) : null,
error: params.success ? null : (params.error ?? null),
};
}
export function normalizeInquiryResponse<T = Record<string, unknown>>(
response: BaseInquiryResponseDto<T>,
): BaseInquiryResponseDto<T> {
return {
...response,
data: response.success ? (response.data ?? null) : null,
error: response.success ? null : (response.error ?? null),
};
}

View File

@@ -0,0 +1,124 @@
function decodeXml(value: string): string {
return value
.replace(/&apos;/g, "'")
.replace(/&quot;/g, '"')
.replace(/&gt;/g, '>')
.replace(/&lt;/g, '<')
.replace(/&amp;/g, '&');
}
function normalizeSoapTextValue(value: string): string {
if (/i:nil\s*=\s*["']true["']/i.test(value)) {
return '';
}
const nestedStrings = [
...value.matchAll(/<(?:[\w]+:)?string[^>]*>([\s\S]*?)<\/(?:[\w]+:)?string>/gi),
]
.map((match) => decodeXml(match[1].trim()))
.filter(Boolean);
if (nestedStrings.length > 0) {
return nestedStrings.join(', ');
}
return decodeXml(value.trim());
}
export interface ShahkarInquiryFields {
response?: string;
result?: string;
comment?: string;
requestId?: string;
id?: string;
ErrorNams?: string;
}
export function parseShahkarInqueryResult(soapXml: string): ShahkarInquiryFields {
const blockMatch = soapXml.match(
/<(?:[\w]+:)?ShahkarInqueryResult[^>]*>([\s\S]*?)<\/(?:[\w]+:)?ShahkarInqueryResult>/i,
);
if (!blockMatch) {
return {};
}
const fields: Record<string, string> = {};
const tagRegex = /<(?:[\w]+:)?(\w+)(?:[^>]*)>([\s\S]*?)<\/(?:[\w]+:)?\1>/gi;
let match: RegExpExecArray | null;
while ((match = tagRegex.exec(blockMatch[1])) !== null) {
fields[match[1]] = normalizeSoapTextValue(match[2]);
}
return fields;
}
export function normalizeShahkarFields(raw: Record<string, unknown>): ShahkarInquiryFields {
const readString = (value: unknown): string | undefined => {
if (value === null || value === undefined) {
return undefined;
}
const text = String(value).trim();
return text.length > 0 ? text : undefined;
};
return {
response: readString(raw.response ?? raw.Response),
result: readString(raw.result ?? raw.Result),
comment: readString(raw.comment ?? raw.Comment),
requestId: readString(raw.requestId ?? raw.RequestId),
id: readString(raw.id ?? raw.Id),
ErrorNams: readString(raw.ErrorNams ?? raw.errorNams),
};
}
export function isShahkarSuccess(fields: ShahkarInquiryFields): boolean {
const responseCode = fields.response?.trim();
const resultText = fields.result?.trim().toUpperCase() ?? '';
return responseCode === '200' && resultText.startsWith('OK');
}
export function getShahkarProviderError(
fields: ShahkarInquiryFields,
): { message: string; code: string; providerCode?: string; providerTrackingCode?: string } | null {
if (isShahkarSuccess(fields)) {
return null;
}
const comment = fields.comment?.trim();
const errorNams = fields.ErrorNams?.trim();
const resultText = fields.result?.trim();
const responseCode = fields.response?.trim();
const providerTrackingCode = fields.requestId?.trim() || undefined;
if (resultText === 'NotIdentifiedException' || responseCode === '600') {
return {
message:
comment ||
'No match found between the provided national code and mobile number',
code: 'INQUIRY_NO_MATCH',
providerCode: resultText ?? responseCode,
providerTrackingCode,
};
}
return {
message: comment || errorNams || resultText || 'Shahkar inquiry failed',
code: 'PROVIDER_ERROR',
providerCode: resultText ?? responseCode,
providerTrackingCode,
};
}
export function describeShahkarResponse(fields: ShahkarInquiryFields): string {
return [
fields.response ? `response=${fields.response}` : null,
fields.result ? `result=${fields.result}` : null,
fields.comment ? `comment=${fields.comment}` : null,
fields.requestId ? `requestId=${fields.requestId}` : null,
]
.filter(Boolean)
.join(' | ');
}