Vizzuality/landgriffon

View on GitHub
api/src/modules/sourcing-locations/sourcing-locations.controller.ts

Summary

Maintainability
D
1 day
Test Coverage
A
100%
import {
  Body,
  Controller,
  Delete,
  Get,
  Param,
  Patch,
  Post,
  Query,
  UseGuards,
  UseInterceptors,
  UsePipes,
  ValidationPipe,
} from '@nestjs/common';
import { SourcingLocationsService } from 'modules/sourcing-locations/sourcing-locations.service';
import {
  ApiBadRequestResponse,
  ApiBearerAuth,
  ApiForbiddenResponse,
  ApiNotFoundResponse,
  ApiOkResponse,
  ApiOperation,
  ApiTags,
  ApiUnauthorizedResponse,
} from '@nestjs/swagger';
import {
  JSONAPIPaginationQueryParams,
  JSONAPIQueryParams,
  JSONAPISingleEntityQueryParams,
} from 'decorators/json-api-parameters.decorator';
import {
  FetchSpecification,
  ProcessFetchSpecification,
} from 'nestjs-base-service';
import {
  SourcingLocation,
  sourcingLocationResource,
} from 'modules/sourcing-locations/sourcing-location.entity';
import { CreateSourcingLocationDto } from 'modules/sourcing-locations/dto/create.sourcing-location.dto';
import { UpdateSourcingLocationDto } from 'modules/sourcing-locations/dto/update.sourcing-location.dto';
import { PaginationMeta } from 'utils/app-base.service';
import { SourcingLocationsMaterialsResponseDto } from 'modules/sourcing-locations/dto/materials.sourcing-location.dto';
import { GetSourcingMaterialsQueryDto } from 'modules/sourcing-locations/dto/materials-query.sourcing-location.dto';
import { SourcingLocationsMaterialsService } from 'modules/sourcing-locations/sourcing-locations-materials.service';
import { SetUserInterceptor } from 'decorators/set-user.interceptor';
import { LocationTypesDto } from 'modules/sourcing-locations/dto/location-type.sourcing-locations.dto';
import { GetLocationTypesDto } from 'modules/sourcing-locations/dto/location-types-options.sourcing-locations.dto';
import { RolesGuard } from 'guards/roles.guard';
import { RequiredRoles } from 'decorators/roles.decorator';
import { ROLES } from 'modules/authorization/roles/roles.enum';
import { SetScenarioIdsInterceptor } from 'modules/impact/set-scenario-ids.interceptor';

@Controller(`/api/v1/sourcing-locations`)
@ApiTags(sourcingLocationResource.className)
@ApiBearerAuth()
@UseGuards(RolesGuard)
export class SourcingLocationsController {
  constructor(
    public readonly sourcingLocationsService: SourcingLocationsService,
    public readonly sourcingLocationsMaterialsService: SourcingLocationsMaterialsService,
  ) {}

  @ApiOperation({
    description: 'Find all sourcing locations',
  })
  @ApiOkResponse({
    type: SourcingLocation,
  })
  @ApiUnauthorizedResponse()
  @ApiForbiddenResponse()
  @JSONAPIQueryParams({
    availableFilters: sourcingLocationResource.columnsAllowedAsFilter.map(
      (columnName: string) => ({
        name: columnName,
      }),
    ),
    entitiesAllowedAsIncludes:
      sourcingLocationResource.entitiesAllowedAsIncludes,
  })
  @Get()
  async findAll(
    @ProcessFetchSpecification({
      allowedFilters: sourcingLocationResource.columnsAllowedAsFilter,
    })
    fetchSpecification: FetchSpecification,
  ): Promise<SourcingLocation> {
    const results: {
      data: (Partial<SourcingLocation> | undefined)[];
      metadata: PaginationMeta | undefined;
    } = await this.sourcingLocationsService.findAllPaginated(
      fetchSpecification,
    );
    return this.sourcingLocationsService.serialize(
      results.data,
      results.metadata,
    );
  }

