import { ConflictException, ForbiddenException, Injectable, NotFoundException, } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { AuthUser } from '../auth/interfaces/auth-user.interface'; import { CreateUserDto } from './dto/create-user.dto'; import { UpdateUserDto } from './dto/update-user.dto'; import { User } from './entities/user.entity'; import { UserRole } from './enums/user-role.enum'; @Injectable() export class UsersService { constructor( @InjectRepository(User) private readonly usersRepository: Repository, ) {} async create(createUserDto: CreateUserDto): Promise { await this.ensureMobileIsUnique(createUserDto.mobile); const user = this.usersRepository.create(createUserDto); return this.usersRepository.save(user); } findAll(): Promise { return this.usersRepository.find(); } async findOne(id: string): Promise { const user = await this.usersRepository.findOneBy({ id }); if (!user) { throw new NotFoundException(`User #${id} not found`); } return user; } async findByMobile(mobile: string): Promise { return this.usersRepository.findOneBy({ mobile }); } async update( id: string, updateUserDto: UpdateUserDto, currentUser?: AuthUser, ): Promise { const user = await this.findOne(id); if (updateUserDto.mobile) { await this.ensureMobileIsUnique(updateUserDto.mobile, id); } if ( updateUserDto.role !== undefined && currentUser?.role !== UserRole.ADMIN ) { throw new ForbiddenException('Only admin can change user role'); } Object.assign(user, updateUserDto); return this.usersRepository.save(user); } async remove(id: string): Promise { const user = await this.findOne(id); await this.usersRepository.remove(user); } private async ensureMobileIsUnique( mobile: string, excludeUserId?: string, ): Promise { const existing = await this.usersRepository.findOneBy({ mobile }); if (existing && existing.id !== excludeUserId) { throw new ConflictException('Mobile number already exists'); } } }