import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Patch, Post, Query, } from '@nestjs/common'; import { ApiCreatedResponse, ApiOkResponse, ApiTags } from '@nestjs/swagger'; import moment from 'moment'; import { type PageDto } from '../../common/dto/page.dto'; import { RoleType } from '../../constants'; import { ApiPageOkResponse, Auth, AuthUser, Whitelist } from '../../decorators'; import { AccountHasClosedException, RainfallNotFoundException, RainfallRecordDateExceedTodayException, RecordMoreThan3DaysException, } from '../../exceptions'; import { ApiConfigService } from '../../shared/services/api-config.service'; import { UserEntity } from '../user/user.entity'; import { CreateRainfallRecordDto } from './dtos/create-rainfall.dto'; import { RainfallRecordPageOptionsDto } from './dtos/get-rainfall-page.dto'; import { RainfallRecordDto } from './dtos/rainfall.dto'; import { UpdateRainfallRecordDto } from './dtos/update-rainfall.dto'; import { RainfallRecordService } from './rainfall.service'; @Controller('rainfall') @ApiTags('rainfall') export class RainfallController { constructor( private rainfallRecordService: RainfallRecordService, private configService: ApiConfigService, ) {} @Get() @Whitelist() @Auth([RoleType.ADMIN, RoleType.USER]) @HttpCode(HttpStatus.OK) @ApiPageOkResponse({ type: RainfallRecordDto, description: 'Get rainfall Records', }) async getRainfallRecords( @Query() dto: RainfallRecordPageOptionsDto, ): Promise<PageDto<RainfallRecordDto>> { return this.rainfallRecordService.findMany(dto); } @Post() @Whitelist() @Auth([RoleType.ADMIN, RoleType.USER]) @HttpCode(HttpStatus.CREATED) @ApiCreatedResponse() async createRainfall( @AuthUser() user: UserEntity, @Body() body: CreateRainfallRecordDto, ): Promise<RainfallRecordDto> { const { fromTime, toTime } = body; const recordDate = moment.utc(fromTime); const recordToTime = moment.utc(toTime); const currentDate = moment.utc(); const recordDateMonth = moment.utc(fromTime).month(); const currentMonth = moment.utc().month(); const daysDifference = currentDate.diff(recordDate, 'days'); if (this.configService.isProduction) { if (user.role === RoleType.USER && daysDifference > 3) { throw new RecordMoreThan3DaysException(); } if (currentMonth - recordDateMonth >= 1 && currentDate.date() > 7) { throw new AccountHasClosedException(); } if (recordToTime >= currentDate || recordDate >= currentDate) { throw new RainfallRecordDateExceedTodayException(); } } const rainfallEntity = await this.rainfallRecordService.createRainfall(body); return rainfallEntity.toDto(); } @Patch(':id') @Whitelist() @Auth([RoleType.ADMIN, RoleType.USER]) @HttpCode(HttpStatus.OK) @ApiOkResponse() async updateRainfall( @AuthUser() user: UserEntity, @Param('id') id: Uuid, @Body() body: UpdateRainfallRecordDto, ): Promise<RainfallRecordDto> { const { fromTime, toTime } = body; const recordDate = moment.utc(fromTime); const recordToTime = moment.utc(toTime); const currentDate = moment.utc(); const recordDateMonth = moment.utc(fromTime).month(); const currentMonth = moment.utc().month(); const daysDifference = currentDate.diff(recordDate, 'days'); if (this.configService.isProduction) { if (user.role === RoleType.USER && daysDifference > 3) { throw new RecordMoreThan3DaysException(); } if (currentMonth - recordDateMonth >= 1 && currentDate.date() > 7) { throw new AccountHasClosedException(); } if (recordToTime >= currentDate || recordDate >= currentDate) { throw new RainfallRecordDateExceedTodayException(); } } const toPatchEntity = await this.rainfallRecordService.findOne({ id, }); if (!toPatchEntity) { throw new RainfallNotFoundException(); } const rainfallEntity = await this.rainfallRecordService.updateRainfall( toPatchEntity, body, ); return rainfallEntity.toDto(); } @Delete(':id') @Whitelist() @Auth([RoleType.ADMIN, RoleType.USER]) @HttpCode(HttpStatus.OK) @ApiOkResponse() async deleteRainfall( @AuthUser() user: UserEntity, @Param('id') id: Uuid, ): Promise<Record<string, string>> { const toDeleteEntity = await this.rainfallRecordService.findOne({ id, }); if (!toDeleteEntity) { throw new RainfallNotFoundException(); } const recordDate = moment.utc(toDeleteEntity.fromTime); const currentDate = moment.utc(); const recordDateMonth = moment.utc(toDeleteEntity.fromTime).month(); const currentMonth = moment.utc().month(); const daysDifference = currentDate.diff(recordDate, 'days'); if (this.configService.isProduction) { if (user.role === RoleType.USER && daysDifference > 3) { throw new RecordMoreThan3DaysException(); } if (currentMonth - recordDateMonth >= 1 && currentDate.date() > 7) { throw new AccountHasClosedException(); } } await this.rainfallRecordService.deleteRainfall(toDeleteEntity); return { status: 'success' }; } }