From 63d187526792e6e29bfec07d0e3f0dce07df31b3 Mon Sep 17 00:00:00 2001
From: helongyang <647556386@qq.com>
Date: 星期六, 19 七月 2025 17:32:41 +0800
Subject: [PATCH] 成品报废单新增优化

---
 代码管理/WMS/WIDESEA_WMSClient/src/extension/outbound/erpProScrapSheet.js                           |   10 
 代码管理/WMS/WIDESEA_WMSClient/src/extension/outbound/extend/AddErpProScrapSheet.vue                |  444 ++++++++++++++++++++++++++++++++++
 代码管理/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Outbound/ErpProScrapSheetController.cs |    6 
 代码管理/WMS/WIDESEA_WMSServer/WIDESEA_DTO/Outbound/ErpProScrapSheetModel.cs                        |   69 +++++
 代码管理/WMS/WIDESEA_WMSServer/WIDESEA_StockService/ProStockInfoService.cs                          |   47 +++
 代码管理/WMS/WIDESEA_WMSClient/src/views/basic/palletCodeInfo.vue                                   |   15 -
 代码管理/WMS/WIDESEA_WMSServer/WIDESEA_IStockService/IProStockInfoService.cs                        |   18 +
 代码管理/WMS/WIDESEA_WMSServer/WIDESEA_IOutboundService/IErpProScrapSheetService.cs                 |    2 
 代码管理/WMS/WIDESEA_WMSClient/src/extension/outbound/extend/ScrapSheet.vue                         |   12 
 代码管理/WMS/WIDESEA_WMSServer/WIDESEA_OutboundService/ErpProScrapSheetService.cs                   |  112 ++++++++
 代码管理/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Stock/ProStockInfoController.cs        |   36 ++
 11 files changed, 750 insertions(+), 21 deletions(-)

diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSClient/src/extension/outbound/erpProScrapSheet.js" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSClient/src/extension/outbound/erpProScrapSheet.js"
index e351097..0a83c94 100644
--- "a/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSClient/src/extension/outbound/erpProScrapSheet.js"
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSClient/src/extension/outbound/erpProScrapSheet.js"
@@ -1,10 +1,11 @@
 
 //姝s鏂囦欢鏄敤鏉ヨ嚜瀹氫箟鎵╁睍涓氬姟浠g爜锛屽彲浠ユ墿灞曚竴浜涜嚜瀹氫箟椤甸潰鎴栬�呴噸鏂伴厤缃敓鎴愮殑浠g爜
 import gridBody from './extend/ScrapSheet.vue'
