From 82065a03737fa1370eb9f4f01ab5332933baf08a Mon Sep 17 00:00:00 2001
From: chen.lin <1442464845@qq.com>
Date: 星期四, 05 三月 2026 09:23:37 +0800
Subject: [PATCH] 云仓WMS+RCS+自动入库临时方法配置

---
 rsf-admin/src/page/orders/asnOrder/AsnOrderEdit.jsx                                               |    6 
 rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskSchedules.java              |   92 +--
 rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/WaitPakinServiceImpl.java    |  132 ++++
 rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/ScheduleJobs.java               |  275 +++++------
 rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/MobileServiceImpl.java           |   91 ++-
 rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/WkOrderController.java         |   14 
 rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/MaterialAutoSchedules.java      |  339 ++++++++++++++
 rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java         |   47 +
 rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/params/WaitPakinParam.java     |    3 
 rsf-admin/src/page/orders/asnOrder/AsnOrderItemList.jsx                                           |    7 
 rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/AsnOrderServiceImpl.java     |   25 +
 rsf-server/src/main/java/com/vincent/rsf/server/manager/service/AsnOrderItemService.java          |    3 
 rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/ReceiveMsgServiceImpl.java       |  114 +++-
 rsf-admin/src/i18n/zh.js                                                                          |    2 
 rsf-admin/src/i18n/en.js                                                                          |    2 
 rsf-server/src/main/java/com/vincent/rsf/server/system/constant/GlobalConfigCode.java             |   11 
 rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/WkOrderItemController.java     |    1 
 rsf-admin/src/page/orders/asnOrder/AsnOrderList.jsx                                               |    1 
 rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/WkOrderItem.java                   |    5 
 rsf-server/src/main/java/com/vincent/rsf/server/manager/service/AsnOrderService.java              |    3 
 rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/WarehouseAreasItem.java            |    5 
 rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/WcsServiceImpl.java              |  116 +++++
 version/db/material_auto_config.sql                                                               |   10 
 rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/AsnOrderItemServiceImpl.java |   28 +
 rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/AsnExceStatus.java                  |    6 
 rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/WkOrder.java                       |    5 
 26 files changed, 1,044 insertions(+), 299 deletions(-)

diff --git a/rsf-admin/src/i18n/en.js b/rsf-admin/src/i18n/en.js
index 754556a..fe7fc7b 100644
--- a/rsf-admin/src/i18n/en.js
+++ b/rsf-admin/src/i18n/en.js
@@ -605,6 +605,7 @@
                 wkType: "wkType",
                 anfme: "anfme",
                 qty: "qty",
+                palletQty: "Pallet Qty",
                 logisNo: "logisNo",
                 arrTime: "Arrived",
                 rleStatus: "Release",
@@ -774,6 +775,7 @@
                 purUnit: "purUnit",
                 unit: 'Unit',
                 qty: "qty",
+                palletQty: "Pallet Qty",
                 safeQty: 'Safe Qty',
                 disQty: 'Def Qty',
                 splrCode: "splrCode",
diff --git a/rsf-admin/src/i18n/zh.js b/rsf-admin/src/i18n/zh.js
index afae1b9..25670f2 100644
--- a/rsf-admin/src/i18n/zh.js
+++ b/rsf-admin/src/i18n/zh.js
@@ -658,6 +658,7 @@
                 wkType: "涓氬姟绫诲瀷",
                 anfme: "璁″垝鏁伴噺",
                 qty: "瀹屾垚鏁伴噺",
+                palletQty: "缁勬墭鏁伴噺",
                 logisNo: "鐗╂祦鍗曞彿",
                 arrTime: "棰勮鍒拌揪鏃堕棿",
                 rleStatus: "閲婃斁鐘舵��",
@@ -809,6 +810,7 @@
                 purUnit: "閲囪喘鍗曚綅",
                 unit: '鍗曚綅',
                 qty: "瀹屾垚鏁�",
+                palletQty: "缁勬墭鏁伴噺",
                 safeQty: '鍚堟牸鏁�',
                 disQty: '涓嶅悎鏍兼暟',
                 splrBatch: "鎵规",
diff --git a/rsf-admin/src/page/orders/asnOrder/AsnOrderEdit.jsx b/rsf-admin/src/page/orders/asnOrder/AsnOrderEdit.jsx
index 9a86482..17d5298 100644
--- a/rsf-admin/src/page/orders/asnOrder/AsnOrderEdit.jsx
+++ b/rsf-admin/src/page/orders/asnOrder/AsnOrderEdit.jsx
@@ -122,6 +122,12 @@
                                     readOnly
                                     parse={v => v}
                                 />
+                                <TextInput
+                                    label="table.field.asnOrder.palletQty"
+                                    source="palletQty"
+                                    readOnly
+                                    parse={v => v}
+                                />
                                 <DateInput
                                     label="table.field.asnOrder.arrTime"
                                     source="arrTime"
diff --git a/rsf-admin/src/page/orders/asnOrder/AsnOrderItemList.jsx b/rsf-admin/src/page/orders/asnOrder/AsnOrderItemList.jsx
index 9f0031e..1f7d887 100644
--- a/rsf-admin/src/page/orders/asnOrder/AsnOrderItemList.jsx
+++ b/rsf-admin/src/page/orders/asnOrder/AsnOrderItemList.jsx
@@ -192,6 +192,7 @@
         <TextField source="model" label="table.field.asnOrderItem.model" />,
         <NumberField source="anfme" label="table.field.asnOrderItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />,
         <NumberField source="qty" label="table.field.asnOrderItem.qty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />,
+        <NumberField source="palletQty" label="table.field.asnOrderItem.palletQty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />,
         <TextField source="stockUnit" label="table.field.asnOrderItem.stockUnit" />,
         <NumberField source="purQty" label="table.field.asnOrderItem.purQty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />,
         <TextField source="purUnit" label="table.field.asnOrderItem.purUnit" />,
@@ -202,7 +203,9 @@
         <TextField source="trackCode" label="table.field.asnOrderItem.barcode" />,
         // <TextField source="packName" label="table.field.asnOrderItem.packName" />, // 鍖呰宸叉敞閲�
       ]
-      const fields = data.map(el => <TextField key={el.fields} source={`extendFields.[${el.fields}]`} label={el.fieldsAlise} />)
+      const fields = data
+        .filter(el => el.fields !== 'crushNo' && el.fieldsAlise !== '鐜板搧绁ㄥ彿')
+        .map(el => <TextField key={el.fields} source={`extendFields.[${el.fields}]`} label={el.fieldsAlise} />)
       const lastArr = [
         <DateField source="updateTime" label="common.field.updateTime" showTime />,
         <ReferenceField source="updateBy" label="common.field.updateBy" reference="user" link={false} sortable={false}>
@@ -238,7 +241,7 @@
           preferenceKey='asnOrderItem'
           bulkActionButtons={false}
           rowClick={(id, resource, record) => false}
-          omit={['id', 'orderId', 'orderCode', 'poDetlId', 'poDetlCode', 'matnrId', 'spec', 'model', 'purQty', 'purUnit', 'qrcode', 'trackCode', 'splrCode', 'platWorkCode', 'projectCode', 'platItemId', 'isptResult$', 'packName']}
+          omit={['id', 'orderId', 'orderCode', 'poDetlId', 'poDetlCode', 'matnrId', 'spec', 'model', 'purQty', 'purUnit', 'qrcode', 'trackCode', 'splrCode', 'platWorkCode', 'projectCode', 'platItemId', 'fieldsIndex', 'isptResult$', 'packName']}
         >
           {columns.map((column) => column)}
         </StyledDatagrid>}
diff --git a/rsf-admin/src/page/orders/asnOrder/AsnOrderList.jsx b/rsf-admin/src/page/orders/asnOrder/AsnOrderList.jsx
index 428440d..d7105a7 100644
--- a/rsf-admin/src/page/orders/asnOrder/AsnOrderList.jsx
+++ b/rsf-admin/src/page/orders/asnOrder/AsnOrderList.jsx
@@ -168,6 +168,7 @@
           <TextField cellClassName="wkType" source="wkType$" label="table.field.asnOrder.wkType" />
           <NumberField source="anfme" label="table.field.asnOrder.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />
           <NumberField source="qty" label="table.field.asnOrder.qty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />
+          <NumberField source="palletQty" label="table.field.asnOrder.palletQty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />
           <DateField source="arrTime" label="table.field.asnOrder.arrTime" showTime />
           <TextField source="rleStatus$" label="table.field.asnOrder.rleStatus" sortable={false} />
           <TextField source="logisNo" label="table.field.asnOrder.logisNo" />
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/MobileServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/MobileServiceImpl.java
index 1b89038..81635dd 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/MobileServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/MobileServiceImpl.java
@@ -30,6 +30,7 @@
 import com.vincent.rsf.server.system.entity.*;
 import com.vincent.rsf.server.system.mapper.FieldsMapper;
 import com.vincent.rsf.server.system.mapper.TenantMapper;
+import com.vincent.rsf.server.system.entity.Config;
 import com.vincent.rsf.server.system.service.ConfigService;
 import com.vincent.rsf.server.system.service.FieldsItemService;
 import com.vincent.rsf.server.system.service.UserLoginService;
@@ -260,8 +261,10 @@
         }
         //TODO /**鏀惰揣鏁伴噺绱姞锛�1. 浼氬嚭瓒呮敹鎯呭喌 2. 浼氭湁鏀惰揣涓嶈冻鎯呭喌*/
         Double rcptedQty = QuantityUtils.add(wkOrder.getQty(), receiptQty);
-        // 鏂伴『搴忥細鏈墽琛�(缁勬墭)鈫掍换鍔℃墽琛屼腑鈫掑凡瀹屾垚锛屼笉鍐嶈缃墽琛屼腑/鏀惰揣瀹屾垚
-        wkOrder.setQty(rcptedQty); // .setExceStatus(AsnExceStatus.ASN_EXCE_STATUS_EXCE_ING.val)
+        wkOrder.setQty(rcptedQty);
+        if (AsnExceStatus.ASN_EXCE_STATUS_UN_EXCE.val.equals(wkOrder.getExceStatus())) {
+            wkOrder.setExceStatus(AsnExceStatus.ASN_EXCE_STATUS_EXCE_ING.val);
+        }
         if (!asnOrderMapper.updateById(wkOrder)) {
             throw new CoolException("宸叉敹璐ф暟閲忎慨鏀瑰け璐ワ紒锛�");
         }
@@ -352,18 +355,21 @@
             if (asnOrderItemMapper.updateById(orderItem) < 1) {
                 throw new CoolException("閫氱煡鍗曟槑缁嗘暟閲忎慨鏀瑰け璐ワ紒锛�");
             }
-            // 鏀惰揣鍖哄凡鍋滅敤锛屼笉鍐嶄繚瀛樿嚦鏀惰揣鍖�
-            // extracted(loginUserId, dto, areasItem, orderItem, wkOrder, matnr);
+            // DirectWaitPakin 鍚敤鏃朵繚瀛樿嚦鏀惰揣鍖猴紝褰㈡垚闂幆锛涙湭鍚敤鏃朵笉鍐欐敹璐у尯
+            Config directPakinConfig = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.DIRECT_WAIT_PAKIN));
+            if (directPakinConfig != null && Boolean.parseBoolean(directPakinConfig.getVal())) {
+                extracted(loginUserId, dto, areasItem, orderItem, wkOrder, matnr);
+            }
         }
 
-        // 鏂伴『搴忥細鏈墽琛�(缁勬墭)鈫掍换鍔℃墽琛屼腑鈫掑凡瀹屾垚锛屼笉鍐嶈缃敹璐у畬鎴�
-        // WkOrder order = asnOrderMapper.getOne(new LambdaQueryWrapper<WkOrder>().eq(WkOrder::getCode, asnCode));
-        // if (order.getQty().compareTo(order.getAnfme()) >= 0.00) {
-        //     order.setExceStatus(AsnExceStatus.ASN_EXCE_STATUS_RECEIPT_DONE.val).setRleStatus(Short.valueOf("1"));
-        //     if (!asnOrderMapper.updateById(order)) {
-        //         throw new CoolException("璁㈠崟鐘舵�佷慨鏀瑰け璐ワ紒锛�");
-        //     }
-        // }
+        // 宸叉敹鏁伴噺 >= 璁″垝鏁伴噺鏃剁疆涓烘敹璐у畬鎴�(2)
+        WkOrder order = asnOrderMapper.getOne(new LambdaQueryWrapper<WkOrder>().eq(WkOrder::getCode, asnCode));
+        if (order != null && order.getAnfme() != null && QuantityUtils.compare(order.getQty(), order.getAnfme()) >= 0) {
+            order.setExceStatus(AsnExceStatus.ASN_EXCE_STATUS_RECEIPT_DONE.val).setRleStatus(Short.valueOf("1"));
+            if (!asnOrderMapper.updateById(order)) {
+                throw new CoolException("璁㈠崟鐘舵�佷慨鏀瑰け璐ワ紒锛�");
+            }
+        }
 
         return R.ok("鏀惰揣鎴愬姛锛侊紒");
     }
@@ -512,13 +518,16 @@
      * @description 鑾峰彇鏀惰揣鍖�
      * @time 2025/3/11 10:12
      */
