import { Body, Controller, Get, Param, Post, Query, UseGuards } from "@nestjs/common"; import { ApiBearerAuth, ApiTags } from "@nestjs/swagger"; import { InventoryService } from "./inventory.service.js"; import { CreateAssetDto } from "./dto/create-asset.dto.js"; import { ReserveAssetDto } from "./dto/reserve-asset.dto.js"; import { InstallAssetDto } from "./dto/install-asset.dto.js"; import { ReturnAssetDto } from "./dto/return-asset.dto.js"; import { CreateReservationDto } from "./dto/create-reservation.dto.js"; import { JwtAuthGuard } from "../auth/jwt-auth.guard.js"; import { PermissionGuard } from "../auth/permission.guard.js"; import { RequirePermission } from "../auth/decorators/require-permission.decorator.js"; import { CurrentUser } from "../auth/decorators/current-user.decorator.js"; import type { EdenAuthenticatedUser } from "../auth/jwt-auth.guard.js"; /** * Serialized assets, the stock ledger, and reservations — Master Prompt * §6.8, ADR-0007. Full cycle modeled here: reserve (generic or a specific * serial) → install/comodato → return. Every mutation appends a * stock_movement (ledger, never an editable balance column — see * PENDING_inventory.cjs's header comment) and an audit_log event. */ @ApiTags("inventory") @ApiBearerAuth() @UseGuards(JwtAuthGuard, PermissionGuard) @Controller("v1/inventory") export class InventoryController { constructor(private readonly inventory: InventoryService) {} @Get("assets") @RequirePermission("inventory", "view") listAssets( @Query("status") status?: string, @Query("warehouseId") warehouseId?: string, @Query("productId") productId?: string, ) { return this.inventory.listAssets(status, warehouseId, productId); } @Get("assets/:id") @RequirePermission("inventory", "view") getAsset(@Param("id") id: string) { return this.inventory.getAsset(id); } @Post("assets") @RequirePermission("inventory", "edit") createAsset(@Body() dto: CreateAssetDto, @CurrentUser() user: EdenAuthenticatedUser) { return this.inventory.createAsset(dto, user); } /** * Reserves this SPECIFIC serialized asset (quantity is always 1 — * the serial has already been picked). For the generic product+quantity * reservation described in the Master Prompt as the step BEFORE a * serial is picked, see POST /v1/inventory/reservations instead. */ @Post("assets/:id/reserve") @RequirePermission("inventory", "edit") reserveAsset( @Param("id") id: string, @Body() dto: ReserveAssetDto, @CurrentUser() user: EdenAuthenticatedUser, ) { return this.inventory.reserveAsset(id, dto, user); } @Post("assets/:id/install") @RequirePermission("inventory", "edit") installAsset( @Param("id") id: string, @Body() dto: InstallAssetDto, @CurrentUser() user: EdenAuthenticatedUser, ) { return this.inventory.installAsset(id, dto, user); } @Post("assets/:id/return") @RequirePermission("inventory", "edit") returnAsset( @Param("id") id: string, @Body() dto: ReturnAssetDto, @CurrentUser() user: EdenAuthenticatedUser, ) { return this.inventory.returnAsset(id, dto, user); } @Get("movements") @RequirePermission("inventory", "view") listMovements( @Query("warehouseId") warehouseId?: string, @Query("productId") productId?: string, @Query("referenceType") referenceType?: string, @Query("referenceId") referenceId?: string, ) { return this.inventory.listMovements(warehouseId, productId, referenceType, referenceId); } /** Generic quantity reservation (product+warehouse, no serial picked yet) — the first step of the Master Prompt §6.8 flow. */ @Get("reservations") @RequirePermission("inventory", "view") listReservations( @Query("status") status?: string, @Query("warehouseId") warehouseId?: string, @Query("productId") productId?: string, ) { return this.inventory.listReservations(status, warehouseId, productId); } @Post("reservations") @RequirePermission("inventory", "edit") createReservation(@Body() dto: CreateReservationDto, @CurrentUser() user: EdenAuthenticatedUser) { return this.inventory.createReservation(dto, user); } @Post("reservations/:id/release") @RequirePermission("inventory", "edit") releaseReservation(@Param("id") id: string, @CurrentUser() user: EdenAuthenticatedUser) { return this.inventory.releaseReservation(id, user); } }