penisularhr / src / modules / audit-log / audit-log.service.ts
audit-log.service.ts
Raw
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import moment from 'moment';
import { type FindOptionsWhere, Repository } from 'typeorm';

import { type PageDto } from '../../common/dto/page.dto';
import { type OperateType } from '../../constants';
import { type GetAuditLogDto } from '../report/dtos/get-report-audit-log.dto';
import { type UserEntity } from '../user/user.entity';
import { AuditLogEntity } from './audit-log.entity';
import { type AuditLogDto } from './dtos/audit-log.dto';
import { type AuditLogPageOptionsDto } from './dtos/get-audit-log-page.dto';
import { ReportAuditLogDto } from './dtos/report-audit-log.dto';

@Injectable()
export class AuditLogService {
  constructor(
    @InjectRepository(AuditLogEntity)
    private auditLogRepository: Repository<AuditLogEntity>,
  ) {}

  async findOne(
    findData: FindOptionsWhere<AuditLogEntity>,
  ): Promise<AuditLogEntity | null> {
    const queryBuilder = this.auditLogRepository.createQueryBuilder('auditLog');

    queryBuilder.where(findData);

    return queryBuilder.getOne();
  }

  async findMany(
    pageOptionsDto: AuditLogPageOptionsDto,
  ): Promise<PageDto<AuditLogDto>> {
    const { order, tableName, operateType, username } = pageOptionsDto;

    const queryBuilder = this.auditLogRepository.createQueryBuilder('auditLog');

    queryBuilder.leftJoinAndSelect('auditLog.user', 'user');

    if (tableName !== undefined) {
      queryBuilder.andWhere('auditLog.tableName ILIKE :tableName', {
        tableName: `%${tableName}%`,
      });
    }

    if (operateType !== undefined) {
      queryBuilder.andWhere('auditLog.operateType = :operateType', {
        operateType,
      });
    }

    if (username !== undefined) {
      queryBuilder.andWhere('user.name ILIKE :username', {
        username: `%${username}%`,
      });
    }

    queryBuilder.orderBy('auditLog.createdAt', order);

    const [items, pageMetaDto] = await queryBuilder.paginate(pageOptionsDto);

    return items.toPageDto(pageMetaDto);
  }

  async create(options: {
    operateType: OperateType;
    tableName: string;
    itemId: Uuid;
    summaryChanges: string;
    oldValue: string | null;
    newValue: string | null;
    user: UserEntity;
  }): Promise<AuditLogEntity | void> {
    const { oldValue, newValue } = options;

    if (oldValue === newValue) {
      return;
    }

    const auditLogEntity = this.auditLogRepository.create(options);
    await this.auditLogRepository.save(auditLogEntity);

    return auditLogEntity;
  }

  async findReportMany(dto: GetAuditLogDto) {
    const {
      operateType,
      tableName,
      userName,
      monthFrom,
      monthTo,
      order,
      year,
    } = dto;

    const currentYear = year ?? moment.utc().year();

    const queryBuilder = this.auditLogRepository.createQueryBuilder('auditLog');

    queryBuilder.leftJoin('auditLog.user', 'user').addSelect(['user.name']);

    if (userName) {
      queryBuilder.andWhere('user.name = :userName', { userName });
    }

    if (tableName) {
      queryBuilder.andWhere('auditLog.tableName = :tableName', {
        tableName,
      });
    }

    if (operateType) {
      queryBuilder.andWhere('auditLog.operateType = :operateType', {
        operateType,
      });
    }

    let fromDate: Date | undefined;
    let toDate: Date | undefined;

    if (monthFrom) {
      fromDate = moment
        .utc({
          year: currentYear,
          month: monthFrom - 1,
          date: 1,
        })
        .toDate();

      queryBuilder.andWhere('auditLog.createdAt >= :fromDate', { fromDate });
    }

    if (monthTo) {
      toDate = moment
        .utc({ year: currentYear, month: monthTo - 1, date: 1 })
        .add(1, 'months')
        .toDate();

      queryBuilder.andWhere('auditLog.createdAt < :toDate', { toDate });
    }

    queryBuilder.orderBy('auditLog.createdAt', order);

    const response = await queryBuilder.getMany();

    return response.map((el) => new ReportAuditLogDto(el));
  }
}