Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Nelsoncg98/InnovaTech/llms.txt

Use this file to discover all available pages before exploring further.

This endpoint performs an atomic, transactional decrement of available stock for a given product. It is the core write operation of servicio-inventario and is designed to be called as part of a larger SAGA transaction orchestrated by servicio-ventapos. The decrement only proceeds when the current stockDisponible is greater than or equal to the requested cantidad; otherwise the operation is rejected and no data is modified. Because the method is annotated with @Transactional, partial writes cannot occur even under concurrent load.

Endpoint

POST /api/v1/inventario/{productoId}/descontar

Path Parameters

productoId
string
required
The unique product identifier of the item whose stock should be decremented. Must correspond to an existing record in the inventario table. Example: PROD-001.

Query Parameters

cantidad
integer
required
The number of units to subtract from the product’s current stockDisponible. Must be a positive integer. The operation is rejected if stockDisponible < cantidad.

Responses

200 OK
string
Returned when the stock decrement succeeds. Response body is the plain string:
Stock descontado exitosamente
400 Bad Request
string
Returned when the current stockDisponible is less than the requested cantidad. The product exists in the database but does not have enough units to fulfil the request. Response body is the plain string:
Stock insuficiente o producto no encontrado
500 Internal Server Error
string
Returned when the productoId does not exist in the inventario table. The service method throws an uncaught RuntimeException("Producto no encontrado en inventario"), which Spring Boot converts to an HTTP 500 response. The controller does not catch this exception.

Example Request

curl -X POST "http://localhost:8080/api/v1/inventario/PROD-001/descontar?cantidad=5"

Example Responses

Success (200 OK):
Stock descontado exitosamente
Failure — insufficient stock (400 Bad Request):
Stock insuficiente o producto no encontrado
Failure — product not found (500 Internal Server Error): Spring Boot returns a default error response body. The RuntimeException thrown by the service is not caught by the controller, so no custom response body is produced for this case.

Business Rules

  • Atomic operation: The service method is annotated @Transactional, so the read-check-write sequence is executed within a single database transaction. If any step fails, the transaction is rolled back automatically.
  • Stock guard: The decrement only executes if inventario.getStockDisponible() >= cantidad. If this condition is not met, the method returns false and the controller responds with HTTP 400. No data is written.
  • Product not found: If inventarioRepository.findByProductoId(productoId) returns an empty Optional, the service throws RuntimeException("Producto no encontrado en inventario"). This exception is not caught in the controller, so Spring Boot handles it as an unhandled exception and returns HTTP 500 Internal Server Error.
  • No fractional quantities: cantidad is an Integer — decimal values are not accepted.

Source Implementation

The controller method in InventarioController.java:
@PostMapping("/{productoId}/descontar")
public ResponseEntity<String> descontarStock(
        @PathVariable String productoId,
        @RequestParam Integer cantidad) {

    boolean exito = inventarioService.descontarStock(productoId, cantidad);
    if (exito) {
        return ResponseEntity.ok("Stock descontado exitosamente");
    } else {
        return ResponseEntity.badRequest().body("Stock insuficiente o producto no encontrado");
    }
}
The transactional service method in InventarioService.java:
@Transactional
public boolean descontarStock(String productoId, Integer cantidad) {
    Inventario inventario = inventarioRepository.findByProductoId(productoId)
            .orElseThrow(() -> new RuntimeException("Producto no encontrado en inventario"));

    if (inventario.getStockDisponible() >= cantidad) {
        inventario.setStockDisponible(inventario.getStockDisponible() - cantidad);
        inventarioRepository.save(inventario);
        return true;
    }
    return false;
}
This endpoint is called internally by servicio-ventapos as part of SAGA-based sale transactions. If you call it directly — for example, from a test script or admin tool — you may decrement stock without the corresponding sale record being created in the POS system. This creates an inventory inconsistency that cannot be automatically corrected. Only call this endpoint directly when you fully understand the downstream implications and have a manual reconciliation plan.

Build docs developers (and LLMs) love