ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/views/outbound/PickingConfirm.vue
@@ -1,5 +1,5 @@ <template> <div class="picking-confirm"> <div class="OutboundPicking-container"> <div class="page-header"> <el-page-header @back="goBack"> <template #content> @@ -7,90 +7,288 @@ </template> </el-page-header> </div> <!-- æ«ç åºå --> <div class="scanner-area"> <el-card> <div class="scanner-form"> <el-input ref="palletInput" v-model="scanData.palletCode" placeholder="æ«ææçç " @change="onPalletScan" @keyup.enter.native="onPalletScan"> </el-input> <el-input ref="barcodeInput" v-model="scanData.barcode" placeholder="æ«æç©ææ¡ç " @change="onBarcodeScan" @keyup.enter.native="onBarcodeScan"> </el-input> <el-button type="success" @click="confirmPicking">确认æ£é</el-button> <el-button type="warning" @click="openSplitDialog">æå </el-button> <el-button type="info" @click="openRevertSplitDialog">æ¤éæå </el-button> <el-button type="primary" @click="openBatchReturnDialog">ååº</el-button> <el-button type="danger" @click="handleDirectOutbound">ç´æ¥åºåº</el-button> </div> </el-card> </div> <!-- æ±æ»ä¿¡æ¯ --> <div class="summary-area"> <el-card> <div class="summary-info"> <el-tag type="warning">æªæ£éæ¡æ°: {{summary.unpickedCount}}</el-tag> <el-tag type="danger">æªæ£éæ°é: {{summary.unpickedQuantity}}</el-tag> <el-tag type="success">å·²æ£éæ¡æ°: {{summary.pickedCount}}</el-tag> <el-tag type="info">æçç¶æ: {{palletStatus}}</el-tag> </div> </el-card> </div> <!-- æ°æ®å表 --> <div class="content-area"> <el-row :gutter="20"> <el-col :span="12"> <el-card header="æªæ£éå表"> <el-table :data="unpickedList" border height="440"> <el-table-column prop="materielCode" label="ç©æç¼ç " width="120"></el-table-column> <div class="content-layout"> <!-- å·¦ä¾§ï¼æ«ç åºå --> <div class="left-section"> <div class="scan-section"> <el-alert title="è¯·ä½¿ç¨æ«ç æªæ«ææçç åç©ææ¡ç ï¼æ«ç æªå¸¦å车åè½ï¼æ«å®ç©ææ¡ç èªå¨ç¡®è®¤" type="info" :closable="false" class="scan-alert" /> <el-table-column prop="assignQuantity" label="åé æ°é" width="100"></el-table-column> <el-table-column prop="remainQuantity" label="å©ä½æ°é" width="100"></el-table-column> <el-table-column prop="locationCode" label="è´§ä½" width="100"></el-table-column> <el-table-column prop="currentBarcode" label="æ¡ç "></el-table-column> <!-- <el-table-column label="æä½" width="100"> <template slot-scope="scope"> <el-button size="mini" type="primary" @click="handleSingleReturn(scope.row)"> ååº </el-button> </template> </el-table-column> --> </el-table> </el-card> </el-col> <el-col :span="12"> <el-card header="å·²æ£éå表"> <div class="table-actions"> <el-button size="mini" type="danger" :disabled="selectedPickedRows.length === 0" @click="batchCancelSelected"> åæ¶æ£é </el-button> <span class="selection-count">已鿩 {{selectedPickedRows.length}} 项</span> </div> <el-table :data="pickedList" border height="400" style="width: 100%" @selection-change="handlePickedSelectionChange"> <el-table-column type="selection" width="55"></el-table-column> <el-table-column prop="materielCode" label="ç©æç¼ç " width="120"></el-table-column> <el-table-column prop="pickedQty" label="å·²æ£æ°é" width="100"></el-table-column> <el-table-column prop="locationCode" label="è´§ä½" width="100"></el-table-column> <el-table-column prop="currentBarcode" label="æ¡ç "></el-table-column> <el-form :model="scanForm" label-width="100px" class="scan-form"> <el-form-item label="æçç " required> <el-input ref="palletInput" v-model="scanForm.palletCode" placeholder="è¯·æ«ææçç " @keyup.enter="handlePalletScan" @blur="loadPalletSummary" clearable /> </el-form-item> </el-table> </el-card> </el-col> </el-row> </div> <el-form-item label="ç©ææ¡ç " required> <el-input ref="materialInput" v-model="scanForm.materialBarcode" placeholder="è¯·æ«æç©ææ¡ç " :disabled="!scanForm.palletCode" @keyup.enter="handleMaterialScan" clearable /> </el-form-item> </el-form> <!-- æå å¼¹çª --> <!-- æå å¼¹çª --> <div v-if="showCustomSplitDialog" class="custom-dialog-overlay"> <div class="custom-dialog-wrapper"> <div class="custom-dialog"> <div class="custom-dialog-header"> <h3>æå æä½</h3> <!-- <el-button type="text" icon="el-icon-close" @click="closeCustomSplitDialog" class="close-button"> </el-button> --> <el-button type="text" @click="closeCustomSplitDialog" class="close-button"> X </el-button> <!-- æçæ£è´§ç»è®¡ --> <div v-if="palletSummary" class="pallet-summary"> <el-card header="æçæ£è´§ç»è®¡"> <el-descriptions :column="3" border> <el-descriptions-item label="æçå·"> {{ scanForm.palletCode }} </el-descriptions-item> <el-descriptions-item label="æªæ£è´§æ¡æ°"> <el-text type="warning">{{ palletSummary.unpickedCount }}</el-text> </el-descriptions-item> <el-descriptions-item label="æªæ£è´§æ»æ°"> <el-text type="danger">{{ palletSummary.unpickedTotal }}</el-text> </el-descriptions-item> </el-descriptions> </el-card> </div> <div class="action-buttons"> <el-button type="primary" @click="handleConfirm" :loading="confirmLoading"> æå¨ç¡®è®¤ </el-button> <el-button @click="handleReset">éç½®</el-button> <el-button @click="$emit('close')">åæ¶</el-button> <div class="custom-dialog-body"> <el-form :model="splitForm" :rules="splitFormRules" ref="splitFormRef" label-width="100px"> <el-form-item label="订åç¼å·"> <el-input v-model="splitForm.orderNo" disabled></el-input> </el-form-item> <el-form-item label="æçç¼å·"> <el-input v-model="splitForm.palletCode" disabled></el-input> </el-form-item> <el-form-item label="åæ¡ç " prop="originalBarcode"> <el-input v-model="splitForm.originalBarcode" placeholder="æ«æåæ¡ç " @keyup.enter.native="onSplitBarcodeScan" @change="onSplitBarcodeScan" clearable> </el-input> </el-form-item> <el-form-item label="ç©æç¼ç "> <el-input v-model="splitForm.materielCode" disabled></el-input> </el-form-item> <el-form-item label="å©ä½æ°é"> <el-input v-model="splitForm.maxQuantity" disabled></el-input> </el-form-item> <el-form-item label="æå æ°é" prop="splitQuantity"> <el-input-number v-model="splitForm.splitQuantity" :min="1" :max="splitForm.maxQuantity" :precision="2" :step="1" style="width: 100%"> </el-input-number> </el-form-item> </el-form> </div> <div class="custom-dialog-footer"> <el-button @click="closeCustomSplitDialog">åæ¶</el-button> <el-button type="primary" @click="handleSplitPackage" :loading="splitLoading">确认æå </el-button> </div> </div> </div> </div> <!-- å³ä¾§ï¼åºåºè¯¦æ å表 --> <div class="right-section"> <el-card class="outbound-details-card" header="åºåºè¯¦æ "> <vol-table ref="outboundTable" :table-config="outboundTableConfig" :height="300" /> </el-card> <!-- æ¤éæå å¼¹çª --> <div v-if="showRevertSplitDialog" class="custom-dialog-overlay"> <div class="custom-dialog-wrapper"> <div class="custom-dialog"> <div class="custom-dialog-header"> <h3>æ¤éæå </h3> <el-button type="text" @click="closeRevertSplitDialog" class="close-button"> à </el-button> </div> <div class="custom-dialog-body"> <el-form :model="revertSplitForm" :rules="revertSplitFormRules" ref="revertSplitFormRef" label-width="100px"> <el-form-item label="åæ¡ç " prop="originalBarcode"> <el-input v-model="revertSplitForm.originalBarcode" placeholder="æ«æåæ¡ç " @keyup.enter.native="onRevertSplitBarcodeScan" @change="onRevertSplitBarcodeScan" clearable> </el-input> </el-form-item> </el-form> </div> <div class="custom-dialog-footer"> <el-button @click="closeRevertSplitDialog">åæ¶</el-button> <el-button type="primary" @click="handleRevertSplit" :loading="revertSplitLoading">确认æ¤é</el-button> </div> </div> </div> </div> <!-- å·²åæ£è®°å½å表 --> <div class="picked-records"> <el-card header="å·²åæ£è®°å½"> <vol-table ref="pickedTable" :table-config="pickedTableConfig" :height="300" /> </el-card> <!-- æ¹éååºå¼¹çª --> <div v-if="showBatchReturnDialog" class="custom-dialog-overlay"> <div class="custom-dialog-wrapper"> <div class="custom-dialog"> <div class="custom-dialog-header"> <h3>ååº</h3> <el-button type="text" @click="closeBatchReturnDialog" class="close-button"> à </el-button> </div> <div class="custom-dialog-body"> <el-form :model="batchReturnForm" :rules="batchReturnFormRules" ref="batchReturnFormRef" label-width="100px"> <el-form-item label="订åç¼å·"> <el-input v-model="batchReturnForm.orderNo" disabled></el-input> </el-form-item> <el-form-item label="æçç¼å·" prop="palletCode"> <el-input v-model="batchReturnForm.palletCode" placeholder="æ«ææçç " @keyup.enter.native="onBatchReturnPalletScan" @change="onBatchReturnPalletScan" clearable> </el-input> </el-form-item> <el-form-item label="æªæ£éæ°é"> <el-input v-model="batchReturnForm.unpickedCount" disabled></el-input> </el-form-item> <el-form-item label="æªæ£éæ¡æ°"> <el-input v-model="batchReturnForm.unpickedQuantity" disabled></el-input> </el-form-item> </el-form> </div> <div class="custom-dialog-footer"> <el-button @click="closeBatchReturnDialog">åæ¶</el-button> <el-button type="primary" @click="handleBatchReturnConfirm" :loading="batchReturnLoading">确认ååº</el-button> </div> </div> </div> </div> <!-- ç´æ¥åºåºå¼¹çª --> <div v-if="showDirectOutDialog" class="custom-dialog-overlay"> <div class="custom-dialog-wrapper"> <div class="custom-dialog"> <div class="custom-dialog-header"> <h3>ç´æ¥åºåº</h3> <el-button type="text" @click="closeDirectOutDialog" class="close-button"> à </el-button> </div> <div class="custom-dialog-body"> <el-form :model="directOutForm" :rules="directOutFormRules" ref="directOutFormRef" label-width="100px"> <el-form-item label="订åç¼å·"> <el-input v-model="directOutForm.orderNo" disabled></el-input> </el-form-item> <el-form-item label="æçç¼å·" prop="palletCode"> <el-input v-model="directOutForm.palletCode" placeholder="æ«ææçç " @keyup.enter.native="onDirectOutPalletScan" @change="onDirectOutPalletScan" clearable> </el-input> </el-form-item> </el-form> </div> <div class="custom-dialog-footer"> <el-button @click="closeDirectOutDialog">åæ¶</el-button> <el-button type="primary" @click="handleDirectOutConfirm" :loading="directOutLoading">确认åºåº</el-button> </div> </div> </div> </div> </div> </template> @@ -98,8 +296,8 @@ <script> import http from '@/api/http.js' import { ref, defineComponent } from "vue"; import { ElMessage } from "element-plus"; import { useRoute } from 'vue-router' import { ElMessage } from 'element-plus' import { useRoute } from 'vue-router' export default defineComponent({ name: 'PickingConfirm', @@ -114,264 +312,968 @@ }, emits: ['confirm', 'close'], data() { // å®ä¹æå 表åéªè¯è§å const validateOriginalBarcode = (rule, value, callback) => { if (!value || value.trim() === '') { callback(new Error('请è¾å ¥åæ¡ç ')); } else { callback(); } }; const validateSplitQuantity = (rule, value, callback) => { if (value === null || value === undefined || value === '') { callback(new Error('请è¾å ¥æå æ°é')); } else if (value <= 0) { callback(new Error('æå æ°éå¿ é¡»å¤§äº0')); } else if (this.splitForm.maxQuantity && value > this.splitForm.maxQuantity) { callback(new Error('æå æ°éä¸è½å¤§äºå©ä½æ°é')); } else { callback(); } }; // å®ä¹æ¤éæå 表åéªè¯è§å const validateRevertOriginalBarcode = (rule, value, callback) => { if (!value || value.trim() === '') { callback(new Error('请è¾å ¥åæ¡ç ')); } else { callback(); } }; // å®ä¹æ¹éååºè¡¨åéªè¯è§å const validateBatchReturnPalletCode = (rule, value, callback) => { if (!value || value.trim() === '') { callback(new Error('请è¾å ¥æçç ')); } else { callback(); } }; // å®ä¹ç´æ¥åºåºè¡¨åéªè¯è§å const validateDirectOutPalletCode = (rule, value, callback) => { if (!value || value.trim() === '') { callback(new Error('请è¾å ¥æçç ')); } else { callback(); } }; return { scanForm: { scanData: { orderNo: '', palletCode: '', materialBarcode: '' barcode: '' }, palletSummary: null, confirmLoading: false, pickedTableConfig: { url: '/api/outbound/getPickingRecords', query: { orderNo: this.orderNo }, columns: [ { prop: 'TaskNo', label: 'ä»»å¡å·', width: 150 }, { prop: 'Barcode', label: 'ç©ææ¡ç ', width: 150 }, { prop: 'MaterielName', label: 'ç©æåç§°', width: 150 }, { prop: 'PickQuantity', label: 'æ£è´§æ°é', width: 100 }, { prop: 'LocationCode', label: 'è´§ä½', width: 120 }, { prop: 'CreateTime', label: 'æ£è´§æ¶é´', width: 180 } unpickedList: [], pickedList: [], selectedUnpickedRows: [], // æªæ£éå表éä¸çè¡ selectedPickedRows: [], // å·²æ£éå表éä¸çè¡ summary: { unpickedCount: 0, unpickedQuantity: 0, pickedCount: 0 }, palletStatus: 'æªç¥', showSplitDialog: false, showRevertSplitDialog: false, showCustomSplitDialog: false, // èªå®ä¹æå å¼¹çªæ¾ç¤ºç¶æ showBatchReturnDialog: false, // æ¹éååºå¼¹çªæ¾ç¤ºç¶æ showReturnDialog: false, splitLoading: false, revertSplitLoading: false, batchReturnLoading: false, // æ¹éååºå è½½ç¶æ splitForm: { orderNo: '', palletCode: '', originalBarcode: '', materielCode: '', splitQuantity: 0, maxQuantity: 0 }, // æå 表åéªè¯è§å splitFormRules: { originalBarcode: [ { required: true, validator: validateOriginalBarcode, trigger: 'blur' } ], splitQuantity: [ { required: true, validator: validateSplitQuantity, trigger: 'blur' } ] }, // åºåºè¯¦æ è¡¨æ ¼é ç½® outboundTableConfig: { url: '/api/outbound/getOutboundDetails', query: { orderNo: this.orderNo }, columns: [ { prop: 'OrderNo', label: 'åºåºåå·', width: 150 }, { prop: 'MaterialCode', label: 'ç©æç¼å·', width: 120 }, { prop: 'MaterialBarcode', label: 'ç©ææ¡ç ', width: 150 }, { prop: 'BatchNo', label: 'æ¹æ¬¡å·', width: 120 }, { prop: 'AssignQuantity', label: 'åé åºåºé', width: 100 }, { prop: 'PalletCode', label: 'æçç¼å·', width: 120 }, { prop: 'Unit', label: 'åä½', width: 80 } revertSplitForm: { originalBarcode: '' }, // æ¤éæå 表åéªè¯è§å revertSplitFormRules: { originalBarcode: [ { required: true, validator: validateRevertOriginalBarcode, trigger: 'blur' } ] }, orderInfo: {orderNo:''} // æ¹éååºè¡¨å batchReturnForm: { orderNo: '', palletCode: '', unpickedCount: 0, unpickedQuantity: 0 }, // æ¹éååºè¡¨åéªè¯è§å batchReturnFormRules: { palletCode: [ { required: true, validator: validateBatchReturnPalletCode, trigger: 'blur' } ] }, showDirectOutDialog: false, // ç´æ¥åºåºå¼¹çªæ¾ç¤ºç¶æ directOutLoading: false, // ç´æ¥åºåºå è½½ç¶æ directOutForm: { orderNo: '', palletCode: '' }, directOutFormRules: { palletCode: [ { required: true, validator: validateDirectOutPalletCode, trigger: 'blur' } ] }, returnForm: { orderNo: '', palletCode: '', barcode: '', materielCode: '', returnQuantity: 0 }, isProcessing: false // 鲿¢éå¤æäº¤ } }, mounted() { this.loadOrderInfo(); // ä»è·¯ç±åæ°è·å订åç¼å· if (this.$route.query.orderNo) { this.scanData.orderNo = this.$route.query.orderNo; this.splitForm.orderNo = this.$route.query.orderNo; this.returnForm.orderNo = this.$route.query.orderNo; } // 页é¢å è½½åèªå¨èç¦å°æçç è¾å ¥æ¡ this.$nextTick(() => { if (this.$refs.palletInput) { this.$refs.palletInput.focus() } }) this.$refs.palletInput.focus(); }); }, methods: { loadOrderInfo() { const orderId = this.$route.query.orderId if (!orderId) return goBack(){ this.$router.back() }, openSplitDialog() { console.log('æå¼èªå®ä¹æå å¼¹çª'); if (!this.scanData.palletCode) { this.$message.warning('è¯·å æ«ææçç '); return; } this.showCustomSplitDialog = true; // é置表å this.resetSplitForm(); // 设置订ååæçä¿¡æ¯ this.splitForm.orderNo = this.scanData.orderNo; this.splitForm.palletCode = this.scanData.palletCode; // æ¸ é¤è¡¨åéªè¯ this.$nextTick(() => { if (this.$refs.splitFormRef) { this.$refs.splitFormRef.clearValidate(); } }); }, // å ³éèªå®ä¹æå å¼¹çª closeCustomSplitDialog() { this.showCustomSplitDialog = false; this.resetSplitForm(); // æ¸ é¤è¡¨åéªè¯ if (this.$refs.splitFormRef) { this.$refs.splitFormRef.clearValidate(); } }, // æå¼æ¤éæå å¼¹çª openRevertSplitDialog() { console.log('æå¼æ¤éæå å¼¹çª'); this.showRevertSplitDialog = true; // é置表å this.resetRevertSplitForm(); // æ¸ é¤è¡¨åéªè¯ this.$nextTick(() => { if (this.$refs.revertSplitFormRef) { this.$refs.revertSplitFormRef.clearValidate(); } }); }, // å ³éæ¤éæå å¼¹çª closeRevertSplitDialog() { this.showRevertSplitDialog = false; this.resetRevertSplitForm(); // æ¸ é¤è¡¨åéªè¯ if (this.$refs.revertSplitFormRef) { this.$refs.revertSplitFormRef.clearValidate(); } }, // æå¼æ¹éååºå¼¹çª openBatchReturnDialog() { console.log('æå¼æ¹éååºå¼¹çª'); this.showBatchReturnDialog = true; // é置表å this.resetBatchReturnForm(); // 设置订åä¿¡æ¯ this.batchReturnForm.orderNo = this.scanData.orderNo; // æ´æ°æªæ£éä¿¡æ¯ this.batchReturnForm.unpickedCount = this.summary.unpickedCount || 0; this.batchReturnForm.unpickedQuantity = this.summary.unpickedQuantity || 0; // æ¸ é¤è¡¨åéªè¯ this.$nextTick(() => { if (this.$refs.batchReturnFormRef) { this.$refs.batchReturnFormRef.clearValidate(); } }); }, // å ³éæ¹éååºå¼¹çª closeBatchReturnDialog() { this.showBatchReturnDialog = false; this.resetBatchReturnForm(); // æ¸ é¤è¡¨åéªè¯ if (this.$refs.batchReturnFormRef) { this.$refs.batchReturnFormRef.clearValidate(); } }, // æ¹éååºæçç æ«ç onBatchReturnPalletScan() { if (!this.batchReturnForm.palletCode) return; this.batchReturnForm.palletCode = this.batchReturnForm.palletCode.replace(/\n/g, '').trim(); // æ¸ é¤éªè¯ç¶æ if (this.$refs.batchReturnFormRef) { this.$refs.batchReturnFormRef.clearValidate(['palletCode']); } }, // æ¹éååºç¡®è®¤ async handleBatchReturnConfirm() { // 表åéªè¯ if (this.$refs.batchReturnFormRef) { this.$refs.batchReturnFormRef.validate((valid) => { if (valid) { this.submitBatchReturn(); } else { this.$message.warning('è¯·æ«ææçç '); return false; } }); } else { // å¦ææ²¡æè¡¨åå¼ç¨ï¼ä½¿ç¨åæçéªè¯ if (!this.batchReturnForm.palletCode) { this.$message.warning('è¯·æ«ææçç '); return; } this.submitBatchReturn(); } }, // æäº¤æ¹éååºè¯·æ± async submitBatchReturn() { this.batchReturnLoading = true; try { const res = await this.http.post('/api/OutboundPicking/batch-return-to-stock', { orderNo: this.batchReturnForm.orderNo, palletCode: this.batchReturnForm.palletCode }); if (res.status) { this.$message.success('æ¹éååºæå'); this.showBatchReturnDialog = false; this.loadData(); } else { this.$message.error(res.message || 'æ¹éååºå¤±è´¥'); } } catch (error) { this.$message.error('æ¹éååºå¤±è´¥'); } finally { this.batchReturnLoading = false; } }, // æå¼ç´æ¥åºåºå¼¹çª openDirectOutDialog() { console.log('æå¼ç´æ¥åºåºå¼¹çª'); this.showDirectOutDialog = true; // é置表å this.resetDirectOutForm(); // 设置订åä¿¡æ¯ this.directOutForm.orderNo = this.scanData.orderNo; // æ¸ é¤è¡¨åéªè¯ this.$nextTick(() => { if (this.$refs.directOutFormRef) { this.$refs.directOutFormRef.clearValidate(); } }); }, // å ³éç´æ¥åºåºå¼¹çª closeDirectOutDialog() { this.showDirectOutDialog = false; this.resetDirectOutForm(); // æ¸ é¤è¡¨åéªè¯ if (this.$refs.directOutFormRef) { this.$refs.directOutFormRef.clearValidate(); } }, // ç´æ¥åºåºæçç æ«ç onDirectOutPalletScan() { if (!this.directOutForm.palletCode) return; this.directOutForm.palletCode = this.directOutForm.palletCode.replace(/\n/g, '').trim(); // æ¸ é¤éªè¯ç¶æ if (this.$refs.directOutFormRef) { this.$refs.directOutFormRef.clearValidate(['palletCode']); } }, // ç´æ¥åºåºç¡®è®¤ async handleDirectOutConfirm() { // 表åéªè¯ if (this.$refs.directOutFormRef) { this.$refs.directOutFormRef.validate((valid) => { if (valid) { this.submitDirectOut(); } else { this.$message.warning('è¯·æ«ææçç '); return false; } }); } else { // å¦ææ²¡æè¡¨åå¼ç¨ï¼ä½¿ç¨åæçéªè¯ if (!this.directOutForm.palletCode) { this.$message.warning('è¯·æ«ææçç '); return; } this.submitDirectOut(); } }, // æäº¤ç´æ¥åºåºè¯·æ± async submitDirectOut() { this.directOutLoading = true; try { const res = await this.http.post('/api/OutboundPicking/direct-outbound', { orderNo: this.directOutForm.orderNo, palletCode: this.directOutForm.palletCode }); debugger; if (res.status) { this.$message.success('ç´æ¥åºåºæå'); this.showDirectOutDialog = false; this.loadData(); } else { this.$message.error(res.message || 'ç´æ¥åºåºå¤±è´¥'); } } catch (error) { this.$message.error('ç´æ¥åºåºå¤±è´¥'); } finally { this.directOutLoading = false; } }, // éç½®ç´æ¥åºåºè¡¨å resetDirectOutForm() { this.directOutForm.palletCode = ''; }, // ä¿®æ¹åæçç´æ¥åºåºæé®ç¹å»äºä»¶ handleDirectOutbound() { this.openDirectOutDialog(); }, async loadData() { if (!this.scanData.orderNo || !this.scanData.palletCode) { return; } try { this.http.get(`/api/OutboundOrder/GetById?id=${orderId}`).then(response => {debugger; if (response.status) { this.orderInfo = response.data // å è½½æªæ£éå表 const unpickedRes = await this.http.post('/api/OutboundPicking/unpicked-list', this.scanData); this.unpickedList = unpickedRes.data || []; // å 载已æ£éå表 const pickedRes = await this.http.post('/api/OutboundPicking/picked-list', this.scanData); this.pickedList = pickedRes.data || []; // å è½½æ±æ»ä¿¡æ¯ const summaryRes = await this.http.post('/api/OutboundPicking/picking-summary',this.scanData); this.summary = summaryRes.data || {}; // æ´æ°æçç¶æ this.updatePalletStatus(); } catch (error) { this.$message.error('å è½½æ°æ®å¤±è´¥'); } }, updatePalletStatus() { if (this.unpickedList.length === 0 && this.pickedList.length > 0) { this.palletStatus = 'å·²å ¨é¨æ£é'; } else if (this.unpickedList.length > 0 && this.pickedList.length === 0) { this.palletStatus = 'å¾ æ£é'; } else if (this.unpickedList.length > 0 && this.pickedList.length > 0) { this.palletStatus = 'é¨åæ£é'; } else { this.palletStatus = 'æ æ°æ®'; } }, // å·²æ£éåè¡¨éæ©åå handlePickedSelectionChange(selection) { this.selectedPickedRows = selection; }, // æ¹éåæ¶éä¸çå·²æ£é项 async batchCancelSelected() { if (this.selectedPickedRows.length === 0) { this.$message.warning('请å éæ©è¦åæ¶ç项'); return; } this.$confirm(`ç¡®å®è¦åæ¶éä¸ç ${this.selectedPickedRows.length} 项åï¼`, 'æç¤º', { confirmButtonText: 'ç¡®å®', cancelButtonText: 'åæ¶', type: 'warning' }).then(async () => { try { let successCount = 0; let errorCount = 0; for (const row of this.selectedPickedRows) { try { const res = await this.http.post('/api/OutboundPicking/CancelPicking', { orderNo: this.scanData.orderNo, palletCode: this.scanData.palletCode, barcode: row.currentBarcode }); } }) } catch (error) { ElMessage.error('å è½½åºåºåä¿¡æ¯å¤±è´¥') } }, goBack() { this.$router.back() }, async handlePalletScan() { if (this.scanForm.palletCode) { ElMessage.success(`å·²æ«ææç: ${this.scanForm.palletCode}`) await this.loadPalletSummary() this.$nextTick(() => { if (this.$refs.materialInput) { this.$refs.materialInput.focus() } }) } }, async handleMaterialScan() { if (!this.scanForm.palletCode) { ElMessage.warning('è¯·å æ«ææçç ') this.$refs.palletInput.focus() return } if (!this.scanForm.materialBarcode) { ElMessage.warning('è¯·æ«æç©ææ¡ç ') return } await this.executePickingConfirm() }, async loadPalletSummary() { if (!this.scanForm.palletCode) { this.palletSummary = null return } try { const result = await http.get('/api/outbound/getPalletPickingSummary', { params: { orderNo: this.orderNo, palletCode: this.scanForm.palletCode } }) if (result.success) { // å¤çç»è®¡ä¿¡æ¯ const summary = result.data const assigned = summary.find(x => x.Status === 'å·²åé ') || { TotalAssignQty: 0, TotalPickedQty: 0 } const picked = summary.find(x => x.Status === 'å·²æ£é') || { TotalPickedQty: 0 } this.palletSummary = { unpickedCount: assigned.TotalAssignQty > 0 ? 1 : 0, // ç®åè®¡ç® unpickedTotal: assigned.TotalAssignQty - assigned.TotalPickedQty } } } catch (error) { console.error('å è½½æçç»è®¡å¤±è´¥:', error) } }, async handleConfirm() { if (!this.scanForm.palletCode || !this.scanForm.materialBarcode) { ElMessage.warning('请填å宿´çæ«ç ä¿¡æ¯') return } await this.executePickingConfirm() }, async executePickingConfirm() { this.confirmLoading = true try { // å æ¾å°å¯¹åºçåºåºéå®ä¿¡æ¯ const lockInfoResult = await this.http.get('/api/outbound/getOutStockLockInfo', { params: { orderNo: this.orderNo, palletCode: this.scanForm.palletCode, materialBarcode: this.scanForm.materialBarcode } }) if (!lockInfoResult.success || !lockInfoResult.data || lockInfoResult.data.length === 0) { ElMessage.error('æªæ¾å°å¯¹åºçåºåºéå®ä¿¡æ¯') return } const lockInfo = lockInfoResult.data[0] const request = { outStockLockId: lockInfo.Id, taskNo: `TASK_${Date.now()}`, palletCode: this.scanForm.palletCode, materialBarcode: this.scanForm.materialBarcode, locationCode: lockInfo.LocationCode } const result = await this.http.post('/api/outbound/pickingConfirm', request) if (result.success) { ElMessage.success('åæ£ç¡®è®¤æå') this.handleReset() this.$emit('confirm') // å·æ°è¡¨æ ¼ if (this.$refs.pickedTable) { this.$refs.pickedTable.refresh() if (res.status) { successCount++; } else { errorCount++; console.error(`åæ¶æ£é失败: ${row.Barcode}`, res.message); } } catch (error) { errorCount++; console.error(`åæ¶æ£é失败: ${row.Barcode}`, error); } } // å·æ°åºåºè¯¦æ è¡¨æ ¼ if (this.$refs.outboundTable) { this.$refs.outboundTable.refresh() if (errorCount === 0) { this.$message.success(`æååæ¶ ${successCount} 项`); } else { this.$message.warning(`æååæ¶ ${successCount} 项ï¼å¤±è´¥ ${errorCount} 项`); } this.loadData(); this.selectedPickedRows = []; } catch (error) { this.$message.error('æ¹éåæ¶æä½å¤±è´¥'); } }).catch(() => { this.$message.info('已忶æ¹éæä½'); }); }, // æçç æ«ç onPalletScan() { // å»é¤å车符åååç©ºæ ¼ this.scanData.palletCode = this.scanData.palletCode.replace(/\n/g, '').trim(); if (!this.scanData.palletCode) return; this.splitForm.palletCode = this.scanData.palletCode; this.returnForm.palletCode = this.scanData.palletCode; // å è½½æ°æ® this.loadData(); // èªå¨è·³è½¬å°ç©ææ¡ç è¾å ¥æ¡ this.$nextTick(() => { this.$refs.barcodeInput.focus(); }); }, // éæ°å è½½æçç»è®¡ await this.loadPalletSummary() onBarcodeScan() { // å»é¤å车符åååç©ºæ ¼ this.scanData.barcode = this.scanData.barcode.replace(/\n/g, '').trim(); if (!this.scanData.barcode) return; // èªå¨ç¡®è®¤æ£é this.confirmPicking(); }, async confirmPicking() { if (this.isProcessing) return; if (!this.scanData.orderNo || !this.scanData.palletCode || !this.scanData.barcode) { this.$message.warning('è¯·å æ«ææçç åç©ææ¡ç '); this.focusBarcodeInput(); return; } this.isProcessing = true; try { const res = await this.http.post('/api/OutboundPicking/confirm-picking', this.scanData); if (res.status) { this.$message.success('æ£é确认æå'); this.scanData.barcode = ''; // æ¸ ç©ºç©ææ¡ç this.loadData(); // æååç»§ç»èç¦å°ç©ææ¡ç è¾å ¥æ¡ï¼åå¤ä¸ä¸ä¸ªæ«ç this.$nextTick(() => { this.$refs.barcodeInput.focus(); }); } else { ElMessage.error(result.ElMessage) // æ¾ç¤ºå端è¿åçéè¯¯ä¿¡æ¯ this.$message.error(res.message || 'æ£é确认失败'); // 失败æ¶èç¦å¹¶éä¸ç©ææ¡ç è¾å ¥æ¡å 容 this.focusBarcodeInput(true); } } catch (error) { ElMessage.error('åæ£ç¡®è®¤å¤±è´¥') this.$message.error('æ£é确认失败: ' + (error.message || 'ç½ç»é误')); // 失败æ¶èç¦å¹¶éä¸ç©ææ¡ç è¾å ¥æ¡å 容 this.focusBarcodeInput(true); } finally { this.confirmLoading = false this.isProcessing = false; } }, handleReset() { this.scanForm.materialBarcode = '' // èç¦å°ç©ææ¡ç è¾å ¥æ¡ focusBarcodeInput(selectText = false) { this.$nextTick(() => { if (this.$refs.materialInput) { this.$refs.materialInput.focus() const input = this.$refs.barcodeInput; if (input && input.$el && input.$el.querySelector('input')) { const inputEl = input.$el.querySelector('input'); inputEl.focus(); if (selectText) { inputEl.select(); } } }) }); }, async cancelPicking(row) { try { const res = await this.http.post('/api/OutboundPicking/CancelPicking', { orderNo: this.scanData.orderNo, palletCode: this.scanData.palletCode, barcode: row.Barcode }); if (res.status) { this.$message.success('åæ¶æ£éæå'); this.loadData(); } else { this.$message.error(res.message || 'åæ¶æ£é失败'); } } catch (error) { this.$message.error('åæ¶æ£é失败'); } }, /* // ååºæä½ - ååºæ´ä¸ªæçæªæ£éçè´§ç© async handleBatchReturn() { if (!this.scanData.orderNo || !this.scanData.palletCode) { this.$message.warning('è¯·å æ«ææçç '); return; } if (this.unpickedList.length === 0) { this.$message.warning('该æç没æå¯ååºçè´§ç©'); return; } this.$confirm(`ç¡®å®è¦ååºæ´ä¸ªæççæªæ£éè´§ç©åï¼å ± ${this.unpickedList.length} æ¡è®°å½`, 'æç¤º', { confirmButtonText: 'ç¡®å®', cancelButtonText: 'åæ¶', type: 'warning' }).then(async () => { try { const res = await this.http.post('/api/OutboundPicking/batch-return-to-stock', { orderNo: this.scanData.orderNo, palletCode: this.scanData.palletCode }); if (res.success) { this.$message.success('æ¹éååºæå'); this.loadData(); } else { this.$message.error(res.message || 'æ¹éååºå¤±è´¥'); } } catch (error) { this.$message.error('æ¹éååºå¤±è´¥'); } }).catch(() => { this.$message.info('已忶æ¹éååº'); }); }, */ /* // ç´æ¥åºåºæä½ async handleDirectOutbound() { if (!this.scanData.orderNo || !this.scanData.palletCode) { this.$message.warning('è¯·å æ«ææçç '); return; } this.$confirm('ç¡®å®è¦ç´æ¥åºåºæ´ä¸ªæçåï¼', 'æç¤º', { confirmButtonText: 'ç¡®å®', cancelButtonText: 'åæ¶', type: 'warning' }).then(async () => { try { const res = await this.http.post('/api/OutboundPicking/direct-outbound', { orderNo: this.scanData.orderNo, palletCode: this.scanData.palletCode }); if (res.success) { this.$message.success('ç´æ¥åºåºæå'); this.loadData(); } else { this.$message.error(res.message || 'ç´æ¥åºåºå¤±è´¥'); } } catch (error) { this.$message.error('ç´æ¥åºåºå¤±è´¥'); } }).catch(() => { this.$message.info('å·²åæ¶ç´æ¥åºåº'); }); }, */ // 确认ååºï¼éè¿å¼¹çªï¼ async handleReturnConfirm() { if (!this.returnForm.barcode) { this.$message.warning('è¯·æ«æååºæ¡ç '); return; } try { const res = await this.http.post('/api/OutboundPicking/return-to-stock', { orderNo: this.returnForm.orderNo, palletCode: this.returnForm.palletCode, barcode: this.returnForm.barcode }); if (res.success) { this.$message.success('ååºæå'); this.showReturnDialog = false; this.resetReturnForm(); this.loadData(); } else { this.$message.error(res.message || 'ååºå¤±è´¥'); } } catch (error) { this.$message.error('ååºå¤±è´¥'); } }, // æå æ«ç async onSplitBarcodeScan() { if (!this.splitForm.originalBarcode) return; // å»é¤å车符åååç©ºæ ¼ this.splitForm.originalBarcode = this.splitForm.originalBarcode.replace(/\n/g, '').trim(); try { const res = await this.http.post('/api/OutboundPicking/split-package-info', { orderNo: this.splitForm.orderNo, palletCode: this.splitForm.palletCode, barcode: this.splitForm.originalBarcode }); if (res.status) { this.splitForm.materielCode = res.data.materielCode; this.splitForm.maxQuantity = res.data.remainQuantity; this.splitForm.splitQuantity = Math.min(1, this.splitForm.maxQuantity); // æ¸ é¤éªè¯ç¶æ if (this.$refs.splitFormRef) { this.$refs.splitFormRef.clearValidate(['originalBarcode']); } } else { this.$message.error(res.message || 'è·åæå ä¿¡æ¯å¤±è´¥'); // éªè¯å¤±è´¥ï¼è®¾ç½®éè¯¯ç¶æ if (this.$refs.splitFormRef) { this.$refs.splitFormRef.validateField('originalBarcode'); } } } catch (error) { this.$message.error('è·åæå ä¿¡æ¯å¤±è´¥'); // éªè¯å¤±è´¥ï¼è®¾ç½®éè¯¯ç¶æ if (this.$refs.splitFormRef) { this.$refs.splitFormRef.validateField('originalBarcode'); } } }, async handleSplitPackage() { // 表åéªè¯ if (this.$refs.splitFormRef) { this.$refs.splitFormRef.validate((valid) => { if (valid) { this.submitSplitPackage(); } else { this.$message.warning('请填å宿´çæå ä¿¡æ¯'); return false; } }); } else { // å¦ææ²¡æè¡¨åå¼ç¨ï¼ä½¿ç¨åæçéªè¯ if (!this.splitForm.originalBarcode || this.splitForm.splitQuantity <= 0) { this.$message.warning('请填å宿´çæå ä¿¡æ¯'); return; } if (this.splitForm.splitQuantity > this.splitForm.maxQuantity) { this.$message.warning('æå æ°éä¸è½å¤§äºå©ä½æ°é'); return; } this.submitSplitPackage(); } }, // æäº¤æå è¯·æ± async submitSplitPackage() { this.splitLoading = true; try { const res = await this.http.post('/api/OutboundPicking/split-package', this.splitForm); if (res.status) { this.$message.success('æå æå'); this.showSplitDialog = false; this.resetSplitForm(); this.loadData(); } else { this.$message.error(res.message || 'æå 失败'); } } catch (error) { this.$message.error('æå 失败'); } }, // æ¤éæå æ«ç onRevertSplitBarcodeScan() { if (!this.revertSplitForm.originalBarcode) return; this.revertSplitForm.originalBarcode = this.revertSplitForm.originalBarcode.replace(/\n/g, '').trim(); // æ¸ é¤éªè¯ç¶æ if (this.$refs.revertSplitFormRef) { this.$refs.revertSplitFormRef.clearValidate(['originalBarcode']); } }, async handleRevertSplit() { // 表åéªè¯ if (this.$refs.revertSplitFormRef) { this.$refs.revertSplitFormRef.validate((valid) => { if (valid) { this.submitRevertSplit(); } else { this.$message.warning('请è¾å ¥åæ¡ç '); return false; } }); } else { // å¦ææ²¡æè¡¨åå¼ç¨ï¼ä½¿ç¨åæçéªè¯ if (!this.revertSplitForm.originalBarcode) { this.$message.warning('请è¾å ¥åæ¡ç '); return; } this.submitRevertSplit(); } }, // æäº¤æ¤éæå è¯·æ± async submitRevertSplit() { this.revertSplitLoading = true; try { const res = await this.http.post('/api/OutboundPicking/revert-split-package', { originalBarcode: this.revertSplitForm.originalBarcode }); if (res.status) { this.$message.success('æ¤éæå æå'); this.showRevertSplitDialog = false; this.revertSplitForm.originalBarcode = ''; this.loadData(); } else { this.$message.error(res.message || 'æ¤éæå 失败'); } } catch (error) { this.$message.error('æ¤éæå 失败'); } }, resetSplitForm() { this.splitForm.originalBarcode = ''; this.splitForm.materielCode = ''; this.splitForm.splitQuantity = 0; this.splitForm.maxQuantity = 0; }, // éç½®æ¹éååºè¡¨å resetBatchReturnForm() { this.batchReturnForm.palletCode = ''; this.batchReturnForm.unpickedCount = 0; this.batchReturnForm.unpickedQuantity = 0; }, resetReturnForm() { this.returnForm.barcode = ''; this.returnForm.materielCode = ''; this.returnForm.returnQuantity = 0; } } }) </script> <style scoped> .picking-confirm { .picking-container { padding: 20px; position: relative; /* 为弹çªå®ä½æä¾ä¸ä¸æ */ } .scanner-form { display: flex; flex-direction: column; height: 70vh; gap: 10px; align-items: center; flex-wrap: wrap; } .content-layout { .scanner-form .el-input { width: 200px; } .summary-info { display: flex; gap: 16px; margin-bottom: 16px; flex: 1; min-height: 0; /* éè¦ï¼é²æ¢flexåå ç´ æº¢åº */ gap: 20px; flex-wrap: wrap; } .left-section { flex: 1; /* è¡¨æ ¼æä½åºåæ ·å¼ */ .table-actions { display: flex; flex-direction: column; justify-content: space-between; align-items: center; margin-bottom: 10px; padding: 0 10px; } .right-section { flex: 1; .selection-count { font-size: 12px; color: #909399; } /* è¡¨æ ¼æ ·å¼è°æ´ */ .content-area .el-table { margin-top: 0; } /* ç¡®ä¿è¡¨æ ¼é«åº¦éåº */ .content-area .el-card__body { padding: 15px; } /* èªå®ä¹å¼¹çªæ ·å¼ */ .custom-dialog-overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.5); display: flex; flex-direction: column; align-items: center; justify-content: center; z-index: 9999; } .scan-section { flex-shrink: 0; .custom-dialog-wrapper { position: relative; z-index: 10000; } .scan-alert { margin-bottom: 16px; .custom-dialog { background: white; border-radius: 4px; width: 500px; max-width: 90vw; max-height: 90vh; box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); overflow: auto; } .scan-form { max-width: 500px; } .pallet-summary { margin: 16px 0; } .action-buttons { margin-top: 16px; } .outbound-details-card { height: 100%; .custom-dialog-header { display: flex; flex-direction: column; justify-content: space-between; align-items: center; padding: 20px 20px 10px; border-bottom: 1px solid #ebeef5; } .outbound-details-card :deep(.el-card__body) { flex: 1; .custom-dialog-header h3 { margin: 0; color: #303133; } /* å ³éæé®æ ·å¼ */ .close-button { font-size: 18px; color: #909399; padding: 0; width: 24px; height: 24px; display: flex; align-items: center; justify-content: center; } .picked-records { flex-shrink: 0; height: 300px; .close-button:hover { color: #409EFF; background-color: transparent; } .picked-records :deep(.el-card__body) { padding: 0; .custom-dialog-body { padding: 20px; } .custom-dialog-footer { padding: 10px 20px 20px; text-align: right; border-top: 1px solid #ebeef5; } .custom-dialog-footer .el-button { margin-left: 10px; } /* ç¡®ä¿å¼¹çªå¨ç§»å¨è®¾å¤ä¸ä¹è½æ£å¸¸æ¾ç¤º */ @media (max-width: 768px) { .custom-dialog { width: 95vw; margin: 10px; } } </style> ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.878.3237/CodeChunks.db-shmBinary files differ
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.878.3237/SemanticSymbols.db-shmBinary files differ
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_BasicService/InvokeMESService.cs
@@ -207,7 +207,7 @@ }; var groupedData = lists.GroupBy(item => new { item.MaterielCode, item.SupplyCode, item.BatchNo, item.InboundOrderRowNo, item.Unit, item.WarehouseCode }) var groupedData = lists.GroupBy(item => new { item.MaterielCode, item.SupplyCode, item.BatchNo, item.InboundOrderRowNo, item.BarcodeUnit, item.WarehouseCode }) .Select(group => new FeedbackInboundDetailsModel { materialCode = group.Key.MaterielCode, @@ -216,11 +216,11 @@ lineNo = group.Key.InboundOrderRowNo, // warehouseCode = group.Key.WarehouseCode=="0"?"1072": group.Key.WarehouseCode, warehouseCode =group.Key.WarehouseCode, unit = group.Key.Unit, unit = group.Key.BarcodeUnit, barcodes = group.Select(row => new FeedbackBarcodesModel { barcode = row.Barcode, qty = row.StockQuantity qty = row.BarcodeQty }).ToList() }).ToList(); feedmodel.details = groupedData; ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_Common/OrderEnum/OrderCreateTypeEnum.cs
@@ -10,15 +10,16 @@ public enum OrderCreateTypeEnum { /// <summary> /// ç³»ç»å å建 /// </summary> [Description("ç³»ç»å å建")] CreateInSystem, /// <summary> /// 䏿¸¸ç³»ç»æ¨é /// </summary> [Description("䏿¸¸ç³»ç»æ¨é")] UpperSystemPush UpperSystemPush, /// <summary> /// ç³»ç»å å建 /// </summary> [Description("ç³»ç»å å建")] CreateInSystem } } ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_Core/BaseRepository/RepositoryBase.cs
@@ -912,7 +912,8 @@ _db.InsertableByObject(obj).AS(type.Name + "_Hty").ExecuteCommand(); } } return DeleteData(entity); // return DeleteData(entity); return true; } public bool DeleteAndMoveIntoHty(List<TEntity> entities, OperateTypeEnum operateType) ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_DTO/Outbound/OutboundOrderGetDTO.cs
@@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Components.Forms; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; @@ -25,11 +26,23 @@ } public class ConfirmPickingDto { [JsonProperty("orderNo")] public string OrderNo { get; set; } [JsonProperty("palletCode")] public string PalletCode { get; set; } [JsonProperty("barcode")] public string Barcode { get; set; } } public class SummaryPickingDto { public string PalletCode { get; set; } public string MaterielCode { get; set; } public int UnpickedCount { get; set; } public decimal UnpickedQuantity { get; set; } public int pickedCount { get; set; } } public class PickingConfirmRequest { public int OrderDetailId { get; set; } @@ -45,6 +58,7 @@ public class DirectOutboundRequest { public string PalletCode { get; set; } public string OrderNo { get; set; } } public class CancelPickingRequest ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_IOutboundService/IOutboundPickingService.cs
@@ -20,12 +20,14 @@ Task<WebResponseContent> ConfirmPicking(PickingConfirmRequest request); Task<WebResponseContent> ConfirmPicking(string orderNo, string palletCode, string barcode); Task<WebResponseContent> DirectOutbound(DirectOutboundRequest request); Task<List<OutStockLockListResp>> GetOutStockLockListAsync(string orderNo); Task<WebResponseContent> GetPalletOutboundStatus(string palletCode); Task GetPalletPickingSummary(string orderNo, string palletCode); Task<List<Dt_OutStockLockInfo>> GetPickedList(string orderNo, string palletCode); Task<List<Dt_PickingRecord>> GetPickingHistory(int orderId); Task<object> GetPickingSummary(string orderNo); Task<object> GetPickingSummary(ConfirmPickingDto dto); Task<List<Dt_OutStockLockInfo>> GetUnpickedList(string orderNo, string palletCode); Task<WebResponseContent> ValidateBarcode(string barcode); } ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_ITaskInfoService/ITaskService.cs
@@ -45,5 +45,6 @@ Task<WebResponseContent> TaskCompleted(string taskNum); Task<WebResponseContent> GenerateOutboundTasksAsync(int[] keys); } } ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_InboundService/InboundOrderService.cs
@@ -367,10 +367,13 @@ SupplyCode = item.SupplyCode, WarehouseCode = materielGroupDTO.WarehouseType, StockQuantity = item.OrderQuantity, BarcodeQty=item.BarcodeQty, BarcodeUnit=item.BarcodeUnit, FactoryArea= inboundOrder.FactoryArea, Status = 0, OrderNo = inboundOrder.InboundOrderNo, BusinessType = inboundOrder.BusinessType, ProductionDate = DateTime.Now.ToString("yyyy-mm-dd HH:mm:ss") }); item.ReceiptQuantity = item.BarcodeQty; ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_Model/Models/Outbound/Dt_OutboundLockInfo.cs
@@ -111,7 +111,7 @@ public string SupplyCode { get; set; } public string WarehouseCode { get; set; } /// <summary> /// ç¶æ ç¶æï¼0-å·²åé 1-é¨åæ£é 2-å·²æ£é 3-已宿 /// ç¶æ ç¶æï¼0-å·²åé 1-åºåºä¸ 2-é¨åæ£é 3å·²æ£é /// </summary> [SugarColumn(IsNullable = false, ColumnDescription = "ç¶æ")] public int Status { get; set; } @@ -127,7 +127,10 @@ [Navigate(NavigateType.OneToOne, nameof(StockInfo))]//ä¸å¯¹ä¸ SchoolIdæ¯StudentAç±»éé¢ç public Dt_StockInfo StockInfo { get; set; } //ä¸è½èµå¼åªè½æ¯null [SugarColumn(IsIgnore = true)] public string FactoryArea { get; set; } [SqlSugar.SugarColumn(IsIgnore = true)] public decimal RemainQuantity => AssignQuantity - PickedQty; } ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_Model/Models/Outbound/Dt_PickingRecord.cs
@@ -19,6 +19,8 @@ { [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] public int Id { get; set; } public int TaskNo { get; set; } public string OrderNo { get; set; } public int OrderDetailId { get; set; } @@ -41,6 +43,9 @@ public string LocationCode { get; set; } public int StockId { get; set; } public string FactoryArea { get; set; } } @@ -79,13 +84,15 @@ [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] public int Id { get; set; } public string OrderNo { get; set; } public int? TaskNum { get; set; } public string PalletCode { get; set; } public string StockId { get; set; } public int StockId { get; set; } public bool IsReverted { get; set; } = false; public int OutStockLockInfoId { get; set; } // å ³èçåºåºéå®ä¿¡æ¯ public string OriginalBarcode { get; set; } // åæ¡ç public string NewBarcode { get; set; } // æ°æ¡ç public string FactoryArea { get; set; } /// <summary> /// æåæ°éï¼æ°æ¡ç æ°éï¼ /// </summary> ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_Model/Models/Stock/Dt_StockInfoDetail.cs
@@ -104,6 +104,7 @@ [SugarColumn(ColumnName = "supplyCode", ColumnDescription = "ä¾åºåç¼å·")] public string? SupplyCode { get; set; } public string FactoryArea { get; set; } /// <summary> /// ä»åº /// é»è®¤å¼: @@ -126,6 +127,11 @@ [SugarColumn(ColumnName = "businessType", ColumnDescription = "ä¸å¡ç±»å")] public string? BusinessType { get; set; } public decimal BarcodeQty { get; set; } public string BarcodeUnit { get; set; } /// <summary> /// 夿³¨ /// </summary> ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_OutboundService/OutStockLockInfoService.cs
@@ -34,9 +34,9 @@ _recordService = recordService; } /// <summary> /// å建åºåºéå®ä¿¡æ¯ - ä¿®å¤çæ¬ /// å建åºåºéå® /// </summary> public Dt_OutStockLockInfo GetOutStockLockInfo( Dt_OutboundOrder outboundOrder, @@ -72,7 +72,7 @@ // 使ç¨ç¬¬ä¸ä¸ªå¯ç¨æ¡ç var firstAvailableDetail = stockDetails .Where(x => x.StockQuantity > x.OutboundQuantity) .OrderBy(x => x.ProductionDate) .OrderBy(x => x.CreateDate) .FirstOrDefault(); if (firstAvailableDetail == null) @@ -84,6 +84,7 @@ return new Dt_OutStockLockInfo() { PalletCode = outStock.PalletCode, AssignQuantity = assignQuantity, MaterielCode = outboundOrderDetail.MaterielCode, @@ -99,8 +100,9 @@ Status = (int)OutLockStockStatusEnum.å·²åé , StockId = outStock.Id, Unit = outboundOrderDetail.Unit, SupplyCode = outboundOrderDetail.SupplyCode, FactoryArea = outboundOrder.FactoryArea, OrderType=outboundOrder.OrderType, SupplyCode = outboundOrderDetail.SupplyCode, WarehouseCode = outboundOrderDetail.WarehouseCode, // æ°å¢å段 CurrentBarcode = targetBarcode, @@ -141,7 +143,7 @@ Status = lockInfo.Status, IsSplitted = lockInfo.IsSplitted, ParentLockId = lockInfo.ParentLockId, MaterielName = detail.MaterielName, Unit = detail.Unit }) ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundOrderDetailService.cs
@@ -70,7 +70,7 @@ MaterielCode = x.Key.MaterielCode, BatchNo = x.Key.BatchNo, Details = x.ToList(), TotalNeedQuantity = x.Sum(v => v.OrderQuantity - v.OverOutQuantity - v.LockQuantity) TotalNeedQuantity = x.Sum(v => v.OrderQuantity - v.OverOutQuantity - v.LockQuantity-v.MoveQty) }) .Where(x => x.TotalNeedQuantity > 0) .ToList(); @@ -107,7 +107,7 @@ } /// <summary> /// æå è¿å åºåååé é宿°éå°å个æç» - ä¿®å¤çæ¬ /// æå è¿å åºåååé é宿°éå°å个æç» /// </summary> private void DistributeLockQuantityByFIFO( List<Dt_OutboundOrderDetail> details, @@ -118,7 +118,7 @@ { // æå è¿å åºæåºåºåºåæç»ï¼å设å å建çæç»éè¦ä¼å æ»¡è¶³ï¼ var sortedDetails = details .Where(d => d.OrderQuantity - d.OverOutQuantity - d.LockQuantity > 0) // åªå¤çè¿éè¦åé çæ°é .Where(d => d.OrderQuantity - d.OverOutQuantity - d.LockQuantity -d.MoveQty> 0) // åªå¤çè¿éè¦åé çæ°é .OrderBy(x => x.Id) .ToList(); @@ -128,7 +128,7 @@ var allocatedStockDetails = assignStocks .SelectMany(x => x.Details) .Where(x => stockAllocations.ContainsKey(x.Id)) .OrderBy(x => x.ProductionDate) .OrderBy(x => x.CreateDate) .ThenBy(x => x.StockId) .ToList(); @@ -201,123 +201,6 @@ } } /// <summary> /// å建åºåºéå®ä¿¡æ¯ /// </summary> private void CreateOutStockLockInfos(Dt_OutboundOrder outboundOrder,List<Dt_OutboundOrderDetail> details, List<Dt_StockInfo> assignStocks,List<Dt_OutStockLockInfo> outStockLockInfos) { foreach (var stock in assignStocks) { // è·å该åºåä¸ç¸å ³ç©æçå¯ç¨æ¡ç ä¿¡æ¯ var stockDetails = stock.Details .Where(x => details.Any(d => d.MaterielCode == x.MaterielCode) && x.StockQuantity > x.OutboundQuantity) .OrderBy(x => x.ProductionDate) // å è¿å åº .ToList(); if (!stockDetails.Any()) continue; var stockAssignQuantity = stockDetails.Sum(x => x.OutboundQuantity); // æ¥æ¾è¿ä¸ªåºåå·²ç»åé çæ°é var existingAssign = outStockLockInfos .Where(x => x.StockId == stock.Id && details.Any(d => d.Id == x.OrderDetailId)) .Sum(x => x.AssignQuantity); var availableAssign = stockAssignQuantity - existingAssign; if (availableAssign <= 0) continue; // æå è¿å åºåååé æ¡ç var barcodeAllocation = AllocateBarcodes(stockDetails, availableAssign); // åé ç»å个æç» foreach (var detail in details.Where(d => d.LockQuantity > 0)) { var alreadyAssigned = outStockLockInfos .Where(x => x.OrderDetailId == detail.Id && x.StockId == stock.Id) .Sum(x => x.AssignQuantity); var canAssign = Math.Min(detail.LockQuantity - alreadyAssigned, availableAssign); if (canAssign > 0) { // 为è¿ä¸ªåé ç¡®å®æ¡ç var (barcode, barcodeQuantity) = GetBarcodeForAllocation(barcodeAllocation, canAssign); var lockInfo = _outStockLockInfoService.GetOutStockLockInfo( outboundOrder, detail, stock, canAssign, barcode); outStockLockInfos.Add(lockInfo); availableAssign -= canAssign; // æ´æ°æ¡ç åé è®°å½ UpdateBarcodeAllocation(barcodeAllocation, barcode, barcodeQuantity); } if (availableAssign <= 0) break; } } } /// <summary> /// æå è¿å åºåååé æ¡ç /// </summary> private Dictionary<string, decimal> AllocateBarcodes(List<Dt_StockInfoDetail> stockDetails, decimal totalQuantity) { var allocation = new Dictionary<string, decimal>(); decimal remainingQuantity = totalQuantity; foreach (var detail in stockDetails.OrderBy(x => x.ProductionDate)) { if (remainingQuantity <= 0) break; decimal available = detail.StockQuantity - detail.OutboundQuantity; decimal allocate = Math.Min(available, remainingQuantity); allocation[detail.Barcode] = allocate; remainingQuantity -= allocate; } return allocation; } /// <summary> /// 为åé è·ååéçæ¡ç /// </summary> private (string barcode, decimal quantity) GetBarcodeForAllocation(Dictionary<string, decimal> barcodeAllocation, decimal requiredQuantity) { foreach (var (barcode, quantity) in barcodeAllocation) { if (quantity >= requiredQuantity) { return (barcode, requiredQuantity); } } // 妿å个æ¡ç æ°éä¸è¶³ï¼ä½¿ç¨ç¬¬ä¸ä¸ªæ¡ç var first = barcodeAllocation.First(); return (first.Key, Math.Min(first.Value, requiredQuantity)); } /// <summary> /// æ´æ°æ¡ç åé è®°å½ /// </summary> private void UpdateBarcodeAllocation(Dictionary<string, decimal> barcodeAllocation, string barcode, decimal usedQuantity) { if (barcodeAllocation.ContainsKey(barcode)) { barcodeAllocation[barcode] -= usedQuantity; if (barcodeAllocation[barcode] <= 0) { barcodeAllocation.Remove(barcode); } } } /// <summary> /// åºåºåºååé åï¼æ´æ°æ°æ®åºæ°æ® /// </summary> ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs
@@ -1,4 +1,6 @@ using Microsoft.AspNetCore.Http; using Dm.filter; using MailKit.Search; using Microsoft.AspNetCore.Http; using SqlSugar; using System; using System.Collections.Generic; @@ -36,9 +38,10 @@ private readonly IOutboundOrderDetailService _outboundOrderDetailService; private readonly IOutboundOrderService _outboundOrderService; private readonly ISplitPackageService _splitPackageService; private readonly IRepository<Dt_Task> _taskRepository; public OutboundPickingService(IRepository<Dt_PickingRecord> BaseDal, IUnitOfWorkManage unitOfWorkManage, IStockInfoService stockInfoService, IStockService stockService, IOutStockLockInfoService outStockLockInfoService, IStockInfoDetailService stockInfoDetailService, ILocationInfoService locationInfoService, IOutboundOrderDetailService outboundOrderDetailService, ISplitPackageService splitPackageService, IOutboundOrderService outboundOrderService) : base(BaseDal) public OutboundPickingService(IRepository<Dt_PickingRecord> BaseDal, IUnitOfWorkManage unitOfWorkManage, IStockInfoService stockInfoService, IStockService stockService, IOutStockLockInfoService outStockLockInfoService, IStockInfoDetailService stockInfoDetailService, ILocationInfoService locationInfoService, IOutboundOrderDetailService outboundOrderDetailService, ISplitPackageService splitPackageService, IOutboundOrderService outboundOrderService, IRepository<Dt_Task> taskRepository) : base(BaseDal) { _unitOfWorkManage = unitOfWorkManage; _stockInfoService = stockInfoService; @@ -49,6 +52,7 @@ _outboundOrderDetailService = outboundOrderDetailService; _splitPackageService = splitPackageService; _outboundOrderService = outboundOrderService; _taskRepository = taskRepository; } @@ -114,8 +118,7 @@ } /// <summary> /// æ«ç æ£é确认 - ç®åçæ¬ /// åªå¤çå®é æ£éçåºåæ£å /// æ«ç æ£é确认 /// </summary> public async Task<WebResponseContent> ConfirmPicking(PickingConfirmRequest request) { @@ -221,19 +224,20 @@ if (stockDetail == null) return WebResponseContent.Instance.Error("æ æçæ¡ç æç©æç¼ç "); // 2. æ£æ¥åºåå¯ç¨æ°é var availableQty = stockDetail.StockQuantity - stockDetail.OutboundQuantity; if (availableQty <= 0) return WebResponseContent.Instance.Error("åºåæ°éä¸è¶³"); //// 2. æ£æ¥åºåå¯ç¨æ°é //var availableQty = stockDetail.StockQuantity - stockDetail.OutboundQuantity; //if (availableQty <= 0) // return WebResponseContent.Instance.Error("åºåæ°éä¸è¶³"); // 3. æ¥æ¾ç¸å ³çåºåºè¯¦æ ä¿¡æ¯ var outStockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() .Where(x => x.OrderNo == orderNo && x.PalletCode == palletCode && x.CurrentBarcode == barcode && x.Status == 0 && x.RemainQuantity > 0) x.Status == (int)OutLockStockStatusEnum.åºåºä¸ && x.AssignQuantity - x.PickedQty > 0) .FirstAsync(); if (outStockInfo == null) return WebResponseContent.Instance.Error("æªæ¾å°å¯¹åºçæ£éä¿¡æ¯æå·²æ£é宿"); @@ -244,36 +248,45 @@ // 5. æ´æ°åºåºè¯¦æ çå·²æ£éæ°é outStockInfo.PickedQty = outStockInfo.AssignQuantity; outStockInfo.Status = 1; outStockInfo.Status = (int)OutLockStockStatusEnum.å·²æ£é; await _outStockLockInfoService.Db.Updateable(outStockInfo).ExecuteCommandAsync(); // 6. æ´æ°åºååºåºæ°é await _stockInfoDetailService.Db.Updateable<Dt_StockInfoDetail>() .SetColumns(x => x.OutboundQuantity == x.OutboundQuantity + outStockInfo.AssignQuantity) .Where(x => x.Id == stockDetail.Id) .ExecuteCommandAsync(); //// 6. æ´æ°åºååºåºæ°é //await _stockInfoDetailService.Db.Updateable<Dt_StockInfoDetail>() // .SetColumns(x => x.OutboundQuantity == x.OutboundQuantity + outStockInfo.AssignQuantity) // .Where(x => x.Id == stockDetail.Id) // .ExecuteCommandAsync(); // 7. æ´æ°åºåºåæç» var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() .Where(x => x.Id == outStockInfo.OrderDetailId) .FirstAsync(); orderDetail.OverOutQuantity += outStockInfo.AssignQuantity; await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync(); if (orderDetail != null) { orderDetail.OverOutQuantity += outStockInfo.AssignQuantity; orderDetail.LockQuantity -= outStockInfo.AssignQuantity; await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync(); } // 8. æ£æ¥æ¯å¦å®æåºåº await CheckAndUpdateOrderStatus(orderNo); //æ¥è¯¢ä»»å¡è¡¨ var task = _taskRepository.QueryData(x => x.OrderNo == orderNo && x.PalletCode == palletCode).FirstOrDefault(); // 9. è®°å½æ£éåå² var pickingHistory = new Dt_PickingRecord { FactoryArea = outStockInfo.FactoryArea, TaskNo = task?.TaskNum ?? 0, LocationCode = task?.SourceAddress ?? "", StockId = stockDetail.Id, OrderNo = orderNo, OrderDetailId = orderDetail?.Id ?? 0, PalletCode = palletCode, Barcode = barcode, MaterielCode = outStockInfo.MaterielCode, PickQuantity = outStockInfo.AssignQuantity, PickTime = DateTime.Now, Operator = App.User.UserName, OutStockLockId = outStockInfo.Id }; await Db.Insertable(pickingHistory).ExecuteCommandAsync(); @@ -325,7 +338,7 @@ .Where(x => x.OrderNo == orderNo && x.PalletCode == palletCode && x.CurrentBarcode == barcode && x.Status == 1) x.Status == 2) .FirstAsync(); if (outStockInfo == null) @@ -333,14 +346,14 @@ // è¿ååºåºè¯¦æ ç¶æ outStockInfo.PickedQty = 0; outStockInfo.Status = 0; outStockInfo.Status = 1; await _outStockLockInfoService.Db.Updateable(outStockInfo).ExecuteCommandAsync(); // è¿ååºååºåºæ°é await _stockInfoDetailService.Db.Updateable<Dt_StockInfoDetail>() .SetColumns(x => x.OutboundQuantity == x.OutboundQuantity - outStockInfo.AssignQuantity) .Where(x => x.Barcode == barcode) .ExecuteCommandAsync(); //// è¿ååºååºåºæ°é //await _stockInfoDetailService.Db.Updateable<Dt_StockInfoDetail>() // .SetColumns(x => x.OutboundQuantity == x.OutboundQuantity - outStockInfo.AssignQuantity) // .Where(x => x.Barcode == barcode) // .ExecuteCommandAsync(); // è¿ååºåºåæç» var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() @@ -384,10 +397,9 @@ var list = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() .Where(x => x.OrderNo == orderNo && x.PalletCode == palletCode && x.Status == 0 && x.RemainQuantity > 0) x.Status == 1) .ToListAsync(); return list; return list.Where(x => x.RemainQuantity > 0).ToList(); } // è·åå·²æ£éå表 @@ -396,26 +408,68 @@ var list = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() .Where(x => x.OrderNo == orderNo && x.PalletCode == palletCode && x.Status == 1) x.Status == 2) .ToListAsync(); return list; } // è·åæ£éæ±æ» public async Task<object> GetPickingSummary(string orderNo) public async Task<object> GetPickingSummary(string orderNo, string palletCode) { var summary = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() .Where(x => x.OrderNo == orderNo && x.Status == 0) .Where(x => x.OrderNo == orderNo && x.PalletCode == palletCode && x.Status == 1) .GroupBy(x => new { x.PalletCode, x.MaterielCode }) .Select(x => new { PalletCode = x.PalletCode, MaterielCode = x.MaterielCode, UnpickedCount = SqlFunc.AggregateCount(x.Id), UnpickedQuantity = SqlFunc.AggregateSum(x.RemainQuantity) UnpickedQuantity = SqlFunc.AggregateSum(x.AssignQuantity) - SqlFunc.AggregateSum(x.PickedQty) }) .ToListAsync(); .FirstAsync(); return summary; return summary; } // è·åæ£éæ±æ» public async Task<object> GetPickingSummary(ConfirmPickingDto dto) { var picked = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() .WhereIF(!string.IsNullOrEmpty(dto.OrderNo), x => x.OrderNo == dto.OrderNo) .WhereIF(!string.IsNullOrEmpty(dto.PalletCode), x => x.PalletCode == dto.PalletCode) .Where(x => x.Status == 2) .GroupBy(x => new { x.PalletCode, x.MaterielCode }) .Select(x => new SummaryPickingDto { PalletCode = x.PalletCode, MaterielCode = x.MaterielCode, pickedCount = SqlFunc.AggregateCount(x.Id) }).FirstAsync(); if (picked == null) { picked = new SummaryPickingDto { pickedCount = 0 }; } var summary = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() .WhereIF(!string.IsNullOrEmpty(dto.OrderNo), x => x.OrderNo == dto.OrderNo) .WhereIF(!string.IsNullOrEmpty(dto.PalletCode), x => x.PalletCode == dto.PalletCode) .Where(x => x.Status == 1) .GroupBy(x => new { x.PalletCode, x.MaterielCode }) .Select(x => new SummaryPickingDto { PalletCode = x.PalletCode, MaterielCode = x.MaterielCode, UnpickedCount = SqlFunc.AggregateCount(x.Id), UnpickedQuantity = SqlFunc.AggregateSum(x.AssignQuantity) - SqlFunc.AggregateSum(x.PickedQty), }).FirstAsync(); if (summary == null) { summary = new SummaryPickingDto { pickedCount = 0 }; } summary.pickedCount = picked.pickedCount; return summary; } /// <summary> /// è·åæ£éåå² @@ -587,50 +641,59 @@ { _unitOfWorkManage.BeginTran(); // 1. è·åæçåºåä¿¡æ¯ var stockInfo = await _stockInfoService.Db.Queryable<Dt_StockInfo>() .Includes(x => x.Details) .Where(x => x.PalletCode == request.PalletCode) .FirstAsync(); .Where(x => x.PalletCode == request.PalletCode).FirstAsync(); if (stockInfo == null) return WebResponseContent.Instance.Error("æªæ¾å°æçåºåä¿¡æ¯"); // 2. è·åç¸å ³çåºåºéå®ä¿¡æ¯ var lockInfos = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() .Where(x => x.PalletCode == request.PalletCode && x.Status == (int)OutLockStockStatusEnum.åºåºä¸) .Where(x => x.OrderNo == request.OrderNo && x.PalletCode == request.PalletCode) .ToListAsync(); // 3. æ´ä¸ªæçåºåº - 设置åºåºæ°éçäºåºåæ°é foreach (var detail in stockInfo.Details) { decimal outboundQuantity = detail.StockQuantity - detail.OutboundQuantity; detail.OutboundQuantity = detail.StockQuantity; // å ¨é¨åºåº await _stockInfoDetailService.Db.Updateable(detail).ExecuteCommandAsync(); } // 4. æ´æ°åºåºéå®ä¿¡æ¯ foreach (var lockInfo in lockInfos) { decimal unpicked = lockInfo.AssignQuantity - lockInfo.PickedQty; lockInfo.PickedQty += unpicked; // æ è®°ä¸ºå ¨é¨æ£é if (lockInfo.Status == (int)OutLockStockStatusEnum.åºåºä¸) { lockInfo.PickedQty = lockInfo.AssignQuantity; } lockInfo.Status = (int)OutLockStockStatusEnum.å·²åºåº; await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync(); // æ´æ°åºåºåæç» var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() .Where(x => x.Id == lockInfo.OrderDetailId) .FirstAsync(); orderDetail.OverOutQuantity += unpicked; orderDetail.LockQuantity -= unpicked; orderDetail.OrderDetailStatus = (int)OrderDetailStatusEnum.Over; orderDetail.LockQuantity = 0; await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync(); .Where(x => x.Id == lockInfo.OrderDetailId) .FirstAsync(); if (orderDetail != null) { orderDetail.OverOutQuantity += lockInfo.PickedQty; orderDetail.LockQuantity -= lockInfo.PickedQty; orderDetail.OrderDetailStatus = (int)OrderDetailStatusEnum.Over; orderDetail.LockQuantity = 0; await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync(); } } var groupDetails = lockInfos.GroupBy(x => x.OrderDetailId).Select(x => new { OrderDetailId = x.Key, TotalQuantity = x.Sum(o => o.PickedQty) }).ToList(); foreach (var item in groupDetails) { var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>().Where(x => x.Id == item.OrderDetailId).FirstAsync(); if (orderDetail != null) { orderDetail.OverOutQuantity = item.TotalQuantity; orderDetail.LockQuantity = 0; orderDetail.OrderDetailStatus = (int)OrderDetailStatusEnum.Over; await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync(); } } // 5. æ´æ°æå è®°å½ç¶æ await CheckAndUpdateOrderStatus(request.OrderNo); var lockInfoIds = lockInfos.Select(x => x.Id).ToList(); var splitRecords = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>() .Where(x => lockInfoIds.Contains(x.OutStockLockInfoId) && @@ -643,7 +706,7 @@ await _splitPackageService.Db.Updateable(record).ExecuteCommandAsync(); } // 6. æ¸ ç©ºè´§ä½ var location = await _locationInfoService.Db.Queryable<Dt_LocationInfo>() .Where(x => x.LocationCode == stockInfo.LocationCode) .FirstAsync(); @@ -653,6 +716,14 @@ await _locationInfoService.Db.Updateable(location).ExecuteCommandAsync(); } foreach (var detail in stockInfo.Details) { await _stockInfoDetailService.Db.Deleteable(detail).ExecuteCommandAsync(); } await _stockInfoService.Db.Deleteable(stockInfo).ExecuteCommandAsync(); _unitOfWorkManage.CommitTran(); return WebResponseContent.Instance.OK("ç´æ¥åºåºæå"); } ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_OutboundService/SplitPackageService.cs
@@ -9,6 +9,7 @@ using WIDESEA_Core.BaseRepository; using WIDESEA_Core.BaseServices; using WIDESEA_DTO.Outbound; using WIDESEA_IBasicService; using WIDESEA_IOutboundService; using WIDESEA_IStockService; using WIDESEA_Model.Models; @@ -23,13 +24,15 @@ private readonly IStockInfoService _stockInfoService; private readonly IStockInfoDetailService _stockInfoDetailService; private readonly IOutStockLockInfoService _outStockLockInfoService; private readonly IDailySequenceService _dailySequenceService; public SplitPackageService(IRepository<Dt_SplitPackageRecord> BaseDal, IUnitOfWorkManage unitOfWorkManage, IStockInfoService stockInfoService, IOutStockLockInfoService outStockLockInfoService, IStockInfoDetailService stockInfoDetailService) : base(BaseDal) public SplitPackageService(IRepository<Dt_SplitPackageRecord> BaseDal, IUnitOfWorkManage unitOfWorkManage, IStockInfoService stockInfoService, IOutStockLockInfoService outStockLockInfoService, IStockInfoDetailService stockInfoDetailService, IDailySequenceService dailySequenceService) : base(BaseDal) { _unitOfWorkManage = unitOfWorkManage; _stockInfoService = stockInfoService; _outStockLockInfoService = outStockLockInfoService; _stockInfoDetailService = stockInfoDetailService; _dailySequenceService = dailySequenceService; } /// <summary> @@ -42,16 +45,16 @@ _unitOfWorkManage.BeginTran(); // 1. éªè¯åºåºéå®ä¿¡æ¯ var lockInfo = await _stockInfoDetailService.Db.Queryable<Dt_OutStockLockInfo>() var lockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() .Where(x => x.OrderNo == request.OrderNo && x.PalletCode == request.PalletCode && x.CurrentBarcode == request.OriginalBarcode && x.Status == 0) x.Status == 1) .FirstAsync(); if (lockInfo == null) return WebResponseContent.Instance.Error("æªæ¾å°ææçåºåºéå®ä¿¡æ¯"); // 2. æ£æ¥å©ä½é宿°é decimal remainingLockQuantity = lockInfo.AssignQuantity - lockInfo.PickedQty; if (request.SplitQuantity > remainingLockQuantity) @@ -61,12 +64,14 @@ .Where(x => x.Barcode == request.OriginalBarcode) .FirstAsync(); var seq = await _dailySequenceService.GetNextSequenceAsync(); // 3. çææ°æ¡ç string newBarcode = ""; string newBarcode = "WSLOT" + DateTime.Now.ToString("yyyyMMdd") + seq.ToString()?.PadLeft(5, '0'); // 4. å建æ°çåºåºéå®ä¿¡æ¯ï¼æ°æ¡ç ï¼ var newLockInfo = new Dt_OutStockLockInfo { OrderNo = lockInfo.OrderNo, OrderDetailId = lockInfo.OrderDetailId, BatchNo = lockInfo.BatchNo, @@ -82,22 +87,28 @@ TaskNum = lockInfo.TaskNum, Status = (int)OutLockStockStatusEnum.åºåºä¸, Unit = lockInfo.Unit, SupplyCode = lockInfo.SupplyCode, OrderType=lockInfo.OrderType, CurrentBarcode = newBarcode, // æ°æ¡ç OriginalLockQuantity = request.SplitQuantity, IsSplitted = 1, ParentLockId = lockInfo.Id // è®°å½ç¶çº§éå®ID }; await Db.Insertable(newLockInfo).ExecuteCommandAsync(); await _outStockLockInfoService.Db.Insertable(newLockInfo).ExecuteCommandAsync(); // 5. æ´æ°åéå®ä¿¡æ¯çåé æ°éï¼åå°æå æ°éï¼ lockInfo.AssignQuantity -= request.SplitQuantity; await Db.Updateable(lockInfo).ExecuteCommandAsync(); await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync(); // 6. è®°å½æå åå²ï¼ç¨äºè¿½è¸ªï¼ var splitHistory = new Dt_SplitPackageRecord { FactoryArea = lockInfo.FactoryArea, TaskNum=lockInfo.TaskNum, OutStockLockInfoId = lockInfo.Id, StockId = stockDetail?.StockId ?? 0, Operator = App.User.UserName, IsReverted = false, OriginalBarcode = lockInfo.CurrentBarcode, NewBarcode = newBarcode, SplitQty = request.SplitQuantity, @@ -110,10 +121,10 @@ }; await Db.Insertable(splitHistory).ExecuteCommandAsync(); Db.Ado.CommitTran(); _unitOfWorkManage.CommitTran(); // 7. åä¼ æ°æ¡ç ç»MES // await SendBarcodeToMES(newBarcode, request.MaterielCode, request.SplitQuantity); // await SendBarcodeToMES(newBarcode, request.MaterielCode, request.SplitQuantity); return WebResponseContent.Instance.OK("æå æå", new { @@ -123,7 +134,7 @@ } catch (Exception ex) { Db.Ado.RollbackTran(); _unitOfWorkManage.RollbackTran(); return WebResponseContent.Instance.Error($"æå 失败: {ex.Message}"); } } @@ -140,66 +151,67 @@ .OrderByDescending(x => x.CreateDate) .FirstAsync(); if (splitPackage == null) return WebResponseContent.Instance.Error("æªæ¾å°æå è®°å½"); if (splitPackage == null) return WebResponseContent.Instance.Error("æªæ¾å°æå è®°å½"); // æ£æ¥æ°æ¡ç æ¯å¦å·²æ£é var newOutStockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() .Where(x => x.CurrentBarcode == splitPackage.NewBarcode) .FirstAsync(); // æ£æ¥æ°æ¡ç æ¯å¦å·²æ£é var newOutStockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() .Where(x => x.CurrentBarcode == splitPackage.NewBarcode) .FirstAsync(); if (newOutStockInfo.Status == 1) return WebResponseContent.Instance.Error("æ°æ¡ç å·²æ£éï¼æ æ³æ¤éæå "); if (newOutStockInfo.Status == 2) return WebResponseContent.Instance.Error("æ°æ¡ç å·²æ£éï¼æ æ³æ¤éæå "); // è¿åååºåºè¯¦æ æ°é var originalOutStockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() .Where(x => x.CurrentBarcode == originalBarcode) .FirstAsync(); // è¿åååºåºè¯¦æ æ°é var originalOutStockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() .Where(x => x.CurrentBarcode == originalBarcode) .FirstAsync(); originalOutStockInfo.AssignQuantity += splitPackage.SplitQty; await _outStockLockInfoService.Db.Updateable(originalOutStockInfo).ExecuteCommandAsync(); originalOutStockInfo.AssignQuantity += splitPackage.SplitQty; await _outStockLockInfoService.Db.Updateable(originalOutStockInfo).ExecuteCommandAsync(); // å 餿°åºåºè¯¦æ è®°å½ await _outStockLockInfoService.Db.Deleteable<Dt_OutStockLockInfo>() .Where(x => x.CurrentBarcode == splitPackage.NewBarcode) .ExecuteCommandAsync(); // å 餿°åºåºè¯¦æ è®°å½ await _outStockLockInfoService.Db.Deleteable<Dt_OutStockLockInfo>() .Where(x => x.CurrentBarcode == splitPackage.NewBarcode) .ExecuteCommandAsync(); // æ è®°æå è®°å½ä¸ºå·²æ¤é splitPackage.IsReverted = true; await Db.Updateable(splitPackage).ExecuteCommandAsync(); // æ è®°æå è®°å½ä¸ºå·²æ¤é splitPackage.IsReverted = true; await Db.Updateable(splitPackage).ExecuteCommandAsync(); _unitOfWorkManage.CommitTran(); return WebResponseContent.Instance.OK("æ¤éæå æå"); return WebResponseContent.Instance.OK("æ¤éæå æå"); } catch (Exception ex) { return WebResponseContent.Instance.Error($"æ¤éæå 失败ï¼{ex.Message}"); _unitOfWorkManage.RollbackTran(); return WebResponseContent.Instance.Error($"æ¤éæå 失败ï¼{ex.Message}"); } } // è·åæå ä¿¡æ¯ public async Task< WebResponseContent > GetSplitPackageInfo(string orderNo, string palletCode, string barcode) public async Task<WebResponseContent> GetSplitPackageInfo(string orderNo, string palletCode, string barcode) { var outStockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() .Where(x => x.OrderNo == orderNo && x.PalletCode == palletCode && x.CurrentBarcode == barcode && x.Status == 0) x.Status == 1) .FirstAsync(); if (outStockInfo == null) return WebResponseContent.Instance .Error("æªæ¾å°å¯¹åºçåºåºä¿¡æ¯"); return WebResponseContent.Instance.Error("æªæ¾å°å¯¹åºçåºåºä¿¡æ¯"); var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() .Where(x => x.Barcode == barcode) .FirstAsync(); //var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() // .Where(x => x.Barcode == barcode) // .FirstAsync(); return WebResponseContent.Instance .OK("",new return WebResponseContent.Instance.OK("", new { MaterielCode = outStockInfo.MaterielCode, RemainQuantity = outStockInfo.RemainQuantity, Unit = "个" // æ ¹æ®å®é æ åµè·ååä½ Unit = outStockInfo.Unit }); } /// <summary> ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_StockService/StockInfoService.cs
@@ -113,7 +113,7 @@ if (stockTotalQuantity < needQuantity) { residueQuantity = needQuantity - stockTotalQuantity; // 䏿åºå¼å¸¸ï¼å 许é¨ååé } else { ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs
@@ -108,6 +108,7 @@ _outStockLockInfoService = outStockLockInfoService; } /// <summary> /// /// </summary> ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService_Inbound.cs
@@ -70,7 +70,8 @@ TaskStatus = TaskStatusEnum.New.ObjToInt(), WarehouseId = stockInfo.WarehouseId, PalletType = stockInfo.PalletType, OrderNo= stockInfo.Details.FirstOrDefault()?.OrderNo }; //空箱 if (stockInfo.PalletType == PalletTypeEnum.Empty.ObjToInt()) ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService_Outbound.cs
@@ -164,7 +164,7 @@ tasks = GetTasks(result.Item1, typeEnum); tasks.ForEach(x => { x.OrderNo = outboundOrder.UpperOrderNo; x.OrderNo = outboundOrder.OrderNo; }); result.Item2.ForEach(x => { @@ -331,7 +331,7 @@ // TaskNum = BaseDal.GetTaskNum(nameof(SequenceEnum.SeqTaskNum)), PalletType = stockInfo.PalletType, WarehouseId = stockInfo.WarehouseId, }; //if (taskType != TaskTypeEnum.OutEmpty) //{ ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Inbound/InboundOrderController.cs
@@ -50,13 +50,14 @@ [HttpPost, Route("Test"), AllowAnonymous, MethodParamsValidate] public async Task<WebResponseContent> Test() { var purchaseToStockResult = await _materialUnitService.ConvertPurchaseToStockAsync("101001-00002", 10); // var purchaseToStockResult = await _materialUnitService.ConvertPurchaseToStockAsync("101001-00002", 10); var pdddurchaseToStockResult = await _materialUnitService.ConvertPurchaseToStockAsync("100513-00210", 10); // var pdddurchaseToStockResult = await _materialUnitService.ConvertPurchaseToStockAsync("100513-00210", 10); var sddd = _locationInfoService.AssignLocation(); var code = sddd.LocationCode; // await _dailySequenceService.GetNextSequenceAsync(); //var ssss=await _dailySequenceService.GetNextSequenceAsync(); //var ddddssss = "WSLOT" + DateTime.Now.ToString("yyyyMMddHHmmss") + ssss.ToString().PadLeft(5, '0'); //erpApiService.GetSuppliersAsync(); //erpApiService.GetMaterialUnitAsync(); ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Outbound/OutboundPickingController.cs
@@ -23,7 +23,7 @@ /// <summary> /// è·åæççåºåºç¶æ /// </summary> [HttpGet("GetPalletOutboundStatus")] [HttpPost("GetPalletOutboundStatus")] public async Task<WebResponseContent> GetPalletOutboundStatus(string palletCode) { return await Service.GetPalletOutboundStatus(palletCode); @@ -32,7 +32,7 @@ /// <summary> /// è·åæççéå®ä¿¡æ¯ /// </summary> [HttpGet("GetPalletLockInfos")] [HttpPost("GetPalletLockInfos")] public async Task<WebResponseContent> GetPalletLockInfos(string palletCode) { var lockInfos = await _outStockLockInfoService.GetPalletLockInfos(palletCode); @@ -41,17 +41,17 @@ [HttpGet("unpicked-list")] public async Task<WebResponseContent> GetUnpickedList(string orderNo, string palletCode) [HttpPost("unpicked-list")] public async Task<WebResponseContent> GetUnpickedList([FromBody] ConfirmPickingDto dto) { var lists= await Service.GetUnpickedList(orderNo, palletCode); var lists= await Service.GetUnpickedList(dto.OrderNo, dto.PalletCode); return WebResponseContent.Instance.OK("", lists); } [HttpGet("picked-list")] public async Task<WebResponseContent> GetPickedList(string orderNo, string palletCode) [HttpPost("picked-list")] public async Task<WebResponseContent> GetPickedList([FromBody] ConfirmPickingDto dto) { var lists = await Service.GetPickedList(orderNo, palletCode); var lists = await Service.GetPickedList(dto.OrderNo, dto.PalletCode); return WebResponseContent.Instance.OK("", lists); } @@ -61,11 +61,48 @@ return await Service.ConfirmPicking(dto.OrderNo, dto.PalletCode, dto.Barcode); } [HttpGet("picking-summary")] public async Task<WebResponseContent> GetPickingSummary(string orderNo) [HttpPost("picking-summary")] public async Task<WebResponseContent> GetPickingSummary([FromBody] ConfirmPickingDto dto) { var data = await Service.GetPickingSummary(orderNo); var data = await Service.GetPickingSummary(dto); return WebResponseContent.Instance.OK("", data); } [HttpPost("split-package")] public async Task<WebResponseContent> SplitPackage([FromBody] SplitPackageDto dto) { return await _splitPackageService.SplitPackage(dto); } [HttpPost("revert-split-package")] public async Task<WebResponseContent> RevertSplitPackage([FromBody] RevertSplitDto dto) { return await _splitPackageService.RevertSplitPackage(dto.OriginalBarcode); } [HttpPost("split-package-info")] public async Task<WebResponseContent> GetSplitPackageInfo([FromBody] ConfirmPickingDto dto) { return await _splitPackageService.GetSplitPackageInfo(dto.OrderNo, dto.PalletCode, dto.Barcode); } [HttpPost("return-to-stock")] public async Task<WebResponseContent> ReturnToStock( ) { var data= ""; return WebResponseContent.Instance.OK("", data); } [HttpPost("direct-outbound")] public async Task<WebResponseContent> DirectOutbound([FromBody] DirectOutboundRequest dto) { return await Service.DirectOutbound(dto); } ///// <summary> @@ -84,14 +121,7 @@ { return await Service.ValidateBarcode(barcode); } /// <summary> /// æå æä½ /// </summary> [HttpPost("SplitPackage")] public async Task<WebResponseContent> SplitPackage([FromBody] SplitPackageDto request) { return await _splitPackageService.SplitPackage(request); } ///// <summary> ///// ç´æ¥åºåº @@ -116,9 +146,9 @@ /// æ¤éæ£é /// </summary> [HttpPost("CancelPicking")] public async Task<WebResponseContent> CancelPicking([FromBody] CancelPickingRequest request) public async Task<WebResponseContent> CancelPicking([FromBody] ConfirmPickingDto dto) { return await Service.CancelPicking(request); return await Service.CancelPicking(dto.OrderNo,dto.PalletCode,dto.Barcode); } } } ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/TaskInfo/TaskController.cs
@@ -24,6 +24,7 @@ { } [HttpPost, Route("PalletOutboundTask"), AllowAnonymous, MethodParamsValidate] public async Task<WebResponseContent> PalletOutboundTask(string endStation, string palletCode = "")