import { forwardRef, Inject, Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import moment from 'moment'; import { Brackets, type FindOptionsWhere, Repository } from 'typeorm'; import { type PageDto } from '../../common/dto/page.dto'; import { OperateType } from '../../constants'; import { ActivityGroupNotFoundException, ActivitySettingInUsedException, SectorNotFoundException, } from '../../exceptions'; import { AuditLogService } from '../audit-log/audit-log.service'; import { SectorService } from '../sector/sector.service'; import { type UserEntity } from '../user/user.entity'; import { ActivityGroupService } from './activity-group.service'; import { ActivityRecordService } from './activity-record.service'; import { ActivityRecordSettingEntity } from './activity-record-setting.entity'; import { type ActivityRecordSettingDto } from './dtos/activity-record-setting.dto'; import { type CreateActivityRecordSettingDto } from './dtos/create-activity-record-setting.dto'; import { type ActivityRecordSettingPageOptionsDto } from './dtos/get-activity-record-setting-page.dto'; import { type UpdateActivityRecordSettingDto } from './dtos/update-activity-record-setting.dto'; @Injectable() export class ActivityRecordSettingService { constructor( @InjectRepository(ActivityRecordSettingEntity) private activityRecordSettingReposiory: Repository, @Inject(forwardRef(() => SectorService)) private sectorService: SectorService, @Inject(forwardRef(() => ActivityRecordService)) private acitvityRecordService: ActivityRecordService, private activityGroupService: ActivityGroupService, private auditLogService: AuditLogService, ) {} async findOne( findData: FindOptionsWhere, ): Promise { const queryBuilder = this.activityRecordSettingReposiory.createQueryBuilder( 'activityRecordSetting', ); queryBuilder .leftJoin('activityRecordSetting.sector', 'sector') .addSelect(['sector.name']) .leftJoin('activityRecordSetting.activityGroup', 'activityGroup') .addSelect(['activityGroup.name']); queryBuilder.where(findData); return queryBuilder.getOne(); } async findMany( pageOptionsDto: ActivityRecordSettingPageOptionsDto, ): Promise> { const { activityName, incentiveName, isActive, sectorName, order, activityGroupName, id, } = pageOptionsDto; const queryBuilder = this.activityRecordSettingReposiory.createQueryBuilder( 'activityRecordSetting', ); queryBuilder .leftJoin('activityRecordSetting.sector', 'sector') .addSelect(['sector.name']) .leftJoin('activityRecordSetting.activityGroup', 'activityGroup') .addSelect(['activityGroup.name']); if (activityName) { queryBuilder.andWhere('activityRecordSetting.name ILIKE :activityName', { activityName: `%${activityName}%`, }); } if (activityGroupName) { queryBuilder.andWhere('activityGroup.name ILIKE :activityGroupName', { activityGroupName: `%${activityGroupName}%`, }); } if (incentiveName) { queryBuilder.andWhere(incentiveName, [ 'activityRecordSetting.incentiveName', ]); } if (id !== undefined) { queryBuilder.andWhere('activityRecordSetting.id = :id', { id, }); } if (isActive !== undefined) { queryBuilder.andWhere('activityRecordSetting.isActive = :isActive', { isActive, }); } if (sectorName) { queryBuilder.andWhere('sector.name ILIKE :sectorName', { sectorName: `%${sectorName}%`, }); } queryBuilder.orderBy('activityRecordSetting.name', order); const [items, pageMetaDto] = await queryBuilder.paginate(pageOptionsDto); return items.toPageDto(pageMetaDto); } async findManyWithoutPagination(): Promise { const queryBuilder = this.activityRecordSettingReposiory.createQueryBuilder( 'activityRecordSetting', ); return queryBuilder.getMany(); } async findManyDropdown({ date, shouldShowInOtfilter, showInactive = false, }: { date?: Date; shouldShowInOtfilter?: boolean; showInactive?: boolean; }): Promise> { const requestDate = date ? moment.utc(date).startOf('date') : moment.utc().startOf('date'); const queryBuilder = this.activityRecordSettingReposiory.createQueryBuilder( 'activityRecordSetting', ); if (!showInactive) { queryBuilder.andWhere('activityRecordSetting.isActive = :status', { status: true, }); queryBuilder.andWhere( new Brackets((qb) => qb .andWhere('activityRecordSetting.activateUntil IS NULL') .orWhere('activityRecordSetting.activateUntil >= :requestDate', { requestDate, }), ), ); } if (shouldShowInOtfilter) { queryBuilder.andWhere( 'activityRecordSetting.shouldShowInOtfilter = :shouldShowInOtfilter', { shouldShowInOtfilter, }, ); } queryBuilder.orderBy('activityRecordSetting.name', 'ASC'); const returnData = await queryBuilder.getMany(); return returnData.map((el) => ({ name: el.name, value: el.name, })); } async createActivityRecordSetting( dto: CreateActivityRecordSettingDto, user: UserEntity, ): Promise { let activateUntil: undefined | Date; if (dto.activateUntil) { activateUntil = moment.utc(dto.activateUntil).startOf('date').toDate(); } const sectorEntity = await this.sectorService.findOne({ name: dto.sector, }); if (!sectorEntity) { throw new SectorNotFoundException(); } const activityGroupEntity = await this.activityGroupService.findOne({ name: dto.activityGroup, }); if (!activityGroupEntity) { throw new ActivityGroupNotFoundException(); } const activityRecordSettingEntity = this.activityRecordSettingReposiory.create({ ...dto, activateUntil, sector: sectorEntity, activityGroup: activityGroupEntity, }); const createdActivity = await this.activityRecordSettingReposiory.save( activityRecordSettingEntity, ); await this.auditLogService.create({ itemId: createdActivity.id, newValue: JSON.stringify(createdActivity), oldValue: null, operateType: OperateType.CREATE, summaryChanges: 'CREATE activity record setting', tableName: 'activityRecordSetting', user, }); return activityRecordSettingEntity; } // eslint-disable-next-line sonarjs/cognitive-complexity async updateActivitySetting( activityRecordSettingEntity: ActivityRecordSettingEntity, dto: UpdateActivityRecordSettingDto, user: UserEntity, ): Promise { const { name, rate, activityGroup, sector, activateUntil, incentiveName, isActive, unit, shouldShowInOtfilter, } = dto; let summaryChanges = 'UPDATE '; const oldValue = JSON.stringify({ ...activityRecordSettingEntity }); if (name) { summaryChanges += activityRecordSettingEntity.name === name ? '' : `Name: ${activityRecordSettingEntity.name} -> ${name}, `; activityRecordSettingEntity.name = name; } if (rate !== undefined) { summaryChanges += activityRecordSettingEntity.rate === rate ? '' : `Rate: ${activityRecordSettingEntity.rate} -> ${rate}, `; activityRecordSettingEntity.rate = rate; } if (unit !== undefined) { summaryChanges += activityRecordSettingEntity.unit === unit ? '' : `Unit: ${activityRecordSettingEntity.unit} -> ${unit}, `; activityRecordSettingEntity.unit = unit; } if (activityGroup) { const activityGroupEntity = await this.activityGroupService.findOne({ name: activityGroup, }); if (!activityGroupEntity) { throw new ActivityGroupNotFoundException(); } summaryChanges += activityRecordSettingEntity.activityGroup.name === activityGroupEntity.name ? '' : `Activity Group: ${activityRecordSettingEntity.activityGroup.name} -> ${activityGroupEntity.name}, `; activityRecordSettingEntity.activityGroup = activityGroupEntity; } if (sector) { const sectorEntity = await this.sectorService.findOne({ name: sector, }); if (!sectorEntity) { throw new SectorNotFoundException(); } summaryChanges += activityRecordSettingEntity.sector.name === sectorEntity.name ? '' : `Sector: ${activityRecordSettingEntity.sector.name} -> ${sectorEntity.name}, `; activityRecordSettingEntity.sector = sectorEntity; } if (activateUntil !== undefined) { summaryChanges += activityRecordSettingEntity.activateUntil === activateUntil ? '' : `Activate Until: ${moment .utc(activityRecordSettingEntity.activateUntil) .startOf('date') .toDate()} -> ${moment .utc(activateUntil) .startOf('date') .toDate()}, `; activityRecordSettingEntity.activateUntil = activateUntil === null ? (null as unknown as undefined) : moment.utc(activateUntil).startOf('date').toDate(); } if (incentiveName !== undefined) { summaryChanges += activityRecordSettingEntity.incentiveName === incentiveName ? '' : `Incentive: ${activityRecordSettingEntity.incentiveName} -> ${incentiveName}, `; activityRecordSettingEntity.incentiveName = incentiveName === null ? (null as unknown as undefined) : incentiveName; } if (isActive !== undefined) { summaryChanges += activityRecordSettingEntity.isActive === isActive ? '' : `IsActive: ${activityRecordSettingEntity.isActive} -> ${isActive}, `; activityRecordSettingEntity.isActive = isActive; } if (shouldShowInOtfilter !== undefined) { summaryChanges += activityRecordSettingEntity.shouldShowInOtfilter === shouldShowInOtfilter ? '' : `ShouldShowInOtFilter: ${activityRecordSettingEntity.shouldShowInOtfilter} -> ${shouldShowInOtfilter}, `; activityRecordSettingEntity.shouldShowInOtfilter = shouldShowInOtfilter; } const updatedActivity = await this.activityRecordSettingReposiory.save( activityRecordSettingEntity, ); await this.auditLogService.create({ itemId: updatedActivity.id, newValue: JSON.stringify(updatedActivity), oldValue, operateType: OperateType.UPDATE, summaryChanges, tableName: 'activityRecordSetting', user, }); return activityRecordSettingEntity; } async delete( activitySettingEntity: ActivityRecordSettingEntity, user: UserEntity, ): Promise { const existingActivityRecord = await this.acitvityRecordService.findOne({ activityRecordSetting: { id: activitySettingEntity.id }, }); if (existingActivityRecord) { throw new ActivitySettingInUsedException(); } await this.auditLogService.create({ itemId: activitySettingEntity.id, newValue: null, oldValue: JSON.stringify(activitySettingEntity), operateType: OperateType.DELETE, summaryChanges: 'DELETE activity record setting', tableName: 'activityRecordSetting', user, }); await this.activityRecordSettingReposiory.remove(activitySettingEntity); } }