import { forwardRef, HttpException, HttpStatus, Inject, Injectable, } from '@nestjs/common'; import { CreateUserDto } from './dto/create-user.dto'; import { UpdateUserDto } from './dto/update-user.dto'; import { Connection, EntityNotFoundError, Equal, Not, Repository, } from 'typeorm'; import { User } from './entities/user.entity'; import { InjectRepository } from '@nestjs/typeorm'; import { randomStringGenerator } from '@nestjs/common/utils/random-string-generator.util'; import { hashPassword } from '../helper/hash_password'; import { CoaService } from 'src/transaction/coa.service'; import { balanceType, coaType } from 'src/helper/enum-list'; import { RoleService } from 'src/configurable/roles.service'; import { InputCoaDto } from 'src/transaction/dto/input-coa.dto'; import * as uuid from 'uuid'; @Injectable() export class UsersService { constructor( @InjectRepository(User) private usersRepository: Repository, @Inject( forwardRef(() => { return CoaService; }), ) private coaService: CoaService, private roleService: RoleService, private connection: Connection, ) {} async create(createUserDto: CreateUserDto, currentUser: any) { const roles = await this.roleService.findOne(createUserDto.roleId); const superior = await this.findByUsername(currentUser.username); const check = await this.usersRepository.findOne({ username: createUserDto.username, }); if (check) { throw new HttpException( { statusCode: HttpStatus.NOT_ACCEPTABLE, error: 'Username Already Exist', }, HttpStatus.NOT_FOUND, ); } const salt = randomStringGenerator(); const userData = new User(); userData.id = uuid.v4(); userData.username = createUserDto.username; userData.password = await hashPassword(createUserDto.password, salt); userData.salt = salt; if (createUserDto.superior) { userData.superior = superior; } else { userData.superior = null; userData.partner = createUserDto.partner; } userData.roles = roles; await this.connection.transaction(async (manager) => { const result = await manager.insert(User, userData); const dataCoaWallet = new InputCoaDto(); dataCoaWallet.user = userData; dataCoaWallet.balanceType = balanceType.CREDIT; dataCoaWallet.type = coaType.WALLET; dataCoaWallet.coaEntityManager = manager; await this.coaService.create(dataCoaWallet); if (createUserDto.superior) { const dataCoaAP = new InputCoaDto(); dataCoaAP.user = userData; dataCoaAP.balanceType = balanceType.CREDIT; dataCoaAP.relatedUserId = superior.id; dataCoaAP.type = coaType.ACCOUNT_PAYABLE; dataCoaAP.coaEntityManager = manager; await this.coaService.create(dataCoaAP); const dataCoaAR = new InputCoaDto(); dataCoaAR.user = userData; dataCoaAR.balanceType = balanceType.DEBIT; dataCoaAR.relatedUserId = superior.id; dataCoaAR.type = coaType.ACCOUNT_RECEIVABLE; dataCoaAR.coaEntityManager = manager; await this.coaService.create(dataCoaAR); } }); return userData; } findAll(page: number, id: string) { return this.usersRepository.findAndCount({ skip: page * 10, take: 10, order: { version: 'DESC', }, where: { id: Not(Equal(id)), }, }); } findByRoles(relationId: string, page: number) { return this.usersRepository.findAndCount({ skip: page * 10, take: 10, where: { roles: relationId, }, order: { updatedAt: 'DESC', }, }); } findBySuperrior(superriorId: string, page: number) { return this.usersRepository.findAndCount({ skip: page * 10, take: 10, relations: ['roles'], where: { superior: superriorId, }, order: { updatedAt: 'DESC', }, }); } async findExist(id: string) { try { return await this.usersRepository.findOneOrFail(id); } catch (e) { if (e instanceof EntityNotFoundError) { throw new HttpException( { statusCode: HttpStatus.NOT_FOUND, error: 'Data not found', }, HttpStatus.NOT_FOUND, ); } else { throw e; } } } async findByUsername(username: string) { try { return await this.usersRepository.findOneOrFail({ where: { username: username, }, relations: ['roles'], }); } catch (e) { if (e instanceof EntityNotFoundError) { throw new HttpException( { statusCode: HttpStatus.NOT_FOUND, error: 'Data not found', }, HttpStatus.NOT_FOUND, ); } else { throw e; } } } async findOne(id: string) { const coa = await this.coaService.findByUser(id, coaType.WALLET); try { const userData = await this.usersRepository.findOneOrFail({ where: { id: id, }, relations: ['roles', 'superior'], }); return { ...userData, wallet: coa.amount, }; } catch (e) { if (e instanceof EntityNotFoundError) { throw new HttpException( { statusCode: HttpStatus.NOT_FOUND, error: 'Data not found', }, HttpStatus.NOT_FOUND, ); } else { throw e; } } } async update(id: string, updateUserDto: UpdateUserDto, currentUser: any) { try { await this.usersRepository.findOneOrFail(id); } catch (e) { if (e instanceof EntityNotFoundError) { throw new HttpException( { statusCode: HttpStatus.NOT_FOUND, error: 'Data not found', }, HttpStatus.NOT_FOUND, ); } else { throw e; } } const check = await this.usersRepository.findOne({ username: updateUserDto.username, id: Not(id), }); if (check) { throw new HttpException( { statusCode: HttpStatus.NOT_ACCEPTABLE, error: 'Username Already Exist', }, HttpStatus.NOT_FOUND, ); } const userData = new User(); userData.id = id; userData.username = updateUserDto.username; userData.partner = updateUserDto.partner; await this.connection.transaction(async (manager) => { const result = await manager.update(User, { id: id }, userData); }); return userData; } async remove(id: string) { try { await this.usersRepository.findOneOrFail(id); } catch (e) { if (e instanceof EntityNotFoundError) { throw new HttpException( { statusCode: HttpStatus.NOT_FOUND, error: 'Data not found', }, HttpStatus.NOT_FOUND, ); } else { throw e; } } await this.usersRepository.delete(id); } async findOneByUsername(username: string) { return this.usersRepository.findOneOrFail({ where: { username, }, relations: ['roles'], }); } async findOneByPartner(partnerId: string) { try { return this.usersRepository.findOneOrFail({ relations: ['roles'], where: { partner: partnerId, }, }); } catch (e) { if (e instanceof EntityNotFoundError) { throw new HttpException( { statusCode: HttpStatus.NOT_FOUND, error: 'Data not found', }, HttpStatus.NOT_FOUND, ); } else { throw e; } } } }