+import gridHeader from './extend/AddErpProScrapSheet.vue'
 let extension = {
   components: {
     //鏌ヨ鐣岄潰鎵╁睍缁勪欢
-    gridHeader: '',
+    gridHeader: gridHeader,
     gridBody: gridBody,
     gridFooter: '',
     //鏂板缓銆佺紪杈戝脊鍑烘鎵╁睍缁勪欢
@@ -17,6 +18,13 @@
   methods: {
     //涓嬮潰杩欎簺鏂规硶鍙互淇濈暀涔熷彲浠ュ垹闄�
     onInit() {
+      let addBtn = this.buttons.find(x => x.value == 'Add');
+      if (addBtn) {
+        addBtn.onClick = function () {
+          this.$refs.gridHeader.open();
+        }
+      };
+
         this.columns.push({
             field: '鎿嶄綔',
             title: '鎿嶄綔',
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSClient/src/extension/outbound/extend/AddErpProScrapSheet.vue" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSClient/src/extension/outbound/extend/AddErpProScrapSheet.vue"
new file mode 100644
index 0000000..b379641
--- /dev/null
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSClient/src/extension/outbound/extend/AddErpProScrapSheet.vue"
@@ -0,0 +1,444 @@
+<template>
+  <div>
+    <vol-box
+      v-model="showDetialBox"
+      :lazy="true"
+      width="1300px"
+      height="700px"
+      :padding="20"
+      title="娣诲姞鎴愬搧瓒呮湡鎶ュ簾鏄庣粏"
+    >
+      <div style="max-height: 700px; overflow-y: auto;">
+        <el-form ref="form" :model="form" label-width="130px">
+          <!-- 浠撳簱閫夋嫨 -->
+          <el-form-item required label="鎵�灞炰粨搴擄細">
+            <el-select
+              v-model="form.warehouseId"
+              filterable
+              placeholder="璇烽�夋嫨浠撳簱"
+              @change="handleWarehouseChange"
+              style="width: 100%;"
+            >
+              <el-option
+                v-for="item in warehouses"
+                :key="item.key"
+                :label="item.value"
+                :value="item.key"
+              >
+                <span style="float: left">{{ item.value }}</span>
+                <span style="float: right; color: #8492a6; font-size: 13px">{{ item.key }}</span>
+              </el-option>
+            </el-select>
+          </el-form-item>
+
+          <!-- 鍗曟嵁缂栧彿锛堝彧璇伙級 -->
+          <el-form-item required label="鍗曟嵁缂栧彿锛�">
+            <el-input
+              v-model="form.proScrapSheetOrderNo"
+              placeholder="绯荤粺灏嗚嚜鍔ㄧ敓鎴�"
+              readonly
+              style="width: 100%;"
+            ></el-input>
+          </el-form-item>
+
+          <!-- 鏄庣粏鍒楄〃 -->
+          <el-form-item label="鎶ュ簾鏄庣粏锛�">
+            <div v-for="(detail, index) in detailList" :key="index" class="detail-item">
+              <div class="detail-header">
+                <span>鏄庣粏 {{ index + 1 }}</span>
+                <el-button
+                  type="text"
+                  size="mini"
+                  color="#f56c6c"
+                  @click="removeDetail(index)"
+                  :disabled="detailList.length <= 1"
+                >
+                  鍒犻櫎
+                </el-button>
+              </div>
+
+              <el-row :gutter="20" class="detail-row">
+                <el-col :span="6">
+                  <el-form-item
+                    required
+                    :prop="'detailList.' + index + '.scrapProCode'"
+                    :rules="{ required: true, message: '璇烽�夋嫨浜у搧缂栫爜', trigger: 'blur' }"
+                  >
+                    <el-select
+                      v-model="detail.scrapProCode"
+                      filterable
+                      placeholder="浜у搧缂栫爜"
+                      @change="handleProCodeChange(detail, index)"
+                      clearable
+                      style="width: 100%;"
+                    >
+                      <el-option
+                        v-for="(code, index) in proCodeOptions"
+                        :key="index"
+                        :label="code"
+                        :value="code"
+                      ></el-option>
+                    </el-select>
+                  </el-form-item>
+                </el-col>
+
+                <el-col :span="5">
+                  <el-form-item
+                    required
+                    :prop="'detailList.' + index + '.scrapProVersion'"
+                    :rules="{ required: true, message: '璇烽�夋嫨鐗堟湰', trigger: 'blur' }"
+                  >
+                    <el-select
+                      v-model="detail.scrapProVersion"
+                      filterable
+                      placeholder="鐗堟湰"
+                      clearable
+                      style="width: 100%;"
+                    >
+                      <el-option
+                        v-for="item in detail.versionOptions"
+                        :key="item"
+                        :label="item"
+                        :value="item"
+                      ></el-option>
+                    </el-select>
+                  </el-form-item>
+                </el-col>
+
+                <el-col :span="5">
+                  <el-form-item
+                    required
+                    :prop="'detailList.' + index + '.scrapProLotNo'"
+                    :rules="{ required: true, message: '璇烽�夋嫨鎵规鍙�', trigger: 'blur' }"
+                  >
+                    <el-select
+                      v-model="detail.scrapProLotNo"
+                      filterable
+                      placeholder="鎵规鍙�"
+                      clearable
+                      style="width: 100%;"
+                    >
+                      <el-option
+                        v-for="item in detail.lotNoOptions"
+                        :key="item"
+                        :label="item"
+                        :value="item"
+                      ></el-option>
+                    </el-select>
+                  </el-form-item>
+                </el-col>
+
+                <el-col :span="4">
+                  <el-form-item
+                    required
+                    :prop="'detailList.' + index + '.scrapPcsQty'"
+                    :rules="{ 
+                      required: true, 
+                      message: '璇疯緭鍏CS鏁伴噺', 
+                      trigger: 'blur',
+                      validator: validateNumber // 鑷畾涔夋暟瀛楁牎楠�
+                    }"
+                  >
+                    <el-input
+                      v-model="detail.scrapPcsQty"
+                      placeholder="PCS鏁伴噺"
+                      style="width: 100%;"
+                      @blur="formatNumber(detail, 'scrapPcsQty')"
+                    ></el-input>
+                  </el-form-item>
+                </el-col>
+              </el-row>
+
+              <el-row :gutter="20" class="detail-row">
+                <el-col :span="24">
+                  <el-form-item label="澶囨敞锛�">
+                    <el-input
+                      v-model="detail.remark"
+                      placeholder="璇疯緭鍏ュ娉ㄤ俊鎭�"
+                      type="textarea"
+                      rows="2"
+                      style="width: 100%;"
+                    ></el-input>
+                  </el-form-item>
+                </el-col>
+              </el-row>
+            </div>
+
+            <!-- 娣诲姞鏄庣粏鎸夐挳 -->
+            <el-button
+              type="dashed"
+              size="small"
+              class="add-detail-btn"
+              @click="addDetail"
+              :disabled="detailList.length >= 10"
+              style="width: 100%; margin-top: 15px;"
+            >
+              <i class="el-icon-plus"></i> 娣诲姞鏄庣粏
+            </el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+
+      <!-- 搴曢儴鎸夐挳 -->
+      <template #footer>
+        <el-button type="primary" size="mini" @click="submitForm" style="padding: 8px 20px;">纭鎻愪氦</el-button>
+        <el-button type="danger" size="mini" @click="close" style="padding: 8px 20px; margin-left: 10px;">鍏抽棴</el-button>
+      </template>
+    </vol-box>
+  </div>
+</template>
+
+<script>
+import VolBox from "@/components/basic/VolBox.vue";
+export default {
+  components: { VolBox },
+  data() {
+    const validateNumber = (rule, value, callback) => {
+      if (!value) {
+        return callback(new Error('璇疯緭鍏ユ暟閲�'));
+      }
+      const numberRegex = /^\d+(\.\d+)?$/;
+      if (!numberRegex.test(value)) {
+        return callback(new Error('璇疯緭鍏ユ湁鏁堢殑鏁板瓧'));
+      }
+      if (parseFloat(value) <= 0) {
+        return callback(new Error('鏁伴噺蹇呴』澶т簬0'));
+      }
+      callback();
+    };
+
+    return {
+      showDetialBox: false,
+      warehouses: [],
+      proCodeOptions: [],
+      form: {
+        warehouseId: "",
+        proScrapSheetOrderNo: ""
+      },
+
+      detailList: [
+        {
+          scrapProCode: "",
+          scrapProVersion: "",
+          scrapProLotNo: "",
+          scrapPcsQty: "",  
+          remark: "",
+          versionOptions: [],
+          lotNoOptions: []
+        }
+      ],
+      validateNumber
+    };
+  },
+  methods: {
+    // 鎵撳紑寮圭獥
+    open() {
+      this.initForm();
+      this.showDetialBox = true;
+    },
+
+    // 鍒濆鍖栬〃鍗�
+    initForm() {
+      this.form = {
+        warehouseId: "",
+        proScrapSheetOrderNo: ""
+      };
+      this.detailList = [this.createEmptyDetail()];
+      
+      // 鍔犺浇浠撳簱鍒楄〃
+      if (this.warehouses.length === 0) {
+        this.getWarehouseList();
+      }
+    },
+
+    // 鍒涘缓绌烘槑缁�
+    createEmptyDetail() {
+      return {
+        scrapProCode: "",
+        scrapProVersion: "",
+        scrapProLotNo: "",
+        scrapPcsQty: "",  
+        remark: "",
+        versionOptions: [],
+        lotNoOptions: []
+      };
+    },
+
+    // 鑾峰彇浠撳簱鍒楄〃
+    getWarehouseList() {
+      this.http
+        .post("api/Warehouse/GetWarehouseDicByUser", null, "鍔犺浇浠撳簱鏁版嵁涓�")
+        .then((res) => {
+          if (!res.status) return this.$message.error(res.message);
+          this.warehouses = res.data || [];
+          // 鑻ュ彧鏈変竴涓粨搴擄紝鑷姩閫変腑
+          if (this.warehouses.length === 1) {
+            this.form.warehouseId = this.warehouses[0].key;
+            this.handleWarehouseChange(this.warehouses[0].key);
+          }
+        });
+    },
+
+    // 浠撳簱鍙樻洿浜嬩欢
+    handleWarehouseChange(warehouseId) {
+      if (!warehouseId) return;
+      // 鏍规嵁浠撳簱ID鍔犺浇浜у搧缂栫爜鍒楄〃
+      this.http
+        .post(`api/ProStockInfo/GetProCodeByWarehouse?warehouseId=${this.form.warehouseId}`,null, "鍔犺浇浜у搧鏁版嵁涓�")
+        .then((res) => {
+          if (res.status) {
+            this.proCodeOptions = [...new Set(res.data)];
+          } else {
+            this.$message.error(res.message);
+          }
+        });
+    },
+
+    // 浜у搧缂栫爜鍙樻洿浜嬩欢
+    handleProCodeChange(detail, index) {
+      if (!detail.scrapProCode) {
+        detail.versionOptions = [];
+        detail.lotNoOptions = [];
+        return;
+      }
+
+      // 鏍规嵁浜у搧缂栫爜鍔犺浇鐗堟湰鍒楄〃
+      this.http
+      .post(
+        `api/ProStockInfo/GetProVersionByCode?scrapProCode=${detail.scrapProCode}&warehouseId=${this.form.warehouseId}`,null, "鍔犺浇鐗堟湰鏁版嵁涓�")
+        .then((res) => {
+          if (res.status) {
+            detail.versionOptions = [...new Set(res.data)];
+          }
+        });
+
+      // 鏍规嵁浜у搧缂栫爜鍔犺浇鎵规鍙峰垪琛�
+      this.http
+        .post(`api/ProStockInfo/GetProLotNoByCode?scrapProCode=${detail.scrapProCode}&warehouseId=${this.form.warehouseId}`,null, "鍔犺浇鎵规鏁版嵁涓�")
+        .then((res) => {
+          if (res.status) {
+            detail.lotNoOptions = [...new Set(res.data)];
+          }
+        });
+    },
+
+    formatNumber(detail, field) {
+      if (!detail[field]) return;
+      
+      let value = detail[field].replace(/[^0-9.]/g, '');
+      
+      const decimalIndex = value.indexOf('.');
+      if (decimalIndex !== -1) {
+        value = value.substring(0, decimalIndex + 1) + value.substring(decimalIndex + 1).replace(/\./g, '');
+      }
+      
+      const parts = value.split('.');
+      if (parts.length > 1 && parts[1].length > 2) {
+        parts[1] = parts[1].substring(0, 2);
+        value = parts.join('.');
+      }
+      
+      detail[field] = value;
+    },
+
+    // 娣诲姞鏄庣粏
+    addDetail() {
+      this.detailList.push(this.createEmptyDetail());
+    },
+
+    // 鍒犻櫎鏄庣粏
+    removeDetail(index) {
+      this.detailList.splice(index, 1);
+    },
+
+    // 鎻愪氦琛ㄥ崟
+    submitForm() {
+  if (!this.form.warehouseId) {
+    return this.$message.error("璇烽�夋嫨鎵�灞炰粨搴�");
+  }
+
+  const invalidDetail = this.detailList.find(item => 
+    !item.scrapProCode || !item.scrapProVersion || !item.scrapProLotNo || !item.scrapPcsQty  || isNaN(parseFloat(item.scrapPcsQty))|| parseFloat(item.scrapPcsQty) <= 0
+  );
+  
+  if (invalidDetail) {
+    return this.$message.error("璇蜂负鎵�鏈夋槑缁嗚緭鍏ユ湁鏁堢殑鏁伴噺鍊硷紙澶т簬0鐨勬暟瀛楋級");
+  }
+
+  const submitData = {
+    warehouseId: this.form.warehouseId,
+    details: this.detailList.map(item => ({
+      scrapProCode: item.scrapProCode,
+      scrapProVersion: item.scrapProVersion,
+      scrapProLotNo: item.scrapProLotNo,
+      scrapPcsQty: parseFloat(item.scrapPcsQty),
+      remark: item.remark
+    }))
+  };
+
+  this.http
+    .post("api/ErpProScrapSheet/Save", submitData, "鎻愪氦涓�")
+    .then((res) => {
+          if (!res.status) return this.$message.error(res.message);
+          this.$message.success("鎿嶄綔鎴愬姛");
+          this.close();
+          this.$emit("parentCall", ($vue) => {
+            $vue.refresh();
+          });
+        });
+    },
+
+    // 鍏抽棴寮圭獥
+    close() {
+      this.showDetialBox = false;
+    }
+  },
+  created() {
+    // 鍒濆鍖栨椂棰勫姞杞戒粨搴撴暟鎹�
+    if (this.warehouses.length === 0) {
+      this.getWarehouseList();
+    }
+  }
+};
+</script>
+
+<style scoped>
+.detail-item {
+  border: 1px solid #e4e7ed;
+  border-radius: 6px;
+  padding: 15px;
+  margin-bottom: 20px;
+  box-shadow: 0 2px 4px rgba(0,0,0,0.05);
+}
+
+.detail-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 15px;
+  padding-bottom: 10px;
+  border-bottom: 1px dashed #e4e7ed;
+  font-weight: 500;
+}
+
+.detail-row {
+  margin-bottom: 15px;
+}
+
+.add-detail-btn {
+  height: 40px;
+  line-height: 38px;
+}
+
+::-webkit-scrollbar {
+  width: 8px;
+  height: 8px;
+}
+::-webkit-scrollbar-thumb {
+  background-color: #ddd;
+  border-radius: 4px;
+}
+::-webkit-scrollbar-track {
+  background-color: #f5f5f5;
+}
+</style>
\ No newline at end of file
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSClient/src/extension/outbound/extend/ScrapSheet.vue" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSClient/src/extension/outbound/extend/ScrapSheet.vue"
index 61e5c50..b799198 100644
--- "a/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSClient/src/extension/outbound/extend/ScrapSheet.vue"
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSClient/src/extension/outbound/extend/ScrapSheet.vue"
@@ -236,20 +236,26 @@
             prop: "overScrapSETQty",
             title: "宸叉姤搴烻ET鏁�",
             type: "int",
-            width: 180,
+            width: 120,
           },
           {
             prop: "overScrapPcsQty",
             title: "宸叉姤搴烶CS鏁�",
             type: "string",
-            width: 180,
+            width: 120,
           },
           {
             prop: "scrapProDetailStatus",
             title: "璁㈠崟鏄庣粏鐘舵��",
             type: "string",
             width: 180,
-        }
+          },
+          {
+            prop: "remark",
+            title: "澶囨敞",
+            type: "string",
+            width: 180,
+          }
         ],
       };
     },
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSClient/src/views/basic/palletCodeInfo.vue" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSClient/src/views/basic/palletCodeInfo.vue"
index bcdf2bc..4a99502 100644
--- "a/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSClient/src/views/basic/palletCodeInfo.vue"
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSClient/src/views/basic/palletCodeInfo.vue"
@@ -29,20 +29,7 @@
     const editFormFields = ref({});
     const editFormOptions = ref([
       [
-        {
-          title: "浠撳簱",
-          field: "warehouseId",
-          type: "select",
-          dataKey: "warehouses",
-          data: [],
-          required: true,
-        },
-        {
-          title: "鏁伴噺",
-          field: "count",
-          type: "int",
-          required: true,
-        },
+        
       ],
     ]);
     const searchFormFields = ref({
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSServer/WIDESEA_DTO/Outbound/ErpProScrapSheetModel.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSServer/WIDESEA_DTO/Outbound/ErpProScrapSheetModel.cs"
new file mode 100644
index 0000000..a956510
--- /dev/null
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSServer/WIDESEA_DTO/Outbound/ErpProScrapSheetModel.cs"
@@ -0,0 +1,69 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using WIDESEA_Core.Attributes;
+
+namespace WIDESEA_DTO.Outbound
+{
+    /// <summary>
+    /// 鎴愬搧鎶ュ簾鍗曟柊澧�
+    /// </summary>
+    [ModelValidate]
+    public class ErpProScrapSheetModel
+    {
+        // <summary>
+        /// 浠撳簱Id
+        /// </summary>
+        [PropertyValidate("浠撳簱Id", NotNullAndEmpty = true)]
+        public int WarehouseId { get; set; }
+        /// <summary>
+        /// 鍗曟嵁缂栧彿
+        /// </summary>
+        [PropertyValidate("鍗曟嵁缂栧彿", NotNullAndEmpty = true)]
+        public string ProScrapSheetOrderNo { get; set; }
+        /// <summary>
+        /// 鎶ュ簾鏄庣粏
+        /// </summary>
+        [PropertyValidate("鎶ュ簾鏄庣粏", NotNullAndEmpty = true)]
+        public List<ErpProScrapSheetDetailDTO> Details { get; set; }
+    }
+
+    [ModelValidate]
+    public class ErpProScrapSheetDetailDTO
+    {
+        /// <summary>
+        /// 浜у搧缂栫爜
+        /// </summary>
+        [PropertyValidate("浜у搧缂栫爜", NotNullAndEmpty = true)]
+        public string ScrapProCode { get; set; }
+        /// <summary>
+        /// 鎶ュ簾鐗堟湰
+        /// </summary>
+        [PropertyValidate("鎶ュ簾鐗堟湰", NotNullAndEmpty = true)]
+        public string ScrapProVersion { get; set; }
+        /// <summary>
+        /// 鎵规鍙�
+        /// </summary>
+        [PropertyValidate("鎵规鍙�", NotNullAndEmpty = true)]
+        public string ScrapProLotNo { get; set; }
+        /// <summary>
+        /// 鎶ュ簾SET鏁伴噺
+        /// </summary>
+        [PropertyValidate("鎶ュ簾SET鏁伴噺", NotNullAndEmpty = true)]
+        public int ScrapSETQty { get; set; }
+        /// <summary>
+        /// 鎶ュ簾PCS鏁�
+        /// </summary>
+        [PropertyValidate("鎶ュ簾PCS鏁�", NotNullAndEmpty = true)]
+        public int ScrapPcsQty { get; set; }
+
+        /// <summary>
+        /// 澶囨敞
+        /// </summary>
+        [PropertyValidate("澶囨敞", NotNullAndEmpty = false)]
+        public string Remark { get; set; }
+    }
+    
+}
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSServer/WIDESEA_IOutboundService/IErpProScrapSheetService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSServer/WIDESEA_IOutboundService/IErpProScrapSheetService.cs"
index 112a79f..471a0ea 100644
--- "a/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSServer/WIDESEA_IOutboundService/IErpProScrapSheetService.cs"
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSServer/WIDESEA_IOutboundService/IErpProScrapSheetService.cs"
@@ -8,11 +8,13 @@
 using WIDESEA_Core;
 using WIDESEA_IOutboundRepository;
 using WIDESEA_Model.Models;
+using WIDESEA_DTO.Outbound;
 
 namespace WIDESEA_IOutboundService
 {
     public interface IErpProScrapSheetService : IService<Dt_ErpProScrapSheet>
     {
         IErpProScrapSheetRepository Repository { get; }
+        public WebResponseContent Save(ErpProScrapSheetModel addProScrapSheet);
     }
 }
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSServer/WIDESEA_IStockService/IProStockInfoService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSServer/WIDESEA_IStockService/IProStockInfoService.cs"
index 2b323b0..bc5158f 100644
--- "a/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSServer/WIDESEA_IStockService/IProStockInfoService.cs"
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSServer/WIDESEA_IStockService/IProStockInfoService.cs"
@@ -43,5 +43,23 @@
         /// 鑾峰彇鎴愬搧鎶ュ簾鐨勫簱瀛�
         /// </summary>
         List<Dt_ProStockInfo> GetOutboundStocks(List<Dt_ProStockInfo> stockInfos, Dt_ErpProScrapSheetDetail outOrderDetail, float needQuantity, out float residueQuantity);
+        /// <summary>
+        /// 鎶ュ簾鍗曞簱瀛樹骇鍝佺紪鍙锋煡璇�
+        /// </summary>
+        /// <param name="warehouseId"></param>
+        /// <returns></returns>
+        public WebResponseContent GetProCodeByWarehouse(int warehouseId);
+        /// <summary>
+        /// 鎶ュ簾鍗曞簱瀛樼増鏈煡璇�
+        /// </summary>
+        /// <param name="scrapProCode"></param>
+        /// <returns></returns>
+        public WebResponseContent GetProVersionByCode(string scrapProCode,int warehouseId);
+        /// <summary>
+        /// 鎶ュ簾鍗曞簱瀛樻壒娆″彿鏌ヨ
+        /// </summary>
+        /// <param name="scrapProCode"></param>
+        /// <returns></returns>
+        public WebResponseContent GetProLotNoByCode(string scrapProCode, int warehouseId);
     }
 }
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSServer/WIDESEA_OutboundService/ErpProScrapSheetService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSServer/WIDESEA_OutboundService/ErpProScrapSheetService.cs"
index 8ccb2c2..da53bab 100644
--- "a/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSServer/WIDESEA_OutboundService/ErpProScrapSheetService.cs"
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSServer/WIDESEA_OutboundService/ErpProScrapSheetService.cs"
@@ -1,4 +1,5 @@
-锘縰sing System;
+锘縰sing SqlSugar;
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
@@ -9,7 +10,12 @@
 using WIDESEA_Core;
 using WIDESEA_Core.BaseRepository;
 using WIDESEA_Core.BaseServices;
