penisularhr / src / modules / report / report.controller.ts
report.controller.ts
Raw
/* eslint-disable @typescript-eslint/no-unsafe-enum-comparison */
/* eslint-disable no-await-in-loop */
import {
  Controller,
  Get,
  HttpCode,
  HttpStatus,
  Query,
  Req,
  UnauthorizedException,
} from '@nestjs/common';
import { ApiOkResponse, ApiTags } from '@nestjs/swagger';
import { Request } from 'express';
import moment from 'moment';

import { PartialIncentiveName } from '../../constants';
import { Auth, AuthUser, Whitelist } from '../../decorators';
import { ValidatorService } from '../../shared/services/validator.service';
import { ActivityGroupService } from '../activity-record/activity-group.service';
import { ActivityRecordService } from '../activity-record/activity-record.service';
import { ActivityRecordSettingService } from '../activity-record/activity-record-setting.service';
import { AdminConfigService } from '../admin-config/admin-config.service';
import { AuditLogService } from '../audit-log/audit-log.service';
import { BlockService } from '../block/block.service';
import { EmployeeService } from '../employee/employee.service';
import { IncentiveRecordService } from '../incentive/incentive-record.service';
import { IncentiveSettingService } from '../incentive/incentive-settings.service';
import { MonthlyRecordService } from '../monthly-record/monthly-record.service';
import { OtRecordService } from '../ot/ot-record.service';
import { PublicHolidayService } from '../public-holiday/public-holiday.service';
import { RainfallRecordService } from '../rainfall/rainfall.service';
import { SectorService } from '../sector/sector.service';
import { UserEntity } from '../user/user.entity';
import { UserService } from '../user/user.service';
import { VehicleNameService } from '../vehicle/vehicle-name.service';
import { VehicleRecordService } from '../vehicle/vehicle-record.service';
import { GetDropdownDto } from './dtos/get-dropdown.dto';
import { GetActivityDto } from './dtos/get-report-activity.dto';
import { GetAuditLogDto } from './dtos/get-report-audit-log.dto';
import { GetByEmployeeDto } from './dtos/get-report-by-employee.dto';
import { GetIncentiveDto } from './dtos/get-report-incentive.dto';
import { GetOtDto } from './dtos/get-report-ot.dto';
import { GetRainfallDto } from './dtos/get-report-rainfall.dto';
import { GetVehicleDto } from './dtos/get-report-vehicle.dto';
import { GetUnfinisedReportDto } from './dtos/get-unfinised-report.dto';

@Controller('report')
@ApiTags('report')
export class ReportController {
  constructor(
    private employeeService: EmployeeService,
    private activityRecordSettingService: ActivityRecordSettingService,
    private activityRecordService: ActivityRecordService,
    private activityGroupService: ActivityGroupService,
    private otRecordService: OtRecordService,
    private monthlyRecordService: MonthlyRecordService,
    private incentiveRecordService: IncentiveRecordService,
    private incentiveSettingService: IncentiveSettingService,
    private validatorService: ValidatorService,
    private rainfallService: RainfallRecordService,
    private vehicleService: VehicleRecordService,
    private vehicleNameService: VehicleNameService,
    private blockService: BlockService,
    private sectorService: SectorService,
    private publicHolidayService: PublicHolidayService,
    private adminConfigService: AdminConfigService,
    private auditLogService: AuditLogService,
    private userService: UserService,
  ) {}

  @Get('employee-info')
  @HttpCode(HttpStatus.OK)
  @ApiOkResponse()
  async getEmployees(@Req() req: Request, @Query() query: GetByEmployeeDto) {
    const { hostname, url, protocol, headers } = req;

    const isValidate = this.validatorService.validateSignature({
      hostname,
      url,
      protocol,
      timestamp: Number(headers['x-report-timestamp']),
      signature:
        headers['x-report-signature'] &&
        !Array.isArray(headers['x-report-signature'])
          ? headers['x-report-signature']
          : '',
    });

    if (!isValidate) {
      throw new UnauthorizedException('invalid signature');
    }

    return this.employeeService.findManyByReportFunction(query);
  }

