import {
Injectable,
InternalServerErrorException,
Logger,
NotFoundException,
} from '@nestjs/common';
import { Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import { UserClient } from 'src/entities/user-client';
import { JobPosition } from 'src/entities/job-position';
import { ApplicationUser } from 'src/entities/application-user';
import { ApplicationProfile } from 'src/entities/application-profile';
import { User } from 'src/entities/user';
import { GeneralException } from 'src/util';
import { Client } from 'src/entities/client';
import { AddUserClientDTO } from '../dto/user.dto';
import { PaginatedResult } from 'src/types/paginated-result';
import { PaginateQuery } from 'src/types/paginate-query';
@Injectable()
export class UserClientService {
private readonly logger = new Logger(UserClientService.name);
constructor(
@InjectRepository(UserClient)
private userClientRepository: Repository<UserClient>,
@InjectRepository(Client)
private clientRepository: Repository<Client>,
@InjectRepository(User)
private userRepository: Repository<User>
) {}
async getClientsByUser(
userId: number,
query: PaginateQuery
): Promise<PaginatedResult<UserClient>> {
const { size } = query;
const page = +query.page || 0;
const offset = page * size;
const innerJoinFilters = [];
if (query.name) {
innerJoinFilters.push('c.name ILIKE :name', { name: `%${query.name}%` });
}
const queryBuilder = this.userClientRepository
.createQueryBuilder('uc')
.select([
'uc.id AS id',
'uc.clientId AS "clientId"',
'uc.userId AS "userId"',
'c.name AS name',
'c.internalCode AS "internalCode"',
'c.mtrixCode AS "mtrixCode"',
'c.type AS type',
])
.where({
userId,
})
.innerJoin('uc.client', 'c', ...innerJoinFilters)
.orderBy('uc.id', 'ASC')
.limit(size)
.offset(offset);
const content = await queryBuilder.getRawMany();
const count = await queryBuilder.getCount();
const lastPage = Math.ceil(count / size);
const prevPage = page < 1 ? null : page;
return {
content,
size: +size,
totalElements: count,
totalPages: lastPage,
first: !prevPage,
last: lastPage === page + 1,
number: page + 1,
numberOfElements: content.length,
};
}
async getUsersByClient(clientId: number): Promise<UserClient[]> {
return await this.userClientRepository
.createQueryBuilder('uc')
.select([
'uc.id AS id',
'uc.clientId AS "clientId"',
'uc.userId AS "userId"',
'u.name AS name',
])
.where({
clientId,
})
.innerJoin('uc.user', 'u')
.orderBy('uc.id', 'ASC')
.getRawMany();
}
async getUsersDetailsByClient(
nameOrId: number | string,
query: PaginateQuery
): Promise<PaginatedResult<UserClient[]>> {
const { size, name } = query;
const page = +query.page || 0;
const offset = name ? 0 : page * size;
const company = await this.clientRepository
.findOneBy(isNaN(+nameOrId) ? { name: String(nameOrId) } : { id: +nameOrId })
if (!company) {
throw new NotFoundException({
messageKey: 'client_not_found',
});
}
const queryBuilder = this.userClientRepository
.createQueryBuilder('uc')
.select([
'DISTINCT u.id AS id',
'u.person_name AS personName',
'u.username AS username',
'u.email AS email',
'u.cpf AS cpf',
'u.observation AS observation',
'u.user_role AS userRole',
'u.enabled AS enabled',
'u.telephone_1 AS telephone1',
'u.telephone_2 AS telephone2',
'u.fax AS fax',
'u.ramal_1 AS ramal1',
'u.ramal_2 AS ramal2',
`CONCAT('{', '"id":', COALESCE(u.job_position_id, 0), ',', '"name": "', jp.position_name, '"', '}') AS cargo`,
'u.created_at AS createdAt',
'u.updated_at AS updatedAt'
])
.addSelect(subQuery => (
subQuery
.select([
`STRING_AGG(DISTINCT CONCAT('{', '"appUserId":', au.id, ',', '"appClientId":', au.application_client_id, ',', '"enabled":', TO_JSONB(au.enabled), ',', '"app": {', '"id":', ap.application_id, ',', '"name":"', TRIM(ai18nt.app_name), '"},', '"profile": {', '"id":', ap.id, ',', '"name":"', TRIM(ap.profile_name), '"}},,'), ',') AS profiles`
])
.from(ApplicationUser, 'au')
.leftJoin(ApplicationProfile, 'ap', 'ap.id = au.application_profile_id')
.leftJoin("applications_i18n", 'ai18n', 'ai18n.id = ap.application_id')
.leftJoin("applications_i18n_translations", 'ai18nt', 'ai18nt.application_id = ai18n.id')
.where('au.user_id = u.id')
.groupBy('au.user_id')
), 'contractedApplications')
.where({
clientId: company.id,
})
.innerJoin('uc.user', 'u')
.leftJoin(JobPosition, 'jp', 'jp.id = COALESCE(u.job_position_id, 0)')
.orderBy('u.id', 'ASC')
.limit(size)
.offset(offset);
if (name) {
queryBuilder.andWhere(`u.person_name ILIKE '%${name}%'`)
.orWhere(`u.username ILIKE '%${name}%'`)
.orWhere(`u.email ILIKE '%${name}%'`)
}
function removeDuplicatesAndConvertToObject(str: string | null) {
return [...new Set(str?.split(',,,'))]
.filter(Boolean)
.map((item) => JSON.parse(item.replace('},,', '}')))
.filter((item, i, self) => i === self.findIndex((t) => t['appUserId'] === item['appUserId']));
}
const content = await queryBuilder.getRawMany();
const count = await queryBuilder.getCount();
const lastPage = Math.ceil(count / size);
const prevPage = page < 1 ? null : page;
return {
content: content.map((result) => ({
...result,
id: +result.id,
cargo: JSON.parse(result.cargo),
contractedApplications: removeDuplicatesAndConvertToObject(result.contractedApplications),
})),
company: {
id: company.id,
name: company.name,
enabled: company.enabled,
internalCode: company.internalCode,
idRefSql: company.idRefSql,
},
size: +size,
totalElements: count,
totalPages: lastPage,
first: !prevPage,
last: lastPage === page + 1,
number: page + 1,
numberOfElements: content.length,
}
}
async addUserToClient({ clientId, userId }: AddUserClientDTO) {
const clientExists = await this.clientRepository.countBy({
id: clientId,
});
if (!clientExists) {
throw new NotFoundException({
messageKey: 'client_not_found',
});
}
const userExists = await this.userRepository.countBy({
id: userId,
});
if (!userExists) {
throw new NotFoundException({
messageKey: 'user_not_found',
});
}
const userClientExists = await this.userClientRepository.countBy({
clientId,
userId,
});
if (userClientExists) {
throw new GeneralException('user_client_already_exists');
}
const saveResult = await this.userClientRepository
.insert({
clientId,
userId,
})
.catch((error) => {
this.logger.error(error);
throw new InternalServerErrorException();
});
return saveResult.raw[0].id;
}
async delete(userId: number, clientId: number) {
const userClient = await this.userClientRepository.countBy({
userId,
clientId,
});
if (!userClient) {
throw new NotFoundException({ messageKey: 'user_client_not_found' });
}
return this.userClientRepository.delete({ userId, clientId });
}
}