+using WIDESEA_Core.CodeConfigEnum;
+using WIDESEA_Core.DB;
 using WIDESEA_Core.Helper;
+using WIDESEA_Core.Seed;
+using WIDESEA_DTO.Outbound;
+using WIDESEA_IBasicService;
 using WIDESEA_IOutboundRepository;
 using WIDESEA_IOutboundService;
 using WIDESEA_Model.Models;
@@ -19,11 +25,14 @@
     public partial class ErpProScrapSheetService : ServiceBase<Dt_ErpProScrapSheet, IErpProScrapSheetRepository>, IErpProScrapSheetService
     {
         private readonly IUnitOfWorkManage _unitOfWorkManage;
+        private readonly IWarehouseService _warehouseService;
+
         public IErpProScrapSheetRepository Repository => BaseDal;
 
-        public ErpProScrapSheetService(IErpProScrapSheetRepository BaseDal, IUnitOfWorkManage unitOfWorkManage) : base(BaseDal)
+        public ErpProScrapSheetService(IErpProScrapSheetRepository BaseDal, IUnitOfWorkManage unitOfWorkManage,IWarehouseService warehouseService) : base(BaseDal)
         {
             _unitOfWorkManage = unitOfWorkManage;
+            _warehouseService = warehouseService;
         }
         public override WebResponseContent AddData(SaveModel saveModel)
         {
@@ -60,5 +69,104 @@
             }
             return base.AddData(saveModel);
         }
