penisularhr / src / modules / ot / ot-record.controller.ts
ot-record.controller.ts
Raw
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' };
  }
}