penisularhr / src / modules / activity-record / activity-group.service.ts
activity-group.service.ts
Raw
import { forwardRef, Inject, Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { type FindOptionsWhere, Repository } from 'typeorm';

import { type PageDto } from '../../common/dto/page.dto';
import { OperateType } from '../../constants';
import {
  ActivityGroupInUsedException,
  DuplicateActivityGroupException,
} from '../../exceptions';
import { AuditLogService } from '../audit-log/audit-log.service';
import { type UserEntity } from '../user/user.entity';
import { ActivityGroupEntity } from './activity-group.entity';
import { ActivityRecordSettingService } from './activity-record-setting.service';
import { type ActivityGroupDto } from './dtos/activity-group.dto';
import { type CreateActivityGroupDto } from './dtos/create-activity-group.dto';
import { type ActivityGroupPageOptionsDto } from './dtos/get-activity-group-page.dto';
import { type UpdateActivityGroupDto } from './dtos/update-activity-group.dto';

@Injectable()
export class ActivityGroupService {
  constructor(
    @InjectRepository(ActivityGroupEntity)
    private activityGroupRepository: Repository<ActivityGroupEntity>,
    @Inject(forwardRef(() => ActivityRecordSettingService))
    private activitySettingService: ActivityRecordSettingService,
    private auditLogService: AuditLogService,
  ) {}

  async findOne(
    findData: FindOptionsWhere<ActivityGroupEntity>,
  ): Promise<ActivityGroupEntity | null> {
    const queryBuilder =
      this.activityGroupRepository.createQueryBuilder('activityGroup');

    queryBuilder.where(findData);

    return queryBuilder.getOne();
  }

  async findMany(
    pageOptionsDto: ActivityGroupPageOptionsDto,
  ): Promise<PageDto<ActivityGroupDto>> {
    const { name, id } = pageOptionsDto;

    const queryBuilder =
      this.activityGroupRepository.createQueryBuilder('activityGroup');

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

    if (id !== undefined) {
      queryBuilder.andWhere('activityGroup.id = :id', { id });
    }

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

    return items.toPageDto(pageMetaDto);
  }

  async findManyDropdown(): Promise<Array<{ name: string; value: string }>> {
    const queryBuilder =
      this.activityGroupRepository.createQueryBuilder('activityGroup');

    queryBuilder.orderBy('activityGroup.name', 'ASC');

    const returnData = await queryBuilder.getMany();

    return returnData.map((el) => ({
      name: el.name,
      value: el.name,
    }));
  }

  async create(
    dto: CreateActivityGroupDto,
    user: UserEntity,
  ): Promise<ActivityGroupEntity> {
    const activityGroupEntity = this.activityGroupRepository.create(dto);
    const createdActivity =
      await this.activityGroupRepository.save(activityGroupEntity);

    await this.auditLogService.create({
      itemId: createdActivity.id,
      newValue: JSON.stringify(createdActivity),
      oldValue: null,
      operateType: OperateType.CREATE,
      summaryChanges: 'CREATE acitivity group',
      tableName: 'acitivityGroup',
      user,
    });

    return activityGroupEntity;
  }

  async update(
    activityGroupEntity: ActivityGroupEntity,
    dto: UpdateActivityGroupDto,
    user: UserEntity,
  ): Promise<ActivityGroupEntity> {
    const { name } = dto;

    const oldValue = JSON.stringify({ ...activityGroupEntity });
    let summaryChanges = 'UPDATE ';

    if (name !== undefined) {
      const existingActivityGroup = await this.findOne({
        name,
      });

      if (existingActivityGroup) {
        throw new DuplicateActivityGroupException();
      }

      summaryChanges +=
        activityGroupEntity.name === name
          ? ''
          : `Name: ${activityGroupEntity.name} -> ${name}, `;
      activityGroupEntity.name = name;
    }

    const updatedEntity =
      await this.activityGroupRepository.save(activityGroupEntity);

    await this.auditLogService.create({
      itemId: updatedEntity.id,
      newValue: JSON.stringify(updatedEntity),
      oldValue,
      operateType: OperateType.UPDATE,
      summaryChanges,
      tableName: 'activityGroup',
      user,
    });

    return activityGroupEntity;
  }

  async delete(
    activityGroupEntity: ActivityGroupEntity,
    user: UserEntity,
  ): Promise<void> {
    const existingActivitySetting = await this.activitySettingService.findOne({
      activityGroup: { id: activityGroupEntity.id },
    });

    if (existingActivitySetting) {
      throw new ActivityGroupInUsedException();
    }

    await this.auditLogService.create({
      itemId: activityGroupEntity.id,
      newValue: null,
      oldValue: JSON.stringify(activityGroupEntity),
      operateType: OperateType.DELETE,
      summaryChanges: 'DELETE activity group',
      tableName: 'activityGroup',
      user,
    });

    await this.activityGroupRepository.remove(activityGroupEntity);
  }
}