+        public WebResponseContent Save(ErpProScrapSheetModel addProScrapSheet) {
+            try
+            {
+                List<Dt_ErpProScrapSheetDetail> erpProScrapSheetDetails = new List<Dt_ErpProScrapSheetDetail>();
+                if (addProScrapSheet.Details != null)
+                {
+                    foreach (var model in addProScrapSheet.Details)
+                    {
+                        Dt_ErpProScrapSheetDetail erpProScrapSheetDetail = new Dt_ErpProScrapSheetDetail()
+                        {
+                            ScrapProCode = model.ScrapProCode,
+                            ScrapProVersion = model.ScrapProVersion,
+                            ScrapProLotNo = model.ScrapProLotNo,
+                            ScrapPcsQty = model.ScrapPcsQty,
+                            ScrapSETQty = 0,
+                        };
+                        erpProScrapSheetDetails.Add(erpProScrapSheetDetail);
+                    }
+                }
+                Dt_ErpProScrapSheet erpProScrapSheet = new Dt_ErpProScrapSheet()
+                {
+                    WarehouseId = addProScrapSheet.WarehouseId,
+                    ProScrapSheetOrderNo = CreateCodeByRule(nameof(RuleCodeEnum.ProScrapSheetRule)),
+                    ProScrapStatus = ProScrapSheetStatusEnum.TOChecked.ObjToInt(),
+                    Details = erpProScrapSheetDetails
+                };
+                _unitOfWorkManage.BeginTran();
+                Db.InsertNav(erpProScrapSheet).Include(x => x.Details).ExecuteCommand();
+                _unitOfWorkManage.CommitTran();
+                return WebResponseContent.Instance.OK();
+
+            }
+            catch(Exception ex)
+            {
+                _unitOfWorkManage.RollbackTran();
+                return WebResponseContent.Instance.Error(ex.Message);
+            }
+            
+        }
+        static object lock_code = new object();
+        public string CreateCodeByRule(string ruleCode)
+        {
+            lock (lock_code)
+            {
+
+                string code = string.Empty;
+                DateTime dateTime = DateTime.Now;
+                DateTime now = DateTime.Now;
+                try
+                {
+                    if (string.IsNullOrEmpty(ruleCode))
+                        throw new ArgumentNullException(nameof(ruleCode));
+                    SqlSugarClient sugarClient = new SqlSugarClient(new ConnectionConfig
+                    {
+                        IsAutoCloseConnection = true,
+                        DbType = DbType.SqlServer,
+                        ConnectionString = DBContext.ConnectionString
+                    });
+                    Dt_CodeRuleConfig codeRuleConfig = sugarClient.Queryable<Dt_CodeRuleConfig>().Where(x => x.RuleCode == ruleCode).First();
+                    if (codeRuleConfig == null)
+                        throw new ArgumentNullException(nameof(codeRuleConfig));
+                    if (codeRuleConfig.ModifyDate != null)
+                    {
+                        dateTime = Convert.ToDateTime(codeRuleConfig.ModifyDate);
+                    }
+                    else
+                    {
+                        dateTime = Convert.ToDateTime(codeRuleConfig.CreateDate);
+                    }
+
+                    if (now.Year == dateTime.Year && now.Month == dateTime.Month && now.Day == dateTime.Day)
+                    {
+                        now = dateTime;
+                        codeRuleConfig.CurrentVal = Convert.ToInt32(codeRuleConfig.CurrentVal) + 1;
+                    }
+                    else
+                    {
+                        codeRuleConfig.CurrentVal = 1;
+                    }
+                    codeRuleConfig.ModifyDate = DateTime.Now;
+                    code = codeRuleConfig.Format;
+                    code = code.Replace($"[{CodeFormatTypeEnum.YYYY}]", now.Year.ToString().PadLeft(4, '0'));
+                    code = code.Replace($"[{CodeFormatTypeEnum.MM}]", now.Month.ToString().PadLeft(2, '0'));
+                    code = code.Replace($"[{CodeFormatTypeEnum.DD}]", now.Day.ToString().PadLeft(2, '0'));
+                    code = code.Replace($"[{CodeFormatTypeEnum.ST}]", codeRuleConfig.StartStr?.ToString() ?? "");
+                    code = code.Replace($"[{CodeFormatTypeEnum.NUM}]", codeRuleConfig.CurrentVal.ToString().PadLeft(codeRuleConfig.Length, '0'));
+                    Dictionary<string, object> keyValuePairs = new Dictionary<string, object>() { { nameof(codeRuleConfig.CurrentVal), codeRuleConfig.CurrentVal }, { nameof(codeRuleConfig.Id), codeRuleConfig.Id }, { nameof(codeRuleConfig.ModifyDate), DateTime.Now } };
+                    sugarClient.Updateable(keyValuePairs).AS(MainDb.CodeRuleConfig).WhereColumns(nameof(codeRuleConfig.Id)).ExecuteCommand();
+                    sugarClient.Updateable(codeRuleConfig);
+
+                }
+                catch (Exception ex)
+                {
+
+                }
+                return code;
+            }
+        }
+
     }
 }
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSServer/WIDESEA_StockService/ProStockInfoService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSServer/WIDESEA_StockService/ProStockInfoService.cs"
index 07c8b06..a50e159 100644
--- "a/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSServer/WIDESEA_StockService/ProStockInfoService.cs"
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSServer/WIDESEA_StockService/ProStockInfoService.cs"
@@ -362,5 +362,52 @@
         //    }
         //    return (deleteStockDetails, updateStockDetails);
         //}
