diff --git a/api-v3/src/inspection-visits/field-inventory.controller.ts b/api-v3/src/inspection-visits/field-inventory.controller.ts new file mode 100644 index 0000000..99e32a6 --- /dev/null +++ b/api-v3/src/inspection-visits/field-inventory.controller.ts @@ -0,0 +1,93 @@ +import { + Body, + Controller, + Get, + Param, + ParseUUIDPipe, + Post, + Query, + Req, + UploadedFile, + UseInterceptors, +} from '@nestjs/common'; +import { FileInterceptor } from '@nestjs/platform-express'; +import { CurrentAuth } from '../auth/decorators/current-auth.decorator'; +import { RequirePermissions } from '../authorization/decorators/require-permissions.decorator'; +import { MAX_ASSET_MEDIA_BYTES, type UploadedAssetFile } from '../asset-master/asset-media-file'; +import type { AuthPrincipal, RequestWithContext } from '../common/http/request-context'; +import { CreateFieldInventoryDto } from './dto/create-field-inventory.dto'; +import { ListFieldInventoryQueryDto } from './dto/list-field-inventory-query.dto'; +import { UploadFieldInventoryPhotoDto } from './dto/upload-field-inventory-photo.dto'; +import { FieldInventoryService } from './field-inventory.service'; + +@Controller('inspection-visits/:visitId/field-inventory') +export class FieldInventoryController { + constructor(private readonly fieldInventory: FieldInventoryService) {} + + @Get() + @RequirePermissions('assets.read', 'inspections.execute') + list( + @Param('visitId', new ParseUUIDPipe({ version: '4' })) visitId: string, + @Query() query: ListFieldInventoryQueryDto, + @CurrentAuth() principal: AuthPrincipal, + ) { + return this.fieldInventory.list(visitId, query, principal); + } + + @Get('types') + @RequirePermissions('assets.read', 'inspections.execute') + types( + @Param('visitId', new ParseUUIDPipe({ version: '4' })) visitId: string, + @Query('parentId') parentId: string | undefined, + @CurrentAuth() principal: AuthPrincipal, + ) { + return this.fieldInventory.types(visitId, parentId, principal); + } + + @Get(':assetId') + @RequirePermissions('assets.read', 'inspections.execute') + detail( + @Param('visitId', new ParseUUIDPipe({ version: '4' })) visitId: string, + @Param('assetId', new ParseUUIDPipe({ version: '4' })) assetId: string, + @CurrentAuth() principal: AuthPrincipal, + ) { + return this.fieldInventory.detail(visitId, assetId, principal); + } + + @Post(':assetId/select') + @RequirePermissions('assets.read', 'inspections.execute') + selectExisting( + @Param('visitId', new ParseUUIDPipe({ version: '4' })) visitId: string, + @Param('assetId', new ParseUUIDPipe({ version: '4' })) assetId: string, + @CurrentAuth() principal: AuthPrincipal, + ) { + return this.fieldInventory.selectExisting(visitId, assetId, principal); + } + + @Post() + @RequirePermissions('assets.create', 'inspections.execute') + create( + @Param('visitId', new ParseUUIDPipe({ version: '4' })) visitId: string, + @Body() dto: CreateFieldInventoryDto, + @CurrentAuth() principal: AuthPrincipal, + @Req() request: RequestWithContext, + ) { + return this.fieldInventory.create(visitId, dto, principal, request); + } + + @Post(':assetId/photos') + @RequirePermissions('assets.create', 'inspections.execute') + @UseInterceptors(FileInterceptor('file', { + limits: { fileSize: MAX_ASSET_MEDIA_BYTES, files: 1 }, + })) + uploadPhoto( + @Param('visitId', new ParseUUIDPipe({ version: '4' })) visitId: string, + @Param('assetId', new ParseUUIDPipe({ version: '4' })) assetId: string, + @Body() dto: UploadFieldInventoryPhotoDto, + @UploadedFile() file: UploadedAssetFile | undefined, + @CurrentAuth() principal: AuthPrincipal, + @Req() request: RequestWithContext, + ) { + return this.fieldInventory.uploadPhoto(visitId, assetId, dto, file, principal, request); + } +}