Skip to content

Commit 7fa4c40

Browse files
committed
feat: implement InventoryStockService to handle stock imports, deductions, refunds, and manual adjustments with unit conversion logic
1 parent 338b45c commit 7fa4c40

File tree

1 file changed

+33
-20
lines changed

1 file changed

+33
-20
lines changed

backend/src/main/java/com/smalltrend/service/inventory/shared/InventoryStockService.java

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,17 @@ public void importStock(StockImportRequest request) {
107107
@Transactional
108108
// Trừ stock.
109109
public void deductStock(ProductVariant variant, int quantity, Long orderId, String notes) {
110+
if (!variant.isBaseUnit()) {
111+
var directVariantStocks = inventoryStockRepository.findByVariantId(variant.getId());
112+
boolean hasDirectVariantStock = directVariantStocks.stream()
113+
.anyMatch(stock -> stock.getQuantity() != null && stock.getQuantity() > 0);
114+
115+
if (hasDirectVariantStock) {
116+
deductFromStocks(variant, quantity, directVariantStocks, orderId, notes);
117+
return;
118+
}
119+
}
120+
110121
ProductVariant baseVariant = variant;
111122
int deductQuantity = quantity;
112123

@@ -123,35 +134,37 @@ public void deductStock(ProductVariant variant, int quantity, Long orderId, Stri
123134
deductQuantity = quantity * factor;
124135
}
125136

126-
// Ưu tiên trừ theo lô cũ (FIFO đơn giản)
127-
int remainingToDeduct = deductQuantity;
128-
var stocks = inventoryStockRepository.findByVariantId(baseVariant.getId());
137+
var baseStocks = inventoryStockRepository.findByVariantId(baseVariant.getId());
138+
deductFromStocks(baseVariant, deductQuantity, baseStocks, orderId, notes);
139+
}
140+
141+
private void deductFromStocks(ProductVariant stockVariant, int quantityToDeduct, java.util.List<InventoryStock> stocks,
142+
Long orderId, String notes) {
143+
int remainingToDeduct = quantityToDeduct;
129144

130145
for (InventoryStock stock : stocks) {
131-
if (remainingToDeduct <= 0)
146+
if (remainingToDeduct <= 0) {
132147
break;
148+
}
133149

134-
if (stock.getQuantity() > 0) {
135-
int oldQty = stock.getQuantity();
136-
int qtyToTake = Math.min(oldQty, remainingToDeduct);
137-
stock.setQuantity(oldQty - qtyToTake);
138-
InventoryStock savedStock = inventoryStockRepository.save(stock);
139-
outOfStockNotificationService.handleStockTransition(savedStock, oldQty, savedStock.getQuantity(), "SALE_ORDER");
150+
int currentQty = stock.getQuantity() != null ? stock.getQuantity() : 0;
151+
if (currentQty <= 0) {
152+
continue;
153+
}
140154

141-
// Ghi nhận biến động cho lô này
142-
recordMovement(baseVariant, stock.getBatch(), stock.getLocation(),
143-
StockTransactionType.SALE, -qtyToTake, "SALE_ORDER", orderId, notes);
155+
int qtyToTake = Math.min(currentQty, remainingToDeduct);
156+
stock.setQuantity(currentQty - qtyToTake);
157+
InventoryStock savedStock = inventoryStockRepository.save(stock);
158+
outOfStockNotificationService.handleStockTransition(savedStock, currentQty, savedStock.getQuantity(), "SALE_ORDER");
144159

145-
remainingToDeduct -= qtyToTake;
146-
}
160+
recordMovement(stockVariant, stock.getBatch(), stock.getLocation(),
161+
StockTransactionType.SALE, -qtyToTake, "SALE_ORDER", orderId, notes);
162+
163+
remainingToDeduct -= qtyToTake;
147164
}
148165

149166
if (remainingToDeduct > 0) {
150-
// Vẫn chưa trừ hết (Tồn kho bị âm - Tùy cấu hình hệ thống POS có thể bắn lỗi)
151-
// Trong bối cảnh bán lẻ, thường ta ghi log cảnh báo và cho phép bán âm, hoặc
152-
// trừ âm vào một location mặc định.
153-
// Để an toàn, chúng ta throw exception ở đây trừ khi requirements cho phép âm.
154-
throw new RuntimeException("Not enough stock available for variant: " + baseVariant.getSku());
167+
throw new RuntimeException("Not enough stock available for variant: " + stockVariant.getSku());
155168
}
156169
}
157170

0 commit comments

Comments
 (0)