-    /** 鏀惰揣鍖哄凡鍋滅敤锛岃繑鍥炵┖鍒楄〃 */
+    /** DirectWaitPakin 鍚敤鏃惰繑鍥炴敹璐у尯鍒楄〃锛屾湭鍚敤鏃惰繑鍥炵┖鍒楄〃锛堜笉褰卞搷缁勬墭涓庝簯浠撳叆搴撴祦绋嬶級 */
     @Override
     public R getReceiptAreas() {
-        // List<WarehouseAreas> areas = warehouseAreasService.list(new LambdaQueryWrapper<WarehouseAreas>()
-        //         .eq(WarehouseAreas::getType, WarehouseAreaType.WAREHOUSE_AREA_RECEIPT.type));
-        // return R.ok(areas);
-        return R.ok(Collections.emptyList());
+        Config directPakinConfig = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.DIRECT_WAIT_PAKIN));
+        if (directPakinConfig == null || !Boolean.parseBoolean(directPakinConfig.getVal())) {
+            return R.ok(Collections.emptyList());
+        }
+        List<WarehouseAreas> areas = warehouseAreasService.list(new LambdaQueryWrapper<WarehouseAreas>()
+                .eq(WarehouseAreas::getType, WarehouseAreaType.WAREHOUSE_AREA_RECEIPT.type));
+        return R.ok(areas);
     }
 
     /**
@@ -623,15 +632,48 @@
             return R.ok(resultList);
         }
         
-        // 鏀惰揣鍖哄凡鍋滅敤锛氭湁ASN鍗曞彿鏃朵粠璁㈠崟鏄庣粏鏌ュ彲缁勬墭鐗╂枡锛涘彲缁勭洏鏁伴噺 = 璁″垝鏁伴噺 - 宸茬粍鎵樻暟閲� - 宸蹭笂鏋舵暟閲�
+        // 鏈堿SN鍗曞彿鏃讹細DirectWaitPakin 鍚敤鍒欎粠鏀惰揣鍖烘煡鍙粍鎵樼墿鏂欙紝鏈惎鐢ㄥ垯浠庤鍗曟槑缁嗘煡锛堝彲缁勭洏鏁伴噺 = 璁″垝 - 宸茬粍鎵� - 宸蹭笂鏋讹級
         if (!Cools.isEmpty(asnCode)) {
+            Config directPakinConfig = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.DIRECT_WAIT_PAKIN));
+            if (directPakinConfig != null && Boolean.parseBoolean(directPakinConfig.getVal())) {
+                LambdaQueryWrapper<WarehouseAreasItem> receiptWrapper = new LambdaQueryWrapper<WarehouseAreasItem>().eq(WarehouseAreasItem::getAsnCode, asnCode);
+                if (!Cools.isEmpty(matnrCode)) receiptWrapper.eq(WarehouseAreasItem::getMatnrCode, matnrCode);
+                if (!Cools.isEmpty(batch)) receiptWrapper.eq(WarehouseAreasItem::getSplrBatch, batch);
+                if (!Objects.isNull(fieldIndex)) receiptWrapper.eq(WarehouseAreasItem::getFieldsIndex, fieldIndex);
+                if (!Cools.isEmpty(code)) receiptWrapper.eq(WarehouseAreasItem::getTrackCode, code);
+                List<WarehouseAreasItem> receiptList = warehouseAreasItemService.list(receiptWrapper);
+                // 缁勬墭閫氱煡妗o紙WaitPakinItem锛夌殑宸茬粍鎵樻暟閲忎篃瑕佹墸鍑忥細鏀惰揣鍖� workQty 浠呭弽鏄犱粠鏀惰揣鍖虹粍鎵樼殑閮ㄥ垎锛屼粠璁㈠崟鐩存帴缁勬墭鐨勫湪姝ゆ眹鎬�
+                Map<Long, Double> waitPakinSumByItemId = new java.util.HashMap<>();
+                if (!receiptList.isEmpty() && receiptList.stream().anyMatch(e -> e.getAsnId() != null && e.getAsnItemId() != null)) {
+                    List<Long> asnItemIds = receiptList.stream().map(WarehouseAreasItem::getAsnItemId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
+                    Long asnId = receiptList.get(0).getAsnId();
+                    if (asnId != null && !asnItemIds.isEmpty()) {
+                        List<WaitPakinItem> wpItems = waitPakinItemService.list(
+                                new LambdaQueryWrapper<WaitPakinItem>().eq(WaitPakinItem::getAsnId, asnId).in(WaitPakinItem::getAsnItemId, asnItemIds).eq(WaitPakinItem::getDeleted, 0));
+                        wpItems.forEach(w -> waitPakinSumByItemId.merge(w.getAsnItemId(), w.getAnfme() != null ? w.getAnfme() : 0.0, (a, b) -> (a != null ? a : 0.0) + (b != null ? b : 0.0)));
+                        waitPakinSumByItemId.replaceAll((k, v) -> QuantityUtils.roundToScale(v));
+                    }
+                }
+                // 鍙粍鎵� = 璁″垝(anfme) - 宸茬粍鎵�(waitPakinSumByItemId)锛屼笉鍙犲姞 areaWorkQty 閬垮厤涓庣粍鎵樻。姹囨�婚噸澶嶈绠�
+                receiptList.removeIf(e -> {
+                    Double anfme = e.getAnfme() != null ? e.getAnfme() : 0.0;
+                    Double qty = e.getQty() != null ? e.getQty() : 0.0;
+                    Double alreadyInWaitPakin = e.getAsnItemId() != null ? waitPakinSumByItemId.getOrDefault(e.getAsnItemId(), 0.0) : 0.0;
+                    Double totalAlready = QuantityUtils.roundToScale(alreadyInWaitPakin);
+                    Double available = QuantityUtils.roundToScale(QuantityUtils.subtract(QuantityUtils.subtract(anfme, totalAlready), qty));
+                    e.setWorkQty(totalAlready);
+                    e.setAvailablePalletQty(available);
+                    return QuantityUtils.compare(available, 0.0) <= 0;
+                });
+                logger.info("=== 浠庢敹璐у尯鏌ヨ鍙粍鎵樼墿鏂欙紙DirectWaitPakin锛塧snCode: {} 杩斿洖 {} 鏉�", asnCode, receiptList.size());
+                return R.ok(receiptList);
+            }
             WkOrder order = asnOrderMapper.getOne(new LambdaQueryWrapper<WkOrder>().eq(WkOrder::getCode, asnCode));
             if (order == null) {
                 logger.info("鏈壘鍒癆SN鍗曞彿: {}", asnCode);
                 return R.ok(Collections.emptyList());
             }
-            // 鎸夋槑缁嗘眹鎬诲凡缁勬墭鏁伴噺锛堢粍鎵樻暟閲忎笉浼氬洜鏀瑰崟鑰屽彉锛�
-            List<WaitPakinItem> pakinItems = waitPakinItemService.list(new LambdaQueryWrapper<WaitPakinItem>().eq(WaitPakinItem::getAsnId, order.getId()));
+            List<WaitPakinItem> pakinItems = waitPakinItemService.list(new LambdaQueryWrapper<WaitPakinItem>().eq(WaitPakinItem::getAsnId, order.getId()).eq(WaitPakinItem::getDeleted, 0));
             Map<Long, Double> palletizedByItemId = pakinItems.stream()
                     .collect(Collectors.groupingBy(WaitPakinItem::getAsnItemId, Collectors.summingDouble(w -> w.getAnfme() != null ? w.getAnfme() : 0.0)));
             palletizedByItemId.replaceAll((k, v) -> QuantityUtils.roundToScale(v));
@@ -645,8 +687,10 @@
             for (WkOrderItem oi : orderItems) {
                 Double anfme = QuantityUtils.roundToScale(oi.getAnfme() != null ? oi.getAnfme() : 0.0);
                 Double qty = QuantityUtils.roundToScale(oi.getQty() != null ? oi.getQty() : 0.0);
-                Double workQty = palletizedByItemId.getOrDefault(oi.getId(), 0.0); // 宸茬粍鎵樻暟閲�
-                if (QuantityUtils.compare(QuantityUtils.subtract(QuantityUtils.subtract(anfme, workQty), qty), 0.0) <= 0) continue; // 鍙粍鐩樻暟閲�<=0 涓嶈繑鍥�
+                Double workQty = palletizedByItemId.getOrDefault(oi.getId(), 0.0);
+                // 鍙粍鐩樻暟閲� = 璁″垝 - 宸茬粍鎵橈紙涓嶆墸鍑忔槑缁嗗畬鎴愭暟閲� qty锛岄伩鍏嶄簯浠撳悓姝ュ畬鎴愭暟閲�=璁″垝鍚庡鑷村彲缁勬墭琚畻鎴� 0锛�
+                Double availablePalletQty = QuantityUtils.roundToScale(QuantityUtils.subtract(anfme, workQty));
+                if (QuantityUtils.compare(availablePalletQty, 0.0) <= 0) continue;
                 WarehouseAreasItem v = new WarehouseAreasItem();
                 v.setId(oi.getId());
                 v.setAsnItemId(oi.getId());
@@ -655,6 +699,7 @@
                 v.setAnfme(anfme);
                 v.setQty(qty);
                 v.setWorkQty(QuantityUtils.roundToScale(workQty));
+                v.setAvailablePalletQty(availablePalletQty);
                 v.setMatnrCode(oi.getMatnrCode());
                 v.setMaktx(oi.getMaktx());
                 v.setSplrBatch(oi.getSplrBatch());
@@ -669,7 +714,7 @@
                 }
                 list.add(v);
             }
-            logger.info("=== 浠庤鍗曟槑缁嗘煡璇㈠彲缁勬墭鐗╂枡锛堟敹璐у尯宸插仠鐢級asnCode: {} 杩斿洖 {} 鏉�", asnCode, list.size());
+            logger.info("=== 浠庤鍗曟槑缁嗘煡璇㈠彲缁勬墭鐗╂枡 asnCode: {} 杩斿洖 {} 鏉�", asnCode, list.size());
             return R.ok(list);
         }
         
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/ReceiveMsgServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/ReceiveMsgServiceImpl.java
index ca580c6..6d8b18f 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/ReceiveMsgServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/ReceiveMsgServiceImpl.java
@@ -26,7 +26,10 @@
 import com.vincent.rsf.server.manager.service.*;
 import com.vincent.rsf.server.manager.service.impl.MatnrServiceImpl;
 import com.vincent.rsf.server.system.constant.DictTypeCode;
+import com.vincent.rsf.server.system.constant.GlobalConfigCode;
 import com.vincent.rsf.server.system.constant.SerialRuleCode;
+import com.vincent.rsf.server.system.entity.Config;
+import com.vincent.rsf.server.system.service.ConfigService;
 import com.vincent.rsf.server.system.entity.DictData;
 import com.vincent.rsf.server.system.entity.DictType;
 import com.vincent.rsf.server.system.entity.Fields;
@@ -113,6 +116,8 @@
     private WaitPakinItemService waitPakinItemService;
     @Autowired
     private WarehouseAreasItemService warehouseAreasItemService;
+    @Autowired
+    private ConfigService configService;
 
 
     /**
@@ -461,22 +466,27 @@
                             .eq(WkOrder::getPoCode, syncOrder.getOrderInternalCode()));
                     if (!Objects.isNull(order)) {
                         // 浠呮湭鎵ц鐘舵�佸彲琚� order/add 淇敼锛堝叆搴撴湭鎵ц銆佸嚭搴撲换鍔″垵濮嬶級
-                        List<Short> editableStatus = Arrays.asList(AsnExceStatus.ASN_EXCE_STATUS_UN_EXCE.val, AsnExceStatus.OUT_STOCK_STATUS_TASK_INIT.val);
+                        List<Short> editableStatus = Arrays.asList(AsnExceStatus.ASN_EXCE_STATUS_UN_EXCE.val
+                                ,AsnExceStatus.ASN_EXCE_STATUS_UN_EXCE.val
+                                ,AsnExceStatus.ASN_EXCE_STATUS_RECEIPT_DONE.val
+                                , AsnExceStatus.OUT_STOCK_STATUS_TASK_INIT.val);
                         if (!editableStatus.contains(order.getExceStatus())) {
                             throw new CoolException("浠呮湭鎵ц鐘舵�佺殑鍗曟嵁鍙慨鏀癸紒锛�");
                         }
                         // 瀛樺湪鍒欎慨鏀癸紙1 鍜� 2 鍧囪蛋姝ゅ锛夛紝缁勬墭鏍¢獙鍦� mergeOrderWithPakin/updateOrderNoPakin 鍐�
                         long pakinCount = waitPakinItemService.count(new LambdaQueryWrapper<WaitPakinItem>()
-                                .eq(WaitPakinItem::getAsnId, order.getId()));
+                                .eq(WaitPakinItem::getAsnId, order.getId()).eq(WaitPakinItem::getDeleted, 0));
                         if (pakinCount > 0) {
-                            // 宸茬粍鎵橈細鎸� lineId锛坧latItemId锛夊悎骞讹紝鏍¢獙鏁伴噺涓庡垹闄�
                             mergeOrderWithPakin(order, syncOrder, resolvedOrderType, typeCode, loginUserId);
-                            // 鏀惰揣鍖哄凡鍋滅敤 // syncReceiptAreaByOrder(order.getId());
-                            return; // 鏈崟宸插鐞嗭紝璺宠繃涓嬫柟鈥滄柊寤轰富鍗�+鏄庣粏鈥�
+                            if (isDirectWaitPakin()) {
+                                syncReceiptAreaByOrder(order.getId());
+                            }
+                            return;
                         }
-                        // 鏈粍鎵橈細鍦ㄥ師鍗曚笂鏇存柊涓诲崟+鏄庣粏锛屼繚鐣� exceStatus/qty/workQty锛岄伩鍏嶅啀娆¤Е鍙戝畾鏃朵换鍔″鑷撮噸澶嶆敹璐�
                         updateOrderNoPakin(order, syncOrder, loginUserId);
-                        // 鏀惰揣鍖哄凡鍋滅敤 // syncReceiptAreaByOrder(order.getId());
+                        if (isDirectWaitPakin()) {
+                            syncReceiptAreaByOrder(order.getId());
+                        }
                         return;
                     } else if (Integer.valueOf(2).equals(syncOrder.getOperateType())) {
                         // 浠� operateType=2 鏃惰姹傚崟鎹繀椤诲瓨鍦�
@@ -551,7 +561,7 @@
             }
         }
         List<WkOrderItem> existingItems = asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, order.getId()));
-        List<WaitPakinItem> pakinItems = waitPakinItemService.list(new LambdaQueryWrapper<WaitPakinItem>().eq(WaitPakinItem::getAsnId, order.getId()));
+        List<WaitPakinItem> pakinItems = waitPakinItemService.list(new LambdaQueryWrapper<WaitPakinItem>().eq(WaitPakinItem::getAsnId, order.getId()).eq(WaitPakinItem::getDeleted, 0));
         Map<Long, Double> palletizedByItemId = pakinItems.stream()
                 .collect(Collectors.groupingBy(WaitPakinItem::getAsnItemId, Collectors.summingDouble(w -> w.getAnfme() != null ? w.getAnfme() : 0.0)));
         palletizedByItemId.replaceAll((k, v) -> QuantityUtils.roundToScale(v));
@@ -567,6 +577,15 @@
                 .map(e -> StringUtils.isNotBlank(e.getPlatItemId()) ? e.getPlatItemId().trim() : null)
                 .filter(Objects::nonNull)
                 .collect(Collectors.toSet());
+
+        // 宸茬粍鎵樺崟鎹慨鏀瑰彧鑳藉鍔犳暟閲忎笉鑳藉噺灏戞暟閲忥細浜戜粨涓嬪彂鐨勬�绘暟閲忎笉寰楀皬浜庡凡缁勬墭鎬婚噺
+        double totalPalletized = QuantityUtils.roundToScale(pakinItems.stream().mapToDouble(w -> w.getAnfme() != null ? w.getAnfme() : 0.0).sum());
+        double incomingTotal = syncOrder.getOrderItems() == null ? 0.0 : syncOrder.getOrderItems().stream()
+                .mapToDouble(it -> it.getAnfme() != null ? it.getAnfme() : 0.0).sum();
+        incomingTotal = QuantityUtils.roundToScale(incomingTotal);
+        if (QuantityUtils.compare(incomingTotal, totalPalletized) < 0) {
+            throw new CoolException("宸茬粍鎵樺崟鎹慨鏀瑰彧鑳藉鍔犳暟閲忎笉鑳藉噺灏戞暟閲忥紙褰撳墠宸茬粍鎵樻�婚噺 " + totalPalletized + "锛屼笅鍙戞�婚噺 " + incomingTotal + "锛夛紒锛�");
+        }
 
         for (WkOrderItem existing : existingItems) {
             String lineId = StringUtils.isNotBlank(existing.getPlatItemId()) ? existing.getPlatItemId().trim() : null;
@@ -603,7 +622,16 @@
                 continue;
             }
             SyncOrdersItem inc = incomingByLineId.get(lineId);
-            existing.setAnfme(QuantityUtils.roundToScale(inc.getAnfme() != null ? inc.getAnfme() : existing.getAnfme()));
+            Double newAnfme = QuantityUtils.roundToScale(inc.getAnfme() != null ? inc.getAnfme() : existing.getAnfme());
+            existing.setAnfme(newAnfme);
+            if (inc.getQty() != null) {
+                existing.setQty(QuantityUtils.roundToScale(inc.getQty()));
+            } else {
+                Double curQty = existing.getQty() != null ? existing.getQty() : 0.0;
+                if (QuantityUtils.compare(curQty, 0.0) != 0) {
+                    existing.setQty(QuantityUtils.roundToScale(newAnfme));
+                }
+            }
             existing.setMaktx(inc.getMaktx());
             existing.setSpec(inc.getSpec());
             existing.setModel(inc.getModel());
@@ -635,6 +663,9 @@
         Double sum = QuantityUtils.roundToScale(asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, order.getId()))
                 .stream().mapToDouble(WkOrderItem::getAnfme).sum());
         order.setAnfme(sum);
+        List<WkOrderItem> afterItems = asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, order.getId()));
+        double qtySum = afterItems.stream().mapToDouble(oi -> oi.getQty() != null ? oi.getQty() : 0.0).sum();
+        order.setQty(QuantityUtils.roundToScale(qtySum));
         asnOrderService.updateById(order);
     }
 
@@ -672,12 +703,23 @@
         for (WkOrderItem existing : existingItems) {
             String lineId = StringUtils.isNotBlank(existing.getPlatItemId()) ? existing.getPlatItemId().trim() : null;
             if (lineId == null || !incomingByLineId.containsKey(lineId)) {
-                // 鏀惰揣鍖哄凡鍋滅敤 // warehouseAreasItemService.remove(new LambdaQueryWrapper<WarehouseAreasItem>().eq(WarehouseAreasItem::getAsnItemId, existing.getId()));
+                if (isDirectWaitPakin()) {
+                    warehouseAreasItemService.remove(new LambdaQueryWrapper<WarehouseAreasItem>().eq(WarehouseAreasItem::getAsnItemId, existing.getId()));
+                }
                 asnOrderItemService.removeById(existing.getId());
                 continue;
             }
             SyncOrdersItem inc = incomingByLineId.get(lineId);
-            existing.setAnfme(QuantityUtils.roundToScale(inc.getAnfme() != null ? inc.getAnfme() : existing.getAnfme()));
+            Double newAnfme = QuantityUtils.roundToScale(inc.getAnfme() != null ? inc.getAnfme() : existing.getAnfme());
+            existing.setAnfme(newAnfme);
+            if (inc.getQty() != null) {
+                existing.setQty(QuantityUtils.roundToScale(inc.getQty()));
+            } else {
+                Double curQty = existing.getQty() != null ? existing.getQty() : 0.0;
+                if (QuantityUtils.compare(curQty, 0.0) != 0) {
+                    existing.setQty(QuantityUtils.roundToScale(newAnfme));
+                }
+            }
             existing.setMaktx(inc.getMaktx());
             existing.setSpec(inc.getSpec());
             existing.setModel(inc.getModel());
@@ -709,31 +751,37 @@
         Double sum = QuantityUtils.roundToScale(asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, order.getId()))
                 .stream().mapToDouble(WkOrderItem::getAnfme).sum());
         order.setAnfme(sum);
+        List<WkOrderItem> afterItems = asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, order.getId()));
+        double qtySum = afterItems.stream().mapToDouble(oi -> oi.getQty() != null ? oi.getQty() : 0.0).sum();
+        order.setQty(QuantityUtils.roundToScale(qtySum));
         asnOrderService.updateById(order);
     }
 
-    /** 鏀惰揣鍖哄凡鍋滅敤锛屾柟娉曟暣浣撴敞閲�
-     * 璁㈠崟淇敼鍚庡悓姝ユ敹璐у尯锛氭寜 asnItemId 灏嗘敹璐у尯璁板綍鐨� anfme 鏇存柊涓鸿鍗曟槑缁嗙殑 anfme銆�
-     */
-//    private void syncReceiptAreaByOrder(Long orderId) {
-//        List<WkOrderItem> orderItems = asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, orderId));
-//        if (orderItems.isEmpty()) {
-//            return;
-//        }
-//        List<WarehouseAreasItem> areaItems = warehouseAreasItemService.list(new LambdaQueryWrapper<WarehouseAreasItem>().eq(WarehouseAreasItem::getAsnId, orderId));
-//        Map<Long, Double> itemAnfme = orderItems.stream().collect(Collectors.toMap(WkOrderItem::getId, i -> i.getAnfme() != null ? i.getAnfme() : 0.0, (a, b) -> b));
-//        for (WarehouseAreasItem area : areaItems) {
-//            if (area.getAsnItemId() == null || !itemAnfme.containsKey(area.getAsnItemId())) {
-//                continue;
-//            }
-//            Double anfme = itemAnfme.get(area.getAsnItemId());
-//            if (area.getAnfme() != null && area.getAnfme().equals(anfme)) {
-//                continue;
-//            }
-//            area.setAnfme(anfme);
-//            warehouseAreasItemService.updateById(area);
-//        }
-//    }
+    /** DirectWaitPakin 鍚敤鏃讹細璁㈠崟淇敼鍚庡悓姝ユ敹璐у尯锛屾寜 asnItemId 灏嗘敹璐у尯璁板綍鐨� anfme 鏇存柊涓鸿鍗曟槑缁嗙殑 anfme銆� */
+    private void syncReceiptAreaByOrder(Long orderId) {
+        List<WkOrderItem> orderItems = asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, orderId));
+        if (orderItems.isEmpty()) {
+            return;
+        }
+        List<WarehouseAreasItem> areaItems = warehouseAreasItemService.list(new LambdaQueryWrapper<WarehouseAreasItem>().eq(WarehouseAreasItem::getAsnId, orderId));
+        Map<Long, Double> itemAnfme = orderItems.stream().collect(Collectors.toMap(WkOrderItem::getId, i -> i.getAnfme() != null ? i.getAnfme() : 0.0, (a, b) -> b));
+        for (WarehouseAreasItem area : areaItems) {
+            if (area.getAsnItemId() == null || !itemAnfme.containsKey(area.getAsnItemId())) {
+                continue;
+            }
+            Double anfme = itemAnfme.get(area.getAsnItemId());
+            if (area.getAnfme() != null && area.getAnfme().equals(anfme)) {
+                continue;
+            }
+            area.setAnfme(anfme);
+            warehouseAreasItemService.updateById(area);
+        }
+    }
+
+    private boolean isDirectWaitPakin() {
+        Config config = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.DIRECT_WAIT_PAKIN));
+        return config != null && Boolean.parseBoolean(config.getVal());
+    }
 
     /**
      * @author Ryan
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/WcsServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/WcsServiceImpl.java
index 58ea573..13c551f 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/WcsServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/WcsServiceImpl.java
@@ -28,7 +28,12 @@
 import com.vincent.rsf.server.api.utils.SlaveProperties;
 import com.vincent.rsf.server.manager.entity.*;
 import com.vincent.rsf.server.manager.service.*;
+import com.vincent.rsf.server.manager.controller.params.PakinItem;
+import com.vincent.rsf.server.manager.controller.params.WaitPakinParam;
 import com.vincent.rsf.server.manager.service.impl.LocServiceImpl;
+import com.vincent.rsf.server.system.constant.GlobalConfigCode;
+import com.vincent.rsf.server.system.entity.Config;
+import com.vincent.rsf.server.system.service.ConfigService;
 import com.vincent.rsf.server.system.utils.SystemAuthUtils;
 import com.vincent.rsf.server.system.constant.SerialRuleCode;
 import com.vincent.rsf.server.manager.enums.LocStsType;
@@ -45,6 +50,7 @@
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.client.RestTemplate;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Date;
@@ -87,6 +93,16 @@
     private RestTemplate restTemplate;
     @Autowired
     private RemotesInfoProperties.RcsApi rcsApi;
+    @Autowired
+    private ConfigService configService;
+    @Autowired
+    private MatnrService matnrService;
+    @Autowired
+    private AsnOrderService asnOrderService;
+    @Autowired
+    private AsnOrderItemService asnOrderItemService;
+    @Autowired
+    private com.vincent.rsf.server.api.service.MobileService mobileService;
 
 
     @Override
@@ -306,6 +322,16 @@
 
         // 2. 鑻ユ湭鍛戒腑鎷f枡/鐩樼偣鍏ュ簱锛屽啀鏍¢獙缁勬墭骞剁户缁叾浠栧叆搴撻�昏緫
         if (pickInTask == null && checkInTask == null) {
+            waitPakin = waitPakinService.getOne(new LambdaQueryWrapper<WaitPakin>()
+                    .eq(WaitPakin::getBarcode, param.getBarcode())
+                    .in(WaitPakin::getIoStatus, PakinIOStatus.PAKIN_IO_STATUS_DONE.val, PakinIOStatus.PAKIN_IO_STATUS_TASK_EXCE.val));
+            // 绌烘墭鐩樻棤缁勬墭鏃讹細鑻ラ厤缃惎鐢ㄥ垯鎸� AUTO_FULL_OUT_MATNR_CODE 鑷姩缁勬墭骞剁敓鎴愬叆搴撳崟锛屽啀缁х画鍏ュ簱浠诲姟閫昏緫
+            if (waitPakin == null) {
+                tryAutoPakinForBarcode(param.getBarcode());
+                waitPakin = waitPakinService.getOne(new LambdaQueryWrapper<WaitPakin>()
+                        .eq(WaitPakin::getBarcode, param.getBarcode())
+                        .in(WaitPakin::getIoStatus, PakinIOStatus.PAKIN_IO_STATUS_DONE.val, PakinIOStatus.PAKIN_IO_STATUS_TASK_EXCE.val));
+            }
             waitPakin = validateWaitPakin(param.getBarcode());
             waitPakinItems = waitPakinItemService.list(
                     new LambdaQueryWrapper<WaitPakinItem>().eq(WaitPakinItem::getPakinId, waitPakin.getId()));
@@ -375,6 +401,9 @@
             throw new RuntimeException(e);
         }
 
+        if (waitPakin == null) {
+            throw new CoolException("璇锋鏌ョ粍鎷栫姸鎬佹槸鍚﹀畬鎴愶紒锛�");
+        }
         // 鍒涘缓骞朵繚瀛樹换鍔�
         Task task = createTask(ruleCode, locNo.getLocNo(), waitPakin.getBarcode(),
                 deviceSite.getDeviceSite(), param.getSourceStaNo().toString(), param.getUser());
@@ -399,6 +428,93 @@
 
 
     /**
+     * RCS 鍏ュ簱鐢宠鏃惰嫢 barcode 鏃犵粍鎵樹笖閰嶇疆鍚敤锛氭寜 AUTO_FULL_OUT_MATNR_CODE 鏃犺鍗曠粍鎵樺苟鐢熸垚鍏ュ簱鍗曪紝渚夸簬鍚庣画鐢熸垚鍏ュ簱浠诲姟銆�
+     */
+    private void tryAutoPakinForBarcode(String barcode) {
+        Config enabledConfig = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.AUTO_PAKIN_ON_ASN_ENABLED));
+        if (enabledConfig == null || !Boolean.parseBoolean(enabledConfig.getVal())) {
+            return;
+        }
+        Config matnrConfig = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.AUTO_FULL_OUT_MATNR_CODE));
+        if (matnrConfig == null || StringUtils.isBlank(matnrConfig.getVal())) {
+            return;
+        }
+        Config qtyConfig = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.AUTO_PAKIN_QTY));
+        double autoQty = 1.0;
+        if (qtyConfig != null && StringUtils.isNotBlank(qtyConfig.getVal())) {
+            try {
+                autoQty = Double.parseDouble(qtyConfig.getVal().trim());
+                if (autoQty <= 0) autoQty = 1.0;
+            } catch (NumberFormatException e) {
+                // ignore
+            }
+        }
+        String matnrCode = matnrConfig.getVal().trim();
+        Matnr matnr = matnrService.getOne(new LambdaQueryWrapper<Matnr>().eq(Matnr::getCode, matnrCode));
+        if (matnr == null) {
+            log.warn("[RCS鍏ュ簱鐢宠-鑷姩缁勬墭] 鐗╂枡涓嶅瓨鍦�: {}", matnrCode);
+            return;
+        }
+        List<PakinItem> pakinItems = new ArrayList<>();
+        PakinItem pi = new PakinItem();
+        pi.setMatnrId(matnr.getId());
+        pi.setReceiptQty(autoQty);
+        pi.setAsnCode(null);
+        pi.setId(null);
+        pakinItems.add(pi);
+        WaitPakinParam param = new WaitPakinParam();
+        param.setBarcode(barcode);
+        param.setItems(pakinItems);
+        WaitPakin waitPakin;
+        try {
+            waitPakin = mobileService.mergeItems(param, 1L);
+        } catch (Exception e) {
+            log.warn("[RCS鍏ュ簱鐢宠-鑷姩缁勬墭] 缁勬墭澶辫触, barcode={}: {}", barcode, e.getMessage());
+            return;
+        }
+        String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_ASN_ORDER, null);
+        if (StringUtils.isBlank(ruleCode)) {
+            log.warn("[RCS鍏ュ簱鐢宠-鑷姩缁勬墭] 鍏ュ簱鍗曠紪鐮佽鍒欐湭閰嶇疆");
+            return;
+        }
+        WkOrder order = new WkOrder();
+        order.setCode(ruleCode)
+                .setType(OrderType.ORDER_IN.type)
+                .setExceStatus(AsnExceStatus.ASN_EXCE_STATUS_UN_EXCE.val)
+                .setAnfme(autoQty)
+                .setWorkQty(0.0)
+                .setQty(0.0)
+                .setCreateBy(1L)
+                .setUpdateBy(1L);
+        if (!asnOrderService.save(order)) {
+            throw new CoolException("鍏ュ簱涓诲崟淇濆瓨澶辫触");
+        }
+        WkOrderItem orderItem = new WkOrderItem();
+        orderItem.setOrderId(order.getId())
+                .setOrderCode(order.getCode())
+                .setMatnrId(matnr.getId())
+                .setMatnrCode(matnr.getCode())
+                .setMaktx(matnr.getName())
+                .setAnfme(autoQty)
+                .setWorkQty(0.0)
+                .setQty(0.0)
+                .setStockUnit(matnr.getStockUnit() != null ? matnr.getStockUnit() : "涓�")
+                .setPurUnit(matnr.getPurUnit() != null ? matnr.getPurUnit() : "涓�")
+                .setFieldsIndex(matnr.getFieldsIndex())
+                .setCreateBy(1L)
+                .setUpdateBy(1L);
+        if (!asnOrderItemService.save(orderItem)) {
+            throw new CoolException("鍏ュ簱鏄庣粏淇濆瓨澶辫触");
+        }
+        waitPakinItemService.update(new LambdaUpdateWrapper<WaitPakinItem>()
+                .eq(WaitPakinItem::getPakinId, waitPakin.getId())
+                .set(WaitPakinItem::getAsnId, order.getId())
+                .set(WaitPakinItem::getAsnCode, order.getCode())
+                .set(WaitPakinItem::getAsnItemId, orderItem.getId()));
+        log.info("[RCS鍏ュ簱鐢宠-鑷姩缁勬墭] 宸茬粍鎵樺苟鐢熸垚鍏ュ簱鍗�: {}, barcode: {}, 鐗╂枡: {}, 鏁伴噺: {}", order.getCode(), barcode, matnrCode, autoQty);
+    }
+
+    /**
      * 楠岃瘉璁惧绔欑偣
      */
     private DeviceSite validateDeviceSite(TaskInParam param) {
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/WkOrderController.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/WkOrderController.java
index 70e7a28..eca93c6 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/WkOrderController.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/WkOrderController.java
@@ -57,7 +57,9 @@
         QueryWrapper<WkOrder> queryWrapper = pageParam.buildWrapper(true);
         List<String> asList = Arrays.asList(OrderType.ORDER_IN.type);
         queryWrapper.in("type", asList);
-        return R.ok().add(asnOrderService.page(pageParam, queryWrapper));
+        Page<WkOrder> pageResult = asnOrderService.page(pageParam, queryWrapper);
+        asnOrderService.fillPalletQty(pageResult.getRecords());
+        return R.ok().add(pageResult);
     }
 
     @ApiOperation("鑾峰彇棣栭〉琛ㄥご鏁版嵁")
