diff --git a/backend/src/main/java/de/effigenix/infrastructure/inventory/persistence/repository/JdbcStockRepository.java b/backend/src/main/java/de/effigenix/infrastructure/inventory/persistence/repository/JdbcStockRepository.java index 13f8cf0..930965f 100644 --- a/backend/src/main/java/de/effigenix/infrastructure/inventory/persistence/repository/JdbcStockRepository.java +++ b/backend/src/main/java/de/effigenix/infrastructure/inventory/persistence/repository/JdbcStockRepository.java @@ -223,21 +223,34 @@ public class JdbcStockRepository implements StockRepository { String stockId = stock.id().value(); // Delete reservations first (cascades to allocations via FK ON DELETE CASCADE) - // Must happen before deleting batches due to FK from allocations -> stock_batches jdbc.sql("DELETE FROM reservations WHERE stock_id = :stockId") .param("stockId", stockId) .update(); - // Delete + re-insert batches - jdbc.sql("DELETE FROM stock_batches WHERE stock_id = :stockId") - .param("stockId", stockId) - .update(); + // Upsert batches: stock_movements has FK to stock_batches (RESTRICT), + // so we cannot delete-all + re-insert. Instead: remove stale, upsert current. + var currentBatchIds = stock.batches().stream() + .map(b -> b.id().value()) + .toList(); + + if (currentBatchIds.isEmpty()) { + jdbc.sql("DELETE FROM stock_batches WHERE stock_id = :stockId") + .param("stockId", stockId) + .update(); + } else { + jdbc.sql("DELETE FROM stock_batches WHERE stock_id = :stockId AND id NOT IN (:batchIds)") + .param("stockId", stockId) + .param("batchIds", currentBatchIds) + .update(); + } for (StockBatch batch : stock.batches()) { - jdbc.sql(""" - INSERT INTO stock_batches - (id, stock_id, batch_id, batch_type, quantity_amount, quantity_unit, expiry_date, status, received_at) - VALUES (:id, :stockId, :batchId, :batchType, :quantityAmount, :quantityUnit, :expiryDate, :status, :receivedAt) + int updated = jdbc.sql(""" + UPDATE stock_batches + SET batch_id = :batchId, batch_type = :batchType, + quantity_amount = :quantityAmount, quantity_unit = :quantityUnit, + expiry_date = :expiryDate, status = :status, received_at = :receivedAt + WHERE id = :id AND stock_id = :stockId """) .param("id", batch.id().value()) .param("stockId", stockId) @@ -249,6 +262,24 @@ public class JdbcStockRepository implements StockRepository { .param("status", batch.status().name()) .param("receivedAt", batch.receivedAt().atOffset(ZoneOffset.UTC)) .update(); + + if (updated == 0) { + jdbc.sql(""" + INSERT INTO stock_batches + (id, stock_id, batch_id, batch_type, quantity_amount, quantity_unit, expiry_date, status, received_at) + VALUES (:id, :stockId, :batchId, :batchType, :quantityAmount, :quantityUnit, :expiryDate, :status, :receivedAt) + """) + .param("id", batch.id().value()) + .param("stockId", stockId) + .param("batchId", batch.batchReference().batchId()) + .param("batchType", batch.batchReference().batchType().name()) + .param("quantityAmount", batch.quantity().amount()) + .param("quantityUnit", batch.quantity().uom().name()) + .param("expiryDate", batch.expiryDate()) + .param("status", batch.status().name()) + .param("receivedAt", batch.receivedAt().atOffset(ZoneOffset.UTC)) + .update(); + } } for (Reservation reservation : stock.reservations()) {