From 79ce234f181a8fa5e3e02938520395243c82a5da Mon Sep 17 00:00:00 2001
From: chen.lin <1442464845@qq.com>
Date: 星期五, 06 三月 2026 08:15:39 +0800
Subject: [PATCH] 拣货过程中的出库库存匹配+空板

---
 rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java |  281 +++++++++++++++++++++++++++++++++++---------------------
 1 files changed, 175 insertions(+), 106 deletions(-)

diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java
index b3f87b7..cc79c6d 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java
@@ -54,6 +54,16 @@
 
     /** 鍑哄簱鍓╀綑閲忓宸細灏忎簬绛変簬姝ゅ�艰涓哄凡鍒嗛厤瀹岋紝閬垮厤娴偣璇樊浜х敓澶氫綑鈥滃簱瀛樹笉瓒斥�濊 */
     private static final BigDecimal ISSUED_TOLERANCE = new BigDecimal("0.000001");
+    /** 鏁伴噺绮惧害锛堝皬鏁颁綅鏁帮級锛岀粺涓�鐢� BigDecimal 璁$畻鍚庢寜姝ょ簿搴﹁垗鍏ュ啀鍐欏洖 Double 瀛楁 */
+    private static final int QTY_SCALE = 6;
+
+    /** 灏� Map/瀹炰綋涓殑鏁伴噺杞负 BigDecimal锛岄伩鍏� double 绮惧害闂 */
+    private static BigDecimal toBigDecimal(Object o) {
+        if (o == null) return BigDecimal.ZERO;
+        if (o instanceof BigDecimal) return (BigDecimal) o;
+        if (o instanceof Number) return new BigDecimal(o.toString());
+        try { return new BigDecimal(o.toString()); } catch (NumberFormatException e) { return BigDecimal.ZERO; }
+    }
 
     @Autowired
     private AsnOrderItemService asnOrderItemService;
@@ -88,6 +98,8 @@
     @Autowired
     private TaskItemService taskItemService;
     @Autowired
+    private TaskService taskService;
+    @Autowired
     private LocItemMapper locItemMapper;
 
     @Override