@@ -84,14 +86,20 @@
     @PreAuthorize("hasAuthority('manager:asnOrder:list')")
     @PostMapping({"/asnOrder/many/{ids}", "/asnOrders/many/{ids}"})
     public R many(@PathVariable Long[] ids) {
-        return R.ok().add(asnOrderService.listByIds(Arrays.asList(ids)));
+        List<WkOrder> list = asnOrderService.listByIds(Arrays.asList(ids));
+        asnOrderService.fillPalletQty(list);
+        return R.ok().add(list);
     }
 
     @PreAuthorize("hasAuthority('manager:asnOrder:list')")
     @OperationLog("琛ㄥ崟鏌ヨ")
     @GetMapping("/asnOrder/{id}")
     public R get(@PathVariable("id") Long id) {
-        return R.ok().add(asnOrderService.getById(id));
+        WkOrder order = asnOrderService.getById(id);
+        if (order != null) {
+            asnOrderService.fillPalletQty(Collections.singletonList(order));
+        }
+        return R.ok().add(order);
     }
 
     @PreAuthorize("hasAuthority('manager:asnOrder:save')")
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/WkOrderItemController.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/WkOrderItemController.java
index e2c3536..9a603f2 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/WkOrderItemController.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/WkOrderItemController.java
@@ -57,6 +57,7 @@
                 record.setExtendFields(fields);
             }
         }
+        asnOrderItemService.fillPalletQty(records);
         page.setRecords(records);
         return R.ok(page);
     }
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/params/WaitPakinParam.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/params/WaitPakinParam.java
index 9facf84..583caf6 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/params/WaitPakinParam.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/params/WaitPakinParam.java
@@ -25,5 +25,8 @@
     @ApiModelProperty("缁勬嫋绫诲瀷{null: 缁勬嫋, defective: 涓嶈壇鍝亇")
     private String type;
 
+    @ApiModelProperty("鏄惁鍗婄锛歵rue 鏃跺悓涓�鏂欑鐮佸彲缁х画缁勬墭杩藉姞锛宖alse 鏃舵枡绠辩爜宸茬粍鎵樺垯涓嶅彲鍐嶇敤")
+    private Boolean isHalf;
+
 }
 
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/WarehouseAreasItem.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/WarehouseAreasItem.java
index 0c62bc5..9529e9a 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/WarehouseAreasItem.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/WarehouseAreasItem.java
@@ -229,6 +229,11 @@
     @TableField(exist = false)
     private Map<String, String> extendFields;
 
+    /** 鍙粍鐩樻暟閲� = 璁″垝(anfme) - 宸茬粍鎵�(workQty) - 宸蹭笂鏋�(qty)锛屼粎缁勭洏鏄庣粏鎺ュ彛杩斿洖鏃跺~鍏咃紝渚涘墠绔洿鎺ュ睍绀� */
+    @ApiModelProperty(value = "鍙粍鐩樻暟閲忥紙璁″垝-宸茬粍鎵�-宸蹭笂鏋讹級")
+    @TableField(exist = false)
+    private Double availablePalletQty;
+
     /**
      * 澶囨敞
      */
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/WkOrder.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/WkOrder.java
index c15aafd..455da9f 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/WkOrder.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/WkOrder.java
@@ -96,6 +96,11 @@
     @ApiModelProperty(value = "宸叉敹鏁伴噺")
     private Double qty;
 
