import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Patch, Post, Query, } from '@nestjs/common'; import { 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, UUIDParam, Whitelist, } from '../../decorators'; import { AccountHasClosedException, OtRecordDateExceedTodayException, OtRecordNotFoundException, RecordMoreThan3DaysException, } from '../../exceptions'; import { ApiConfigService } from '../../shared/services/api-config.service'; import { UserEntity } from '../user/user.entity'; import { CreateOtRecordDto } from './dtos/create-ot-record.dto'; import { OtRecordPageOptionsDto } from './dtos/get-ot-record-page.dto'; import { OtRecordDto } from './dtos/ot-record.dto'; import { UpdateOtRecordDto } from './dtos/update-ot-record.dto'; import { OtRecordService } from './ot-record.service'; @Controller('ot-records') @ApiTags('ot-records') export class OtRecordController { constructor( private otRecordService: OtRecordService, private configService: ApiConfigService, ) {} @Get() @Whitelist() @Auth([RoleType.ADMIN, RoleType.USER]) @HttpCode(HttpStatus.OK) @ApiPageOkResponse({ type: OtRecordDto, description: 'Get OT records list', }) async getOtRecords( @Query() query: OtRecordPageOptionsDto, ): Promise<PageDto<OtRecordDto>> { return this.otRecordService.findMany(query); } @Post() @Whitelist() @Auth([RoleType.ADMIN, RoleType.USER]) @HttpCode(HttpStatus.OK) @ApiOkResponse() async createOtRecord( @AuthUser() user: UserEntity, @Body() body: CreateOtRecordDto, ): Promise<OtRecordDto> { const { date } = body; const recordDate = moment.utc(date); const currentDate = moment.utc(); const recordDateMonth = moment.utc(date).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 (recordDate > currentDate) { throw new OtRecordDateExceedTodayException(); } } const otRecordEntity = await this.otRecordService.createOtRecord( body, user, ); return otRecordEntity.toDto(); } //NOTE: The reason cannot path activity and employee due to calculation for incentive very complicated @Patch(':id') @Whitelist() @Auth([RoleType.ADMIN, RoleType.USER]) @HttpCode(HttpStatus.OK) @ApiOkResponse() async updateOtRecord( @AuthUser() user: UserEntity, @UUIDParam('id') id: Uuid, @Body() body: UpdateOtRecordDto, ): Promise<OtRecordDto> { const toPatchEntity = await this.otRecordService.findOne({ id, }); if (!toPatchEntity) { throw new OtRecordNotFoundException(); } const recordDate = moment.utc(toPatchEntity.date); const currentDate = moment.utc(); const recordDateMonth = moment.utc(toPatchEntity.date).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 (recordDate > currentDate) { throw new OtRecordDateExceedTodayException(); } } const otRecordEntity = await this.otRecordService.updateOtRecord( toPatchEntity, body, user, ); return otRecordEntity.toDto(); } @Delete(':id') @Whitelist() @Auth([RoleType.ADMIN, RoleType.USER]) @HttpCode(HttpStatus.OK) @ApiOkResponse() async deleteOtRecord( @AuthUser() user: UserEntity, @UUIDParam('id') id: Uuid, ) { const toDeteleEntity = await this.otRecordService.findOne({ id, }); if (!toDeteleEntity) { throw new OtRecordNotFoundException(); } const recordDate = moment.utc(toDeteleEntity.date); const currentDate = moment.utc(); const recordDateMonth = moment.utc(toDeteleEntity.date).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.otRecordService.deleteOtRecord(toDeteleEntity, user); return { status: 'success' }; } }