ppob-backend/src/users/users.service.ts
2021-12-23 19:59:35 +07:00

449 lines
11 KiB
TypeScript

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, 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';
import { UserDetail } from './entities/user_detail.entity';
import { COA } from '../transaction/entities/coa.entity';
@Injectable()
export class UsersService {
constructor(
@InjectRepository(User)
private usersRepository: Repository<User>,
@InjectRepository(UserDetail)
private userDetailRepository: Repository<UserDetail>,
@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 userDetailData = new UserDetail();
userDetailData.name = createUserDto.name;
userDetailData.phone_number = createUserDto.phone_number;
userDetailData.user = userData;
const user_detail = await manager.insert(UserDetail, userDetailData);
const dataCoaWallet = new InputCoaDto();
dataCoaWallet.user = userData;
dataCoaWallet.balanceType = balanceType.CREDIT;
dataCoaWallet.type = coaType.WALLET;
dataCoaWallet.coaEntityManager = manager;
await this.coaService.create(dataCoaWallet);
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);
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);
}
});
return userData;
}
async findAll(page: number, id: string) {
const baseQuery = this.usersRepository
.createQueryBuilder('user')
.where('user.id != :id', {
id: id,
})
.leftJoinAndSelect('user.roles', 'roles', `roles.id = user.roles_id`)
.leftJoinAndMapOne(
'user.user_detail',
UserDetail,
'user_detail',
`user_detail.user = user.id`,
)
.leftJoinAndMapOne(
'user.coa',
COA,
'coa',
`coa.user = user.id and coa.type = '0'`,
)
.select([
'user.id',
'user.username',
'user.isActive',
'user.createdAt',
'roles.id',
'roles.name',
'user_detail',
'coa.amount',
]);
const data = await baseQuery
.orderBy('user.createdAt', 'DESC')
.skip(page * 10)
.take(10)
.getMany();
const totalData = await baseQuery.getCount();
return {
data,
count: totalData,
};
}
findByRoles(relationId: string, page: number, pageSize?: number) {
return this.usersRepository.findAndCount({
skip: page * (pageSize || 10),
take: pageSize || 10,
where: {
roles: relationId,
},
order: {
updatedAt: 'DESC',
},
});
}
async findBySuperrior(superriorId: string, page: number) {
const baseQuery = this.usersRepository
.createQueryBuilder('user')
.where('user.id != :id and user.superior_id = :superior', {
id: superriorId,
superior: superriorId,
})
.leftJoinAndSelect('user.roles', 'roles', `roles.id = user.roles_id`)
.leftJoinAndMapOne(
'user.user_detail',
UserDetail,
'user_detail',
`user_detail.user = user.id`,
)
.leftJoinAndMapOne(
'user.coa',
COA,
'coa',
`coa.user = user.id and coa.type = '0'`,
)
.select([
'user.id',
'user.username',
'user.isActive',
'roles.id',
'roles.name',
'user_detail',
'coa.amount',
]);
const data = await baseQuery
.skip(page * 10)
.take(10)
.getMany();
const totalData = await baseQuery.getCount();
return {
data,
count: totalData,
};
}
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: 'User not found',
},
HttpStatus.NOT_FOUND,
);
} else {
throw e;
}
}
}
async findByUsername(username: string) {
try {
return await this.usersRepository.findOneOrFail({
where: {
username: username,
},
relations: ['superior', 'roles', 'partner'],
});
} catch (e) {
if (e instanceof EntityNotFoundError) {
throw new HttpException(
{
statusCode: HttpStatus.NOT_FOUND,
error: 'User 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
.createQueryBuilder('users')
.leftJoinAndSelect('users.roles', 'roles')
.leftJoinAndSelect('users.superior', 'superior')
.leftJoinAndSelect('users.userDetail', 'userDetail')
.where('users.id = :id', {
id: id,
})
.select([
'users.id',
'users.username',
'users.isActive',
'users.createdAt',
'roles.id',
'roles.name',
'superior.id',
'superior.username',
'userDetail.id',
'userDetail.name',
'userDetail.phone_number',
])
.getOne();
return {
...userData,
wallet: coa.amount,
};
} catch (e) {
if (e instanceof EntityNotFoundError) {
throw new HttpException(
{
statusCode: HttpStatus.NOT_FOUND,
error: 'User not found',
},
HttpStatus.NOT_FOUND,
);
} else {
throw e;
}
}
}
async update(id: string, updateUserDto: UpdateUserDto, currentUser: any) {
let userData;
let userDetailData;
try {
userData = await this.usersRepository.findOneOrFail(id);
userDetailData = await this.userDetailRepository.findOneOrFail({
where: {
user: userData,
},
});
} catch (e) {
if (e instanceof EntityNotFoundError) {
throw new HttpException(
{
statusCode: HttpStatus.NOT_FOUND,
error: 'User 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,
);
}
userData.username = updateUserDto.username;
userData.partner = updateUserDto.partner;
userDetailData.name = updateUserDto.name;
userDetailData.phone_number = updateUserDto.phone_number;
await this.connection.transaction(async (manager) => {
await manager.save(userData);
await manager.save(userDetailData);
});
return userData;
}
async updatePassword(
id: string,
updateUserDto: UpdateUserDto,
currentUser: any,
) {
try {
const dataUser = await this.usersRepository.findOneOrFail(id);
dataUser.password = await hashPassword(
updateUserDto.password,
dataUser.salt,
);
const result = await this.usersRepository.save(dataUser);
return dataUser;
} catch (e) {
if (e instanceof EntityNotFoundError) {
throw new HttpException(
{
statusCode: HttpStatus.NOT_FOUND,
error: 'User not found',
},
HttpStatus.NOT_FOUND,
);
} else {
throw e;
}
}
}
setStatus = async (id: string, type: string) => {
const userData = new User();
if (type === 'active') {
userData.isActive = true;
} else {
userData.isActive = false;
}
await this.connection.transaction(async (manager) => {
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: 'User not found',
},
HttpStatus.NOT_FOUND,
);
} else {
throw e;
}
}
await this.usersRepository.delete(id);
}
async findOneByUsername(username: string) {
return this.usersRepository.findOneOrFail({
where: {
username,
isActive: true,
},
relations: ['roles', 'partner'],
});
}
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: 'User not found',
},
HttpStatus.NOT_FOUND,
);
} else {
throw e;
}
}
}
}