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 { RainfallTimeframeExists, ToTimeEarlierThanFromTimeException, } from '../../exceptions'; import { type GetRainfallDto } from '../report/dtos/get-report-rainfall.dto'; import { type CreateRainfallRecordDto } from './dtos/create-rainfall.dto'; import { type RainfallRecordPageOptionsDto } from './dtos/get-rainfall-page.dto'; import { type RainfallRecordDto } from './dtos/rainfall.dto'; import { type UpdateRainfallRecordDto } from './dtos/update-rainfall.dto'; import { RainfallRecordEntity } from './rainfall.entity'; @Injectable() export class RainfallRecordService { constructor( @InjectRepository(RainfallRecordEntity) private rainfallRepository: Repository, ) {} async findOne( findData?: FindOptionsWhere, ): Promise { const queryBuilder = this.rainfallRepository.createQueryBuilder('rainfall'); if (findData) { queryBuilder.where(findData); } return queryBuilder.getOne(); } async findOneByTimeFrame( timeFrame: Date, ): Promise { const queryBuilder = this.rainfallRepository.createQueryBuilder('rainfall'); queryBuilder .where('rainfall.fromTime <= :fromTime', { fromTime: timeFrame }) .andWhere('rainfall.toTime >= :toTime', { toTime: timeFrame }); return queryBuilder.getOne(); } async findMany( pageOptionsDto: RainfallRecordPageOptionsDto, ): Promise> { const { fromTime, toTime, order } = pageOptionsDto; const queryBuilder = this.rainfallRepository.createQueryBuilder('rainfall'); if (fromTime) { queryBuilder.andWhere('rainfall.fromTime >= :fromTime', { fromTime }); } if (toTime) { queryBuilder.andWhere('rainfall.toTime <= :toTime', { toTime }); } queryBuilder.orderBy('rainfall.fromTime', order); const [items, pageMetaDto] = await queryBuilder.paginate(pageOptionsDto); return items.toPageDto(pageMetaDto); } async findReportMany(dto: GetRainfallDto) { const { monthFrom, monthTo, order, year } = dto; const currentYear = year ?? moment.utc().year(); const queryBuilder = this.rainfallRepository.createQueryBuilder('rainfall'); let fromDate: Date | undefined; let toDate: Date | undefined; if (monthFrom) { fromDate = moment .utc({ year: currentYear, month: monthFrom - 1, date: 1, }) .toDate(); queryBuilder.andWhere('rainfall.fromTime >= :fromDate', { fromDate }); } if (monthTo) { toDate = moment .utc({ year: currentYear, month: monthTo - 1, date: 1 }) .add(1, 'months') .toDate(); queryBuilder.andWhere('rainfall.toTime < :toDate', { toDate }); } queryBuilder.orderBy('rainfall.fromTime', order); const response = await queryBuilder.getMany(); return response.map((el) => el.toDto()); } async createRainfall( dto: CreateRainfallRecordDto, ): Promise { const { fromTime, toTime } = dto; if (toTime < fromTime) { throw new ToTimeEarlierThanFromTimeException(); } const fromTimeEntity = await this.findOneByTimeFrame(fromTime); const toTimeEntity = await this.findOneByTimeFrame(toTime); if (fromTimeEntity || toTimeEntity) { throw new RainfallTimeframeExists(); } const rainfallEntity = this.rainfallRepository.create(dto); await this.rainfallRepository.save(rainfallEntity); return rainfallEntity; } async updateRainfall( rainfallRecordEntity: RainfallRecordEntity, dto: UpdateRainfallRecordDto, ): Promise { const { amount, fromTime, toTime } = dto; if (amount !== undefined) { rainfallRecordEntity.amount = amount; } if (fromTime) { rainfallRecordEntity.fromTime = fromTime; } if (toTime) { if (toTime < rainfallRecordEntity.fromTime) { throw new ToTimeEarlierThanFromTimeException(); } rainfallRecordEntity.toTime = toTime; } await this.rainfallRepository.save(rainfallRecordEntity); return rainfallRecordEntity; } async deleteRainfall( rainfallRecordEntity: RainfallRecordEntity, ): Promise { await this.rainfallRepository.remove(rainfallRecordEntity); } }