From 8b8ddb693ea1e97d22cc8ec406a3c84a0c565c5e Mon Sep 17 00:00:00 2001 From: Matin Date: Mon, 17 Feb 2025 15:43:12 +0330 Subject: [PATCH] chore: create legal and real user data info --- database/seeder.runner.ts | 2 +- src/common/DTO/param.dto.ts | 6 + src/common/enums/message.enum.ts | 13 +++ src/modules/address/address.controller.ts | 15 ++- src/modules/address/address.module.ts | 7 +- .../address/entities/address.entity.ts | 20 ++++ src/modules/address/entities/city.entity.ts | 6 +- .../address/providers/address.service.ts | 58 +++++++++- .../repositories/address.repository.ts | 12 ++ .../users/DTO/create-legal-user.dto.ts | 32 +++++- src/modules/users/DTO/create-real-user.dto.ts | 17 ++- src/modules/users/DTO/create-user.dto.ts | 46 ++++++++ .../users/entities/legal-user.entity.ts | 16 ++- .../users/entities/real-user.entity.ts | 5 + src/modules/users/entities/user.entity.ts | 7 +- src/modules/users/providers/users.service.ts | 103 +++++++++++++++++- src/modules/users/users.controller.ts | 32 ++++++ src/modules/users/users.module.ts | 13 +++ 18 files changed, 390 insertions(+), 20 deletions(-) create mode 100644 src/modules/address/repositories/address.repository.ts create mode 100644 src/modules/users/DTO/create-user.dto.ts diff --git a/database/seeder.runner.ts b/database/seeder.runner.ts index 0fb8930..c6cf884 100644 --- a/database/seeder.runner.ts +++ b/database/seeder.runner.ts @@ -13,11 +13,11 @@ export const runSeeder = async () => { await connectionSource.initialize(); logger.log("start seeding database"); // - await seedCityAndProvince(connectionSource, logger); await seedPermissionsAndRoles(connectionSource, logger); await seedAdmin(connectionSource, logger); await seedNotifSettings(connectionSource, logger); await seedPaymentGateways(connectionSource, logger); + await seedCityAndProvince(connectionSource, logger); logger.log("seeding completed"); process.exit(0); diff --git a/src/common/DTO/param.dto.ts b/src/common/DTO/param.dto.ts index 32d9674..5201875 100644 --- a/src/common/DTO/param.dto.ts +++ b/src/common/DTO/param.dto.ts @@ -9,3 +9,9 @@ export class ParamDto { @ApiProperty({ description: "Id of the entity", example: "8b1e8b1e-8b1e-8b1e-8b1e-8b1e8b1e8b1e" }) id: string; } + +export class ParamNumberIdDto { + @IsNotEmpty({ message: CommonMessage.ID_REQUIRED }) + @ApiProperty({ description: "Id of the entity", example: "20" }) + id: string; +} diff --git a/src/common/enums/message.enum.ts b/src/common/enums/message.enum.ts index 3edc7c4..ee155fe 100644 --- a/src/common/enums/message.enum.ts +++ b/src/common/enums/message.enum.ts @@ -391,9 +391,12 @@ export const enum FinancialMessage { GENDER_TYPE_INVALID = "نوع جنسیت باید یکی از مقادیر FEMALE یا MALE باشد", ECONOMIC_CODE_INVALID = "کد اقتصادی باید یک رشته باشد", REGISTRATION_ID_INVALID = "شناسه ثبت باید یک رشته باشد", + ADDRESS_ID_INVALID = "ادرس باید یک رشته باشد", + POSTALCODE_INVALID = "کد پستی باید یک رشته باشد", NATIONAL_ID_INVALID = "شناسه ملی باید یک رشته باشد", FIXED_PHONE_INVALID = "شماره تماس ثابت باید یک رشته باشد", USER_ID_REQUIRED = "شناسه کاربر مورد نیاز است", + CITY_ID_REQUIRED = "شناسه شهر مورد نیاز است", USER_ID_SHOULD_BE_A_UUID = "شناسه کاربر باید یک UUID معتبر باشد", FINANCIAL_INFO_ALREADY_EXISTS = "دیتا اطلاعات مالی وجود دارد", FINANCIAL_INFO_NOT_FOUND = "دیتا اطلاعات مالی یافت نشد", @@ -450,8 +453,18 @@ export const enum AdsMessage { export const enum ProvinceMessage { SEARCH_QUERY_MUST_BE_A_STRING = "رشته جستجو باید یک رشته باشد", + NOT_FOUND = "استانی با این مشخصات یافت نشد", } export const enum CityMessage { SEARCH_QUERY_MUST_BE_A_STRING = "رشته جستجو باید یک رشته باشد", + NOT_FOUND = "شهری با این مشخصات یافت نشد", +} + +export const enum RealUserMessage { + REAL_DATA_EXIST = "اطلاعات حقیقی این کاربر وجود دارد", +} + +export const enum LegalUserMessage { + LEGAL_DATA_EXIST = "اطلاعات حقوقی این کاربر وجود دارد", } diff --git a/src/modules/address/address.controller.ts b/src/modules/address/address.controller.ts index 9b1b79c..091c05c 100644 --- a/src/modules/address/address.controller.ts +++ b/src/modules/address/address.controller.ts @@ -1,9 +1,10 @@ -import { Controller, Get, Query } from "@nestjs/common"; +import { Controller, Get, Param, Query } from "@nestjs/common"; import { ApiOperation } from "@nestjs/swagger"; import { SearchCitiesDto } from "./DTO/cities-search-query.dto"; import { SearchProvincesDto } from "./DTO/provinces-search-query.dto"; import { AddressService } from "./providers/address.service"; +import { ParamNumberIdDto } from "../../common/DTO/param.dto"; @Controller("address") export class AddressController { @@ -20,4 +21,16 @@ export class AddressController { getProvincesList(@Query() queryDto: SearchProvincesDto) { return this.addressService.getAllProvinces(queryDto); } + + @ApiOperation({ summary: "Get cities of provinces" }) + @Get("provinces/:id/cities") + getCitiesByProvinces(@Query() queryDto: SearchProvincesDto, @Param() paramDto: ParamNumberIdDto) { + return this.addressService.getCitiesByProvince(queryDto, +paramDto.id); + } + + @ApiOperation({ summary: "Get province of city" }) + @Get("cities/:id/province") + getProvinceByCity(@Param() paramDto: ParamNumberIdDto) { + return this.addressService.getProvinceByCity(+paramDto.id); + } } diff --git a/src/modules/address/address.module.ts b/src/modules/address/address.module.ts index c013c6e..eca11d2 100644 --- a/src/modules/address/address.module.ts +++ b/src/modules/address/address.module.ts @@ -2,15 +2,18 @@ import { Module } from "@nestjs/common"; import { TypeOrmModule } from "@nestjs/typeorm"; import { AddressController } from "./address.controller"; +import { Address } from "./entities/address.entity"; import { City } from "./entities/city.entity"; import { Province } from "./entities/province.entity"; import { AddressService } from "./providers/address.service"; +import { AddressRepository } from "./repositories/address.repository"; import { CityRepository } from "./repositories/city.repository"; import { ProvinceRepository } from "./repositories/province.repository"; @Module({ - imports: [TypeOrmModule.forFeature([City, Province])], - providers: [AddressService, CityRepository, ProvinceRepository], + imports: [TypeOrmModule.forFeature([City, Province, Address])], + providers: [AddressService, CityRepository, ProvinceRepository, AddressRepository], controllers: [AddressController], + exports: [TypeOrmModule, CityRepository, ProvinceRepository, AddressService], }) export class AddressModule {} diff --git a/src/modules/address/entities/address.entity.ts b/src/modules/address/entities/address.entity.ts index e69de29..d296194 100644 --- a/src/modules/address/entities/address.entity.ts +++ b/src/modules/address/entities/address.entity.ts @@ -0,0 +1,20 @@ +import { Column, Entity, ManyToOne, OneToOne } from "typeorm"; + +import { City } from "./city.entity"; +import { BaseEntity } from "../../../common/entities/base.entity"; +import { User } from "../../users/entities/user.entity"; + +@Entity() +export class Address extends BaseEntity { + @Column({ type: "varchar", length: 255, nullable: true }) + address: string; + + @Column({ type: "varchar", length: 10, nullable: true }) + postalCode: string; + + @ManyToOne(() => City, (city) => city.addresses, { nullable: false }) + city: City; + + @OneToOne(() => User, (user) => user.address, { onDelete: "CASCADE" }) + user: User; +} diff --git a/src/modules/address/entities/city.entity.ts b/src/modules/address/entities/city.entity.ts index 312819e..61b9a30 100644 --- a/src/modules/address/entities/city.entity.ts +++ b/src/modules/address/entities/city.entity.ts @@ -1,5 +1,6 @@ -import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from "typeorm"; +import { Column, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm"; +import { Address } from "./address.entity"; import { Province } from "./province.entity"; @Entity() @@ -10,6 +11,9 @@ export class City { @Column({ type: "varchar", length: 255 }) name: string; + @OneToMany(() => Address, (address) => address.city) + addresses: Address[]; + @ManyToOne(() => Province, (province) => province.cities, { nullable: false }) province: Province; } diff --git a/src/modules/address/providers/address.service.ts b/src/modules/address/providers/address.service.ts index eda58a0..1949491 100644 --- a/src/modules/address/providers/address.service.ts +++ b/src/modules/address/providers/address.service.ts @@ -1,5 +1,6 @@ -import { Injectable } from "@nestjs/common"; +import { BadRequestException, Injectable } from "@nestjs/common"; +import { CityMessage, ProvinceMessage } from "../../../common/enums/message.enum"; import { PaginationUtils } from "../../utils/providers/pagination.utils"; import { SearchCitiesDto } from "../DTO/cities-search-query.dto"; import { CityRepository } from "../repositories/city.repository"; @@ -51,4 +52,59 @@ export class AddressService { paginate: true, }; } + + async getProvince(id: number) { + const province = await this.provinceRepository.findOneBy({ + id, + }); + if (!province) throw new BadRequestException(CityMessage.NOT_FOUND); + + return { province }; + } + + async getCity(id: number) { + const city = await this.cityRepository.findOneBy({ + id, + }); + if (!city) throw new BadRequestException(CityMessage.NOT_FOUND); + + return { city }; + } + + async getCitiesByProvince(queryDto: SearchCitiesDto, id: number) { + const { limit, skip } = PaginationUtils(queryDto); + + const province = await this.provinceRepository.findOneBy({ + id, + }); + if (!province) throw new BadRequestException(CityMessage.NOT_FOUND); + + const queryBuilder = this.cityRepository.createQueryBuilder("city").where("city.provinceId = :provinceId", { provinceId: province.id }); + if (queryDto.q) { + queryBuilder.andWhere("city.name ILIKE :q", { q: `%${queryDto.q}%` }); + } + + queryBuilder.skip(skip).take(limit); + + const [cities, count] = await queryBuilder.getManyAndCount(); + + return { + cities, + count, + pagination: true, + }; + } + + async getProvinceByCity(id: number) { + const province = await this.provinceRepository.findOne({ + where: { + cities: { + id, + }, + }, + }); + if (!province) throw new BadRequestException(ProvinceMessage.NOT_FOUND); + + return { province }; + } } diff --git a/src/modules/address/repositories/address.repository.ts b/src/modules/address/repositories/address.repository.ts new file mode 100644 index 0000000..09ca867 --- /dev/null +++ b/src/modules/address/repositories/address.repository.ts @@ -0,0 +1,12 @@ +import { Injectable } from "@nestjs/common"; +import { InjectRepository } from "@nestjs/typeorm"; +import { Repository } from "typeorm"; + +import { Address } from "../entities/address.entity"; + +@Injectable() +export class AddressRepository extends Repository
{ + constructor(@InjectRepository(Address) addressRepository: Repository
) { + super(addressRepository.target, addressRepository.manager, addressRepository.queryRunner); + } +} diff --git a/src/modules/users/DTO/create-legal-user.dto.ts b/src/modules/users/DTO/create-legal-user.dto.ts index 7170a1a..87c0479 100644 --- a/src/modules/users/DTO/create-legal-user.dto.ts +++ b/src/modules/users/DTO/create-legal-user.dto.ts @@ -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; } diff --git a/src/modules/users/DTO/create-real-user.dto.ts b/src/modules/users/DTO/create-real-user.dto.ts index aa157b0..6d6a66d 100644 --- a/src/modules/users/DTO/create-real-user.dto.ts +++ b/src/modules/users/DTO/create-real-user.dto.ts @@ -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; } diff --git a/src/modules/users/DTO/create-user.dto.ts b/src/modules/users/DTO/create-user.dto.ts new file mode 100644 index 0000000..24656c2 --- /dev/null +++ b/src/modules/users/DTO/create-user.dto.ts @@ -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; +} diff --git a/src/modules/users/entities/legal-user.entity.ts b/src/modules/users/entities/legal-user.entity.ts index 88d02b2..9eb7d7b 100644 --- a/src/modules/users/entities/legal-user.entity.ts +++ b/src/modules/users/entities/legal-user.entity.ts @@ -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; diff --git a/src/modules/users/entities/real-user.entity.ts b/src/modules/users/entities/real-user.entity.ts index 6c0355f..12bb7b2 100644 --- a/src/modules/users/entities/real-user.entity.ts +++ b/src/modules/users/entities/real-user.entity.ts @@ -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; diff --git a/src/modules/users/entities/user.entity.ts b/src/modules/users/entities/user.entity.ts index 588e46a..88e2408 100644 --- a/src/modules/users/entities/user.entity.ts +++ b/src/modules/users/entities/user.entity.ts @@ -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) diff --git a/src/modules/users/providers/users.service.ts b/src/modules/users/providers/users.service.ts index 0f65b91..18c6d39 100644 --- a/src/modules/users/providers/users.service.ts +++ b/src/modules/users/providers/users.service.ts @@ -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, + }; + } + /************************************************************ */ } diff --git a/src/modules/users/users.controller.ts b/src/modules/users/users.controller.ts index 1a515c5..316e665 100644 --- a/src/modules/users/users.controller.ts +++ b/src/modules/users/users.controller.ts @@ -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); + } + + /************************************************************ */ } diff --git a/src/modules/users/users.module.ts b/src/modules/users/users.module.ts index 1fcfe69..c234e59 100644 --- a/src/modules/users/users.module.ts +++ b/src/modules/users/users.module.ts @@ -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],