+    /** 缁勬墭鏁伴噺锛堥潪鎸佷箙鍖栵紝鍒楄〃灞曠ず鐢細璇ュ崟涓� WaitPakinItem.anfme 姹囨�伙級 */
+    @ApiModelProperty(value = "缁勬墭鏁伴噺")
+    @com.baomidou.mybatisplus.annotation.TableField(exist = false)
+    private Double palletQty;
+
     /**
      * 鐗╂祦鍗曞彿
      */
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/WkOrderItem.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/WkOrderItem.java
index 4c19413..c39cd58 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/WkOrderItem.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/WkOrderItem.java
@@ -128,6 +128,11 @@
     @ApiModelProperty(value= "閫佽揣鏁伴噺")
     private Double anfme;
 
+    /** 缁勬墭鏁伴噺锛堥潪鎸佷箙鍖栵紝鍒楄〃灞曠ず锛氳鏄庣粏 WaitPakinItem.anfme 姹囨�伙級 */
+    @ApiModelProperty(value = "缁勬墭鏁伴噺")
+    @TableField(exist = false)
+    private Double palletQty;
+
     /**
      * 搴撳瓨鍗曚綅
      */
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/AsnExceStatus.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/AsnExceStatus.java
index 2a08c0b..cc93b8a 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/AsnExceStatus.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/AsnExceStatus.java
@@ -9,12 +9,12 @@
  */
 public enum AsnExceStatus {
 
-    // ASN/鍏ュ簱鍗曟墽琛岀姸鎬侊紙鏂伴『搴忥級锛氭湭鎵ц(缁勬墭) 鈫� 浠诲姟鎵ц涓� 鈫� 宸插畬鎴�
+    // ASN/鍏ュ簱鍗曟墽琛岀姸鎬侊細鏈墽琛�(缁勬墭) 鈫� 浠诲姟鎵ц涓� 鈫� 宸插畬鎴�
     ASN_EXCE_STATUS_UN_EXCE("0", "鏈墽琛�"),
-    /** @deprecated 宸插仠鐢紝鏂版祦绋嬩笉鍐嶄娇鐢� */
+
     ASN_EXCE_STATUS_EXCE_ING("1", "鎵ц涓�"),
-    /** @deprecated 宸插仠鐢紝鏂版祦绋嬩笉鍐嶄娇鐢� */
     ASN_EXCE_STATUS_RECEIPT_DONE("2", "鏀惰揣瀹屾垚"),
+
     ASN_EXCE_STATUS_TASK_EXCE("3", "浠诲姟鎵ц涓�"),
     /** 宸插畬鎴愶細鏁村崟鍏ㄦ祦绋嬬粨鏉燂紙鏀惰揣+缁勬墭+涓婃灦/鍏ュ簱浠诲姟绛夛級锛屽彲褰掓。鍘嗗彶銆佷笂鎶� ERP锛涚敱缁勬墭/浠诲姟瀹氭椂鎴栫Щ鍘嗗彶鏃惰缃� */
     ASN_EXCE_STATUS_TASK_DONE("4", "宸插畬鎴�"),
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/MaterialAutoSchedules.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/MaterialAutoSchedules.java
new file mode 100644
index 0000000..4c56377
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/MaterialAutoSchedules.java
@@ -0,0 +1,339 @@
+package com.vincent.rsf.server.manager.schedules;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.vincent.rsf.framework.exception.CoolException;
+import com.vincent.rsf.server.manager.controller.params.OutStockToTaskParams;
+import com.vincent.rsf.server.manager.controller.params.PakinItem;
+import com.vincent.rsf.server.manager.controller.params.WaitPakinParam;
+import com.vincent.rsf.server.manager.entity.*;
+import com.vincent.rsf.server.manager.enums.AsnExceStatus;
+import com.vincent.rsf.server.manager.enums.OrderType;
+import com.vincent.rsf.server.manager.enums.OrderWorkType;
+import com.vincent.rsf.server.manager.enums.TaskStsType;
+import com.vincent.rsf.server.manager.service.*;
+import com.vincent.rsf.server.manager.utils.LocManageUtil;
+import com.vincent.rsf.server.system.constant.GlobalConfigCode;
+import com.vincent.rsf.server.system.constant.SerialRuleCode;
+import com.vincent.rsf.server.system.entity.Config;
+import com.vincent.rsf.server.system.service.ConfigService;
+import com.vincent.rsf.server.system.utils.SerialRuleUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 鎸囧畾鐗╂枡鑷姩鍖栧畾鏃朵换鍔★細鍙厤缃墿鏂欑紪鐮佸悗锛�
+ * 1锛夋湁搴撳瓨鏃惰嚜鍔ㄧ敓鎴愬叏鐗堝嚭搴撳崟锛�
+ * 2锛夎鐗╂枡鍑哄簱鍗曡嚜鍔ㄤ笅鍙戜换鍔★紱
+ * 3锛塕CS 鍏ュ簱閫氱煡鏃讹紙鍙�夛級鑷姩缁勬墭锛屾暟閲忓彲閰嶇疆銆�
+ */
+@Slf4j
+@Component
+public class MaterialAutoSchedules {
+
+    private static final Long SYSTEM_USER_ID = 1L;
+    private static final String DEFAULT_SITE_NO = "1001";
+
+    @Autowired
+    private ConfigService configService;
+    @Autowired
+    private OutStockService outStockService;
+    @Autowired
+    private AsnOrderItemService asnOrderItemService;
+    @Autowired
+    private LocItemService locItemService;
+    @Autowired
+    private LocService locService;
+    @Autowired
+    private MatnrService matnrService;
+    @Autowired
+    private TaskService taskService;
+    @Autowired
+    private TaskItemService taskItemService;
+    @Autowired
+    private com.vincent.rsf.server.api.service.MobileService mobileService;
+    @Autowired
+    private AsnOrderService asnOrderService;
+    @Autowired
+    private WaitPakinItemService waitPakinItemService;
+
+    /**
+     * 瀹氭椂浠诲姟1锛氭寚瀹氱墿鏂欐湁搴撳瓨鏃惰嚜鍔ㄧ敓鎴愬叏鐗堝嚭搴撳崟锛堟瘡 2 鍒嗛挓锛�
+     * 閰嶇疆锛欰UTO_FULL_OUT_MATNR_CODE锛堢墿鏂欑紪鐮侊級銆丄UTO_FULL_OUT_ENABLED锛坱rue 鍚敤锛�
+     */
+    @Scheduled(cron = "0 0/2 * * * ?")
+    @Transactional(rollbackFor = Exception.class)
+    public void autoCreateFullOutOrder() {
+        Config enabledConfig = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.AUTO_FULL_OUT_ENABLED));
+        if (enabledConfig == null || !Boolean.parseBoolean(enabledConfig.getVal())) {
+            return;
+        }
+        Config matnrConfig = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.AUTO_FULL_OUT_MATNR_CODE));
+        if (matnrConfig == null || StringUtils.isBlank(matnrConfig.getVal())) {
+            return;
+        }
+        String matnrCode = matnrConfig.getVal().trim();
+        Matnr matnr = matnrService.getOne(new LambdaQueryWrapper<Matnr>().eq(Matnr::getCode, matnrCode));
+        if (matnr == null) {
+            log.warn("[鑷姩鍏ㄧ増鍑哄簱鍗昡 鐗╂枡涓嶅瓨鍦�: {}", matnrCode);
+            return;
+        }
+        // 宸叉湁璇ョ墿鏂欐湭涓嬪彂鐨勫嚭搴撳崟鍒欐湰杞笉鍐嶇敓鎴愶紝绛変笅鍙戝畬鍚庡啀鐢熸垚锛堥伩鍏嶉噸澶嶏級
+        List<Long> initOrderIds = outStockService.list(new LambdaQueryWrapper<WkOrder>()
+                        .eq(WkOrder::getType, OrderType.ORDER_OUT.type)
+                        .eq(WkOrder::getExceStatus, AsnExceStatus.OUT_STOCK_STATUS_TASK_INIT.val))
+                .stream().map(WkOrder::getId).collect(Collectors.toList());
+        if (!initOrderIds.isEmpty()) {
+            long hasMatnr = asnOrderItemService.count(new LambdaQueryWrapper<WkOrderItem>()
+                    .in(WkOrderItem::getOrderId, initOrderIds)
+                    .eq(WkOrderItem::getMatnrCode, matnrCode));
+            if (hasMatnr > 0) {
+                return;
+            }
+        }
+        // 鎸夊簱浣嶅垎缁勶細璇ョ墿鏂欍�佸簱浣嶇姸鎬佷负 F 鐨勫湪搴擄紱姣忎釜搴撲綅鍚勭敓鎴愪竴寮犲嚭搴撳崟
+        List<LocItem> items = locItemService.list(new LambdaQueryWrapper<LocItem>()
+                .eq(LocItem::getMatnrCode, matnrCode)
+                .gt(LocItem::getAnfme, 0));
+        if (items.isEmpty()) {
+            return;
+        }
+        Map<Long, List<LocItem>> byLocId = items.stream().collect(Collectors.groupingBy(LocItem::getLocId));
+        for (Long locId : byLocId.keySet()) {
+            Loc loc = locService.getById(locId);
+            if (loc == null || !"F".equals(loc.getUseStatus())) {
+                continue;
+            }
+            List<LocItem> locItems = byLocId.get(locId);
+            double sumQty = locItems.stream().mapToDouble(li -> li.getAnfme() != null ? li.getAnfme() : 0).sum();
+            if (sumQty <= 0) continue;
+            try {
+                String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_OUT_STOCK_CODE, null);
+                if (StringUtils.isBlank(ruleCode)) {
+                    log.warn("[鑷姩鍏ㄧ増鍑哄簱鍗昡 鍑哄簱鍗曠紪鐮佽鍒欐湭閰嶇疆");
+                    break;
+                }
+                WkOrder order = new WkOrder();
+                order.setCode(ruleCode)
+                        .setType(OrderType.ORDER_OUT.type)
+                        .setWkType(OrderWorkType.ORDER_WORK_TYPE_STOCK_OUT.type)
+                        .setExceStatus(AsnExceStatus.OUT_STOCK_STATUS_TASK_INIT.val)
+                        .setAnfme(sumQty)
+                        .setWorkQty(0.0)
+                        .setQty(0.0)
+                        .setCreateBy(SYSTEM_USER_ID)
+                        .setUpdateBy(SYSTEM_USER_ID);
+                if (!outStockService.save(order)) {
+                    throw new CoolException("鍑哄簱涓诲崟淇濆瓨澶辫触");
+                }
+                LocItem first = locItems.get(0);
+                WkOrderItem orderItem = new WkOrderItem();
+                orderItem.setOrderId(order.getId())
+                        .setOrderCode(order.getCode())
+                        .setMatnrId(matnr.getId())
+                        .setMatnrCode(matnr.getCode())
+                        .setMaktx(matnr.getName())
+                        .setAnfme(sumQty)
+                        .setWorkQty(0.0)
+                        .setQty(0.0)
+                        .setStockUnit(first.getUnit() != null ? first.getUnit() : "涓�")
+                        .setPurUnit(first.getUnit() != null ? first.getUnit() : "涓�")
+                        .setSplrBatch(first.getSplrBatch())
+                        .setBatch(first.getBatch())
+                        .setFieldsIndex(first.getFieldsIndex())
+                        .setCreateBy(SYSTEM_USER_ID)
+                        .setUpdateBy(SYSTEM_USER_ID);
+                if (!asnOrderItemService.save(orderItem)) {
+                    throw new CoolException("鍑哄簱鏄庣粏淇濆瓨澶辫触");
+                }
+                log.info("[鑷姩鍏ㄧ増鍑哄簱鍗昡 宸茬敓鎴愬嚭搴撳崟: {}, 搴撲綅: {}, 鐗╂枡: {}, 鏁伴噺: {}", order.getCode(), loc.getCode(), matnrCode, sumQty);
+            } catch (Exception e) {
+                log.error("[鑷姩鍏ㄧ増鍑哄簱鍗昡 鐢熸垚澶辫触, 搴撲綅: {}, 鐗╂枡: {}", loc.getCode(), matnrCode, e);
+            }
+        }
+    }
+
+    /**
+     * 瀹氭椂浠诲姟2锛氳鐗╂枡鍑哄簱鍗曡嚜鍔ㄤ笅鍙戜换鍔★紙姣� 1 鍒嗛挓锛�
+     * 閰嶇疆锛欰UTO_FULL_OUT_DISPATCH_ENABLED锛坱rue 鍚敤锛夈�丄UTO_FULL_OUT_MATNR_CODE
+     */
+    @Scheduled(cron = "0 0/1 * * * ?")
+    @Transactional(rollbackFor = Exception.class)
+    public void autoDispatchOutTask() {
+        Config enabledConfig = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.AUTO_FULL_OUT_DISPATCH_ENABLED));
+        if (enabledConfig == null || !Boolean.parseBoolean(enabledConfig.getVal())) {
+            return;
+        }
+        Config matnrConfig = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.AUTO_FULL_OUT_MATNR_CODE));
+        if (matnrConfig == null || StringUtils.isBlank(matnrConfig.getVal())) {
+            return;
+        }
+        String matnrCode = matnrConfig.getVal().trim();
+        List<WkOrder> orders = outStockService.list(new LambdaQueryWrapper<WkOrder>()
+                .eq(WkOrder::getType, OrderType.ORDER_OUT.type)
+                .eq(WkOrder::getExceStatus, AsnExceStatus.OUT_STOCK_STATUS_TASK_INIT.val));
+        for (WkOrder order : orders) {
+            List<WkOrderItem> orderItems = asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>()
+                    .eq(WkOrderItem::getOrderId, order.getId())
+                    .eq(WkOrderItem::getMatnrCode, matnrCode));
+            if (orderItems.isEmpty()) continue;
+            List<OutStockToTaskParams> paramsList = new ArrayList<>();
+            for (WkOrderItem oi : orderItems) {
+                double remaining = (oi.getAnfme() != null ? oi.getAnfme() : 0) - (oi.getWorkQty() != null ? oi.getWorkQty() : 0);
+                if (remaining <= 0) continue;
+                String batch = oi.getSplrBatch() != null ? oi.getSplrBatch() : oi.getBatch();
+                List<LocItem> locItems = LocManageUtil.getFirstInFirstOutItemList(oi.getMatnrCode(), batch, remaining);
+                for (LocItem locItem : locItems) {
+                    if (remaining <= 0) break;
+                    Loc loc = locService.getById(locItem.getLocId());
+                    if (loc == null || !"F".equals(loc.getUseStatus())) continue;
+                    double outQty = Math.min(remaining, locItem.getAnfme() != null ? locItem.getAnfme() : 0);
+                    if (outQty <= 0) continue;
+                    OutStockToTaskParams param = new OutStockToTaskParams();
+                    param.setId(locItem.getId());
+                    param.setLocCode(loc.getCode());
+                    param.setOutQty(outQty);
+                    param.setSiteNo(DEFAULT_SITE_NO);
+                    param.setBatch(locItem.getBatch());
+                    paramsList.add(param);
+                    remaining -= outQty;
+                }
+            }
+            if (paramsList.isEmpty()) continue;
+            try {
+                outStockService.genOutStockTask(paramsList, SYSTEM_USER_ID, order.getId());
+                List<TaskItem> taskItems = taskItemService.list(new LambdaQueryWrapper<TaskItem>().eq(TaskItem::getSourceId, order.getId()));
+                if (!taskItems.isEmpty()) {
+                    Set<Long> taskIds = taskItems.stream().map(TaskItem::getTaskId).collect(Collectors.toSet());
+                    List<Task> tasks = taskService.listByIds(taskIds).stream()
+                            .filter(t -> TaskStsType.GENERATE_OUT.id.equals(t.getTaskStatus()))
+                            .collect(Collectors.toList());
+                    if (!tasks.isEmpty()) {
+                        taskService.pubTaskToWcs(tasks);
+                        log.info("[鑷姩涓嬪彂浠诲姟] 鍑哄簱鍗�: {} 宸蹭笅鍙戜换鍔�", order.getCode());
+                    }
+                }
+            } catch (Exception e) {
+                log.error("[鑷姩涓嬪彂浠诲姟] 鍑哄簱鍗�: {} 涓嬪彂澶辫触", order.getCode(), e);
+            }
+        }
+    }
+
+    /**
+     * 瀹氭椂浠诲姟3锛氭棤璁㈠崟缁勬墭 + 鑷姩鐢熸垚鍏ュ簱鍗曪紙浠呴拡瀵归厤缃墿鏂欙紝姣� 2 鍒嗛挓锛�
+     * 鍏堟寜閰嶇疆鐗╂枡涓庢暟閲忓仛鏃犺鍗曠粍鎵橈紝鍐嶇敓鎴愬叆搴撳崟骞跺叧鑱旂粍鎵樻槑缁嗭紝渚夸簬 RCS 鍏ュ簱闂幆銆�
+     * 閰嶇疆锛欰UTO_PAKIN_ON_ASN_ENABLED锛坱rue锛夈�丄UTO_FULL_OUT_MATNR_CODE銆丄UTO_PAKIN_QTY锛堟暟閲忥級
+     */
+    @Scheduled(cron = "0 0/2 * * * ?")
+    @Transactional(rollbackFor = Exception.class)
+    public void autoPakinOnInbound() {
+        Config enabledConfig = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.AUTO_PAKIN_ON_ASN_ENABLED));
+        if (enabledConfig == null || !Boolean.parseBoolean(enabledConfig.getVal())) {
+            return;
+        }
+        Config matnrConfig = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.AUTO_FULL_OUT_MATNR_CODE));
+        if (matnrConfig == null || StringUtils.isBlank(matnrConfig.getVal())) {
+            return;
+        }
+        Config qtyConfig = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.AUTO_PAKIN_QTY));
+        double autoQty = 1.0;
+        if (qtyConfig != null && StringUtils.isNotBlank(qtyConfig.getVal())) {
+            try {
+                autoQty = Double.parseDouble(qtyConfig.getVal().trim());
+                if (autoQty <= 0) autoQty = 1.0;
+            } catch (NumberFormatException e) {
+                // ignore
+            }
+        }
+        String matnrCode = matnrConfig.getVal().trim();
+        Matnr matnr = matnrService.getOne(new LambdaQueryWrapper<Matnr>().eq(Matnr::getCode, matnrCode));
+        if (matnr == null) {
+            log.warn("[鏃犺鍗曡嚜鍔ㄧ粍鎵榏 鐗╂枡涓嶅瓨鍦�: {}", matnrCode);
+            return;
+        }
+        // 宸叉湁璇ョ墿鏂欐湭鎵ц鍏ュ簱鍗曞垯鏈疆涓嶇户缁敓鎴愶紝閬垮厤鍫嗙Н
+        List<Long> initAsnIds = asnOrderService.list(new LambdaQueryWrapper<WkOrder>()
+                        .eq(WkOrder::getType, OrderType.ORDER_IN.type)
+                        .eq(WkOrder::getExceStatus, AsnExceStatus.ASN_EXCE_STATUS_UN_EXCE.val))
+                .stream().map(WkOrder::getId).collect(Collectors.toList());
+        if (!initAsnIds.isEmpty()) {
+            long hasMatnr = asnOrderItemService.count(new LambdaQueryWrapper<WkOrderItem>()
+                    .in(WkOrderItem::getOrderId, initAsnIds)
+                    .eq(WkOrderItem::getMatnrCode, matnrCode));
+            if (hasMatnr > 0) {
+                return;
+            }
+        }
+        // 1锛夋棤璁㈠崟缁勬墭锛氫粎鐗╂枡 + 鏁伴噺锛屼笉浼� asnCode/id
+        List<PakinItem> pakinItems = new ArrayList<>();
+        PakinItem pi = new PakinItem();
+        pi.setMatnrId(matnr.getId());
+        pi.setReceiptQty(autoQty);
+        pi.setAsnCode(null);
+        pi.setId(null);
+        pakinItems.add(pi);
+        String barcode = "AUTO-PAKIN-" + System.currentTimeMillis();
+        WaitPakinParam param = new WaitPakinParam();
+        param.setBarcode(barcode);
+        param.setItems(pakinItems);
+        WaitPakin waitPakin;
+        try {
+            waitPakin = mobileService.mergeItems(param, SYSTEM_USER_ID);
+        } catch (Exception e) {
+            log.warn("[鏃犺鍗曡嚜鍔ㄧ粍鎵榏 缁勬墭澶辫触: {}", e.getMessage());
+            return;
+        }
+        // 2锛夎嚜鍔ㄧ敓鎴愬叆搴撳崟锛堜竴鏉℃槑缁嗭紝閰嶇疆鐗╂枡 + 鏁伴噺锛�
+        String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_ASN_ORDER, null);
+        if (StringUtils.isBlank(ruleCode)) {
+            log.warn("[鏃犺鍗曡嚜鍔ㄧ粍鎵榏 鍏ュ簱鍗曠紪鐮佽鍒欐湭閰嶇疆");
+            return;
+        }
+        WkOrder order = new WkOrder();
+        order.setCode(ruleCode)
+                .setType(OrderType.ORDER_IN.type)
+                .setExceStatus(AsnExceStatus.ASN_EXCE_STATUS_UN_EXCE.val)
+                .setAnfme(autoQty)
+                .setWorkQty(0.0)
+                .setQty(0.0)
+                .setCreateBy(SYSTEM_USER_ID)
+                .setUpdateBy(SYSTEM_USER_ID);
+        if (!asnOrderService.save(order)) {
+            throw new CoolException("鍏ュ簱涓诲崟淇濆瓨澶辫触");
+        }
+        WkOrderItem orderItem = new WkOrderItem();
+        orderItem.setOrderId(order.getId())
+                .setOrderCode(order.getCode())
+                .setMatnrId(matnr.getId())
+                .setMatnrCode(matnr.getCode())
+                .setMaktx(matnr.getName())
+                .setAnfme(autoQty)
+                .setWorkQty(0.0)
+                .setQty(0.0)
+                .setStockUnit(matnr.getStockUnit() != null ? matnr.getStockUnit() : "涓�")
+                .setPurUnit(matnr.getPurUnit() != null ? matnr.getPurUnit() : "涓�")
+                .setFieldsIndex(matnr.getFieldsIndex())
+                .setCreateBy(SYSTEM_USER_ID)
+                .setUpdateBy(SYSTEM_USER_ID);
+        if (!asnOrderItemService.save(orderItem)) {
+            throw new CoolException("鍏ュ簱鏄庣粏淇濆瓨澶辫触");
+        }
+        // 3锛夊叧鑱旂粍鎵樻槑缁嗗埌鍏ュ簱鍗曪紙asnId / asnCode / asnItemId锛�
+        boolean updated = waitPakinItemService.update(new LambdaUpdateWrapper<WaitPakinItem>()
+                .eq(WaitPakinItem::getPakinId, waitPakin.getId())
+                .set(WaitPakinItem::getAsnId, order.getId())
+                .set(WaitPakinItem::getAsnCode, order.getCode())
+                .set(WaitPakinItem::getAsnItemId, orderItem.getId()));
+        if (!updated) {
+            log.warn("[鏃犺鍗曡嚜鍔ㄧ粍鎵榏 缁勬墭鏄庣粏鍏宠仈鍏ュ簱鍗曞け璐�, pakinId={}", waitPakin.getId());
+        }
+        log.info("[鏃犺鍗曡嚜鍔ㄧ粍鎵榏 宸茬粍鎵樺苟鐢熸垚鍏ュ簱鍗�: {}, 鐗╂枡: {}, 鏁伴噺: {}", order.getCode(), matnrCode, autoQty);
+    }
+}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/ScheduleJobs.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/ScheduleJobs.java
index 9eaaa0e..de355f0 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/ScheduleJobs.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/ScheduleJobs.java
@@ -69,156 +69,133 @@
     @Autowired
     private FieldsItemService fieldsItemService;
 
