chore: create legal and real user data info

This commit is contained in:
Matin
2025-02-17 15:43:12 +03:30
parent 14373bb665
commit 8b8ddb693e
18 changed files with 390 additions and 20 deletions
+26 -6
View File
@@ -1,32 +1,52 @@
import { ApiPropertyOptional } from "@nestjs/swagger";
import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
import { IsNotEmpty, IsOptional, IsString, IsUUID } from "class-validator";
import { FinancialMessage } from "../../../common/enums/message.enum";
export class CreateFinancialDto {
@ApiPropertyOptional({ description: "Economic code" })
export class CreateLegalUserDto {
@ApiProperty({ description: "Economic code" })
@IsOptional()
@IsString({ message: FinancialMessage.ECONOMIC_CODE_INVALID })
economicCode?: string;
@ApiPropertyOptional({ description: "Registration ID" })
@ApiProperty({ description: "Company registered name" })
@IsOptional()
@IsString({ message: FinancialMessage.ECONOMIC_CODE_INVALID })
companyRegisteredName?: string;
@ApiProperty({ description: "Registration ID" })
@IsOptional()
@IsString({ message: FinancialMessage.REGISTRATION_ID_INVALID })
registrationId?: string;
@ApiProperty({ description: "national Id" })
@IsOptional()
@IsString({ message: FinancialMessage.NATIONAL_ID_INVALID })
nationalId?: string;
@ApiPropertyOptional({ description: "number" })
@IsOptional()
@IsString({ message: FinancialMessage.FIXED_PHONE_INVALID })
number?: string;
@ApiPropertyOptional({ description: "number" })
@ApiPropertyOptional({ description: "postalCode" })
@IsOptional()
@IsString({ message: FinancialMessage.NATIONAL_ID_INVALID })
nationalId?: string;
postalCode?: string;
@ApiPropertyOptional({ description: "address" })
@IsOptional()
@IsString({ message: FinancialMessage.NATIONAL_ID_INVALID })
address?: string;
@ApiPropertyOptional({ description: "User id", example: "123e4567-e89b-12d3-a456-426614174000" })
@IsOptional()
@IsNotEmpty({ message: FinancialMessage.USER_ID_REQUIRED })
@IsUUID("4", { message: FinancialMessage.USER_ID_SHOULD_BE_A_UUID })
userId: string;
@ApiPropertyOptional({ description: "City id", example: "1" })
@IsOptional()
@IsNotEmpty({ message: FinancialMessage.CITY_ID_REQUIRED })
cityId: string;
}
+16 -1
View File
@@ -4,7 +4,7 @@ import { IsEnum, IsNotEmpty, IsOptional, IsString, IsUUID } from "class-validato
import { FinancialMessage } from "../../../common/enums/message.enum";
import { GenderType } from "../enums/gender-type.enum";
export class CreateFinancialDto {
export class CreateRealUserDto {
@ApiPropertyOptional({ enum: GenderType, description: "Gender type" })
@IsOptional()
@IsEnum(GenderType, { message: FinancialMessage.GENDER_TYPE_INVALID })
@@ -30,9 +30,24 @@ export class CreateFinancialDto {
@IsString({ message: FinancialMessage.NATIONAL_ID_INVALID })
nationalId?: string;
@ApiPropertyOptional({ description: "Address" })
@IsOptional()
@IsString({ message: FinancialMessage.ADDRESS_ID_INVALID })
address?: string;
@ApiPropertyOptional({ description: "PostalCode" })
@IsOptional()
@IsString({ message: FinancialMessage.ADDRESS_ID_INVALID })
postalCode?: string;
@ApiPropertyOptional({ description: "User id", example: "123e4567-e89b-12d3-a456-426614174000" })
@IsOptional()
@IsNotEmpty({ message: FinancialMessage.USER_ID_REQUIRED })
@IsUUID("4", { message: FinancialMessage.USER_ID_SHOULD_BE_A_UUID })
userId: string;
@ApiPropertyOptional({ description: "City id", example: "1" })
@IsOptional()
@IsNotEmpty({ message: FinancialMessage.CITY_ID_REQUIRED })
cityId: string;
}
+46
View File
@@ -0,0 +1,46 @@
import { ApiProperty, PartialType } from "@nestjs/swagger";
import { IsEmail, IsMobilePhone, IsNotEmpty, IsNumberString, IsString, Length, MinLength } from "class-validator";
import { CreateLegalUserDto } from "./create-legal-user.dto";
import { AuthMessage } from "../../../common/enums/message.enum";
export class CreateUserDto extends PartialType(CreateLegalUserDto) {
@IsNotEmpty({ message: AuthMessage.PHONE_NOT_EMPTY })
@IsMobilePhone("fa-IR", {}, { message: AuthMessage.INVALID_PHONE_FORMAT })
@ApiProperty({ description: "phone number", default: "09123456789" })
phone: string;
@IsNotEmpty({ message: AuthMessage.FIRST_NAME_NOT_EMPTY })
@IsString({ message: AuthMessage.FIRST_NAME_NOT_EMPTY })
@Length(2, 50, { message: AuthMessage.FIRST_NAME_SHOULD_BE_BETWEEN_2_AND_50 })
@ApiProperty({ description: "First name", example: "mahyar" })
firstName: string;
@IsNotEmpty({ message: AuthMessage.LAST_NAME_NOT_EMPTY })
@IsString({ message: AuthMessage.LAST_NAME_NOT_EMPTY })
@Length(2, 50, { message: AuthMessage.LAST_NAME_SHOULD_BE_BETWEEN_2_AND_50 })
@ApiProperty({ description: "Last name", example: "jamshidi" })
lastName: string;
@IsNotEmpty({ message: AuthMessage.EMAIL_NOT_EMPTY })
@IsEmail({}, { message: AuthMessage.INVALID_EMAIL_FORMAT })
@ApiProperty({ description: "Email", example: "ma@gmail.com" })
email: string;
@IsNotEmpty({ message: AuthMessage.BIRTH_DATE_NOT_EMPTY })
@IsString({ message: AuthMessage.BIRTH_DATE_NOT_EMPTY })
@ApiProperty({ description: "Birth date", example: "1403/01/01" })
birthDate: string;
@IsNotEmpty({ message: AuthMessage.NATIONAL_NOT_EMPTY })
@IsNumberString({ no_symbols: true }, { message: AuthMessage.NATIONAL_CODE_INCORRECT })
@Length(10, 10, { message: AuthMessage.NATIONAL_CODE_INCORRECT })
@ApiProperty({ description: "iranian format (10 char)", example: "4569852169" })
nationalCode: string;
@IsNotEmpty({ message: AuthMessage.PASSWORD_NOT_EMPTY })
@IsString({ message: AuthMessage.PASSWORD_FORMAT_INVALID })
@ApiProperty({ description: "password", example: "12S345SS678" })
@MinLength(8, { message: AuthMessage.PASSWORD_LENGTH })
password: string;
}
@@ -2,22 +2,30 @@ import { Column, Entity, JoinColumn, OneToOne, Unique } from "typeorm";
import { User } from "./user.entity";
import { BaseEntity } from "../../../common/entities/base.entity";
import { Address } from "../../address/entities/address.entity";
@Unique(["user"])
@Entity()
export class LegalUser extends BaseEntity {
@Column({ nullable: true })
@Column({ type: "varchar", length: 50, nullable: true })
economicCode: string;
@Column({ nullable: true })
@Column({ type: "varchar", length: 50, nullable: true })
registrationId: string;
@Column({ nullable: true })
@Column({ type: "varchar", length: 100, nullable: true })
companyRegisteredName: string;
@Column({ type: "varchar", length: 20, nullable: true })
nationalId: string;
@Column({ nullable: true })
@Column({ type: "varchar", length: 20, nullable: true })
number: string;
@OneToOne(() => Address, { nullable: false, cascade: true })
@JoinColumn()
address: Address;
@OneToOne(() => User, (user) => user.legalUser, { onDelete: "CASCADE" })
@JoinColumn()
user: User;
@@ -2,6 +2,7 @@ import { Column, Entity, JoinColumn, OneToOne, Unique } from "typeorm";
import { User } from "./user.entity";
import { BaseEntity } from "../../../common/entities/base.entity";
import { Address } from "../../address/entities/address.entity";
import { GenderType } from "../enums/gender-type.enum";
@Unique(["user"])
@@ -20,6 +21,10 @@ export class RealUser extends BaseEntity {
@Column({ nullable: true })
nationality: string;
@OneToOne(() => Address, { nullable: false, cascade: true })
@JoinColumn()
address: Address;
@OneToOne(() => User, (user) => user.realUser, { onDelete: "CASCADE" })
@JoinColumn()
user: User;
+6 -1
View File
@@ -1,11 +1,12 @@
import { Exclude } from "class-transformer";
import { Column, Entity, JoinTable, ManyToMany, OneToMany, OneToOne } from "typeorm";
import { Column, Entity, JoinColumn, JoinTable, ManyToMany, OneToMany, OneToOne } from "typeorm";
import { LegalUser } from "./legal-user.entity";
import { RealUser } from "./real-user.entity";
import { Role } from "./role.entity";
import { UserGroup } from "./user-group.entity";
import { BaseEntity } from "../../../common/entities/base.entity";
import { Address } from "../../address/entities/address.entity";
import { UserAnnouncement } from "../../announcements/entities/user-announcement.entity";
import { Criticism } from "../../criticisms/entities/criticism.entity";
import { DanakServiceReview } from "../../danak-services/entities/danak-service-review.entity";
@@ -106,6 +107,10 @@ export class User extends BaseEntity {
@OneToOne(() => LegalUser, (legalUser) => legalUser.user, { cascade: true, nullable: true })
legalUser: LegalUser;
@OneToOne(() => Address, (address) => address.user, { cascade: true, nullable: true })
@JoinColumn()
address: Address;
}
// @ManyToMany(() => DanakService, (danakService) => danakService.users)
+101 -2
View File
@@ -2,8 +2,15 @@ import { BadRequestException, Injectable } from "@nestjs/common";
import slugify from "slugify";
import { In, Not, QueryRunner } from "typeorm";
// import { CreateFinancialDto } from "../DTO/create-legal-user.dto";
import { AdminMessage, AdsMessage, CommonMessage, UserMessage } from "../../../common/enums/message.enum";
import {
AdminMessage,
AdsMessage,
CommonMessage,
LegalUserMessage,
RealUserMessage,
UserMessage,
} from "../../../common/enums/message.enum";
import { AddressService } from "../../address/providers/address.service";
import { CompleteRegistrationDto } from "../../auth/DTO/complete-register.dto";
import { UserSettingsService } from "../../settings/providers/user-settings.service";
import { PaginationUtils } from "../../utils/providers/pagination.utils";
@@ -11,6 +18,8 @@ import { PasswordService } from "../../utils/providers/password.service";
import { WalletsService } from "../../wallets/providers/wallets.service";
import { CheckValidityDTO } from "../DTO/check-validity.dto";
import { CreateAdminDto } from "../DTO/create-admin.dto";
import { CreateLegalUserDto } from "../DTO/create-legal-user.dto";
import { CreateRealUserDto } from "../DTO/create-real-user.dto";
import { CreateRoleDto } from "../DTO/create-role.dto";
import { SearchAdminQueryDto } from "../DTO/search-admins-query.dto";
import { SearchCustomersDto } from "../DTO/search-customers.dto";
@@ -21,7 +30,9 @@ import { Role } from "../entities/role.entity";
import { User } from "../entities/user.entity";
import { RoleEnum } from "../enums/role.enum";
import { ValidityType } from "../enums/validity-type.enum";
import { LegalUserRepository } from "../repositories/legal-user.repository";
import { PermissionsRepository } from "../repositories/permissions.repository";
import { RealUserRepository } from "../repositories/real-user.repository";
import { RoleRepository } from "../repositories/roles.repository";
import { UserGroupRepository } from "../repositories/user-group.repository";
import { UserRepository } from "../repositories/users.repository";
@@ -36,6 +47,9 @@ export class UsersService {
private readonly rolesRepository: RoleRepository,
private readonly permissionsRepository: PermissionsRepository,
private readonly passwordService: PasswordService,
private readonly realUserRepository: RealUserRepository,
private readonly legalUserRepository: LegalUserRepository,
private readonly addressService: AddressService,
) {}
/************************************************************ */
@@ -63,6 +77,22 @@ export class UsersService {
/************************************************************ */
async getMyFinancialInfo(userId: string) {
const user = await this.userRepository
.createQueryBuilder("user")
.leftJoinAndSelect("user.address", "address")
.leftJoinAndSelect("address.city", "city")
.leftJoinAndSelect("city.province", "province")
.leftJoinAndSelect("user.realUser", "realUser")
.leftJoinAndSelect("user.legalUser", "legalUser")
.where("user.id = :id", { id: userId })
.getOne();
if (!user) throw new BadRequestException(UserMessage.USER_NOT_FOUND);
return { user };
}
/************************************************************ */
async updateProfile(userId: string, updateProfileDto: UpdateProfileDto) {
if (updateProfileDto.userName) {
//
@@ -347,5 +377,74 @@ export class UsersService {
};
}
async createRealUserData(createDto: CreateRealUserDto, userId: string) {
const userExist = await this.userRepository.findOneBy({
id: userId,
});
if (!userExist) throw new BadRequestException(UserMessage.USER_NOT_FOUND);
console.log(userExist);
const existingRealUser = await this.realUserRepository.findOne({
where: { user: { id: userExist.id } },
});
console.log(existingRealUser);
if (existingRealUser) throw new BadRequestException(RealUserMessage.REAL_DATA_EXIST);
const { city } = await this.addressService.getCity(+createDto.cityId);
const realUser = this.realUserRepository.create({
...createDto,
user: userExist,
address: {
address: createDto.address,
city,
postalCode: createDto.postalCode,
user: userExist,
},
});
await this.realUserRepository.save(realUser);
return {
message: CommonMessage.CREATED,
realUser,
};
}
// /************************************************************ */
async createLegalUserData(createDto: CreateLegalUserDto, userId: string) {
const userExist = await this.userRepository.findOneBy({
id: userId,
});
if (!userExist) throw new BadRequestException(UserMessage.USER_NOT_FOUND);
const existingLegalUser = await this.legalUserRepository.findOne({
where: { user: { id: userExist.id } },
});
if (existingLegalUser) throw new BadRequestException(LegalUserMessage.LEGAL_DATA_EXIST);
const { city } = await this.addressService.getCity(+createDto.cityId);
const legalUser = this.legalUserRepository.create({
...createDto,
user: userExist,
address: {
address: createDto.address,
city,
postalCode: createDto.postalCode,
user: userExist,
},
});
await this.legalUserRepository.save(legalUser);
return {
message: CommonMessage.CREATED,
legalUser,
};
}
/************************************************************ */
}
+32
View File
@@ -3,6 +3,8 @@ import { ApiOperation, ApiTags } from "@nestjs/swagger";
import { CheckValidityDTO } from "./DTO/check-validity.dto";
import { CreateAdminDto } from "./DTO/create-admin.dto";
import { CreateLegalUserDto } from "./DTO/create-legal-user.dto";
import { CreateRealUserDto } from "./DTO/create-real-user.dto";
import { CreateRoleDto } from "./DTO/create-role.dto";
import { SearchAdminQueryDto } from "./DTO/search-admins-query.dto";
import { SearchCustomersDto } from "./DTO/search-customers.dto";
@@ -32,6 +34,15 @@ export class UsersController {
/************************************************************ */
@AuthGuards()
@ApiOperation({ summary: "Get user financial info" })
@Get("me/financial-info")
getFinancialInfo(@UserDec() user: User) {
return this.usersService.getMyFinancialInfo(user.id);
}
/************************************************************ */
@AuthGuards()
@ApiOperation({ summary: "Update user profile" })
@Patch("update-profile")
@@ -126,4 +137,25 @@ export class UsersController {
createRole(@Body() createDto: CreateRoleDto) {
return this.usersService.createRole(createDto);
}
/************************************************************ */
@AuthGuards()
@ApiOperation({ summary: "Create real user data" })
@HttpCode(HttpStatus.CREATED)
@Post("real-user")
createRealUser(@Body() createDto: CreateRealUserDto, @UserDec("id") userId: string) {
return this.usersService.createRealUserData(createDto, userId);
}
/************************************************************ */
@AuthGuards()
@ApiOperation({ summary: "Create legal user data" })
@HttpCode(HttpStatus.CREATED)
@Post("legal-user")
createLegalUser(@Body() createDto: CreateLegalUserDto, @UserDec("id") userId: string) {
return this.usersService.createLegalUserData(createDto, userId);
}
/************************************************************ */
}
+13
View File
@@ -12,17 +12,29 @@ import { PermissionsRepository } from "./repositories/permissions.repository";
import { RoleRepository } from "./repositories/roles.repository";
import { UserGroupRepository } from "./repositories/user-group.repository";
import { UserRepository } from "./repositories/users.repository";
<<<<<<< HEAD
=======
import { UsersController } from "./users.controller";
import { AddressModule } from "../address/address.module";
>>>>>>> 5908724 (chore: create legal and real user data info)
import { UserSetting } from "../settings/entities/user-setting.entity";
import { UserSettingsService } from "../settings/providers/user-settings.service";
import { UserSettingsRepository } from "../settings/repositories/user-settings.repository";
import { WalletsModule } from "../wallets/wallets.module";
import { RealUser } from "./entities/real-user.entity";
import { RealUserRepository } from "./repositories/real-user.repository";
<<<<<<< HEAD
import { UsersController } from "./users.controller";
import { UtilsModule } from "../utils/utils.module";
@Module({
imports: [TypeOrmModule.forFeature([User, Role, UserGroup, UserSetting, RealUser, LegalUser, Permission]), WalletsModule, UtilsModule],
=======
import { AddressService } from "../address/providers/address.service";
@Module({
imports: [TypeOrmModule.forFeature([User, Role, UserGroup, UserSetting, RealUser, LegalUser]), WalletsModule, AddressModule],
>>>>>>> 5908724 (chore: create legal and real user data info)
providers: [
UsersService,
UserRepository,
@@ -33,6 +45,7 @@ import { UtilsModule } from "../utils/utils.module";
PermissionsRepository,
RealUserRepository,
LegalUserRepository,
AddressService,
],
controllers: [UsersController],
exports: [UsersService, UserRepository],