  @Get('employee-sector')
  @HttpCode(HttpStatus.OK)
  @ApiOkResponse()
  async getSectorSum(@Req() req: Request, @Query() query: GetByEmployeeDto) {
    const { hostname, url, protocol, headers } = req;

    const isValidate = this.validatorService.validateSignature({
      hostname,
      url,
      protocol,
      timestamp: Number(headers['x-report-timestamp']),
      signature:
        headers['x-report-signature'] &&
        !Array.isArray(headers['x-report-signature'])
          ? headers['x-report-signature']
          : '',
    });

    if (!isValidate) {
      throw new UnauthorizedException('invalid signature');
    }

    const employees =
      await this.employeeService.findManyByReportFunction(query);

    const returnData: unknown[] = [];

    for (const employee of employees) {
      returnData.push(
        this.activityRecordService.getSummaryActivityByEmployee(
          query,
          employee,
        ),
      );
    }

    return Promise.all(returnData);
  }

  @Get('employee-ot')
  @HttpCode(HttpStatus.OK)
  @ApiOkResponse()
  async getOtSum(@Req() req: Request, @Query() query: GetByEmployeeDto) {
    const { hostname, url, protocol, headers } = req;

    const isValidate = this.validatorService.validateSignature({
      hostname,
      url,
      protocol,
      timestamp: Number(headers['x-report-timestamp']),
      signature:
        headers['x-report-signature'] &&
        !Array.isArray(headers['x-report-signature'])
          ? headers['x-report-signature']
          : '',
    });

    if (!isValidate) {
      throw new UnauthorizedException('invalid signature');
    }

    const employees =
      await this.employeeService.findManyByReportFunction(query);

    const returnData: unknown[] = [];

    for (const employee of employees) {
      returnData.push(
        this.otRecordService.getSummaryOTByEmployee(query, employee),
      );
    }

    return Promise.all(returnData);
  }

  @Get('employee-incentive')
  @HttpCode(HttpStatus.OK)
  @ApiOkResponse()
  async getIncentiveSum(@Req() req: Request, @Query() query: GetByEmployeeDto) {
    const { hostname, url, protocol, headers } = req;

    const isValidate = this.validatorService.validateSignature({
      hostname,
      url,
      protocol,
      timestamp: Number(headers['x-report-timestamp']),
      signature:
        headers['x-report-signature'] &&
        !Array.isArray(headers['x-report-signature'])
          ? headers['x-report-signature']
          : '',
    });

    if (!isValidate) {
      throw new UnauthorizedException('invalid signature');
    }

    const employees =
      await this.employeeService.findManyByReportFunction(query);

    const returnData: unknown[] = [];

    for (const employee of employees) {
      returnData.push(
        this.incentiveRecordService.getSummaryIncentiveByEmployee(
          query,
          employee,
        ),
      );
    }

    return Promise.all(returnData);
  }

  @Get('employee-monthly')
  @HttpCode(HttpStatus.OK)
  @ApiOkResponse()
  async getMonthlyRecord(
    @Req() req: Request,
    @Query() query: GetByEmployeeDto,
  ) {
    const { hostname, url, protocol, headers } = req;

    const isValidate = this.validatorService.validateSignature({
      hostname,
      url,
      protocol,
      timestamp: Number(headers['x-report-timestamp']),
      signature:
        headers['x-report-signature'] &&
        !Array.isArray(headers['x-report-signature'])
          ? headers['x-report-signature']
          : '',
    });

    if (!isValidate) {
      throw new UnauthorizedException('invalid signature');
    }

    const employees =
      await this.employeeService.findManyByReportFunction(query);

    const returnData: unknown[] = [];

    for (const employee of employees) {
      returnData.push(
        this.monthlyRecordService.getSummarMonthlyByEmployee(query, employee),
      );
    }

    return Promise.all(returnData);
  }