-//    /**
-//     * @author Ryan
-//     * @date 2025/5/9
-//     * @description: 鐩存帴缁勬墭寮�鍏充负true锛屽皢鏀惰揣鍗曠洿鎺ュ姞鍏ヤ复鏃跺簱瀛�
-//     * @version 1.0
-//     */
-//    @Scheduled(cron = "0/25 * * * * ?")
-//    @Transactional(rollbackFor = Exception.class)
-//    public synchronized void IgnoreReceipt() {
-//        Config config = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.DIRECT_WAIT_PAKIN));
-//        if (Objects.isNull(config)) {
-//            return;
-//        }
-//        if (!Boolean.parseBoolean(config.getVal())) {
-//            return;
-//        }
-//        //鑷姩鏀惰揣鍗�
-//        List<WkOrder> orders = asnOrderService.list(new LambdaQueryWrapper<WkOrder>()
-//                .eq(WkOrder::getType, OrderType.ORDER_IN.type)
-//                .eq(WkOrder::getExceStatus, AsnExceStatus.ASN_EXCE_STATUS_UN_EXCE.val));
-//         if (!orders.isEmpty()) {
-//            for (WkOrder order : orders) {
-//                if (order.getWkType().equals(OrderWorkType.ORDER_WORK_TYPE_OTHER_TERANSFER.type)) {
-//                    WkOrder one = outStockService.getOne(new LambdaQueryWrapper<WkOrder>()
-//                            .eq(WkOrder::getPoCode, order.getPoCode())
-//                            .eq(WkOrder::getWkType, OrderWorkType.ORDER_WORK_TYPE_STOCK_TERANSFER.type));
-//                    if (Objects.isNull(one)) {
-//                        throw new CoolException("鏁版嵁閿欒");
-//                    }
-//                    if (!one.getExceStatus().equals(AsnExceStatus.OUT_STOCK_STATUS_TASK_DONE.val)) {
-//                        continue;
-//                    }
-//                }
-//
-//                List<WkOrderItem> orderItems = asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, order.getId()));
-//                if (orderItems.isEmpty()) {
-//                    return;
-//                }
-//                // 鏀惰揣鍖哄凡鍋滅敤锛氫笉鍐嶅啓鍏ユ敹璐у尯锛屼粎鏇存柊鍗曟嵁鐘舵�佷笌鏁伴噺
-////                List<WarehouseAreas> receiptAreas = warehouseAreasService.list(new LambdaQueryWrapper<WarehouseAreas>()
-////                        .eq(WarehouseAreas::getType, WarehouseAreasType.WAREHOUSE_AREAS_TYPE_RECEIPT.type));
-////                WarehouseAreas receiptArea = receiptAreas.isEmpty() ? null : receiptAreas.get(0);
-////                List<WarehouseAreasItem> items = new ArrayList<>();
-//                for (WkOrderItem item : orderItems) {
-////                    Long areaId = receiptArea == null ? null : receiptArea.getId();
-////                    String areaName = receiptArea == null ? null : receiptArea.getName();
-////                    WarehouseAreasItem param = new WarehouseAreasItem();
-////                    BeanUtils.copyProperties(item, param);
-////                    param.setAsnCode(order.getCode()).setAsnId(order.getId());
-////                    if (areaId != null) {
-////                        param.setAreaId(areaId).setAreaName(areaName);
-////                    }
-////                    items.add(param);
-////                    Matnr matnr = matnrService.getOne(new LambdaQueryWrapper<Matnr>().eq(Matnr::getId, item.getMatnrId()));
-////                    if (Objects.isNull(matnr)) {
-////                        throw new CoolException("鐗╂枡涓嶅瓨鍦紒锛�");
-////                    }
-////                    if (receiptArea != null) {
-////                        try {
-////                            updateReceipt(receiptArea, item, order, matnr);
-////                        } catch (Exception e) {
-////                            throw new CoolException(e.getMessage());
-////                        }
-////                    }
-//                    if (!asnOrderItemService.update(new LambdaUpdateWrapper<WkOrderItem>().set(WkOrderItem::getQty, item.getAnfme()).eq(WkOrderItem::getId, item.getId()))) {
-//                        throw new CoolException("鏀惰揣鍗曟槑缁嗗畬鎴愭暟閲忎慨鏀瑰け璐ワ紒锛�");
-//                    }
-//                }
-////                if (!warehouseAreasItemService.saveBatch(items)) {
-////                    throw new CoolException("鏀惰揣鍗曚繚瀛樿嚦鏀惰揣鍖烘墽琛屽け璐ワ紒锛�");
-////                }
-//
-//                if (!asnOrderService.update(new LambdaUpdateWrapper<WkOrder>()
-//                        .set(WkOrder::getQty, order.getAnfme())
-//                        .set(WkOrder::getExceStatus, AsnExceStatus.ASN_EXCE_STATUS_RECEIPT_DONE.val)
-//                        .eq(WkOrder::getId, order.getId()))) {
-//                    throw new CoolException("鏀惰揣鍗曠姸鎬佷慨鏀瑰け璐ワ紒锛�");
-//                }
-//            }
-//        }
-//    }
-
-
-    /** 鏀惰揣鍖哄凡鍋滅敤锛屾柟娉曟暣浣撴敞閲�
-     * @author Ryan
-     * @date 2025/5/12
-     * @description: 鏀惰揣鍖哄簱瀛樻洿鏂�
+    /**
+     * 鑷姩鏀惰揣锛氫粎褰� DirectWaitPakin 閰嶇疆涓� true 鏃舵墽琛岋紝灏嗘湭鎵ц鍏ュ簱鍗曠洿鎺ユ敹璐у苟鍐欏叆鏀惰揣鍖猴紝鏇存柊鍗曟嵁鐘舵�佷负鏀惰揣瀹屾垚銆�
+     * 涓嶅奖鍝嶄簯浠揥MS鍏ュ簱鎺ュ彛锛�8.3 鍚屾鍗曪級涓庣粍鎵樻祦绋嬶紱鍏抽棴鏃朵笉鍋氫换浣曟搷浣溿��
      */
