Skip to content

Commit

Permalink
[DEV-3470] kyc nationality auto failed (#1866)
Browse files Browse the repository at this point in the history
* [DEV-3470] kyc nationality auto failed

* [DEV-3470] Refactoring

* [DEV-3470] Refactoring 2
  • Loading branch information
Yannick1712 authored Dec 20, 2024
1 parent fc63980 commit 3c64a4e
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 34 deletions.
20 changes: 5 additions & 15 deletions src/subdomains/generic/kyc/services/kyc-admin.service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Injectable, NotFoundException } from '@nestjs/common';
import { UpdateResult } from 'src/shared/models/entity';
import { DfxLogger } from 'src/shared/services/dfx-logger';
import { MailFactory, MailTranslationKey } from 'src/subdomains/supporting/notification/factories/mail.factory';
import { UserData } from '../../user/models/user-data/user-data.entity';
import { WebhookService } from '../../user/services/webhook/webhook.service';
import { UpdateKycStepDto } from '../dto/input/update-kyc-step.dto';
Expand All @@ -21,7 +20,6 @@ export class KycAdminService {
private readonly webhookService: WebhookService,
private readonly kycService: KycService,
private readonly kycNotificationService: KycNotificationService,
private readonly mailFactory: MailFactory,
) {}

async getKycSteps(userDataId: number): Promise<KycStep[]> {
Expand All @@ -44,19 +42,11 @@ export class KycAdminService {

case KycStepName.IDENT:
if (kycStep.isCompleted) await this.kycService.completeIdent(kycStep);
if (kycStep.isFailed) {
const reasons = `<ul>${kycStep.comment
?.split(';')
.map(
(c) =>
`<li>${this.mailFactory.translate(
MailFactory.parseMailKey(MailTranslationKey.KYC_FAILED_REASONS, c),
kycStep.userData.language.symbol,
)}</li>`,
)
.join('')}</ul>`;
await this.kycNotificationService.identFailed(kycStep.userData, reasons);
}
if (kycStep.isFailed)
await this.kycNotificationService.identFailed(
kycStep.userData,
this.kycService.getMailFailedReason(kycStep.comment, kycStep.userData.language.symbol),
);

break;
}
Expand Down
65 changes: 46 additions & 19 deletions src/subdomains/generic/kyc/services/kyc.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { DisabledProcess, Process } from 'src/shared/services/process.service';
import { Lock } from 'src/shared/utils/lock';
import { Util } from 'src/shared/utils/util';
import { CheckStatus } from 'src/subdomains/core/aml/enums/check-status.enum';
import { MailFactory, MailTranslationKey } from 'src/subdomains/supporting/notification/factories/mail.factory';
import { Between, In, IsNull, LessThan, Not } from 'typeorm';
import { MergeReason } from '../../user/models/account-merge/account-merge.entity';
import { AccountMergeService } from '../../user/models/account-merge/account-merge.service';
Expand Down Expand Up @@ -97,6 +98,7 @@ export class KycService {
private readonly accountMergeService: AccountMergeService,
private readonly webhookService: WebhookService,
private readonly sumsubService: SumsubService,
private readonly mailFactory: MailFactory,
) {}

@Cron(CronExpression.EVERY_DAY_AT_4AM)
Expand Down Expand Up @@ -186,8 +188,9 @@ export class KycService {
const nationality = result.nationality
? await this.countryService.getCountryWithSymbol(result.nationality)
: null;
const nationalityStep = entity.userData.getStepsWith(KycStepName.NATIONALITY_DATA).find((s) => s.isCompleted);

const errors = this.getIdentCheckErrors(entity, result, nationality);
const errors = this.getIdentCheckErrors(entity, nationalityStep, result, nationality);
const comment = errors.join(';');

if (errors.includes(KycError.REVERSED_NAMES)) {
Expand All @@ -196,6 +199,15 @@ export class KycService {
surname: entity.userData.firstname,
});
continue;
} else if (errors.includes(KycError.NATIONALITY_NOT_MATCHING)) {
await this.kycStepRepo.update(...nationalityStep.fail(undefined, KycError.NATIONALITY_NOT_MATCHING));
if (errors.length === 1) {
await this.kycNotificationService.identFailed(
entity.userData,
this.getMailFailedReason(comment, entity.userData.language.symbol),
);
continue;
}
}

if (errors.includes(KycError.USER_DATA_BLOCKED) || errors.includes(KycError.USER_DATA_MERGED)) {
Expand Down Expand Up @@ -271,6 +283,19 @@ export class KycService {
);
}

public getMailFailedReason(comment: string, language: string): string {
return `<ul>${comment
?.split(';')
.map(
(c) =>
`<li>${this.mailFactory.translate(
MailFactory.parseMailKey(MailTranslationKey.KYC_FAILED_REASONS, c),
language,
)}</li>`,
)
.join('')}</ul>`;
}

private async tryContinue(kycHash: string, ip: string, autoStep: boolean): Promise<KycSessionDto> {
let user = await this.getUser(kycHash);
await this.verifyUserDuplication(user);
Expand Down Expand Up @@ -849,24 +874,26 @@ export class KycService {
return errors;
}

private getIdentCheckErrors(entity: KycStep, data: IdentResultData, nationality?: Country): KycError[] {
const errors = this.getStepDefaultErrors(entity);
const nationalityStepResult = entity.userData
.getStepsWith(KycStepName.NATIONALITY_DATA)
.find((s) => s.isCompleted)
.getResult<{ nationality: IEntity }>();
private getIdentCheckErrors(
identStep: KycStep,
nationalityStep: KycStep,
data: IdentResultData,
nationality?: Country,
): KycError[] {
const errors = this.getStepDefaultErrors(identStep);
const nationalityStepResult = nationalityStep.getResult<{ nationality: IEntity }>();

if (!Util.isSameName(entity.userData.firstname, data.firstname)) errors.push(KycError.FIRST_NAME_NOT_MATCHING);
if (!Util.isSameName(identStep.userData.firstname, data.firstname)) errors.push(KycError.FIRST_NAME_NOT_MATCHING);
if (
!Util.isSameName(entity.userData.surname, data.lastname) &&
!Util.isSameName(entity.userData.surname, data.birthname)
!Util.isSameName(identStep.userData.surname, data.lastname) &&
!Util.isSameName(identStep.userData.surname, data.birthname)
)
errors.push(KycError.LAST_NAME_NOT_MATCHING);

if (
(Util.isSameName(entity.userData.firstname, data.lastname) ||
Util.isSameName(entity.userData.firstname, data.birthname)) &&
Util.isSameName(entity.userData.surname, data.firstname)
(Util.isSameName(identStep.userData.firstname, data.lastname) ||
Util.isSameName(identStep.userData.firstname, data.birthname)) &&
Util.isSameName(identStep.userData.surname, data.firstname)
)
errors.push(KycError.REVERSED_NAMES);

Expand All @@ -883,16 +910,16 @@ export class KycService {
if (!data.success) errors.push(KycError.INVALID_RESULT);

const userCountry =
entity.userData.organizationCountry ?? entity.userData.verifiedCountry ?? entity.userData.country;
if (entity.userData.accountType === AccountType.PERSONAL) {
identStep.userData.organizationCountry ?? identStep.userData.verifiedCountry ?? identStep.userData.country;
if (identStep.userData.accountType === AccountType.PERSONAL) {
if (userCountry && !userCountry.dfxEnable) errors.push(KycError.COUNTRY_NOT_ALLOWED);

if (!entity.userData.verifiedName && entity.userData.status === UserDataStatus.ACTIVE) {
if (!identStep.userData.verifiedName && identStep.userData.status === UserDataStatus.ACTIVE) {
errors.push(KycError.VERIFIED_NAME_MISSING);
} else if (entity.userData.verifiedName) {
if (!Util.includesSameName(entity.userData.verifiedName, entity.userData.firstname))
} else if (identStep.userData.verifiedName) {
if (!Util.includesSameName(identStep.userData.verifiedName, identStep.userData.firstname))
errors.push(KycError.FIRST_NAME_NOT_MATCHING_VERIFIED_NAME);
if (!Util.includesSameName(entity.userData.verifiedName, entity.userData.surname))
if (!Util.includesSameName(identStep.userData.verifiedName, identStep.userData.surname))
errors.push(KycError.LAST_NAME_NOT_MATCHING_VERIFIED_NAME);
}
} else {
Expand Down

0 comments on commit 3c64a4e

Please sign in to comment.