Added API for externalAPI, added env for clients

This commit is contained in:
SepehrYahyaee
2026-06-13 11:26:33 +03:30
parent cb47069e90
commit 3abbd45fac
13 changed files with 335 additions and 161 deletions

View File

@@ -3,6 +3,8 @@
# --------------------------------------------- # ---------------------------------------------
NODE_ENV = NODE_ENV =
PORT = PORT =
CLIENT_ID =
CLIENT_NAME =
# --------------------------------------------- # ---------------------------------------------
# 🌐 Application URLs # 🌐 Application URLs
# --------------------------------------------- # ---------------------------------------------

View File

@@ -1,7 +1,7 @@
import { join } from "node:path"; import { join } from "node:path";
import { APP_INTERCEPTOR, APP_PIPE } from "@nestjs/core"; import { APP_INTERCEPTOR, APP_PIPE } from "@nestjs/core";
import { Module, ValidationPipe } from "@nestjs/common"; import { Module } from "@nestjs/common";
import { ConfigModule, ConfigService } from "@nestjs/config"; import { ConfigService } from "@nestjs/config";
import { UnicodeDigitsNormalizeInterceptor } from "./common/interceptors/unicode-digits-normalize.interceptor"; import { UnicodeDigitsNormalizeInterceptor } from "./common/interceptors/unicode-digits-normalize.interceptor";
import { MongooseModule } from "@nestjs/mongoose"; import { MongooseModule } from "@nestjs/mongoose";
import { ServeStaticModule } from "@nestjs/serve-static"; import { ServeStaticModule } from "@nestjs/serve-static";
@@ -24,79 +24,18 @@ import { applyIranFaTimestampPlugin } from "./helpers/mongoose-fa-timestamps.plu
import { CronModule } from "./utils/cron/cron.module"; import { CronModule } from "./utils/cron/cron.module";
import { WorkflowStepManagementModule } from "./workflow-step-management/workflow-step-management.module"; import { WorkflowStepManagementModule } from "./workflow-step-management/workflow-step-management.module";
import { ExpertInitiatedModule } from "./expert-initiated/expert-initiated.module"; import { ExpertInitiatedModule } from "./expert-initiated/expert-initiated.module";
import * as Joi from "joi"; import { DatabaseModule } from "./core/database/database.module";
import { AppConfigModule } from "./core/config/config.module";
@Module({ @Module({
imports: [ imports: [
ConfigModule.forRoot({ AppConfigModule,
isGlobal: true, DatabaseModule,
validationSchema: Joi.object({
NODE_ENV: Joi.string()
.valid("development", "production")
.default("development"),
PORT: Joi.number().port().default(9001),
URL: Joi.string().uri().required(),
BASE_URL_DEV: Joi.string()
.uri()
.when("NODE_ENV", {
is: Joi.string().valid("development"),
then: Joi.required(),
otherwise: Joi.optional(),
}),
SWAGGER_USER_DEV: Joi.string().when("NODE_ENV", {
is: Joi.string().valid("development"),
then: Joi.required(),
otherwise: Joi.optional(),
}),
SWAGGER_PASSWORD_DEV: Joi.string().when("NODE_ENV", {
is: Joi.string().valid("development"),
then: Joi.required(),
otherwise: Joi.optional(),
}),
MONGO_HOST: Joi.string().required(),
MONGO_PORT: Joi.number().port().required(),
MONGO_USER: Joi.string().required(),
MONGO_PASS: Joi.string().required(),
MONGO_DB_NAME: Joi.string().required(),
JWT_SECRET: Joi.string().required(),
SANHUB_BASE_URL: Joi.string().uri(),
SANHUB_URL_LOGIN: Joi.string().uri(),
SANHUB_USERNAME: Joi.string(),
SANHUB_PASSWORD: Joi.string(),
AI_URL: Joi.string().uri(),
AI_URL_V2: Joi.string().uri(),
AI_USERNAME: Joi.string(),
AI_PASSWORD: Joi.string(),
SMS_PROVIDER: Joi.string()
.valid("kavenegar", "parsian")
.default("kavenegar"),
SMS_API_KEY: Joi.string(),
AUTH_SMS_TEMPLATE: Joi.string(),
EXP_OTP_TIME: Joi.number(),
}),
}),
CronModule, CronModule,
ServeStaticModule.forRoot({ ServeStaticModule.forRoot({
rootPath: join(__dirname, "..", "files"), rootPath: join(__dirname, "..", "files"),
serveRoot: "/files", serveRoot: "/files",
}), }),
MongooseModule.forRootAsync({
inject: [ConfigService],
useFactory: (configService: ConfigService) => {
return {
uri: `mongodb://${configService.get<string>("MONGO_USER")}:${configService.get<string>("MONGO_PASS")}@${configService.get<string>("MONGO_HOST")}:${configService.get<string>("MONGO_PORT")}/${configService.get<string>("MONGO_DB_NAME")}?authSource=admin&${configService.get<string>("MONGO_OPTIONS")}`,
tls: configService.get<string>("MONGO_TLS") === "true",
tlsAllowInvalidCertificates:
configService.get<string>("MONGO_TLS_ALLOW_INVALID_CERTS") ===
"true",
autoIndex: configService.get<string>("NODE_ENV") !== "production",
connectionFactory: (connection) => {
applyIranFaTimestampPlugin(connection);
return connection;
},
};
},
}),
UsersModule, UsersModule,
AuthModule, AuthModule,
ClientModule, ClientModule,

View File

@@ -1,17 +1,24 @@
import { Body, Controller, Get, Post, UseGuards } from "@nestjs/common"; import { Body, Controller, Get, Patch, Post } from "@nestjs/common";
import { ApiBearerAuth, ApiTags } from "@nestjs/swagger"; import {
import { GlobalGuard } from "src/auth/guards/global.guard"; ApiBody,
import { RolesGuard } from "src/auth/guards/role.guard"; ApiOperation,
import { Roles } from "src/decorators/roles.decorator"; ApiResponse,
ApiTags,
} from "@nestjs/swagger";
import { CurrentUser } from "src/decorators/user.decorator"; import { CurrentUser } from "src/decorators/user.decorator";
import { RoleEnum } from "src/Types&Enums/role.enum"; import { SystemSettingsResponseDto } from "src/system-settings/dto/system-settings.dto";
import { SystemSettingsService } from "src/system-settings/system-settings.service";
import { ClientService } from "./client.service"; import { ClientService } from "./client.service";
import { ClientDto } from "./dto/create-client.dto"; import { ClientDto } from "./dto/create-client.dto";
import { SetExternalInquiriesLiveDto } from "./dto/external-inquiries-live.dto";
@Controller("client") @Controller("client")
@ApiTags("client-management") @ApiTags("client-management")
export class ClientController { export class ClientController {
constructor(private readonly clientService: ClientService) {} constructor(
private readonly clientService: ClientService,
private readonly systemSettingsService: SystemSettingsService,
) {}
@Post() @Post()
async addClient(@Body() client: ClientDto) { async addClient(@Body() client: ClientDto) {
@@ -27,4 +34,33 @@ export class ClientController {
async getClientList(@CurrentUser() user) { async getClientList(@CurrentUser() user) {
return await this.clientService.getClientList(); return await this.clientService.getClientList();
} }
/** Toggle SandHub/Tejarat live HTTP vs mock inquiries (`system_settings.externalApis.sandHubUseLiveApi`). */
@Patch("external-inquiries-live")
@ApiOperation({
summary: "Enable or disable live external inquiries",
description:
"Updates `system_settings.externalApis.sandHubUseLiveApi`. No auth required. Use the request examples below to switch between live Tejarat/SandHub HTTP and offline mock mode.",
})
@ApiBody({
type: SetExternalInquiriesLiveDto,
examples: {
enableLive: {
summary: "Enable live inquiries",
description: "Call real SandHub/Tejarat HTTP APIs.",
value: { enabled: true },
},
disableLive: {
summary: "Disable live inquiries (mock mode)",
description: "Use mocked inquiry responses; flows continue without external connectivity.",
value: { enabled: false },
},
},
})
@ApiResponse({ status: 200, type: SystemSettingsResponseDto })
async setExternalInquiriesLive(@Body() body?: SetExternalInquiriesLiveDto) {
return this.systemSettingsService.updateSettings({
externalApis: { sandHubUseLiveApi: body?.enabled === true },
});
}
} }

View File

@@ -1,5 +1,6 @@
import { Module } from "@nestjs/common"; import { Module } from "@nestjs/common";
import { MongooseModule } from "@nestjs/mongoose"; import { MongooseModule } from "@nestjs/mongoose";
import { SystemSettingsModule } from "src/system-settings/system-settings.module";
import { ClientController } from "./client.controller"; import { ClientController } from "./client.controller";
import { ClientPanelController } from "./client-panel.controller"; import { ClientPanelController } from "./client-panel.controller";
import { ClientService } from "./client.service"; import { ClientService } from "./client.service";
@@ -10,6 +11,7 @@ import { ClientDbSchema, ClientModel } from "./entities/schema/client.schema";
@Module({ @Module({
imports: [ imports: [
SystemSettingsModule,
MongooseModule.forFeature([ MongooseModule.forFeature([
{ name: ClientModel.name, schema: ClientDbSchema }, { name: ClientModel.name, schema: ClientDbSchema },
{ {

View File

@@ -142,6 +142,38 @@ export class ClientService {
return await this.clientDbService.find({ clientCode: companyCode }); return await this.clientDbService.find({ clientCode: companyCode });
} }
/**
* Resolve a client by insurer company code from an external inquiry.
* Creates the client when missing so inquiry flows don't fail on unknown codes.
*/
async findOrCreateClientByCompanyCode(
companyCode: number | string | null | undefined,
companyName: string | null | undefined,
) {
const name = typeof companyName === "string" ? companyName.trim() : "";
const code = Number(companyCode);
if (!name || !Number.isFinite(code)) {
return null;
}
let client = await this.clientDbService.find({ clientCode: code });
if (client) return client;
try {
await this.addClient({
clientName: { persian: name, english: null },
clientCode: code,
useExpertMode: "legal",
});
} catch (err) {
client = await this.clientDbService.find({ clientCode: code });
if (client) return client;
throw err;
}
return this.clientDbService.find({ clientCode: code });
}
async getClients(): Promise<ClientDtoRs[]> { async getClients(): Promise<ClientDtoRs[]> {
const clients = await this.clientDbService.findAll(); const clients = await this.clientDbService.findAll();
const show = clients.map((c) => new ClientDtoRs(c)); const show = clients.map((c) => new ClientDtoRs(c));

View File

@@ -0,0 +1,10 @@
import { ApiProperty } from "@nestjs/swagger";
export class SetExternalInquiriesLiveDto {
@ApiProperty({
description:
"When true, SandHub/Tejarat live HTTP inquiries run. When false, mocked inquiry data is used.",
example: true,
})
enabled: boolean;
}

View File

@@ -0,0 +1,14 @@
import { Module } from "@nestjs/common";
import { ConfigModule } from "@nestjs/config";
import { validate } from "./config.validation";
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
expandVariables: true,
validate,
}),
],
})
export class AppConfigModule {}

View File

@@ -0,0 +1,75 @@
import {
IsBooleanString,
IsEnum,
IsNumber,
IsPositive,
IsString,
IsUrl,
Matches,
Max,
Min,
MinLength,
} from "class-validator";
import { StringValue } from "ms";
export enum Environment {
Development = "development",
Production = "production",
}
export class EnvironmentVariables {
@IsEnum(Environment, {
message: "NODE_ENV should be development or production",
})
NODE_ENV: Environment;
// --------------------------------------------------------- //
@IsNumber(
{
allowNaN: false,
allowInfinity: false,
},
{
message: "PORT must be a valid number",
},
)
@IsPositive({ message: "PORT must be positive" })
@Min(0, { message: "PORT must be between 0 and 65535" })
@Max(65535, { message: "PORT must be between 0 and 65535" })
PORT: number;
// --------------------------------------------------------- //
@IsString({ message: "MONGO_URI must be string" })
@IsUrl(
{
require_tld: false,
protocols: ["mongodb", "mongodb+srv"],
},
{
message: "MONGO_URI must be in the correct format (mongodb://...)",
},
)
MONGO_URI: string;
// --------------------------------------------------------- //
@IsBooleanString({ message: "MONGO_TLS must be boolean" })
MONGO_TLS: string;
// --------------------------------------------------------- //
@IsBooleanString({ message: "MONGO_TLS_ALLOW_INVALID_CERTS must be boolean" })
MONGO_TLS_ALLOW_INVALID_CERTS: string;
// --------------------------------------------------------- //
@IsString({ message: "JWT_SECRET must be string" })
@MinLength(32, {
message: "JWT_SECRET must be at least 32 characters",
})
JWT_SECRET: string;
// --------------------------------------------------------- //
@Matches(/^\d+(ms|s|m|h|d|w|y)$/, {
message: "JWT_EXPIRY must be in the correct format",
})
JWT_EXPIRY: StringValue;
// --------------------------------------------------------- //
// @IsString({ message: "HASH_PEPPER must be string" })
// @MinLength(32, {
// message: "HASH_PEPPER must be at least 32 characters",
// })
// HASH_PEPPER: string;
// --------------------------------------------------------- //
}

View File

@@ -0,0 +1,23 @@
import { plainToInstance } from "class-transformer";
import { validateSync } from "class-validator";
import { EnvironmentVariables } from "./config.schema";
export function validate(config: Record<string, unknown>) {
const validatedConfig = plainToInstance(EnvironmentVariables, config, {
enableImplicitConversion: true,
});
const errors = validateSync(validatedConfig, {
skipMissingProperties: false,
});
if (errors.length > 0) {
const messages = errors
.flatMap((error) => Object.values(error.constraints ?? {}))
.join("\n");
throw new Error(`Environment validation failed:\n${messages}`);
}
return validatedConfig;
}

View File

@@ -0,0 +1,19 @@
import { Module } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { MongooseModule } from "@nestjs/mongoose";
@Module({
imports: [
MongooseModule.forRootAsync({
inject: [ConfigService],
useFactory: (configService: ConfigService) => ({
uri: configService.get<string>("MONGO_URI"),
tls: configService.get<string>("MONGO_TLS") === "true",
tlsAllowInvalidCertificates:
configService.get<string>("MONGO_TLS_ALLOW_INVALID_CERTS") === "true",
autoIndex: configService.get<string>("NODE_ENV") !== "production",
}),
}),
],
})
export class DatabaseModule {}

View File

@@ -1160,24 +1160,16 @@ export class RequestManagementService {
); );
} }
const companyCode = inquiryMapped?.CompanyCode; const companyCode = inquiryMapped?.CompanyCode;
let client = const client = await this.clientService.findOrCreateClientByCompanyCode(
await this.clientService.findClientWithCompanyCode(+companyCode); companyCode,
clientName,
);
if (!client) { if (!client) {
await this.clientService.addClient({ throw new BadRequestException(
clientName: { `CompanyCode missing or invalid in inquiry response`,
persian: clientName, );
english: null,
},
clientCode: Number(companyCode),
useExpertMode: "legal",
});
} }
// if (!client) {
// throw new HttpException("Client not found", HttpStatus.CONFLICT);
// }
// Persist inquiry/body data into new model // Persist inquiry/body data into new model
if (!party.person) party.person = {} as any; if (!party.person) party.person = {} as any;
const resolvedClientId = const resolvedClientId =
@@ -1286,27 +1278,13 @@ export class RequestManagementService {
const carBodyCompanyCode = m.companyId ?? m.CompanyCode; const carBodyCompanyCode = m.companyId ?? m.CompanyCode;
const carBodyCompanyName = m.CompanyName ?? m.companyPersianName; const carBodyCompanyName = m.CompanyName ?? m.companyPersianName;
if (carBodyCompanyCode) { if (carBodyCompanyCode && carBodyCompanyName) {
let carBodyClient: any = const carBodyClient =
await this.clientService.findClientWithCompanyCode( await this.clientService.findOrCreateClientByCompanyCode(
Number(carBodyCompanyCode), carBodyCompanyCode,
carBodyCompanyName,
); );
if (!carBodyClient && carBodyCompanyName) {
await this.clientService.addClient({
clientName: {
persian: carBodyCompanyName,
english: null,
},
clientCode: Number(carBodyCompanyCode),
useExpertMode: "legal",
});
// Re-fetch after creation so we get the actual document with _id
carBodyClient = await this.clientService.findClientWithCompanyCode(
Number(carBodyCompanyCode),
);
}
const carBodyClientId = const carBodyClientId =
(carBodyClient as any)?._id ?? (carBodyClient as any)?._doc?._id; (carBodyClient as any)?._id ?? (carBodyClient as any)?._doc?._id;
@@ -2075,8 +2053,10 @@ export class RequestManagementService {
const clientName = sandHubReport?.CompanyName; const clientName = sandHubReport?.CompanyName;
const companyCode = sandHubReport?.CompanyCode; const companyCode = sandHubReport?.CompanyCode;
const client = const client = await this.clientService.findOrCreateClientByCompanyCode(
await this.clientService.findClientWithCompanyCode(+companyCode); companyCode,
clientName,
);
if (!client) { if (!client) {
throw new HttpException("Client not found", HttpStatus.CONFLICT); throw new HttpException("Client not found", HttpStatus.CONFLICT);
@@ -5021,7 +5001,10 @@ export class RequestManagementService {
sandHubReport?.CompanyName || sandHubReport?.LastCompanyName; sandHubReport?.CompanyName || sandHubReport?.LastCompanyName;
const companyCode = sandHubReport?.CompanyCode; const companyCode = sandHubReport?.CompanyCode;
const client = companyCode const client = companyCode
? await this.clientService.findClientWithCompanyCode(+companyCode) ? await this.clientService.findOrCreateClientByCompanyCode(
companyCode,
clientName,
)
: await this.clientService.findOne({ clientName }); : await this.clientService.findOne({ clientName });
if (!client) { if (!client) {
throw new NotFoundException( throw new NotFoundException(
@@ -5228,7 +5211,10 @@ export class RequestManagementService {
sandHubReport?.CompanyName || sandHubReport?.LastCompanyName; sandHubReport?.CompanyName || sandHubReport?.LastCompanyName;
const companyCode = sandHubReport?.CompanyCode; const companyCode = sandHubReport?.CompanyCode;
const client = companyCode const client = companyCode
? await this.clientService.findClientWithCompanyCode(+companyCode) ? await this.clientService.findOrCreateClientByCompanyCode(
companyCode,
clientName,
)
: await this.clientService.findOne({ clientName }); : await this.clientService.findOne({ clientName });
if (!client) { if (!client) {
throw new NotFoundException( throw new NotFoundException(
@@ -5834,7 +5820,10 @@ export class RequestManagementService {
// Try to find client by company code first (more reliable) // Try to find client by company code first (more reliable)
const client = companyCode const client = companyCode
? await this.clientService.findClientWithCompanyCode(+companyCode) ? await this.clientService.findOrCreateClientByCompanyCode(
companyCode,
clientName,
)
: await this.clientService.findOne({ clientName: clientName }); : await this.clientService.findOne({ clientName: clientName });
if (!client) { if (!client) {
@@ -5898,7 +5887,10 @@ export class RequestManagementService {
// Try to find client by company code first (more reliable) // Try to find client by company code first (more reliable)
const client = companyCode const client = companyCode
? await this.clientService.findClientWithCompanyCode(+companyCode) ? await this.clientService.findOrCreateClientByCompanyCode(
companyCode,
clientName,
)
: await this.clientService.findOne({ clientName: clientName }); : await this.clientService.findOne({ clientName: clientName });
if (!client) { if (!client) {
@@ -6168,7 +6160,10 @@ export class RequestManagementService {
// Try to find client by company code first (more reliable) // Try to find client by company code first (more reliable)
const client = companyCode const client = companyCode
? await this.clientService.findClientWithCompanyCode(+companyCode) ? await this.clientService.findOrCreateClientByCompanyCode(
companyCode,
clientName,
)
: await this.clientService.findOne({ clientName: clientName }); : await this.clientService.findOne({ clientName: clientName });
if (!client) { if (!client) {

View File

@@ -40,40 +40,49 @@ export class SandHubService {
return this.systemSettingsService.isSandHubLiveEnabled(); return this.systemSettingsService.isSandHubLiveEnabled();
} }
/** Tenant-specific company fields for mocked external inquiries (MOCK_INQUIRY_COMPANY_*). */
private getMockInquiryCompanyId(): string {
return process.env.CLIENT_ID ?? "15";
}
private getMockInquiryCompanyName(): string {
return process.env.CLIENT_NAME ?? "بیمه سامان";
}
/** Fixed plate/insurance inquiry payload used everywhere we mock block-inquiry style APIs. */ /** Fixed plate/insurance inquiry payload used everywhere we mock block-inquiry style APIs. */
private getDefaultMockPlateInquiryRaw(): Record<string, unknown> { private getDefaultMockPlateInquiryRaw(): Record<string, unknown> {
return { return {
PrntPlcyCmpDocNo: "1403/1143-70591/200/35", PrntPlcyCmpDocNo: "1404/1143-70591/200/123",
MapTypNam: "پرايد هاچ بک -111", MapTypNam: "فائو ( FAW )",
MtrNum: "5215907", MtrNum: "TZ196XYAP223A210074",
ShsNum: "NAS431100E5798656", ShsNum: "LFP8C7PC3R1K12157",
DisFnYrNum: "0", DisFnYrNum: null,
DisLfYrNum: "0", DisLfYrNum: null,
DisPrsnYrNum: "0", DisPrsnYrNum: null,
DisPrsnYrPrcnt: "0", DisPrsnYrPrcnt: null,
DisFnYrPrcnt: "0", DisFnYrPrcnt: "5",
DisLfYrPrcnt: "0", DisLfYrPrcnt: "5",
vin: "IRPC941V2BD798656", vin: "LFP8C7PC3R1K12157",
MapVehicleSystemName: "ثبت نشده", MapVehicleSystemName: "ثبت نشده",
LfCvrCptl: 0, LfCvrCptl: 0,
FnCvrCptl: 0, FnCvrCptl: 0,
PrsnCvrCptl: 0, PrsnCvrCptl: 0,
VehicleSystemCode: 1, VehicleSystemCode: 1,
EdrsJson: '[{"id":1,"Dsc":" الحاقيه توضيحات ندارد"}]', EdrsJson: "",
PersonCvrCptl: 12000000000, PersonCvrCptl: 12000000000,
LifeCvrCptl: 16000000000, LifeCvrCptl: 16000000000,
FinancialCvrCptl: 4000000000, FinancialCvrCptl: 4000000000,
CarGroupCode: 3, CarGroupCode: 3,
CylCnt: 4, CylCnt: 4,
LastCompanyDocumentNumber: "03/1031/2835/1001/662", LastCompanyDocumentNumber: "31/3100/03/18350",
UsageCode: "8", UsageCode: "8",
MapUsageCode: 1, MapUsageCode: 1,
MapUsageName: "شخصي", MapUsageName: "شخصي",
Plk1: 59, Plk1: 16,
Plk2: 16, Plk2: 12,
Plk3: 419, Plk3: 498,
PlkSrl: 78, PlkSrl: 60,
PrintEndorsCompanyDocumentNumber: "بيمه نامه الحاقيه ندارد.", PrintEndorsCompanyDocumentNumber: "",
EndorseDate: null, EndorseDate: null,
InsuranceFullName: null, InsuranceFullName: null,
SystemField: "سايپا", SystemField: "سايپا",
@@ -81,12 +90,12 @@ export class SandHubService {
UsageField: "سواري", UsageField: "سواري",
MainColorField: "سفيد", MainColorField: "سفيد",
SecondColorField: "سفيد شيري", SecondColorField: "سفيد شيري",
ModelField: "1394", ModelField: "2024",
CapacityField: "جمعا 4 نفر", CapacityField: "جمعا 4 نفر",
CylinderNumberField: "4", CylinderNumberField: "4",
EngineNumberField: "5215907", EngineNumberField: "5215907",
ChassisNumberField: "NAS431100E5798656", ChassisNumberField: "LFP8C7PC3R1K12157",
VinNumberField: "IRPC941V2BD798656", VinNumberField: "LFP8C7PC3R1K12157",
InstallDateField: "1403/03/01", InstallDateField: "1403/03/01",
AxelNumberField: "2", AxelNumberField: "2",
WheelNumberField: "4", WheelNumberField: "4",
@@ -107,7 +116,7 @@ export class SandHubService {
SystemCodeCii: 0, SystemCodeCii: 0,
SystemNameCii: "ثبت نشده", SystemNameCii: "ثبت نشده",
TypeCodeCii: 12189, TypeCodeCii: 12189,
TypeNameCii: "پرايد هاچ بک -111", TypeNameCii: "فائو ( FAW )",
UsageNameCii: "سواري", UsageNameCii: "سواري",
UsageCodeCii: 1, UsageCodeCii: 1,
ModelCii: 1394, ModelCii: 1394,
@@ -116,6 +125,47 @@ export class SandHubService {
}; };
} }
private getDefaultMockCarBodyInquiryRaw(
userDetail: SandHubDetailDto,
): Record<string, unknown> {
const companyId = Number(this.getMockInquiryCompanyId());
return {
data: {
id: 70016075946,
printNumber: "1405/1143-70591/220/1/0",
companyId: Number.isNaN(companyId) ? 15 : companyId,
companyName: this.getMockInquiryCompanyName(),
beginDate: "1405/01/17",
endDate: "1406/01/17",
issueDate: "1405/01/16",
hasEndorsement: null,
motorNumber: "TZ196XYAP223A210074",
chassisNumber: "LFP8C7PC3R1K12157",
vin: "LFP8C7PC3R1K12157",
plateTypeId: 9,
plateTypeTitle: "پلاک قدیمی",
platePartOne: 16,
plateSerialNumber: 60,
plateLetterid: 12,
plateLetterTitle: "م ",
vehicleSystemTitle: "فائو ( FAW )",
vehicleGroupId: 2,
vehicleGroupTitle: "سواری چهار سیلندر",
insurerNationalCode: userDetail.nationalCodeOfInsurer,
insurerName: "هانيه کارخانهء",
ownerNationalCode: userDetail.nationalCodeOfInsurer,
previousId: 70006331822,
noLossYearsCount: 4,
platePartThree: 498,
lossDocuments: [],
},
isSuccess: true,
statusCode: 200,
message: "عملیات با موفقیت انجام شد",
};
}
/** /**
* Bodies returned from `makeSandHubRequest` in mock mode (same shape callers expect from real API). * Bodies returned from `makeSandHubRequest` in mock mode (same shape callers expect from real API).
*/ */
@@ -401,30 +451,7 @@ export class SandHubService {
this.logger.debug( this.logger.debug(
`[MOCK] getTejaratCarBodyInquiry plate=${JSON.stringify(requestPayload)}`, `[MOCK] getTejaratCarBodyInquiry plate=${JSON.stringify(requestPayload)}`,
); );
raw = { raw = this.getDefaultMockCarBodyInquiryRaw(userDetail);
data: {
printNumber: "MOCK-BADANE-001",
companyId: 34,
companyName: "بیمه تجارت نو",
beginDate: "1404/06/15",
endDate: "1405/06/15",
issueDate: "1404/06/13",
hasEndorsement: null,
motorNumber: "MOCK-ENGINE",
chassisNumber: "MOCK-CHASSIS",
vin: "MOCK-VIN",
vehicleSystemTitle: "سایپا",
vehicleGroupTitle: "سواری چهار سیلندر",
insurerNationalCode: userDetail.nationalCodeOfInsurer,
insurerName: "نام آزمایشی",
ownerNationalCode: userDetail.nationalCodeOfInsurer,
noLossYearsCount: 0,
lossDocuments: [],
},
isSuccess: true,
statusCode: 200,
message: "mock-ok",
};
} }
const mapped = this.mapCarBodyInquiryResponse(raw); const mapped = this.mapCarBodyInquiryResponse(raw);