-//    @Transactional(rollbackFor = Exception.class)
-//    public void updateReceipt(WarehouseAreas areasItem, WkOrderItem orderItem, WkOrder wkOrder, Matnr matnr) throws Exception {
-//        Companys companys = new Companys();
-//        if (StringUtils.isNoneBlank(orderItem.getSplrCode())) {
-//            companys = companysService.getOne(new LambdaQueryWrapper<Companys>().eq(Companys::getCode, orderItem.getSplrCode()));
-//        }
-//        WarehouseAreasItem item = new WarehouseAreasItem();
-//        item.setTrackCode(orderItem.getBarcode())
-//                .setAreaName(areasItem.getName())
-//                .setAreaId(areasItem.getId())
-//                .setAsnItemId(orderItem.getId())
-//                .setAsnCode(wkOrder.getCode())
-//                .setAsnId(wkOrder.getId())
-//                .setProdTime(orderItem.getProdTime())
-//                .setPlatItemId(orderItem.getPlatItemId())
-//                .setPlatOrderCode(orderItem.getPlatOrderCode())
-//                .setPlatWorkCode(orderItem.getPlatWorkCode())
-//                .setProjectCode(orderItem.getProjectCode())
-//                .setSplrId(companys.getId())
-//                .setUnit(orderItem.getStockUnit())
-//                .setStockUnit(orderItem.getStockUnit())
-//                .setMatnrCode(matnr.getCode())
-//                .setAnfme(orderItem.getAnfme())
-//                .setMatnrId(matnr.getId())
-//                .setIsptResult(orderItem.getIsptResult())
-//                .setMaktx(matnr.getName())
-//                .setSplrBatch(orderItem.getSplrBatch())
-//                .setWeight(matnr.getWeight())
-//                .setFieldsIndex(orderItem.getFieldsIndex())
-//                .setShipperId(matnr.getShipperId());
-//        List<WarehouseAreasItem> warehousList = StringUtils.isNotBlank(orderItem.getFieldsIndex())
-//                ? warehouseAreasItemService.list(new LambdaQueryWrapper<WarehouseAreasItem>().eq(WarehouseAreasItem::getFieldsIndex, orderItem.getFieldsIndex()))
-//                : Collections.emptyList();
-//        WarehouseAreasItem warehousItem = warehousList.isEmpty() ? null : warehousList.get(0);
-//        if (!Objects.isNull(warehousItem)) {
-//            List<FieldsItem> fieldsList = fieldsItemService.list(new LambdaQueryWrapper<FieldsItem>()
-//                    .eq(FieldsItem::getUuid, orderItem.getFieldsIndex()).last("LIMIT 1"));
-//            FieldsItem fieldsItem = fieldsList.isEmpty() ? null : fieldsList.get(0);
-//            if (!Objects.isNull(fieldsItem)) {
-//                throw new CoolException("绁ㄥ彿锛�" + fieldsItem.getValue() + "宸插湪鏀惰揣鍖猴紝涓嶅彲鎺ㄩ�佺浉褰撶エ鍙锋暟鎹�傝鑱旂郴绠$悊鍛橈紒锛�" );
-//            }
-//        }
-//        LambdaQueryWrapper<WarehouseAreasItem> queryWrapper = new LambdaQueryWrapper<WarehouseAreasItem>()
-//                .eq(WarehouseAreasItem::getMatnrCode, orderItem.getMatnrCode())
-//                .eq(!Cools.isEmpty(orderItem.getFieldsIndex()), WarehouseAreasItem::getFieldsIndex, orderItem.getFieldsIndex())
-//                .eq(WarehouseAreasItem::getAsnCode, orderItem.getOrderCode())
-//                .eq(StringUtils.isNotBlank(orderItem.getSplrBatch()), WarehouseAreasItem::getSplrBatch, orderItem.getSplrBatch());
-//        if (Objects.isNull(orderItem.getIsptResult())) {
-//            queryWrapper.isNull(WarehouseAreasItem::getIsptResult);
-//        } else {
-//            queryWrapper.eq(WarehouseAreasItem::getIsptResult, orderItem.getIsptResult());
-//        }
-//        List<WarehouseAreasItem> serviceList = warehouseAreasItemService.list(queryWrapper);
-//        WarehouseAreasItem serviceOne = serviceList.isEmpty() ? null : serviceList.get(0);
-//        if (!Objects.isNull(serviceOne)) {
-//            item.setId(serviceOne.getId());
-//            item.setAnfme(orderItem.getAnfme());
-//        }
-//        if (!warehouseAreasItemService.saveOrUpdate(item)) {
-//            throw new CoolException("鏀惰揣澶辫触锛侊紒");
-//        }
-//    }
+    @Scheduled(cron = "0/25 * * * * ?")
+    @Transactional(rollbackFor = Exception.class)
+    public synchronized void IgnoreReceipt() {
+        Config config = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.DIRECT_WAIT_PAKIN));
+        if (Objects.isNull(config) || !Boolean.parseBoolean(config.getVal())) {
+            return;
+        }
+        List<WkOrder> orders = asnOrderService.list(new LambdaQueryWrapper<WkOrder>()
+                .eq(WkOrder::getType, OrderType.ORDER_IN.type)
+                .eq(WkOrder::getExceStatus, AsnExceStatus.ASN_EXCE_STATUS_UN_EXCE.val));
+        if (orders.isEmpty()) {
+            return;
+        }
+        WarehouseAreas receiptArea = warehouseAreasService.getOne(new LambdaQueryWrapper<WarehouseAreas>()
+                .eq(WarehouseAreas::getType, WarehouseAreasType.WAREHOUSE_AREAS_TYPE_RECEIPT.type), false);
+        for (WkOrder order : orders) {
+            if (OrderWorkType.ORDER_WORK_TYPE_OTHER_TERANSFER.type.equals(order.getWkType())) {
+                WkOrder one = outStockService.getOne(new LambdaQueryWrapper<WkOrder>()
+                        .eq(WkOrder::getPoId, order.getPoId())
+                        .eq(WkOrder::getWkType, OrderWorkType.ORDER_WORK_TYPE_STOCK_TERANSFER.type));
+                if (Objects.isNull(one)) {
+                    throw new CoolException("鏁版嵁閿欒");
+                }
+                if (!one.getExceStatus().equals(AsnExceStatus.OUT_STOCK_STATUS_TASK_DONE.val)) {
+                    continue;
+                }
+            }
+            List<WkOrderItem> orderItems = asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, order.getId()));
+            if (orderItems.isEmpty()) {
+                continue;
+            }
+            for (WkOrderItem item : orderItems) {
+                if (receiptArea != null) {
+                    Matnr matnr = matnrService.getOne(new LambdaQueryWrapper<Matnr>().eq(Matnr::getId, item.getMatnrId()));
+                    if (Objects.isNull(matnr)) {
+                        throw new CoolException("鐗╂枡涓嶅瓨鍦紒锛�");
+                    }
+                    try {
+                        updateReceipt(receiptArea, item, order, matnr);
+                    } catch (Exception e) {
+                        throw new CoolException(e.getMessage());
+                    }
+                }
+                if (!asnOrderItemService.update(new LambdaUpdateWrapper<WkOrderItem>().set(WkOrderItem::getQty, item.getAnfme()).eq(WkOrderItem::getId, item.getId()))) {
+                    throw new CoolException("鏀惰揣鍗曟槑缁嗗畬鎴愭暟閲忎慨鏀瑰け璐ワ紒锛�");
+                }
+            }
+            if (!asnOrderService.update(new LambdaUpdateWrapper<WkOrder>()
+                    .set(WkOrder::getQty, order.getAnfme())
+                    .set(WkOrder::getExceStatus, AsnExceStatus.ASN_EXCE_STATUS_RECEIPT_DONE.val)
+                    .eq(WkOrder::getId, order.getId()))) {
+                throw new CoolException("鏀惰揣鍗曠姸鎬佷慨鏀瑰け璐ワ紒锛�");
+            }
+        }
+    }
+
+    /**
+     * 鏀惰揣鍖哄簱瀛樻洿鏂帮紙浠� DirectWaitPakin 鍚敤鏃剁敱 IgnoreReceipt 璋冪敤锛�
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public void updateReceipt(WarehouseAreas areasItem, WkOrderItem orderItem, WkOrder wkOrder, Matnr matnr) throws Exception {
+        Companys companys = new Companys();
+        if (StringUtils.isNoneBlank(orderItem.getSplrCode())) {
+            companys = companysService.getOne(new LambdaQueryWrapper<Companys>().eq(Companys::getCode, orderItem.getSplrCode()));
+        }
+        if (Objects.isNull(companys)) {
+            companys = new Companys();
+        }
+        WarehouseAreasItem item = new WarehouseAreasItem();
+        item.setTrackCode(orderItem.getBarcode())
+                .setAreaName(areasItem.getName())
+                .setAreaId(areasItem.getId())
+                .setAsnItemId(orderItem.getId())
+                .setAsnCode(wkOrder.getCode())
+                .setAsnId(wkOrder.getId())
+                .setProdTime(orderItem.getProdTime())
+                .setPlatItemId(orderItem.getPlatItemId())
+                .setPlatOrderCode(orderItem.getPlatOrderCode())
+                .setPlatWorkCode(orderItem.getPlatWorkCode())
+                .setProjectCode(orderItem.getProjectCode())
+                .setSplrId(companys.getId())
+                .setUnit(orderItem.getStockUnit())
+                .setStockUnit(orderItem.getStockUnit())
+                .setMatnrCode(matnr.getCode())
+                .setAnfme(orderItem.getAnfme())
+                .setMatnrId(matnr.getId())
+                .setIsptResult(orderItem.getIsptResult())
+                .setMaktx(matnr.getName())
+                .setSplrBatch(orderItem.getSplrBatch())
+                .setWeight(matnr.getWeight())
+                .setFieldsIndex(orderItem.getFieldsIndex())
+                .setShipperId(matnr.getShipperId());
+        if (StringUtils.isNotBlank(orderItem.getFieldsIndex())) {
+            List<WarehouseAreasItem> warehousList = warehouseAreasItemService.list(new LambdaQueryWrapper<WarehouseAreasItem>().eq(WarehouseAreasItem::getFieldsIndex, orderItem.getFieldsIndex()));
+            WarehouseAreasItem warehousItem = warehousList.isEmpty() ? null : warehousList.get(0);
+            if (Objects.nonNull(warehousItem)) {
+                List<FieldsItem> fieldsList = fieldsItemService.list(new LambdaQueryWrapper<FieldsItem>().eq(FieldsItem::getUuid, orderItem.getFieldsIndex()).last("LIMIT 1"));
+                FieldsItem fieldsItem = fieldsList.isEmpty() ? null : fieldsList.get(0);
+                if (Objects.nonNull(fieldsItem)) {
+                    throw new CoolException("绁ㄥ彿锛�" + fieldsItem.getValue() + "宸插湪鏀惰揣鍖猴紝涓嶅彲鎺ㄩ�佺浉褰撶エ鍙锋暟鎹�傝鑱旂郴绠$悊鍛橈紒锛�");
+                }
+            }
+        }
+        LambdaQueryWrapper<WarehouseAreasItem> queryWrapper = new LambdaQueryWrapper<WarehouseAreasItem>()
+                .eq(WarehouseAreasItem::getMatnrCode, orderItem.getMatnrCode())
+                .eq(!Cools.isEmpty(orderItem.getFieldsIndex()), WarehouseAreasItem::getFieldsIndex, orderItem.getFieldsIndex())
+                .eq(WarehouseAreasItem::getAsnCode, orderItem.getOrderCode())
+                .eq(StringUtils.isNotBlank(orderItem.getSplrBatch()), WarehouseAreasItem::getSplrBatch, orderItem.getSplrBatch());
+        if (Objects.isNull(orderItem.getIsptResult())) {
+            queryWrapper.isNull(WarehouseAreasItem::getIsptResult);
+        } else {
+            queryWrapper.eq(WarehouseAreasItem::getIsptResult, orderItem.getIsptResult());
+        }
+        WarehouseAreasItem serviceOne = warehouseAreasItemService.getOne(queryWrapper);
+        if (Objects.nonNull(serviceOne)) {
+            item.setId(serviceOne.getId());
+            Double anfme = Math.round((item.getAnfme() + serviceOne.getAnfme()) * 10000) / 10000.0;
+            item.setAnfme(anfme);
+        }
+        if (!warehouseAreasItemService.saveOrUpdate(item)) {
+            throw new CoolException("鏀惰揣澶辫触锛侊紒");
+        }
+    }
 
 
     /**
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskSchedules.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskSchedules.java
index 07a4621..b0f52cc 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskSchedules.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskSchedules.java
@@ -254,7 +254,7 @@
     @Scheduled(cron = "0/35 * * * * ?  ")
     @Transactional(rollbackFor = Exception.class)
     public void pubTaskToWcs() {
-        log.info("瀹氭椂浠诲姟寮�濮嬫墽琛岋細浠诲姟涓嬪彂鍒癛CS");
+        log.debug("瀹氭椂浠诲姟寮�濮嬫墽琛岋細浠诲姟涓嬪彂鍒癛CS");
         Long loginUserId = SystemAuthUtils.getLoginUserId();
         List<Integer> list = Arrays.asList(
                  TaskType.TASK_TYPE_LOC_MOVE.type
@@ -274,7 +274,7 @@
                 .in(Task::getTaskType, list)
                 .in(Task::getTaskStatus, integers)
                 .orderByDesc(Task::getSort));
-        log.info("鏌ヨ鍒板緟涓嬪彂浠诲姟鏁伴噺锛歿}", tasks.size());
+        log.debug("鏌ヨ鍒板緟涓嬪彂浠诲姟鏁伴噺锛歿}", tasks.size());
         if (tasks.isEmpty()) {
             log.debug("娌℃湁寰呬笅鍙戠殑浠诲姟锛屽畾鏃朵换鍔$粨鏉�");
             return;
@@ -298,9 +298,9 @@
 //            }
 //        }
         /**涓嬪彂鏅�氱珯鐐逛换鍔★紝鎶ラ敊鍥炴粴锛屼笉鍐嶅線涓嬫墽琛�*/
-        log.info("寮�濮嬩笅鍙憑}涓换鍔″埌RCS", tasks.size());
+        log.debug("寮�濮嬩笅鍙憑}涓换鍔″埌RCS", tasks.size());
         taskService.pubTaskToWcs(tasks);
-        log.info("瀹氭椂浠诲姟鎵ц瀹屾垚锛氫换鍔′笅鍙戝埌RCS");
+        log.debug("瀹氭椂浠诲姟鎵ц瀹屾垚锛氫换鍔′笅鍙戝埌RCS");
     }
 
     /**
@@ -619,66 +619,48 @@
                 }
             } else if ((task.getTaskType() >= TaskType.TASK_TYPE_OUT.type && task.getTaskType() <= TaskType.TASK_TYPE_EMPITY_OUT.type)
                     || task.getTaskType().equals(TaskType.TASK_TYPE_PICK_IN.type)) {
-                /**鍒ゆ柇鍗曟嵁鏄惁瀹屾垚**/
-                // 鍙湁娉㈡绫诲瀷鐨勪换鍔℃墠闇�瑕佹煡璇㈡尝娆″叧鑱斿崟
+                /**鍒ゆ柇鍗曟嵁鏄惁瀹屾垚锛氭尝娆′笅鍙戙�佹寜鍗曚笅鍙戯紙鐐瑰嚮涓嬪彂浠诲姟锛夊畬鎴愬悗鍧囧皢鍑哄簱鍗曠疆涓哄畬缁�*/
+                Set<Long> orderIdsToDone = new HashSet<>();
                 if (task.getResource() != null && task.getResource().equals(TaskResouceType.TASK_RESOUCE_WAVE_TYPE.val)) {
                     Set<Long> longSet = taskItems.stream()
                             .map(TaskItem::getSourceId)
                             .filter(Objects::nonNull)
                             .collect(Collectors.toSet());
-                    
-                    if (longSet.isEmpty()) {
-                        logger.warn("浠诲姟{}鐨勪换鍔℃槑缁嗕腑娌℃湁鏈夋晥鐨剆ourceId锛岃烦杩囨尝娆″叧鑱斿崟鏌ヨ銆備换鍔$紪鐮侊細{}锛屼换鍔$被鍨嬶細{}", 
-                                task.getId(), task.getTaskCode(), task.getTaskType());
-                    } else {
+                    if (!longSet.isEmpty()) {
                         List<WaveOrderRela> waveOrderRelas = waveOrderRelaService.list(new LambdaQueryWrapper<WaveOrderRela>()
                                 .in(WaveOrderRela::getWaveId, longSet));
-                        if (Cools.isEmpty(waveOrderRelas)) {
-                            logger.warn("浠诲姟{}鐨勬尝娆″搴斿叧鑱斿崟鏈壘鍒帮紝鍙兘鏄暟鎹笉涓�鑷存垨浠诲姟涓嶆槸閫氳繃娉㈡鍒涘缓鐨勩�備换鍔$紪鐮侊細{}锛宻ourceIds锛歿}", 
-                                    task.getId(), task.getTaskCode(), longSet);
-                        } else {
-                            Set<Long> orderIds = waveOrderRelas.stream().map(WaveOrderRela::getOrderId).collect(Collectors.toSet());
-                            List<WkOrder> wkOrders = asnOrderService.listByIds(orderIds);
-                            if (wkOrders.isEmpty()) {
-                                logger.warn("浠诲姟{}鐨勫叧鑱斿崟鎹笉瀛樺湪銆備换鍔$紪鐮侊細{}锛宱rderIds锛歿}", 
-                                        task.getId(), task.getTaskCode(), orderIds);
-                            } else {
-                                Config allowChang = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.ALLOW_OVER_CHANGE));
-
-                                wkOrders.forEach(order -> {
-                                    //鍒ゆ柇鏄惁鍏佽瓒呮敹锛屼笉鍏佽瓒呮敹娣诲姞鎷掓敹鍒ゆ柇
-                                    if (!Objects.isNull(allowChang)) {
-                                        if (!Boolean.parseBoolean(allowChang.getVal())) {
-                                            if (order.getAnfme().compareTo(order.getQty()) == 0) {
-                                                order.setExceStatus(AsnExceStatus.OUT_STOCK_STATUS_TASK_DONE.val);
-                                                if (order.getQty() == null || order.getQty().compareTo(0.0) == 0) {
-                                                    order.setQty(order.getWorkQty() != null ? order.getWorkQty() : 0.0);
-                                                }
-                                                if (!asnOrderService.updateById(order)) {
-                                                    logger.error("鍑哄簱鍗曟洿鏂扮姸鎬佸け璐ャ�傝鍗旾D锛歿}锛岃鍗曠紪鐮侊細{}", order.getId(), order.getCode());
-                                                }
-                                            }
-                                        } else {
-                                            if (order.getAnfme().compareTo(order.getQty()) <= 0) {
-                                                order.setExceStatus(AsnExceStatus.OUT_STOCK_STATUS_TASK_DONE.val);
-                                                if (order.getQty() == null || order.getQty().compareTo(0.0) == 0) {
-                                                    order.setQty(order.getWorkQty() != null ? order.getWorkQty() : 0.0);
-                                                }
-                                                if (!asnOrderService.updateById(order)) {
-                                                    logger.error("鍑哄簱鍗曟洿鏂扮姸鎬佸け璐ャ�傝鍗旾D锛歿}锛岃鍗曠紪鐮侊細{}", order.getId(), order.getCode());
-                                                }
-                                            }
-                                        }
-                                    }
-                                    //妫�鏌ュ崟鎹槸鍚﹀畬鎴�
-
-                                });
-                            }
+                        if (!Cools.isEmpty(waveOrderRelas)) {
+                            orderIdsToDone.addAll(waveOrderRelas.stream().map(WaveOrderRela::getOrderId).collect(Collectors.toSet()));
                         }
                     }
-                } else {
-                    logger.debug("浠诲姟{}涓嶆槸娉㈡绫诲瀷浠诲姟锛堣祫婧愮被鍨嬶細{}锛夛紝璺宠繃娉㈡鍏宠仈鍗曟煡璇€�備换鍔$紪鐮侊細{}", 
-                            task.getId(), task.getResource(), task.getTaskCode());
+                } else if (task.getResource() != null && task.getResource().equals(TaskResouceType.TASK_RESOUCE_ORDER_TYPE.val)) {
+                    // 鎸夊崟涓嬪彂锛氫换鍔℃槑缁� sourceId 涓哄嚭搴撳崟ID
+                    Set<Long> ids = taskItems.stream()
+                            .map(TaskItem::getSourceId)
+                            .filter(Objects::nonNull)
+                            .collect(Collectors.toSet());
+                    orderIdsToDone.addAll(ids);
+                }
+                if (!orderIdsToDone.isEmpty()) {
+                    List<WkOrder> wkOrders = asnOrderService.listByIds(orderIdsToDone);
+                    if (!wkOrders.isEmpty()) {
+                        Config allowChang = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.ALLOW_OVER_CHANGE));
+                        wkOrders.forEach(order -> {
+                            if (order.getAnfme() == null) return;
+                            boolean canDone = Boolean.TRUE.equals(allowChang != null && Boolean.parseBoolean(allowChang.getVal()))
+                                    ? (order.getQty() != null && order.getAnfme().compareTo(order.getQty()) <= 0)
+                                    : (order.getQty() != null && order.getAnfme().compareTo(order.getQty()) == 0);
+                            if (canDone) {
+                                order.setExceStatus(AsnExceStatus.OUT_STOCK_STATUS_TASK_DONE.val);
+                                if (order.getQty() == null || order.getQty().compareTo(0.0) == 0) {
+                                    order.setQty(order.getWorkQty() != null ? order.getWorkQty() : 0.0);
+                                }
+                                if (!asnOrderService.updateById(order)) {
+                                    logger.error("鍑哄簱鍗曟洿鏂扮姸鎬佸け璐ャ�傝鍗旾D锛歿}锛岃鍗曠紪鐮侊細{}", order.getId(), order.getCode());
+                                }
+                            }
+                        });
+                    }
                 }
                 
                 //鍑哄簱鍗曚笂鎶CS淇敼搴撲綅鐘舵��
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/AsnOrderItemService.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/AsnOrderItemService.java
index 54282b5..15c8d00 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/AsnOrderItemService.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/AsnOrderItemService.java
@@ -24,4 +24,7 @@
 
     IPage<Map<String, Object>> listByAsnId(PageParam<WkOrderItem, BaseParam> pageParam, QueryWrapper<WkOrderItem> buildWrapper);
 
