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); } }