mirror of
https://github.com/HamzaSha1/zod-backend.git
synced 2025-08-25 13:49:40 +00:00
feat/working on update card control
This commit is contained in:
@ -34,4 +34,10 @@ export class CardRepository {
|
|||||||
getCardByReferenceNumber(referenceNumber: string): Promise<Card | null> {
|
getCardByReferenceNumber(referenceNumber: string): Promise<Card | null> {
|
||||||
return this.cardRepository.findOne({ where: { cardReference: referenceNumber }, relations: ['account'] });
|
return this.cardRepository.findOne({ where: { cardReference: referenceNumber }, relations: ['account'] });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getActiveCardForCustomer(customerId: string): Promise<Card | null> {
|
||||||
|
return this.cardRepository.findOne({
|
||||||
|
where: { customerId, status: CardStatus.ACTIVE },
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,4 +34,12 @@ export class CardService {
|
|||||||
|
|
||||||
return card;
|
return card;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getActiveCardForCustomer(customerId: string): Promise<Card> {
|
||||||
|
const card = await this.cardRepository.getActiveCardForCustomer(customerId);
|
||||||
|
if (!card) {
|
||||||
|
throw new BadRequestException('CARD.NOT_FOUND');
|
||||||
|
}
|
||||||
|
return card;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,11 +28,7 @@ export class TransactionService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const transaction = await this.transactionRepository.createCardTransaction(card, body);
|
const transaction = await this.transactionRepository.createCardTransaction(card, body);
|
||||||
const total = new Decimal(body.transactionAmount)
|
const total = new Decimal(body.transactionAmount).plus(body.billingAmount).plus(body.fees).plus(body.vatOnFees);
|
||||||
.plus(body.billingAmount)
|
|
||||||
.plus(body.settlementAmount)
|
|
||||||
.plus(body.fees)
|
|
||||||
.plus(body.vatOnFees);
|
|
||||||
|
|
||||||
await this.accountService.decreaseAccountBalance(card.account.accountReference, total.toNumber());
|
await this.accountService.decreaseAccountBalance(card.account.accountReference, total.toNumber());
|
||||||
|
|
||||||
|
@ -1,16 +1,22 @@
|
|||||||
import { Controller, Get } from '@nestjs/common';
|
import { Body, Controller, Post, UseGuards } from '@nestjs/common';
|
||||||
import { ConfigService } from '@nestjs/config';
|
import { ConfigService } from '@nestjs/config';
|
||||||
import { ApiTags } from '@nestjs/swagger';
|
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
|
||||||
|
import { IJwtPayload } from '~/auth/interfaces';
|
||||||
import { CardService } from '~/card/services';
|
import { CardService } from '~/card/services';
|
||||||
|
import { AuthenticatedUser } from '~/common/decorators';
|
||||||
|
import { AccessTokenGuard } from '~/common/guards';
|
||||||
import { ApiDataResponse } from '~/core/decorators';
|
import { ApiDataResponse } from '~/core/decorators';
|
||||||
import { ResponseFactory } from '~/core/utils';
|
import { ResponseFactory } from '~/core/utils';
|
||||||
import { Customer } from '~/customer/entities';
|
import { CustomerResponseDto } from '~/customer/dtos/response';
|
||||||
import { CustomerService } from '~/customer/services';
|
import { CustomerService } from '~/customer/services';
|
||||||
|
import { UpdateCardControlsRequestDto } from '../dtos/requests';
|
||||||
import { CreateApplicationResponse, InquireApplicationResponse } from '../dtos/response';
|
import { CreateApplicationResponse, InquireApplicationResponse } from '../dtos/response';
|
||||||
import { NeoLeapService } from '../services/neoleap.service';
|
import { NeoLeapService } from '../services/neoleap.service';
|
||||||
|
|
||||||
@Controller('neotest')
|
@Controller('neotest')
|
||||||
@ApiTags('Neoleap Test API , for testing purposes only, will be removed in production')
|
@ApiTags('Neoleap Test API , for testing purposes only, will be removed in production')
|
||||||
|
@UseGuards(AccessTokenGuard)
|
||||||
|
@ApiBearerAuth()
|
||||||
export class NeoTestController {
|
export class NeoTestController {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly neoleapService: NeoLeapService,
|
private readonly neoleapService: NeoLeapService,
|
||||||
@ -19,21 +25,38 @@ export class NeoTestController {
|
|||||||
private readonly configService: ConfigService,
|
private readonly configService: ConfigService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@Get('inquire-application')
|
@Post('update-kys')
|
||||||
|
@ApiDataResponse(CustomerResponseDto)
|
||||||
|
async updateKys(@AuthenticatedUser() user: IJwtPayload) {
|
||||||
|
const customer = await this.customerService.updateKyc(user.sub);
|
||||||
|
|
||||||
|
return ResponseFactory.data(new CustomerResponseDto(customer));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('inquire-application')
|
||||||
@ApiDataResponse(InquireApplicationResponse)
|
@ApiDataResponse(InquireApplicationResponse)
|
||||||
async inquireApplication() {
|
async inquireApplication(@AuthenticatedUser() user: IJwtPayload) {
|
||||||
const data = await this.neoleapService.inquireApplication('15');
|
const customer = await this.customerService.findCustomerById(user.sub);
|
||||||
|
const data = await this.neoleapService.inquireApplication(customer.waitingNumber.toString());
|
||||||
return ResponseFactory.data(data);
|
return ResponseFactory.data(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('create-application')
|
@Post('create-application')
|
||||||
@ApiDataResponse(CreateApplicationResponse)
|
@ApiDataResponse(CreateApplicationResponse)
|
||||||
async createApplication() {
|
async createApplication(@AuthenticatedUser() user: IJwtPayload) {
|
||||||
const customer = await this.customerService.findCustomerById(
|
const customer = await this.customerService.findCustomerById(user.sub);
|
||||||
this.configService.get<string>('MOCK_CUSTOMER_ID', 'ff462af1-1e0c-4216-8865-738e5b525ac1'),
|
const data = await this.neoleapService.createApplication(customer);
|
||||||
);
|
|
||||||
const data = await this.neoleapService.createApplication(customer as Customer);
|
|
||||||
await this.cardService.createCard(customer.id, data);
|
await this.cardService.createCard(customer.id, data);
|
||||||
return ResponseFactory.data(data);
|
return ResponseFactory.data(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Post('update-card-controls')
|
||||||
|
async updateCardControls(
|
||||||
|
@AuthenticatedUser() user: IJwtPayload,
|
||||||
|
@Body() { amount, count }: UpdateCardControlsRequestDto,
|
||||||
|
) {
|
||||||
|
const card = await this.cardService.getActiveCardForCustomer(user.sub);
|
||||||
|
await this.neoleapService.updateCardControl(card.cardReference, amount, count);
|
||||||
|
return ResponseFactory.data({ message: 'Card controls updated successfully' });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
export * from './account-transaction-webhook.request.dto';
|
export * from './account-transaction-webhook.request.dto';
|
||||||
export * from './card-transaction-webhook.request.dto';
|
export * from './card-transaction-webhook.request.dto';
|
||||||
|
export * from './update-card-controls.request.dto';
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
||||||
|
import { IsNumber, IsOptional, IsPositive } from 'class-validator';
|
||||||
|
|
||||||
|
export class UpdateCardControlsRequestDto {
|
||||||
|
@ApiProperty()
|
||||||
|
@IsNumber()
|
||||||
|
@IsPositive()
|
||||||
|
amount!: number;
|
||||||
|
|
||||||
|
@IsNumber()
|
||||||
|
@IsPositive()
|
||||||
|
@IsOptional()
|
||||||
|
@ApiPropertyOptional()
|
||||||
|
count?: number;
|
||||||
|
}
|
@ -1,2 +1,3 @@
|
|||||||
export * from './create-application.response.dto';
|
export * from './create-application.response.dto';
|
||||||
export * from './inquire-application.response';
|
export * from './inquire-application.response';
|
||||||
|
export * from './update-card-controls.response.dto';
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
export class UpdateCardControlsResponseDto {}
|
@ -1,3 +1,4 @@
|
|||||||
export * from './create-application.request.interface';
|
export * from './create-application.request.interface';
|
||||||
export * from './inquire-application.request.interface';
|
export * from './inquire-application.request.interface';
|
||||||
export * from './neoleap-header.request.interface';
|
export * from './neoleap-header.request.interface';
|
||||||
|
export * from './update-card-control.request.interface';
|
||||||
|
@ -0,0 +1,77 @@
|
|||||||
|
import { INeoleapHeaderRequest } from './neoleap-header.request.interface';
|
||||||
|
|
||||||
|
export interface IUpdateCardControlRequest extends INeoleapHeaderRequest {
|
||||||
|
UpdateCardControlsRequestDetails: {
|
||||||
|
InstitutionCode: string;
|
||||||
|
CardIdentifier: {
|
||||||
|
Id: string;
|
||||||
|
InstitutionCode: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
UsageTransactionLimit?: {
|
||||||
|
AmountLimit: number;
|
||||||
|
CountLimit: number;
|
||||||
|
};
|
||||||
|
DomesticCashDailyLimit?: {
|
||||||
|
AmountLimit: number;
|
||||||
|
CountLimit: number;
|
||||||
|
};
|
||||||
|
InternationalCashDailyLimit?: {
|
||||||
|
AmountLimit: number;
|
||||||
|
CountLimit: number;
|
||||||
|
};
|
||||||
|
DomesticPosDailyLimit?: {
|
||||||
|
AmountLimit: number;
|
||||||
|
CountLimit: number;
|
||||||
|
lenient?: boolean;
|
||||||
|
};
|
||||||
|
InternationalPosDailyLimit?: {
|
||||||
|
AmountLimit: number;
|
||||||
|
CountLimit: number;
|
||||||
|
};
|
||||||
|
EcommerceDailyLimit?: {
|
||||||
|
AmountLimit: number;
|
||||||
|
CountLimit: number;
|
||||||
|
};
|
||||||
|
DomesticCashMonthlyLimit?: {
|
||||||
|
AmountLimit: number;
|
||||||
|
CountLimit: number;
|
||||||
|
};
|
||||||
|
InternationalCashMonthlyLimit?: {
|
||||||
|
AmountLimit: number;
|
||||||
|
CountLimit: number;
|
||||||
|
};
|
||||||
|
DomesticPosMonthlyLimit?: {
|
||||||
|
AmountLimit: number;
|
||||||
|
CountLimit: number;
|
||||||
|
};
|
||||||
|
InternationalPosMonthlyLimit?: {
|
||||||
|
AmountLimit: number;
|
||||||
|
CountLimit: number;
|
||||||
|
};
|
||||||
|
EcommerceMonthlyLimit?: {
|
||||||
|
AmountLimit: number;
|
||||||
|
CountLimit: number;
|
||||||
|
};
|
||||||
|
DomesticCashTransactionLimit?: {
|
||||||
|
AmountLimit: number;
|
||||||
|
CountLimit: number;
|
||||||
|
};
|
||||||
|
InternationalCashTransactionLimit?: {
|
||||||
|
AmountLimit: number;
|
||||||
|
CountLimit: number;
|
||||||
|
};
|
||||||
|
DomesticPosTransactionLimit?: {
|
||||||
|
AmountLimit: number;
|
||||||
|
CountLimit: number;
|
||||||
|
};
|
||||||
|
InternationalPosTransactionLimit?: {
|
||||||
|
AmountLimit: number;
|
||||||
|
CountLimit: number;
|
||||||
|
};
|
||||||
|
EcommerceTransactionLimit?: {
|
||||||
|
AmountLimit: number;
|
||||||
|
CountLimit: number;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
@ -6,10 +6,15 @@ import moment from 'moment';
|
|||||||
import { v4 as uuid } from 'uuid';
|
import { v4 as uuid } from 'uuid';
|
||||||
import { CountriesNumericISO } from '~/common/constants';
|
import { CountriesNumericISO } from '~/common/constants';
|
||||||
import { Customer } from '~/customer/entities';
|
import { Customer } from '~/customer/entities';
|
||||||
import { Gender } from '~/customer/enums';
|
import { Gender, KycStatus } from '~/customer/enums';
|
||||||
import { CREATE_APPLICATION_MOCK, INQUIRE_APPLICATION_MOCK } from '../__mocks__/';
|
import { CREATE_APPLICATION_MOCK, INQUIRE_APPLICATION_MOCK } from '../__mocks__/';
|
||||||
import { CreateApplicationResponse, InquireApplicationResponse } from '../dtos/response';
|
import { CreateApplicationResponse, InquireApplicationResponse, UpdateCardControlsResponseDto } from '../dtos/response';
|
||||||
import { ICreateApplicationRequest, IInquireApplicationRequest, INeoleapHeaderRequest } from '../interfaces';
|
import {
|
||||||
|
ICreateApplicationRequest,
|
||||||
|
IInquireApplicationRequest,
|
||||||
|
INeoleapHeaderRequest,
|
||||||
|
IUpdateCardControlRequest,
|
||||||
|
} from '../interfaces';
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class NeoLeapService {
|
export class NeoLeapService {
|
||||||
private readonly baseUrl: string;
|
private readonly baseUrl: string;
|
||||||
@ -26,9 +31,15 @@ export class NeoLeapService {
|
|||||||
|
|
||||||
async createApplication(customer: Customer) {
|
async createApplication(customer: Customer) {
|
||||||
const responseKey = 'CreateNewApplicationResponseDetails';
|
const responseKey = 'CreateNewApplicationResponseDetails';
|
||||||
// if (customer.cards.length > 0) {
|
|
||||||
// throw new BadRequestException('CUSTOMER.ALREADY_HAS_CARD');
|
if (customer.kycStatus !== KycStatus.APPROVED) {
|
||||||
// }
|
throw new BadRequestException('CUSTOMER.KYC_NOT_APPROVED');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (customer.cards.length > 0) {
|
||||||
|
throw new BadRequestException('CUSTOMER.ALREADY_HAS_CARD');
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.useGateway) {
|
if (!this.useGateway) {
|
||||||
return plainToInstance(CreateApplicationResponse, CREATE_APPLICATION_MOCK[responseKey], {
|
return plainToInstance(CreateApplicationResponse, CREATE_APPLICATION_MOCK[responseKey], {
|
||||||
excludeExtraneousValues: true,
|
excludeExtraneousValues: true,
|
||||||
@ -132,6 +143,35 @@ export class NeoLeapService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async updateCardControl(cardId: string, amount: number, count?: number) {
|
||||||
|
const responseKey = 'UpdateCardControlResponseDetails';
|
||||||
|
if (!this.useGateway) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload: IUpdateCardControlRequest = {
|
||||||
|
UpdateCardControlsRequestDetails: {
|
||||||
|
InstitutionCode: this.institutionCode,
|
||||||
|
CardIdentifier: {
|
||||||
|
InstitutionCode: this.institutionCode,
|
||||||
|
Id: cardId,
|
||||||
|
},
|
||||||
|
UsageTransactionLimit: {
|
||||||
|
AmountLimit: amount,
|
||||||
|
CountLimit: count || 10,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
RequestHeader: this.prepareHeaders('UpdateCardControl'),
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.sendRequestToNeoLeap<IUpdateCardControlRequest, UpdateCardControlsResponseDto>(
|
||||||
|
'cardcontrol/UpdateCardControl',
|
||||||
|
payload,
|
||||||
|
responseKey,
|
||||||
|
UpdateCardControlsResponseDto,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private prepareHeaders(serviceName: string): INeoleapHeaderRequest['RequestHeader'] {
|
private prepareHeaders(serviceName: string): INeoleapHeaderRequest['RequestHeader'] {
|
||||||
return {
|
return {
|
||||||
Version: '1.0.0',
|
Version: '1.0.0',
|
||||||
@ -156,7 +196,7 @@ export class NeoLeapService {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (data.data?.ResponseHeader?.ResponseCode !== '000' || !data.data[responseKey]) {
|
if (data.data?.ResponseHeader?.ResponseCode !== '000') {
|
||||||
throw new BadRequestException(
|
throw new BadRequestException(
|
||||||
data.data.ResponseHeader.ResponseDescription || 'Unexpected Error from Service Provider',
|
data.data.ResponseHeader.ResponseDescription || 'Unexpected Error from Service Provider',
|
||||||
);
|
);
|
||||||
|
@ -58,6 +58,24 @@ export class CustomerResponseDto {
|
|||||||
@ApiProperty()
|
@ApiProperty()
|
||||||
waitingNumber!: number;
|
waitingNumber!: number;
|
||||||
|
|
||||||
|
@ApiProperty()
|
||||||
|
country!: string | null;
|
||||||
|
|
||||||
|
@ApiProperty()
|
||||||
|
region!: string | null;
|
||||||
|
|
||||||
|
@ApiProperty()
|
||||||
|
city!: string | null;
|
||||||
|
|
||||||
|
@ApiProperty()
|
||||||
|
neighborhood!: string | null;
|
||||||
|
|
||||||
|
@ApiProperty()
|
||||||
|
street!: string | null;
|
||||||
|
|
||||||
|
@ApiProperty()
|
||||||
|
building!: string | null;
|
||||||
|
|
||||||
@ApiPropertyOptional({ type: DocumentMetaResponseDto })
|
@ApiPropertyOptional({ type: DocumentMetaResponseDto })
|
||||||
profilePicture!: DocumentMetaResponseDto | null;
|
profilePicture!: DocumentMetaResponseDto | null;
|
||||||
|
|
||||||
@ -80,7 +98,12 @@ export class CustomerResponseDto {
|
|||||||
this.isJunior = customer.isJunior;
|
this.isJunior = customer.isJunior;
|
||||||
this.isGuardian = customer.isGuardian;
|
this.isGuardian = customer.isGuardian;
|
||||||
this.waitingNumber = customer.waitingNumber;
|
this.waitingNumber = customer.waitingNumber;
|
||||||
|
this.country = customer.country;
|
||||||
|
this.region = customer.region;
|
||||||
|
this.city = customer.city;
|
||||||
|
this.neighborhood = customer.neighborhood;
|
||||||
|
this.street = customer.street;
|
||||||
|
this.building = customer.building;
|
||||||
this.profilePicture = customer.profilePicture ? new DocumentMetaResponseDto(customer.profilePicture) : null;
|
this.profilePicture = customer.profilePicture ? new DocumentMetaResponseDto(customer.profilePicture) : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
import { BadRequestException, Injectable, Logger } from '@nestjs/common';
|
import { BadRequestException, Injectable, Logger } from '@nestjs/common';
|
||||||
|
import moment from 'moment';
|
||||||
import { Transactional } from 'typeorm-transactional';
|
import { Transactional } from 'typeorm-transactional';
|
||||||
|
import { CountryIso } from '~/common/enums';
|
||||||
import { DocumentService, OciService } from '~/document/services';
|
import { DocumentService, OciService } from '~/document/services';
|
||||||
import { GuardianService } from '~/guardian/services';
|
import { GuardianService } from '~/guardian/services';
|
||||||
import { CreateJuniorRequestDto } from '~/junior/dtos/request';
|
import { CreateJuniorRequestDto } from '~/junior/dtos/request';
|
||||||
|
import { User } from '~/user/entities';
|
||||||
import {
|
import {
|
||||||
CreateCustomerRequestDto,
|
CreateCustomerRequestDto,
|
||||||
CustomerFiltersRequestDto,
|
CustomerFiltersRequestDto,
|
||||||
@ -10,7 +13,7 @@ import {
|
|||||||
UpdateCustomerRequestDto,
|
UpdateCustomerRequestDto,
|
||||||
} from '../dtos/request';
|
} from '../dtos/request';
|
||||||
import { Customer } from '../entities';
|
import { Customer } from '../entities';
|
||||||
import { KycStatus } from '../enums';
|
import { Gender, KycStatus } from '../enums';
|
||||||
import { CustomerRepository } from '../repositories/customer.repository';
|
import { CustomerRepository } from '../repositories/customer.repository';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@ -125,6 +128,33 @@ export class CustomerService {
|
|||||||
this.logger.log(`KYC rejected for customer ${customerId}`);
|
this.logger.log(`KYC rejected for customer ${customerId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this function is for testing only and will be removed
|
||||||
|
@Transactional()
|
||||||
|
async updateKyc(userId: string) {
|
||||||
|
this.logger.log(`Updating KYC for customer ${userId}`);
|
||||||
|
await this.customerRepository.updateCustomer(userId, {
|
||||||
|
kycStatus: KycStatus.APPROVED,
|
||||||
|
gender: Gender.MALE,
|
||||||
|
nationalId: '1089055972',
|
||||||
|
nationalIdExpiry: moment('2031-09-17').toDate(),
|
||||||
|
countryOfResidence: CountryIso.SAUDI_ARABIA,
|
||||||
|
country: CountryIso.SAUDI_ARABIA,
|
||||||
|
region: 'Mecca',
|
||||||
|
city: 'AT Taif',
|
||||||
|
neighborhood: 'Al Faisaliah',
|
||||||
|
street: 'Al Faisaliah Street',
|
||||||
|
building: '4',
|
||||||
|
});
|
||||||
|
|
||||||
|
await User.update(userId, {
|
||||||
|
phoneNumber: this.generateSaudiPhoneNumber(),
|
||||||
|
countryCode: '+966',
|
||||||
|
});
|
||||||
|
|
||||||
|
this.logger.log(`KYC updated for customer ${userId}`);
|
||||||
|
return this.findCustomerById(userId);
|
||||||
|
}
|
||||||
|
|
||||||
private async validateProfilePictureForCustomer(userId: string, profilePictureId?: string) {
|
private async validateProfilePictureForCustomer(userId: string, profilePictureId?: string) {
|
||||||
if (!profilePictureId) return;
|
if (!profilePictureId) return;
|
||||||
|
|
||||||
@ -202,4 +232,15 @@ export class CustomerService {
|
|||||||
async findAnyCustomer() {
|
async findAnyCustomer() {
|
||||||
return this.customerRepository.findOne({ isGuardian: true });
|
return this.customerRepository.findOne({ isGuardian: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TO BE REMOVED: This function is for testing only and will be removed
|
||||||
|
private generateSaudiPhoneNumber(): string {
|
||||||
|
// Saudi mobile numbers are 9 digits, always starting with '5'
|
||||||
|
const firstDigit = '5';
|
||||||
|
let rest = '';
|
||||||
|
for (let i = 0; i < 8; i++) {
|
||||||
|
rest += Math.floor(Math.random() * 10);
|
||||||
|
}
|
||||||
|
return `${firstDigit}${rest}`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,8 @@
|
|||||||
},
|
},
|
||||||
"CUSTOMER": {
|
"CUSTOMER": {
|
||||||
"NOT_FOUND": "لم يتم العثور على العميل.",
|
"NOT_FOUND": "لم يتم العثور على العميل.",
|
||||||
"ALREADY_EXISTS": "العميل موجود بالفعل."
|
"ALREADY_EXISTS": "العميل موجود بالفعل.",
|
||||||
|
"KYC_NOT_APPROVED": "لم يتم الموافقة على هوية العميل بعد."
|
||||||
},
|
},
|
||||||
|
|
||||||
"GIFT": {
|
"GIFT": {
|
||||||
|
@ -42,7 +42,8 @@
|
|||||||
},
|
},
|
||||||
"CUSTOMER": {
|
"CUSTOMER": {
|
||||||
"NOT_FOUND": "The customer was not found.",
|
"NOT_FOUND": "The customer was not found.",
|
||||||
"ALREADY_EXISTS": "The customer already exists."
|
"ALREADY_EXISTS": "The customer already exists.",
|
||||||
|
"KYC_NOT_APPROVED": "The customer's KYC has not been approved yet."
|
||||||
},
|
},
|
||||||
|
|
||||||
"GIFT": {
|
"GIFT": {
|
||||||
|
Reference in New Issue
Block a user