diff --git a/backend/src/migrations/1724932441086-UserPhoneNullable.ts b/backend/src/migrations/1724932441086-UserPhoneNullable.ts new file mode 100644 index 00000000..e0065dda --- /dev/null +++ b/backend/src/migrations/1724932441086-UserPhoneNullable.ts @@ -0,0 +1,23 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class UserPhoneNullable1724932441086 implements MigrationInterface { + name = 'UserPhoneNullable1724932441086'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "user" ALTER COLUMN "phone" DROP NOT NULL`, + ); + await queryRunner.query( + `ALTER TABLE "user_history" ALTER COLUMN "phone" DROP NOT NULL`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "user" ALTER COLUMN "phone" SET NOT NULL`, + ); + await queryRunner.query( + `ALTER TABLE "user_history" ALTER COLUMN "phone" SET NOT NULL`, + ); + } +} diff --git a/backend/src/modules/user/dto/create-user.dto.ts b/backend/src/modules/user/dto/create-user.dto.ts index 7e9ff9b4..5bad6b25 100644 --- a/backend/src/modules/user/dto/create-user.dto.ts +++ b/backend/src/modules/user/dto/create-user.dto.ts @@ -27,8 +27,7 @@ export class CreateUserDto { @MaxLength(50) email: string; - @IsString() - @IsNotEmpty() + @IsOptional() @IsPhoneValid() phone: string; diff --git a/backend/src/modules/user/entities/user-history.entity.ts b/backend/src/modules/user/entities/user-history.entity.ts index ae8b3b54..ec4da2b0 100644 --- a/backend/src/modules/user/entities/user-history.entity.ts +++ b/backend/src/modules/user/entities/user-history.entity.ts @@ -35,7 +35,7 @@ export class UserHistory extends BaseEntity implements HistoryEntityInterface { @Column({ type: 'varchar', name: 'email' }) email: string; - @Column({ type: 'varchar', name: 'phone' }) + @Column({ type: 'varchar', name: 'phone', nullable: true }) phone: string; @Column({ type: 'enum', enum: Role, name: 'role', default: Role.EMPLOYEE }) diff --git a/backend/src/modules/user/entities/user.entity.ts b/backend/src/modules/user/entities/user.entity.ts index 2fd584e9..83cf171f 100644 --- a/backend/src/modules/user/entities/user.entity.ts +++ b/backend/src/modules/user/entities/user.entity.ts @@ -15,7 +15,7 @@ export class User extends BaseEntity { @Column({ type: 'varchar', name: 'email', unique: true }) email: string; - @Column({ type: 'varchar', name: 'phone' }) + @Column({ type: 'varchar', name: 'phone', nullable: true }) phone: string; @Column({ type: 'enum', enum: Role, name: 'role', default: Role.EMPLOYEE }) diff --git a/backend/src/modules/user/services/cognito.service.ts b/backend/src/modules/user/services/cognito.service.ts index e5429659..34b644ad 100644 --- a/backend/src/modules/user/services/cognito.service.ts +++ b/backend/src/modules/user/services/cognito.service.ts @@ -29,10 +29,7 @@ export class CognitoUserService { Username: email, DesiredDeliveryMediums: [DeliveryMediumType.EMAIL], UserAttributes: [ - { - Name: 'phone_number', - Value: phone, - }, + ...(phone ? [{ Name: 'phone_number', Value: phone }] : []), { Name: 'name', Value: name, @@ -48,9 +45,8 @@ export class CognitoUserService { ], }); - const data: AdminCreateUserCommandOutput = await this.cognitoProvider.send( - createUserCommand, - ); + const data: AdminCreateUserCommandOutput = + await this.cognitoProvider.send(createUserCommand); return data.User.Username; } diff --git a/backend/src/modules/user/services/user.service.ts b/backend/src/modules/user/services/user.service.ts index 1e7a6b94..4b603032 100644 --- a/backend/src/modules/user/services/user.service.ts +++ b/backend/src/modules/user/services/user.service.ts @@ -372,7 +372,10 @@ export class UserService { ) { throw new BadRequestException(USER_ERRORS.ALREADY_EXISTS_EMAIL); } else if ( - await this.userRepository.get({ where: { phone: createUserDto.phone } }) + createUserDto.phone && + (await this.userRepository.get({ + where: { phone: createUserDto.phone }, + })) ) { throw new BadRequestException(USER_ERRORS.ALREADY_EXISTS_PHONE); } diff --git a/frontend/src/assets/locales/ro/translation.json b/frontend/src/assets/locales/ro/translation.json index 735b1320..6007f48c 100644 --- a/frontend/src/assets/locales/ro/translation.json +++ b/frontend/src/assets/locales/ro/translation.json @@ -953,7 +953,7 @@ "max": "Numărul de telefon poate avea maxim 15 caractere", "min": "Numărul de telefon poate avea minim 10 caractere", "invalid": "Numărul de telefon are un format invalid", - "label": "Telefon*" + "label": "Telefon" } } }, diff --git a/frontend/src/pages/users/components/UserCreate/UserCreateConfig.ts b/frontend/src/pages/users/components/UserCreate/UserCreateConfig.ts index 354348dc..c918253f 100644 --- a/frontend/src/pages/users/components/UserCreate/UserCreateConfig.ts +++ b/frontend/src/pages/users/components/UserCreate/UserCreateConfig.ts @@ -79,10 +79,6 @@ export const UserCreateConfig: Record = { phone: { key: 'phone', rules: { - required: { - value: true, - message: translations.phone.required, - }, maxLength: { value: 15, message: translations.phone.max, @@ -92,6 +88,9 @@ export const UserCreateConfig: Record = { message: translations.phone.min, }, validate: (value: string) => { + if (!value) { + return true; + } return isValidPhoneNumber(value) || translations.phone.invalid; }, },