  @ApiOperation({
    description: 'Find all Materials with details for Sourcing Locations',
  })
  @ApiOkResponse({
    type: SourcingLocationsMaterialsResponseDto,
  })
  @ApiUnauthorizedResponse()
  @ApiForbiddenResponse()
  @JSONAPIPaginationQueryParams()
  @Get('/materials')
  async findAllMaterials(
    @ProcessFetchSpecification()
    fetchSpecification: FetchSpecification,

    @Query(ValidationPipe) queryParams: GetSourcingMaterialsQueryDto,
  ): Promise<SourcingLocationsMaterialsResponseDto> {
    const results: {
      data: (Partial<SourcingLocation> | undefined)[];
      metadata: PaginationMeta | undefined;
    } = await this.sourcingLocationsMaterialsService.findAllPaginated(
      fetchSpecification,
    );
    return this.sourcingLocationsMaterialsService.serialize(
      results.data,
      results.metadata,
    );
  }

  @ApiOperation({
    description:
      'Gets available location types. Optionally returns all supported location types',
  })
  @ApiOkResponse({ type: LocationTypesDto })
  @UseInterceptors(SetScenarioIdsInterceptor)
  @Get('/location-types')
  async getLocationTypes(
    @Query(ValidationPipe) locationTypesOptions: GetLocationTypesDto,
  ): Promise<LocationTypesDto> {
    return this.sourcingLocationsService.getLocationTypes(locationTypesOptions);
  }

  /**
   * @deprecated: We will deprecate this endpoint in favour of /location-types supporting a supported param
   *              to return all supported location types
   */
  @ApiOperation({
    description: 'Get location types supported by the platform',
    deprecated: true,
  })
  @ApiOkResponse({ type: LocationTypesDto })
  @Get('/location-types/supported')
  async getAllSupportedLocationTypes(): Promise<LocationTypesDto> {
    return this.sourcingLocationsService.getAllSupportedLocationTypes({
      sort: 'ASC',
    });
  }

  @ApiOperation({ description: 'Find sourcing location by id' })
  @ApiOkResponse({ type: SourcingLocation })
  @ApiNotFoundResponse({ description: 'Sourcing location not found' })
  @JSONAPISingleEntityQueryParams()
  @Get(':id')
  async findOne(
    @ProcessFetchSpecification({
      allowedFilters: sourcingLocationResource.columnsAllowedAsFilter,
    })
    fetchSpecification: FetchSpecification,
    @Param('id') id: string,
  ): Promise<SourcingLocation> {
    return await this.sourcingLocationsService.serialize(
      await this.sourcingLocationsService.getById(id, fetchSpecification),
    );
  }

  @ApiOperation({ description: 'Create a sourcing location' })
  @ApiOkResponse({ type: SourcingLocation })
  @ApiBadRequestResponse({
    description: 'Bad Request. Incorrect or missing parameters',
  })
  @RequiredRoles(ROLES.ADMIN)
  @Post()
  @UsePipes(new ValidationPipe())
  async create(
    @Body() dto: CreateSourcingLocationDto,
  ): Promise<SourcingLocation> {
    return await this.sourcingLocationsService.serialize(
      await this.sourcingLocationsService.create(dto),
    );
  }

  @ApiOperation({ description: 'Updates a sourcing location' })
  @ApiOkResponse({ type: SourcingLocation })
  @ApiNotFoundResponse({ description: 'Sourcing location not found' })
  @RequiredRoles(ROLES.ADMIN)
  @UseInterceptors(SetUserInterceptor)
  @Patch(':id')
  async update(
    @Body(new ValidationPipe()) dto: UpdateSourcingLocationDto,
    @Param('id') id: string,
  ): Promise<SourcingLocation> {
    return await this.sourcingLocationsService.serialize(
      await this.sourcingLocationsService.update(id, dto),
    );
  }

  @ApiOperation({ description: 'Deletes a sourcing location' })
  @ApiOkResponse()
  @ApiNotFoundResponse({ description: 'Sourcing location not found' })
  @RequiredRoles(ROLES.ADMIN)
  @Delete(':id')
  async delete(@Param('id') id: string): Promise<void> {
    return await this.sourcingLocationsService.remove(id);
  }
}