@@ -115,12 +127,12 @@
                 continue;
             }
             for (Map<String, Object> row : statusRows) {
-                double v = row.get("stockQty") instanceof Number ? ((Number) row.get("stockQty")).doubleValue() : 0d;
+                BigDecimal stockQtyVal = toBigDecimal(row.get("stockQty"));
                 String useStatus = getStr(row, "useStatus", "usestatus");
                 String statusDesc = useStatus != null ? LocStsType.getDescByType(useStatus) : null;
                 String locCodesWithQty = getStr(row, "locCodes$", "loccodes$");
                 Matnr copy = cloneMatnrForRow(record);
-                copy.setStockQty(v);
+                copy.setStockQty(stockQtyVal.setScale(QTY_SCALE, RoundingMode.HALF_UP).doubleValue());
                 copy.setLocUseStatus$(statusDesc);
                 copy.setLocCodes$(locCodesWithQty);
                 expanded.add(copy);
@@ -158,12 +170,12 @@
             try { matnrId = Long.parseLong(parts[0]); } catch (NumberFormatException ex) { continue; }
             String useStatus = parts[1];
             List<Map<String, Object>> locs = e.getValue();
-            double stockQty = 0d;
+            BigDecimal stockQty = BigDecimal.ZERO;
             StringBuilder sb = new StringBuilder();
             for (Map<String, Object> locRow : locs) {
                 Object q = getAny(locRow, "locQty", "locqty");
-                double qty = q instanceof Number ? ((Number) q).doubleValue() : 0d;
-                stockQty += qty;
+                BigDecimal qty = toBigDecimal(q);
+                stockQty = stockQty.add(qty);
                 String code = getStr(locRow, "locCode", "loccode");
                 if (sb.length() > 0) sb.append(",");
                 sb.append(code != null ? code : "").append("(").append(formatQtyForLoc(qty)).append(")");
@@ -178,10 +190,11 @@
         return rowsByMatnr;
     }
 
-    private static String formatQtyForLoc(double qty) {
-        if (qty == (long) qty) return String.valueOf((long) qty);
-        String s = BigDecimal.valueOf(qty).setScale(6, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString();
-        return s;
+    private static String formatQtyForLoc(BigDecimal qty) {
+        if (qty == null) return "0";
+        BigDecimal scaled = qty.setScale(QTY_SCALE, RoundingMode.HALF_UP).stripTrailingZeros();
+        if (scaled.scale() <= 0) return scaled.toPlainString();
+        return scaled.toPlainString();
     }
 
     private static Long getLong(Map<String, Object> map, String... keys) {
@@ -227,8 +240,10 @@
         });
         List<WkOrderItem> orderItems = asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>()
                 .eq(WkOrderItem::getOrderId, params.getOrders().getId()));
-        Double sum = orderItems.stream().mapToDouble(WkOrderItem::getAnfme).sum();
-        orders.setAnfme(sum);
+        BigDecimal sum = orderItems.stream()
+                .map(o -> toBigDecimal(o.getAnfme()))
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+        orders.setAnfme(sum.setScale(QTY_SCALE, RoundingMode.HALF_UP).doubleValue());
         if (!this.updateById(orders)) {
             throw new CoolException("璁″垝鏀惰揣鏁伴噺淇敼澶辫触锛侊紒");
         }
@@ -259,18 +274,18 @@
         List<WkOrderItem> orderItems = outStockItemService.list(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, id));
         if (!orderItems.isEmpty()) {
             for (WkOrderItem orderItem : orderItems) {
-                if (!Objects.isNull(orderItem.getPoDetlId())) {
+                    if (!Objects.isNull(orderItem.getPoDetlId())) {
                     DeliveryItem deliveryItem = deliveryItemService.getById(orderItem.getPoDetlId());
-                    Double workQty = Math.round((deliveryItem.getWorkQty() - orderItem.getAnfme()) * 1000000) / 1000000.0;
-                    deliveryItem.setWorkQty(workQty.compareTo(0.0) >= 0 ? workQty : 0);
+                    BigDecimal workQty = toBigDecimal(deliveryItem.getWorkQty()).subtract(toBigDecimal(orderItem.getAnfme())).setScale(QTY_SCALE, RoundingMode.HALF_UP);
+                    deliveryItem.setWorkQty(workQty.compareTo(BigDecimal.ZERO) >= 0 ? workQty.doubleValue() : 0);
                     if (!deliveryItemService.updateById(deliveryItem)) {
                         throw new CoolException("DO鍗曟槑缁嗘洿鏂板け璐ワ紒锛�");
                     }
 
                     Delivery delivery = deliveryService.getOne(new LambdaQueryWrapper<Delivery>().eq(Delivery::getCode, orderItem.getPoCode()));
                     if (!Objects.isNull(delivery)) {
-                        Double wkQty = Math.round((delivery.getWorkQty() - delivery.getAnfme()) * 1000000) / 1000000.0;
-                        delivery.setWorkQty(wkQty.compareTo(0.0) >= 0 ? wkQty : 0).setExceStatus(POExceStatus.PO_EXCE_STATUS_UN_EXCE.val);
+                        BigDecimal wkQty = toBigDecimal(delivery.getWorkQty()).subtract(toBigDecimal(delivery.getAnfme())).setScale(QTY_SCALE, RoundingMode.HALF_UP);
+                        delivery.setWorkQty(wkQty.compareTo(BigDecimal.ZERO) >= 0 ? wkQty.doubleValue() : 0).setExceStatus(POExceStatus.PO_EXCE_STATUS_UN_EXCE.val);
                         if (!deliveryService.updateById(delivery)) {
                             throw new CoolException("DO鍗曟嵁淇敼澶辫触锛侊紒");
                         }
@@ -333,8 +348,8 @@
                 if (item.getAnfme().compareTo(0.0) <= 0) {
                     throw new CoolException("鍑哄簱鏁伴噺涓嶈兘灏忎簬鎴栫瓑浜庨浂锛侊紒");
                 }
-                Double anfme = Math.round((deliveryItem.getAnfme() - item.getAnfme()) * 1000000) / 1000000.0;
-                if (anfme.compareTo(0.0) < 0) {
+                BigDecimal anfme = toBigDecimal(deliveryItem.getAnfme()).subtract(toBigDecimal(item.getAnfme())).setScale(QTY_SCALE, RoundingMode.HALF_UP);
+                if (anfme.compareTo(BigDecimal.ZERO) < 0) {
                     throw new CoolException("鍑哄簱鏁伴噺涓嶈冻锛侊紒");
                 }
 
@@ -366,9 +381,9 @@
                 }
             });
 
-            Double sum = orderItems.stream().mapToDouble(WkOrderItem::getAnfme).sum();
+            BigDecimal sum = orderItems.stream().map(o -> toBigDecimal(o.getAnfme())).reduce(BigDecimal.ZERO, BigDecimal::add);
             //淇敼璁″垝鏁伴噺
-            order.setAnfme(sum).setWorkQty(0.0);
+            order.setAnfme(sum.setScale(QTY_SCALE, RoundingMode.HALF_UP).doubleValue()).setWorkQty(0.0);
             if (!this.saveOrUpdate(order)) {
                 throw new CoolException("涓诲崟鏁伴噺淇敼澶辫触锛侊紒");
             }
@@ -381,10 +396,10 @@
                 exceStatus = AsnExceStatus.ASN_EXCE_STATUS_TASK_DONE.val;
             }
 
-            Double wkQty = Math.round((delivery.getWorkQty() + sum) * 1000000) / 1000000.0;
+            BigDecimal wkQty = toBigDecimal(delivery.getWorkQty()).add(sum).setScale(QTY_SCALE, RoundingMode.HALF_UP);
             if (!deliveryService.update(new LambdaUpdateWrapper<Delivery>()
                     .set(Delivery::getExceStatus, exceStatus)
-                    .set(Delivery::getWorkQty, wkQty)
+                    .set(Delivery::getWorkQty, wkQty.doubleValue())
                     .eq(Delivery::getId, key))) {
                 throw new CoolException("涓诲崟淇敼澶辫触锛侊紒");
             }
@@ -411,9 +426,9 @@
         if (orders.isEmpty()) {
             throw new CoolException("褰撳墠鍗曟嵁鐘舵�佷笉鑳芥墽琛屾尝娆$敓鎴愭搷浣滐紒锛�");
         }
-        Double sum = orders.stream().mapToDouble(WkOrder::getAnfme).sum();
-        Double workQty = orders.stream().mapToDouble(WkOrder::getWorkQty).sum();
-        Double anfme = Math.round((sum - workQty) * 1000000) / 1000000.0;
+        BigDecimal sum = orders.stream().map(o -> toBigDecimal(o.getAnfme())).reduce(BigDecimal.ZERO, BigDecimal::add);
+        BigDecimal workQty = orders.stream().map(o -> toBigDecimal(o.getWorkQty())).reduce(BigDecimal.ZERO, BigDecimal::add);
+        BigDecimal anfme = sum.subtract(workQty).setScale(QTY_SCALE, RoundingMode.HALF_UP);
         Wave wave = new Wave();
         String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_WAVE_TYPE, null);
         if (StringUtils.isBlank(ruleCode)) {
@@ -423,7 +438,7 @@
                 .setType(Short.parseShort("1"))
                 .setCode(ruleCode)
                 .setExceStatus(WaveExceStatus.WAVE_EXCE_STATUS_INIT.val)
-                .setAnfme(anfme);
+                .setAnfme(anfme.doubleValue());
         if (!waveService.save(wave)) {
             throw new CoolException("娉㈡淇濆瓨澶辫触锛侊紒");
         }
@@ -442,8 +457,8 @@
         if (!waveItemService.saveBatch(waveItems)) {
             throw new CoolException("娉㈡鏄庣粏淇濆瓨澶辫触锛侊紒");
         }
-        double sum1 = waveItems.stream().mapToDouble(WaveItem::getAnfme).sum();
-        wave.setAnfme(sum1).setGroupQty(waveItems.size());
+        BigDecimal sum1 = waveItems.stream().map(o -> toBigDecimal(o.getAnfme())).reduce(BigDecimal.ZERO, BigDecimal::add);
+        wave.setAnfme(sum1.setScale(QTY_SCALE, RoundingMode.HALF_UP).doubleValue()).setGroupQty(waveItems.size());
         if (!waveService.saveOrUpdate(wave)) {
             throw new CoolException("涓诲崟淇敼澶辫触锛侊紒");
         }
@@ -478,10 +493,10 @@
             throw new CoolException("鍑哄簱鍗曟墽琛屾暟閲忎慨鏀瑰け璐ワ紒锛�");
         }
         for (WkOrder order : orders) {
-            Double wkQty = Math.round((order.getWorkQty() + order.getAnfme()) * 1000000) / 1000000.0;
+            BigDecimal wkQty = toBigDecimal(order.getWorkQty()).add(toBigDecimal(order.getAnfme())).setScale(QTY_SCALE, RoundingMode.HALF_UP);
             if (!this.update(new LambdaUpdateWrapper<WkOrder>()
                     .set(WkOrder::getWaveId, wave.getId())
-                    .set(WkOrder::getWorkQty, wkQty)
+                    .set(WkOrder::getWorkQty, wkQty.doubleValue())
                     .set(WkOrder::getExceStatus, AsnExceStatus.OUT_STOCK_STATUS_TASK_WAVE.val)
                     .eq(WkOrder::getId, order.getId()))) {
                 throw new CoolException("鎵ц鐘舵�佷慨鏀逛慨鏀瑰け璐ワ紒锛�");
@@ -593,8 +608,8 @@
         // 閲嶆柊姹囨�讳富鍗曟暟閲忥紙鍒犻櫎鏄庣粏鍚庯級
         List<WkOrderItem> afterItems = asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>()
                 .eq(WkOrderItem::getOrderId, orders.getId()));
-        Double sum = afterItems.stream().mapToDouble(WkOrderItem::getAnfme).sum();
-        orders.setAnfme(sum);
+        BigDecimal sum = afterItems.stream().map(o -> toBigDecimal(o.getAnfme())).reduce(BigDecimal.ZERO, BigDecimal::add);
+        orders.setAnfme(sum.setScale(QTY_SCALE, RoundingMode.HALF_UP).doubleValue());
         this.updateById(orders);
         return R.ok();
     }
@@ -628,9 +643,9 @@
             if (locItem == null) {
                 continue;
             }
-            Double anfme = taskItem.getAnfme() != null ? taskItem.getAnfme() : 0.0;
-            Double newWorkQty = Math.round((locItem.getWorkQty() - anfme) * 1000000) / 1000000.0;
-            locItem.setWorkQty(newWorkQty >= 0 ? newWorkQty : 0)
+            BigDecimal anfme = toBigDecimal(taskItem.getAnfme());
+            BigDecimal newWorkQty = toBigDecimal(locItem.getWorkQty()).subtract(anfme).setScale(QTY_SCALE, RoundingMode.HALF_UP);
+            locItem.setWorkQty(newWorkQty.compareTo(BigDecimal.ZERO) >= 0 ? newWorkQty.doubleValue() : 0)
                     .setOrderId(null)
                     .setOrderItemId(null)
                     .setUpdateBy(loginUserId)
@@ -733,61 +748,74 @@
                 if (StringUtils.isNotBlank(locItem.getFieldsIndex())) {
                     orderItemWrapper.eq(WkOrderItem::getFieldsIndex, locItem.getFieldsIndex());
                 }
-                // 鍚屼竴鍑哄簱鍗曚笅鍚屼竴鐗╂枡鍙兘鏈夊鏉℃槑缁嗭紙濡傚琛屽悎骞讹級锛岀敤 list 鍙栦粛鏈夊墿浣欐暟閲忕殑绗竴鏉★紝閬垮厤 getOne 杩斿洖澶氭潯鎶� TooManyResultsException
+                // 鍚屼竴鍑哄簱鍗曚笅鍚屼竴鐗╂枡鍙兘鏈夊鏉℃槑缁嗭紙濡傚琛屽悎骞讹級锛岀敤 list 鍙栦粛鏈夊墿浣欐暟閲忕殑绗竴鏉�
                 List<WkOrderItem> orderItemCandidates = outStockItemService.list(orderItemWrapper);
                 WkOrderItem orderItem = orderItemCandidates.stream()
                         .filter(o -> o.getAnfme() != null && o.getWorkQty() != null && o.getAnfme().compareTo(o.getWorkQty()) > 0)
                         .findFirst()
                         .orElse(null);
 
-                // 濡傛灉鎵句笉鍒板崟鎹槑缁嗭紝涓擫ocItem鏉ヨ嚜搴撳瓨璋冩暣锛屽垯鑷姩鍒涘缓WkOrderItem
+                // 涓ユ牸鍖归厤鏈壘鍒版椂锛氬啀鎸夈�屽悓鍗曞彿+鍚岀墿鏂欍�嶅鏉惧尮閰嶏紝閬垮厤鍘熸槑缁� fields_index 涓虹┖鑰屽垎閰嶅甫绁ㄥ彿瀵艰嚧閲嶅鍒涘缓涓�鏉�
                 if (Objects.isNull(orderItem)) {
-                    // 妫�鏌ユ槸鍚︽槸搴撳瓨璋冩暣浜х敓鐨勫簱瀛�
-                    if (locItem.getWkType() != null && 
-                        locItem.getWkType().equals(Short.parseShort(OrderWorkType.ORDER_WORK_TYPE_STOCK_REVISE.type))) {
-                        // 鑾峰彇鍑哄簱鍗曚俊鎭�
-                        WkOrder outOrder = outStockService.getById(outId);
-                        if (Objects.isNull(outOrder)) {
-                            throw new CoolException("鍑哄簱鍗曟嵁涓嶅瓨鍦紒锛�");
-                        }
-                        
-                        log.info("搴撳瓨璋冩暣浜х敓鐨勫簱瀛橈紝鑷姩鍒涘缓WkOrderItem - 鍑哄簱鍗旾D锛歿}锛岀墿鏂橧D锛歿}锛屾壒娆★細{}", 
-                                outId, locItem.getMatnrId(), locItem.getBatch());
-                        
-                        // 鍒涘缓WkOrderItem
-                        orderItem = new WkOrderItem();
-                        orderItem.setOrderId(outId)
-                                .setOrderCode(outOrder.getCode())
-                                .setMatnrId(locItem.getMatnrId())
-                                .setMatnrCode(locItem.getMatnrCode())
-                                .setMaktx(locItem.getMaktx())
-                                .setBatch(StringUtils.isNotBlank(param.getBatch()) ? param.getBatch() : locItem.getBatch())
-                                .setSplrBatch(StringUtils.isNotBlank(locItem.getSplrBatch()) ? locItem.getSplrBatch() : 
-                                             (StringUtils.isNotBlank(locItem.getBatch()) ? locItem.getBatch() : null))
-                                .setFieldsIndex(locItem.getFieldsIndex())
-                                .setAnfme(param.getOutQty())
-                                .setWorkQty(0.0)
-                                .setStockUnit(locItem.getUnit())
-                                .setPurUnit(locItem.getUnit())
-                                .setSpec(locItem.getSpec())
-                                .setModel(locItem.getModel())
-                                .setCreateBy(loginUserId)
-                                .setUpdateBy(loginUserId)
-                                .setCreateTime(new Date())
-                                .setUpdateTime(new Date());
-                        
-                        if (!outStockItemService.save(orderItem)) {
-                            throw new CoolException("搴撳瓨璋冩暣鍗曟嵁鏄庣粏鍒涘缓澶辫触锛侊紒");
-                        }
-                        
-                        log.info("WkOrderItem鍒涘缓鎴愬姛 - ID锛歿}锛屽嚭搴撳崟ID锛歿}锛岀墿鏂橧D锛歿}", 
-                                orderItem.getId(), outId, locItem.getMatnrId());
-                    } else {
-                        throw new CoolException("鍗曟嵁鏄庣粏涓嶅瓨鍦紒锛佸嚭搴撳崟ID锛�" + outId + "锛岀墿鏂橧D锛�" + locItem.getMatnrId() + 
-                                (StringUtils.isNotBlank(locItem.getSplrBatch()) ? "锛屼緵搴斿晢鎵规锛�" + locItem.getSplrBatch() : 
-                                 StringUtils.isNotBlank(locItem.getBatch()) ? "锛屽簱瀛樻壒娆★細" + locItem.getBatch() : "") +
-                                (StringUtils.isNotBlank(locItem.getFieldsIndex()) ? "锛屽瓧娈电储寮曪細" + locItem.getFieldsIndex() : ""));
+                    LambdaQueryWrapper<WkOrderItem> relaxedWrapper = new LambdaQueryWrapper<WkOrderItem>()
+                            .eq(WkOrderItem::getOrderId, outId)
+                            .eq(WkOrderItem::getMatnrId, locItem.getMatnrId());
+                    if (StringUtils.isNotBlank(locItem.getSplrBatch())) {
+                        relaxedWrapper.eq(WkOrderItem::getSplrBatch, locItem.getSplrBatch());
+                    } else if (StringUtils.isNotBlank(locItem.getBatch())) {
+                        relaxedWrapper.and(w -> w.eq(WkOrderItem::getBatch, locItem.getBatch()).or().eq(WkOrderItem::getSplrBatch, locItem.getBatch()));
                     }
+                    orderItem = outStockItemService.list(relaxedWrapper).stream()
+                            .filter(o -> o.getAnfme() != null && o.getWorkQty() != null && o.getAnfme().compareTo(o.getWorkQty()) > 0)
+                            .findFirst()
+                            .orElse(null);
+                    if (orderItem != null && StringUtils.isNotBlank(locItem.getFieldsIndex()) && !locItem.getFieldsIndex().equals(orderItem.getFieldsIndex())) {
+                        orderItem.setFieldsIndex(locItem.getFieldsIndex());
+                        outStockItemService.updateById(orderItem);
+                    }
+                }
+
+                // 鎵句笉鍒板崟鎹槑缁嗘椂锛氬嚭搴撳崟瀛樺湪鍒欒嚜鍔ㄥ垱寤篧kOrderItem锛堝簱瀛樿皟鏁存垨鍒嗛厤鏃跺嚭搴撳崟鏆傛棤璇ョ墿鏂欒锛�
+                if (Objects.isNull(orderItem)) {
+                    WkOrder outOrder = outStockService.getById(outId);
+                    if (Objects.isNull(outOrder)) {
+                        throw new CoolException("鍑哄簱鍗曟嵁涓嶅瓨鍦紒锛�");
+                    }
+                    boolean isStockRevise = locItem.getWkType() != null
+                            && locItem.getWkType().equals(Short.parseShort(OrderWorkType.ORDER_WORK_TYPE_STOCK_REVISE.type));
+                    if (isStockRevise) {
+                        log.info("搴撳瓨璋冩暣浜х敓鐨勫簱瀛橈紝鑷姩鍒涘缓WkOrderItem - 鍑哄簱鍗旾D锛歿}锛岀墿鏂橧D锛歿}锛屾壒娆★細{}",
+                                outId, locItem.getMatnrId(), locItem.getBatch());
+                    } else {
+                        log.info("鍑哄簱鍗曚笅鏃犲尮閰嶆槑缁嗭紝鑷姩鍒涘缓WkOrderItem - 鍑哄簱鍗旾D锛歿}锛岀墿鏂橧D锛歿}锛屾壒娆★細{}",
+                                outId, locItem.getMatnrId(), locItem.getBatch());
+                    }
+                    orderItem = new WkOrderItem();
+                    orderItem.setOrderId(outId)
+                            .setOrderCode(outOrder.getCode())
+                            .setMatnrId(locItem.getMatnrId())
+                            .setMatnrCode(locItem.getMatnrCode())
+                            .setMaktx(locItem.getMaktx())
+                            .setBatch(StringUtils.isNotBlank(param.getBatch()) ? param.getBatch() : locItem.getBatch())
+                            .setSplrBatch(StringUtils.isNotBlank(locItem.getSplrBatch()) ? locItem.getSplrBatch() :
+                                    (StringUtils.isNotBlank(locItem.getBatch()) ? locItem.getBatch() : null))
+                            .setFieldsIndex(locItem.getFieldsIndex())
+                            .setAnfme(param.getOutQty())
+                            .setWorkQty(0.0)
+                            .setStockUnit(locItem.getUnit())
+                            .setPurUnit(locItem.getUnit())
+                            .setSpec(locItem.getSpec())
+                            .setModel(locItem.getModel())
+                            .setCreateBy(loginUserId)
+                            .setUpdateBy(loginUserId)
+                            .setCreateTime(new Date())
+                            .setUpdateTime(new Date());
+
+                    if (!outStockItemService.save(orderItem)) {
+                        throw new CoolException("鍑哄簱鍗曟槑缁嗗垱寤哄け璐ワ紒锛�");
+                    }
+                    log.info("WkOrderItem鍒涘缓鎴愬姛 - ID锛歿}锛屽嚭搴撳崟ID锛歿}锛岀墿鏂橧D锛歿}",
+                            orderItem.getId(), outId, locItem.getMatnrId());
                 }
 
                 locItem.setOutQty(param.getOutQty())
@@ -815,9 +843,9 @@
                     throw new CoolException(e.getMessage());
                 }
 
-                Double workQty = Math.round((orderItem.getWorkQty() + locItem.getOutQty()) * 1000000) / 1000000.0;
+                BigDecimal workQty = toBigDecimal(orderItem.getWorkQty()).add(toBigDecimal(locItem.getOutQty())).setScale(QTY_SCALE, RoundingMode.HALF_UP);
 
-                orderItem.setUpdateBy(loginUserId).setUpdateTime(new Date()).setWorkQty(workQty);
+                orderItem.setUpdateBy(loginUserId).setUpdateTime(new Date()).setWorkQty(workQty.doubleValue());
 
                 if (!outStockItemService.updateById(orderItem)) {
                     throw new CoolException("鍗曟嵁鏄庣粏淇敼澶辫触锛侊紒");
@@ -825,15 +853,15 @@
             }
         }
 
