ÏîÄ¿´úÂë/WIDESEA_WMSClient/config/buttons.js
@@ -284,7 +284,7 @@ onClick: function () { } },{ name: "å æ® ç ç¹ æ ä½", name: "å æ® ç äº æ ä½", icon: '', class: '', value: 'OrderStockTake', @@ -315,7 +315,7 @@ type: 'warning', onClick: function () { } },,{ },{ name: "å ³éåæ®", icon: '', class: '', @@ -323,7 +323,23 @@ type: 'warning', onClick: function () { } }, },{ name: "çäºæåæä½", icon: '', class: '', value: 'OutOrderStockTake', type: 'warning', onClick: function () { } },{ name: "çäºç»çæä½", icon: '', class: '', value: 'StockTakeGroupPallet', type: 'warning', onClick: function () { } } ] export default buttons ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/inbound/extend/OrderStockTake.vue
@@ -15,7 +15,7 @@ </el-tag> </div> <!-- æ ¸å¿è¾å ¥è¡¨å --> <!-- æ ¸å¿è¾å ¥è¡¨åï¼ç§»é¤æææ ¡éªè§å --> <el-form :model="formData" ref="formRef" @@ -23,20 +23,8 @@ class="stock-take-form" @submit.prevent > <!-- æç®±å·è¾å ¥æ¡ --> <el-form-item label="æç®±å·ï¼" name="boxNo" :rules="[ { required: true, message: 'è¯·æ«ææè¾å ¥æç®±å·', trigger: 'blur', }, { validator: validateBoxNo, trigger: 'blur' }, ]" class="form-item" > <!-- æç®±å·è¾å ¥æ¡ï¼ç§»é¤æ ¡éªè§å --> <el-form-item label="æç®±å·ï¼" name="boxNo" class="form-item"> <el-input ref="boxNoInputRef" v-model="formData.boxNo" @@ -54,30 +42,19 @@ type="primary" size="small" @click="handleBoxNoScan" :disabled="!formData.boxNo.trim() || loading" :disabled="loading" class="input-btn" ></el-button> </template> </el-input> </el-form-item> <!-- æ°å¢ï¼ç«å°éæ©ä¸ææ¡ --> <el-form-item label="ååºç«å°ï¼" name="station" :rules="[ { required: true, message: 'è¯·éæ©ååºç«å°', trigger: 'blur', }, ]" class="form-item" > <!-- ç«å°éæ©ä¸ææ¡ï¼ç§»é¤æ ¡éªè§å --> <el-form-item label="ååºç«å°ï¼" name="station" class="form-item"> <el-select v-model="selectedStation" placeholder="è¯·éæ©ååºç«å°" :disabled="!formData.boxNo.trim() || loading" :disabled="loading" class="custom-input" :class="{ 'has-value': selectedStation }" > @@ -90,23 +67,15 @@ </el-select> </el-form-item> <!-- æ¡ç è¾å ¥æ¡ --> <el-form-item label="çç¹æ¡ç ï¼" name="barcode" :rules="[ { required: true, message: 'è¯·æ«ææè¾å ¥æ¡ç ', trigger: 'blur' }, { validator: validateBarcode, trigger: 'blur' }, ]" class="form-item" > <!-- æ¡ç è¾å ¥æ¡ï¼ç§»é¤æ ¡éªè§å --> <el-form-item label="çç¹æ¡ç ï¼" name="barcode" class="form-item"> <el-input ref="barcodeInputRef" v-model="formData.barcode" placeholder="è¯·ä½¿ç¨æ«ç æªæ«ææ¡ç ï¼ææå¨è¾å ¥" clearable @keydown.enter="debouncedHandleBarcodeScan" :disabled="!formData.boxNo.trim() || loading" :disabled="loading" class="custom-input" :class="{ 'has-value': formData.barcode.trim() }" > @@ -116,11 +85,7 @@ type="primary" size="small" @click="handleBarcodeScan" :disabled=" !formData.boxNo.trim() || !formData.barcode.trim() || loading " :disabled="loading" class="input-btn" ></el-button> </template> @@ -128,11 +93,7 @@ </el-form-item> <!-- åºåæ°éæ¡ï¼åªè¯»ï¼ --> <el-form-item label="åºåæ°éï¼" name="stockQuantity" class="form-item" > <el-form-item label="åºåæ°éï¼" name="stockQuantity" class="form-item"> <el-input v-model="formData.stockQuantity" placeholder="æ«ææ¡ç åèªå¨å¡«å " @@ -142,41 +103,25 @@ ></el-input> </el-form-item> <!-- å®é çç¹æ°é --> <el-form-item label="å®é çç¹æ°éï¼" name="actualQuantity" :rules="[ { required: true, message: '请è¾å ¥å®é çç¹æ°é', trigger: 'blur', }, { type: 'number', message: '请è¾å ¥ææçæ°å', trigger: 'blur' }, { validator: validateActualQuantity, trigger: 'blur' }, ]" class="form-item" > <!-- å®é çç¹æ°éï¼åªè¯»ï¼é»è®¤0 --> <el-form-item label="å®é çç¹æ°éï¼" name="actualQuantity" class="form-item"> <el-input v-model.number="formData.actualQuantity" placeholder="请è¾å ¥å®é çç¹æ°é" type="number" clearable @keydown.enter="handleStockTakeComplete" :disabled="!formData.stockQuantity || loading" class="custom-input" v-model="formData.actualQuantity" placeholder="é»è®¤å¼ä¸º0" readonly class="custom-input custom-readonly-input" :class="{ 'has-value': formData.actualQuantity !== '' }" ></el-input> </el-form-item> </el-form> <!-- æä½æé®åºå --> <!-- æä½æé®åºåï¼ç®åç¦ç¨é»è¾ --> <div class="action-buttons"> <el-button type="info" size="small" @click="handleBoxReturn" :disabled="!formData.boxNo.trim() || !selectedStation || loading" :disabled="loading" class="return-btn" > <Return /> æç®±ååº @@ -185,7 +130,7 @@ type="primary" size="small" @click="handleStockTakeComplete" :disabled="isFormCompleteDisabled" :disabled="loading" class="complete-btn" > <Check /> çç¹å®æ @@ -211,7 +156,6 @@ import VolBox from "@/components/basic/VolBox.vue"; import http from "@/api/http"; // æ°å¢ï¼å¼å ¥ç«å°ç®¡çå·¥å ·ï¼å示ä¾ä»£ç ä¿æä¸è´ï¼ import { stationManager, STATION_STORAGE_KEY } from "@/../src/uitils/stationManager"; // ååºå¼åé - åæ®å· @@ -225,18 +169,18 @@ const formData = reactive({ boxNo: "", // æç®±å· barcode: "", // çç¹æ¡ç stockQuantity: "", // åºåæ°éï¼åªè¯»ï¼ actualQuantity: "", // å®é çç¹æ°é stockQuantity: "", // åºåæ°é actualQuantity: 0, // å®é çç¹æ°éé»è®¤0 }); const loading = ref(false); const formRef = ref(null); // æ°å¢ï¼ç«å°ç¸å ³ååºå¼æ°æ®ï¼ä»¿ç §ç¤ºä¾ä»£ç ï¼ // ç«å°ç¸å ³ååºå¼æ°æ® const stations = ref([ { label: "ç«å°2", value: "2-1" }, { label: "ç«å°3", value: "3-1" }, ]); const selectedStation = ref(stationManager.getStation() || ""); // é»è®¤éä¸ç¼åçç«å° const selectedStation = ref(stationManager.getStation() || ""); // 模æ¿å¼ç¨ const boxNoInputRef = ref(null); @@ -247,39 +191,24 @@ return window.innerWidth < 768; }); // 计ç®å±æ§ï¼çç¹å®ææé®æ¯å¦ç¦ç¨ const isFormCompleteDisabled = computed(() => { return ( loading.value || !formData.boxNo.trim() || !formData.barcode.trim() || !formData.stockQuantity || formData.actualQuantity === "" || formData.actualQuantity === null || formData.actualQuantity === undefined || Number(formData.actualQuantity) < 0 // å°äº0æ¶ç¦ç¨ï¼0æ¯å 许ç ); }); // ç»ä»¶æè½½æ¶èç¦å°æç®±å·è¾å ¥æ¡ onMounted(() => { nextTick(() => { boxNoInputRef.value?.focus(); }); // çå¬çªå£å¤§å°åå window.addEventListener("resize", () => {}); }); // çå¬æç®±å·ååï¼æ¸ 空åç»ç¸å ³å段 // çå¬æç®±å·ååï¼æ¸ 空åç»ç¸å ³å段ï¼ä» ä¿çåºç¡æ¸ 空é»è¾ï¼ watch( () => formData.boxNo, (newVal) => { if (!newVal.trim()) { formData.barcode = ""; formData.stockQuantity = ""; formData.actualQuantity = ""; // æ°å¢ï¼æç®±å·æ¸ 空æ¶ï¼éç½®ç«å°éæ© formData.actualQuantity = 0; selectedStation.value = stationManager.getStation() || ""; orderNo.value = ""; } }, { immediate: true } @@ -296,17 +225,16 @@ }; }; // æå¼å¼¹çªå¹¶æ¥æ¶åæ®å· const open = (receiptNo) => { // æå¼å¼¹çª const open = () => { showStockTakeBox.value = true; orderNo.value = receiptNo; // é置表å formData.boxNo = ""; formData.barcode = ""; formData.stockQuantity = ""; formData.actualQuantity = ""; // æ°å¢ï¼æå¼å¼¹çªæ¶éç½®ç«å°éæ©ï¼é»è®¤åç¼åçç«å°ï¼ formData.actualQuantity = 0; selectedStation.value = stationManager.getStation() || ""; orderNo.value = ""; nextTick(() => { boxNoInputRef.value?.focus(); }); @@ -321,43 +249,6 @@ orderNo.value = ""; }; // æç®±å·éªè¯ï¼ä¼åï¼æå¼æ¶ä» éªè¯é¿åº¦ï¼æ 弿¶è§¦åå¿ å¡«ï¼ const validateBoxNo = (rule, value, callback) => { // æå¼æ¶éªè¯é¿åº¦ if (value && value.trim().length < 3) { callback(new Error("æç®±å·é¿åº¦ä¸è½å°äº3ä½")); } // æ 弿¶ç±requiredè§åå¤çï¼è¿éä¸éå¤æç¤º else { callback(); } }; // æ¡ç éªè¯ï¼ä¼åï¼æå¼æ¶ä» éªè¯é¿åº¦ï¼ const validateBarcode = (rule, value, callback) => { if (value && value.trim().length < 6) { callback(new Error("æ¡ç é¿åº¦ä¸è½å°äº6ä½")); } else { callback(); } }; // å®é çç¹æ°ééªè¯ï¼å 许0ï¼ä½ä¸å 许å°äº0 const validateActualQuantity = (rule, value, callback) => { // 空å¼ç±requiredè§åå¤çï¼è¿éåªéªè¯æ°å¼åæ³æ§ if (value === null || value === undefined || value === "") { callback(); // 空å¼ä¸å¨è¿éæç¤ºï¼äº¤ç»requiredè§å } // éªè¯æ°å¼æ¯å¦å°äº0 else if (value < 0) { callback(new Error("å®é çç¹æ°éä¸è½å°äº0")); } // éªè¯éè¿ï¼å 许0ï¼ else { callback(); } }; // æç®±å·å¤±ç¦å¤ç const handleBoxNoBlur = () => { if (formData.boxNo.trim() && boxNoInputRef.value?.input) { @@ -365,39 +256,29 @@ } }; // æç®±å·æ«æéªè¯ï¼å端æ¥å£ï¼ const validateBoxNoApi = async (boxNo) => { // æç®±å·æ«æå¤çï¼ç§»é¤åç«¯æ ¡éªï¼ç´æ¥è°ç¨æ¥å£ const handleBoxNoScan = async () => { const boxNo = formData.boxNo.trim(); if (!boxNo) { ElMessage.warning("请è¾å ¥æç®±å·"); return; } try { loading.value = true; // ç´æ¥è°ç¨æ¥å£ï¼ä¸ååç«¯æ ¡éª const res = await http.post( `/api/TakeStockOrder/ValidateBoxNo?orderNo=${encodeURIComponent( orderNo.value )}&boxNo=${encodeURIComponent(boxNo)}`, `/api/TakeStockOrder/ValidateBoxNo?orderNo=${encodeURIComponent(orderNo.value)}&boxNo=${encodeURIComponent(boxNo)}`, "éªè¯æç®±å·ä¸..." ); if (!res.status) { throw new Error(res.message || "æç®±å·éªè¯å¤±è´¥"); } return res.data; } catch (error) { throw error; if (res.data?.takeStockOrder) { orderNo.value = res.data.takeStockOrder; } }; // æç®±å·æ«æå¤ç const handleBoxNoScan = async () => { if (!formRef.value) return; // æå¨è§¦åéªè¯ï¼ä» éªè¯å½ååæ®µï¼ const valid = await formRef.value.validateField("boxNo"); if (valid !== true) return; const boxNo = formData.boxNo.trim(); if (!boxNo) return; try { loading.value = true; await validateBoxNoApi(boxNo); ElMessage.success(`æç®±å· ${boxNo} éªè¯éè¿`); ElMessage.success(`æç®±å· ${boxNo} éªè¯éè¿ï¼åæ®å·ï¼${orderNo.value}`); nextTick(() => { barcodeInputRef.value?.focus(); }); @@ -413,13 +294,20 @@ } }; // æ¡ç æ«æéªè¯ï¼å端æ¥å£ï¼ const validateBarcodeApi = async (boxNo, barcode) => { // æ¡ç æ«æå¤çï¼ç§»é¤åç«¯æ ¡éªï¼ç´æ¥è°ç¨æ¥å£ const handleBarcodeScan = async () => { const boxNo = formData.boxNo.trim(); const barcode = formData.barcode.trim(); if (!boxNo || !barcode) { ElMessage.warning("请è¾å ¥æç®±å·åæ¡ç "); return; } try { loading.value = true; // ç´æ¥è°ç¨æ¥å£ï¼ä¸ååç«¯æ ¡éª const res = await http.post( `/api/TakeStockOrder/ValidateBarcode?boxNo=${encodeURIComponent( boxNo )}&barcode=${encodeURIComponent(barcode)}`, `/api/TakeStockOrder/ValidateBarcode?boxNo=${encodeURIComponent(boxNo)}&barcode=${encodeURIComponent(barcode)}`, "éªè¯æ¡ç ä¸..." ); @@ -427,41 +315,13 @@ throw new Error(res.message || "æ¡ç éªè¯å¤±è´¥"); } if ( res.data?.stockQuantity === undefined || res.data?.stockQuantity === null ) { throw new Error("æªæ¥è¯¢å°è¯¥æ¡ç çåºåæ°é"); if (res.data?.stockQuantity !== undefined && res.data?.stockQuantity !== null) { formData.stockQuantity = res.data.stockQuantity; } return res.data; } catch (error) { throw error; } }; // æ¡ç æ«æå¤ç const handleBarcodeScan = async () => { if (!formRef.value) return; const valid = await formRef.value.validateField("barcode"); if (valid !== true) return; const boxNo = formData.boxNo.trim(); const barcode = formData.barcode.trim(); if (!boxNo || !barcode) return; try { loading.value = true; const result = await validateBarcodeApi(boxNo, barcode); formData.stockQuantity = result.stockQuantity; ElMessage.success( `æ¡ç ${barcode} éªè¯éè¿ï¼åºåæ°éï¼${result.stockQuantity}` ); ElMessage.success(`æ¡ç ${barcode} éªè¯éè¿ï¼åºåæ°éï¼${formData.stockQuantity}`); nextTick(() => { const actualQuantityInput = document.querySelector( ".form-item:last-child .el-input__inner" ); actualQuantityInput?.focus(); const actualQuantityInput = document.querySelector(".form-item:last-child .el-input__inner"); actualQuantityInput?.blur(); }); } catch (error) { ElMessage.error(error.message); @@ -475,32 +335,33 @@ } }; // çç¹å®ææäº¤ // çç¹å®ææäº¤ï¼å®å ¨ç§»é¤åç«¯æ ¡éªï¼ç´æ¥ä¼ å¼ç»å端 const handleStockTakeComplete = async () => { if (!formRef.value) return; // å ¨è¡¨åéªè¯ const valid = await formRef.value.validate(); if (!valid) return; // é¢å¤æ£æ¥å®é çç¹æ°éæ¯å¦å°äº0 if (formData.actualQuantity < 0) { ElMessage.error("å®é çç¹æ°éä¸è½å°äº0"); // ä» åæåºç¡ç空æç¤ºï¼å¯éï¼ä¹å¯ä»¥å»æï¼ if (!formData.boxNo.trim()) { ElMessage.warning("请è¾å ¥æç®±å·"); return; } if (!formData.barcode.trim()) { ElMessage.warning("请è¾å ¥æ¡ç "); return; } // ç´æ¥è·åææå¼ï¼ä¸å任使 ¡éª const { boxNo, barcode, actualQuantity, stockQuantity } = formData; const receiptNo = orderNo.value; try { loading.value = true; // ç´æ¥ä¼ å¼ç»å端ï¼ä¸åä»»ä½åç«¯æ ¡éª const res = await http.post( "/api/TakeStockOrder/CompleteStockTake", { orderNo: receiptNo, boxNo, barcode, actualQuantity, actualQuantity, // åºå®ä¼ 0 stockQuantity, }, { @@ -512,7 +373,7 @@ ElMessage.success("çç¹å®æï¼æäº¤æåï¼"); formData.barcode = ""; formData.stockQuantity = ""; formData.actualQuantity = ""; formData.actualQuantity = 0; nextTick(() => { barcodeInputRef.value?.focus(); }); @@ -527,16 +388,11 @@ } }; // æç®±ååºåè½ï¼æ ¸å¿ä¿®æ¹ï¼å¢å ç«å°éªè¯ + ä¼ å ¥sourceAddressåæ°ï¼ // æç®±ååºåè½ï¼ç®åæ ¡éªï¼ç´æ¥ä¼ å¼ const handleBoxReturn = async () => { const boxNo = formData.boxNo.trim(); // æ°å¢ï¼éªè¯ç«å°æ¯å¦éæ© if (!boxNo) { ElMessage.warning("请å è¾å ¥ææ«ææç®±å·"); return; } if (!selectedStation.value) { ElMessage.warning("è¯·éæ©ååºç«å°"); ElMessage.warning("请è¾å ¥æç®±å·"); return; } @@ -552,11 +408,9 @@ loading.value = true; // æ°å¢ï¼æ¼æ¥sourceAddressåæ°ï¼ç«å°æ°æ®ï¼å°æ¥å£è¯·æ±ä¸ // ç´æ¥ä¼ å¼ç»å端ï¼ä¸åä¸¥æ ¼æ ¡éª const res = await http.post( `/api/TakeStockOrder/ReturnBox?boxNo=${encodeURIComponent(boxNo)}&orderNo=${encodeURIComponent( orderNo.value )}&sourceAddress=${encodeURIComponent(selectedStation.value)}`, // æ°å¢sourceAddressåæ° `/api/TakeStockOrder/ReturnBox?boxNo=${encodeURIComponent(boxNo)}&orderNo=${encodeURIComponent(orderNo.value)}&sourceAddress=${encodeURIComponent(selectedStation.value)}`, "æç®±ååºä¸..." ); @@ -565,8 +419,9 @@ formData.boxNo = ""; formData.barcode = ""; formData.stockQuantity = ""; formData.actualQuantity = ""; selectedStation.value = stationManager.getStation() || ""; // éç½®ç«å°éæ© formData.actualQuantity = 0; selectedStation.value = stationManager.getStation() || ""; orderNo.value = ""; nextTick(() => { boxNoInputRef.value?.focus(); }); @@ -603,7 +458,7 @@ </script> <style scoped> /* 䏻容卿 ·å¼ - ä¼åé´è·åååºå¼ */ /* æ ·å¼å®å ¨ä¿çï¼æ ä¿®æ¹ */ .stock-take-container { width: 100%; display: flex; @@ -612,7 +467,6 @@ padding: 8px 0; } /* åæ®ä¿¡æ¯æ ·å¼ - ä¼åè§è§å±çº§ */ .receipt-info { margin-bottom: 4px; } @@ -633,7 +487,6 @@ margin-left: 6px; } /* è¡¨åæ ·å¼ - ä¼åé´å½±åå è¾¹è· */ .stock-take-form { width: 100%; background-color: #ffffff; @@ -647,17 +500,15 @@ margin-bottom: 16px; } /* è¾å ¥æ¡æ ¸å¿æ ·å¼ - ä¼åç¶ææ¾ç¤º */ .custom-input { width: 100%; position: relative; } /* æå¼æ¶éèå ä½ç¬¦ + ä¼åè¾¹æ¡ */ .custom-input.has-value :deep(.el-input__inner), .custom-input.has-value :deep(.el-select__wrapper) { --el-input-placeholder-color: transparent; /* éèå ä½ç¬¦ */ border-color: #8cc5ff; /* æµ èè¾¹æ¡ï¼åºåæ å¼ç¶æ */ --el-input-placeholder-color: transparent; border-color: #8cc5ff; background-color: #ffffff; } @@ -673,7 +524,6 @@ padding: 0 12px; } /* èç¦æ ·å¼ä¼å */ .custom-input :deep(.el-input__inner:focus), .custom-input :deep(.el-select__wrapper:focus) { border-color: #409eff; @@ -682,7 +532,6 @@ outline: none; } /* æ¸ é¤æé®æ ·å¼ä¼å */ .custom-input :deep(.el-input__clear) { color: #91c9f7; width: 18px; @@ -693,7 +542,6 @@ color: #409eff; } /* åªè¯»è¾å ¥æ¡æ ·å¼ - å¢å¼ºåºå度 */ .custom-readonly-input :deep(.el-input__inner) { background-color: #f0f8fb; color: #1989fa; @@ -703,7 +551,6 @@ padding-right: 12px; } /* è¾å ¥æ¡æé®æ ·å¼ - ä¼å尺寸åhoverææ */ .input-btn { border-radius: 0 8px 8px 0 !important; height: 42px; @@ -720,28 +567,23 @@ transform: translateY(-1px); } /* 表åéªè¯éè¯¯æ ·å¼ - å ³é®ï¼æå¼æ¶ä¸æ¾ç¤ºéè¯¯è¾¹æ¡ */ .form-item :deep(.el-form-item__error) { font-size: 12px; color: #f56c6c; margin-top: 4px; /* ä» å¨è¾å ¥æ¡ä¸ºç©ºä¸éªè¯å¤±è´¥æ¶æ¾ç¤º */ display: none; } /* åªæè¾å ¥æ¡ä¸ºç©º + éªè¯å¤±è´¥æ¶æ¾ç¤ºé误æç¤º */ .form-item:deep(.el-form-item--error) .custom-input:not(.has-value) + .el-form-item__error { display: block; } /* æå¼æ¶å³ä½¿éªè¯å¤±è´¥ï¼ä¹ä¸æ¾ç¤ºéè¯¯è¾¹æ¡ */ .custom-input.has-value :deep(.el-input__inner.el-input__inner--error), .custom-input.has-value :deep(.el-select__wrapper.el-select__wrapper--error) { border-color: #8cc5ff; box-shadow: none; } /* æä½æé®åºå - ä¼åé´è·åååºå¼ */ .action-buttons { display: flex; justify-content: flex-end; @@ -750,7 +592,6 @@ flex-wrap: wrap; } /* ååºæé®æ ·å¼ - ä¼åäº¤äº */ .return-btn { border-radius: 8px; padding: 9px 20px; @@ -779,7 +620,6 @@ box-shadow: none; } /* çç¹å®ææé®æ ·å¼ - ä¼åäº¤äº */ .complete-btn { border-radius: 8px; padding: 9px 20px; @@ -806,7 +646,6 @@ box-shadow: none; } /* åæ¶æé®æ ·å¼ - ä¼åç¹å»åºå */ .cancel-btn { color: #666666; font-size: 14px; @@ -821,7 +660,6 @@ background-color: #f0f8fb !important; } /* å¼¹çªæ´ä½æ ·å¼ - ä¼ååè§åé´å½± */ .custom-vol-box { border-radius: 16px !important; overflow: hidden; @@ -844,7 +682,6 @@ padding: 16px 24px; } /* ååºå¼éé - å°å±å¹ä¼å */ @media (max-width: 768px) { .stock-take-form { padding: 16px; @@ -869,14 +706,12 @@ </style> <style> /* å ¨å±è¡¥å æ ·å¼ - ç»ä¸ä¸»é¢ */ .el-tag--primary { --el-tag-bg-color: #e8f4f8; --el-tag-border-color: #409eff; --el-tag-text-color: #1989fa; } /* å ä½ç¬¦æ ·å¼ - ç»ä¸é¢è² */ .el-input__inner::-webkit-input-placeholder, .el-select__placeholder { color: #b3d8ff; @@ -901,7 +736,6 @@ font-size: 13px; } /* ä¿¡æ¯æé®å ¨å±æ ·å¼ */ .el-button--info { --el-button-bg-color: #e8f4f8; --el-button-border-color: #409eff; @@ -911,7 +745,6 @@ --el-button-hover-text-color: #1989fa; } /* ç¡®è®¤å¼¹çªæ ·å¼ä¼å */ .el-message-box { border-radius: 12px !important; box-shadow: 0 4px 20px rgba(64, 158, 255, 0.15); ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/inbound/extend/StockTakeGroupPallet.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,1124 @@ <template> <vol-box v-model="show" :title="'ç»çæä½ - åæ®å·ï¼' + orderNo" :height="1000" :width="1100" :padding="20" :modal="true"> <div class="barcode-scanner-container"> <!-- ä»åºéæ© - ç´§åå¸å± --> <div class="location-section compact"> <el-form :model="form" :rules="rules" ref="locationForm" class="compact-form"> <el-form-item label="å ¥åºä»åº" prop="warehouseType" class="location-select compact-item"> <el-select v-model="form.warehouseType" placeholder="è¯·éæ©ä»åº" clearable filterable @change="handleWarehouseChange" style="width: 100%" :loading="warehouseLoading" size="medium"> <el-option v-for="item in warehouseTypes" :key="item.warehouseType" :label="item.warehouseTypeDesc" :value="item.warehouseType" /> </el-select> </el-form-item> </el-form> </div> <!-- ä»åºåºåéæ© - ç´§åå¸å± --> <div class="location-section compact"> <el-form :model="form" :rules="rules" ref="locationForm" class="compact-form"> <el-form-item label="ä»åºåºå" prop="locationType" class="location-select compact-item"> <el-select v-model="form.locationType" placeholder="请å éæ©ä»åº" clearable filterable @change="handleLocationChange" style="width: 100%" :loading="locationLoading" size="medium"> <el-option v-for="item in locationTypes" :key="item.locationType" :label="item.locationTypeDesc" :value="item.locationType" /> </el-select> </el-form-item> </el-form> </div> <!-- æçä¿¡æ¯æ¾ç¤º - ç´§åå¸å± --> <div class="tray-info compact" v-if="trayBarcode"> <i class="el-icon-s-management"></i> å½åæç®±: {{ trayBarcode }} <span class="location-info" v-if="form.warehouseType"> | ä»åº: {{ currentWarehouseName }} </span> <span class="location-info" v-if="form.locationType"> | ä»åºåºå: {{ currentLocationDesc }} </span> </div> <!-- æ«ç åºå - ç´§åå¸å± --> <div class="input-section compact"> <el-card shadow="hover" class="compact-card"> <div slot="header" class="compact-header"> <span><i class="el-icon-scanner"></i> æ«ç åºå</span> <span class="scan-status"> <span class="scan-indicator"></span> {{ form.locationType && form.warehouseType ? 'æ«ç 就绪' : '请å éæ©ä»åºåä»åºåºå' }} </span> </div> <!-- æçæ¡ç è¾å ¥ --> <div class="input-wrapper custom-input-group compact-input"> <div class="input-label">æçæ¡ç </div> <el-input ref="trayInput" v-model="trayBarcode" placeholder="è¯·æ«ææè¾å ¥æç®±ç åæå车é®" clearable :disabled="!form.locationType || !form.warehouseType" @keyup.enter.native="handleTraySubmit" @clear="handleTrayClear" @input="handleTrayInput" class="custom-input" size="medium"> <template slot="append"> <el-button @click="handleTraySubmit" type="primary" icon="el-icon-position" :disabled="!form.locationType || !trayBarcode || !form.warehouseType" size="medium"> 确认 </el-button> </template> </el-input> </div> <!-- ç©ææ¡ç è¾å ¥ --> <div class="input-wrapper custom-input-group compact-input"> <div class="input-label">ç©ææ¡ç </div> <el-input ref="barcodeInput" v-model="barcode" placeholder="è¯·æ«ææè¾å ¥ç©ææ¡ç åæå车é®" clearable :disabled="!form.locationType || !trayBarcode || !form.warehouseType" @keyup.enter.native="handleBarcodeSubmit" @clear="handleClear" @input="handleBarcodeInput" class="custom-input" size="medium"> <template slot="append"> <el-button :loading="loading" @click="handleBarcodeSubmit" type="primary" icon="el-icon-search" :disabled="!form.locationType || !trayBarcode || !barcode || !from.warehouseType" size="medium"> {{ loading ? 'æ¥è¯¢ä¸...' : 'æ¥è¯¢' }} </el-button> </template> </el-input> </div> <div class="input-tips compact-tips"> <p>æç¤ºï¼è¯·å éæ©ä»åº â éæ©ä»åºåºå â è¾å ¥æç®±ç â è¾å ¥ç©ææ¡ç </p> <p v-if="!form.warehouseType" class="warning-text">â ï¸ è¯·å éæ©ä»åº</p> <p v-if="!form.locationType && !form.warehouseType" class="warning-text">â ï¸ è¯·å éæ©ä»åºåºå</p> <p v-if="form.warehouseType && form.locationType && !trayBarcode" class="warning-text">â ï¸ è¯·å è¾å ¥æç®±ç </p> </div> </el-card> </div> <!-- å è½½ç¶æ --> <div v-if="loading" class="loading compact"> <el-progress :percentage="100" status="success" :show-text="false" /> <p>æ£å¨æ¥è¯¢ç©æä¿¡æ¯...</p> </div> <!-- é误æç¤º --> <div v-if="error" class="error-message compact"> <el-alert :title="error" type="error" show-icon closable @close="error = ''" /> </div> <!-- æªç»çå表 --> <div class="unpallet-section compact"> <el-card shadow="hover" class="compact-card unpallet-card"> <div slot="header" class="compact-header"> <span><i class="el-icon-tickets"></i> æªç»çæ¡ç </span> <span class="list-actions"> <el-tag type="primary" size="small">æªç»ç {{ totalStockCount }}</el-tag> </span> </div> <div class="table-container"> <el-table :data="unpalletMaterials" stripe style="width: 100%" height="100%" size="small" v-loading="unpalletBarcodesLoading"> <el-table-column type="index" label="åºå·" width="60" align="center"></el-table-column> <el-table-column prop="barcode" label="æ¡ç " min-width="140" show-overflow-tooltip></el-table-column> <el-table-column prop="materielCode" label="ç©æç¼ç " min-width="150" show-overflow-tooltip></el-table-column> <el-table-column prop="batchNo" label="æ¹æ¬¡" min-width="150" show-overflow-tooltip></el-table-column> <el-table-column prop="orderQuantity" label="æ°é" min-width="130" align="right"></el-table-column> <el-table-column prop="unit" label="åä½" width="80" align="center"></el-table-column> <el-table-column prop="supplyCode" label="ä¾åºå" min-width="130" show-overflow-tooltip></el-table-column> </el-table> </div> </el-card> </div> <!-- ç©æå表 - åºå®é«åº¦å¸¦æ»å¨æ¡ --> <div class="material-list compact"> <el-card shadow="hover" class="compact-card"> <div slot="header" class="compact-header"> <span><i class="el-icon-tickets"></i> ç»çæ°æ®</span> <span class="list-actions"> <el-tag type="primary" size="small">å ± {{ materials.length }} æ¡</el-tag> <el-tag type="primary" size="small">æªå ¥åºæ°é {{ totalStockSum }}{{ uniqueUnit }}</el-tag> <el-tag v-if="trayBarcode" type="success" size="small">æç: {{ trayBarcode }}</el-tag> <el-tag v-if="form.warehouseType" type="info" size="small">ä»åº: {{ currentWarehouseName }}</el-tag> <el-tag v-if="form.locationType" type="info" size="small">åºå: {{ currentLocationDesc }}</el-tag> </span> </div> <div v-if="materials.length === 0" class="empty-state compact"> <i class="el-icon-document"></i> <p v-if="!form.warehouseType">请å éæ©ä»åº</p> <p v-if="!form.locationType">请å éæ©ä»åºåºå</p> <p v-else-if="!trayBarcode">请å è¾å ¥æç®±æ¡ç </p> <p v-else>ææ ç©ææ°æ®ï¼è¯·æ«ææè¾å ¥ç©ææ¡ç </p> </div> <div class="table-container" v-else> <el-table :data="materials" stripe style="width: 100%" height="100%" size="small"> <el-table-column type="index" label="åºå·" width="60" align="center"></el-table-column> <el-table-column prop="barcode" label="æ¡ç " min-width="140" show-overflow-tooltip></el-table-column> <el-table-column prop="materielCode" label="ç©æç¼ç " min-width="150" show-overflow-tooltip></el-table-column> <el-table-column prop="batchNo" label="æ¹æ¬¡" min-width="150" show-overflow-tooltip></el-table-column> <el-table-column prop="stockQuantity" label="æ°é" min-width="130" align="right"></el-table-column> <el-table-column prop="unit" label="åä½" width="80" align="center"></el-table-column> <el-table-column prop="supplyCode" label="ä¾åºå" min-width="130" show-overflow-tooltip></el-table-column> <el-table-column prop="warehouseType" label="ä»åº" min-width="120" show-overflow-tooltip></el-table-column> </el-table> </div> </el-card> </div> </div> <template #footer> <el-button type="danger" size="small" @click="handleDialogClose()">å ³é</el-button> </template> </vol-box> </template> <script> import http from '@/api/http.js'; import VolBox from '@/components/basic/VolBox.vue'; export default { components: { VolBox }, data() { return { show: false, orderNo: "", palletVisible: this.visible, trayBarcodeReg: /^[A-Z]\d{9}$/, trayBarcode: '', barcode: '', materials: [], loading: false, error: '', debugMode: false, currentFocus: 'warehouse', unpalletBarcodes: [], unpalletBarcodesLoading: false, unpalletMaterials: [], // æªç»çè¯¦ç»æ°æ®å表 // æ«ç æªç¸å ³åé scanCode: '', lastKeyTime: null, isManualInput: false, isScanning: false, scanTimer: null, manualInputTimer: null, scanTarget: 'tray', // å½åæ«ç ç®æ : tray æ material // åºåç»è®¡ç¸å ³åé totalStockSum: 0, totalStockCount: 0, uniqueUnit: '', sumLoading: false, sumError: '', // ä»åºç¸å ³åé warehouseTypes: [], warehouseLoading: false, // ä»åºåºåç¸å ³åé locationTypes: [], locationLoading: false, form: { warehouseType: null, locationType: null }, rules: { locationType: [ { validator: this.validateLocationType, trigger: 'change' } ], trayBarcode: [ { pattern: this.trayBarcodeReg, message: 'æçå·æ ¼å¼é误ï¼é为1个大å忝+9个æ°åï¼å¦A000008024ï¼', trigger: 'blur' } ], warehouseType: [ { message: 'è¯·éæ©ä»åº', trigger: 'change' } ] } } }, computed: { // å½åéæ©çä»åºåç§° currentWarehouseName() { const warehouse = this.warehouseTypes.find(item => item.warehouseType === this.form.warehouseType); return warehouse ? warehouse.warehouseTypeDesc : ''; }, // å½åéæ©çä»åºåºåæè¿° currentLocationDesc() { const location = this.locationTypes.find(item => item.locationType === this.form.locationType) return location ? location.locationTypeDesc : '' } }, watch: { visible(newVal, oldVal) { this.palletVisible = newVal; // å½ä» false å为 true æ¶ï¼è¡¨ç¤ºå¼¹æ¡æå¼ if (newVal === true && oldVal === false) { console.log('å¼¹æ¡æå¼ï¼éç½®æ°æ®'); this.resetData(); this.$nextTick(() => { setTimeout(() => { this.fetchUnpalletMaterialDetails(); }, 300); }); } // å½ä» true å为 false æ¶ï¼è¡¨ç¤ºå¼¹æ¡å ³é if (newVal === false && oldVal === true) { console.log('å¼¹æ¡å ³éï¼éç½®æ°æ®'); this.resetData(); } }, palletVisible(newVal) { this.$emit('update:visible', newVal); }, docNo(newVal) { if (newVal) { this.palletForm = { palletCode: '', barcode: '' }; this.backData = []; this.$refs.palletForm?.reset(); this.fetchUnpalletMaterialDetails(); } } }, mounted() { document.addEventListener('keypress', this.handleKeyPress); }, beforeDestroy() { document.removeEventListener('keypress', this.handleKeyPress); this.clearAllTimers(); }, methods: { open() { this.show = true; this.orderNo = ""; this.resetData(); this.initLocationTypes(); this.initwarehouseTypes(); this.fetchUnpalletMaterialDetails(); }, validateLocationType(rule, value, callback) { if (!this.form.warehouseType) { callback(new Error('请å éæ©ä»åº')); } else if (value === null || value === undefined || value === '') { callback(new Error('è¯·éæ©ä»åºåºå')); } else { callback(); } }, // æ ¹æ®æ¡ç å表è·åè¯¦ç»æ°æ® async fetchUnpalletMaterialDetails() { try { const response = await http.post('/api/InboundOrder/UnPalletGroupBarcode?orderNo=' + this.orderNo, {}); if (response.status && Array.isArray(response.data)) { this.unpalletMaterials = response.data; this.unpalletBarcodes = response.data.map(item => item.barcode || ''); this.totalStockCount = response.data.length; } else { this.unpalletMaterials = []; } } catch (err) { this.unpalletMaterials = this.unpalletBarcodes.map(barcode => ({ barcode: barcode, materielCode: '-', batchNo: '-', stockQuantity: '-', unit: '-', supplyCode: '-', warehouseType: '-' })); } }, async initLocationTypes() { try { const { data } = await this.http.post("api/LocationInfo/GetLocationTypes") this.locationTypes = data } catch (e) { this.$message.error('è·ååºåç±»å失败') } }, async initwarehouseTypes() { try { const { data } = await this.http.post("api/Warehouse/GetwarehouseTypes") this.warehouseTypes = data } catch (e) { this.$message.error('è·ååºåç±»å失败') } }, async fetchStockStatistics(orderNo) { // åæ®å·ä¸ºç©ºæ¶ä¸æ¥è¯¢ if (!orderNo) { this.sumError = 'åæ®å·ä¸ºç©ºï¼æ æ³ç»è®¡'; return; } this.sumLoading = true; this.sumError = ''; try { const response = await http.post('/api/InboundOrder/UnPalletQuantity?orderNo=' + orderNo, {}); if (response.data) { this.totalStockSum = response.data.stockSumQuantity || 0; this.totalStockCount = response.data.stockCount || 0; this.uniqueUnit = response.data.uniqueUnit || ''; } } catch (err) { this.sumError = 'ç»è®¡å 载失败'; this.totalStockSum = 0; this.totalStockCount = 0; } finally { this.sumLoading = false; } }, async validateForm() { return new Promise((resolve) => { if (!this.$refs.locationForm) { this.error = 'è¡¨åæªåå§å'; this.$message.warning('请å éæ©ä»åºåºå'); resolve(false); return; } this.$refs.locationForm.validate((valid) => { if (valid) { this.error = ''; resolve(true); } else { if (!this.from.warehouseType) { this.error = '请å éæ©ä»åº'; } else if (this.form.locationType === null || this.form.locationType === undefined || this.form.locationType === '') { this.error = '请å éæ©ä»åºåºå'; } else { this.error = 'è¯·æ£æ¥è¡¨å填忝妿£ç¡®'; } resolve(false); } }); }); }, // èç¦å°æçè¾å ¥æ¡ focusTrayInput() { if (this.$refs.trayInput && this.$refs.trayInput.$el) { const inputEl = this.$refs.trayInput.$el.querySelector('input'); if (inputEl) { inputEl.focus(); this.currentFocus = 'tray'; this.scanTarget = 'tray'; inputEl.select(); } } }, // èç¦å°ç©æè¾å ¥æ¡ focusBarcodeInput() { if (this.$refs.barcodeInput && this.$refs.barcodeInput.$el) { const inputEl = this.$refs.barcodeInput.$el.querySelector('input'); if (inputEl) { inputEl.focus(); this.currentFocus = 'material'; this.scanTarget = 'material'; inputEl.select(); } } }, // éç½®æææ°æ® resetData() { this.trayBarcode = ''; this.barcode = ''; this.materials = []; this.unpalletBarcodes = []; this.unpalletMaterials = []; this.loading = false; this.error = ''; this.scanCode = ''; this.lastKeyTime = null; this.isManualInput = false; this.isScanning = false; this.currentFocus = 'warehouse'; this.scanTarget = 'tray'; this.clearAllTimers(); this.totalStockSum = 0; this.totalStockCount = 0; this.sumLoading = false; this.sumError = ''; this.form = { warehouseType: null, locationType: null } this.warehouseTypes = []; this.locationTypes = []; // æ¸ é¤è¡¨åéªè¯ç¶æ this.$nextTick(() => { if (this.$refs.locationForm) { this.$refs.locationForm.clearValidate(); } }); }, // æ¸ é¤ææè®¡æ¶å¨ clearAllTimers() { if (this.manualInputTimer) { clearTimeout(this.manualInputTimer); this.manualInputTimer = null; } if (this.scanTimer) { clearTimeout(this.scanTimer); this.scanTimer = null; } }, handleDialogClose() { this.show = false; this.resetData(); }, // 确认æé® async handleConfirm() { if (!await this.validateForm()) return; if (this.materials.length === 0) { this.$message.warning('请è³å°æ·»å ä¸ä¸ªç©æ'); return; } if (!this.trayBarcode) { this.$message.warning('请è¾å ¥æçæ¡ç '); return; } const result = { warehouseType: this.form.warehouseType, warehouseName: this.currentWarehouseName, locationType: this.form.locationType, locationDesc: this.currentLocationDesc, trayBarcode: this.trayBarcode, materials: this.materials, docNo: this.docNo }; // 触åç¶ç»ä»¶ç back-success äºä»¶ this.$emit('back-success', result); this.palletVisible = false; }, // å¤çæçè¾å ¥ handleTrayInput() { // æ 记为æå¨è¾å ¥æ¨¡å¼ this.isManualInput = true; this.isScanning = false; // æ¸ é¤ä¹åç计æ¶å¨ if (this.manualInputTimer) { clearTimeout(this.manualInputTimer); } // 设置计æ¶å¨ï¼å¦æä¸æ®µæ¶é´å 没æè¾å ¥ï¼åé置为æ«ç æ¨¡å¼ this.manualInputTimer = setTimeout(() => { this.isManualInput = false; }, 1000); }, // å¤çç©æè¾å ¥ handleBarcodeInput() { // æ 记为æå¨è¾å ¥æ¨¡å¼ this.isManualInput = true; this.isScanning = false; // æ¸ é¤ä¹åç计æ¶å¨ if (this.manualInputTimer) { clearTimeout(this.manualInputTimer); } // 设置计æ¶å¨ï¼å¦æä¸æ®µæ¶é´å 没æè¾å ¥ï¼åé置为æ«ç æ¨¡å¼ this.manualInputTimer = setTimeout(() => { this.isManualInput = false; }, 1000); }, // å¤çæçæ¡ç æäº¤ async handleTraySubmit() { // å ç´æ¥æ£æ¥locationTypeï¼é¿å 表åéªè¯ç弿¥é®é¢ if (!this.form.warehouseType) { this.error = '请å éæ©ä»åº'; return; } if (!this.form.locationType) { this.error = '请å éæ©ä»åºåºå'; //this.$message.warning('请å éæ©ä»åºåºå'); return; } // ç¶ååè¿è¡å®æ´ç表åéªè¯ if (!await this.validateForm()) return; const currentTrayBarcode = this.trayBarcode.trim(); if (!currentTrayBarcode) { this.error = '请è¾å ¥ææ«ææçæ¡ç '; return; } this.error = ''; if (!this.trayBarcodeReg.test(currentTrayBarcode)) { // ElMessage.warning({ // message: 'æçå·æ ¼å¼é误', // type: 'warning', // duration: 3000 // }) this.$message("æçå·æ ¼å¼é误"); this.focusTrayInput(); return; } // 设置æçæ¡ç åï¼èªå¨èç¦å°ç©æè¾å ¥æ¡ this.focusBarcodeInput(); // this.$message({ // message: `æçæ¡ç 已设置: ${currentTrayBarcode}`, // type: 'success', // duration: 2000 // }); this.$message.success(`æçæ¡ç 已设置: ${currentTrayBarcode}`); }, // æ¸ é¤æç clearTray() { this.trayBarcode = ''; this.materials = []; this.focusTrayInput(); this.$message({ message: 'æçæ¡ç å·²æ¸ é¤', type: 'info', duration: 2000 }); }, // æ¸ ç©ºæçè¾å ¥ handleTrayClear() { this.error = ''; }, // æ¸ ç©ºè¾å ¥ handleClear() { this.error = ''; this.scanCode = ''; this.isManualInput = false; this.isScanning = false; }, // å¤çç©ææ¡ç æäº¤ async handleBarcodeSubmit() { if (!await this.validateForm()) return; const currentBarcode = this.barcode.trim(); if (!this.trayBarcode) { this.error = '请å è¾å ¥æçæ¡ç '; this.focusTrayInput(); return; } if (!currentBarcode) { this.error = '请è¾å ¥ææ«æç©ææ¡ç '; return; } this.focusBarcodeInput(); this.error = ''; this.loading = true; try { // è°ç¨APIæ¥è¯¢ç©æä¿¡æ¯ const materialData = await this.fetchMaterialData(currentBarcode); if (!materialData || materialData.length === 0) { return; } this.materials = []; materialData.forEach(item => { this.materials.push({ ...item, trayCode: this.trayBarcode, locationType: this.form.locationType, locationDesc: this.currentLocationDesc, scanTime: this.formatTime(new Date()) }); }); this.orderNo = materialData[0].orderNo; await this.fetchStockStatistics(materialData[0].orderNo); await this.fetchUnpalletMaterialDetails(); // æ¸ ç©ºç©æè¾å ¥æ¡å¹¶ä¿æèç¦ this.barcode = ''; this.scanCode = ''; // æ¸ ç©ºæ«ç ç¼å this.isScanning = false; setTimeout(() => { this.focusBarcodeInput(); }, 100); } catch (err) { this.error = err.message || 'æ¥è¯¢æ¡ç ä¿¡æ¯å¤±è´¥ï¼è¯·éè¯'; this.focusBarcodeInput(); setTimeout(() => { // éä¸è¾å ¥æ¡å çé误å 容ï¼ç¡®ä¿focus宿忧è¡ï¼ const inputEl = this.$refs.barcodeInput?.$el?.querySelector('input'); if (inputEl) inputEl.select(); }, 100); } finally { this.loading = false; } }, // APIè¯·æ± - æ¿æ¢ä¸ºå®é çAPIè°ç¨ async fetchMaterialData(barcode) { try { const response = await http.post('/api/Inbound/StockTakeGroupPallet', { palletCode: this.trayBarcode, barcode: barcode, locationTypeDesc: this.currentLocationDesc, locationType: this.form.locationType, // æ·»å ä»åºåºåä¿¡æ¯ warehouseType: this.form.warehouseType } ); let materialData; if (typeof response.data === 'string') { try { materialData = JSON.parse(response.data); } catch (e) { } } else { materialData = response.data; } if (!response.status) { this.error = response.message || 'æ¥è¯¢æ¡ç ä¿¡æ¯å¤±è´¥ï¼è¯·éè¯'; } return materialData; } catch (error) { console.error('APIè°ç¨å¤±è´¥:', error); } }, // å¤çæ«ç æªè¾å ¥ handleKeyPress(event) { // å¦ææ¯æå¨è¾å ¥æ¨¡å¼ï¼ä¸å¤çæ«ç æªé»è¾ if (this.isManualInput) { return; } const key = event.key; const currentTime = new Date().getTime(); // 忽ç¥ç´æ¥æä¸çå车é®ï¼ç±handleBarcodeSubmitå¤çï¼ if (key === 'Enter') { if (this.scanCode.length > 0) { // 黿¢é»è®¤å车è¡ä¸ºï¼é¿å 表åæäº¤ event.preventDefault(); // æ«ç 宿ï¼èªå¨è§¦åæ¥è¯¢ this.isScanning = false; // æ ¹æ®å½åæ«ç ç®æ 设置ç¸åºçè¾å ¥æ¡å¼ if (this.scanTarget === 'tray') { this.trayBarcode = this.scanCode; this.handleTraySubmit(); } else if (this.scanTarget === 'material') { this.barcode = this.scanCode; this.handleBarcodeSubmit(); } } this.scanCode = ''; this.lastKeyTime = null; return; } // æå»ºæ«ç å 容ï¼å¿«éè¿ç»è¾å ¥è§ä¸ºæ«ç ï¼ if (this.lastKeyTime && currentTime - this.lastKeyTime < 50) { this.scanCode += key; this.isScanning = true; } else { this.scanCode = key; this.isScanning = true; } // 设置计æ¶å¨ï¼å¦æä¸æ®µæ¶é´å 没æè¾å ¥ï¼åéç½®æ«æç¶æ if (this.scanTimer) { clearTimeout(this.scanTimer); } this.scanTimer = setTimeout(() => { this.isScanning = false; }, 100); this.lastKeyTime = currentTime; }, // æ ¼å¼åæ¶é´ formatTime(date) { const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); const hours = String(date.getHours()).padStart(2, '0'); const minutes = String(date.getMinutes()).padStart(2, '0'); const seconds = String(date.getSeconds()).padStart(2, '0'); return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; } } } </script> <style scoped> .barcode-scanner-container { max-width: 1200px; margin: 0 auto; padding: 10px; display: flex; flex-direction: column; height: 100%; gap: 8px; } /* ç´§åå¸å±æ ·å¼ */ .compact { margin-bottom: 0; } .compact-form { margin-bottom: 0; } .compact-item { margin-bottom: 0; } .compact-card { margin-bottom: 0; } .compact-card>>>.el-card__body { padding: 12px; } .compact-header { display: flex; justify-content: space-between; align-items: center; padding: 0 !important; } .compact-header>>>.el-card__header { padding: 8px 12px; } .compact-input { margin: 8px 0; } .compact-tips { margin-top: 8px; font-size: 11px; } /* ä»åºåºåéæ© - ç´§å */ .location-section.compact { margin-bottom: 8px; } .location-section.compact>>>.el-form-item { margin-bottom: 0; } /* æçä¿¡æ¯ - ç´§å */ .tray-info.compact { padding: 6px 10px; margin-bottom: 8px; font-size: 13px; } /* æ«ç åºå - ç´§å */ .input-section.compact { margin-bottom: 8px; flex-shrink: 0; } /* ç©æå表 - åºå®é«åº¦å¸¦æ»å¨ */ .material-list.compact { flex: 1; min-height: 0; /* éè¦ï¼å 许flexå项æ¶ç¼© */ display: flex; flex-direction: column; } .material-list.compact>>>.el-card { display: flex; flex-direction: column; height: 100%; } .material-list.compact>>>.el-card__body { flex: 1; display: flex; flex-direction: column; padding: 0; min-height: 0; } .table-container { flex: 1; min-height: 0; overflow: hidden; } .material-list.compact>>>.el-table { flex: 1; } .material-list.compact>>>.el-table__body-wrapper { overflow-y: auto; } /* ç´§åçç©ºç¶æ */ .empty-state.compact { padding: 20px 0; flex: 1; display: flex; flex-direction: column; justify-content: center; align-items: center; } .empty-state.compact i { font-size: 36px; margin-bottom: 8px; } .empty-state.compact p { font-size: 13px; } /* å ¶ä»åææ ·å¼è°æ´ */ .page-title { text-align: center; margin-bottom: 15px; } .scan-status { font-size: 12px; color: #67C23A; } .scan-indicator { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background-color: #67C23A; margin-right: 5px; animation: pulse 1.5s infinite; } @keyframes pulse { 0% { opacity: 1; } 50% { opacity: 0.4; } 100% { opacity: 1; } } .input-wrapper { position: relative; } .input-tips { margin-top: 6px; color: #909399; } .warning-text { color: #E6A23C; font-weight: bold; } .loading.compact { text-align: center; margin: 10px 0; padding: 5px; } .loading.compact p { margin-top: 5px; color: #409EFF; font-size: 12px; } .error-message.compact { margin: 5px 0; } .error-message.compact>>>.el-alert { padding: 6px 12px; } .list-actions { display: flex; align-items: center; gap: 4px; } .list-actions>>>.el-tag { height: 24px; line-height: 22px; padding: 0 6px; } .clear-all-btn { margin-left: 8px; } .material-code { font-family: 'Courier New', monospace; font-weight: bold; color: #409EFF; } .location-info { color: #606266; font-weight: normal; } .debug-info { background: #f5f7fa; padding: 8px; border-radius: 4px; margin-top: 8px; font-size: 11px; color: #909399; } .small-button { padding: 6px 8px; font-size: 11px; } /* è¾å ¥æ¡ç»æ ·å¼è°æ´ */ .custom-input-group { display: flex; align-items: center; width: 100%; margin: 8px 0; border: 1px solid #DCDFE6; border-radius: 4px; overflow: hidden; background: #fff; } .input-label { padding: 0 12px; background: #F5F7FA; border-right: 1px solid #DCDFE6; color: #606266; font-size: 13px; white-space: nowrap; height: 36px; line-height: 36px; flex-shrink: 0; min-width: 70px; text-align: center; } .input-container { display: flex; flex: 1; align-items: center; } .custom-input { flex: 1; } .custom-input>>>.el-input__inner { border: none; border-radius: 0; height: 36px; line-height: 36px; font-size: 13px; } /* ååºå¼è°æ´ */ @media (max-width: 768px) { .barcode-scanner-container { padding: 5px; } .custom-input-group { flex-direction: column; border: none; } .input-label { width: 100%; border-right: none; border-bottom: 1px solid #DCDFE6; margin-bottom: 5px; } .input-container { width: 100%; border: 1px solid #DCDFE6; border-radius: 4px; } .unpallet-section.compact { margin-bottom: 8px; flex-shrink: 0; } .unpallet-card { flex-shrink: 0; } .unpallet-barcode-list { display: flex; flex-wrap: wrap; gap: 6px; padding: 8px 0; max-height: 180px; overflow-y: auto; } .unpallet-barcode-list>>>.el-tag { cursor: pointer; max-width: calc(33.333% - 4px); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } @media (max-width: 768px) { .unpallet-barcode-list>>>.el-tag { max-width: calc(50% - 4px); } } } </style> ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/inbound/extend/TakeStockSelect.vue
@@ -1,81 +1,30 @@ <template> <el-dialog v-model="dialogVisible" title="ææ¶æå平账" width="1000px" title="æå平账" width="600px" :close-on-click-modal="false" :destroy-on-close="true" @closed="handleDialogClosed" > <div class="reconciliation-container"> <!-- åæ®åºæ¬ä¿¡æ¯ --> <div class="order-info"> <div class="info-row"> <span class="label">åæ®IDï¼</span> <span class="value">{{ currentRow.id || "-" }}</span> </div> <div class="info-row" v-if="selectedItem"> <span class="label">å·²é订åï¼</span> <span class="value selected-order">{{ selectedItem.id }}</span> </div> <!-- ç§»é¤åæ®IDå±ç¤ºï¼ä» ä¿çæ¡ç è¾å ¥æ¡ --> <!-- æ¡ç è¾å ¥æ¡ --> <div class="barcode-input-container"> <el-input v-model="barcode" placeholder="请è¾å ¥/æ«ææ¡ç å平账" clearable @keyup.enter="handleEnterConfirm" class="barcode-input" :disabled="loading" /> </div> <!-- æ°æ®å表å±ç¤º --> <el-scrollbar height="400px" class="custom-scrollbar"> <transition-group name="data-item-transition"> <div class="data-item" v-for="(item, index) in displayData" :key="`${item.orderId}-${index}`" > <div class="radio-container"> <el-radio v-model="selectedItem" :label="item" :value="item" @change="handleRadioChange(item)" ></el-radio> <!-- 空æç¤ºï¼ä» æ¡ç ä¸ºç©ºæ¶æ¾ç¤ºï¼ --> <div class="empty-tip" v-if="!barcode && !loading"> <span>请è¾å ¥æ¡ç åè¿è¡å¹³è´¦æä½</span> </div> <div class="data-detail"> <div class="detail-row"> <span class="label">订åIDï¼</span> <span class="value">{{ item.id || "-" }}</span> </div> <div class="detail-row"> <span class="label">ç©æç¼ç ï¼</span> <span class="value">{{ item.materielCode || "-" }}</span> </div> <div class="detail-row"> <span class="label">ç©æåç§°ï¼</span> <span class="value">{{ item.materielName || "-" }}</span> </div> <div class="detail-row"> <span class="label">æ¹æ¬¡å·ï¼</span> <span class="value">{{ item.batchNo || "-" }}</span> </div> <div class="detail-row"> <span class="label">è®¢åæ°éï¼</span> <span class="value">{{ item.orderQuantity || 0 }}</span> </div> <div class="detail-row"> <span class="label">åä½ï¼</span> <span class="value">{{ item.unit || "-" }}</span> </div> <div class="detail-row"> <span class="label">ä¾åºåç¼ç ï¼</span> <span class="value">{{ item.supplyCode || "-" }}</span> </div> <div class="detail-row"> <span class="label">ä»åºç¼ç ï¼</span> <span class="value">{{ item.warehouseCode || "-" }}</span> </div> </div> </div> </transition-group> <div class="empty-tip" v-if="displayData.length === 0"> <span>ææ ç¸å ³æ°æ®</span> </div> </el-scrollbar> </div> <template #footer> @@ -83,7 +32,7 @@ <el-button type="primary" @click="handleConfirm" :disabled="!selectedItem" :disabled="!barcode || loading" :loading="loading" > {{ loading ? "平账ä¸..." : "确认平账" }} @@ -91,7 +40,7 @@ </template> </el-dialog> <!-- æå°ç»ä»¶ï¼å¿ 须卿¨¡æ¿ä¸å£°æï¼æè½éè¿refè·åï¼ --> <!-- æå°ç»ä»¶ï¼ä¿çåæé»è¾ï¼ --> <printView ref="printViewRef" @parentcall="parentcall"></printView> </template> @@ -103,52 +52,50 @@ // å¼¹çªæ¾ç¤ºç¶æ const dialogVisible = ref(false); // å½åéä¸çè¡æ°æ® const currentRow = ref({}); // è¦å±ç¤ºçæ°æ®å表 const displayData = ref([]); // éä¸çæ°æ®é¡¹ const selectedItem = ref(null); // æ¡ç è¾å ¥æ¡å¼ const barcode = ref(""); // å è½½ç¶æ const loading = ref(false); // 声ææå°ç»ä»¶çrefå¼ç¨ï¼å ³é®ï¼æ¿ä»£this.$refs.printViewï¼ // æå°ç»ä»¶refå¼ç¨ const printViewRef = ref(null); // æå¼å¼¹çªæ¹æ³ï¼ä¾ç¶ç»ä»¶è°ç¨ï¼ const open = (row, data) => { currentRow.value = row; displayData.value = data; selectedItem.value = null; // éç½®éæ© // æå¼å¼¹çªæ¹æ³ï¼æ åæ°ï¼ä¾ç¶ç»ä»¶ç´æ¥è°ç¨ï¼ const open = () => { barcode.value = ""; // æ¯æ¬¡æå¼å¼¹çªéç½®æ¡ç dialogVisible.value = true; }; // å¤çåéæé®åå const handleRadioChange = (item) => { selectedItem.value = item; }; // å¼¹çªå ³éæ¶çå¤ç const handleDialogClosed = () => { selectedItem.value = null; barcode.value = ""; loading.value = false; }; // ç¶ç»ä»¶è°ç¨çåè°ï¼å¦æprintViewéè¦ï¼ // ç¶ç»ä»¶è°ç¨çåè°ï¼ä¿çåæé»è¾ï¼ const parentcall = (params) => { console.log("printViewåè°åæ°ï¼", params); }; // 确认平账æä½ // å车触åå¹³è´¦ï¼æ«ç æªèªå¨å车æ¶è°ç¨ï¼ const handleEnterConfirm = async () => { if (!barcode.value) { ElMessage.warning("请è¾å ¥æ¡ç ååæä½"); return; } await handleConfirm(); }; // 确认平账æä½ï¼æ ¸å¿é»è¾ï¼ const handleConfirm = async () => { if (!selectedItem.value) { ElMessage.warning("è¯·éæ©ä¸æ¡æ°æ®è¿è¡å¹³è´¦å¤ç"); if (!barcode.value) { ElMessage.warning("请è¾å ¥æ¡ç è¿è¡å¹³è´¦å¤ç"); return; } try { // 确认æç¤º await ElMessageBox.confirm( `ç¡®å®è¦å¯¹è®¢å ${selectedItem.value.id} è¿è¡å¹³è´¦å¤çåï¼`, `ç¡®å®è¦å¯¹æ¡ç ${barcode.value} è¿è¡å¹³è´¦å¤çåï¼`, "平账确认", { confirmButtonText: "ç¡®å®", @@ -159,10 +106,9 @@ loading.value = true; // è°ç¨å¹³è´¦æ¥å£ // è°ç¨å¹³è´¦æ¥å£ï¼ä» ä¼ ébarcodeåæ°ï¼ const params = { id: currentRow.value.id, // è¡ID orderId: selectedItem.value.id, // éæ©çåæ®orderId barcode: barcode.value, }; const response = await axios.get( @@ -172,21 +118,20 @@ } ); console.log("æ¥å£å®æ´è¿åå¼ï¼", response); // è°è¯ç¨ï¼æå°å®æ´è¿å console.log("æ¥å£å®æ´è¿åå¼ï¼", response); // è°è¯ç¨ // ç¬¬ä¸æ¥ï¼æ ¡éªæå¤å±ç¶æ // æ ¡éªæ¥å£è¿åç¶æ if (response.data?.status) { ElMessage.success("平账æä½æå"); // ç¬¬äºæ¥ï¼è§£ææ£ç¡®çscannedDetailå±çº§ï¼ä¸å±dataï¼ const thirdLayerData = response.data.data?.data; // å ³é®ä¿®å¤ï¼å第ä¸å±data // è§£æè¿åæ°æ®ï¼ä¿çåææå°é»è¾ï¼ const thirdLayerData = response.data.data?.data; const scannedDetail = thirdLayerData?.scannedDetail; console.log("è§£æåçscannedDetailï¼", scannedDetail); // è°è¯ç¨ï¼æå°ç®æ æ°æ® console.log("è§£æåçscannedDetailï¼", scannedDetail); // ç¬¬ä¸æ¥ï¼å¤ææå°æ¡ä»¶ // 夿æå°æ¡ä»¶å¹¶è§¦åæå° if (scannedDetail?.isUnpacked && scannedDetail?.materialCodes?.length > 0) { // ç¡®ä¿æå°ç»ä»¶å®ä¾åå¨ if (printViewRef.value) { console.log("触åæå°æ¹æ³ï¼åæ°ï¼", scannedDetail.materialCodes); printViewRef.value.open(scannedDetail.materialCodes); @@ -197,21 +142,20 @@ ElMessage.info("æ éæå°ï¼æªæ»¡è¶³æå æ¡ä»¶ææ ç©æç¼ç æ°æ®"); } dialogVisible.value = false; dialogVisible.value = false; // 平账æååå ³éå¼¹çª } else { ElMessage.error(response.data?.message || "平账æä½å¤±è´¥"); } } catch (error) { // å®åé误å¤çï¼åºåç¨æ·åæ¶åçå®é误 // åºåç¨æ·åæ¶åçå®é误 if (error === "cancel" || error === "close") { ElMessage.info("å·²åæ¶å¹³è´¦æä½"); return; } // æå°é误æ¥å¿ï¼æ¹ä¾¿ææ¥ console.error("平账æ¥å£è°ç¨å¤±è´¥ï¼", error); ElMessage.error(`平账æä½å¤±è´¥ï¼${error.message || "ç½ç»å¼å¸¸"}`); } finally { loading.value = false; loading.value = false; // æ 论æå失败ï¼ç»æå è½½ç¶æ } }; @@ -222,103 +166,24 @@ </script> <style scoped> /* æ ·å¼é¨åä¸åï¼çç¥éå¤ä»£ç */ .reconciliation-container { padding: 10px 0; } .order-info { margin-bottom: 20px; padding: 10px; background: #f5f7fa; border-radius: 4px; display: flex; flex-wrap: wrap; gap: 20px; /* æ¡ç è¾å ¥æ¡æ ·å¼ */ .barcode-input-container { margin: 20px 0; } .info-row { display: flex; align-items: center; } .label { font-weight: 600; color: #606266; margin-right: 5px; min-width: 80px; text-align: right; } .value { color: #303133; } .selected-order { color: #409eff; font-weight: 600; } .custom-scrollbar { border: 1px solid #e4e7ed; border-radius: 4px; } .data-item { display: flex; align-items: flex-start; padding: 15px; margin: 10px; background: #fff; border: 1px solid #e4e7ed; border-radius: 4px; transition: all 0.3s; } .data-item:hover { box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); } .data-item.selected { border-color: #409eff; background-color: #f0f7ff; } .radio-container { margin-right: 12px; margin-top: 4px; } .data-detail { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; flex: 1; } .detail-row { display: flex; align-items: center; .barcode-input { width: 100%; font-size: 16px; height: 48px; } .empty-tip { text-align: center; padding: 50px 0; color: #909399; } .data-item-transition-enter-from, .data-item-transition-leave-to { opacity: 0; transform: translateY(10px); } .data-item-transition-enter-active, .data-item-transition-leave-active { transition: all 0.3s ease; } :deep(.el-radio__label) { display: none; } </style> ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/inbound/extend/allocateOrderDetail.vue
@@ -612,6 +612,7 @@ outboundQuantity: formData.outboundDecimal, operator: "", orderNo: this.row.orderNo, stockDetailIds:[] }; this.http ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/inbound/takeStockOrder.js
@@ -1,12 +1,14 @@ // èªå®ä¹æ©å±ä¸å¡ä»£ç import gridBody from "./extend/OrderStockTake.vue"; import gridHeader from "./extend/TakeStockSelect.vue"; import gridFooter from "./extend/StockTakeGroupPallet.vue"; let extension = { components: { // æ¥è¯¢ç颿©å±ç»ä»¶ï¼å°èªå®ä¹å¼¹çªæ³¨å为 gridBody ç»ä»¶ gridHeader: '', gridHeader: gridHeader, gridBody: gridBody, // 对åºä½ ççç¹å¼¹çªç»ä»¶ gridFooter: '', gridFooter: gridFooter, // æ°å»º/ç¼è¾å¼¹åºæ¡æ©å±ç»ä»¶ï¼æ¤å¤ä¸ç¨ï¼çç©ºï¼ modelHeader: '', modelBody: '', @@ -16,21 +18,27 @@ buttons: { view: [], box: [], detail: [] }, // æ©å±æé®ï¼å¦éé¢å¤æ·»å å¯å¨æ¤é ç½®ï¼ methods: { onInit() { // æ¾å° value 为 "OrderStockTake" çæé®ï¼é卿¡æ¶ä¸æåé 置该æé®ï¼ let OrderStockTakeBtn = this.buttons.find(x => x.value === 'OrderStockTake'); if (OrderStockTakeBtn) { // éåæé®ç¹å»äºä»¶ OrderStockTakeBtn.onClick = function () { // 1. è·åè¡¨æ ¼éä¸è¡æ°æ® let rows = this.$refs.table.getSelected(); if (rows.length === 0) return this.$error("è¯·éæ©ä¸æ¡çç¹åæ®æ°æ®ï¼"); if (rows.length > 1) return this.$error("åªè½éæ©ä¸æ¡çç¹åæ®æ°æ®ï¼"); this.$refs.gridBody.open(); }; } let OutOrderStockTakeBtn = this.buttons.find(x => x.value === 'OutOrderStockTake'); if (OutOrderStockTakeBtn) { // éåæé®ç¹å»äºä»¶ OutOrderStockTakeBtn.onClick = function () { const selectedReceiptNo = rows[0].orderNo; if (!selectedReceiptNo) return this.$error("éä¸çåæ®ç¼ºå°ææçåæ®å·ï¼"); this.$refs.gridHeader.open(); }; } let StockTakeGroupPalletBtn = this.buttons.find(x => x.value === 'StockTakeGroupPallet'); if (StockTakeGroupPalletBtn) { // éåæé®ç¹å»äºä»¶ StockTakeGroupPalletBtn.onClick = function () { // 3. è°ç¨èªå®ä¹å¼¹çªç open æ¹æ³ï¼å¹¶ä¼ éåæ®å·ï¼æ ¸å¿ï¼ç»å¼¹çªä¼ åï¼ this.$refs.gridBody.open(selectedReceiptNo); this.$refs.gridFooter.open(); }; } ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/inbound/takeStockOrderDetail.js
@@ -18,19 +18,6 @@ buttons: { view: [], box: [], detail: [] }, // æ©å±æé® methods: { onInit() { // åæçç¹æé®é»è¾ä¿ç let OrderStockTakeBtn = this.buttons.find(x => x.value === 'OrderStockTake'); if (OrderStockTakeBtn) { OrderStockTakeBtn.onClick = function () { let rows = this.$refs.table.getSelected(); if (rows.length === 0) return this.$error("è¯·éæ©ä¸æ¡çç¹åæ®æ°æ®ï¼"); if (rows.length > 1) return this.$error("åªè½éæ©ä¸æ¡çç¹åæ®æ°æ®ï¼"); const selectedReceiptNo = rows[0].orderNo; if (!selectedReceiptNo) return this.$error("éä¸çåæ®ç¼ºå°ææçåæ®å·ï¼"); this.$refs.gridBody.open(selectedReceiptNo); }; } // çå¬åæå¼¹çªäºä»¶ï¼ä¿çï¼ this.$nextTick(() => { @@ -48,128 +35,9 @@ }); // ========== æ°å¢æä½åï¼äººå·¥å¹³è´¦ + ææ¶æå平账 ========== this.columns.push({ field: 'operation', title: 'æä½', width: 200, fixed: 'right', align: 'center', formatter: (row) => { return ` <span style="cursor: pointer;color: #2d8cf0;margin-right: 10px;" class="manual-reconciliation"> <i class="el-icon-check"></i>人工平账 </span> <span style="cursor: pointer;color: #1989fa;" class="misc-reconciliation"> <i class="el-icon-edit"></i>ææ¶æå平账 </span> `; }, click: (row, column, event) => { const target = event.target; // åºåç¹å»çæ¯äººå·¥å¹³è´¦è¿æ¯ææ¶æå平账 if (target.closest('.manual-reconciliation')) { this.handleManualReconciliation(row); // 人工平账é»è¾ } else if (target.closest('.misc-reconciliation')) { this.handleMiscReconciliation(row); // ææ¶æå平账é»è¾ } } }); }, // ========== äººå·¥å¹³è´¦æ ¸å¿é»è¾ ========== handleManualReconciliation(row) { // å¼¹åºç¡®è®¤æ¡ ElMessageBox.confirm( 'ç¡®è®¤è¦æ§è¡äººå·¥å¹³è´¦æä½åï¼', 'æä½ç¡®è®¤', { confirmButtonText: '确认', cancelButtonText: 'åæ¶', type: 'warning' } ).then(async () => { // æ·»å é®ç½©å±é²æ¢éå¤ç¹å» const loading = ElLoading.service({ lock: true, text: 'å¤çä¸ï¼è¯·ç¨å...', background: 'rgba(0, 0, 0, 0.7)' }); try { // è°ç¨äººå·¥å¹³è´¦æ¥å£ const response = await this.http.get(`/api/TakeStockOrder/ManualReconciliation?id=${row.id}`); if (response.status) { ElMessage.success('人工平账æä½æåï¼'); this.$refs.table.reload(); // å·æ°è¡¨æ ¼ } else { ElMessage.error(`æä½å¤±è´¥ï¼${response.message || 'æªç¥é误'}`); } } catch (error) { } finally { // å ³éé®ç½©å± loading.close(); } }).catch(() => { ElMessage.info('å·²åæ¶äººå·¥å¹³è´¦æä½'); }); }, // ========== ææ¶æåå¹³è´¦æ ¸å¿é»è¾ï¼ä¿®æ¹åï¼ ========== handleMiscReconciliation(row) { // éä¸å½åè¡ const table = this.$refs.table.$refs.table; if (table) { table.clearSelection(); table.toggleRowSelection(row, true); } // è°ç¨æ¥å£è·åææ¶æåå¹³è´¦æ°æ® const fetchMiscData = async () => { const loading = ElLoading.service({ lock: true, text: 'å è½½æ°æ®ä¸...', background: 'rgba(0, 0, 0, 0.7)' }); try { // è°ç¨æ¥å£ï¼ä¼ érowä¸çremarkåidåæ° const response = await this.http.get(`/api/TakeStockOrder/SelectOrder?remark=${row.remark || ''}&id=${row.id}`); loading.close(); if (response.status) { if (!Array.isArray(response.data) || response.data.length === 0) { ElMessage.warning("æªæ¥è¯¢å°ç¸å ³æ°æ®"); // æå¼ç©ºæ°æ®çå¼¹çª this.$refs.gridHeader.open(row, []); return; } // æåéè¦å±ç¤ºçåæ®µ const displayData = response.data.map(item => ({ id: item.id || '', materielCode: item.materielCode || '', materielName: item.materielName || '', batchNo: item.batchNo || '', orderQuantity: item.orderQuantity || 0, unit: item.unit || '', supplyCode: item.supplyCode || '', warehouseCode: item.warehouseCode || '' })); // æå¼å¼¹çªå¹¶ä¼ éå¤çåçæ°æ® this.$refs.gridHeader.open(row, displayData); } else { ElMessage.error(`æ¥è¯¢å¤±è´¥ï¼${response.message || 'æªç¥é误'}`); } } catch (error) { loading.close(); ElMessage.error(`ç½ç»å¼å¸¸ï¼${error.message || 'æ¥å£è°ç¨å¤±è´¥'}`); } }; // æ§è¡æ°æ®æ¥è¯¢å¹¶æå¼å¼¹çª fetchMiscData(); }, onInited() { // æ¡æ¶åå§åå®æåæ§è¡ ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/outbound/extend/DirectOutbound.vue
@@ -69,6 +69,7 @@ outboundQuantity: this.keys.length > 1 ? 1 : this.outboundQuantity, operator: "", orderNo: this.orderNo, stockDetailIds:[] }; console.log(requestParams); this.http.post("api/Outbound/ProcessPickingOutbound", requestParams, 'æ°æ®å¤çä¸...') ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/outbound/extend/StockSelect.vue
@@ -3,7 +3,7 @@ <vol-box v-model="showDetialBox" :lazy="true" width="60%" width="80%" :padding="15" title="æå®åºå" > @@ -11,6 +11,8 @@ <el-alert :closable="false" style="width: 100%"> <el-row> <el-col :span="16"> <span class="less-style">åæ®ç¼å·ï¼{{ mainOrderNo }}</span> <el-divider direction="vertical"></el-divider> <span class="less-style">ç©æåç§°ï¼ {{ row.materielName }} </span> <el-divider direction="vertical"></el-divider> <span class="less-style">ç©æç¼å·ï¼ {{ row.materielCode }} </span> @@ -92,12 +94,10 @@ </el-table> </div> <template #footer> <!-- <el-button type="primary" size="small" @click="outbound" <el-button type="primary" size="small" @click="outbound" >ç´æ¥åºåº</el-button > <el-button type="primary" size="small" @click="lockStock" >éå®åºå</el-button > --> <el-button type="danger" size="small" @click="showDetialBox = false" >å ³é</el-button > @@ -114,6 +114,7 @@ return { row: null, kcname: "", mainOrderNo: '', pkcx: false, showDetialBox: false, tableData: [], @@ -137,6 +138,12 @@ width: 150, }, { prop: "barcode", title: "æ¡ç ", type: "string", width: 150, }, { prop: "locationCode", title: "è´§ä½ç¼å·", type: "string", @@ -147,6 +154,25 @@ title: "å¯ç¨æ°é", type: "string", }, { prop: "supplyCode", title: "ä¾åºå", type: "string", }, { prop: "batchNo", title: "æ¹æ¬¡å·", type: "string", }, { prop: "stockId", title: "åºå主é®", type: "string", },{ prop: "orderDetailId", title: "åæ®æç»ä¸»é®", type: "string", }, ], selection: [], selectionSum: 0, @@ -155,13 +181,14 @@ }; }, methods: { open(row) { console.log(row); open(row, orderNo) { this.row = row; this.mainOrderNo = orderNo; // åå¨ä¸»åæ®ç¼å· this.showDetialBox = true; this.originalQuantity = this.row.lockQuantity; this.selectionSum = this.row.lockQuantity; this.getData(); if (this.selectionSum == this.row.orderQuantity) { this.selectionClass = "equle-style"; } else if (this.selectionSum < this.row.orderQuantity) { @@ -220,23 +247,7 @@ this.tableData = x; }); }, revokeAssign() { console.log(this.row); this.http .post( "api/OutboundOrderDetail/RevokeLockOutboundStock?id=" + this.row.id, null, "æ°æ®å¤çä¸" ) .then((x) => { if (!x.status) return this.$message.error(x.message); this.$message.success("æä½æå"); this.showDetialBox = false; this.$emit("parentCall", ($vue) => { $vue.getData(); }); }); }, handleSelectionChange(val) { this.selection = val; this.selectionSum = ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/outbound/extend/outOrderDetail.vue
@@ -1,6 +1,12 @@ <template> <div> <vol-box v-model="showDetialBox" :lazy="true" width="75%" :padding="15" title="åæ®æç»ä¿¡æ¯"> <vol-box v-model="showDetialBox" :lazy="true" width="75%" :padding="15" title="åæ®æç»ä¿¡æ¯" > <div class="box-head"> <el-alert :closable="false" style="width: 100%"> <el-row> @@ -8,33 +14,89 @@ <span>å·²éä¸ {{ selection.length }} 项</span> </el-col> <el-col :span="8"> <el-link type="primary" size="small" v-if="isBatch === 0" style="float: right; height: 20px" @click="handleOpenPicking">æ£é</el-link> <el-link type="primary" size="small" style="float: right; height: 20px; margin-right: 10px" v-if="isBatch === 1" @click="handleOpenBatchPicking">åæ¹æ£é</el-link> <el-link type="primary" size="small" v-if="isBatch === 0" style="float: right; height: 20px; margin-right: 10px" @click="outbound">ç´æ¥åºåº</el-link> <el-link type="primary" size="small" v-if="isBatch === 1" style="float: right; height: 20px; margin-right: 10px" @click="outboundbatch">åæ¹åºåº</el-link> <el-link type="primary" size="small" style="float: right; height: 20px; margin-right: 10px" @click="getData">å·æ°</el-link> <el-link type="primary" size="small" v-if="isBatch === 0" style="float: right; height: 20px" @click="handleOpenPicking" >æ£é</el-link > <el-link type="primary" size="small" style="float: right; height: 20px; margin-right: 10px" v-if="isBatch === 1" @click="handleOpenBatchPicking" >åæ¹æ£é</el-link > <el-link type="primary" size="small" v-if="isBatch === 0" style="float: right; height: 20px; margin-right: 10px" @click="outbound" >ç´æ¥åºåº</el-link > <el-link type="primary" size="small" v-if="isBatch === 1" style="float: right; height: 20px; margin-right: 10px" @click="outboundbatch" >åæ¹åºåº</el-link > <el-link type="primary" size="small" style="float: right; height: 20px; margin-right: 10px" @click="getData" >å·æ°</el-link > </el-col> </el-row> </el-alert> </div> <div class="box-table" style="margin-top: 1%"> <el-table ref="singleTable" :data="tableData" style="width: 100%; height: 100%" highlight-current-row @current-change="handleCurrentChange" height="500px" @row-click="handleRowClick" @selection-change="handleSelectionChange"> <el-table ref="singleTable" :data="tableData" style="width: 100%; height: 100%" highlight-current-row @current-change="handleCurrentChange" height="500px" @row-click="handleRowClick" @selection-change="handleSelectionChange" > <el-table-column type="selection" width="55"> </el-table-column> <el-table-column label="åºå·" type="index" fixed="left" width="55" align="center"></el-table-column> <el-table-column v-for="(item, index) in tableColumns.filter((x) => !x.hidden)" :key="index" :prop="item.prop" :label="item.title" :width="item.width" align="center"> <el-table-column label="åºå·" type="index" fixed="left" width="55" align="center" ></el-table-column> <el-table-column v-for="(item, index) in tableColumns.filter((x) => !x.hidden)" :key="index" :prop="item.prop" :label="item.title" :width="item.width" align="center" > <template #default="scoped"> <div v-if="item.type == 'icon'"> <el-tooltip class="item" effect="dark" :content="item.title" placement="bottom"> <el-link type="primary" :disabled="getButtonEnable(item.prop, scoped.row)" @click="tableButtonClick(scoped.row, item)"> <el-tooltip class="item" effect="dark" :content="item.title" placement="bottom" > <el-link type="primary" :disabled="getButtonEnable(item.prop, scoped.row)" @click="tableButtonClick(scoped.row, item)" > <i :class="item.icon" style="font-size: 22px"></i> </el-link> </el-tooltip> @@ -53,9 +115,15 @@ </div> </vol-box> <stock-select ref="child" @parentCall="parentCall"></stock-select> <selected-stock ref="selectedStock" @parentCall="parentCall"></selected-stock> <selected-stock ref="selectedStock" @parentCall="parentCall" ></selected-stock> <NoStockOut ref="NoStockOut" @parentCall="parentCall"></NoStockOut> <DirectOutbound ref="DirectOutbound" @parentCall="parentCall"></DirectOutbound> <DirectOutbound ref="DirectOutbound" @parentCall="parentCall" ></DirectOutbound> </div> </template> @@ -79,7 +147,14 @@ } from "element-plus"; export default { components: { VolBox, VolForm, StockSelect, SelectedStock, NoStockOut, DirectOutbound }, components: { VolBox, VolForm, StockSelect, SelectedStock, NoStockOut, DirectOutbound, }, data() { return { row: null, @@ -291,13 +366,15 @@ }, tableButtonClick(row, column) { if (column.prop == "assignStock") { this.$refs.child.open(row); this.$refs.child.open(row,this.row.orderNo); } else if (column.prop == "NoStockOut") { this.$refs.NoStockOut.open(row); } else { this.$refs.selectedStock.open(row); } }, lockstocks() { if (this.selection.length === 0) { return this.$message.error("è¯·éæ©åæ®æç»"); @@ -337,7 +414,7 @@ outboundQuantity: 1, operator: "", orderNo: this.row.orderNo, isBatch: this.isBatch isBatch: this.isBatch, }; console.log(requestParams); this.$refs.DirectOutbound.open(requestParams); @@ -350,14 +427,14 @@ const keys = this.selection.map((item) => item.id); const requestParams = { detailIds: keys, outboundQuantity: this.selection[0].orderQuantity - this.selection[0].lockQuantity, outboundQuantity: this.selection[0].orderQuantity - this.selection[0].lockQuantity, operator: "", orderNo: this.row.orderNo, isBatch: this.isBatch isBatch: this.isBatch, }; console.log(requestParams); this.$refs.DirectOutbound.open(requestParams); }, setCurrent(row) { this.$refs.singleTable.setCurrentRow(row); ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/outbound/outboundOrder.js
@@ -505,6 +505,7 @@ outboundQuantity: 1, operator: this.currentOperator || "admin", orderNo: param, stockDetailIds:[] }; try { ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_DTO/CalcOut/PickingOutboundRequestDTO.cs
@@ -39,5 +39,7 @@ /// åºåºç®æ ä½ç½® /// </summary> public string OutboundTargetLocation { get; set; } public List<int> StockDetailIds { get; set; } } } ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_IInboundService/IInboundService.cs
@@ -29,6 +29,12 @@ /// <returns></returns> Task<WebResponseContent> AllcatedGroupPallet(GroupPalletDto palletDto); /// <summary> /// çç¹ç»ç /// </summary> /// <param name="palletDto"></param> /// <returns></returns> Task<WebResponseContent> StockTakeGroupPallet(GroupPalletDto palletDto); /// <summary> /// å ¥åºåæ¹åä¼ ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_IInboundService/ITakeStockOrderService.cs
@@ -25,7 +25,9 @@ WebResponseContent SelectOrder(string remark, int id); WebResponseContent DocumentReconciliation(int orderId, int id); WebResponseContent DocumentReconciliation(string barcode); WebResponseContent StockTakeGroupPallet(string barcode, string boxNo); } } ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_IOutboundService/IOutboundService.cs
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_InboundService/InboundService.cs
@@ -52,7 +52,8 @@ private readonly HttpClientHelper _httpClientHelper; private readonly IRepository<Dt_MesReturnRecord> _mesReturnRecord; private readonly ILocationInfoService _locationInfoService; public InboundService(IUnitOfWorkManage unitOfWorkManage, IInboundOrderDetailService inboundOrderDetailService, IInboundOrderService inbounOrderService, IRepository<Dt_InboundOrder> inboundOrderRepository, IRepository<Dt_WarehouseArea> warehouseAreaRepository, IRepository<Dt_LocationType> locationTypeRepository, IRepository<Dt_StockInfo> stockInfoRepository, IRepository<Dt_InboundOrderDetail> inboundOrderDetailRepository, IStockService stockService, IRepository<Dt_Task> taskRepository,IRepository<Dt_AllocateMaterialInfo> allocateMaterialInfo, HttpClientHelper httpClientHelper, IRepository<Dt_MesReturnRecord> mesReturnRecord,ILocationInfoService locationInfoService) private readonly IRepository<Dt_TakeStockOrder> _takeStockOrder; public InboundService(IUnitOfWorkManage unitOfWorkManage, IInboundOrderDetailService inboundOrderDetailService, IInboundOrderService inbounOrderService, IRepository<Dt_InboundOrder> inboundOrderRepository, IRepository<Dt_WarehouseArea> warehouseAreaRepository, IRepository<Dt_LocationType> locationTypeRepository, IRepository<Dt_StockInfo> stockInfoRepository, IRepository<Dt_InboundOrderDetail> inboundOrderDetailRepository, IStockService stockService, IRepository<Dt_Task> taskRepository,IRepository<Dt_AllocateMaterialInfo> allocateMaterialInfo, HttpClientHelper httpClientHelper, IRepository<Dt_MesReturnRecord> mesReturnRecord,ILocationInfoService locationInfoService,IRepository<Dt_TakeStockOrder> takeStockOrder) { _unitOfWorkManage = unitOfWorkManage; InboundOrderDetailService = inboundOrderDetailService; @@ -68,6 +69,7 @@ _httpClientHelper = httpClientHelper; _mesReturnRecord = mesReturnRecord; _locationInfoService = locationInfoService; _takeStockOrder = takeStockOrder; } public async Task<WebResponseContent> GroupPallet(GroupPalletDto palletDto) @@ -594,5 +596,125 @@ return httpResponseResult; } public async Task<WebResponseContent> StockTakeGroupPallet(GroupPalletDto palletDto) { WebResponseContent content = new WebResponseContent(); try { (bool, string, object?) result2 = ModelValidate.ValidateModelData(palletDto); if (!result2.Item1) return content.Error(result2.Item2); // éªè¯ä»åºç¼å·æ¯å¦åå¨ var code = _warehouseAreaRepository.Db.Queryable<Dt_WarehouseArea>() .Where(x => x.Code == palletDto.WarehouseType) .Select(x => x.Code) .First(); if (string.IsNullOrEmpty(code)) { return content.Error($"ä»åºä¸æ²¡æè¯¥{palletDto.WarehouseType}ç¼å·ã"); } // æ¥è¯¢å½åæççåºåä¿¡æ¯ Dt_StockInfo? stockInfo = await _stockInfoRepository.Db.Queryable<Dt_StockInfo>() .Includes(x => x.Details) .Where(x => x.PalletCode == palletDto.PalletCode) .FirstAsync(); // éªè¯æçæ¯å¦å·²çæä»»å¡ if (_taskRepository.QueryFirst(x => x.PalletCode == palletDto.PalletCode) != null) { return content.Error($"该æçå·²çæä»»å¡"); } // éªè¯æçæ¯å¦å·²ä¸æ¶ï¼å·²ä¸æ¶ä¸è½ç»çï¼ if (stockInfo != null && !string.IsNullOrEmpty(stockInfo.LocationCode) && stockInfo.StockStatus != (int)StockStatusEmun.ç»çæå) { return content.Error("已䏿¶çæçä¸è½å次ç»ç"); } Dt_StockInfoDetail stockInfoDetail = _stockService.StockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() .Where(x => x.Barcode == palletDto.Barcode && x.StockId == 0) .First(); if (stockInfoDetail == null) { return content.Error($"{palletDto.Barcode} æ¡ç å·²å ³èå ¶ä»æçï¼æ æ³ç»ç"); } Dt_TakeStockOrder takeStockOrder = _takeStockOrder.Db.Queryable<Dt_TakeStockOrder>() .Where(x => x.OrderNo == stockInfoDetail.OrderNo) .First(); if (takeStockOrder == null) { return content.Error($"{palletDto.Barcode} ä¸å±äºçç¹åæ®ä¸çæ¡ç ï¼ä¸å 许çäºç»ç"); } if (stockInfo == null) { stockInfo = new Dt_StockInfo() { PalletType = (int)PalletTypeEnum.None, LocationType = Convert.ToInt32(palletDto.locationType), PalletCode = palletDto.PalletCode, StockStatus = (int)StockStatusEmun.ç»çæå, Details = new List<Dt_StockInfoDetail>() }; } if (stockInfo.Details.Count > 0 && stockInfo.Details.FirstOrDefault()?.WarehouseCode != palletDto.WarehouseType) { return content.Error($"该æçç»çä»åºä¸º{stockInfo.Details.FirstOrDefault()?.WarehouseCode}ä¸å½åä»åº{palletDto.WarehouseType}ä¸ä¸è´ï¼ä¸å 许ç»ç"); } _unitOfWorkManage.BeginTran(); try { if (stockInfo.Id == 0) { int newStockId = await _stockInfoRepository.Db.Insertable(stockInfo).ExecuteReturnIdentityAsync(); stockInfo.Id = newStockId; } stockInfoDetail.StockId = stockInfo.Id; await _stockService.StockInfoDetailService.Db.Updateable(stockInfoDetail) .Where(x => x.Id == stockInfoDetail.Id) .ExecuteCommandAsync(); if (stockInfo.Id != 0 && stockInfo.Details != null && !stockInfo.Details.Contains(stockInfoDetail)) { stockInfo.Details.Add(stockInfoDetail); await _stockInfoRepository.Db.Updateable(stockInfo) .IgnoreColumns(x => x.Details) .ExecuteCommandAsync(); } // æäº¤äºå¡ _unitOfWorkManage.CommitTran(); } catch (Exception) { // äºå¡åæ» _unitOfWorkManage.RollbackTran(); throw; // æç»å¤å±catchå¤çæ¥å¿ } // æ¥è¯¢ææ°çåºåä¿¡æ¯ï¼å å«å ³èçæç»ï¼ Dt_StockInfo? NewstockInfo = await _stockInfoRepository.Db.Queryable<Dt_StockInfo>() .Includes(x => x.Details) .Where(x => x.PalletCode == palletDto.PalletCode) .FirstAsync(); return WebResponseContent.Instance.OK(data: NewstockInfo.Details.OrderByDescending(x => x.Id)); } catch (Exception ex) { _unitOfWorkManage.RollbackTran(); LogFactory.GetLog($"ç»çä¿¡æ¯").Info(true, $"ãå¼å¸¸ãï¼ã{ex.Message}ã{Environment.NewLine}ã{ex.StackTrace}ã{Environment.NewLine}{Environment.NewLine}"); return content.Error(ex.Message); } } } } ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_InboundService/TakeStockOrderService.cs
@@ -80,10 +80,10 @@ { return WebResponseContent.Instance.Error("该æçå¤äºéçç¹ç¶æï¼è¯·æ£æ¥çç¹ä»»å¡"); } Dt_TakeStockOrder takeStockOrder = _takeStockOrder.QueryFirst(x=>x.OrderNo == orderNo); Dt_TakeStockOrder takeStockOrder = _takeStockOrder.QueryFirst(x=>x.AllPalletCode.Contains(boxNo)&& x.TakeStockStatus == TakeStockStatusEnum.çç¹ä¸.ObjToInt()); if (takeStockOrder == null) { return WebResponseContent.Instance.Error("æªæ¾å°è¯¥çç¹åæ®"); return WebResponseContent.Instance.Error("该æçæªæ¾å°è¯¥çç¹åæ®"); } if (takeStockOrder.AllPalletCode.Contains(",")) { @@ -103,8 +103,8 @@ return WebResponseContent.Instance.Error($"ç®±å·ã{boxNo}ãæªå¨çç¹åç®±å·ã{takeStockOrder.AllPalletCode}ã䏿¾å°å¹é 项"); } } return WebResponseContent.Instance.OK(); var resultData = new { takeStockOrder = takeStockOrder.OrderNo }; return WebResponseContent.Instance.OK(data:resultData); } catch(Exception ex) { @@ -148,10 +148,6 @@ { try { if(completeStockTakeDTO.actualQuantity == completeStockTakeDTO.stockQuantity) { return WebResponseContent.Instance.OK("该æ¡ç ä¸ºå¹³è´¦ï¼æ éè®°å½å·®å¼"); } Dt_TakeStockOrder takeStockOrder = _takeStockOrder.QueryFirst(x=>x.OrderNo == completeStockTakeDTO.orderNo); if (takeStockOrder == null) { @@ -167,7 +163,6 @@ { return WebResponseContent.Instance.Error("æ¡ç åºåæ°æ®æªæ¾å°å¹é æ°æ®"); } List<Dt_AllocateMaterialInfo> allocateMaterialInfos = new List<Dt_AllocateMaterialInfo>(); Dt_TakeStockOrderDetail takeStockOrderDetail = new Dt_TakeStockOrderDetail() { TakeStockId = takeStockOrder.Id, @@ -179,7 +174,7 @@ Unit = stockInfoDetail.Unit, SysQty = completeStockTakeDTO.stockQuantity, Qty = completeStockTakeDTO.actualQuantity, Remark = completeStockTakeDTO.actualQuantity - completeStockTakeDTO.stockQuantity >= 0 ? "çç" : "çäº", Remark = "çäº", barcode = completeStockTakeDTO.barcode, WarehouseCode = stockInfoDetail.WarehouseCode ?? "", FactoryArea = stockInfoDetail.FactoryArea, @@ -188,25 +183,12 @@ DifferenceQty = completeStockTakeDTO.actualQuantity - completeStockTakeDTO.stockQuantity }; foreach (var item in stockInfo.Details) { Dt_AllocateMaterialInfo allocateMaterialInfo = new Dt_AllocateMaterialInfo() { Barcode = item.Barcode, BatchNo = item.BatchNo, FactoryArea = item.FactoryArea, MaterialCode = item.MaterielCode, MaterialName = item.MaterielName, OrderId = takeStockOrder.Id, OrderNo = takeStockOrder.OrderNo, Quantity = item.StockQuantity, SupplyCode = item.SupplyCode, Unit = item.Unit }; } stockInfoDetail.StockId = 0; stockInfoDetail.OrderNo = takeStockOrder.OrderNo; stockInfo.StockStatus = StockStatusEmun.çç¹åºå宿.ObjToInt(); _unitOfWorkManage.BeginTran(); _takeStockOrderDetail.AddData(takeStockOrderDetail); _stockInfoDetailRepository.UpdateData(stockInfoDetail); _stockInfoRepository.UpdateData(stockInfo); _unitOfWorkManage.CommitTran(); return WebResponseContent.Instance.OK("çç¹å®æï¼è¯·å走该å¼å¸¸æç®±è¿è¡å¹³è´¦å¤çï¼"); @@ -236,18 +218,14 @@ } var task = _taskRepository.QueryFirst(x => x.PalletCode == boxNo); if (task != null) { return content.Error($"æç{boxNo}åå¨ä»»å¡ååºå¤±è´¥!"); return content.Error($"æç{boxNo}åå¨ä»»å¡ï¼ååºå¤±è´¥!"); } if(stock.StockStatus != StockStatusEmun.çç¹åºåºå®æ.ObjToInt() && stock.StockStatus != StockStatusEmun.çç¹åºå宿.ObjToInt()) { return content.Error("该æçç¶æä¸å¯¹,ä¸å 许çç¹å ¥åº"); } stock.StockStatus = StockStatusEmun.å ¥åºç¡®è®¤.ObjToInt(); var palletCodes = new HashSet<string>(StringComparer.OrdinalIgnoreCase); if (!string.IsNullOrEmpty(takeStockOrder.AllPalletCode)) { @@ -256,19 +234,14 @@ .Select(p => p.Trim()) .ToHashSet(StringComparer.OrdinalIgnoreCase); } Dt_TakeStockOrderDetail isReturn = _takeStockOrderDetail.QueryFirst(x => x.TakePalletCode == boxNo && (x.TakeDetalStatus == TakeStockDetailStatusEnum.æªè¿è¡å¹³è´¦å¤ç.ObjToInt() || x.TakeDetalStatus == TakeStockDetailStatusEnum.ææ¶æå平账å¤çä¸.ObjToInt())); if(isReturn != null) { return WebResponseContent.Instance.Error("该æçè¿ææ¡ç å¾ å¹³è´¦ï¼è¯·å å¤çåååº"); } bool hasRelatedTasks = _taskRepository.QueryData(x => palletCodes.Contains(x.PalletCode)).Any(); bool hasRelatedDetails = _takeStockOrderDetail.QueryData(x => palletCodes.Contains(x.TakePalletCode)).Any(); int overPalletCodeCount = _stockInfoRepository.QueryData(x => palletCodes.Contains(x.PalletCode) && (x.StockStatus == StockStatusEmun.åºåºå®æ.ObjToInt() || x.StockStatus == StockStatusEmun.å ¥åºå®æ.ObjToInt() || x.StockStatus == StockStatusEmun.åºåºéå®.ObjToInt()|| x.StockStatus == StockStatusEmun.å ¥åºç¡®è®¤.ObjToInt())).Count(); bool hasRelatedTasks = palletCodes.Count == overPalletCodeCount + 1; if (!hasRelatedTasks && !hasRelatedDetails) if (hasRelatedTasks) { takeStockOrder.TakeStockStatus = (int)TakeStockStatusEnum.çç¹å®æ; } stock.StockStatus = StockStatusEmun.å ¥åºç¡®è®¤.ObjToInt(); // åé æ°è´§ä½ var newLocation = _locationInfoService.AssignLocation(stock.LocationType); @@ -416,128 +389,123 @@ } } public WebResponseContent DocumentReconciliation(int orderId, int id) public WebResponseContent DocumentReconciliation(string barcode) { WebResponseContent webResponseContent = new WebResponseContent(); try { Dt_TakeStockOrderDetail takeStockOrderDetail = _takeStockOrderDetail.QueryFirst(x => x.Id == id); Dt_TakeStockOrderDetail takeStockOrderDetail = _takeStockOrderDetail.QueryFirst(x => x.barcode == barcode); if(takeStockOrderDetail== null) { return WebResponseContent.Instance.Error("æªæ¾å°è¯¥çç¹å·®å¼æ°æ®"); } if(takeStockOrderDetail.Remark == "çç") { Dt_InboundOrderDetail inboundOrderDetail = _inboundOrderDetailRepository.QueryFirst(x => x.Id == orderId); if(inboundOrderDetail == null) { return WebResponseContent.Instance.Error("æªæ¾å°éæ©çææ¶å¹³è´¦åæ®"); } Dt_InboundOrder inboundOrder = _inboundOrderRepository.Db.Queryable<Dt_InboundOrder>().Where(x=>x.Id == inboundOrderDetail.OrderId).Includes(x=>x.Details).First(); Dt_StockInfo stockInfo = _stockInfoRepository.Db.Queryable<Dt_StockInfo>().Where(x=>x.PalletCode == takeStockOrderDetail.TakePalletCode && x.StockStatus == StockStatusEmun.çç¹åºå宿.ObjToInt()).Includes(x=>x.Details).First(); if(stockInfo== null) { return WebResponseContent.Instance.Error($"çç¹æç{takeStockOrderDetail.TakePalletCode}çåºåä¿¡æ¯æªæ¾å°ï¼ææçç¶æä¸æ£ç¡®"); } var datevaliDate = _inboundOrderRepository.Db.Queryable<Dt_MaterialExpirationDate>().Where(x => x.MaterialCode.Contains(inboundOrderDetail.MaterielCode.Substring(0, 6))).First(); var newStockDetail = new Dt_StockInfoDetail { StockId = stockInfo == null ? 0 : stockInfo.Id, Barcode = inboundOrderDetail.Barcode, MaterielCode = inboundOrderDetail.MaterielCode, MaterielName = inboundOrderDetail.MaterielName, BatchNo = inboundOrderDetail.BatchNo, Unit = inboundOrderDetail.Unit, InboundOrderRowNo = inboundOrderDetail.lineNo, SupplyCode = inboundOrderDetail.SupplyCode, WarehouseCode = inboundOrderDetail.WarehouseCode, StockQuantity = inboundOrderDetail.OrderQuantity, BarcodeQty = inboundOrderDetail.BarcodeQty, BarcodeUnit = inboundOrderDetail.BarcodeUnit, FactoryArea = inboundOrder.FactoryArea, Status = 0, OrderNo = inboundOrder.InboundOrderNo, BusinessType = inboundOrder.BusinessType, ValidDate = inboundOrder.BusinessType == BusinessTypeEnum.å¤é¨ä»åºè°æºä».ToString() ? inboundOrderDetail.ValidDate : datevaliDate == null ? null : Convert.ToDateTime(DateTime.Now).AddDays(Convert.ToDouble(datevaliDate.ValidityDays)), }; stockInfo.Details.Add(newStockDetail); //if(takeStockOrderDetail.Remark == "çç") //{ // Dt_InboundOrderDetail inboundOrderDetail = _inboundOrderDetailRepository.QueryFirst(x => x.Id == orderId); // if(inboundOrderDetail == null) // { // return WebResponseContent.Instance.Error("æªæ¾å°éæ©çææ¶å¹³è´¦åæ®"); // } // Dt_InboundOrder inboundOrder = _inboundOrderRepository.Db.Queryable<Dt_InboundOrder>().Where(x=>x.Id == inboundOrderDetail.OrderId).Includes(x=>x.Details).First(); // Dt_StockInfo stockInfo = _stockInfoRepository.Db.Queryable<Dt_StockInfo>().Where(x=>x.PalletCode == takeStockOrderDetail.TakePalletCode && x.StockStatus == StockStatusEmun.çç¹åºå宿.ObjToInt()).Includes(x=>x.Details).First(); // if(stockInfo== null) // { // return WebResponseContent.Instance.Error($"çç¹æç{takeStockOrderDetail.TakePalletCode}çåºåä¿¡æ¯æªæ¾å°ï¼ææçç¶æä¸æ£ç¡®"); // } // var datevaliDate = _inboundOrderRepository.Db.Queryable<Dt_MaterialExpirationDate>().Where(x => x.MaterialCode.Contains(inboundOrderDetail.MaterielCode.Substring(0, 6))).First(); // var newStockDetail = new Dt_StockInfoDetail // { // StockId = stockInfo == null ? 0 : stockInfo.Id, // Barcode = inboundOrderDetail.Barcode, // MaterielCode = inboundOrderDetail.MaterielCode, // MaterielName = inboundOrderDetail.MaterielName, // BatchNo = inboundOrderDetail.BatchNo, // Unit = inboundOrderDetail.Unit, // InboundOrderRowNo = inboundOrderDetail.lineNo, // SupplyCode = inboundOrderDetail.SupplyCode, // WarehouseCode = inboundOrderDetail.WarehouseCode, // StockQuantity = inboundOrderDetail.OrderQuantity, // BarcodeQty = inboundOrderDetail.BarcodeQty, // BarcodeUnit = inboundOrderDetail.BarcodeUnit, // FactoryArea = inboundOrder.FactoryArea, // Status = 0, // OrderNo = inboundOrder.InboundOrderNo, // BusinessType = inboundOrder.BusinessType, // ValidDate = inboundOrder.BusinessType == BusinessTypeEnum.å¤é¨ä»åºè°æºä».ToString() ? inboundOrderDetail.ValidDate : datevaliDate == null ? null : Convert.ToDateTime(DateTime.Now).AddDays(Convert.ToDouble(datevaliDate.ValidityDays)), // }; // stockInfo.Details.Add(newStockDetail); inboundOrderDetail.ReceiptQuantity = inboundOrderDetail.OrderQuantity; inboundOrderDetail.OverInQuantity = inboundOrderDetail.OrderQuantity; inboundOrderDetail.OrderDetailStatus = OrderDetailStatusEnum.Over.ObjToInt(); int overCount = 1; int moreOverCount = inboundOrder.Details.Count(x => x.OrderDetailStatus == OrderDetailStatusEnum.Over.ObjToInt()); if (inboundOrder.Details.Count() == overCount + moreOverCount) { inboundOrder.OrderStatus = InOrderStatusEnum.å ¥åºå®æ.ObjToInt(); } else { inboundOrder.OrderStatus = InOrderStatusEnum.å ¥åºä¸.ObjToInt(); } takeStockOrderDetail.DifferenceQty -= inboundOrderDetail.OrderQuantity; if(takeStockOrderDetail.DifferenceQty > 0) { takeStockOrderDetail.TakeDetalStatus = TakeStockDetailStatusEnum.ææ¶æå平账å¤çä¸.ObjToInt(); } else if (takeStockOrderDetail.DifferenceQty == 0) { takeStockOrderDetail.TakeDetalStatus = TakeStockDetailStatusEnum.ææ¶æå平账å¤ç.ObjToInt(); } else { return WebResponseContent.Instance.Error("è¯¥ææ¶åæ®æç»æ¡ç æ°é大äºå¾ 平账æ°éï¼è¯·å¦éå ¶ä»åæ®å¹³è´¦"); } // inboundOrderDetail.ReceiptQuantity = inboundOrderDetail.OrderQuantity; // inboundOrderDetail.OverInQuantity = inboundOrderDetail.OrderQuantity; // inboundOrderDetail.OrderDetailStatus = OrderDetailStatusEnum.Over.ObjToInt(); // int overCount = 1; // int moreOverCount = inboundOrder.Details.Count(x => x.OrderDetailStatus == OrderDetailStatusEnum.Over.ObjToInt()); // if (inboundOrder.Details.Count() == overCount + moreOverCount) // { // inboundOrder.OrderStatus = InOrderStatusEnum.å ¥åºå®æ.ObjToInt(); // } // else // { // inboundOrder.OrderStatus = InOrderStatusEnum.å ¥åºä¸.ObjToInt(); // } // takeStockOrderDetail.DifferenceQty -= inboundOrderDetail.OrderQuantity; // if(takeStockOrderDetail.DifferenceQty > 0) // { // takeStockOrderDetail.TakeDetalStatus = TakeStockDetailStatusEnum.ææ¶æå平账å¤çä¸.ObjToInt(); // } // else if (takeStockOrderDetail.DifferenceQty == 0) // { // takeStockOrderDetail.TakeDetalStatus = TakeStockDetailStatusEnum.ææ¶æå平账å¤ç.ObjToInt(); // } // else // { // return WebResponseContent.Instance.Error("è¯¥ææ¶åæ®æç»æ¡ç æ°é大äºå¾ 平账æ°éï¼è¯·å¦éå ¶ä»åæ®å¹³è´¦"); // } _unitOfWorkManage.BeginTran(); _inboundOrderRepository.UpdateData(inboundOrder); _inboundOrderDetailRepository.UpdateData(inboundOrderDetail); _takeStockOrderDetail.UpdateData(takeStockOrderDetail); BaseDal.Db.Insertable(newStockDetail).ExecuteCommand(); _unitOfWorkManage.CommitTran(); List<string> barcodes = new List<string>(); barcodes.Add(inboundOrderDetail.Barcode); _outboundPickingService.NoStockOutBatchInOrderFeedbackToMes(inboundOrder.Id, barcodes); // _unitOfWorkManage.BeginTran(); // _inboundOrderRepository.UpdateData(inboundOrder); // _inboundOrderDetailRepository.UpdateData(inboundOrderDetail); // _takeStockOrderDetail.UpdateData(takeStockOrderDetail); // BaseDal.Db.Insertable(newStockDetail).ExecuteCommand(); // _unitOfWorkManage.CommitTran(); // List<string> barcodes = new List<string>(); // barcodes.Add(inboundOrderDetail.Barcode); // _outboundPickingService.NoStockOutBatchInOrderFeedbackToMes(inboundOrder.Id, barcodes); } else { Dt_OutboundOrderDetail outboundOrderDetail = _outboundOrderDetailRepository.QueryFirst(x => x.Id == orderId); //} //else //{ Dt_OutboundOrderDetail outboundOrderDetail = _outboundOrderDetailRepository.QueryFirst(x => x.Remark == takeStockOrderDetail.TakeStockNo && (x.OrderQuantity-x.LockQuantity-x.MoveQty)>0); if (outboundOrderDetail == null) { return WebResponseContent.Instance.Error("æªæ¾å°éæ©çæåå¹³è´¦åæ®"); } if(outboundOrderDetail.MaterielCode != takeStockOrderDetail.MaterielCode) { return WebResponseContent.Instance.Error("䏿åå¹³è´¦åæ®ç©æç¼ç ä¸å¹é "); } if (!string.IsNullOrWhiteSpace(outboundOrderDetail.BatchNo)&& outboundOrderDetail.BatchNo != takeStockOrderDetail.BatchNo) { return WebResponseContent.Instance.Error("䏿åå¹³è´¦åæ®ç©ææ¹æ¬¡ä¸å¹é "); } if (!string.IsNullOrWhiteSpace(outboundOrderDetail.SupplyCode) && outboundOrderDetail.SupplyCode != takeStockOrderDetail.SupplyCode) { return WebResponseContent.Instance.Error("䏿åå¹³è´¦åæ®ä¾åºåä¸å¹é "); } Dt_OutboundOrder outboundOrder = _outboundOrderRepository.Db.Queryable<Dt_OutboundOrder>().Where(x => x.Id == outboundOrderDetail.OrderId).Includes(x => x.Details).First(); Dt_StockInfo stockInfo = _stockInfoRepository.Db.Queryable<Dt_StockInfo>().Where(x => x.PalletCode == takeStockOrderDetail.TakePalletCode && x.StockStatus == StockStatusEmun.çç¹åºå宿.ObjToInt()).Includes(x => x.Details).First(); if (stockInfo == null) { return WebResponseContent.Instance.Error($"çç¹æç{takeStockOrderDetail.TakePalletCode}çåºåä¿¡æ¯æªæ¾å°ï¼ææçç¶æä¸æ£ç¡®"); } if(outboundOrderDetail.OrderQuantity + takeStockOrderDetail.DifferenceQty > 0) { return WebResponseContent.Instance.Error("该æååæ®æç»åææ°é大äºå¾ 平账æ°éï¼è¯·å¦éå ¶ä»åæ®å¹³è´¦"); } else if(outboundOrderDetail.OrderQuantity + takeStockOrderDetail.DifferenceQty < 0) { takeStockOrderDetail.TakeDetalStatus = TakeStockDetailStatusEnum.ææ¶æå平账å¤çä¸.ObjToInt(); } else { takeStockOrderDetail.TakeDetalStatus = TakeStockDetailStatusEnum.ææ¶æå平账å¤ç.ObjToInt(); } OutboundCompleteRequestDTO request = new OutboundCompleteRequestDTO() { OrderNo = outboundOrder.OrderNo, PalletCode = stockInfo.PalletCode, PalletCode = takeStockOrderDetail.TakePalletCode, Barcode = takeStockOrderDetail.barcode, Operator = App.User.UserName }; decimal stoQty = takeStockOrderDetail.SysQty; webResponseContent = CompleteOutboundWithBarcode(request, stoQty, orderId); webResponseContent = CompleteOutboundWithBarcode(request,outboundOrderDetail.Id); takeStockOrderDetail.DifferenceQty = 0; _takeStockOrderDetail.UpdateData(takeStockOrderDetail); } return WebResponseContent.Instance.OK(data: webResponseContent); } catch(Exception ex) @@ -547,7 +515,7 @@ } } public WebResponseContent CompleteOutboundWithBarcode(OutboundCompleteRequestDTO request ,decimal stoQty, int orderDetailId) public WebResponseContent CompleteOutboundWithBarcode(OutboundCompleteRequestDTO request ,int orderDetailId) { WebResponseContent content = WebResponseContent.Instance; @@ -572,13 +540,7 @@ return WebResponseContent.Instance.Error($"æ¡ç {request.Barcode} 对åºçåºåæç»ä¸åå¨"); } // 3. éªè¯åºåæç»ä¸æçæ¯å¦å¹é if (stockDetail.StockId != stockInfo.Id) { response.Success = false; response.Message = $"æ¡ç {request.Barcode} ä¸å±äºæçå· {request.PalletCode} çåºåæç»"; return WebResponseContent.Instance.Error($"æ¡ç {request.Barcode} ä¸å±äºæçå· {request.PalletCode} çåºåæç»"); } // 4. æ¥æ¾åºåºåä¿¡æ¯ Dt_OutboundOrder outboundOrder = _outboundOrderRepository.QueryFirst(o => o.OrderNo == request.OrderNo); @@ -595,11 +557,11 @@ return WebResponseContent.Instance.Error("æªæ¾å°åºåºåæç»"); } // å®é åºåºé decimal actualOutboundQuantity = outboundOrderDetail.OrderQuantity; decimal actualOutboundQuantity = outboundOrderDetail.OrderQuantity-outboundOrderDetail.LockQuantity-outboundOrderDetail.MoveQty; // 8. 夿æ¯å¦éè¦æå ï¼å½åºåºæ°éå°äºåºåæ°éæ¶éè¦æå ï¼ bool isUnpacked = outboundOrderDetail.OrderQuantity < stockDetail.StockQuantity; bool isUnpacked = actualOutboundQuantity < stockDetail.StockQuantity; List<MaterialCodeReturnDTO> returnDTOs = new List<MaterialCodeReturnDTO>(); string newBarcode = string.Empty; // 9. å¼å¯äºå¡ @@ -744,10 +706,10 @@ if (!string.IsNullOrEmpty(newBarcode)) { // ç©ææ°æ¡ç åä¼ _feedbackMesService.BarcodeFeedback(newBarcode); //_feedbackMesService.BarcodeFeedback(newBarcode); } _feedbackMesService.OutboundFeedback(outboundOrder.OrderNo); //_feedbackMesService.OutboundFeedback(outboundOrder.OrderNo); } catch (Exception ex) @@ -767,6 +729,10 @@ return content; } public WebResponseContent StockTakeGroupPallet(string barcode, string boxNo) { throw new NotImplementedException(); } } } ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundService.cs
@@ -108,139 +108,120 @@ public WebResponseContent ProcessPickingOutbound(PickingOutboundRequestDTO request) { WebResponseContent content = WebResponseContent.Instance; PickingOutboundResponseDTO response = new PickingOutboundResponseDTO(); decimal totalNeedAllocate = 0; // æ»éæ±åé é decimal totalActualAllocate = 0; // å®é æ»åé é try { _unitOfWorkManage.BeginTran(); // 1. 计ç®åºåºæ°éé»è¾ OutboundCalculationDTO calculationResult = CalcOutboundQuantity(request); if (!calculationResult.CanOutbound) { content = WebResponseContent.Instance.Error("æ æ³å¤çæ£è´§åºåºï¼" + calculationResult.ErrorMessage); _unitOfWorkManage.RollbackTran(); return content; } // è®°å½æ»éæ±æ°é totalNeedAllocate = calculationResult.MaterielCalculations.Sum(x => x.UnallocatedQuantity); // 2. è°ç¨åºåºå¤çé»è¾ï¼éå®åºåï¼çæåºåºè®°å½ç // 2. å¤çç©æåé List<PickedStockDetailDTO> pickedDetails = new List<PickedStockDetailDTO>(); // è·ååºåºåä¿¡æ¯ Dt_OutboundOrder outboundOrder = calculationResult.OutboundOrder; // åºåºè¯¦æ æ·»å æä¿®æ¹éå List<Dt_OutStockLockInfo> outStockLockInfos = new List<Dt_OutStockLockInfo>(); List<Dt_OutboundOrderDetail> outboundOrderDetails = new(); List<Dt_OutboundOrderDetail> outboundOrderDetails = new List<Dt_OutboundOrderDetail>(); List<Dt_Task> tasks = new List<Dt_Task>(); foreach (var materielCalc in calculationResult.MaterielCalculations) { (List<PickedStockDetailDTO> PickedDetails, List<Dt_Task> Tasks, List<Dt_OutStockLockInfo> OutStockLockInfo) materielPickedDetails = ProcessMaterielTaskGeneration(outboundOrder, materielCalc, request, calculationResult.FactoryArea); var materielPickedDetails = ProcessMaterielTaskGeneration(outboundOrder, materielCalc, request, calculationResult.FactoryArea); // 计ç®å½åç©æå®é åé é decimal actualAllocatedQuantity = materielPickedDetails.PickedDetails.Sum(x => x.OutboundQuantity); actualAllocatedQuantity = Math.Min(actualAllocatedQuantity, materielCalc.UnallocatedQuantity); totalActualAllocate += actualAllocatedQuantity; // ç´¯å è³æ»å®é åé é materielCalc.UnallocatedQuantity = materielCalc.UnallocatedQuantity - actualAllocatedQuantity; // å¤çåºåºéå®è®°å½ foreach (var item in materielPickedDetails.OutStockLockInfo) { Dt_OutStockLockInfo? outStockLockInfo = materielCalc.OutStockLockInfos.FirstOrDefault(x => x.Id == item.Id && x.Id > 0); if (outStockLockInfo != null) Dt_OutStockLockInfo? existLockInfo = materielCalc.OutStockLockInfos.FirstOrDefault(x => x.Id == item.Id && x.Id > 0); if (existLockInfo != null) { outStockLockInfo = item; existLockInfo = item; Dt_Task? task = tasks.FirstOrDefault(x => x.PalletCode == item.PalletCode); if (task != null) { outStockLockInfo.TaskNum = task.TaskNum; } if (task != null) existLockInfo.TaskNum = task.TaskNum; } else { Dt_Task? task = tasks.FirstOrDefault(x => x.PalletCode == item.PalletCode); if (task != null) { item.TaskNum = task.TaskNum; } if (task != null) item.TaskNum = task.TaskNum; materielCalc.OutStockLockInfos.Add(item); } outStockLockInfos.Add(item); } // å¤çä»»å¡ foreach (var item in materielPickedDetails.Tasks) { Dt_Task? task = tasks.FirstOrDefault(x => x.PalletCode == item.PalletCode); if (task == null) { if (tasks.FirstOrDefault(x => x.PalletCode == item.PalletCode) == null) tasks.Add(item); } } // æ±æ»åæ£æç» pickedDetails.AddRange(materielPickedDetails.PickedDetails); decimal allallocatedQuantity = Math.Min(materielCalc.UnallocatedQuantity, materielPickedDetails.PickedDetails.Sum(x => x.OutboundQuantity)); materielCalc.UnallocatedQuantity = allallocatedQuantity; // æ´æ°åºåºåæç»ï¼å¢å é宿°éï¼ä¸å¢å å·²åºæ°éï¼ // æå®é åé éæ´æ°åæ®é宿°é decimal remainingToLock = actualAllocatedQuantity; foreach (var detail in materielCalc.Details) { if (allallocatedQuantity <= 0) break; decimal lockQuantity = (detail.OrderQuantity - detail.OverOutQuantity); if (lockQuantity < materielCalc.UnallocatedQuantity) { detail.LockQuantity += lockQuantity; // å¢å é宿°é 䏿´æ° OverOutQuantity å OrderDetailStatusï¼å ä¸ºè¿æ²¡æå®é åºåº if (remainingToLock <= 0) break; decimal maxLockableQty = detail.OrderQuantity - detail.OverOutQuantity - detail.LockQuantity; if (maxLockableQty <= 0) continue; decimal currentLockQty = Math.Min(remainingToLock, maxLockableQty); detail.LockQuantity += currentLockQty; outboundOrderDetails.Add(detail); materielCalc.UnallocatedQuantity -= lockQuantity; } else { detail.LockQuantity += materielCalc.UnallocatedQuantity; outboundOrderDetails.Add(detail); break; } remainingToLock -= currentLockQty; } } // 3. æ´æ°åºåºåç¶æä¸ºåºåºä¸ï¼è¡¨ç¤ºå·²æä»»å¡åé ï¼ // 3. æ¹éæ´æ°ç¶æï¼åæé»è¾ä¸åï¼ UpdateOutboundOrderStatus(request.OrderNo, (int)OutOrderStatusEnum.åºåºä¸); // 4. æ´æ°åºåºåæç»é宿°é _detailRepository.UpdateData(outboundOrderDetails); // 5. æ´æ°åºåç¶æ if (pickedDetails.Any()) { UpdateStockStatus(pickedDetails.Select(x => x.PalletCode).ToList(), StockStatusEmun.åºåºéå®.ObjToInt()); // 6. æ´æ°è´§ä½ç¶æ UpdateLocationStatus(pickedDetails.Select(x => x.LocationCode).ToList(), LocationStatusEnum.Lock.ObjToInt()); // 7. æ´æ°åºå详æ } UpdateOutStockLockInfo(outStockLockInfos); // 8. æ·»å 任塿°æ® _taskRepository.AddData(tasks); if (tasks.Any()) _taskRepository.AddData(tasks); _unitOfWorkManage.CommitTran(); // 4. æé ååºï¼åºåãå ¨é¨åé ãåãé¨ååé ã string responseMsg = totalActualAllocate == totalNeedAllocate ? "忣任å¡åé æå" : $"忣任å¡åé 宿ï¼å®é åé {totalActualAllocate}ï¼éæ±{totalNeedAllocate}ï¼åºåä¸è¶³é¨åæªåé ï¼"; response.Success = true; response.Message = "忣任å¡åé æå"; response.Tasks = tasks; // è¿å第ä¸ä¸ªä»»å¡å· response.PickedDetails = pickedDetails; // è¿å第ä¸ä¸ªåæ£æç» content = WebResponseContent.Instance.OK("忣任å¡åé æå", response); return content; response.Message = responseMsg; response.Tasks = tasks; response.PickedDetails = pickedDetails; content = WebResponseContent.Instance.OK(responseMsg, response); } catch (Exception ex) { _unitOfWorkManage.RollbackTran(); content = WebResponseContent.Instance.Error("å¤çæ£è´§åºåºå¤±è´¥ï¼" + ex.Message); } return content; } /// <summary> /// 计ç®åºåºæ°éé»è¾ /// 计ç®åºåºæ°éé»è¾ï¼åæé»è¾ä¸åï¼ /// </summary> /// <param name="request"></param> /// <returns></returns> public OutboundCalculationDTO CalcOutboundQuantity(PickingOutboundRequestDTO request) { OutboundCalculationDTO result = new(); OutboundCalculationDTO result = new OutboundCalculationDTO(); try { Dt_OutboundOrder outboundOrder = _outboundRepository.QueryFirst(x => x.OrderNo == request.OrderNo); @@ -253,23 +234,14 @@ result.FactoryArea = outboundOrder.FactoryArea; List<Dt_OutboundOrderDetail> selectedDetails = new List<Dt_OutboundOrderDetail>(); if (request.DetailIds == null || !request.DetailIds.Any()) { selectedDetails = _detailRepository.QueryData(x => x.OrderId == outboundOrder.Id); } else { // è·åéæ©çåºåºæç» selectedDetails = _detailRepository.QueryData(x => x.OrderId == outboundOrder.Id && request.DetailIds.Contains(x.Id)); } //if (outboundOrder.IsBatch == 1 && request.DetailIds.Count == 1) //{ // selectedDetails = _detailRepository.QueryData(x => x.OrderId == selectedDetails.First().OrderId && x.WarehouseCode == selectedDetails.First().WarehouseCode && x.MaterielCode == selectedDetails.First().MaterielCode && x.BatchNo == selectedDetails.First().BatchNo && x.SupplyCode == selectedDetails.First().SupplyCode); //} if (!selectedDetails.Any()) { @@ -280,23 +252,21 @@ if (selectedDetails.Any(x => x.LockQuantity > x.OrderQuantity - x.MoveQty || x.OverOutQuantity > x.OrderQuantity - x.MoveQty)) { List<int> selectDetailIds = selectedDetails.Where(x => x.LockQuantity > x.OrderQuantity - x.MoveQty || x.OverOutQuantity > x.OrderQuantity - x.MoveQty).Select(x => x.Id).ToList(); result.CanOutbound = false; result.ErrorMessage = $"åºåºæç»ä¿¡æ¯{string.Join(",", selectDetailIds)}å·²åé 宿"; return result; } outboundOrder.Details = selectedDetails; result.OutboundOrder = outboundOrder; result.SelectedDetails = selectedDetails; if (outboundOrder.IsBatch == 0 || request.DetailIds.Count != 1) { // 夿ç»åºåºï¼æç©æåç»å¤ç result.MaterielCalculations = CalcMaterielOutboundQuantities(outboundOrder, selectedDetails.ToList()); } else { // åæç»åºåºï¼éªè¯è¾å ¥çåºåºæ°é if (!request.OutboundQuantity.HasValue || request.OutboundQuantity.Value <= 0) { result.CanOutbound = false; @@ -308,10 +278,8 @@ decimal orderQuantity = selectedDetails.Sum(x => x.OrderQuantity); decimal moveQuantity = selectedDetails.Sum(x => x.MoveQty); decimal overQuantity = selectedDetails.Sum(x => x.OverOutQuantity); Dt_OutboundOrderDetail? singleDetail = selectedDetails.First(); //夿å¯åºåºæ°é if (orderQuantity - lockQuantity - moveQuantity < request.OutboundQuantity.Value || orderQuantity - overQuantity - moveQuantity < request.OutboundQuantity.Value) { result.CanOutbound = false; @@ -325,10 +293,7 @@ { inputQuantity -= (item.OrderQuantity - item.MoveQty - item.LockQuantity); outboundOrderDetails.Add(item); if (inputQuantity <= 0) { break; } if (inputQuantity <= 0) break; } result.MaterielCalculations = new List<MaterielOutboundCalculationDTO>() @@ -348,31 +313,24 @@ Details = outboundOrderDetails } }; outboundOrder.Details = outboundOrderDetails; } result.CanOutbound = true; return result; } catch (Exception ex) { result.CanOutbound = false; result.ErrorMessage = ex.Message; } return result; } } /// <summary> /// å¤åºåºåæç»æ¶ï¼æç©æåç»è®¡ç®åºåºæ°é /// æç©æåç»è®¡ç®åºåºæ°éï¼åæé»è¾ä¸åï¼ /// </summary> /// <param name="selectedDetails"></param> /// <returns></returns> private List<MaterielOutboundCalculationDTO> CalcMaterielOutboundQuantities(Dt_OutboundOrder outboundOrder, List<Dt_OutboundOrderDetail> selectedDetails) { // æç©æåç»ï¼ç©æç¼å·ãæ¹æ¬¡å·ãä¾åºåç¼å·ãä»åºç¼å· List<MaterielOutboundCalculationDTO> materielGroups = selectedDetails return selectedDetails .GroupBy(x => new { x.MaterielCode, @@ -392,138 +350,397 @@ UnallocatedQuantity = g.Sum(x => x.OrderQuantity - x.LockQuantity - x.MoveQty), MovedQuantity = g.Sum(x => x.MoveQty), Details = g.ToList(), OutStockLockInfos = _outboundLockInfoRepository.QueryData(x => x.MaterielCode == g.Key.MaterielCode && x.BatchNo == g.Key.BatchNo && x.OrderType == (int)outboundOrder.OrderType && x.OrderNo == outboundOrder.OrderNo) OutStockLockInfos = _outboundLockInfoRepository.QueryData(x => x.MaterielCode == g.Key.MaterielCode && x.BatchNo == g.Key.BatchNo && x.OrderType == (int)outboundOrder.OrderType && x.OrderNo == outboundOrder.OrderNo) }) .ToList(); return materielGroups; } /// <summary> /// å¤çç©æçä»»å¡çæ /// å¤çç©æä»»å¡çæï¼æ ¸å¿ï¼æå¤å°åå¤å°+ç§»é¤åºåä¸è¶³å¼å¸¸ï¼ /// </summary> /// <param name="outboundOrder">åºåºè®¢å</param> /// <param name="materielCalc">æç©æçåºåºè®¡ç®ç»æ</param> /// <param name="request">忣åºåºè¯·æ±</param> /// <param name="factoryArea"></param> /// <returns></returns> /// <exception cref="Exception"></exception> private (List<PickedStockDetailDTO> PickedDetails, List<Dt_Task> Tasks, List<Dt_OutStockLockInfo> OutStockLockInfo) ProcessMaterielTaskGeneration(Dt_OutboundOrder outboundOrder, MaterielOutboundCalculationDTO materielCalc, PickingOutboundRequestDTO request, string factoryArea) private (List<PickedStockDetailDTO> PickedDetails, List<Dt_Task> Tasks, List<Dt_OutStockLockInfo> OutStockLockInfo) ProcessMaterielTaskGeneration( Dt_OutboundOrder outboundOrder, MaterielOutboundCalculationDTO materielCalc, PickingOutboundRequestDTO request, string factoryArea) { List<PickedStockDetailDTO> pickedDetails = new List<PickedStockDetailDTO>(); List<Dt_Task> generatedTasks = new List<Dt_Task>(); List<Dt_Task> generatedTasks = new List<Dt_Task>(); // åå§ç©ºä»»å¡å表 List<Dt_OutStockLockInfo> lockInfoList = new List<Dt_OutStockLockInfo>(); decimal remainingQuantity = materielCalc.UnallocatedQuantity; // æå»ºåºåæ¥è¯¢æ¡ä»¶ï¼å å«åºå表ãåºåæç»ï¼ List<Dt_StockInfo> stockQuery = BuildStockQueryWithInfo(materielCalc, factoryArea); if (!stockQuery.Any()) // 1. ä¼å å¤çæå®åºåæç» if (request.StockDetailIds?.Any() == true) { throw new Exception($"ç©æ {materielCalc.MaterielCode} 对åºçåºåä¸åå¨"); var specifiedResult = AllocateSpecifiedStockDetails(outboundOrder, materielCalc, request, factoryArea, remainingQuantity); pickedDetails.AddRange(specifiedResult.PickedDetails); lockInfoList.AddRange(specifiedResult.LockInfoList); remainingQuantity -= specifiedResult.ActualAllocatedQuantity; // ===== æ ¸å¿ä¿®å¤ï¼æå®åºååé åï¼ç«å³çæä»»å¡ï¼æ 论å©ä½éå¤å°ï¼===== if (specifiedResult.PickedDetails.Any()) // ææå®åºååé ç»æå°±çæä»»å¡ { var specifiedTasks = GenerateTasksForSpecifiedStock(specifiedResult.PickedDetails, request.OutboundTargetLocation); generatedTasks.AddRange(specifiedTasks); // æ·»å æå®åºåä»»å¡å°æ»ä»»å¡å表 } // æ¹éè®¡ç®æ»å¯ç¨åºåæ°é (Dictionary<int, decimal> AvailableStockMap, Dictionary<int, List<Dt_OutStockLockInfo>> LockStockMap) data = GetBatchAvailableStockQuantities(materielCalc, stockQuery); // å©ä½é<=0æ¶ï¼ç´æ¥è¿åï¼å·²çææå®åºåä»»å¡ï¼ if (remainingQuantity <= 0) { return (pickedDetails, generatedTasks, lockInfoList); } } // å¯ç¨åºåæ°éæ å° Dictionary<int, decimal> availableStockMap = data.AvailableStockMap; // 2. å¤çå©ä½æ°éçèªå¨åé ï¼åæé»è¾ä¸åï¼èªå¨åé çä»»å¡ä¼è¿½å å°generatedTasksï¼ List<Dt_StockInfo> stockQuery = BuildStockQueryWithInfo(materielCalc, factoryArea); var allocatedPalletCodes = pickedDetails.Select(x => x.PalletCode).Distinct().ToList(); stockQuery = stockQuery.Where(x => !allocatedPalletCodes.Contains(x.PalletCode)).ToList(); // ç©ææ»å¯ç¨åºåæ°é decimal totalAvailableStock = availableStockMap.Values.Sum(); var stockData = GetBatchAvailableStockQuantities(materielCalc, stockQuery); decimal totalAutoAvailable = stockData.AvailableStockMap.Values.Sum(); decimal autoAllocateQuantity = Math.Min(remainingQuantity, totalAutoAvailable); remainingQuantity -= autoAllocateQuantity; // å·²éå®åºåæ°éæ å° Dictionary<int, List<Dt_OutStockLockInfo>> lockStockMap = data.LockStockMap; // éªè¯æ»å¯ç¨åºåæ¯å¦æ»¡è¶³åºåºéæ± //if (totalAvailableStock < materielCalc.UnallocatedQuantity) //{ // throw new Exception($"ç©æ {materielCalc.MaterielCode} å¯ç¨åºå {totalAvailableStock} ä¸è¶³åºåºæ°é {materielCalc.UnallocatedQuantity}"); //} // éåé æ°é decimal remainingQuantity = Math.Min(totalAvailableStock, materielCalc.UnallocatedQuantity); // éåé æ°é //decimal remainingQuantity = materielCalc.UnallocatedQuantity; // å·²åé çæçå表 List<string> allocatedPallets = new List<string>(); // è·å第ä¸ä¸ªåºåºæç» if (autoAllocateQuantity > 0 && stockQuery.Any()) { Dt_OutboundOrderDetail firstDetail = materielCalc.Details.First(); // é¢å è½½åºåæç»åéå®è®°å½ List<int> stockIds = stockQuery.Select(x => x.Id).ToList(); Dictionary<int, List<Dt_StockInfoDetail>> stockDetailMap = stockQuery.ToDictionary(x => x.Id, x => x.Details); // è®°å½æ¯ä¸ªæççå®é åé é Dictionary<string, decimal> palletAllocations = new Dictionary<string, decimal>(); List<Dt_OutStockLockInfo> lockInfoList = new List<Dt_OutStockLockInfo>(); foreach (var stock in stockQuery) { if (remainingQuantity <= 0) break; // å½ååºåå¯ç¨æ°é decimal availableQuantity = availableStockMap.GetValueOrDefault(stock.Id, 0); if (autoAllocateQuantity <= 0) break; decimal availableQuantity = stockData.AvailableStockMap.GetValueOrDefault(stock.Id, 0); if (availableQuantity <= 0) continue; // 计ç®è¯¥æçå¯åé æ°é decimal allocateQuantity = Math.Min(remainingQuantity, availableQuantity); (decimal ActualAllocatedQuantity, List<Dt_OutStockLockInfo> LockInfoList) actualAllocated = AllocateStockQuantity(stock, allocateQuantity, availableQuantity, outboundOrder, firstDetail, request, lockStockMap.GetValueOrDefault(stock.Id, new List<Dt_OutStockLockInfo>()), stockDetailMap); // èªå¨åé æ¶æ¥è¯¢æçæ»åºåï¼åæä¼åé»è¾ä¸åï¼ decimal palletMaterielTotalStock = _stockDetailRepository.QueryData( x => x.StockId == stock.Id && x.MaterielCode == materielCalc.MaterielCode ).Sum(x => x.StockQuantity); // æ¬æ¬¡åé çæ°é decimal actualAllocatedQuantity = actualAllocated.ActualAllocatedQuantity; decimal allocateQuantity = Math.Min(autoAllocateQuantity, availableQuantity); var actualAllocated = AllocateStockQuantity( stock, allocateQuantity, availableQuantity, outboundOrder, firstDetail, request, stockData.LockStockMap.GetValueOrDefault(stock.Id, new List<Dt_OutStockLockInfo>()), stockDetailMap, palletMaterielTotalStock); if (actualAllocatedQuantity > 0) if (actualAllocated.ActualAllocatedQuantity > 0) { allocatedPallets.Add(stock.PalletCode); palletAllocations[stock.PalletCode] = actualAllocatedQuantity; // è®°å½å®é åé é remainingQuantity -= actualAllocatedQuantity; palletAllocations[stock.PalletCode] = actualAllocated.ActualAllocatedQuantity; autoAllocateQuantity -= actualAllocated.ActualAllocatedQuantity; lockInfoList.AddRange(actualAllocated.LockInfoList); } } foreach (var palletCode in allocatedPallets) // çæèªå¨åé çä»»å¡ï¼è¿½å å°generatedTasksï¼ä¸ä¼éå¤ï¼ foreach (var palletCode in palletAllocations.Keys) { Dt_StockInfo stock = stockQuery.First(x => x.PalletCode == palletCode); // è·åå®é åé çæ°é decimal actualAllocatedQuantity = palletAllocations.GetValueOrDefault(palletCode, 0); // 计ç®åé åå©ä½çåºåæ°é decimal originalAvailableQuantity = availableStockMap.GetValueOrDefault(stock.Id, 0); decimal remainingStockQuantity = Math.Max(0, originalAvailableQuantity - actualAllocatedQuantity); decimal actualQty = palletAllocations[palletCode]; decimal originalAvailable = stockData.AvailableStockMap.GetValueOrDefault(stock.Id, 0); pickedDetails.Add(new PickedStockDetailDTO { PalletCode = palletCode, MaterielCode = materielCalc.MaterielCode, OutboundQuantity = actualAllocatedQuantity, // æ¬æ¬¡å®é åé çåºåºé RemainingQuantity = remainingStockQuantity, // åé åå©ä½çå¯ç¨åºå OutboundQuantity = actualQty, RemainingQuantity = Math.Max(0, originalAvailable - actualQty), LocationCode = stock.LocationCode, OutStockLockInfos = lockInfoList OutStockLockInfos = lockInfoList.Where(x => x.PalletCode == palletCode).ToList() }); Dt_OutStockLockInfo? outStockLockInfo = lockInfoList.FirstOrDefault(x => x.PalletCode == palletCode); int taskNum = outStockLockInfo?.TaskNum ?? Db.Ado.GetScalar($"SELECT NEXT VALUE FOR SeqTaskNum").ObjToInt(); int taskNum = lockInfoList.FirstOrDefault(x => x.PalletCode == palletCode)?.TaskNum ?? Db.Ado.GetScalar($"SELECT NEXT VALUE FOR SeqTaskNum").ObjToInt(); Dt_Task task = GenerationOutTask(stock, TaskTypeEnum.Outbound, taskNum, request.OutboundTargetLocation); if (generatedTasks.FirstOrDefault(x => x.PalletCode == stock.PalletCode) == null) generatedTasks.Add(task); // è¿æ»¤éå¤ä»»å¡ï¼æå®åºåçæçå·²çæï¼ä¸ä¼é夿·»å ï¼ if (generatedTasks.FirstOrDefault(x => x.PalletCode == palletCode) == null) generatedTasks.Add(task); } } // è¿åãæå®åºåä»»å¡+èªå¨åé ä»»å¡ãçåå¹¶å表 return (pickedDetails, generatedTasks, lockInfoList); } /// <summary> /// çæåºåºä»»å¡ /// åé æå®åºåæç»ï¼æ ¸å¿ä¼åï¼æ¥è¯¢æçç©ææ»åºåå¹¶ä¼ éï¼ /// </summary> /// <param name="stockInfo"></param> /// <param name="taskType"></param> /// <param name="outStation"></param> /// <returns></returns> private (decimal ActualAllocatedQuantity, List<PickedStockDetailDTO> PickedDetails, List<Dt_OutStockLockInfo> LockInfoList) AllocateSpecifiedStockDetails( Dt_OutboundOrder outboundOrder, MaterielOutboundCalculationDTO materielCalc, PickingOutboundRequestDTO request, string factoryArea, decimal needAllocateQuantity) { List<PickedStockDetailDTO> pickedDetails = new List<PickedStockDetailDTO>(); List<Dt_OutStockLockInfo> lockInfoList = new List<Dt_OutStockLockInfo>(); decimal actualAllocated = 0; List<Dt_StockInfoDetail> specifiedStockDetails = _stockDetailRepository.QueryData( x => request.StockDetailIds.Contains(x.Id) && x.MaterielCode == materielCalc.MaterielCode && x.StockQuantity > 0 && (x.Status == (int)StockStatusEmun.å ¥åºå®æ || x.Status == (int)StockStatusEmun.æå¨è§£é)); if (!specifiedStockDetails.Any()) { throw new Exception($"æå®åºåæç»ID [{string.Join(",", request.StockDetailIds)}] ä¸å卿ä¸å¯ç¨"); } List<int> stockIds = specifiedStockDetails.Select(x => x.StockId).Distinct().ToList(); List<Dt_StockInfo> specifiedStocks = _stockInfoRepository.QueryData(x => stockIds.Contains(x.Id)); Dictionary<int, Dt_StockInfo> stockMap = specifiedStocks.ToDictionary(x => x.Id); foreach (var stockDetail in specifiedStockDetails) { if (needAllocateQuantity <= 0) break; if (!stockMap.ContainsKey(stockDetail.StockId)) continue; Dt_StockInfo stock = stockMap[stockDetail.StockId]; decimal availableQty = stockDetail.StockQuantity; decimal allocateQty = Math.Min(needAllocateQuantity, availableQty); if (allocateQty <= 0) continue; // ===== æ ¸å¿ä¼å1ï¼æ¥è¯¢è¯¥æçä¸å½åç©æçæ»åºå ===== decimal palletMaterielTotalStock = _stockDetailRepository.QueryData( x => x.StockId == stock.Id && x.MaterielCode == materielCalc.MaterielCode ).Sum(x => x.StockQuantity); // 该æçè¯¥ç©æçæ»åºåï¼èéæ¬æ¬¡åé éï¼ var lockInfos = materielCalc.OutStockLockInfos .Where(x => x.StockId == stock.Id && x.MaterielCode == materielCalc.MaterielCode) .ToList(); // ===== ä¼ éæ»åºåå°AllocateStockQuantity ===== var allocateResult = AllocateStockQuantity( stock, allocateQty, availableQty, outboundOrder, materielCalc.Details.First(), request, lockInfos, new Dictionary<int, List<Dt_StockInfoDetail>> { { stock.Id, new List<Dt_StockInfoDetail> { stockDetail } } }, palletMaterielTotalStock // æ°å¢ï¼ä¼ å ¥æçç©ææ»åºå ); if (allocateResult.ActualAllocatedQuantity > 0) { pickedDetails.Add(new PickedStockDetailDTO { PalletCode = stock.PalletCode, MaterielCode = materielCalc.MaterielCode, OutboundQuantity = allocateResult.ActualAllocatedQuantity, RemainingQuantity = Math.Max(0, availableQty - allocateResult.ActualAllocatedQuantity), LocationCode = stock.LocationCode, OutStockLockInfos = allocateResult.LockInfoList }); actualAllocated += allocateResult.ActualAllocatedQuantity; needAllocateQuantity -= allocateResult.ActualAllocatedQuantity; lockInfoList.AddRange(allocateResult.LockInfoList); } } return (actualAllocated, pickedDetails, lockInfoList); } /// <summary> /// 为æå®åºåçæä»»å¡ï¼åæé»è¾ä¸åï¼ /// </summary> private List<Dt_Task> GenerateTasksForSpecifiedStock(List<PickedStockDetailDTO> pickedDetails, string outboundTargetLocation) { List<Dt_Task> tasks = new List<Dt_Task>(); var palletCodes = pickedDetails.Select(x => x.PalletCode).Distinct().ToList(); foreach (var palletCode in palletCodes) { Dt_StockInfo stock = _stockInfoRepository.QueryFirst(x => x.PalletCode == palletCode); if (stock == null) continue; int taskNum = pickedDetails.First(x => x.PalletCode == palletCode) .OutStockLockInfos.FirstOrDefault()?.TaskNum ?? Db.Ado.GetScalar($"SELECT NEXT VALUE FOR SeqTaskNum").ObjToInt(); Dt_Task task = GenerationOutTask(stock, TaskTypeEnum.Outbound, taskNum, outboundTargetLocation); if (tasks.FirstOrDefault(x => x.PalletCode == palletCode) == null) tasks.Add(task); } return tasks; } /// <summary> /// æå»ºåºåæ¥è¯¢æ¡ä»¶ï¼åæé»è¾ä¸åï¼ /// </summary> private List<Dt_StockInfo> BuildStockQueryWithInfo(MaterielOutboundCalculationDTO materielCalc, string factoryArea) { ISugarQueryable<Dt_StockInfoDetail> stockDetails = _stockDetailRepository.Db.Queryable<Dt_StockInfoDetail>() .Where(x => x.MaterielCode == materielCalc.MaterielCode && x.StockQuantity > 0 && (x.Status == (int)StockStatusEmun.å ¥åºå®æ || x.Status == (int)StockStatusEmun.æå¨è§£é)); if (!string.IsNullOrEmpty(materielCalc.SupplyCode)) stockDetails = stockDetails.Where(x => x.SupplyCode == materielCalc.SupplyCode); if (!string.IsNullOrEmpty(materielCalc.WarehouseCode)) stockDetails = stockDetails.Where(x => x.WarehouseCode == materielCalc.WarehouseCode); if (!string.IsNullOrEmpty(factoryArea)) stockDetails = stockDetails.Where(x => x.FactoryArea == factoryArea); if (!string.IsNullOrEmpty(materielCalc.BatchNo)) stockDetails = stockDetails.Where(x => x.BatchNo == materielCalc.BatchNo); List<Dt_StockInfoDetail> stockDetailList = stockDetails.ToList(); List<string> locationCodes = _locationInfoRepository.QueryData(x => (x.LocationStatus == LocationStatusEnum.InStock.ObjToInt() || x.LocationStatus == LocationStatusEnum.Lock.ObjToInt()) && x.EnableStatus == EnableStatusEnum.Normal.ObjToInt()).Select(x => x.LocationCode).ToList(); List<int> stockIds = stockDetailList.GroupBy(x => x.StockId).Select(x => x.Key).ToList(); List<Dt_StockInfo> stockInfos = _stockInfoRepository.QueryData(x => stockIds.Contains(x.Id) && (x.StockStatus == StockStatusEmun.å ¥åºå®æ.ObjToInt() || x.StockStatus == StockStatusEmun.åºåºéå®.ObjToInt()) && !string.IsNullOrEmpty(x.LocationCode) && locationCodes.Contains(x.LocationCode)); foreach (var stockInfo in stockInfos) { stockInfo.Details = stockDetailList.Where(x => x.StockId == stockInfo.Id).ToList(); } return stockInfos; } /// <summary> /// æ¹éè·åæçå¯ç¨åºåä¿¡æ¯ï¼åæé»è¾ä¸åï¼ /// </summary> private (Dictionary<int, decimal> AvailableStockMap, Dictionary<int, List<Dt_OutStockLockInfo>> LockStockMap) GetBatchAvailableStockQuantities( MaterielOutboundCalculationDTO materielCalc, List<Dt_StockInfo> stockInfos) { List<int> stockIds = stockInfos.Select(x => x.Id).ToList(); Dictionary<int, decimal> availableStockMap = new Dictionary<int, decimal>(); Dictionary<int, List<Dt_OutStockLockInfo>> lockStockMap = new Dictionary<int, List<Dt_OutStockLockInfo>>(); List<Dt_OutStockLockInfo> allocatedData = materielCalc.OutStockLockInfos .Where(x => stockIds.Contains(x.StockId) && x.MaterielCode == materielCalc.MaterielCode).ToList(); foreach (var stockInfo in stockInfos) { decimal totalQuantity = stockInfo.Details.Sum(x => x.StockQuantity); List<Dt_OutStockLockInfo> outStockLockInfos = allocatedData .Where(x => x.StockId == stockInfo.Id && x.MaterielCode == materielCalc.MaterielCode).ToList(); decimal allocatedQuantity = outStockLockInfos.Sum(x => x.AllocatedQuantity); availableStockMap[stockInfo.Id] = Math.Max(0, totalQuantity - allocatedQuantity); lockStockMap[stockInfo.Id] = outStockLockInfos; } return (availableStockMap, lockStockMap); } /// <summary> /// åé åºåï¼æ ¸å¿ä¼åï¼OriginalQuantityèµå¼ä¸ºæçç©ææ»åºåï¼ /// </summary> private (decimal ActualAllocatedQuantity, List<Dt_OutStockLockInfo> LockInfoList) AllocateStockQuantity( Dt_StockInfo stockInfo, decimal allocateQuantity, decimal availableQuantity, Dt_OutboundOrder outboundOrder, Dt_OutboundOrderDetail detail, PickingOutboundRequestDTO request, List<Dt_OutStockLockInfo> lockInfos, Dictionary<int, List<Dt_StockInfoDetail>> stockDetailMap = null, decimal palletMaterielTotalStock = 0 // æ°å¢ï¼æçç©ææ»åºååæ° ) { decimal actualAllocatedQuantity = Math.Min(allocateQuantity, availableQuantity); List<Dt_OutStockLockInfo> lockInfoList = new List<Dt_OutStockLockInfo>(); if (actualAllocatedQuantity > 0) { // æ£æ¥ç®æ ä½ç½®ä¸è´æ§ if (lockInfos.Any() && !string.IsNullOrEmpty(lockInfos.First().OutboundTargetLocation) && !string.Equals(lockInfos.First().OutboundTargetLocation, request.OutboundTargetLocation, StringComparison.OrdinalIgnoreCase)) { return (0, lockInfoList); } Dt_OutStockLockInfo? lockInfo = lockInfos.FirstOrDefault(x => x.StockId == stockInfo.Id && x.Status == OutLockStockStatusEnum.å·²åé .ObjToInt() && x.PalletCode == stockInfo.PalletCode && x.OrderNo == outboundOrder.OrderNo); if (lockInfo != null) { List<string> currentIds = lockInfo.OrderDetailIds?.Split(',').ToList() ?? new List<string>(); if (!currentIds.Contains(detail.Id.ToString())) { currentIds.Add(detail.Id.ToString()); lockInfo.OrderDetailIds = string.Join(",", currentIds); } decimal totalAllocatedQuantity = CalcTotalAllocatedQuantity(lockInfos, stockInfo.Id, detail.MaterielCode); lockInfo.AssignQuantity += actualAllocatedQuantity; lockInfo.AllocatedQuantity = totalAllocatedQuantity; // åééå®è®°å½ä¹æ´æ°OriginalQuantity为æçæ»åºåï¼å¯éï¼ä¿ææ°æ®ä¸è´ï¼ if (palletMaterielTotalStock > 0) lockInfo.OriginalQuantity = palletMaterielTotalStock; lockInfoList.Add(lockInfo); } else { // ===== æ ¸å¿ä¼å2ï¼OriginalQuantityèµå¼ä¸ºæçç©ææ»åºå ===== decimal originalQuantity = palletMaterielTotalStock; // æ¿ä»£åæå±é¨æç»æ°é List<string> allDetailIds = outboundOrder.Details.Where(x => x.OrderId == outboundOrder.Id && x.MaterielCode == detail.MaterielCode && x.BatchNo == detail.BatchNo && x.SupplyCode == detail.SupplyCode && x.WarehouseCode == detail.WarehouseCode) .Select(x => x.Id.ToString()).ToList(); decimal totalAllocatedQuantity = CalcTotalAllocatedQuantity(lockInfos, stockInfo.Id, detail.MaterielCode); lockInfo = new Dt_OutStockLockInfo { OrderNo = request.OrderNo, OrderDetailIds = string.Join(",", allDetailIds), OrderType = outboundOrder.OrderType, BatchNo = detail.BatchNo, MaterielCode = detail.MaterielCode, MaterielName = detail.MaterielName, StockId = stockInfo.Id, OrderQuantity = allDetailIds.Count > 1 ? outboundOrder.Details.Where(x => x.OrderId == outboundOrder.Id && x.MaterielCode == detail.MaterielCode && x.BatchNo == detail.BatchNo && x.SupplyCode == detail.SupplyCode && x.WarehouseCode == detail.WarehouseCode).Sum(x => x.OrderQuantity) : detail.OrderQuantity, OriginalQuantity = originalQuantity, // ç°å¨èµå¼ä¸ºæçç©ææ»åºå AssignQuantity = actualAllocatedQuantity, AllocatedQuantity = totalAllocatedQuantity, LocationCode = stockInfo.LocationCode, PalletCode = stockInfo.PalletCode, Unit = detail.Unit, OutboundTargetLocation = request.OutboundTargetLocation, Status = OutLockStockStatusEnum.å·²åé .ObjToInt(), SupplyCode = detail.SupplyCode, WarehouseCode = detail.WarehouseCode, FactoryArea = outboundOrder.FactoryArea, TaskNum = Db.Ado.GetScalar($"SELECT NEXT VALUE FOR SeqTaskNum").ObjToInt(), OrderDetailId = 0 }; lockInfoList.Add(lockInfo); } } return (actualAllocatedQuantity, lockInfoList); } /// <summary> /// 计ç®è¯¥æç累计已åé æ°éï¼åæé»è¾ä¸åï¼ /// </summary> private decimal CalcTotalAllocatedQuantity(List<Dt_OutStockLockInfo> lockInfos, int stockId, string materielCode) { List<Dt_OutStockLockInfo> lockRecords = _outboundLockInfoRepository.QueryData(x => x.StockId == stockId && x.MaterielCode == materielCode); return lockRecords?.Sum(x => x.AssignQuantity) ?? 0; } /// <summary> /// çæåºåºä»»å¡ï¼åæé»è¾ä¸åï¼ /// </summary> public Dt_Task GenerationOutTask(Dt_StockInfo stockInfo, TaskTypeEnum taskType, int taskNum, string outStation) { Dt_Task task = new() return new Dt_Task { CurrentAddress = stockInfo.LocationCode, Grade = 0, @@ -538,240 +755,13 @@ PalletType = stockInfo.PalletType, WarehouseId = stockInfo.WarehouseId, }; return task; } /// <summary> /// æå»ºåºåæ¥è¯¢æ¡ä»¶ï¼å å«åºåä¿¡æ¯ååºåæç»ï¼ /// </summary> /// <param name="materielCalc"></param> /// <param name="factoryArea"></param> /// <returns></returns> private List<Dt_StockInfo> BuildStockQueryWithInfo(MaterielOutboundCalculationDTO materielCalc, string factoryArea) { // åºç¡æ¥è¯¢æ¡ä»¶ï¼ç©æç¼å·ãæ¹æ¬¡å·ï¼å¦ææä¾ï¼ãåºåæ°é>0 ISugarQueryable<Dt_StockInfoDetail> stockDetails = _stockDetailRepository.Db.Queryable<Dt_StockInfoDetail>().Where(x => x.MaterielCode == materielCalc.MaterielCode && x.StockQuantity > 0 && (x.Status == (int)StockStatusEmun.å ¥åºå®æ || x.Status == (int)StockStatusEmun.æå¨è§£é)); // æ ¹æ®æ¡ä»¶æ·»å ä¾åºåç¼å·å¹é ï¼ä¸ä¸ºç©ºæ¶æéè¦å¹é ï¼ if (!string.IsNullOrEmpty(materielCalc.SupplyCode)) { stockDetails = stockDetails.Where(x => x.SupplyCode == materielCalc.SupplyCode); } // æ ¹æ®æ¡ä»¶æ·»å ä»åºç¼å·å¹é ï¼ä¸ä¸ºç©ºæ¶æéè¦å¹é ï¼ if (!string.IsNullOrEmpty(materielCalc.WarehouseCode)) { stockDetails = stockDetails.Where(x => x.WarehouseCode == materielCalc.WarehouseCode); } // æ ¹æ®æ¡ä»¶æ·»å ååºå¹é ï¼ä¸ä¸ºç©ºæ¶æéè¦å¹é ï¼ if (!string.IsNullOrEmpty(factoryArea)) { stockDetails = stockDetails.Where(x => x.FactoryArea == factoryArea); } // æ ¹æ®æ¹æ¬¡å·è¿è¡è¿æ»¤ï¼å¦ææä¾ï¼ if (!string.IsNullOrEmpty(materielCalc.BatchNo)) { stockDetails = stockDetails.Where(x => x.BatchNo == materielCalc.BatchNo); } List<Dt_StockInfoDetail> stockDetailList = stockDetails.ToList(); // è·åå¯ç¨è´§ä½ç¼å· List<string> locationCodes = _locationInfoRepository.QueryData(x => (x.LocationStatus == LocationStatusEnum.InStock.ObjToInt() /*|| x.LocationStatus == LocationStatusEnum.Lock.ObjToInt()*/) && x.EnableStatus == EnableStatusEnum.Normal.ObjToInt()).Select(x => x.LocationCode).ToList(); // è·åææç¸å ³çåºåä¿¡æ¯ List<int> stockIds = stockDetailList.GroupBy(x => x.StockId).Select(x => x.Key).ToList(); List<Dt_StockInfo> stockInfos = _stockInfoRepository.QueryData(x => stockIds.Contains(x.Id) && (x.StockStatus == StockStatusEmun.å ¥åºå®æ.ObjToInt() /*|| x.StockStatus == StockStatusEmun.åºåºéå®.ObjToInt()*/) && !string.IsNullOrEmpty(x.LocationCode) && locationCodes.Contains(x.LocationCode)); // å¨å åä¸å ³èæ°æ® foreach (var stockInfo in stockInfos) { stockInfo.Details = new List<Dt_StockInfoDetail>(); stockInfo.Details = stockDetailList.Where(x => x.StockId == stockInfo.Id).ToList(); } return stockInfos; } /// <summary> /// æ¹éè·åæçå¯ç¨åºåä¿¡æ¯ /// </summary> /// <param name="stockInfos">åºåä¿¡æ¯å表</param> /// <param name="materielCode">ç©æç¼å·</param> /// <returns>è¿åå¼ä¸º(åºå主é®ï¼å¯ç¨æ°é)åå ¸</returns> private (Dictionary<int, decimal> AvailableStockMap, Dictionary<int, List<Dt_OutStockLockInfo>> LockStockMap) GetBatchAvailableStockQuantities(MaterielOutboundCalculationDTO materielCalc, List<Dt_StockInfo> stockInfos) { List<int> stockIds = stockInfos.Select(x => x.Id).ToList(); Dictionary<int, decimal> availableStockMap = new Dictionary<int, decimal>(); // å¯ç¨åºåæ°é Dictionary<int, List<Dt_OutStockLockInfo>> lockStockMap = new Dictionary<int, List<Dt_OutStockLockInfo>>(); // å·²éå®åºåæ°é // æ¹éæ¥è¯¢å·²åé æ°é List<Dt_OutStockLockInfo> allocatedData = materielCalc.OutStockLockInfos.Where(x => stockIds.Contains(x.StockId) && x.MaterielCode == materielCalc.MaterielCode).ToList(); foreach (var stockInfo in stockInfos) { // è®¡ç®æ»åºåæ°é decimal totalQuantity = stockInfo.Details.Sum(x => x.StockQuantity); List<Dt_OutStockLockInfo> outStockLockInfos = allocatedData.Where(x => x.StockId == stockInfo.Id && x.MaterielCode == materielCalc.MaterielCode).ToList(); // 计ç®å·²åé æ°é decimal allocatedQuantity = outStockLockInfos.Sum(x => x.AllocatedQuantity); availableStockMap[stockInfo.Id] = Math.Max(0, totalQuantity - allocatedQuantity); lockStockMap[stockInfo.Id] = outStockLockInfos; } return (availableStockMap, lockStockMap); } /// <summary> /// åé åºå /// </summary> /// <param name="stockInfo">åºåä¿¡æ¯</param> /// <param name="allocateQuantity">è¦åé çæ°é</param> /// <param name="availableQuantity">å¯åé çæ°é</param> /// <param name="outboundOrder">åºåºå</param> /// <param name="detail">åºåºåæç»</param> /// <param name="request"></param> /// <param name="lockInfos"></param> /// <param name="stockDetailMap"></param> /// <returns></returns> private (decimal ActualAllocatedQuantity, List<Dt_OutStockLockInfo> LockInfoList) AllocateStockQuantity(Dt_StockInfo stockInfo, decimal allocateQuantity, decimal availableQuantity, Dt_OutboundOrder outboundOrder, Dt_OutboundOrderDetail detail, PickingOutboundRequestDTO request, List<Dt_OutStockLockInfo> lockInfos, Dictionary<int, List<Dt_StockInfoDetail>> stockDetailMap = null) { decimal actualAllocatedQuantity = Math.Min(allocateQuantity, availableQuantity); // å®é åé æ°é List<Dt_OutStockLockInfo> lockInfoList = new List<Dt_OutStockLockInfo>(); if (actualAllocatedQuantity > 0) { //æ£æ¥ç®æ ä½ç½®ä¸è´æ§ï¼å¦ææçå·²æéå®è®°å½ä¸ç®æ ä½ç½®ä¸åï¼åä¸å 许åé if (lockInfos.Any() && !string.IsNullOrEmpty(lockInfos.First().OutboundTargetLocation)) { if (!string.Equals(lockInfos.First().OutboundTargetLocation, request.OutboundTargetLocation, StringComparison.OrdinalIgnoreCase)) { // æççç®æ ä½ç½®ä¸æ°è¯·æ±çç®æ ä½ç½®ä¸åï¼ä¸å 许使ç¨è¯¥æç return (0, lockInfoList); } } Dt_OutStockLockInfo? lockInfo = lockInfos.FirstOrDefault(x => x.StockId == stockInfo.Id && x.Status == OutLockStockStatusEnum.å·²åé .ObjToInt() && x.PalletCode == stockInfo.PalletCode && x.OrderNo == outboundOrder.OrderNo); if (lockInfo != null) { // 追å å½åæç»IDå°OrderDetailIdsåæ®µï¼é¿å éå¤ï¼ List<string> currentIds = lockInfo.OrderDetailIds?.Split(',').ToList() ?? new List<string>(); if (!currentIds.Contains(detail.Id.ToString())) { currentIds.Add(detail.Id.ToString()); lockInfo.OrderDetailIds = string.Join(",", currentIds); } // 计ç®è¯¥æçè¯¥ç©æçæ»ç´¯è®¡å·²åºåºæ°éï¼è·¨ææåæ®ï¼ decimal totalAllocatedQuantity = CalcTotalAllocatedQuantity(lockInfos, stockInfo.Id, detail.MaterielCode); // æ´æ°åé åºåºé decimal beforeAssignQuantity = totalAllocatedQuantity; // æ¬æ¬¡åé åçæ»ç´¯è®¡é lockInfo.AssignQuantity += actualAllocatedQuantity; // æ¬æ¬¡åé æ°é lockInfo.AllocatedQuantity = beforeAssignQuantity; // è®°å½æ¬æ¬¡åé åçæ»ç´¯è®¡é lockInfoList.Add(lockInfo); } else { // å建æ°çéå®è®°å½ï¼ä½¿ç¨é¢å è½½çåºåæç»ï¼ decimal originalQuantity = 0; if (stockDetailMap?.ContainsKey(stockInfo.Id) == true) { originalQuantity = stockDetailMap[stockInfo.Id].Sum(x => x.StockQuantity); } // è·åè¯¥ç©æå¨è¯¥è®¢åä¸çæææç»ID List<string> allDetailIds = (outboundOrder.Details.Where(x => x.OrderId == outboundOrder.Id && x.MaterielCode == detail.MaterielCode && x.BatchNo == detail.BatchNo && x.SupplyCode == detail.SupplyCode && x.WarehouseCode == detail.WarehouseCode)) .Select(x => x.Id.ToString()) .ToList(); // 计ç®è¯¥æçè¯¥ç©æçæ»ç´¯è®¡å·²åºåºæ°éï¼è·¨ææåæ®ï¼ decimal totalAllocatedQuantity = CalcTotalAllocatedQuantity(lockInfos, stockInfo.Id, detail.MaterielCode); lockInfo = new Dt_OutStockLockInfo { OrderNo = request.OrderNo, OrderDetailIds = string.Join(",", allDetailIds), // è®°å½è¯¥ç©æçæææç»ID OrderType = outboundOrder.OrderType, BatchNo = detail.BatchNo, MaterielCode = detail.MaterielCode, MaterielName = detail.MaterielName, StockId = stockInfo.Id, OrderQuantity = allDetailIds.SelectMany(id => allDetailIds).Count() > 1 ? (outboundOrder.Details.Where(x => x.OrderId == outboundOrder.Id && x.MaterielCode == detail.MaterielCode && x.BatchNo == detail.BatchNo && x.SupplyCode == detail.SupplyCode && x.WarehouseCode == detail.WarehouseCode)) .Sum(x => x.OrderQuantity) : detail.OrderQuantity, // å¦æåªæä¸ä¸ªæç»ï¼ä½¿ç¨æç»æ°é OriginalQuantity = originalQuantity, AssignQuantity = actualAllocatedQuantity, // æ¬æ¬¡åé æ°é AllocatedQuantity = totalAllocatedQuantity, // æ¬æ¬¡åé åçæ»ç´¯è®¡å·²åºåºæ°éï¼è·¨ææåæ®ï¼ LocationCode = stockInfo.LocationCode, PalletCode = stockInfo.PalletCode, Unit = detail.Unit, OutboundTargetLocation = request.OutboundTargetLocation, Status = OutLockStockStatusEnum.å·²åé .ObjToInt(), SupplyCode = detail.SupplyCode, WarehouseCode = detail.WarehouseCode, FactoryArea = outboundOrder.FactoryArea, TaskNum = Db.Ado.GetScalar($"SELECT NEXT VALUE FOR SeqTaskNum").ObjToInt(), OrderDetailId = 0 // æªå ³èå ·ä½æç»ID }; lockInfoList.Add(lockInfo); } } return (actualAllocatedQuantity, lockInfoList); } /// <summary> /// 计ç®è¯¥æç累计已åé æ°é /// </summary> /// <param name="lockInfos"></param> /// <param name="stockId"></param> /// <param name="materielCode"></param> /// <returns></returns> private decimal CalcTotalAllocatedQuantity(List<Dt_OutStockLockInfo> lockInfos, int stockId, string materielCode) { // æ¥è¯¢è¯¥æçè¯¥ç©æå¨ææéå®è®°å½ä¸çæå¤§å·²åé æ°é List<Dt_OutStockLockInfo> lockRecords = _outboundLockInfoRepository.QueryData(x => x.StockId == stockId && x.MaterielCode == materielCode); if (lockRecords == null || !lockRecords.Any()) { return 0; } // è¿å累计已åé æ°é return lockRecords.Sum(x => x.AssignQuantity); } /// <summary> /// æ´æ°åºåºåç¶æ /// </summary> public bool UpdateOutboundOrderStatus(string orderNo, int status) { try { Dt_OutboundOrder outboundOrder = _outboundRepository.QueryFirst(x => x.OrderNo == orderNo); if (outboundOrder == null) return false; outboundOrder.OrderStatus = status; _outboundRepository.UpdateData(outboundOrder); return true; @@ -782,22 +772,12 @@ } } /// <summary> /// /// </summary> /// <param name="palletCodes"></param> /// <param name="status"></param> /// <returns></returns> public bool UpdateStockStatus(List<string> palletCodes, int status) { try { List<Dt_StockInfo> stockInfos = _stockInfoRepository.QueryData(x => palletCodes.Contains(x.PalletCode)); stockInfos.ForEach(stockInfo => { stockInfo.StockStatus = status; }); stockInfos.ForEach(stockInfo => stockInfo.StockStatus = status); _stockInfoRepository.UpdateData(stockInfos); return true; } @@ -807,22 +787,12 @@ } } /// <summary> /// /// </summary> /// <param name="locationCodes"></param> /// <param name="status"></param> /// <returns></returns> public bool UpdateLocationStatus(List<string> locationCodes, int status) { try { List<Dt_LocationInfo> locationInfos = _locationInfoRepository.QueryData(x => locationCodes.Contains(x.LocationCode)); locationInfos.ForEach(x => { x.LocationStatus = status; }); locationInfos.ForEach(x => x.LocationStatus = status); _locationInfoRepository.UpdateData(locationInfos); return true; } @@ -832,21 +802,14 @@ } } /// <summary> /// /// </summary> /// <param name="outStockLockInfos"></param> /// <returns></returns> public bool UpdateOutStockLockInfo(List<Dt_OutStockLockInfo> outStockLockInfos) { try { List<Dt_OutStockLockInfo> updateData = outStockLockInfos.Where(x => x.Id > 0).ToList(); _outboundLockInfoRepository.UpdateData(updateData); List<Dt_OutStockLockInfo> addData = outStockLockInfos.Where(x => x.Id <= 0).ToList(); _outboundLockInfoRepository.AddData(addData); return true; } catch ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_StockService/StockInfoService.cs
@@ -523,24 +523,25 @@ if (relevantDetails.Any()) { var firstDetail = relevantDetails.First(); var useableQuantity = relevantDetails.Sum(d => d.StockQuantity - d.OutboundQuantity); foreach (var item in relevantDetails) { result.Add(new StockSelectViewDTO { LocationCode = stock.LocationCode, MaterielCode = firstDetail.MaterielCode, MaterielName = firstDetail.MaterielName, BatchNo = orderDetail.BatchNo, SupplyCode = orderDetail.SupplyCode, Barcode = firstDetail.Barcode, MaterielCode = item.MaterielCode, MaterielName = item.MaterielName, BatchNo = item.BatchNo, SupplyCode = item.SupplyCode, Barcode = item.Barcode, PalletCode = stock.PalletCode, UseableQuantity = useableQuantity, UseableQuantity = item.StockQuantity, StockCreateDate = stock.CreateDate, StockId = stock.Id, StockId = item.Id, OrderDetailId = orderDetail.Id // å ³èå°å ·ä½çåºåºåæç» }); } } } } ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Allocate/AllocateOrderController.cs
@@ -92,6 +92,10 @@ ValidDate = barcodeDto.validDate, BoxSN = barcodeDto.BoxSN }; if (businessType == BusinessTypeEnum.æºä»è°å¤é¨ä»åº || businessType == BusinessTypeEnum.æºä»è°æºä») { orderDetail.WarehouseCode = model.fromWarehouse; } allocateOrder.Details.Add(orderDetail); } } @@ -108,6 +112,10 @@ BarcodeQty=detailDto.Qty, MaterielName = materialName }; if (businessType == BusinessTypeEnum.æºä»è°å¤é¨ä»åº || businessType == BusinessTypeEnum.æºä»è°æºä») { orderDetail.WarehouseCode = model.fromWarehouse; } allocateOrder.Details.Add(orderDetail); } allocateOrder.Details.AddRange(allocateOrder.Details); ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Inbound/InboundController.cs
@@ -41,6 +41,17 @@ } /// <summary> /// çç¹ç»ç /// </summary> /// <param name="palletDto"></param> /// <returns></returns> [HttpPost, Route("StockTakeGroupPallet"), AllowAnonymous] public async Task<WebResponseContent> StockTakeGroupPallet([FromBody] GroupPalletDto palletDto) { return await Service.StockTakeGroupPallet(palletDto); } /// <summary> /// å ¥åºåæ¹åä¼ MES /// </summary> /// <param name="palletDto"></param> ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Inbound/TakeStockOrderController.cs
@@ -76,9 +76,18 @@ /// æåææ¶åå¤ç /// </summary> [HttpPost, HttpGet, Route("DocumentReconciliation"), AllowAnonymous] public WebResponseContent DocumentReconciliation(int orderId,int id) public WebResponseContent DocumentReconciliation(string barcode) { return Service.DocumentReconciliation(orderId, id); return Service.DocumentReconciliation(barcode); } /// <summary> /// çç¹ç»ç /// </summary> [HttpPost, HttpGet, Route("StockTakeGroupPallet"), AllowAnonymous] public WebResponseContent StockTakeGroupPallet(string barcode, string boxNo) { return Service.StockTakeGroupPallet(barcode,boxNo); } } }