penisularhr / src / modules / activity-record / activity-record.controller.ts
activity-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,
  ActivityRecordDateExceedTodayException,
  ActivityRecordNotFoundException,
  // RecordDateIsHolodayException,
  // RecordDateIsWeekendException,
  RecordMoreThan3DaysException,
} from '../../exceptions';
import { ApiConfigService } from '../../shared/services/api-config.service';
// import { PublicHolidayService } from '../public-holiday/public-holiday.service';
import { UserEntity } from '../user/user.entity';
import { ActivityRecordService } from './activity-record.service';
import { ActivityRecordDto } from './dtos/activity-record.dto';
import { CreateActivityRecordDto } from './dtos/create-activity-record.dto';
import { ActivityRecordPageOptionsDto } from './dtos/get-activity-record-page.dto';
import { UpdateActivityRecordDto } from './dtos/update-activity-record.dto';

@Controller('activity-records')
@ApiTags('activity-records')
export class ActivityRecordController {
  constructor(
    private activityRecordService: ActivityRecordService,
    // @Inject(forwardRef(() => PublicHolidayService))
    // private publicHolidayService: PublicHolidayService,
    private configService: ApiConfigService,
  ) {}

  @Get()
  @Whitelist()
  @Auth([RoleType.ADMIN, RoleType.USER])
  @HttpCode(HttpStatus.OK)
  @ApiPageOkResponse({
    type: ActivityRecordDto,
    description: 'Get activity records list',
  })
  async getActivityRecords(
    @Query() query: ActivityRecordPageOptionsDto,
  ): Promise<PageDto<ActivityRecordDto>> {
    return this.activityRecordService.findMany(query);
  }

  @Post()
  @Whitelist()
  @Auth([RoleType.ADMIN, RoleType.USER])
  @HttpCode(HttpStatus.OK)
  @ApiOkResponse()
  async createActivityRecord(
    @AuthUser() user: UserEntity,
    @Body() body: CreateActivityRecordDto,
  ): Promise<ActivityRecordDto> {
    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');

    // const publicHolidayEntity = await this.publicHolidayService.findOne({
    //   date: recordDate.toDate(),
    // });

    // NOTE: Temporary remove this restriction
    // if (publicHolidayEntity) {
    //   throw new RecordDateIsHolodayException();
    // }

    // NOTE: Temporary remove this restriction
    // if (recordDate.isoWeekday() >= 6) {
    //   throw new RecordDateIsWeekendException();
    // }

    if (this.configService.isProduction) {
      if (recordDate > currentDate) {
        throw new ActivityRecordDateExceedTodayException();
      }

      if (user.role === RoleType.USER && daysDifference > 3) {
        throw new RecordMoreThan3DaysException();
      }

      if (currentMonth - recordDateMonth >= 1 && currentDate.date() > 7) {
        throw new AccountHasClosedException();
      }
    }

    const otRecordEntity =
      await this.activityRecordService.createActivityRecord(body, user);

    return otRecordEntity.toDto();
  }

  @Patch(':id')
  @Whitelist()
  @Auth([RoleType.ADMIN, RoleType.USER])
  @HttpCode(HttpStatus.OK)
  @ApiOkResponse()
  async updateActivityRecord(
    @AuthUser() user: UserEntity,
    @UUIDParam('id') id: Uuid,
    @Body() body: UpdateActivityRecordDto,
  ): Promise<ActivityRecordDto> {
    const toPatchEntity = await this.activityRecordService.findOne(
      {
        id,
      },
      true,
    );

    if (!toPatchEntity) {
      throw new ActivityRecordNotFoundException();
    }

    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');

    // const publicHolidayEntity = await this.publicHolidayService.findOne({
    //   date: recordDate.toDate(),
    // });

    // NOTE: Temporary remove this restriction
    // if (publicHolidayEntity) {
    //   throw new RecordDateIsHolodayException();
    // }

    // NOTE: Temporary remove this restriction
    // if (recordDate.isoWeekday() >= 6) {
    //   throw new RecordDateIsWeekendException();
    // }

    if (this.configService.isProduction) {
      if (recordDate > currentDate) {
        throw new ActivityRecordDateExceedTodayException();
      }

      if (user.role === RoleType.USER && daysDifference > 3) {
        throw new RecordMoreThan3DaysException();
      }

      if (currentMonth - recordDateMonth >= 1 && currentDate.date() > 7) {
        throw new AccountHasClosedException();
      }
    }

    const activityRecordEntity =
      await this.activityRecordService.updateActivityRecord(
        toPatchEntity,
        body,
        user,
      );

    return activityRecordEntity.toDto();
  }

  @Delete(':id')
  @Whitelist()
  @Auth([RoleType.ADMIN, RoleType.USER])
  @HttpCode(HttpStatus.OK)
  @ApiOkResponse()
  async deleteActivityRecord(
    @AuthUser() user: UserEntity,
    @UUIDParam('id') id: Uuid,
  ) {
    const toDeleteEntity = await this.activityRecordService.findOne(
      {
        id,
      },
      true,
    );

    if (!toDeleteEntity) {
      throw new ActivityRecordNotFoundException();
    }

    const recordDate = moment.utc(toDeleteEntity.date);
    const currentDate = moment.utc();

    const recordDateMonth = moment.utc(toDeleteEntity.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.activityRecordService.deleteActivityRecord(toDeleteEntity, user);

    return { status: 'success' };
  }
}