+    /** 涓烘敹璐ф槑缁嗗垪琛ㄥ~鍏呯粍鎵樻暟閲忥紙palletQty锛夛紝鏉ユ簮浜庣粍鎵樻。 WaitPakinItem 鎸� asnItemId 姹囨�� */
+    void fillPalletQty(List<WkOrderItem> items);
+
 }
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/AsnOrderService.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/AsnOrderService.java
index 70a771e..2c09f94 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/AsnOrderService.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/AsnOrderService.java
@@ -32,4 +32,7 @@
     R getDashbord();
 
     R getStockTrand();
+
+    /** 涓哄叆搴撻�氱煡鍗曞垪琛ㄥ~鍏呯粍鎵樻暟閲忥紙palletQty锛夛紝鐢ㄤ簬鍒楄〃灞曠ず */
+    void fillPalletQty(List<WkOrder> orders);
 }
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/AsnOrderItemServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/AsnOrderItemServiceImpl.java
index c2d7766..5473012 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/AsnOrderItemServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/AsnOrderItemServiceImpl.java
@@ -10,6 +10,8 @@
 import com.vincent.rsf.framework.common.Cools;
 import com.vincent.rsf.framework.common.R;
 import com.vincent.rsf.framework.exception.CoolException;
+import com.vincent.rsf.server.common.utils.QuantityUtils;
+import com.vincent.rsf.server.manager.entity.WaitPakinItem;
 import com.vincent.rsf.server.manager.entity.WkOrder;
 import com.vincent.rsf.server.manager.entity.WkOrderItem;
 import com.vincent.rsf.server.manager.enums.OrderType;
@@ -27,6 +29,7 @@
 import com.vincent.rsf.server.manager.service.AsnOrderItemService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.vincent.rsf.server.manager.service.AsnOrderService;
+import com.vincent.rsf.server.manager.service.WaitPakinItemService;
 import com.vincent.rsf.server.manager.service.CompanysService;
 import com.vincent.rsf.server.manager.service.MatnrService;
 import com.vincent.rsf.server.system.constant.SerialRuleCode;
@@ -70,6 +73,9 @@
     private DictDataService dictDataService;
     @Autowired
     private AsnOrderService asnOrderService;
+
+    @Autowired
+    private WaitPakinItemService waitPakinItemService;
 
     @Override
     public R generateBarcode(List<Long> orders) {
@@ -301,4 +307,26 @@
         return hsahMap;
     }
 
+    @Override
+    public void fillPalletQty(List<WkOrderItem> items) {
+        if (items == null || items.isEmpty()) {
+            return;
+        }
+        List<Long> itemIds = items.stream().map(WkOrderItem::getId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
+        if (itemIds.isEmpty()) {
+            return;
+        }
+        List<WaitPakinItem> allItems = waitPakinItemService.list(
+                new LambdaQueryWrapper<WaitPakinItem>().in(WaitPakinItem::getAsnItemId, itemIds).eq(WaitPakinItem::getDeleted, 0));
+        Map<Long, Double> sumByAsnItemId = allItems.stream()
+                .collect(Collectors.groupingBy(WaitPakinItem::getAsnItemId,
+                        Collectors.summingDouble(w -> w.getAnfme() != null ? w.getAnfme() : 0.0)));
+        sumByAsnItemId.replaceAll((k, v) -> QuantityUtils.roundToScale(v));
+        for (WkOrderItem item : items) {
+            if (item.getId() != null) {
+                item.setPalletQty(sumByAsnItemId.getOrDefault(item.getId(), 0.0));
+            }
+        }
+    }
+
 }
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/AsnOrderServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/AsnOrderServiceImpl.java
index 1f39b07..1eb0a76 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/AsnOrderServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/AsnOrderServiceImpl.java
@@ -17,6 +17,7 @@
 import com.vincent.rsf.server.manager.controller.params.BatchUpdateParam;
 import com.vincent.rsf.server.manager.entity.*;
 import com.vincent.rsf.server.manager.enums.*;
+import com.vincent.rsf.server.common.utils.QuantityUtils;
 import com.vincent.rsf.server.manager.mapper.AsnOrderMapper;
 import com.vincent.rsf.server.manager.service.*;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -383,7 +384,7 @@
     public R removeOrders(List<Long> ids) {
         // 宸茬粍鎵樹笉鍙垹闄わ紝闇�鍏堣В闄ょ粍鎵�
         long palletizedCount = waitPakinItemService.count(new LambdaQueryWrapper<WaitPakinItem>()
-                .in(WaitPakinItem::getAsnId, ids));
+                .in(WaitPakinItem::getAsnId, ids).eq(WaitPakinItem::getDeleted, 0));
         if (palletizedCount > 0) {
             throw new CoolException("鍗曟嵁宸茬粍鎵橈紝璇峰厛瑙i櫎缁勬墭鍚庡啀鍒犻櫎锛侊紒");
         }
@@ -560,4 +561,26 @@
             throw new CoolException("鍘熷崟鎹垹闄ゅけ璐ワ紒锛�");
         }
     }
+
+    @Override
+    public void fillPalletQty(List<WkOrder> orders) {
+        if (orders == null || orders.isEmpty()) {
+            return;
+        }
+        List<Long> orderIds = orders.stream().map(WkOrder::getId).filter(Objects::nonNull).collect(Collectors.toList());
+        if (orderIds.isEmpty()) {
+            return;
+        }
+        List<WaitPakinItem> allItems = waitPakinItemService.list(
+                new LambdaQueryWrapper<WaitPakinItem>().in(WaitPakinItem::getAsnId, orderIds).eq(WaitPakinItem::getDeleted, 0));
+        Map<Long, Double> sumByAsnId = allItems.stream()
+                .collect(Collectors.groupingBy(WaitPakinItem::getAsnId,
+                        Collectors.summingDouble(w -> w.getAnfme() != null ? w.getAnfme() : 0.0)));
+        sumByAsnId.replaceAll((k, v) -> QuantityUtils.roundToScale(v));
+        for (WkOrder order : orders) {
+            if (order.getId() != null) {
+                order.setPalletQty(sumByAsnId.getOrDefault(order.getId(), 0.0));
+            }
+        }
+    }
 }
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java
index 0bd3bb6..6ad6dfd 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java
@@ -1571,11 +1571,11 @@
                     if (Objects.isNull(waveItem)) {
                         throw new CoolException("娉㈡鏄庣粏涓嶅瓨鍦紒锛�");
                     }
