mirror of
https://github.com/HamzaSha1/zod-backend.git
synced 2026-10-25 06:07:57 +00:00
- Added address fields to registration (verify-user DTO) - Added address fields to KYC initiation (initiate-kyc DTO) - Added national_id column to kyc_transactions table - Changed duplicate KYC check from customerId to nationalId - Added KYC webhook endpoint (/api/neoleap-webhooks/kyc) - Added webhook processing logic - Updated customer service to save address during registration and KYC - Added validation to require address before card creation - Removed duplicate src/migrations/ directory
105 lines
4.0 KiB
TypeScript
105 lines
4.0 KiB
TypeScript
import { ApiProperty } from '@nestjs/swagger';
|
|
import {
|
|
IsEnum,
|
|
IsNotEmpty,
|
|
IsNumberString,
|
|
IsOptional,
|
|
IsString,
|
|
Matches,
|
|
MaxLength,
|
|
MinLength,
|
|
} from 'class-validator';
|
|
import { i18nValidationMessage as i18n } from 'nestjs-i18n';
|
|
import { COUNTRY_CODE_REGEX, PASSWORD_REGEX } from '~/auth/constants';
|
|
import { CountryIso } from '~/common/enums';
|
|
import { DEFAULT_OTP_LENGTH } from '~/common/modules/otp/constants';
|
|
import { IsValidPhoneNumber } from '~/core/decorators/validations';
|
|
|
|
export class VerifyUserRequestDto {
|
|
@ApiProperty({ example: '+962' })
|
|
@Matches(COUNTRY_CODE_REGEX, {
|
|
message: i18n('validation.Matches', { path: 'general', property: 'auth.countryCode' }),
|
|
})
|
|
countryCode!: string;
|
|
|
|
@ApiProperty({ example: '787259134' })
|
|
@IsValidPhoneNumber({
|
|
message: i18n('validation.IsValidPhoneNumber', { path: 'general', property: 'auth.phoneNumber' }),
|
|
})
|
|
phoneNumber!: string;
|
|
@ApiProperty({ example: 'John' })
|
|
@IsString({ message: i18n('validation.IsString', { path: 'general', property: 'customer.firstName' }) })
|
|
@IsNotEmpty({ message: i18n('validation.IsNotEmpty', { path: 'general', property: 'customer.firstName' }) })
|
|
firstName!: string;
|
|
|
|
@ApiProperty({ example: 'Doe' })
|
|
@IsString({ message: i18n('validation.IsString', { path: 'general', property: 'customer.lastName' }) })
|
|
@IsNotEmpty({ message: i18n('validation.IsNotEmpty', { path: 'general', property: 'customer.lastName' }) })
|
|
lastName!: string;
|
|
|
|
@ApiProperty({ example: 'JO' })
|
|
@IsEnum(CountryIso, {
|
|
message: i18n('validation.IsEnum', { path: 'general', property: 'customer.countryOfResidence' }),
|
|
})
|
|
@IsOptional()
|
|
countryOfResidence: CountryIso = CountryIso.SAUDI_ARABIA;
|
|
|
|
// Address fields (optional during registration, required for card creation)
|
|
@ApiProperty({ example: 'SA', description: 'Country code', required: false })
|
|
@IsEnum(CountryIso, {
|
|
message: i18n('validation.IsEnum', { path: 'general', property: 'customer.country' }),
|
|
})
|
|
@IsOptional()
|
|
country?: CountryIso;
|
|
|
|
@ApiProperty({ example: 'Riyadh', description: 'Region/Province', required: false })
|
|
@IsString({ message: i18n('validation.IsString', { path: 'general', property: 'customer.region' }) })
|
|
@IsOptional()
|
|
region?: string;
|
|
|
|
@ApiProperty({ example: 'Riyadh', description: 'City', required: false })
|
|
@IsString({ message: i18n('validation.IsString', { path: 'general', property: 'customer.city' }) })
|
|
@IsOptional()
|
|
city?: string;
|
|
|
|
@ApiProperty({ example: 'Al Olaya', description: 'Neighborhood/District', required: false })
|
|
@IsString({ message: i18n('validation.IsString', { path: 'general', property: 'customer.neighborhood' }) })
|
|
@IsOptional()
|
|
neighborhood?: string;
|
|
|
|
@ApiProperty({ example: 'King Fahd Road', description: 'Street name', required: false })
|
|
@IsString({ message: i18n('validation.IsString', { path: 'general', property: 'customer.street' }) })
|
|
@IsOptional()
|
|
street?: string;
|
|
|
|
@ApiProperty({ example: '123', description: 'Building number', required: false })
|
|
@IsString({ message: i18n('validation.IsString', { path: 'general', property: 'customer.building' }) })
|
|
@IsOptional()
|
|
building?: string;
|
|
|
|
@ApiProperty({ example: 'Abcd1234@' })
|
|
@Matches(PASSWORD_REGEX, {
|
|
message: i18n('validation.Matches', { path: 'general', property: 'auth.password' }),
|
|
})
|
|
password!: string;
|
|
|
|
@ApiProperty({ example: 'Abcd1234@' })
|
|
@Matches(PASSWORD_REGEX, {
|
|
message: i18n('validation.Matches', { path: 'general', property: 'auth.confirmPassword' }),
|
|
})
|
|
confirmPassword!: string;
|
|
|
|
@ApiProperty({ example: '111111' })
|
|
@IsNumberString(
|
|
{ no_symbols: true },
|
|
{ message: i18n('validation.IsNumberString', { path: 'general', property: 'auth.otp' }) },
|
|
)
|
|
@MaxLength(DEFAULT_OTP_LENGTH, {
|
|
message: i18n('validation.MaxLength', { path: 'general', property: 'auth.otp', length: DEFAULT_OTP_LENGTH }),
|
|
})
|
|
@MinLength(DEFAULT_OTP_LENGTH, {
|
|
message: i18n('validation.MinLength', { path: 'general', property: 'auth.otp', length: DEFAULT_OTP_LENGTH }),
|
|
})
|
|
otp!: string;
|
|
}
|