  @Get('activity')
  @HttpCode(HttpStatus.OK)
  @ApiOkResponse()
  async getActivityRecords(
    @Req() req: Request,
    @Query() query: GetActivityDto,
  ) {
    const { hostname, url, protocol, headers } = req;

    const isValidate = this.validatorService.validateSignature({
      hostname,
      url,
      protocol,
      timestamp: Number(headers['x-report-timestamp']),
      signature:
        headers['x-report-signature'] &&
        !Array.isArray(headers['x-report-signature'])
          ? headers['x-report-signature']
          : '',
    });

    if (!isValidate) {
      throw new UnauthorizedException('invalid signature');
    }

    return this.activityRecordService.findReportMany(query);
  }

  @Get('activity-sum')
  @HttpCode(HttpStatus.OK)
  @ApiOkResponse()
  async getActivitySumRecords(
    @Req() req: Request,
    @Query() query: GetActivityDto,
  ) {
    const { hostname, url, protocol, headers } = req;

    const isValidate = this.validatorService.validateSignature({
      hostname,
      url,
      protocol,
      timestamp: Number(headers['x-report-timestamp']),
      signature:
        headers['x-report-signature'] &&
        !Array.isArray(headers['x-report-signature'])
          ? headers['x-report-signature']
          : '',
    });

    if (!isValidate) {
      throw new UnauthorizedException('invalid signature');
    }

    return this.activityRecordService.findByActivitySum(query);
  }

  @Get('ot')
  @HttpCode(HttpStatus.OK)
  @ApiOkResponse()
  async getOtRecords(@Req() req: Request, @Query() query: GetOtDto) {
    const { hostname, url, protocol, headers } = req;

    const isValidate = this.validatorService.validateSignature({
      hostname,
      url,
      protocol,
      timestamp: Number(headers['x-report-timestamp']),
      signature:
        headers['x-report-signature'] &&
        !Array.isArray(headers['x-report-signature'])
          ? headers['x-report-signature']
          : '',
    });

    if (!isValidate) {
      throw new UnauthorizedException('invalid signature');
    }

    return this.otRecordService.findReportMany(query);
  }

  @Get('incentive')
  @HttpCode(HttpStatus.OK)
  @ApiOkResponse()
  async getIncentiveRecords(
    @Req() req: Request,
    @Query() query: GetIncentiveDto,
  ) {
    const { hostname, url, protocol, headers } = req;

    const isValidate = this.validatorService.validateSignature({
      hostname,
      url,
      protocol,
      timestamp: Number(headers['x-report-timestamp']),
      signature:
        headers['x-report-signature'] &&
        !Array.isArray(headers['x-report-signature'])
          ? headers['x-report-signature']
          : '',
    });

    if (!isValidate) {
      throw new UnauthorizedException('invalid signature');
    }

    return this.incentiveRecordService.findReportMany(query);
  }

  @Get('rainfall')
  @HttpCode(HttpStatus.OK)
  @ApiOkResponse()
  async getRainfallRecords(
    @Req() req: Request,
    @Query() query: GetRainfallDto,
  ) {
    const { hostname, url, protocol, headers } = req;

    const isValidate = this.validatorService.validateSignature({
      hostname,
      url,
      protocol,
      timestamp: Number(headers['x-report-timestamp']),
      signature:
        headers['x-report-signature'] &&
        !Array.isArray(headers['x-report-signature'])
          ? headers['x-report-signature']
          : '',
    });

    if (!isValidate) {
      throw new UnauthorizedException('invalid signature');
    }

    return this.rainfallService.findReportMany(query);
  }

  @Get('vehicle')
  @HttpCode(HttpStatus.OK)
  @ApiOkResponse()
  async getVehicleRecords(@Req() req: Request, @Query() query: GetVehicleDto) {
    const { hostname, url, protocol, headers } = req;

    const isValidate = this.validatorService.validateSignature({
      hostname,
      url,
      protocol,
      timestamp: Number(headers['x-report-timestamp']),
      signature:
        headers['x-report-signature'] &&
        !Array.isArray(headers['x-report-signature'])
          ? headers['x-report-signature']
          : '',
    });

    if (!isValidate) {
      throw new UnauthorizedException('invalid signature');
    }

    return this.vehicleService.findReportMany(query);
  }

