penisularhr / src / modules / public-holiday / public-holiday.service.ts
public-holiday.service.ts
Raw
import { forwardRef, Inject, 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 { AccountHasClosedException } from '../../exceptions';
import { ApiConfigService } from '../../shared/services/api-config.service';
import { ActivityRecordService } from '../activity-record/activity-record.service';
import { ActivityRecordSettingService } from '../activity-record/activity-record-setting.service';
import { BlockService } from '../block/block.service';
import { EmployeeService } from '../employee/employee.service';
import { UserService } from '../user/user.service';
import { type CreatePublicHolidayDto } from './dtos/create-public-holiday.dto';
import { type PublicHolidayPageOptionsDto } from './dtos/get-public-holiday-page.dto';
import { type PublicHolidayDto } from './dtos/public-holiday.dto';
import { type UpdatePublicHolidayDto } from './dtos/update-public-holiday.dto';
import { PublicHolidayEntity } from './public-holiday.entity';

@Injectable()
export class PublicHolidayService {
  constructor(
    @InjectRepository(PublicHolidayEntity)
    private publicHolidayRepository: Repository<PublicHolidayEntity>,
    @Inject(forwardRef(() => ActivityRecordService))
    private activityRecordService: ActivityRecordService,
    @Inject(forwardRef(() => EmployeeService))
    private employeeService: EmployeeService,
    private userService: UserService,
    private blockService: BlockService,
    private activitySettingService: ActivityRecordSettingService,
    private configService: ApiConfigService,
  ) {}

  async findOne(
    findData: FindOptionsWhere<PublicHolidayEntity>,
  ): Promise<PublicHolidayEntity | null> {
    const queryBuilder =
      this.publicHolidayRepository.createQueryBuilder('publicHoliday');

    queryBuilder.where(findData);

    return queryBuilder.getOne();
  }

  async findMany(
    pageOptionsDto: PublicHolidayPageOptionsDto,
  ): Promise<PageDto<PublicHolidayDto>> {
    const { order, date, name } = pageOptionsDto;

    const queryBuilder =
      this.publicHolidayRepository.createQueryBuilder('publicHoliday');

    if (date !== undefined) {
      queryBuilder.andWhere('publicHoliday.date = :date', { date });
    }

    if (name !== undefined) {
      queryBuilder.searchByString(name, ['publicHoliday.name']);
    }

    queryBuilder.orderBy('publicHoliday.date', order);

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

    return items.toPageDto(pageMetaDto);
  }

  async findManyWithoutPagination(
    findData: FindOptionsWhere<PublicHolidayEntity>,
  ): Promise<PublicHolidayEntity[]> {
    const queryBuilder =
      this.publicHolidayRepository.createQueryBuilder('publicHoliday');

    queryBuilder.where(findData);

    return queryBuilder.getMany();
  }

  async createPublicHoliday(
    dto: CreatePublicHolidayDto,
  ): Promise<PublicHolidayEntity> {
    const { date } = dto;

    const toCreateHolidayMonth = moment.utc(date).month();
    const currentMonth = moment.utc().month();
    const currentDate = moment.utc().date();

    if (
      this.configService.isProduction &&
      currentMonth - toCreateHolidayMonth >= 1 &&
      currentDate > this.configService.recordDateConfig.accountCloseDate
    ) {
      throw new AccountHasClosedException();
    }

    const user = await this.userService.findFirstUser();

    const employeeArr = await this.employeeService.findManyWithoutPagination();

    for (const employee of employeeArr) {
      if (employee.dateResign && employee.dateResign <= date) {
        continue;
      }

      // eslint-disable-next-line no-await-in-loop
      await this.activityRecordService.createActivityRecord(
        {
          activityName: 'Public Holiday',
          blockName: 'none',
          date,
          employeeName: employee.name,
          hour: 8,
          quantity: 8,
        },
        user!,
      );
    }

    const publicHolidayEntity = this.publicHolidayRepository.create(dto);
    await this.publicHolidayRepository.save(publicHolidayEntity);

    return publicHolidayEntity;
  }

  async updatePublicHoliday(
    publicHolidayEntity: PublicHolidayEntity,
    dto: UpdatePublicHolidayDto,
  ): Promise<PublicHolidayEntity> {
    const { name } = dto;

    publicHolidayEntity.name = name;

    await this.publicHolidayRepository.save(publicHolidayEntity);

    return publicHolidayEntity;
  }

  async delete(publicHolidayEntity: PublicHolidayEntity): Promise<void> {
    const currentHolidayEntityMonth = moment
      .utc(publicHolidayEntity.date)
      .month();
    const currentMonth = moment.utc().month();
    const currentDate = moment.utc().date();

    if (
      this.configService.isProduction &&
      currentMonth - currentHolidayEntityMonth >= 1 &&
      currentDate > this.configService.recordDateConfig.accountCloseDate
    ) {
      throw new AccountHasClosedException();
    }

    const user = await this.userService.findFirstUser();

    const employeeArr = await this.employeeService.findManyWithoutPagination();

    const publicHolidayActivitySetting =
      await this.activitySettingService.findOne({
        name: 'Public Holiday',
      });

    const block = await this.blockService.findOne({
      name: 'none',
    });

    for (const employee of employeeArr) {
      if (!publicHolidayActivitySetting || !block) {
        continue;
      }

      // eslint-disable-next-line no-await-in-loop
      const activityRecord = await this.activityRecordService.findOne(
        {
          activityRecordSetting: { id: publicHolidayActivitySetting.id },
          block: { id: block.id },
          employee: { id: employee.id },
          date: publicHolidayEntity.date,
        },
        true,
      );

      if (!activityRecord) {
        continue;
      }

      // eslint-disable-next-line no-await-in-loop
      await this.activityRecordService.deleteActivityRecord(
        activityRecord,
        user!,
      );
    }

    await this.publicHolidayRepository.remove(publicHolidayEntity);
  }
}