+        public WebResponseContent GetProCodeByWarehouse(int warehouseId)
+        {
+            try
+            {
+                List<Dt_ProStockInfo> proStockInfo = BaseDal.QueryData(x => x.WarehouseId == warehouseId);
+                List<int> proStockId = proStockInfo.Select(x => x.Id).ToList();
+                List<Dt_ProStockInfoDetail> proStockInfoDetails = BaseDal.Db.Queryable<Dt_ProStockInfoDetail>().Where(x => proStockId.Contains(x.OutDetailId)).ToList();
+                List<string> proCode = proStockInfoDetails.Select(x => x.ProductCode).ToList();
+                return WebResponseContent.Instance.OK(data: proCode);
+            }
+            catch (Exception ex)
+            {
+                return WebResponseContent.Instance.Error(ex.Message);
+            }
+        }
+
+        public WebResponseContent GetProVersionByCode(string scrapProCode, int warehouseId)
+        {
+            try
+            {
+                List<Dt_ProStockInfo> proStockInfo = BaseDal.QueryData(x => x.WarehouseId == warehouseId);
+                List<int> proStockId = proStockInfo.Select(x => x.Id).ToList();
+                List<Dt_ProStockInfoDetail> proStockInfoDetails = BaseDal.Db.Queryable<Dt_ProStockInfoDetail>().Where(x => scrapProCode.Contains(x.ProductCode) && proStockId.Contains(x.OutDetailId)).ToList();
+                List<string> productVersion = proStockInfoDetails.Select(x => x.ProductVersion).ToList();
+                return WebResponseContent.Instance.OK(data: productVersion);
+            }
+            catch (Exception ex)
+            {
+                return WebResponseContent.Instance.Error(ex.Message);
+            }
+        }
+
+        public WebResponseContent GetProLotNoByCode(string scrapProCode, int warehouseId)
+        {
+            try
+            {
+                List<Dt_ProStockInfo> proStockInfo = BaseDal.QueryData(x => x.WarehouseId == warehouseId);
+                List<int> proStockId = proStockInfo.Select(x => x.Id).ToList();
+                List<Dt_ProStockInfoDetail> proStockInfoDetails = BaseDal.Db.Queryable<Dt_ProStockInfoDetail>().Where(x => scrapProCode.Contains(x.ProductCode) && proStockId.Contains(x.OutDetailId)).ToList();
+                List<string> lotNumber = proStockInfoDetails.Select(x => x.LotNumber).ToList();
+                return WebResponseContent.Instance.OK(data: lotNumber);
+            }
+            catch (Exception ex)
+            {
+                return WebResponseContent.Instance.Error(ex.Message);
+            }
+        }
     }
 }
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Outbound/ErpProScrapSheetController.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Outbound/ErpProScrapSheetController.cs"
index a58f2ff..a03bbb0 100644
--- "a/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Outbound/ErpProScrapSheetController.cs"
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Outbound/ErpProScrapSheetController.cs"
@@ -4,6 +4,7 @@
 using WIDESEA_Core;
 using WIDESEA_IOutboundService;
 using WIDESEA_Model.Models;