  @Get('dropdown')
  @Whitelist()
  @HttpCode(HttpStatus.OK)
  @ApiOkResponse()
  @Auth([], { public: true })
  async getDropdown(
    @Req() req: Request,
    @Query() query: GetDropdownDto,
    @AuthUser() user?: UserEntity,
  ) {
    if (!user) {
      const { hostname, url, protocol, headers } = req;

      const isValidate = this.validatorService.validateSignature({
        hostname,
        url,
        protocol,
        timestamp: Number(headers['x-report-timestamp']),
        signature:
          headers['x-report-signature'] &&
          !Array.isArray(headers['x-report-signature'])
            ? headers['x-report-signature']
            : '',
      });

      if (!isValidate) {
        throw new UnauthorizedException('invalid signature');
      }
    }

    const employeeName = await this.employeeService.findManyDropdown({
      date: query.date,
      shouldFilter: query.shouldFilter,
      showInactive: query.showInactive,
    });
    const blockName = await this.blockService.findManyDropdown(
      query.showInactive,
    );
    const activityName =
      await this.activityRecordSettingService.findManyDropdown({
        date: query.date,
        shouldShowInOtfilter: query.shouldShowInOtfilter,
        showInactive: query.showInactive,
      });

    const incentiveName = await this.incentiveSettingService.findManyDropdown(
      query.showInactive,
    );
    const partialIncentiveName = incentiveName.filter(
      (el) =>
        el.name === PartialIncentiveName.FRUIT_HARVEST ||
        el.name === PartialIncentiveName.SUCKER_HARVEST ||
        el.name === PartialIncentiveName.SUCKER_PLANTING ||
        el.name === 'None',
    );
    const sectorName = await this.sectorService.findManyDropdown();
    const activityGroupName =
      await this.activityGroupService.findManyDropdown();
    const vehicleName = await this.vehicleNameService.findManyDropdown();
    const fullSelectionEmployee = [...employeeName];

    const activitySettingEntityArr =
      await this.activityRecordSettingService.findManyWithoutPagination();

    const incentiveSettingEntityArr =
      await this.incentiveSettingService.findManyWithoutPagination();

    const userEntityArr = await this.userService.findMany();

    const userArr = userEntityArr.map((el: UserEntity) => el.toDto());

    fullSelectionEmployee.push({
      name: 'None',
      value: null,
    });

    return {
      employeeName,
      blockName,
      activityName,
      incentiveName,
      sectorName,
      activityGroupName,
      partialIncentiveName,
      vehicleName,
      fullSelectionEmployee,
      activitySettingEntityArr,
      incentiveSettingEntityArr,
      userArr,
    };
  }

  @Get('unfinished-activity-record')
  @Whitelist()
  @HttpCode(HttpStatus.OK)
  @ApiOkResponse()
  @Auth([], { public: true })
  // eslint-disable-next-line sonarjs/cognitive-complexity
  async getUnfinishedActivityRecords(
    @Req() req: Request,
    @Query() query: GetUnfinisedReportDto,
    @AuthUser() user?: UserEntity,
  ) {
    if (!user) {
      const { hostname, url, protocol, headers } = req;

      const isValidate = this.validatorService.validateSignature({
        hostname,
        url,
        protocol,
        timestamp: Number(headers['x-report-timestamp']),
        signature:
          headers['x-report-signature'] &&
          !Array.isArray(headers['x-report-signature'])
            ? headers['x-report-signature']
            : '',
      });

      if (!isValidate) {
        throw new UnauthorizedException('invalid signature');
      }
    }

    const employees = await this.employeeService.findManyWithoutPagination({
      isActive: true,
    });

    if (employees.length === 0) {
      return [];
    }

    const toReturnArr: Array<{
      date: Date;
      employee: string;
      currentHour: number;
      expectedHour: number;
    }> = [];

    let toDeductDay = 0;

    for (let i = 0; i < query.days; i++) {
      const toCheckDate = moment.utc().startOf('date').add(-toDeductDay, 'day');

      let shouldCheckHolidayAndWeekend = true;

      while (shouldCheckHolidayAndWeekend) {
        const publicHolidayEntity = await this.publicHolidayService.findOne({
          date: toCheckDate.toDate(),
        });

        //NOTE: Temporary disable weekend check
        // if (publicHolidayEntity || toCheckDate.isoWeekday() >= 6) {
        if (publicHolidayEntity) {
          toDeductDay++;
          toCheckDate.add(-1, 'day');
        } else {
          shouldCheckHolidayAndWeekend = false;
        }
      }

      for (const employee of employees) {
        const currentDateSumHour =
          await this.activityRecordService.getEmployeeDayHour(
            toCheckDate.toDate(),
            employee,
          );

        if (currentDateSumHour < 8) {
          toReturnArr.push({
            date: toCheckDate.toDate(),
            employee: employee.name,
            currentHour: currentDateSumHour,
            expectedHour: 8,
          });
        }
      }

      toDeductDay++;
    }

    return toReturnArr;
  }

