initial commit

This commit is contained in:
2026-06-09 14:07:37 +03:30
parent 30ac533800
commit 996a4fcda7
121 changed files with 20557 additions and 3 deletions

View File

@@ -0,0 +1,245 @@
import { Injectable } from '@nestjs/common';
import { InquiryType } from '../common/enums/inquiry-type.enum';
import { InquiryStatus } from '../common/enums/inquiry-status.enum';
import { ProviderName } from '../common/enums/provider-name.enum';
import { BaseInquiryResponseDto } from '../common/dto/base-inquiry-response.dto';
import { NormalizedErrorDto } from '../common/dto/normalized-error.dto';
import { generateTrackingCode } from '../common/helpers/tracking-code.helper';
import { InquiryException } from '../common/exceptions/inquiry.exception';
import { InquiryLogService } from '../logging/inquiry-log.service';
import {
LegacyInquiryPayload,
PersonInquiryPayload,
PersonInquiryResult,
} from '../providers/shared/legacy-api.provider.abstract';
import { ProviderOrchestratorService } from '../providers/strategy/provider-orchestrator.service';
import { PersonInquiryRequestDto } from './dto/person-inquiry-request.dto';
import { PersonInquiryDataDto } from './dto/person-inquiry-data.dto';
@Injectable()
export class InquiryService {
constructor(
private readonly orchestrator: ProviderOrchestratorService,
private readonly inquiryLogService: InquiryLogService,
) {}
/**
* Person inquiry — unified business flow with provider fallback and audit logging.
*/
async inquirePerson(
dto: PersonInquiryRequestDto,
requestId: string,
): Promise<BaseInquiryResponseDto<PersonInquiryDataDto>> {
const trackingCode = generateTrackingCode();
const payload: PersonInquiryPayload = {
nationalCode: dto.nationalCode,
birthDate: dto.birthDate,
dateHasPostfix: (dto as PersonInquiryRequestDto & { dateHasPostfix?: number }).dateHasPostfix,
};
const start = Date.now();
try {
const result = await this.executeInquiry<PersonInquiryPayload, PersonInquiryResult>(
InquiryType.PERSON,
payload,
requestId,
trackingCode,
);
const response = this.buildSuccessResponse(
result.data,
result.provider,
trackingCode,
result.duration,
'Person inquiry completed successfully',
);
await this.persistLog({
inquiryType: InquiryType.PERSON,
provider: result.provider,
requestPayload: payload as unknown as Record<string, unknown>,
responsePayload: response.data as unknown as Record<string, unknown>,
status: InquiryStatus.SUCCESS,
duration: result.duration,
requestId,
trackingCode,
});
return response;
} catch (error) {
const duration = Date.now() - start;
const normalized = this.extractError(error);
const response: BaseInquiryResponseDto<PersonInquiryDataDto> = {
success: false,
provider: 'GATEWAY',
trackingCode,
message: normalized.message,
error: normalized,
duration,
};
await this.persistLog({
inquiryType: InquiryType.PERSON,
provider: ProviderName.HAMTA,
requestPayload: payload as unknown as Record<string, unknown>,
status: InquiryStatus.FAILURE,
duration,
requestId,
trackingCode,
error: normalized as unknown as Record<string, unknown>,
}).catch(() => undefined);
return response;
}
}
async inquire(
inquiryType: InquiryType,
payload: LegacyInquiryPayload,
requestId: string,
): Promise<BaseInquiryResponseDto<Record<string, unknown>>> {
const trackingCode = generateTrackingCode();
const start = Date.now();
try {
const result = await this.executeInquiry<LegacyInquiryPayload, unknown>(
inquiryType,
payload,
requestId,
trackingCode,
);
const response = this.buildGenericSuccessResponse(
result.data,
result.provider,
trackingCode,
result.duration,
`${this.getInquiryLabel(inquiryType)} completed successfully`,
);
await this.persistLog({
inquiryType,
provider: result.provider,
requestPayload: payload,
responsePayload: response.data,
status: InquiryStatus.SUCCESS,
duration: result.duration,
requestId,
trackingCode,
});
return response;
} catch (error) {
const duration = Date.now() - start;
const normalized = this.extractError(error);
const response: BaseInquiryResponseDto<Record<string, unknown>> = {
success: false,
provider: 'GATEWAY',
trackingCode,
message: normalized.message,
error: normalized,
duration,
};
await this.persistLog({
inquiryType,
provider: ProviderName.HAMTA,
requestPayload: payload,
status: InquiryStatus.FAILURE,
duration,
requestId,
trackingCode,
error: normalized as unknown as Record<string, unknown>,
}).catch(() => undefined);
return response;
}
}
private async executeInquiry<TRequest, TResponse>(
inquiryType: InquiryType,
payload: TRequest,
requestId: string,
trackingCode: string,
) {
return this.orchestrator.executeWithFallback<TRequest, TResponse>(inquiryType, payload, {
requestId,
trackingCode,
});
}
private buildSuccessResponse(
result: PersonInquiryResult,
provider: string,
trackingCode: string,
duration: number,
message: string,
): BaseInquiryResponseDto<PersonInquiryDataDto> {
return {
success: true,
provider,
trackingCode,
message,
duration,
data: {
nationalCode: result.nationalCode,
birthDate: result.birthDate,
fullName: result.fullName,
},
};
}
private buildGenericSuccessResponse(
result: unknown,
provider: string,
trackingCode: string,
duration: number,
message: string,
): BaseInquiryResponseDto<Record<string, unknown>> {
return {
success: true,
provider,
trackingCode,
message,
duration,
data: this.toResponseData(result),
};
}
private toResponseData(result: unknown): Record<string, unknown> {
if (result && typeof result === 'object' && 'raw' in result) {
const raw = (result as { raw: unknown }).raw;
return raw && typeof raw === 'object' ? (raw as Record<string, unknown>) : { raw };
}
return result && typeof result === 'object'
? (result as Record<string, unknown>)
: { raw: result };
}
private getInquiryLabel(inquiryType: InquiryType): string {
return inquiryType.replace(/_INQUIRY$/, '').toLowerCase().replace(/_/g, ' ');
}
private extractError(error: unknown): NormalizedErrorDto {
if (error instanceof InquiryException) {
return error.normalizedError;
}
if (error && typeof error === 'object' && 'normalizedError' in error) {
return (error as { normalizedError: NormalizedErrorDto }).normalizedError;
}
return {
code: 'INQUIRY_FAILED',
message: error instanceof Error ? error.message : 'Inquiry failed',
};
}
private async persistLog(
input: Parameters<InquiryLogService['create']>[0],
): Promise<void> {
await this.inquiryLogService.create(input);
}
}