ppob-backend/src/users/users.service.ts
2022-06-28 13:51:18 +07:00

714 lines
18 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';
import { mapSeries } from 'bluebird';
import { Partner } from './entities/partner.entity';
@Injectable()
export class UsersService {
constructor(
@InjectRepository(User)
private usersRepository: Repository<User>,
@InjectRepository(Partner)
private partnerRepository: Repository<Partner>,
@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) {
let approvalRole = '';
if (superior.superior) {
if(superior.roles.name == 'Sales'){
approvalRole = 'Supervisor';
} else {
approvalRole = 'Admin';
}
userData.superior = superior;
userData.status_approval = superior.superior.id;
userData.is_active = false;
} else {
userData.superior = superior;
userData.is_active = true;
}
} 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;
userDetailData.identity_number = createUserDto.identity_number;
userDetailData.image_identity = createUserDto.image_identity;
userDetailData.image_store = createUserDto.image_store;
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 (roles.name == 'Supervisor' || roles.name == 'Sales') {
const dataCOAProfit = new InputCoaDto();
dataCOAProfit.user = userData;
dataCOAProfit.balanceType = balanceType.CREDIT;
dataCOAProfit.type = coaType.PROFIT;
dataCOAProfit.coaEntityManager = manager;
await this.coaService.create(dataCOAProfit);
}
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,
pageSize: number,
id: string,
superior: string,
type: 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.is_active',
'user.createdAt',
'roles.id',
'roles.name',
'user_detail',
'coa.amount',
]);
if (superior) {
baseQuery.where('user.superior = :id_supperior', {
id_supperior: superior,
});
}
if (type) {
if (type == 'partner') {
baseQuery.where('user.partner_id is not null');
} else {
baseQuery.where('user.partner_id is null');
}
}
const data = await baseQuery
.orderBy('user.createdAt', 'DESC')
.skip(page * pageSize)
.take(pageSize)
.getMany();
const totalData = await baseQuery.getCount();
return {
data,
count: totalData,
};
}
async findAllSubordinate(id: string, role: number) {
let listUser = [];
let listToFind = [];
const baseQuery = await this.usersRepository.find({
where: {
superior: id,
},
});
const listId = baseQuery.map((x) => {
return x.id;
});
listUser = listUser.concat(listId);
listToFind = listId;
if (role == 1) {
return listUser;
}
for (let it = 2; it <= role; it++) {
let newListToFind = [];
await mapSeries(listToFind, async (ltf) => {
const getListUser = await this.usersRepository.find({
where: {
superior: ltf,
},
});
if (getListUser.length > 0) {
const listId = getListUser.map((x) => {
return x.id;
});
newListToFind = newListToFind.concat(listId);
listUser = listUser.concat(listId);
}
});
listToFind = newListToFind;
}
return listUser;
}
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, pageSize: 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.is_active',
'roles.id',
'roles.name',
'user_detail',
'coa.amount',
]);
const data = await baseQuery
.skip(page * pageSize)
.take(pageSize)
.getMany();
const totalData = await baseQuery.getCount();
return {
data,
count: totalData,
};
}
async findApproval(superrior, page: number, pageSize: number) {
const dataUser = await this.findByUsername(superrior.username);
const baseQuery = this.usersRepository
.createQueryBuilder('user')
.where(
'user.id != :id and status_approval = :status and is_rejected is false',
{
id: superrior.userId,
status: superrior.userId,
},
)
.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.is_active',
'roles.id',
'roles.name',
'user_detail',
'coa.amount',
]);
const data = await baseQuery
.skip(page * pageSize)
.take(pageSize)
.getMany();
const totalData = await baseQuery.getCount();
return {
data,
count: totalData,
};
}
async findExist(id: string) {
try {
return await this.usersRepository.findOneOrFail({
where: {
id: id,
},
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 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) {
try {
const userData = await this.usersRepository
.createQueryBuilder('users')
.leftJoinAndSelect('users.roles', 'roles')
.leftJoinAndSelect('users.superior', 'superior')
.leftJoinAndSelect('users.userDetail', 'userDetail')
.leftJoinAndSelect('users.partner', 'partner')
.where('users.id = :id', {
id: id,
})
.select([
'users.id',
'users.username',
'users.is_active',
'users.is_rejected',
'users.createdAt',
'roles.id',
'roles.name',
'superior.id',
'superior.username',
'userDetail.id',
'userDetail.name',
'userDetail.phone_number',
'userDetail.identity_number',
'userDetail.image_identity',
'userDetail.image_store',
'partner.id',
'partner.name',
'partner.code',
'partner.npwp',
'partner.address',
'partner.phone_number',
'partner.callback_url'
])
.getOne();
const coa = await this.coaService.findByUser(id, coaType.WALLET);
let coaProfit;
if (
userData.roles.id != 'e4dfb6a3-2338-464a-8fb8-5cbc089d4209' &&
userData.roles.id != '21dceea2-416e-4b55-b74c-12605e1f8d1b'
) {
coaProfit = await this.coaService.findByUser(id, coaType.PROFIT);
}
return {
...userData,
wallet: coa.amount,
profit: coaProfit ? coaProfit.amount : coaProfit,
};
} 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;
userDetailData.identity_number = updateUserDto.identity_number;
userDetailData.image_identity = updateUserDto.image_identity;
userDetailData.image_store = updateUserDto.image_store;
await this.connection.transaction(async (manager) => {
await manager.save(userData);
await manager.save(userDetailData);
});
return userData;
}
async updatePassword(id: string, updateUserDto: UpdateUserDto) {
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;
}
}
}
async updatePasswordPartner(id: string, password) {
try {
const dataUser = await this.usersRepository.findOneOrFail({
where: {
partner: id,
},
});
dataUser.password = await hashPassword(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;
}
}
}
async confirmationUser(id: string, user: string, status: string) {
try {
const dataUser = await this.usersRepository.findOneOrFail(id);
const supervisorUser = await this.findExist(user);
if (status == 'approved') {
if (supervisorUser.roles.name == 'Admin') {
dataUser.status_approval = 'Done';
dataUser.is_active = true;
} else {
dataUser.status_approval = supervisorUser.superior.id;
}
} else if (status == 'resend') {
dataUser.is_rejected = false;
} else {
dataUser.is_rejected = true;
}
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.is_active = true;
} else {
userData.is_active = 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,
is_active: 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;
}
}
}
async findPartner(partnerId: string) {
try {
return this.partnerRepository.findOneOrFail({
where: {
id: partnerId,
},
});
} catch (e) {
if (e instanceof EntityNotFoundError) {
throw new HttpException(
{
statusCode: HttpStatus.NOT_FOUND,
error: 'Partner not found',
},
HttpStatus.NOT_FOUND,
);
} else {
throw e;
}
}
}
}