Skip to main content

Overview

The Purchase Service (jea-compra) manages all purchase orders from suppliers, providing robust procurement capabilities with automatic inventory updates and resilient inter-service communication.

Key Features

Supplier Integration

Links purchases to supplier records for complete vendor management

Multi-Service Communication

Uses Feign clients to communicate with 4 different microservices

Circuit Breaker

Resilience4j circuit breakers with fallback methods for fault tolerance

Automatic Calculations

Same tax calculation logic as sales for consistency

Inventory Updates

Automatically increases stock quantities on purchase completion

Document Generation

Auto-generates unique purchase order numbers

Purchase Entity Structure

Purchase orders contain comprehensive information about procurement transactions:
@Entity
public class Compra {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    
    @Column(nullable = false, unique = true)
    private String serie;           // Purchase order series
    
    @Column(nullable = false, unique = true)
    private String numero;          // Purchase order number
    
    private String descripcion;     // Purchase description
    
    @Column(name = "proveedor_id")
    private Long proveedorId;       // Supplier reference
    
    @Transient
    private Proveedor proveedor;    // Supplier details (via Feign)
    
    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "compra_id")
    private List<CompraDetalle> detalle;  // Purchase line items
    
    private LocalDateTime fechaCompra;    // Purchase timestamp
    
    private Double baseImponible;   // Taxable amount
    private Double igv;             // 18% VAT
    private Double total;           // Grand total
    
    @Column(name = "formapago_id")
    private Long formapagoId;       // Payment method reference
}

Feign Client Integration

The Purchase Service demonstrates advanced inter-service communication using Spring Cloud OpenFeign:

Product Service Integration

@FeignClient(name = "jea-catalogo-service", path = "/producto")
public interface ProductoFeign {
    
    @GetMapping("/{id}")
    @CircuitBreaker(name = "orderByIdCB", fallbackMethod = "fallbackProductById")
    public ResponseEntity<Producto> listarProducto(@PathVariable Long id);
    
    @PutMapping("/{id}/cantidad")
    @CircuitBreaker(name = "orderByIdCB", fallbackMethod = "fallbackProductById")
    ResponseEntity<Producto> actualizarCantidad(@PathVariable Long id, 
                                                @RequestBody Integer nuevaCantidad);
    
    default ResponseEntity<Producto> fallbackProductById(Long id, Exception e) {
        Producto productDto = new Producto();
        productDto.setNombre("Servicio no disponible de producto");
        return ResponseEntity.ok(productDto);
    }
}
Circuit breakers prevent cascade failures. If a dependent service is unavailable, the fallback method returns a safe default response, allowing the system to continue operating gracefully.

Connected Services

The Purchase Service communicates with multiple microservices:
1

Catalog Service

Retrieves product information and updates inventory quantities after purchase completion
2

Supplier Service

Fetches supplier details and validates supplier existence
3

Payment Service

Retrieves payment method information for transaction records
4

Category Service

Gets product category information for reporting and organization

Circuit Breaker Pattern

The service implements Resilience4j circuit breakers for fault tolerance:

Benefits

  • Prevents Cascade Failures - Stops failure propagation across services
  • Graceful Degradation - Returns fallback responses when services are unavailable
  • System Stability - Maintains operation even when dependencies fail
  • Fast Failure - Quickly returns errors instead of waiting for timeouts

Configuration

Circuit breakers are configured per Feign client with:
  • Failure rate thresholds
  • Timeout settings
  • Fallback methods
  • Recovery time windows

Purchase Order Process

1

Create Purchase Order

Client submits purchase order with supplier ID, payment method, and line items
2

Validate Supplier

System fetches supplier details from Supplier Service to validate existence
3

Validate Products

Each product in the purchase order is validated against the Catalog Service
4

Calculate Totals

Automatically calculates base amount, IGV (18%), and total for the purchase
5

Generate Document Numbers

Creates unique series and sequential number for purchase order tracking
6

Save Purchase Order

Persists purchase order with all details to the database
7

Update Inventory

Automatically increases product quantities in the Catalog Service

Available Endpoints

The Purchase Service provides comprehensive purchase order management:
MethodEndpointDescription
POST/compraCreate new purchase order
GET/compraList all purchase orders
GET/compra/{id}Get purchase order by ID
PUT/compra/{id}Update purchase order
DELETE/compra/{id}Delete purchase order
GET/compra/proveedor/{id}Get purchases by supplier
GET/compra/fechaSearch by date range

Automatic Inventory Updates

When a purchase order is completed, the system automatically updates inventory:
public void completarCompra(Integer compraId) {
    Compra compra = compraRepository.findById(compraId)
        .orElseThrow(() -> new ResourceNotFoundException("Compra not found"));
    
    // Update inventory for each line item
    for (CompraDetalle detalle : compra.getDetalle()) {
        Integer nuevaCantidad = getCurrentQuantity(detalle.getProductoId()) 
            + detalle.getCantidad();
        productoFeign.actualizarCantidad(detalle.getProductoId(), nuevaCantidad);
    }
}
This ensures inventory levels are always accurate and up-to-date.

Tax Calculations

Purchase orders use the same IGV (18% VAT) calculation logic as sales:
@PrePersist
public void prePersist() {
    calcularTotales();
    generarSerieYNumero();
}

private void calcularTotales() {
    this.baseImponible = 0.0;
    this.igv = 0.0;
    this.total = 0.0;
    
    if (detalle != null) {
        for (CompraDetalle d : detalle) {
            d.calcularMontos();
            this.baseImponible += d.getBaseImponible();
            this.igv += d.getIgv();
            this.total += d.getTotal();
        }
    }
}
IGV calculations are automatic. Do not manually set tax amounts as they will be overwritten by the pre-persist lifecycle hook.

Supplier Management Integration

Purchase orders are tightly integrated with supplier records:
  • Supplier Validation - Verifies supplier exists before creating purchase order
  • Supplier History - Track all purchases from each supplier
  • Payment Terms - Associate purchase orders with supplier payment terms
  • Performance Tracking - Monitor supplier performance metrics

Payment Processing

Purchase orders support various payment methods:
  • Cash (Efectivo)
  • Credit Card (Tarjeta de crédito)
  • Bank Transfer (Transferencia bancaria)
  • Check (Cheque)
  • Mobile Payments (Yape, Plin, BIM)
Payment method selection affects accounting and reconciliation processes.

Best Practices

Always validate supplier existence and status before creating purchase orders. Inactive suppliers should not be used for new orders.
Verify that all products in the purchase order exist in the catalog and are active before submission.
Double-check quantities before submitting purchase orders. Once completed, inventory updates are automatic and should match received goods.
Keep purchase costs updated in the product catalog to ensure accurate profit margin calculations.
Monitor circuit breaker status to identify dependent service issues early. Implement alerts for circuit breaker trips.

Error Handling

The Purchase Service implements comprehensive error handling:
  • Service Unavailability - Circuit breakers provide fallback responses
  • Invalid Suppliers - Validation errors are returned with clear messages
  • Insufficient Product Data - Missing product information triggers appropriate errors
  • Transaction Failures - Rollback mechanisms ensure data consistency

Next Steps

API Reference

Detailed purchase API documentation

Supplier Management

Manage supplier relationships

Inventory Control

Monitor inventory levels

Payment Processing

Configure payment methods

Build docs developers (and LLMs) love