penisularhr / src / modules / vehicle / vehicle-record.controller.ts
vehicle-record.controller.ts
Raw
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,
  OtRecordDateExceedTodayException,
  RecordMoreThan3DaysException,
  VehicleNotFoundException,
} from '../../exceptions';
import { ApiConfigService } from '../../shared/services/api-config.service';
import { UserEntity } from '../user/user.entity';
import { CreateVehicleRecordDto } from './dtos/create-vehicle-record.dto';
import { VehicleRecordPageOptionsDto } from './dtos/get-vehicle-record-page.dto';
import { UpdateVehicleRecordDto } from './dtos/update-vehicle-record.dto';
import { VehicleRecordDto } from './dtos/vehicle-record.dto';
import { VehicleRecordService } from './vehicle-record.service';

@Controller('vehicle-record')
@ApiTags('vehicle-record')
export class VehicleRecordController {
  constructor(
    private vehicleRecordService: VehicleRecordService,
    private configService: ApiConfigService,
  ) {}

  @Get()
  @Whitelist()
  @Auth([RoleType.ADMIN, RoleType.USER])
  @HttpCode(HttpStatus.OK)
  @ApiPageOkResponse({
    type: VehicleRecordDto,
    description: 'Get Vehicle Records',
  })
  async getVechileRecords(
    @Query() dto: VehicleRecordPageOptionsDto,
  ): Promise<PageDto<VehicleRecordDto>> {
    return this.vehicleRecordService.findMany(dto);
  }

  @Post()
  @Whitelist()
  @Auth([RoleType.ADMIN, RoleType.USER])
  @HttpCode(HttpStatus.CREATED)
  @ApiCreatedResponse()
  async createVehicle(
    @AuthUser() user: UserEntity,
    @Body() body: CreateVehicleRecordDto,
  ): Promise<VehicleRecordDto> {
    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();
      }
    }

    const vehicleEntity = await this.vehicleRecordService.createVehicle(body);

    return vehicleEntity.toDto();
  }

  @Patch(':id')
  @Whitelist()
  @Auth([RoleType.ADMIN, RoleType.USER])
  @HttpCode(HttpStatus.OK)
  @ApiOkResponse()
  async updateRainfall(
    @AuthUser() user: UserEntity,
    @Param('id') id: Uuid,
    @Body() body: UpdateVehicleRecordDto,
  ): Promise<VehicleRecordDto> {
    const toPatchEntity = await this.vehicleRecordService.findOne({
      id,
    });

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

    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();
      }
    }

    const vehicleEntity = await this.vehicleRecordService.updateVehicle(
      toPatchEntity,
      body,
    );

    return vehicleEntity.toDto();
  }

  @Delete(':id')
  @Whitelist()
  @Auth([RoleType.ADMIN, RoleType.USER])
  @HttpCode(HttpStatus.OK)
  @ApiOkResponse()
  async deleteRainfall(
    @Param('id') id: Uuid,
    @AuthUser() user: UserEntity,
  ): Promise<Record<string, string>> {
    const toDeleteEntity = await this.vehicleRecordService.findOne({
      id,
    });

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

    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();
      }

      if (recordDate > currentDate) {
        throw new OtRecordDateExceedTodayException();
      }
    }

    await this.vehicleRecordService.deleteVehicle(toDeleteEntity);

    return { status: 'success' };
  }
}