  @Get('employee-advance-info')
  @HttpCode(HttpStatus.OK)
  @ApiOkResponse()
  async getAdvanceInfo(@Req() req: Request, @Query() query: GetByEmployeeDto) {
    const { hostname, url, protocol, headers } = req;

    const isValidate = this.validatorService.validateSignature({
      hostname,
      url,
      protocol,
      timestamp: Number(headers['x-report-timestamp']),
      signature:
        headers['x-report-signature'] &&
        !Array.isArray(headers['x-report-signature'])
          ? headers['x-report-signature']
          : '',
    });

    if (!isValidate) {
      throw new UnauthorizedException('invalid signature');
    }

    const employees =
      await this.employeeService.findManyByReportFunction(query);

    const adminConfig = await this.adminConfigService.findOne();

    const returnData: unknown[] = [];

    for (const employee of employees) {
      returnData.push(
        this.activityRecordService.getAdvanceInfoByEmployee(
          query,
          employee,
          adminConfig,
        ),
      );
    }

    return Promise.all(returnData);
  }

  @Get('employee-rest-day-wages-info')
  @HttpCode(HttpStatus.OK)
  @ApiOkResponse()
  async getRestDayWagesInfo(
    @Req() req: Request,
    @Query() query: GetByEmployeeDto,
  ) {
    const { hostname, url, protocol, headers } = req;

    const isValidate = this.validatorService.validateSignature({
      hostname,
      url,
      protocol,
      timestamp: Number(headers['x-report-timestamp']),
      signature:
        headers['x-report-signature'] &&
        !Array.isArray(headers['x-report-signature'])
          ? headers['x-report-signature']
          : '',
    });

    if (!isValidate) {
      throw new UnauthorizedException('invalid signature');
    }

    const employees =
      await this.employeeService.findManyByReportFunction(query);

    const adminConfig = await this.adminConfigService.findOne();

    const returnData: unknown[] = [];

    for (const employee of employees) {
      returnData.push(
        this.activityRecordService.getRestDayWagesInfoByEmployee(
          query,
          employee,
          adminConfig,
        ),
      );
    }

    return Promise.all(returnData);
  }

  @Get('audit-log')
  @HttpCode(HttpStatus.OK)
  @ApiOkResponse()
  async getAuditLog(@Req() req: Request, @Query() query: GetAuditLogDto) {
    const { hostname, url, protocol, headers } = req;

    const isValidate = this.validatorService.validateSignature({
      hostname,
      url,
      protocol,
      timestamp: Number(headers['x-report-timestamp']),
      signature:
        headers['x-report-signature'] &&
        !Array.isArray(headers['x-report-signature'])
          ? headers['x-report-signature']
          : '',
    });

    if (!isValidate) {
      throw new UnauthorizedException('invalid signature');
    }

    return this.auditLogService.findReportMany(query);
  }
}