-        Double sum = Items.stream().mapToDouble(OutStockToTaskParams::getOutQty).sum();
+        BigDecimal sum = Items.stream().map(OutStockToTaskParams::getOutQty).map(OutStockServiceImpl::toBigDecimal).reduce(BigDecimal.ZERO, BigDecimal::add);
         //鏇存柊鍑哄簱鍗曟槑缁嗗強涓诲崟
         WkOrder outOrder = outStockService.getById(outId);
         if (Objects.isNull(outOrder)) {
             throw new CoolException("鍑哄簱鍗曟嵁涓嶅瓨鍦紒锛�");
         }
-        Double workQty = Math.round((outOrder.getWorkQty() + sum) * 1000000) / 1000000.0;
+        BigDecimal workQty = toBigDecimal(outOrder.getWorkQty()).add(sum).setScale(QTY_SCALE, RoundingMode.HALF_UP);
 
-        outOrder.setWorkQty(workQty).setExceStatus(AsnExceStatus.OUT_STOCK_STATUS_TASK_CREATE.val);
+        outOrder.setWorkQty(workQty.doubleValue()).setExceStatus(AsnExceStatus.OUT_STOCK_STATUS_TASK_CREATE.val);
 
         if (!outStockService.updateById(outOrder)) {
             throw new CoolException("鍑哄簱鍗曠姸鎬佷慨鏀瑰け璐ワ紒锛�");
@@ -875,16 +903,16 @@
             if (!items.isEmpty()) {
                 for (WkOrderItem orderItem : items) {
                     DeliveryItem deliveryItem = deliveryItemService.getById(orderItem.getPoDetlId());
-                    Double workQty = Math.round((deliveryItem.getWorkQty() - orderItem.getAnfme()) * 1000000) / 1000000.0;
-                    deliveryItem.setWorkQty(workQty.compareTo(0.0) >= 0 ? workQty : 0);
+                    BigDecimal workQty = toBigDecimal(deliveryItem.getWorkQty()).subtract(toBigDecimal(orderItem.getAnfme())).setScale(QTY_SCALE, RoundingMode.HALF_UP);
+                    deliveryItem.setWorkQty(workQty.compareTo(BigDecimal.ZERO) >= 0 ? workQty.doubleValue() : 0);
                     if (!deliveryItemService.updateById(deliveryItem)) {
                         throw new CoolException("DO鍗曟槑缁嗘洿鏂板け璐ワ紒锛�");
                     }
 
                     Delivery delivery = deliveryService.getOne(new LambdaQueryWrapper<Delivery>().eq(Delivery::getCode, orderItem.getPoCode()));
                     if (!Objects.isNull(delivery)) {
-                        Double wkQty = Math.round((delivery.getWorkQty() - delivery.getAnfme()) * 1000000) / 1000000.0;
-                        delivery.setWorkQty(wkQty.compareTo(0.0) >= 0 ? wkQty : 0).setExceStatus(POExceStatus.PO_EXCE_STATUS_UN_EXCE.val);
+                        BigDecimal wkQty = toBigDecimal(delivery.getWorkQty()).subtract(toBigDecimal(delivery.getAnfme())).setScale(QTY_SCALE, RoundingMode.HALF_UP);
+                        delivery.setWorkQty(wkQty.compareTo(BigDecimal.ZERO) >= 0 ? wkQty.doubleValue() : 0).setExceStatus(POExceStatus.PO_EXCE_STATUS_UN_EXCE.val);
                         if (!deliveryService.updateById(delivery)) {
                             throw new CoolException("DO鍗曟嵁淇敼澶辫触锛侊紒");
                         }
@@ -929,22 +957,44 @@
                 if (issued.compareTo(ISSUED_TOLERANCE) <= 0) {
                     break;
                 }
-                // 璇ュ簱浣嶅彲鍒嗛厤鏁伴噺锛氬彇鏈寰呭垎閰嶄笌搴撲綅搴撳瓨鐨勮緝灏忓��
-                double allocatable = Math.min(issued.doubleValue(), locItem.getAnfme() != null ? locItem.getAnfme() : 0);
+                // 棰勭害鍑哄簱涓笖鏈敓鎴愭嫞鏂欏叆搴撳崟鐨勫簱浣嶏細鎵e噺銆屾嫞鏂欎腑鍗犵敤銆嶅緱鍒板墿浣欏彲鐢紝骞舵爣璁般�屾鍦ㄦ嫞鏂欎腑锛屽墿浣� X 鍙敤銆�
+                BigDecimal pickingAllocated = getPickingAllocatedOnLoc(loc.getCode(), locItem.getMatnrId(), locItem.getBatch(), locItem.getFieldsIndex());
+                BigDecimal rawAnfme = toBigDecimal(locItem.getAnfme());
+                BigDecimal available = rawAnfme.subtract(pickingAllocated).setScale(QTY_SCALE, RoundingMode.HALF_UP);
+                if (available.compareTo(BigDecimal.ZERO) < 0) available = BigDecimal.ZERO;
+                locItem.setAnfme(available.doubleValue());
+                String pickingStatus = null;
+                if (pickingAllocated.compareTo(ISSUED_TOLERANCE) > 0) {
+                    pickingStatus = "姝e湪鎷f枡涓紝鍓╀綑 " + available.setScale(2, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString() + " 鍙敤";
+                }
+                // 璇ュ簱浣嶅彲鍒嗛厤鏁伴噺锛氬彇鏈寰呭垎閰嶄笌搴撲綅鍓╀綑鍙敤鐨勮緝灏忓��
+                BigDecimal allocatable = issued.min(available);
                 // 褰撳垎閰嶉噺绛変簬搴撲綅搴撳瓨鏃讹紝浣跨敤搴撲綅搴撳瓨绮惧害浣滀负鍑哄簱鏁伴噺锛岄伩鍏嶆埅鏂鑷寸晫闈㈡樉绀�/搴撳瓨鏍¢獙涓嶄竴鑷达紙濡傚簱瀛�15.123457琚埅鎴�15.123锛�
-                double outQtyToSet = (locItem.getAnfme() != null && Math.abs(allocatable - locItem.getAnfme()) < 1e-6)
-                        ? locItem.getAnfme() : allocatable;
+                BigDecimal outQtyToSet = (allocatable.subtract(available).abs().compareTo(ISSUED_TOLERANCE) <= 0) ? available : allocatable;
                 ExistDto existDto = new ExistDto().setBatch(locItem.getBatch()).setMatnr(locItem.getMatnrCode()).setLocNo(locItem.getLocCode());
                 if (existDtos.add(existDto)) {
                     // 棣栨浣跨敤璇ュ簱浣嶏細鍔犲叆鍒楄〃骞舵墸鍑� issued
-                    locItem.setOutQty(outQtyToSet);
-                    locItem.setBarcode(loc.getBarcode());
+                    locItem.setOutQty(outQtyToSet.doubleValue());
+                    String barcode = StringUtils.isNotBlank(loc.getBarcode()) ? loc.getBarcode() : null;
+                    if (barcode == null && LocStsType.LOC_STS_TYPE_R.type.equals(loc.getUseStatus())) {
+                        List<Task> tasksOnLoc = taskService.list(new LambdaQueryWrapper<Task>()
+                                .eq(Task::getOrgLoc, loc.getCode())
+                                .in(Task::getTaskStatus, Arrays.asList(TaskStsType.GENERATE_OUT.id, TaskStsType.WAVE_SEED.id))
+                                .last("LIMIT 1"));
+                        if (!tasksOnLoc.isEmpty() && StringUtils.isNotBlank(tasksOnLoc.get(0).getBarcode())) {
+                            barcode = tasksOnLoc.get(0).getBarcode();
+                        }
+                    }
+                    locItem.setBarcode(barcode != null ? barcode : loc.getBarcode());
                     OrderOutItemDto orderOutItemDto = new OrderOutItemDto();
                     orderOutItemDto.setLocItem(locItem);
+                    if (pickingStatus != null) {
+                        orderOutItemDto.setPickingStatus(pickingStatus);
+                    }
 
                     List<DeviceSite> deviceSites = deviceSiteService.list(new LambdaQueryWrapper<DeviceSite>()
                             .eq(DeviceSite::getChannel, loc.getChannel())
-                            .eq(DeviceSite::getType, issued.doubleValue() >= locItem.getAnfme() && itemList.size() == 1 ? TaskType.TASK_TYPE_OUT.type : TaskType.TASK_TYPE_PICK_AGAIN_OUT.type)
+                            .eq(DeviceSite::getType, issued.compareTo(toBigDecimal(locItem.getAnfme())) >= 0 && itemList.size() == 1 ? TaskType.TASK_TYPE_OUT.type : TaskType.TASK_TYPE_PICK_AGAIN_OUT.type)
                     );
                     // 鍑哄簱鍙e垪琛ㄦ帓搴忥細1001 鎺掔涓�锛屼綔涓洪粯璁�
                     deviceSites.sort((a, b) -> {
@@ -970,21 +1020,21 @@
                     }
 
                     list.add(orderOutItemDto);
-                    issued = issued.subtract(new BigDecimal(locItem.getAnfme().toString()));
+                    issued = issued.subtract(outQtyToSet);
                 } else {
                     // 璇ュ簱浣嶅凡琚墠搴忚鍗曡鍗犵敤锛氬彧鎵e噺 issued锛屼笉閲嶅鍔犲叆鍒楄〃锛岄伩鍏嶄骇鐢熲�滃簱瀛樹笉瓒斥�濊剰鏁版嵁
-                    issued = issued.subtract(new BigDecimal(String.valueOf(allocatable)));
+                    issued = issued.subtract(allocatable);
                 }
             }
             if (issued.compareTo(ISSUED_TOLERANCE) > 0) {
-                double remaining = issued.setScale(6, RoundingMode.HALF_UP).doubleValue();
+                BigDecimal remaining = issued.setScale(QTY_SCALE, RoundingMode.HALF_UP);
                 LocItem locItem = new LocItem()
                         .setId(new Random().nextLong())
                         .setMatnrCode(wkOrderItem.getMatnrCode())
                         .setMaktx(wkOrderItem.getMaktx())
                         .setAnfme(0.00)
-                        .setWorkQty(remaining)
-                        .setOutQty(remaining)
+                        .setWorkQty(remaining.doubleValue())
+                        .setOutQty(remaining.doubleValue())
                         .setUnit(wkOrderItem.getStockUnit())
                         .setBatch(wkOrderItem.getSplrBatch());
                 OrderOutItemDto orderOutItemDto = new OrderOutItemDto();
@@ -998,6 +1048,25 @@
     }
 
     /**
+     * 璇ュ簱浣嶄笅銆屾嫞鏂欏嚭搴撱�嶄笖鏈敓鎴愭嫞鏂欏叆搴撳崟鐨勪换鍔″崰鐢ㄧ殑鏁伴噺锛堝悓涓�鐗╂枡+鎵规+绁ㄥ彿锛�
+     */
+    private BigDecimal getPickingAllocatedOnLoc(String locCode, Long matnrId, String batch, String fieldsIndex) {
+        List<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>()
+                .eq(Task::getOrgLoc, locCode)
+                .eq(Task::getTaskType, TaskType.TASK_TYPE_PICK_AGAIN_OUT.type)
+                .in(Task::getTaskStatus, Arrays.asList(TaskStsType.GENERATE_OUT.id, TaskStsType.WAVE_SEED.id)));
+        if (tasks.isEmpty()) return BigDecimal.ZERO;
+        Set<Long> taskIds = tasks.stream().map(Task::getId).collect(Collectors.toSet());
+        LambdaQueryWrapper<TaskItem> q = new LambdaQueryWrapper<TaskItem>()
+                .in(TaskItem::getTaskId, taskIds)
+                .eq(TaskItem::getMatnrId, matnrId);
+        if (StringUtils.isNotBlank(batch)) q.eq(TaskItem::getBatch, batch);
+        if (StringUtils.isNotBlank(fieldsIndex)) q.eq(TaskItem::getFieldsIndex, fieldsIndex);
+        List<TaskItem> items = taskItemService.list(q);
+        return items.stream().map(ti -> toBigDecimal(ti.getAnfme())).reduce(BigDecimal.ZERO, BigDecimal::add);
+    }
+
+    /**
      * @param
      * @param wave
      * @return
@@ -1008,11 +1077,11 @@
     private List<WaveItem> mergeWave(List<WkOrderItem> orderItems, Wave wave) {
         List<WaveItem> items = new ArrayList<>();
         orderItems.forEach(order -> {
-            Double anfme = Math.round((order.getAnfme() - order.getWorkQty()) * 1000000) / 1000000.0;
+            BigDecimal anfme = toBigDecimal(order.getAnfme()).subtract(toBigDecimal(order.getWorkQty())).setScale(QTY_SCALE, RoundingMode.HALF_UP);
             WaveItem item = new WaveItem();
             BeanUtils.copyProperties(order, item);
                 item.setId(null)
-                    .setAnfme(anfme)
+                    .setAnfme(anfme.doubleValue())
                     .setMatnrId(order.getMatnrId())
                     .setMaktx(order.getMaktx())
                     .setWaveId(wave.getId())
@@ -1034,7 +1103,7 @@
                         p1.getUnit(),
                         p1.getTrackCode(),
                         p1.getFieldsIndex(),
-                        Math.round((p1.getAnfme() + p2.getAnfme())* 1000000) / 1000000.0,
+                        toBigDecimal(p1.getAnfme()).add(toBigDecimal(p2.getAnfme())).setScale(QTY_SCALE, RoundingMode.HALF_UP).doubleValue(),
                         p1.getWorkQty(),
                         p1.getTenantId(),
                         p1.getStatus(),

--
Gitblit v1.9.1