-//                    try {
-//                        saveOutStockItem(maps.get(key), null, waveItem, null, loginUserId);
-//                    } catch (Exception e) {
-//                        throw new CoolException(e.getMessage());
-//                    }
+                    try {
+                        saveOutStockItem(maps.get(key), null, waveItem, null, loginUserId);
+                    } catch (Exception e) {
+                        throw new CoolException(e.getMessage());
+                    }
                 } else if (task.getResource().equals(TaskResouceType.TASK_RESOUCE_ORDER_TYPE.val)) {
                     WkOrderItem orderItem = asnOrderItemService.getById(key);
                     if (Objects.isNull(orderItem)) {
@@ -1703,8 +1703,35 @@
                 .setUpdateTime(new Date())
                 .setAnfme(sum);
         if (!Objects.isNull(waveItem)) {
-            //TODO 鐢熸垚娉㈡鏃堕渶瑕佸皢娉㈡鍙峰啓鍏ュ崟鎹紝閫氳繃鐗╂枡锛屾壒娆★紝鍔ㄦ�佸瓧娈电瓑鍞竴鍊煎弽鏌ュ崟鎹俊鎭�
+            // 娉㈡鍑哄簱锛氭洿鏂板嚭搴撳崟瀹屾垚鏁伴噺鍙婂嚭搴撳崟鏄庣粏鎵ц鏁伴噺
             stock.setSourceId(waveItem.getId()).setType(OrderType.ORDER_OUT.type);
+            Long orderId = waveItem.getOrderId();
+            if (orderId != null) {
+                WkOrder wkOrder = asnOrderService.getById(orderId);
+                if (wkOrder != null) {
+                    Double curQty = wkOrder.getQty() != null ? wkOrder.getQty() : 0.0;
+                    Double newQty = QuantityUtils.roundToScale(curQty + sum);
+                    wkOrder.setExceStatus(AsnExceStatus.OUT_STOCK_STATUS_TASK_WORKING.val).setQty(newQty);
+                    if (!asnOrderService.updateById(wkOrder)) {
+                        throw new CoolException("鍑哄簱鍗曞畬鎴愭暟閲忔洿鏂板け璐ワ紒锛�");
+                    }
+                }
+                // 鎸夊嚭搴撳崟鏄庣粏姹囨�绘湰娆′换鍔℃暟閲忥紝鏇存柊鍚勬槑缁� workQty
+                Map<Long, Double> sumByOrderItemId = taskItems.stream()
+                        .filter(ti -> ti.getOrderItemId() != null)
+                        .collect(Collectors.groupingBy(TaskItem::getOrderItemId,
+                                Collectors.summingDouble(ti -> ti.getAnfme() != null ? ti.getAnfme() : 0.0)));
+                for (Map.Entry<Long, Double> e : sumByOrderItemId.entrySet()) {
+                    WkOrderItem oi = outStockItemService.getById(e.getKey());
+                    if (oi != null) {
+                        Double wq = oi.getWorkQty() != null ? oi.getWorkQty() : 0.0;
+                        oi.setWorkQty(QuantityUtils.roundToScale(wq + e.getValue()));
+                        if (!outStockItemService.updateById(oi)) {
+                            throw new CoolException("鍑哄簱鍗曟槑缁嗘墽琛屾暟閲忔洿鏂板け璐ワ紒锛�");
+                        }
+                    }
+                }
+            }
         } else if (!Objects.isNull(orderItem) && StringUtils.isNotBlank(orderItem.getId() + "")) {
             WkOrder wkOrder = asnOrderService.getById(orderItem.getOrderId());
             Double qty = Math.round((wkOrder.getQty() + sum) * 1000000) / 1000000.0;
@@ -2229,10 +2256,10 @@
             List<TaskItem> items = orderMap.get(key);
             //淇濆瓨鍏ュ嚭搴撴槑缁�
             saveStockItems(items, task, pakinItem.getId(), pakinItem.getAsnCode(), pakinItem.getWkType(), pakinItem.getType(), loginUserId);
-            // 鏀惰揣鍖哄凡鍋滅敤锛屼笉鍐嶇Щ鍑烘敹璐у尯搴撳瓨
-            // if (Objects.nonNull(pakinItem.getSource())) {
-            //     removeReceiptStock(pakinItem, loginUserId);
-            // }
+            // DirectWaitPakin 鍚敤鏃剁粍鎵樻潵鑷敹璐у尯锛屽叆搴撳畬鎴愬悗绉诲嚭鏀惰揣鍖哄簱瀛橈紱鏈惎鐢ㄦ椂 source 涓� null 涓嶆墽琛�
+            if (Objects.nonNull(pakinItem.getSource())) {
+                removeReceiptStock(pakinItem, loginUserId);
+            }
         });
 
         Set<Long> pkinItemIds = taskItems.stream().map(TaskItem::getSource).collect(Collectors.toSet());
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/WaitPakinServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/WaitPakinServiceImpl.java
index eea2499..b912340 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/WaitPakinServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/WaitPakinServiceImpl.java
@@ -12,10 +12,12 @@
 import com.vincent.rsf.server.manager.service.*;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.vincent.rsf.server.common.utils.QuantityUtils;
+import com.vincent.rsf.server.system.constant.GlobalConfigCode;
 import com.vincent.rsf.server.system.constant.SerialRuleCode;
+import com.vincent.rsf.server.system.entity.Config;
+import com.vincent.rsf.server.system.service.ConfigService;
 import com.vincent.rsf.server.system.utils.SerialRuleUtils;
 import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -45,6 +47,8 @@
     private TaskItemService taskItemService;
     @Autowired
     private MatnrMapper matnrMapper;
+    @Autowired
+    private ConfigService configService;
 
 
     /**
@@ -67,8 +71,8 @@
         WaitPakin pakin = waitPakinService.getOne(new LambdaQueryWrapper<WaitPakin>()
                 .eq(WaitPakin::getBarcode, waitPakin.getBarcode()));
 
-        // 濡傛灉鏂欑鐮佸凡缁忕粍鎵樿繃锛屾彁绀哄凡缁勬墭锛岃鏇存崲鏂欑鐮�
-        if (!Objects.isNull(pakin)) {
+        // 鍗婄鏃跺厑璁稿悓涓�鏂欑鐮佺户缁粍鎵樿拷鍔狅紱闈炲崐绠辨椂鏂欑鐮佸凡缁勬墭鍒欎笉鍙啀鐢�
+        if (!Objects.isNull(pakin) && !Boolean.TRUE.equals(waitPakin.getIsHalf())) {
             throw new CoolException("宸茬粍鎵橈紝璇锋洿鎹㈡枡绠辩爜");
         }
 
@@ -85,14 +89,17 @@
 
         Double sum = QuantityUtils.roundToScale(waitPakin.getItems().stream().mapToDouble(PakinItem::getReceiptQty).sum());
 
-        WaitPakin waitPakin1 = new WaitPakin();
+        Config directPakinConfig = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.DIRECT_WAIT_PAKIN));
+        boolean directWaitPakin = directPakinConfig != null && Boolean.parseBoolean(directPakinConfig.getVal());
+
+        WaitPakin waitPakin1;
         if (Objects.isNull(pakin)) {
+            waitPakin1 = new WaitPakin();
             String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_WAIT_PAKIN_CODE, null);
             if (StringUtils.isBlank(ruleCode)) {
                 throw new CoolException("缂栫爜瑙勫垯閿欒锛� 缂栫爜瑙勫垯銆孲YS_WAIT_PAKIN_CODE銆嶈鍒欐槸涓嶅瓨鍦�");
             }
             waitPakin1.setCode(ruleCode)
-                    //鐘舵�佷慨鏀逛负鍏ュ簱涓�
                     .setIoStatus(PakinIOStatus.PAKIN_IO_STATUS_DONE.val)
                     .setAnfme(sum)
                     .setUpdateBy(userId)
@@ -102,14 +109,94 @@
                 throw new CoolException("涓诲崟淇濆瓨澶辫触锛侊紒");
             }
         } else {
-            BeanUtils.copyProperties(pakin, waitPakin1);
+            // 鍗婄杩藉姞锛氭部鐢ㄥ凡鏈夌粍鎵樺崟锛屽彧杩藉姞鏄庣粏
+            waitPakin1 = pakin;
         }
 
         List<WaitPakinItem> items = new ArrayList<>();
+        if (directWaitPakin) {
+            // DirectWaitPakin 鍚敤锛氱粍鎵樻潵鑷敹璐у尯锛宲aram 涓� id 涓� WarehouseAreasItem.id
+            for (PakinItem pakinItem1 : waitPakin.getItems()) {
+                WarehouseAreasItem areaItem = warehouseAreasItemService.getById(pakinItem1.getId());
+                if (areaItem == null) {
+                    throw new CoolException("鐗╂枡鏈�佽嚦鏀惰揣鍖猴紒锛�");
+                }
+                WaitPakinItem pakinItem = new WaitPakinItem();
+                pakinItem.setPakinId(waitPakin1.getId())
+                        .setSource(areaItem.getId())
+                        .setAsnId(areaItem.getAsnId())
+                        .setAsnCode(areaItem.getAsnCode())
+                        .setAsnItemId(areaItem.getAsnItemId())
+                        .setIsptResult(areaItem.getIsptResult())
+                        .setPlatItemId(areaItem.getPlatItemId())
+                        .setPlatOrderCode(areaItem.getPlatOrderCode())
+                        .setPlatWorkCode(areaItem.getPlatWorkCode())
+                        .setProjectCode(areaItem.getProjectCode())
+                        .setBatch(areaItem.getSplrBatch())
+                        .setUnit(areaItem.getStockUnit())
+                        .setFieldsIndex(areaItem.getFieldsIndex())
+                        .setMatnrId(areaItem.getMatnrId())
+                        .setMaktx(areaItem.getMaktx())
+                        .setUpdateBy(userId)
+                        .setCreateBy(userId)
+                        .setMatnrCode(areaItem.getMatnrCode());
+                WkOrder order = asnOrderService.getById(areaItem.getAsnId());
+                if (order != null) {
+                    pakinItem.setType(order.getType()).setWkType(StringUtils.isNotBlank(order.getWkType()) ? Short.parseShort(order.getWkType()) : null);
+                }
+                if (pakinItem1.getReceiptQty() == null || pakinItem1.getReceiptQty().compareTo(0.0) <= 0) {
+                    throw new CoolException("缁勬墭鏁伴噺涓嶈兘灏忎簬绛変簬闆讹紒锛�");
+                }
+                if (QuantityUtils.compare(pakinItem1.getReceiptQty(), areaItem.getAnfme()) > 0) {
+                    throw new CoolException("缁勬墭鏁伴噺涓嶈兘澶т簬鏀惰揣鏁伴噺锛侊紒");
+                }
+                pakinItem.setAnfme(QuantityUtils.roundToScale(pakinItem1.getReceiptQty())).setTrackCode(pakinItem1.getTrackCode());
+                items.add(pakinItem);
+            }
+            if (!waitPakinItemService.saveBatch(items)) {
+                throw new CoolException("缁勬墭鏄庣粏淇濆瓨澶辫触锛侊紒");
+            }
+            for (WaitPakinItem pakinItem : items) {
+                WarehouseAreasItem one = warehouseAreasItemService.getOne(new LambdaQueryWrapper<WarehouseAreasItem>().eq(WarehouseAreasItem::getId, pakinItem.getSource()));
+                if (one == null) {
+                    throw new CoolException("鏀惰揣鍖烘暟鎹敊璇紒锛�");
+                }
+                Double workQty = QuantityUtils.roundToScale(QuantityUtils.add(one.getWorkQty() != null ? one.getWorkQty() : 0.0, pakinItem.getAnfme()));
+                Double qty = QuantityUtils.roundToScale(QuantityUtils.add(workQty, one.getQty() != null ? one.getQty() : 0.0));
+                one.setWorkQty(workQty);
+                if (QuantityUtils.compare(qty, one.getAnfme() != null ? one.getAnfme() : 0.0) > 0) {
+                    throw new CoolException("缁勬墭鏁伴噺涓嶈兘澶т簬鏀惰揣鏁伴噺锛侊紒");
+                }
+                if (!warehouseAreasItemService.saveOrUpdate(one)) {
+                    throw new CoolException("鏀惰揣鍖烘墽琛屾暟閲忎慨鏀瑰け璐ワ紒锛�");
+                }
+            }
+            // 鍗婄杩藉姞鏃堕渶鎸夎缁勬墭鍗曚笅鍏ㄩ儴鏄庣粏閲嶇畻鎬绘暟閲�
+            List<WaitPakinItem> allItems = waitPakinItemService.list(new LambdaQueryWrapper<WaitPakinItem>().eq(WaitPakinItem::getPakinId, waitPakin1.getId()));
+            waitPakin1.setAnfme(QuantityUtils.roundToScale(allItems.stream().mapToDouble(w -> w.getAnfme() != null ? w.getAnfme() : 0.0).sum()));
+            if (!this.updateById(waitPakin1)) {
+                throw new CoolException("缁勬墭鏁伴噺淇敼澶辫触锛侊紒");
+            }
+            return waitPakin1;
+        }
+
+        // 鏈堿SN鏃讹細鎸夎鍗曟槑缁嗘眹鎬诲凡缁勬墭鏁伴噺锛屾牎楠� 宸茬粍鎵�+鏈缁勭洏 鈮� 璁″垝鏁伴噺
+        Map<Long, Double> alreadyPalletizedByItemId = new java.util.HashMap<>();
+        for (PakinItem p : waitPakin.getItems()) {
+            if (StringUtils.isNotBlank(p.getAsnCode()) && p.getId() != null) {
+                alreadyPalletizedByItemId.putIfAbsent(p.getId(), null);
+            }
+        }
+        if (!alreadyPalletizedByItemId.isEmpty()) {
+            for (Long asnItemId : alreadyPalletizedByItemId.keySet()) {
+                double alreadySum = waitPakinItemService.list(new LambdaQueryWrapper<WaitPakinItem>().eq(WaitPakinItem::getAsnItemId, asnItemId).eq(WaitPakinItem::getDeleted, 0))
+                        .stream().mapToDouble(w -> w.getAnfme() != null ? w.getAnfme() : 0.0).sum();
+                alreadyPalletizedByItemId.put(asnItemId, QuantityUtils.roundToScale(alreadySum));
+            }
+        }
+
         for (PakinItem pakinItem1 : waitPakin.getItems()) {
             WaitPakinItem pakinItem = new WaitPakinItem();
-            
-            // 濡傛灉ASN鍗曞彿涓虹┖锛屼粠鐗╂枡淇℃伅琛ㄨ幏鍙栫墿鏂欎俊鎭紝涓嶆煡璇㈡敹璐у尯
             if (StringUtils.isBlank(pakinItem1.getAsnCode())) {
                 if (Objects.isNull(pakinItem1.getMatnrId())) {
                     throw new CoolException("鐗╂枡ID涓嶈兘涓虹┖锛侊紒");
@@ -184,8 +271,10 @@
                         if (waitPakinItem.getReceiptQty() == null || waitPakinItem.getReceiptQty().compareTo(0.0) <= 0) {
                             throw new CoolException("缁勬墭鏁伴噺涓嶈兘灏忎簬绛変簬闆讹紒锛�");
                         }
-                        if (QuantityUtils.compare(waitPakinItem.getReceiptQty(), orderItem.getAnfme()) > 0) {
-                            throw new CoolException("缁勬墭鏁伴噺涓嶈兘澶т簬璁″垝鏁伴噺锛侊紒");
+                        Double anfme = orderItem.getAnfme() != null ? orderItem.getAnfme() : 0.0;
+                        Double already = alreadyPalletizedByItemId.getOrDefault(orderItem.getId(), 0.0);
+                        if (QuantityUtils.compare(QuantityUtils.add(already, waitPakinItem.getReceiptQty()), anfme) > 0) {
+                            throw new CoolException("缁勬墭鏁伴噺涓嶈兘瓒呰繃鍙粍鐩樻暟閲忥紙璁″垝" + anfme + "锛屽凡缁勬墭" + already + "锛屾湰娆℃渶澶�" + QuantityUtils.subtract(anfme, already) + "锛夛紒锛�");
                         }
                         pakinItem.setAnfme(QuantityUtils.roundToScale(waitPakinItem.getReceiptQty()))
                                 .setTrackCode(waitPakinItem.getTrackCode());
@@ -284,16 +373,19 @@
                                 throw new CoolException("缁勬墭鏄庣粏鍒犻櫎澶辫触锛侊紒");
                             }
                         }
-                        // 鏀惰揣鍖哄凡鍋滅敤锛屼笉鍐嶅洖鍐欐敹璐у尯
-                        // for (int i = 0; i < warehouseAreasItems.size(); i++) {
-                        //     if (warehouseAreasItems.get(i).getId().equals(pakinItems.get(i1).getSource())) {
-                        //         double v = Math.round((warehouseAreasItems.get(i).getWorkQty() - item.getReceiptQty()) * 1000000) / 1000000.0;
-                        //         warehouseAreasItems.get(i).setWorkQty(v);
-                        //         if (!warehouseAreasItemService.updateById(warehouseAreasItems.get(i))) {
-                        //             throw new CoolException("鏀惰揣鍖烘暟閲忎慨鏀瑰け璐ワ紒锛�");
-                        //         }
-                        //     }
-                        // }
+                        // DirectWaitPakin 鍚敤鏃剁粍鎵樻潵鑷敹璐у尯锛岃В缁戦渶鍥炲啓鏀惰揣鍖� workQty
+                        if (Objects.nonNull(pakinItems.get(i1).getSource())) {
+                            for (WarehouseAreasItem areaItem : warehouseAreasItems) {
+                                if (areaItem.getId().equals(pakinItems.get(i1).getSource())) {
+                                    Double v = QuantityUtils.roundToScale(QuantityUtils.subtract(areaItem.getWorkQty() != null ? areaItem.getWorkQty() : 0.0, item.getReceiptQty()));
+                                    areaItem.setWorkQty(v);
+                                    if (!warehouseAreasItemService.updateById(areaItem)) {
+                                        throw new CoolException("鏀惰揣鍖烘暟閲忎慨鏀瑰け璐ワ紒锛�");
+                                    }
+                                    break;
+                                }
+                            }
+                        }
                     }
                 }
             }
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/system/constant/GlobalConfigCode.java b/rsf-server/src/main/java/com/vincent/rsf/server/system/constant/GlobalConfigCode.java
index 12e22dc..1dd2027 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/system/constant/GlobalConfigCode.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/system/constant/GlobalConfigCode.java
@@ -42,4 +42,15 @@
     /** 浜戜粨閫氱煡鐘舵�侊細澶辫触 */
     public final static String CLOUD_WMS_NOTIFY_STATUS_FAIL = "CLOUD_WMS_NOTIFY_STATUS_FAIL";
 
+    /** 鎸囧畾鐗╂枡鑷姩鍏ㄧ増鍑哄簱锛氱墿鏂欑紪鐮侊紙val=鐗╂枡缂栫爜鏃跺惎鐢ㄦ寜鐗╂枡鑷姩鐢熸垚鍏ㄧ増鍑哄簱鍗曪級 */
+    public final static String AUTO_FULL_OUT_MATNR_CODE = "AUTO_FULL_OUT_MATNR_CODE";
+    /** 鏄惁鍚敤锛氭湁搴撳瓨鏃惰嚜鍔ㄧ敓鎴愬叏鐗堝嚭搴撳崟 */
+    public final static String AUTO_FULL_OUT_ENABLED = "AUTO_FULL_OUT_ENABLED";
+    /** 鏄惁鍚敤锛氳鐗╂枡鍑哄簱鍗曡嚜鍔ㄤ笅鍙戜换鍔� */
+    public final static String AUTO_FULL_OUT_DISPATCH_ENABLED = "AUTO_FULL_OUT_DISPATCH_ENABLED";
+    /** 鏄惁鍚敤锛歊CS 鍏ュ簱閫氱煡鏃惰嚜鍔ㄧ粍鎵� */
+    public final static String AUTO_PAKIN_ON_ASN_ENABLED = "AUTO_PAKIN_ON_ASN_ENABLED";
+    /** 鑷姩缁勬墭鏁伴噺锛堜笌 AUTO_PAKIN_ON_ASN_ENABLED 閰嶅悎锛屾瘡鏉℃槑缁嗙粍鎵樻暟閲忥級 */
+    public final static String AUTO_PAKIN_QTY = "AUTO_PAKIN_QTY";
+
 }
diff --git a/version/db/material_auto_config.sql b/version/db/material_auto_config.sql
new file mode 100644
index 0000000..63153fa
--- /dev/null
+++ b/version/db/material_auto_config.sql
@@ -0,0 +1,10 @@
+-- 鎸囧畾鐗╂枡鑷姩鍖栧畾鏃朵换鍔¢厤缃紙鐗╂枡缂栫爜銆佽嚜鍔ㄥ叏鐗堝嚭搴撱�佽嚜鍔ㄤ笅鍙戙�佸叆搴撹嚜鍔ㄧ粍鎵樺強鏁伴噺锛�
+-- 浣跨敤鏂瑰紡锛氬湪绯荤粺閰嶇疆涓淮鎶や互涓� flag锛寁al 濉墿鏂欑紪鐮佹垨 true/false/鏁板瓧
+INSERT INTO `sys_config` (`uuid`, `name`, `flag`, `type`, `val`, `content`, `status`, `deleted`, `tenant_id`, `create_by`, `create_time`, `update_by`, `update_time`, `memo`)
+VALUES
+(UPPER(UUID()), '鎸囧畾鐗╂枡缂栫爜(鑷姩鍏ㄧ増鍑哄簱/鑷姩缁勬墭)', 'AUTO_FULL_OUT_MATNR_CODE', 3, '', '濉墿鏂欑紪鐮佹椂鍙備笌鑷姩鍏ㄧ増鍑哄簱涓庤嚜鍔ㄧ粍鎵�', 1, 0, 1, NULL, NOW(), NULL, NOW(), '涓� AUTO_FULL_OUT_ENABLED 绛夐厤鍚�'),
+(UPPER(UUID()), '鍚敤锛氭湁搴撳瓨鏃惰嚜鍔ㄧ敓鎴愬叏鐗堝嚭搴撳崟', 'AUTO_FULL_OUT_ENABLED', 1, 'false', 'true/false', 1, 0, 1, NULL, NOW(), NULL, NOW(), '闇�閰嶇疆 AUTO_FULL_OUT_MATNR_CODE'),
+(UPPER(UUID()), '鍚敤锛氳鐗╂枡鍑哄簱鍗曡嚜鍔ㄤ笅鍙戜换鍔�', 'AUTO_FULL_OUT_DISPATCH_ENABLED', 1, 'false', 'true/false', 1, 0, 1, NULL, NOW(), NULL, NOW(), '闇�閰嶇疆 AUTO_FULL_OUT_MATNR_CODE'),
+(UPPER(UUID()), '鍚敤锛歊CS鍏ュ簱閫氱煡鏃惰嚜鍔ㄧ粍鎵�', 'AUTO_PAKIN_ON_ASN_ENABLED', 1, 'false', 'true/false', 1, 0, 1, NULL, NOW(), NULL, NOW(), '闇�閰嶇疆 AUTO_FULL_OUT_MATNR_CODE銆丄UTO_PAKIN_QTY'),
+(UPPER(UUID()), '鑷姩缁勬墭鏁伴噺', 'AUTO_PAKIN_QTY', 2, '1', '姣忔潯鍏ュ簱鏄庣粏鑷姩缁勬墭鏁伴噺', 1, 0, 1, NULL, NOW(), NULL, NOW(), '涓� AUTO_PAKIN_ON_ASN_ENABLED 閰嶅悎')
+;

--
Gitblit v1.9.1