diff --git a/src/auth/auth.module.ts b/src/auth/auth.module.ts index f24662b..f7e9789 100644 --- a/src/auth/auth.module.ts +++ b/src/auth/auth.module.ts @@ -7,10 +7,12 @@ import { ConfigModule, ConfigService } from '@nestjs/config'; import { UserService } from 'src/user/user.service'; import { EmailModule } from 'src/email/email.module'; import { AuthGuard } from './auth.guard'; +import { BranchModule } from 'src/branch/branch.module'; @Module({ imports: [ forwardRef(() => UserModule), + forwardRef(() => BranchModule), ConfigModule, JwtModule.registerAsync({ useFactory: (configService: ConfigService) => ({ diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts index 361f257..54ec600 100644 --- a/src/auth/auth.service.ts +++ b/src/auth/auth.service.ts @@ -92,7 +92,10 @@ export class AuthService { async updatePassword(user: User, newPasswod: string): Promise { const password = await this.encryptPassword(newPasswod); - await this.userService.update(user, { password }); + await this.userService.update(user, { + password, + isGenericPassword: false, + }); return true; } diff --git a/src/branch/branch.module.ts b/src/branch/branch.module.ts index 09693be..46e7bd2 100644 --- a/src/branch/branch.module.ts +++ b/src/branch/branch.module.ts @@ -1,4 +1,4 @@ -import { Module } from '@nestjs/common'; +import { forwardRef, Module } from '@nestjs/common'; import { BranchService } from './branch.service'; import { BranchController } from './branch.controller'; import { TypeOrmModule } from '@nestjs/typeorm'; @@ -14,9 +14,10 @@ import { State } from 'src/state/entities/state.entity'; @Module({ imports: [ TypeOrmModule.forFeature([Branch, City, State, Country]), - AuthModule, + forwardRef(() => AuthModule), ], controllers: [BranchController], providers: [BranchService, CityService, StateService, CountryService], + exports: [BranchService], }) export class BranchModule {} diff --git a/src/user/dto/user.dto.ts b/src/user/dto/user.dto.ts index 912d564..fbf5c83 100644 --- a/src/user/dto/user.dto.ts +++ b/src/user/dto/user.dto.ts @@ -16,6 +16,8 @@ import { MaxLength, MinLength, IsString, + IsUUID, + IsBoolean, } from 'class-validator'; import { UserGender } from '../entities/profile.entity'; import { IsOlderThan } from 'src/utils/is-older-than-validator'; @@ -88,6 +90,14 @@ export class BaseUserDTO { @IsOptional() @IsEnum(UserGender) gender?: UserGender; + + @IsOptional() + @IsBoolean() + @Expose() + @ApiProperty({ + description: 'Indicates whether the user has a generic password', + }) + isGenericPassword?: boolean; } export class UserDTO extends IntersectionType(BaseUserDTO, PasswordDTO) {} @@ -98,6 +108,15 @@ export class UserAdminDTO extends BaseUserDTO { @Expose() role: UserRole; + @ApiProperty({ + description: 'branchId of the user (branch_admin or delivery)', + required: false, + }) + @IsOptional() + @IsUUID() + @Expose() + branchId?: string; + // Data use if it is a delivery @ApiProperty({ description: 'Motorcycle brand', required: false }) diff --git a/src/user/entities/user.entity.ts b/src/user/entities/user.entity.ts index 86cadb6..da83a58 100644 --- a/src/user/entities/user.entity.ts +++ b/src/user/entities/user.entity.ts @@ -96,4 +96,10 @@ export class User extends BaseModel { @Column({ type: 'character varying', name: 'ws_id', nullable: true }) wsId: string | undefined; + + @Column({ type: 'boolean', default: false, name: 'is_mobile_customer' }) + isMobileCustomer: boolean; + + @Column({ type: 'boolean', default: false, name: 'is_generic_password' }) + isGenericPassword: boolean; } diff --git a/src/user/migrations/1747259587010-add-flags-to-user-migration.ts b/src/user/migrations/1747259587010-add-flags-to-user-migration.ts new file mode 100644 index 0000000..b9387c9 --- /dev/null +++ b/src/user/migrations/1747259587010-add-flags-to-user-migration.ts @@ -0,0 +1,25 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class AddFlagsToUserMigration1747259587010 + implements MigrationInterface +{ + name = 'AddFlagsToUserMigration1747259587010'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "user" ADD "is_mobile_customer" boolean NOT NULL DEFAULT false`, + ); + await queryRunner.query( + `ALTER TABLE "user" ADD "is_generic_password" boolean NOT NULL DEFAULT false`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "user" DROP COLUMN "is_generic_password"`, + ); + await queryRunner.query( + `ALTER TABLE "user" DROP COLUMN "is_mobile_customer"`, + ); + } +} diff --git a/src/user/user.module.ts b/src/user/user.module.ts index 8e858e4..cc33946 100644 --- a/src/user/user.module.ts +++ b/src/user/user.module.ts @@ -9,6 +9,8 @@ import { AuthModule } from 'src/auth/auth.module'; import { Branch } from 'src/branch/entities/branch.entity'; import { UserAddress } from './entities/user-address.entity'; import { UserMoto } from './entities/user-moto.entity'; +import { BranchModule } from 'src/branch/branch.module'; +import { EmailModule } from 'src/email/email.module'; @Module({ imports: [ @@ -21,6 +23,8 @@ import { UserMoto } from './entities/user-moto.entity'; UserMoto, ]), forwardRef(() => AuthModule), + forwardRef(() => BranchModule), + EmailModule, ], providers: [UserService], exports: [UserService, TypeOrmModule], diff --git a/src/user/user.service.ts b/src/user/user.service.ts index 5b342c4..a2849ed 100644 --- a/src/user/user.service.ts +++ b/src/user/user.service.ts @@ -16,6 +16,8 @@ import { CreateUserAddressDTO } from './dto/user-address.dto'; import { ConfigService } from '@nestjs/config'; import { UserMoto } from './entities/user-moto.entity'; import { UpdateUserMotoDTO } from './dto/user-moto.dto'; +import { BranchService } from 'src/branch/branch.service'; +import { EmailService } from 'src/email/email.service'; @Injectable() export class UserService { @@ -31,6 +33,9 @@ export class UserService { @InjectRepository(UserMoto) private UserMotoRepository: Repository, private configService: ConfigService, + + private readonly branchService: BranchService, + private emailService: EmailService, ) {} async userExists(options: Partial): Promise { @@ -126,7 +131,28 @@ export class UserService { const hashedPassword = await bcrypt.hash(password, 10); const newUser = this.userRepository.create(user); newUser.password = hashedPassword; + newUser.isGenericPassword = true; + if ( + user.role === UserRole.BRANCH_ADMIN || + user.role === UserRole.DELIVERY + ) { + if (!user.branchId) { + throw new BadRequestException('branchId is required for this role'); + } + + const branch = await this.branchService.findOne(user.branchId); + + newUser.branch = branch; + } const userCreated = await this.userRepository.save(newUser); + + await this.emailService.sendEmail({ + recipients: [{ email: user.email, name: user.firstName }], + subject: 'Welcome to Pharmatech', + html: `

Hi, your account has been created. Your password is: ${password}

`, + text: `Hi, your account has been created. Your password is: ${password}`, + }); + const profile = new Profile(); profile.user = userCreated; if (user.gender) {