forked from Yara724/api
Merge pull request 'Fixed smsApiKey index error and err handling in ESG' (#142) from s.yahyaee/yara724-api:main into main
Reviewed-on: Yara724/api#142
This commit is contained in:
@@ -114,6 +114,7 @@ export class ClientService {
|
|||||||
) {}
|
) {}
|
||||||
async addClient(client: ClientDto): Promise<ClientDtoRs> {
|
async addClient(client: ClientDto): Promise<ClientDtoRs> {
|
||||||
try {
|
try {
|
||||||
|
const smsApiKey = client.property?.smsApiKey?.trim();
|
||||||
const newClient = await this.clientDbService.create({
|
const newClient = await this.clientDbService.create({
|
||||||
clientCode: client.clientCode,
|
clientCode: client.clientCode,
|
||||||
|
|
||||||
@@ -129,9 +130,7 @@ export class ClientService {
|
|||||||
: (client.clientName?.english ?? null),
|
: (client.clientName?.english ?? null),
|
||||||
},
|
},
|
||||||
|
|
||||||
property: {
|
...(smsApiKey ? { property: { smsApiKey } } : {}),
|
||||||
smsApiKey: client.property?.smsApiKey ?? null,
|
|
||||||
},
|
|
||||||
|
|
||||||
useExpertMode: client.useExpertMode ?? null,
|
useExpertMode: client.useExpertMode ?? null,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -23,8 +23,9 @@ class ClientName {
|
|||||||
}
|
}
|
||||||
class Property {
|
class Property {
|
||||||
@ApiPropertyOptional({})
|
@ApiPropertyOptional({})
|
||||||
|
@IsOptional()
|
||||||
@IsString()
|
@IsString()
|
||||||
smsApiKey: string;
|
smsApiKey?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ClientDto {
|
export class ClientDto {
|
||||||
|
|||||||
@@ -1,15 +1,49 @@
|
|||||||
import { Injectable } from "@nestjs/common";
|
import { Injectable, Logger, OnModuleInit } from "@nestjs/common";
|
||||||
import { InjectModel } from "@nestjs/mongoose";
|
import { InjectModel } from "@nestjs/mongoose";
|
||||||
import { FilterQuery, Model, UpdateQuery } from "mongoose";
|
import { FilterQuery, Model, UpdateQuery } from "mongoose";
|
||||||
import { ClientModel, ClientDocument } from "../schema/client.schema";
|
import { ClientModel, ClientDocument } from "../schema/client.schema";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ClientDbService {
|
export class ClientDbService implements OnModuleInit {
|
||||||
|
private readonly logger = new Logger(ClientDbService.name);
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@InjectModel(ClientModel.name)
|
@InjectModel(ClientModel.name)
|
||||||
private readonly clientModel: Model<ClientModel>,
|
private readonly clientModel: Model<ClientModel>,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
async onModuleInit(): Promise<void> {
|
||||||
|
await this.dropLegacyPropertyUniqueIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `property` was once declared `unique: true` in the schema. Production keeps
|
||||||
|
* `autoIndex: false`, so the stale unique index remained and rejected a second
|
||||||
|
* client with a missing/null SMS key (E11000 duplicate key).
|
||||||
|
*/
|
||||||
|
private async dropLegacyPropertyUniqueIndex(): Promise<void> {
|
||||||
|
try {
|
||||||
|
const indexes = await this.clientModel.collection.indexes();
|
||||||
|
for (const index of indexes) {
|
||||||
|
if (!index.unique || !index.name || index.name === "_id_") continue;
|
||||||
|
|
||||||
|
const keys = Object.keys(index.key ?? {});
|
||||||
|
const isLegacyPropertyIndex =
|
||||||
|
keys.length === 1 &&
|
||||||
|
(keys[0] === "property" || keys[0] === "property.smsApiKey");
|
||||||
|
|
||||||
|
if (!isLegacyPropertyIndex) continue;
|
||||||
|
|
||||||
|
await this.clientModel.collection.dropIndex(index.name);
|
||||||
|
this.logger.warn(
|
||||||
|
`Dropped legacy unique index on clients.${keys[0]}: ${index.name}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
this.logger.error("Failed to drop legacy client property index", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async create(client: ClientModel): Promise<ClientModel> {
|
async create(client: ClientModel): Promise<ClientModel> {
|
||||||
return await this.clientModel.create(client);
|
return await this.clientModel.create(client);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,9 +96,9 @@ export class ClientModel {
|
|||||||
english: string;
|
english: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
@Prop({ required: false, unique: false, type: Object })
|
@Prop({ required: false, type: Object })
|
||||||
property: {
|
property?: {
|
||||||
smsApiKey: string;
|
smsApiKey?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
@Prop({ required: true, unique: false })
|
@Prop({ required: true, unique: false })
|
||||||
|
|||||||
@@ -4061,9 +4061,6 @@ export class RequestManagementService {
|
|||||||
persian: data.clientName,
|
persian: data.clientName,
|
||||||
english: null,
|
english: null,
|
||||||
},
|
},
|
||||||
property: {
|
|
||||||
smsApiKey: null,
|
|
||||||
},
|
|
||||||
useExpertMode: "genuine",
|
useExpertMode: "genuine",
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ import { firstValueFrom } from "rxjs";
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SandHubService {
|
export class SandHubService {
|
||||||
|
private static readonly ESG_INQUIRY_UNAVAILABLE_MESSAGE =
|
||||||
|
"استعلام در دسترس نیست";
|
||||||
|
|
||||||
private readonly logger = new Logger(SandHubService.name);
|
private readonly logger = new Logger(SandHubService.name);
|
||||||
private loginToken: string | null = null;
|
private loginToken: string | null = null;
|
||||||
private tokenExpiry: Date | null = null;
|
private tokenExpiry: Date | null = null;
|
||||||
@@ -528,17 +531,13 @@ export class SandHubService {
|
|||||||
if (!raw) return raw;
|
if (!raw) return raw;
|
||||||
|
|
||||||
if (raw?.success === false) {
|
if (raw?.success === false) {
|
||||||
|
this.logger.warn(
|
||||||
|
"ESG policyByPlate inquiry returned success=false",
|
||||||
|
raw,
|
||||||
|
);
|
||||||
return {
|
return {
|
||||||
Error: {
|
Error: {
|
||||||
Message:
|
Message: SandHubService.ESG_INQUIRY_UNAVAILABLE_MESSAGE,
|
||||||
raw?.error?.message ||
|
|
||||||
raw?.message ||
|
|
||||||
"ESG policyByPlate inquiry returned an error",
|
|
||||||
Code: raw?.error?.code || raw?.error?.providerCode || "ESG_INQUIRY_ERROR",
|
|
||||||
ProviderMessage: raw?.error?.providerMessage,
|
|
||||||
ProviderCode: raw?.error?.providerCode,
|
|
||||||
TrackingCode: raw?.trackingCode,
|
|
||||||
Conflict: raw?.error?.conflict,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -622,10 +621,9 @@ export class SandHubService {
|
|||||||
|
|
||||||
private mapEsgPersonInquiryToOldFormat(raw: any): Record<string, unknown> {
|
private mapEsgPersonInquiryToOldFormat(raw: any): Record<string, unknown> {
|
||||||
if (raw?.success === false) {
|
if (raw?.success === false) {
|
||||||
throw new NotFoundException(
|
this.logger.warn("ESG person inquiry returned success=false", raw);
|
||||||
raw?.error?.message ||
|
throw new BadRequestException(
|
||||||
raw?.message ||
|
SandHubService.ESG_INQUIRY_UNAVAILABLE_MESSAGE,
|
||||||
"Personal inquiry failed: Record not found for the given national code and birth date.",
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -648,10 +646,9 @@ export class SandHubService {
|
|||||||
|
|
||||||
private mapEsgShebaInquiryToOldFormat(raw: any): Record<string, unknown> {
|
private mapEsgShebaInquiryToOldFormat(raw: any): Record<string, unknown> {
|
||||||
if (raw?.success === false) {
|
if (raw?.success === false) {
|
||||||
|
this.logger.warn("ESG sheba inquiry returned success=false", raw);
|
||||||
throw new BadRequestException(
|
throw new BadRequestException(
|
||||||
raw?.error?.message ||
|
SandHubService.ESG_INQUIRY_UNAVAILABLE_MESSAGE,
|
||||||
raw?.message ||
|
|
||||||
"Sheba ID validation failed. The provided Sheba ID does not match the national ID.",
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user