+using WIDESEA_DTO.Outbound;
 
 namespace WIDESEA_WMSServer.Controllers.Outbound
 {
@@ -17,5 +18,10 @@
         public ErpProScrapSheetController(IErpProScrapSheetService service) : base(service)
         {
         }
+        [HttpGet,HttpPost,Route("Save"),AllowAnonymous]
+        public WebResponseContent Save([FromBody] ErpProScrapSheetModel addProScrapSheet)
+        {
+            return Service.Save(addProScrapSheet);
+        }
     }
 }
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Stock/ProStockInfoController.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Stock/ProStockInfoController.cs"
index 31a7ca6..36f7c5f 100644
--- "a/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Stock/ProStockInfoController.cs"
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Stock/ProStockInfoController.cs"
@@ -1,4 +1,6 @@
-锘縰sing Microsoft.AspNetCore.Mvc;
+锘縰sing Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using WIDESEA_Core;
 using WIDESEA_Core.BaseController;
 using WIDESEA_IStockService;
 using WIDESEA_Model.Models;
@@ -15,5 +17,37 @@
         public ProStockInfoController(IProStockInfoService service) : base(service)
         {
         }
+
+        /// <summary>
+        /// 鎶ュ簾鍗曞簱瀛樹骇鍝佺紪鍙锋煡璇�
+        /// </summary>
+        /// <param name="warehouseId"></param>
+        /// <returns></returns>
+        [HttpPost,HttpGet,Route("GetProCodeByWarehouse"),AllowAnonymous]
+        public WebResponseContent GetProCodeByWarehouse(int warehouseId)
+        {
+            return Service.GetProCodeByWarehouse(warehouseId);
+        }
+        /// <summary>
+        /// 鎶ュ簾鍗曞簱瀛樼増鏈煡璇�
+        /// </summary>
+        /// <param name="warehouseId"></param>
+        /// <returns></returns>
+        [HttpPost, HttpGet, Route("GetProVersionByCode"), AllowAnonymous]
+        public WebResponseContent GetProVersionByCode(string scrapProCode,int warehouseId)
+        {
+            return Service.GetProVersionByCode(scrapProCode,warehouseId);
+        }
+
+        /// <summary>
+        /// 鎶ュ簾鍗曞簱瀛樼増鏈煡璇�
+        /// </summary>
+        /// <param name="warehouseId"></param>
+        /// <returns></returns>
+        [HttpPost, HttpGet, Route("GetProLotNoByCode"), AllowAnonymous]
+        public WebResponseContent GetProLotNoByCode(string scrapProCode, int warehouseId)
+        {
+            return Service.GetProLotNoByCode(scrapProCode, warehouseId);
+        }
     }
 }

--
Gitblit v1.9.3