Merge branch 'master' of http://115.159.85.185:8098/r/ZhongRui/ALDbanyunxiangmu
| | |
| | | width: 90, |
| | | }, |
| | | { |
| | | prop: "overOutQuantity", |
| | | title: "æªææ°é", |
| | | type: "string", |
| | | width: 90, |
| | | }, |
| | | { |
| | | prop: "unit", |
| | | title: "åä½", |
| | | type: "string", |
| | |
| | | |
| | | let wheres = [{ |
| | | 'name': 'orderType', |
| | | 'value': '0', |
| | | 'value': ['0','116'], |
| | | 'displayType': 'text' |
| | | }]; |
| | | |
| | |
| | | </div> |
| | | |
| | | <!-- æå
å¼¹çª --> |
| | | <div v-if="showCustomSplitDialog" class="custom-dialog-overlay"> |
| | | <div v-if="showCustomSplitDialog" class="custom-dialog-overlay" style="z-index: 2000;"> |
| | | <div class="custom-dialog-wrapper"> |
| | | <div class="custom-dialog"> |
| | | <div class="custom-dialog-header"> |
| | |
| | | </div> |
| | | |
| | | <!-- æ¤éæå
å¼¹çª --> |
| | | <div v-if="showRevertSplitDialog" class="custom-dialog-overlay"> |
| | | <div v-if="showRevertSplitDialog" class="custom-dialog-overlay" style="z-index: 2001;"> |
| | | <div class="custom-dialog-wrapper"> |
| | | <div class="custom-dialog"> |
| | | <div class="custom-dialog-header"> |
| | |
| | | </div> |
| | | |
| | | <!-- æå
é¾ä¿¡æ¯å¼¹çª --> |
| | | <div v-if="showSplitChainDialog" class="custom-dialog-overlay"> |
| | | <div v-if="showSplitChainDialog" class="custom-dialog-overlay" style="z-index: 2002;"> |
| | | <div class="custom-dialog-wrapper"> |
| | | <div class="custom-dialog" style="width: 750px;"> |
| | | <div class="custom-dialog-header"> |
| | |
| | | </div> |
| | | |
| | | <!-- æ¹éååºå¼¹çª --> |
| | | <div v-if="showBatchReturnDialog" class="custom-dialog-overlay"> |
| | | <div v-if="showBatchReturnDialog" class="custom-dialog-overlay" style="z-index: 2003;"> |
| | | <div class="custom-dialog-wrapper"> |
| | | <div class="custom-dialog"> |
| | | <div class="custom-dialog-header"> |
| | |
| | | </div> |
| | | |
| | | <!-- åèµ°ç©ºç®±å¼¹çª --> |
| | | <div v-if="showEmptyPalletDialog" class="custom-dialog-overlay"> |
| | | <div v-if="showEmptyPalletDialog" class="custom-dialog-overlay" style="z-index: 2004;"> |
| | | <div class="custom-dialog-wrapper"> |
| | | <div class="custom-dialog"> |
| | | <div class="custom-dialog-header"> |
| | |
| | | </div> |
| | | </template> |
| | | |
| | | |
| | | |
| | | <script> |
| | | import http from '@/api/http.js' |
| | | import { ref, defineComponent } from "vue"; |
| | | import { defineComponent } from "vue"; |
| | | import { ElMessage } from 'element-plus' |
| | | import { useRoute } from 'vue-router' |
| | | import printView from "@/extension/outbound/extend/printView.vue" |
| | | |
| | | export default defineComponent({ |
| | |
| | | components: {printView}, |
| | | data() { |
| | | return { |
| | | // ä¿æææåå§æ°æ®ç»æä¸å... |
| | | scanData: { |
| | | orderNo: '', |
| | | palletCode: '', |
| | |
| | | }, |
| | | palletStatus: 'æªç¥', |
| | | |
| | | // å¼¹çªç¶æ |
| | | // å¼¹çªç¶æ - å
³é®ä¿®å¤ï¼åªå
许ä¸ä¸ªå¼¹çªæå¼ |
| | | activeDialog: null, // 'split', 'revert', 'batchReturn', 'emptyPallet', 'splitChain' |
| | | showCustomSplitDialog: false, |
| | | showRevertSplitDialog: false, |
| | | showBatchReturnDialog: false, |
| | | showEmptyPalletDialog: false, |
| | | showSplitChainDialog: false, // æ°å¢ï¼æå
é¾ä¿¡æ¯å¼¹çª |
| | | showSplitChainDialog: false, |
| | | |
| | | // æ·»å é²éå¤ç¹å»æ å¿ |
| | | isOpeningDialog: false, |
| | | // å è½½ç¶æ |
| | | splitLoading: false, |
| | | revertSplitLoading: false, |
| | | batchReturnLoading: false, |
| | | emptypalletOutLoading: false, |
| | | splitChainLoading: false, // æ°å¢ï¼æå
é¾å è½½ç¶æ |
| | | splitChainLoading: false, |
| | | |
| | | // è¡¨åæ°æ® |
| | | // è¡¨åæ°æ®... |
| | | splitForm: { |
| | | orderNo: '', |
| | | palletCode: '', |
| | |
| | | palletCode: '' |
| | | }, |
| | | |
| | | // æ°å¢ï¼æå
é¾ç¸å
³æ°æ® |
| | | splitChainInfo: { |
| | | originalBarcode: '', |
| | | totalSplitTimes: 0, |
| | | splitChain: [] |
| | | }, |
| | | |
| | | // éªè¯è§å |
| | | // éªè¯è§å... |
| | | splitFormRules: { |
| | | originalBarcode: [ |
| | | { required: true, message: '请è¾å
¥åæ¡ç ', trigger: 'blur' } |
| | |
| | | isProcessing: false |
| | | } |
| | | }, |
| | | watch: { |
| | | // å
³é®ä¿®å¤ï¼ç¡®ä¿å䏿¶é´åªæä¸ä¸ªå¼¹çªæå¼ |
| | | activeDialog(newVal, oldVal) { |
| | | this.showCustomSplitDialog = newVal === 'split' |
| | | this.showRevertSplitDialog = newVal === 'revert' |
| | | this.showBatchReturnDialog = newVal === 'batchReturn' |
| | | this.showEmptyPalletDialog = newVal === 'emptyPallet' |
| | | this.showSplitChainDialog = newVal === 'splitChain' |
| | | } |
| | | }, |
| | | computed: { |
| | | // æ¯å¦å¯ä»¥åæ¶æ´ä¸ªæå
é¾ |
| | | canCancelWholeChain() { |
| | | return this.splitChainInfo.splitChain && |
| | | this.splitChainInfo.splitChain.some(item => !item.isReverted); |
| | |
| | | this.batchReturnForm.orderNo = this.$route.query.orderNo; |
| | | this.emptypalletOutForm.orderNo = this.$route.query.orderNo; |
| | | } |
| | | this.$nextTick(() => { |
| | | this.$refs.palletInput.focus(); |
| | | // ä½¿ç¨ requestAnimationFrame ç¡®ä¿é¡µé¢å®å
¨å è½½ |
| | | requestAnimationFrame(() => { |
| | | if (this.$refs.palletInput) { |
| | | this.$refs.palletInput.focus(); |
| | | } |
| | | }); |
| | | |
| | | }, |
| | | methods: { |
| | | goBack(){ |
| | |
| | | } |
| | | }, |
| | | |
| | | // æå
ç¸å
³æ¹æ³ |
| | | openSplitDialog() { |
| | | 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; |
| | | |
| | | // 1. å
³éææVueå¼¹çª |
| | | this.closeAllDialogs(); |
| | | |
| | | // 2. 强å¶ä»DOMä¸ç§»é¤ææå¼¹çª |
| | | setTimeout(() => { |
| | | const dialogs = document.querySelectorAll('.custom-dialog-overlay'); |
| | | dialogs.forEach(dialog => { |
| | | if (dialog.parentNode) { |
| | | dialog.parentNode.removeChild(dialog); |
| | | } |
| | | }); |
| | | |
| | | // 妿已ç»å卿å¨å¼¹çªï¼å
ç§»é¤ |
| | | if (this.manualDialog && this.manualDialog.parentNode) { |
| | | this.manualDialog.parentNode.removeChild(this.manualDialog); |
| | | } |
| | | |
| | | // 3. çå¾
ä¸å¸§ |
| | | requestAnimationFrame(() => { |
| | | // 4. ç´æ¥å建æ°å¼¹çªï¼ä¸ä¾èµVueçååºå¼ç³»ç» |
| | | this.createManualSplitDialog(); |
| | | }); |
| | | }, 10); |
| | | }, |
| | | |
| | | // å建æå¨æå
å¼¹çª |
| | | createManualSplitDialog() { |
| | | const newDialog = document.createElement('div'); |
| | | newDialog.className = 'custom-dialog-overlay emergency-fix'; |
| | | |
| | | // çæéæºIDç¨äºäºä»¶ç»å® |
| | | const dialogId = 'manual-dialog-' + Date.now(); |
| | | newDialog.id = dialogId; |
| | | |
| | | // åå¨å¼ç¨ |
| | | this.manualDialog = newDialog; |
| | | |
| | | // å¼¹çªå
容 |
| | | newDialog.innerHTML = ` |
| | | <div class="custom-dialog-wrapper"> |
| | | <div class="custom-dialog" style="width: 500px;"> |
| | | <div class="custom-dialog-header"> |
| | | <h3 style="margin: 0; color: #303133;">æå
æä½</h3> |
| | | <button class="close-button" onclick="document.getElementById('${dialogId}').remove()" style=" |
| | | font-size: 18px; |
| | | color: #909399; |
| | | padding: 0; |
| | | width: 24px; |
| | | height: 24px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | background: none; |
| | | border: none; |
| | | cursor: pointer; |
| | | ">Ã</button> |
| | | </div> |
| | | <div class="custom-dialog-body" style="padding: 20px;"> |
| | | <div style="margin-bottom: 15px;"> |
| | | <div style="display: flex; align-items: center; margin-bottom: 5px;"> |
| | | <span style="width: 100px; text-align: right; padding-right: 12px; color: #606266;">订åç¼å·:</span> |
| | | <input type="text" value="${this.scanData.orderNo}" disabled style=" |
| | | flex: 1; |
| | | padding: 8px 12px; |
| | | border: 1px solid #dcdfe6; |
| | | border-radius: 4px; |
| | | background-color: #f5f7fa; |
| | | color: #909399; |
| | | "> |
| | | </div> |
| | | </div> |
| | | |
| | | <div style="margin-bottom: 15px;"> |
| | | <div style="display: flex; align-items: center; margin-bottom: 5px;"> |
| | | <span style="width: 100px; text-align: right; padding-right: 12px; color: #606266;">æçç¼å·:</span> |
| | | <input type="text" value="${this.scanData.palletCode}" disabled style=" |
| | | flex: 1; |
| | | padding: 8px 12px; |
| | | border: 1px solid #dcdfe6; |
| | | border-radius: 4px; |
| | | background-color: #f5f7fa; |
| | | color: #909399; |
| | | "> |
| | | </div> |
| | | </div> |
| | | |
| | | <div style="margin-bottom: 15px;"> |
| | | <div style="display: flex; align-items: center; margin-bottom: 5px;"> |
| | | <span style="width: 100px; text-align: right; padding-right: 12px; color: #606266;">åæ¡ç :</span> |
| | | <div style="flex: 1; display: flex; align-items: center; gap: 10px;"> |
| | | <input type="text" id="${dialogId}-barcode" placeholder="æ«æåæ¡ç " style=" |
| | | flex: 1; |
| | | padding: 8px 12px; |
| | | border: 1px solid #dcdfe6; |
| | | border-radius: 4px; |
| | | "> |
| | | <button id="${dialogId}-viewChain" style=" |
| | | padding: 8px 16px; |
| | | background: #409eff; |
| | | color: white; |
| | | border: none; |
| | | border-radius: 4px; |
| | | cursor: pointer; |
| | | white-space: nowrap; |
| | | ">æ¥çæå
é¾</button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div style="margin-bottom: 15px;"> |
| | | <div style="display: flex; align-items: center; margin-bottom: 5px;"> |
| | | <span style="width: 100px; text-align: right; padding-right: 12px; color: #606266;">ç©æç¼ç :</span> |
| | | <input type="text" id="${dialogId}-materiel" disabled style=" |
| | | flex: 1; |
| | | padding: 8px 12px; |
| | | border: 1px solid #dcdfe6; |
| | | border-radius: 4px; |
| | | background-color: #f5f7fa; |
| | | color: #909399; |
| | | "> |
| | | </div> |
| | | </div> |
| | | |
| | | <div style="margin-bottom: 15px;"> |
| | | <div style="display: flex; align-items: center; margin-bottom: 5px;"> |
| | | <span style="width: 100px; text-align: right; padding-right: 12px; color: #606266;">å©ä½æ°é:</span> |
| | | <input type="text" id="${dialogId}-remain" disabled style=" |
| | | flex: 1; |
| | | padding: 8px 12px; |
| | | border: 1px solid #dcdfe6; |
| | | border-radius: 4px; |
| | | background-color: #f5f7fa; |
| | | color: #909399; |
| | | "> |
| | | </div> |
| | | </div> |
| | | |
| | | <div style="margin-bottom: 15px;"> |
| | | <div style="display: flex; align-items: center; margin-bottom: 5px;"> |
| | | <span style="width: 100px; text-align: right; padding-right: 12px; color: #606266;">æå
æ°é:</span> |
| | | <div style="flex: 1;"> |
| | | <input type="number" id="${dialogId}-splitQty" value="1" min="0.01" step="0.01" style=" |
| | | width: 100%; |
| | | padding: 8px 12px; |
| | | border: 1px solid #dcdfe6; |
| | | border-radius: 4px; |
| | | "> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="custom-dialog-footer" style=" |
| | | padding: 10px 20px 20px; |
| | | text-align: right; |
| | | border-top: 1px solid #ebeef5; |
| | | "> |
| | | <button id="${dialogId}-cancel" style=" |
| | | padding: 9px 15px; |
| | | background: white; |
| | | color: #606266; |
| | | border: 1px solid #dcdfe6; |
| | | border-radius: 4px; |
| | | cursor: pointer; |
| | | margin-right: 10px; |
| | | ">åæ¶</button> |
| | | <button id="${dialogId}-confirm" style=" |
| | | padding: 9px 15px; |
| | | background: #409eff; |
| | | color: white; |
| | | border: none; |
| | | border-radius: 4px; |
| | | cursor: pointer; |
| | | ">确认æå
</button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | `; |
| | | |
| | | // æ·»å æ ·å¼ |
| | | newDialog.style.cssText = ` |
| | | position: fixed; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background: rgba(0,0,0,0.5); |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | z-index: 999999; |
| | | `; |
| | | |
| | | // å¼¹çªå®¹å¨æ ·å¼ |
| | | const wrapper = newDialog.querySelector('.custom-dialog-wrapper'); |
| | | if (wrapper) { |
| | | wrapper.style.position = 'relative'; |
| | | wrapper.style.zIndex = '1000000'; |
| | | } |
| | | |
| | | // å¼¹çªå
å®¹æ ·å¼ |
| | | const dialog = newDialog.querySelector('.custom-dialog'); |
| | | if (dialog) { |
| | | dialog.style.background = 'white'; |
| | | dialog.style.borderRadius = '4px'; |
| | | dialog.style.maxWidth = '90vw'; |
| | | dialog.style.maxHeight = '90vh'; |
| | | dialog.style.boxShadow = '0 2px 12px 0 rgba(0, 0, 0, 0.1)'; |
| | | dialog.style.overflow = 'auto'; |
| | | } |
| | | |
| | | // å¼¹çªå¤´é¨æ ·å¼ |
| | | const header = newDialog.querySelector('.custom-dialog-header'); |
| | | if (header) { |
| | | header.style.display = 'flex'; |
| | | header.style.justifyContent = 'space-between'; |
| | | header.style.alignItems = 'center'; |
| | | header.style.padding = '20px 20px 10px'; |
| | | header.style.borderBottom = '1px solid #ebeef5'; |
| | | } |
| | | |
| | | document.body.appendChild(newDialog); |
| | | console.log('ç´§æ¥å¼¹çªå·²å建'); |
| | | |
| | | // ç»å®äºä»¶ |
| | | this.bindManualDialogEvents(dialogId); |
| | | |
| | | // èªå¨èç¦å°æ¡ç è¾å
¥æ¡ |
| | | setTimeout(() => { |
| | | const barcodeInput = document.getElementById(`${dialogId}-barcode`); |
| | | if (barcodeInput) { |
| | | barcodeInput.focus(); |
| | | // æ·»å å车é®çå¬ |
| | | barcodeInput.addEventListener('keyup', (event) => { |
| | | if (event.key === 'Enter') { |
| | | this.onManualSplitBarcodeScan(dialogId); |
| | | } |
| | | }); |
| | | } |
| | | }, 100); |
| | | }, |
| | | |
| | | // ç»å®æå¨å¼¹çªäºä»¶ |
| | | bindManualDialogEvents(dialogId) { |
| | | const vm = this; // ä¿åVueå®ä¾å¼ç¨ |
| | | |
| | | // æ¥çæå
é¾æé® |
| | | const viewChainBtn = document.getElementById(`${dialogId}-viewChain`); |
| | | if (viewChainBtn) { |
| | | viewChainBtn.onclick = () => { |
| | | const barcodeInput = document.getElementById(`${dialogId}-barcode`); |
| | | if (barcodeInput && barcodeInput.value.trim()) { |
| | | vm.viewSplitChainFromManualDialog(barcodeInput.value.trim(), dialogId); |
| | | } else { |
| | | ElMessage.warning('请å
è¾å
¥æ¡ç '); |
| | | } |
| | | }; |
| | | } |
| | | |
| | | // åæ¶æé® |
| | | const cancelBtn = document.getElementById(`${dialogId}-cancel`); |
| | | if (cancelBtn) { |
| | | cancelBtn.onclick = () => { |
| | | const dialog = document.getElementById(dialogId); |
| | | if (dialog && dialog.parentNode) { |
| | | dialog.parentNode.removeChild(dialog); |
| | | } |
| | | }; |
| | | } |
| | | |
| | | // 确认æå
æé® |
| | | const confirmBtn = document.getElementById(`${dialogId}-confirm`); |
| | | if (confirmBtn) { |
| | | confirmBtn.onclick = () => { |
| | | vm.handleManualSplitPackage(dialogId); |
| | | }; |
| | | } |
| | | |
| | | // æ¡ç è¾å
¥æ¡ååäºä»¶ |
| | | const barcodeInput = document.getElementById(`${dialogId}-barcode`); |
| | | if (barcodeInput) { |
| | | // 鲿å¤ç |
| | | let timeout; |
| | | barcodeInput.addEventListener('input', () => { |
| | | clearTimeout(timeout); |
| | | timeout = setTimeout(() => { |
| | | if (barcodeInput.value.trim()) { |
| | | vm.onManualSplitBarcodeScan(dialogId); |
| | | } |
| | | }, 500); |
| | | }); |
| | | } |
| | | }, |
| | | |
| | | // æå¨å¼¹çªçæ¡ç æ«æå¤ç |
| | | async onManualSplitBarcodeScan(dialogId) { |
| | | const barcodeInput = document.getElementById(`${dialogId}-barcode`); |
| | | if (!barcodeInput || !barcodeInput.value.trim()) return; |
| | | |
| | | const barcode = barcodeInput.value.trim(); |
| | | |
| | | try { |
| | | const res = await http.post('/api/OutboundBatchPicking/split-package-info', { |
| | | orderNo: this.scanData.orderNo, |
| | | palletCode: this.scanData.palletCode, |
| | | barcode: barcode |
| | | }); |
| | | |
| | | if (res.status) { |
| | | // æ´æ°ç©æç¼ç |
| | | const materielInput = document.getElementById(`${dialogId}-materiel`); |
| | | if (materielInput) { |
| | | materielInput.value = res.data.materielCode || ''; |
| | | } |
| | | |
| | | // æ´æ°å©ä½æ°é |
| | | const remainInput = document.getElementById(`${dialogId}-remain`); |
| | | if (remainInput) { |
| | | remainInput.value = res.data.remainQuantity || 0; |
| | | } |
| | | |
| | | // æ´æ°æå
æ°éï¼é»è®¤ä¸º1ï¼ä¸è¶
è¿å©ä½æ°éï¼ |
| | | const splitQtyInput = document.getElementById(`${dialogId}-splitQty`); |
| | | if (splitQtyInput) { |
| | | const maxQty = res.data.remainQuantity || 0; |
| | | splitQtyInput.max = maxQty; |
| | | const currentVal = parseFloat(splitQtyInput.value) || 1; |
| | | if (currentVal > maxQty) { |
| | | splitQtyInput.value = Math.min(1, maxQty); |
| | | } |
| | | } |
| | | } else { |
| | | ElMessage.error(res.message || 'è·åæå
ä¿¡æ¯å¤±è´¥'); |
| | | } |
| | | } catch (error) { |
| | | console.error('è·åæå
ä¿¡æ¯å¤±è´¥:', error); |
| | | ElMessage.error('è·åæå
ä¿¡æ¯å¤±è´¥'); |
| | | } |
| | | }, |
| | | |
| | | // 仿å¨å¼¹çªæ¥çæå
é¾ |
| | | viewSplitChainFromManualDialog(barcode, dialogId) { |
| | | // å
å
³éæå¨å¼¹çª |
| | | const dialog = document.getElementById(dialogId); |
| | | if (dialog && dialog.parentNode) { |
| | | dialog.parentNode.removeChild(dialog); |
| | | } |
| | | |
| | | // å»¶è¿ä¸ä¸ï¼ç¶åæå¼Vueçæå
é¾å¼¹çª |
| | | setTimeout(() => { |
| | | this.viewSplitChain(barcode); |
| | | }, 50); |
| | | }, |
| | | |
| | | // å¤çæå¨å¼¹çªçæå
æä½ |
| | | async handleManualSplitPackage(dialogId) { |
| | | const barcodeInput = document.getElementById(`${dialogId}-barcode`); |
| | | const splitQtyInput = document.getElementById(`${dialogId}-splitQty`); |
| | | |
| | | if (!barcodeInput || !barcodeInput.value.trim()) { |
| | | ElMessage.warning('请è¾å
¥åæ¡ç '); |
| | | return; |
| | | } |
| | | |
| | | if (!splitQtyInput || !splitQtyInput.value || parseFloat(splitQtyInput.value) <= 0) { |
| | | ElMessage.warning('请è¾å
¥ææçæå
æ°é'); |
| | | return; |
| | | } |
| | | |
| | | const originalBarcode = barcodeInput.value.trim(); |
| | | const splitQuantity = parseFloat(splitQtyInput.value); |
| | | |
| | | try { |
| | | // æ¾ç¤ºå è½½ç¶æ |
| | | const confirmBtn = document.getElementById(`${dialogId}-confirm`); |
| | | if (confirmBtn) { |
| | | confirmBtn.disabled = true; |
| | | confirmBtn.textContent = 'å¤çä¸...'; |
| | | } |
| | | |
| | | const res = await http.post('/api/OutboundBatchPicking/split-package', { |
| | | orderNo: this.scanData.orderNo, |
| | | palletCode: this.scanData.palletCode, |
| | | originalBarcode: originalBarcode, |
| | | splitQuantity: splitQuantity |
| | | }); |
| | | |
| | | if (res.status) { |
| | | ElMessage.success('æå
æå'); |
| | | |
| | | // å
³éæå¨å¼¹çª |
| | | const dialog = document.getElementById(dialogId); |
| | | if (dialog && dialog.parentNode) { |
| | | dialog.parentNode.removeChild(dialog); |
| | | } |
| | | |
| | | // éæ°å è½½æ°æ® |
| | | await this.loadPalletData(); |
| | | } else { |
| | | ElMessage.error(res.message || 'æå
失败'); |
| | | |
| | | // æ¢å¤æé®ç¶æ |
| | | if (confirmBtn) { |
| | | confirmBtn.disabled = false; |
| | | confirmBtn.textContent = '确认æå
'; |
| | | } |
| | | } |
| | | } catch (error) { |
| | | console.error('æå
失败:', error); |
| | | ElMessage.error('æå
失败'); |
| | | |
| | | // æ¢å¤æé®ç¶æ |
| | | const confirmBtn = document.getElementById(`${dialogId}-confirm`); |
| | | if (confirmBtn) { |
| | | confirmBtn.disabled = false; |
| | | confirmBtn.textContent = '确认æå
'; |
| | | } |
| | | } |
| | | }, |
| | | closeAllDialogsImmediately() { |
| | | console.log('ç«å³å
³éææå¼¹çª'); |
| | | |
| | | // ç´æ¥è®¾ç½®ä¸º falseï¼ä¸çå¾
ä»»ä½å¼æ¥æä½ |
| | | this.showCustomSplitDialog = false; |
| | | this.showRevertSplitDialog = false; |
| | | this.showBatchReturnDialog = false; |
| | | this.showEmptyPalletDialog = false; |
| | | this.showSplitChainDialog = false; |
| | | |
| | | // 强å¶DOMæ´æ° |
| | | this.$forceUpdate(); |
| | | }, |
| | | |
| | | async onSplitBarcodeScan() { |
| | |
| | | }); |
| | | if (res.status) { |
| | | this.$message.success('æå
æå'); |
| | | this.showCustomSplitDialog = false; |
| | | this.closeAllDialogs(); |
| | | await this.loadPalletData(); |
| | | } else { |
| | | this.$message.error(res.message || 'æå
失败'); |
| | |
| | | }); |
| | | } |
| | | }, |
| | | // 卿å
å¼¹çªä¸æ¥çæå
é¾ |
| | | async viewSplitChainFromSplit(barcode) { |
| | | if (!barcode) { |
| | | this.$message.warning('请å
è¾å
¥æ¡ç '); |
| | | return; |
| | | } |
| | | |
| | | // å
å
³éæå
å¼¹çª |
| | | this.closeCustomSplitDialog(); |
| | | |
| | | await this.$nextTick(); |
| | | |
| | | // ç¶åæå¼æå
é¾ä¿¡æ¯å¼¹çª |
| | | await this.viewSplitChain(barcode); |
| | | }, |
| | | |
| | | async viewSplitChainFromSplit(barcode) { |
| | | if (!barcode) { |
| | | this.$message.warning('请å
è¾å
¥æ¡ç '); |
| | | return; |
| | | } |
| | | |
| | | this.closeAllDialogs(); |
| | | |
| | | setTimeout(() => { |
| | | this.viewSplitChain(barcode); |
| | | }, 50); |
| | | }, |
| | | |
| | | // æ¤éæå
|
| | | async onRevertSplitBarcodeScan() { |
| | | if (!this.revertSplitForm.newBarcode) return; |
| | | this.revertSplitForm.newBarcode = this.revertSplitForm.newBarcode.replace(/\n/g, '').trim(); |
| | | |
| | | // æ°å¢ï¼æ«æåèªå¨æ¾ç¤ºæå
é¾ä¿¡æ¯ |
| | | await this.viewSplitChain(this.revertSplitForm.newBarcode); |
| | | }, |
| | | |
| | | async handleRevertSplit() { |
| | |
| | | }); |
| | | if (res.status) { |
| | | this.$message.success('æ¤éæå
æå'); |
| | | this.showRevertSplitDialog = false; |
| | | this.closeAllDialogs(); |
| | | await this.loadPalletData(); |
| | | } else { |
| | | this.$message.error(res.message || 'æ¤éæå
失败'); |
| | |
| | | }); |
| | | } |
| | | }, |
| | | // æ¥æ¾å®æ´æå
é¾ï¼ä»æ ¹æ¡ç å¼å§ï¼ |
| | | async findRootChain(currentBarcode) { |
| | | this.splitChainLoading = true; |
| | | try { |
| | | const res = await http.post('/api/OutboundBatchPicking/find-root-split-chain', { |
| | | orderNo: this.scanData.orderNo, |
| | | barcode: currentBarcode |
| | | }); |
| | | |
| | | if (res.status) { |
| | | this.splitChainInfo = res.data; |
| | | this.$message.success('å·²å è½½å®æ´æå
é¾'); |
| | | } else { |
| | | this.$message.error(res.message || 'æ¥æ¾å®æ´æå
é¾å¤±è´¥'); |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('æ¥æ¾å®æ´æå
é¾å¤±è´¥'); |
| | | } finally { |
| | | this.splitChainLoading = false; |
| | | } |
| | | }, |
| | | // æå
é¾ç¸å
³æ¹æ³ |
| | | // æ¥çæå
é¾ä¿¡æ¯ |
| | | async viewSplitChain(barcode) { |
| | | if (!barcode) { |
| | | this.$message.warning('请å
è¾å
¥æ¡ç '); |
| | | return; |
| | | } |
| | | |
| | | this.splitChainLoading = true; |
| | | try { |
| | | const res = await http.post('/api/OutboundBatchPicking/split-package-chain-info', { |
| | | orderNo: this.scanData.orderNo, |
| | | barcode: barcode |
| | | }); |
| | | |
| | | if (res.status) { |
| | | this.splitChainInfo = res.data; |
| | | |
| | | // æ¾ç¤ºæç¤ºä¿¡æ¯ï¼åè¯ç¨æ·è¿æ¯ä»ä¹ç±»åçæå
é¾ |
| | | let chainType = "å½åæ¡ç çæå
é¾"; |
| | | if (this.splitChainInfo.chainType === 'root') { |
| | | chainType = "宿´æå
é¾ï¼ä»åå§æ¡ç å¼å§ï¼"; |
| | | } else if (this.splitChainInfo.chainType === 'branch') { |
| | | chainType = "忝æå
é¾"; |
| | | |
| | | async findRootChain(currentBarcode) { |
| | | this.splitChainLoading = true; |
| | | try { |
| | | const res = await http.post('/api/OutboundBatchPicking/find-root-split-chain', { |
| | | orderNo: this.scanData.orderNo, |
| | | barcode: currentBarcode |
| | | }); |
| | | |
| | | if (res.status) { |
| | | this.splitChainInfo = res.data; |
| | | this.$message.success('å·²å è½½å®æ´æå
é¾'); |
| | | } else { |
| | | this.$message.error(res.message || 'æ¥æ¾å®æ´æå
é¾å¤±è´¥'); |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('æ¥æ¾å®æ´æå
é¾å¤±è´¥'); |
| | | } finally { |
| | | this.splitChainLoading = false; |
| | | } |
| | | }, |
| | | |
| | | // æ¥çæå
é¾ä¿¡æ¯ |
| | | async viewSplitChain(barcode) { |
| | | if (!barcode) { |
| | | this.$message.warning('请å
è¾å
¥æ¡ç '); |
| | | return; |
| | | } |
| | | |
| | | this.$message.info(`å·²å è½½${chainType}ï¼å
±${this.splitChainInfo.totalSplitTimes}次æå
`); |
| | | this.showSplitChainDialog = true; |
| | | } else { |
| | | this.$message.error(res.message || 'è·åæå
é¾ä¿¡æ¯å¤±è´¥'); |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('è·åæå
é¾ä¿¡æ¯å¤±è´¥'); |
| | | } finally { |
| | | this.splitChainLoading = false; |
| | | } |
| | | }, |
| | | this.splitChainLoading = true; |
| | | try { |
| | | const res = await http.post('/api/OutboundBatchPicking/split-package-chain-info', { |
| | | orderNo: this.scanData.orderNo, |
| | | barcode: barcode |
| | | }); |
| | | |
| | | if (res.status) { |
| | | this.splitChainInfo = res.data; |
| | | this.activeDialog = 'splitChain'; |
| | | } else { |
| | | this.$message.error(res.message || 'è·åæå
é¾ä¿¡æ¯å¤±è´¥'); |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('è·åæå
é¾ä¿¡æ¯å¤±è´¥'); |
| | | } finally { |
| | | this.splitChainLoading = false; |
| | | } |
| | | }, |
| | | |
| | | // å
³éæå
é¾ä¿¡æ¯å¼¹çª |
| | | closeSplitChainDialog() { |
| | | closeSplitChainDialog() { |
| | | this.showSplitChainDialog = false; |
| | | |
| | | }, |
| | | // 卿¤éæå
å¼¹çªä¸æ¥çæå
é¾ |
| | | async viewSplitChainFromRevert(barcode) { |
| | | if (!barcode) { |
| | | this.$message.warning('请å
è¾å
¥æ¡ç '); |
| | | return; |
| | | } |
| | | |
| | | // å
å
³éæ¤éæå
å¼¹çª |
| | | this.closeRevertSplitDialog(); |
| | | |
| | | await this.$nextTick(); |
| | | |
| | | // ç¶åæå¼æå
é¾ä¿¡æ¯å¼¹çª |
| | | await this.viewSplitChain(barcode); |
| | | }, |
| | | // å¿«ééæ°æå¼æå
é¾å¼¹çª |
| | | async quickReopenSplitChainDialog(barcode) { |
| | | if (!barcode) return; |
| | | |
| | | this.showSplitChainDialog = true; |
| | | this.splitChainLoading = true; |
| | | |
| | | try { |
| | | const res = await http.post('/api/OutboundBatchPicking/split-package-chain-info', { |
| | | orderNo: this.scanData.orderNo, |
| | | barcode: barcode |
| | | }); |
| | | |
| | | if (res.status) { |
| | | this.splitChainInfo = res.data; |
| | | } |
| | | } catch (error) { |
| | | console.error('éæ°å è½½æå
é¾ä¿¡æ¯å¤±è´¥:', error); |
| | | } finally { |
| | | this.splitChainLoading = false; |
| | | } |
| | | }, |
| | | // åæ¶å个æå
è®°å½ |
| | | async cancelSingleSplit(newBarcode) { |
| | | // å
è®°å½å½åä¿¡æ¯ï¼ç¶åå
³éå¼¹çª |
| | | const originalBarcode = this.splitChainInfo.originalBarcode; |
| | | this.closeSplitChainDialog(); |
| | | |
| | | await this.$nextTick(); |
| | | |
| | | try { |
| | | await this.$confirm( |
| | | `ç¡®å®è¦åæ¶æ¡ç ${newBarcode} çæå
æä½åï¼`, |
| | | 'åæ¶å个æå
', |
| | | { |
| | | confirmButtonText: 'ç¡®å®åæ¶', |
| | | cancelButtonText: 'åæ³æ³', |
| | | type: 'warning' |
| | | } |
| | | ); |
| | | |
| | | this.revertSplitLoading = true; |
| | | |
| | | const res = await http.post('/api/OutboundBatchPicking/cancel-split', { |
| | | orderNo: this.scanData.orderNo, |
| | | palletCode: this.scanData.palletCode, |
| | | newBarcode: newBarcode |
| | | }); |
| | | |
| | | if (res.status) { |
| | | this.$message.success('åæ¶æå
æå'); |
| | | await this.loadPalletData(); |
| | | // éæ°æå¼å¼¹çªæ¾ç¤ºæ´æ°åçç¶æ |
| | | await this.viewSplitChain(originalBarcode); |
| | | } else { |
| | | this.$message.error(res.message || 'åæ¶æå
失败'); |
| | | await this.viewSplitChain(originalBarcode); |
| | | } |
| | | } catch (error) { |
| | | if (error === 'cancel') { |
| | | // ç¨æ·åæ¶åéæ°æå¼å¼¹çª |
| | | await this.viewSplitChain(originalBarcode); |
| | | } else { |
| | | this.$message.error('åæ¶æå
失败'); |
| | | await this.viewSplitChain(originalBarcode); |
| | | } |
| | | } finally { |
| | | this.revertSplitLoading = false; |
| | | } |
| | | }, |
| | | |
| | | // åæ¶æ´ä¸ªæå
é¾ |
| | | async cancelWholeSplitChain() { |
| | | // å
è®°å½å½åæå
é¾ä¿¡æ¯ï¼ç¶åå
³éå¼¹çª |
| | | const originalBarcode = this.splitChainInfo.originalBarcode; |
| | | this.closeSplitChainDialog(); |
| | | |
| | | // ç»ä¸ç¹æ¶é´è®©å¼¹çªå®å
¨å
³é |
| | | await this.$nextTick(); |
| | | |
| | | try { |
| | | // ç°å¨æ¾ç¤ºç¡®è®¤å¯¹è¯æ¡ï¼ç¡®ä¿å®å¨æåé¢ |
| | | await this.$confirm( |
| | | `ç¡®å®è¦åæ¶æ´ä¸ªæå
é¾åï¼\nè¿å°åæ¶ä»æ¡ç ${originalBarcode} å¼å§çæææå
æä½ã`, |
| | | 'åæ¶æå
é¾ç¡®è®¤', |
| | | { |
| | | confirmButtonText: 'ç¡®å®åæ¶', |
| | | cancelButtonText: 'åæ³æ³', |
| | | type: 'warning', |
| | | center: true, |
| | | closeOnClickModal: false |
| | | // åæ¶å个æå
è®°å½ |
| | | async cancelSingleSplit(newBarcode) { |
| | | const originalBarcode = this.splitChainInfo.originalBarcode; |
| | | |
| | | try { |
| | | await this.$confirm( |
| | | `ç¡®å®è¦åæ¶æ¡ç ${newBarcode} çæå
æä½åï¼`, |
| | | 'åæ¶å个æå
', |
| | | { |
| | | confirmButtonText: 'ç¡®å®åæ¶', |
| | | cancelButtonText: 'åæ³æ³', |
| | | type: 'warning' |
| | | } |
| | | ); |
| | | |
| | | this.revertSplitLoading = true; |
| | | |
| | | const res = await http.post('/api/OutboundBatchPicking/cancel-split', { |
| | | orderNo: this.scanData.orderNo, |
| | | palletCode: this.scanData.palletCode, |
| | | newBarcode: newBarcode |
| | | }); |
| | | |
| | | if (res.status) { |
| | | this.$message.success('åæ¶æå
æå'); |
| | | await this.loadPalletData(); |
| | | this.closeAllDialogs(); |
| | | setTimeout(() => { |
| | | this.viewSplitChain(originalBarcode); |
| | | }, 50); |
| | | } else { |
| | | this.$message.error(res.message || 'åæ¶æå
失败'); |
| | | } |
| | | } catch (error) { |
| | | if (error !== 'cancel') { |
| | | this.$message.error('åæ¶æå
失败'); |
| | | } |
| | | } finally { |
| | | this.revertSplitLoading = false; |
| | | } |
| | | ); |
| | | |
| | | // ç¨æ·ç¡®è®¤åæ§è¡åæ¶æä½ |
| | | this.revertSplitLoading = true; |
| | | |
| | | const res = await http.post('/api/OutboundBatchPicking/cancel-split-chain', { |
| | | orderNo: this.scanData.orderNo, |
| | | palletCode: this.scanData.palletCode, |
| | | startBarcode: originalBarcode |
| | | }); |
| | | |
| | | console.log('åæ¶æå
é¾ååº:', res); |
| | | |
| | | if (res.status) { |
| | | this.$message.success('åæ¶æå
龿å'); |
| | | await this.loadPalletData(); |
| | | // å¯éï¼éæ°æå¼æå
é¾ä¿¡æ¯å¼¹çªæ¾ç¤ºæ´æ°åçç¶æ |
| | | // await this.viewSplitChain(originalBarcode); |
| | | } else { |
| | | this.$message.error(res.message || 'åæ¶æå
é¾å¤±è´¥'); |
| | | // 失败åéæ°æå¼å¼¹çª |
| | | await this.viewSplitChain(originalBarcode); |
| | | } |
| | | } catch (error) { |
| | | // ç¨æ·åæ¶æä½ |
| | | if (error === 'cancel') { |
| | | console.log('ç¨æ·åæ¶äºæå
龿ä½'); |
| | | // ç¨æ·åæ¶åéæ°æå¼å¼¹çª |
| | | await this.viewSplitChain(originalBarcode); |
| | | } else { |
| | | console.error('åæ¶æå
é¾é误:', error); |
| | | this.$message.error('åæ¶æå
é¾å¤±è´¥: ' + error.message); |
| | | // åºéåéæ°æå¼å¼¹çª |
| | | await this.viewSplitChain(originalBarcode); |
| | | } |
| | | } finally { |
| | | this.revertSplitLoading = false; |
| | | } |
| | | }, |
| | | }, |
| | | |
| | | // åæ¶æ´ä¸ªæå
é¾ |
| | | async cancelWholeSplitChain() { |
| | | try { |
| | | await this.$confirm( |
| | | `ç¡®å®è¦åæ¶æ´ä¸ªæå
é¾åï¼\nè¿å°åæ¶ä»æ¡ç ${this.splitChainInfo.originalBarcode} å¼å§çæææå
æä½ã`, |
| | | 'åæ¶æå
é¾ç¡®è®¤', |
| | | { |
| | | confirmButtonText: 'ç¡®å®åæ¶', |
| | | cancelButtonText: 'åæ³æ³', |
| | | type: 'warning', |
| | | center: true, |
| | | closeOnClickModal: false |
| | | } |
| | | ); |
| | | |
| | | this.revertSplitLoading = true; |
| | | |
| | | const res = await http.post('/api/OutboundBatchPicking/cancel-split-chain', { |
| | | orderNo: this.scanData.orderNo, |
| | | palletCode: this.scanData.palletCode, |
| | | startBarcode: this.splitChainInfo.originalBarcode |
| | | }); |
| | | |
| | | if (res.status) { |
| | | this.$message.success('åæ¶æå
龿å'); |
| | | this.closeAllDialogs(); |
| | | await this.loadPalletData(); |
| | | } else { |
| | | this.$message.error(res.message || 'åæ¶æå
é¾å¤±è´¥'); |
| | | } |
| | | } catch (error) { |
| | | if (error !== 'cancel') { |
| | | this.$message.error('åæ¶æå
é¾å¤±è´¥: ' + error.message); |
| | | } |
| | | } finally { |
| | | this.revertSplitLoading = false; |
| | | } |
| | | }, |
| | | |
| | | // æ£æ¥æ¡ç æ¯å¦å·²è¢«åæ£ |
| | | hasPicked(barcode) { |
| | |
| | | return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')} ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}:${date.getSeconds().toString().padStart(2, '0')}`; |
| | | }, |
| | | |
| | | // å
³é®ä¿®å¤ï¼æ°å¢å
³éææå¼¹çªçæ¹æ³ |
| | | closeAllDialogs() { |
| | | this.activeDialog = null; |
| | | // ç¡®ä¿ææå¼¹çªç¶æé½è¢«éç½® |
| | | // å
³éVueå¼¹çª |
| | | this.showCustomSplitDialog = false; |
| | | this.showRevertSplitDialog = false; |
| | | this.showBatchReturnDialog = false; |
| | | this.showEmptyPalletDialog = false; |
| | | this.showSplitChainDialog = false; |
| | | |
| | | // å
³éæå¨å¼¹çª |
| | | if (this.manualDialog && this.manualDialog.parentNode) { |
| | | this.manualDialog.parentNode.removeChild(this.manualDialog); |
| | | this.manualDialog = null; |
| | | } |
| | | |
| | | // ç§»é¤ææç´§æ¥å¼¹çª |
| | | const emergencyDialogs = document.querySelectorAll('.emergency-fix'); |
| | | emergencyDialogs.forEach(dialog => { |
| | | if (dialog.parentNode) { |
| | | dialog.parentNode.removeChild(dialog); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // ååºç¸å
³æ¹æ³ |
| | | openBatchReturnDialog() { |
| | | if (!this.scanData.palletCode) { |
| | | this.$message.warning('请å
æ«ææçç '); |
| | | return; |
| | | } |
| | | this.showBatchReturnDialog = true; |
| | | this.batchReturnForm.orderNo = this.scanData.orderNo; |
| | | this.batchReturnForm.palletCode = this.scanData.palletCode; |
| | | this.batchReturnForm.unpickedCount = this.summary.unpickedCount; |
| | | this.batchReturnForm.unpickedQuantity = this.summary.unpickedQuantity; |
| | | |
| | | if (this.isOpeningDialog) return; |
| | | |
| | | this.isOpeningDialog = true; |
| | | |
| | | setTimeout(() => { |
| | | this.closeAllDialogsImmediately(); |
| | | |
| | | requestAnimationFrame(() => { |
| | | this.showBatchReturnDialog = true; |
| | | this.batchReturnForm.orderNo = this.scanData.orderNo; |
| | | this.batchReturnForm.palletCode = this.scanData.palletCode; |
| | | this.batchReturnForm.unpickedCount = this.summary.unpickedCount; |
| | | this.batchReturnForm.unpickedQuantity = this.summary.unpickedQuantity; |
| | | |
| | | this.$nextTick(() => { |
| | | this.isOpeningDialog = false; |
| | | }); |
| | | }); |
| | | }, 0); |
| | | }, |
| | | |
| | | async handleBatchReturnConfirm() { |
| | |
| | | }); |
| | | if (res.status) { |
| | | this.$message.success('ååºæå'); |
| | | this.showBatchReturnDialog = false; |
| | | this.closeAllDialogs(); |
| | | await this.loadPalletData(); |
| | | } else { |
| | | this.$message.error(res.message || 'ååºå¤±è´¥'); |
| | |
| | | }, |
| | | |
| | | // åç©ºç®±æ¹æ³ |
| | | handleEmptyPallet() { |
| | | this.showEmptyPalletDialog = true; |
| | | this.emptypalletOutForm.orderNo = this.scanData.orderNo; |
| | | this.emptypalletOutForm.palletCode = ''; |
| | | handleEmptyPallet() { |
| | | if (this.isOpeningDialog) return; |
| | | |
| | | this.isOpeningDialog = true; |
| | | |
| | | setTimeout(() => { |
| | | this.closeAllDialogsImmediately(); |
| | | |
| | | requestAnimationFrame(() => { |
| | | this.showEmptyPalletDialog = true; |
| | | this.emptypalletOutForm.orderNo = this.scanData.orderNo; |
| | | this.emptypalletOutForm.palletCode = ''; |
| | | |
| | | this.$nextTick(() => { |
| | | this.isOpeningDialog = false; |
| | | }); |
| | | }); |
| | | }, 0); |
| | | }, |
| | | |
| | | async handleEmptyPalletConfirm() { |
| | |
| | | }); |
| | | if (res.status) { |
| | | this.$message.success('å走空箱æå'); |
| | | this.showEmptyPalletDialog = false; |
| | | this.closeAllDialogs(); |
| | | await this.loadPalletData(); |
| | | } else { |
| | | this.$message.error(res.message || 'å走空箱失败'); |
| | |
| | | async loadPalletData() { |
| | | if (!this.scanData.orderNo || !this.scanData.palletCode) return; |
| | | |
| | | await this.loadUnpickedList(); |
| | | await this.loadPickedList(); |
| | | await this.loadPalletStatus(); |
| | | try { |
| | | await this.loadUnpickedList(); |
| | | await this.loadPickedList(); |
| | | await this.loadPalletStatus(); |
| | | } catch (error) { |
| | | console.error('å è½½æçæ°æ®å¤±è´¥:', error); |
| | | } |
| | | }, |
| | | |
| | | async loadUnpickedList() { |
| | |
| | | palletCode: this.scanData.palletCode |
| | | }); |
| | | if (res.status) { |
| | | //this.unpickedList = res.data || []; |
| | | this.unpickedList = (res.data || []).filter(item => item.canPick === true); |
| | | this.summary.unpickedCount = this.unpickedList.length; |
| | | this.summary.unpickedQuantity = this.unpickedList.reduce((sum, item) => sum + (item.remainQuantity || 0), 0); |
| | |
| | | palletCode: this.scanData.palletCode |
| | | }); |
| | | if (res.status) { |
| | | this.pickedList = res.data || []; |
| | | |
| | | this.pickedList = res.data.map(item => { |
| | | // æ¹å¼1ï¼ä¿çåbarcodeåæ®µï¼æ°å¢currentBarcode |
| | | return { |
| | | ...item, |
| | | currentBarcode: item.barcode |
| | | }; |
| | | }); |
| | | |
| | | this.pickedList = res.data.map(item => ({ |
| | | ...item, |
| | | currentBarcode: item.barcode |
| | | })); |
| | | this.summary.pickedCount = this.pickedList.length; |
| | | } |
| | | } catch (error) { |
| | |
| | | this.resetSplitForm(); |
| | | }, |
| | | |
| | | openRevertSplitDialog() { |
| | | this.showRevertSplitDialog = true; |
| | | this.revertSplitForm.newBarcode = ''; |
| | | openRevertSplitDialog() { |
| | | if (this.isOpeningDialog) return; |
| | | |
| | | this.isOpeningDialog = true; |
| | | |
| | | setTimeout(() => { |
| | | this.closeAllDialogsImmediately(); |
| | | |
| | | requestAnimationFrame(() => { |
| | | this.showRevertSplitDialog = true; |
| | | this.revertSplitForm.newBarcode = ''; |
| | | |
| | | this.$nextTick(() => { |
| | | this.isOpeningDialog = false; |
| | | }); |
| | | }); |
| | | }, 0); |
| | | }, |
| | | |
| | | closeRevertSplitDialog() { |
| | | closeRevertSplitDialog() { |
| | | this.showRevertSplitDialog = false; |
| | | this.revertSplitForm.newBarcode = ''; |
| | | }, |
| | | |
| | | closeBatchReturnDialog() { |
| | | closeBatchReturnDialog() { |
| | | this.showBatchReturnDialog = false; |
| | | }, |
| | | |
| | |
| | | this.emptypalletOutForm.palletCode = this.emptypalletOutForm.palletCode.replace(/\n/g, '').trim(); |
| | | }, |
| | | |
| | | closeEmptyPalletDialog() { |
| | | closeEmptyPalletDialog() { |
| | | this.showEmptyPalletDialog = false; |
| | | this.emptypalletOutForm.palletCode = ''; |
| | | }, |
| | |
| | | color: #909399; |
| | | } |
| | | |
| | | /* èªå®ä¹å¼¹çªæ ·å¼ */ |
| | | :deep(.el-message-box) { |
| | | z-index: 10010 !important; |
| | | } |
| | | |
| | | :deep(.el-overlay) { |
| | | z-index: 10009 !important; |
| | | } |
| | | |
| | | :deep(.el-message) { |
| | | z-index: 10011 !important; |
| | | } |
| | | |
| | | /* èªå®ä¹å¼¹çªæ ·å¼ - å
³é®ä¿®å¤ */ |
| | | .custom-dialog-overlay { |
| | | position: fixed; |
| | | top: 0; |
| | |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | z-index: 2000; /* ä¿æä¸ä¸ªåçç z-index */ |
| | | z-index: 9999; /* æé«z-indexç¡®ä¿å¨æä¸å± */ |
| | | } |
| | | |
| | | .custom-dialog-wrapper { |
| | | position: relative; |
| | | z-index: 10000; |
| | | } |
| | | |
| | | .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; |
| | | } |
| | | |
| | | .custom-dialog-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 20px 20px 10px; |
| | | border-bottom: 1px solid #ebeef5; |
| | | } |
| | | |
| | | .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; |
| | | } |
| | | |
| | | .close-button:hover { |
| | | color: #409EFF; |
| | | background-color: transparent; |
| | | } |
| | | |
| | | .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; |
| | | } |
| | | |
| | | .scanner-form { |
| | | flex-direction: column; |
| | | align-items: stretch; |
| | | } |
| | | |
| | | .scanner-form .el-input { |
| | | width: 100%; |
| | | } |
| | | } |
| | | |
| | | /* åæçæ ·å¼ä¿æä¸å */ |
| | | .OutboundPicking-container { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .scanner-form { |
| | | display: flex; |
| | | gap: 10px; |
| | | align-items: center; |
| | | flex-wrap: wrap; |
| | | } |
| | | |
| | | .scanner-form .el-input { |
| | | width: 200px; |
| | | } |
| | | |
| | | .summary-info { |
| | | display: flex; |
| | | gap: 20px; |
| | | flex-wrap: wrap; |
| | | } |
| | | |
| | | .table-actions { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 10px; |
| | | padding: 0 10px; |
| | | } |
| | | |
| | | .selection-count { |
| | | font-size: 12px; |
| | | color: #909399; |
| | | } |
| | | |
| | | /* åæçèªå®ä¹å¼¹çªæ ·å¼ */ |
| | | .custom-dialog-overlay { |
| | | position: fixed; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background-color: rgba(0, 0, 0, 0.5); |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | z-index: 2000; |
| | | } |
| | | |
| | | .custom-dialog-wrapper { |
| | |
| | | flex-direction: column; |
| | | align-items: stretch; |
| | | } |
| | | /* ç¡®ä¿ç¡®è®¤å¯¹è¯æ¡å¨æåé¢ */ |
| | | .el-message-box__wrapper { |
| | | z-index: 10001 !important; |
| | | } |
| | | |
| | | .el-message { |
| | | z-index: 10002 !important; |
| | | } |
| | | |
| | | .scanner-form .el-input { |
| | | width: 100%; |
| | | } |
| | | } |
| | | |
| | | /* æ°å¢ï¼æå¨å¼¹çªçæé®æ¬åææ */ |
| | | :deep(button) { |
| | | transition: all 0.3s; |
| | | } |
| | | |
| | | :deep(button:hover) { |
| | | opacity: 0.8; |
| | | } |
| | | |
| | | :deep(button:active) { |
| | | opacity: 0.6; |
| | | } |
| | | </style> |
| | |
| | | { |
| | | try |
| | | { |
| | | //erp æµè¯ç¯å¢ |
| | | var request = new TokenRequest { appId = "BG_SYSTEM", secretKey = "7e9239c1e132462a9cf03bfa342a044aMTcxODE5MzgxODI4Mw" }; |
| | | ////erp æ£å¼ç¯å¢ |
| | | //var request = new TokenRequest { appId = "BG_SYSTEM", secretKey = "9a3d0b5a37Bfc6dAM4b34ODb8ebDOSb937106d1b19DS29098" }; |
| | | var response = await PostAsync<TokenRequest, TokenResponse>("auth/getAccessToken", request, includeToken: false); |
| | | var _token = response?.data?.access_token; |
| | | return _token ?? ""; |
| | |
| | | using Org.BouncyCastle.Asn1.Ocsp; |
| | | using SqlSugar; |
| | | using System; |
| | | using System.Collections.Concurrent; |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | | using System.Net; |
| | |
| | | using WIDESEA_IBasicService; |
| | | using WIDESEA_IOutboundService; |
| | | using WIDESEA_Model.Models; |
| | | using WIDESEA_Model.Models.Outbound; |
| | | |
| | | namespace WIDESEA_BasicService |
| | | { |
| | | { |
| | | public class InvokeMESService : IInvokeMESService |
| | | { |
| | | private readonly IHttpClientFactory _httpClientFactory; |
| | |
| | | private readonly IOutboundOrderService _outboundOrderService; |
| | | private readonly IOutboundOrderDetailService _outboundOrderDetailService; |
| | | private readonly IOutStockLockInfoService _outStockLockInfoService; |
| | | public InvokeMESService(IHttpClientFactory httpClientFactory, ILogger<InvokeMESService> logger, IRepository<Dt_FeedbackToMes> feedbacktomesRepository, IRepository<Dt_StockInfoDetail> stockInfoDetailRepository, IRepository<Dt_StockInfo> stockInfoRepository, IRepository<Dt_InboundOrder> inboundOrderRepository, IOutboundOrderService outboundOrderService, IOutboundOrderDetailService outboundOrderDetailService, IOutStockLockInfoService outStockLockInfoService, IMaterialUnitService materialUnitService, IRepository<Dt_PickingRecord> pickingRecoreRepository) |
| | | private readonly IRepository<Dt_InterfaceLog> _interfacelogRepository; |
| | | |
| | | // åå¨èµæºIDåå
¶å¯¹åºçé对象ãä½¿ç¨ ConcurrentDictionary ç¡®ä¿å¯¹åå
¸æä½æ¬èº«ç线ç¨å®å
¨ã |
| | | private static readonly ConcurrentDictionary<string, object> _resourceLocks = new ConcurrentDictionary<string, object>(); |
| | | |
| | | // å
¨å±éæéï¼ç¨äºä¿æ¤ _resourceLocks åå
¸ä¸ GetOrAdd æ TryRemove æ¶çç«äº |
| | | private static readonly object _globalLocker = new object(); |
| | | public InvokeMESService(IHttpClientFactory httpClientFactory, ILogger<InvokeMESService> logger, IRepository<Dt_FeedbackToMes> feedbacktomesRepository, IRepository<Dt_StockInfoDetail> stockInfoDetailRepository, IRepository<Dt_StockInfo> stockInfoRepository, IRepository<Dt_InboundOrder> inboundOrderRepository, IOutboundOrderService outboundOrderService, IOutboundOrderDetailService outboundOrderDetailService, IOutStockLockInfoService outStockLockInfoService, IMaterialUnitService materialUnitService, IRepository<Dt_PickingRecord> pickingRecoreRepository, IRepository<Dt_InterfaceLog> interfacelogRepository) |
| | | { |
| | | _httpClientFactory = httpClientFactory; |
| | | _logger = logger; |
| | |
| | | _outStockLockInfoService = outStockLockInfoService; |
| | | _materialUnitService = materialUnitService; |
| | | _pickingRecoreRepository = pickingRecoreRepository; |
| | | _interfacelogRepository = interfacelogRepository; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | _client.DefaultRequestHeaders.Clear(); |
| | | _client.DefaultRequestHeaders.Add("Accept", "application/json"); |
| | | |
| | | _logger.LogInformation("InvokeMESService FeedbackOutbound : "+ model.orderNo +" , " + json); |
| | | _logger.LogInformation("InvokeMESService FeedbackOutbound : " + model.orderNo + " , " + json); |
| | | |
| | | var response = await _client.PostAsync("AldMaterialOutbound/MaterialOutbound", content); |
| | | string body = await response.Content.ReadAsStringAsync(); |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | /// <summary> |
| | | /// |
| | | /// </summary> |
| | |
| | | /// <returns></returns> |
| | | public async Task<WebResponseContent> BatchOrderFeedbackToMes(List<string> orderNos, int inout) |
| | | { |
| | | if (inout == 1) |
| | | // 1. ãå
å鿢å ã |
| | | if (MemoryLockManager.TryAcquireLock(orderNos[0])) |
| | | { |
| | | foreach (var orderNo in orderNos) |
| | | try |
| | | { |
| | | try |
| | | if (inout == 1) |
| | | { |
| | | var stockinfos = _stockInfoRepository.Db.Queryable<Dt_StockInfo>("info").Where(info => info.StockStatus == 6) |
| | | .Where(it => SqlFunc.Subqueryable<Dt_StockInfoDetail>().Where(s => s.StockId == it.Id && s.OrderNo == orderNo).Any()) |
| | | .ToList(); |
| | | var feeds = _feedbacktomesRepository.Db.Queryable<Dt_FeedbackToMes>().Where(x => x.OrderNo == orderNo && x.ReportStatus == 1).Select(o => o.PalletCode).ToList(); |
| | | var unreports = stockinfos.Where(x => !feeds.Contains(x.PalletCode)).ToList(); |
| | | if (unreports != null && !unreports.Any()) |
| | | foreach (var orderNo in orderNos) |
| | | { |
| | | return WebResponseContent.Instance.Error("没æéè¦åä¼ çæ°æ®"); |
| | | } |
| | | foreach (var item in unreports) |
| | | { |
| | | var lists = _stockInfoDetailRepository.Db.Queryable<Dt_StockInfoDetail>().Where(x => x.StockId == item.Id).ToList(); |
| | | if (lists.Any()) |
| | | try |
| | | { |
| | | var inboundOrder = _inboundOrderRepository.Db.Queryable<Dt_InboundOrder>().First(x => x.InboundOrderNo == lists.FirstOrDefault().OrderNo); |
| | | if (inboundOrder != null) |
| | | var stockinfos = _stockInfoRepository.Db.Queryable<Dt_StockInfo>("info").Where(info => info.StockStatus == 6) |
| | | .Where(it => SqlFunc.Subqueryable<Dt_StockInfoDetail>().Where(s => s.StockId == it.Id && s.OrderNo == orderNo).Any()) |
| | | .ToList(); |
| | | var feeds = _feedbacktomesRepository.Db.Queryable<Dt_FeedbackToMes>().Where(x => x.OrderNo == orderNo && x.ReportStatus == 1).Select(o => o.PalletCode).ToList(); |
| | | var unreports = stockinfos.Where(x => !feeds.Contains(x.PalletCode)).ToList(); |
| | | if (unreports != null && !unreports.Any()) |
| | | { |
| | | if (inboundOrder.OrderType == (int)InOrderTypeEnum.AllocatInbound)//è°æ¨å
¥åº |
| | | return WebResponseContent.Instance.Error("没æéè¦åä¼ çæ°æ®"); |
| | | } |
| | | foreach (var item in unreports) |
| | | { |
| | | var lists = _stockInfoDetailRepository.Db.Queryable<Dt_StockInfoDetail>().Where(x => x.StockId == item.Id).ToList(); |
| | | if (lists.Any()) |
| | | { |
| | | var allocate = SqlSugarHelper.DbWMS.Queryable<Dt_AllocateOrder>().Where(x => x.OrderNo == inboundOrder.InboundOrderNo).First(); |
| | | var allocatefeedmodel = new AllocateDto |
| | | var inboundOrder = _inboundOrderRepository.Db.Queryable<Dt_InboundOrder>().First(x => x.InboundOrderNo == lists.FirstOrDefault().OrderNo); |
| | | if (inboundOrder != null) |
| | | { |
| | | ReqCode = Guid.NewGuid().ToString(), |
| | | ReqTime = DateTime.Now.ToString(), |
| | | BusinessType = "2", |
| | | FactoryArea = inboundOrder.FactoryArea, |
| | | OperationType = 1, |
| | | Operator = inboundOrder.Operator, |
| | | OrderNo = inboundOrder.UpperOrderNo, |
| | | fromWarehouse = allocate?.FromWarehouse ?? "", |
| | | toWarehouse = allocate?.ToWarehouse ?? "", |
| | | Details = new List<AllocateDtoDetail>() |
| | | if (inboundOrder.OrderType == (int)InOrderTypeEnum.AllocatInbound)//è°æ¨å
¥åº |
| | | { |
| | | var allocate = SqlSugarHelper.DbWMS.Queryable<Dt_AllocateOrder>().Where(x => x.OrderNo == inboundOrder.InboundOrderNo).First(); |
| | | var allocatefeedmodel = new AllocateDto |
| | | { |
| | | ReqCode = Guid.NewGuid().ToString(), |
| | | ReqTime = DateTime.Now.ToString(), |
| | | BusinessType = "2", |
| | | FactoryArea = inboundOrder.FactoryArea, |
| | | OperationType = 1, |
| | | Operator = inboundOrder.Operator, |
| | | OrderNo = inboundOrder.UpperOrderNo, |
| | | fromWarehouse = allocate?.FromWarehouse ?? "", |
| | | toWarehouse = allocate?.ToWarehouse ?? "", |
| | | Details = new List<AllocateDtoDetail>() |
| | | |
| | | }; |
| | | }; |
| | | |
| | | var groupedData = lists.GroupBy(item => new { item.MaterielCode, item.InboundOrderRowNo, item.BarcodeUnit, item.WarehouseCode }) |
| | | .Select(group => new AllocateDtoDetail |
| | | { |
| | | MaterialCode = group.Key.MaterielCode, |
| | | LineNo = group.Key.InboundOrderRowNo, |
| | | WarehouseCode = group.Key.WarehouseCode, |
| | | Qty = group.Sum(x => x.BarcodeQty), |
| | | Unit = group.Key.BarcodeUnit, |
| | | Barcodes = group.Select(row => new BarcodeInfo |
| | | { |
| | | Barcode = row.Barcode, |
| | | Qty = row.BarcodeQty, |
| | | BatchNo = row.BatchNo, |
| | | SupplyCode = row.SupplyCode, |
| | | Unit = row.BarcodeUnit |
| | | }).ToList() |
| | | }).ToList(); |
| | | allocatefeedmodel.Details = groupedData; |
| | | var groupedData = lists.GroupBy(item => new { item.MaterielCode, item.InboundOrderRowNo, item.BarcodeUnit, item.WarehouseCode }) |
| | | .Select(group => new AllocateDtoDetail |
| | | { |
| | | MaterialCode = group.Key.MaterielCode, |
| | | LineNo = group.Key.InboundOrderRowNo, |
| | | WarehouseCode = group.Key.WarehouseCode, |
| | | Qty = group.Sum(x => x.BarcodeQty), |
| | | Unit = group.Key.BarcodeUnit, |
| | | Barcodes = group.Select(row => new BarcodeInfo |
| | | { |
| | | Barcode = row.Barcode, |
| | | Qty = row.BarcodeQty, |
| | | BatchNo = row.BatchNo, |
| | | SupplyCode = row.SupplyCode, |
| | | Unit = row.BarcodeUnit |
| | | }).ToList() |
| | | }).ToList(); |
| | | allocatefeedmodel.Details = groupedData; |
| | | |
| | | var result = await FeedbackAllocate(allocatefeedmodel); |
| | | if (result != null && result.code == 200) |
| | | { |
| | | _feedbacktomesRepository.Db.Insertable(new Dt_FeedbackToMes { OrderNo = orderNo, PalletCode = item.PalletCode, ReportStatus = 1 }).ExecuteCommand(); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | var feedmodel = new FeedbackInboundRequestModel |
| | | { |
| | | reqCode = Guid.NewGuid().ToString(), |
| | | reqTime = DateTime.Now.ToString(), |
| | | business_type = inboundOrder.BusinessType, |
| | | factoryArea = inboundOrder.FactoryArea, |
| | | operationType = 1, |
| | | Operator = inboundOrder.Operator, |
| | | orderNo = inboundOrder.UpperOrderNo, |
| | | status = inboundOrder.OrderStatus, |
| | | details = new List<FeedbackInboundDetailsModel>() |
| | | var result = await FeedbackAllocate(allocatefeedmodel); |
| | | if (result != null && result.code == 200) |
| | | { |
| | | _feedbacktomesRepository.Db.Insertable(new Dt_FeedbackToMes { OrderNo = orderNo, PalletCode = item.PalletCode, ReportStatus = 1 }).ExecuteCommand(); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | var feedmodel = new FeedbackInboundRequestModel |
| | | { |
| | | reqCode = Guid.NewGuid().ToString(), |
| | | reqTime = DateTime.Now.ToString(), |
| | | business_type = inboundOrder.BusinessType, |
| | | factoryArea = inboundOrder.FactoryArea, |
| | | operationType = 1, |
| | | Operator = inboundOrder.Operator, |
| | | orderNo = inboundOrder.UpperOrderNo, |
| | | status = inboundOrder.OrderStatus, |
| | | details = new List<FeedbackInboundDetailsModel>() |
| | | |
| | | }; |
| | | }; |
| | | |
| | | 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, |
| | | supplyCode = group.Key.SupplyCode, |
| | | batchNo = group.Key.BatchNo, |
| | | lineNo = group.Key.InboundOrderRowNo, |
| | | qty = group.Sum(x => x.BarcodeQty), |
| | | // warehouseCode = group.Key.WarehouseCode=="0"?"1072": group.Key.WarehouseCode, |
| | | warehouseCode = group.Key.WarehouseCode, |
| | | unit = group.Key.BarcodeUnit, |
| | | barcodes = group.Select(row => new FeedbackBarcodesModel |
| | | { |
| | | barcode = row.Barcode, |
| | | qty = row.BarcodeQty |
| | | }).ToList() |
| | | }).ToList(); |
| | | feedmodel.details = groupedData; |
| | | var result = await FeedbackInbound(feedmodel); |
| | | if (result != null && result.code == 200) |
| | | { |
| | | _feedbacktomesRepository.Db.Insertable(new Dt_FeedbackToMes { OrderNo = orderNo, PalletCode = item.PalletCode, ReportStatus = 1 }).ExecuteCommand(); |
| | | 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, |
| | | supplyCode = group.Key.SupplyCode, |
| | | batchNo = group.Key.BatchNo, |
| | | lineNo = group.Key.InboundOrderRowNo, |
| | | qty = group.Sum(x => x.BarcodeQty), |
| | | // warehouseCode = group.Key.WarehouseCode=="0"?"1072": group.Key.WarehouseCode, |
| | | warehouseCode = group.Key.WarehouseCode, |
| | | unit = group.Key.BarcodeUnit, |
| | | barcodes = group.Select(row => new FeedbackBarcodesModel |
| | | { |
| | | barcode = row.Barcode, |
| | | qty = row.BarcodeQty |
| | | }).ToList() |
| | | }).ToList(); |
| | | feedmodel.details = groupedData; |
| | | var result = await FeedbackInbound(feedmodel); |
| | | if (result != null && result.code == 200) |
| | | { |
| | | _feedbacktomesRepository.Db.Insertable(new Dt_FeedbackToMes { OrderNo = orderNo, PalletCode = item.PalletCode, ReportStatus = 1 }).ExecuteCommand(); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _logger.LogInformation("InvokeMESService BatchOrderFeedbackToMes ååMES失败: " + ex.Message); |
| | | return WebResponseContent.Instance.Error(ex.Message); |
| | | } |
| | | |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | else if (inout == 2) |
| | | { |
| | | _logger.LogInformation("InvokeMESService BatchOrderFeedbackToMes ååMES失败: " + ex.Message); |
| | | return WebResponseContent.Instance.Error(ex.Message); |
| | | } |
| | | foreach (var orderNo in orderNos) |
| | | { |
| | | var outboundOrder = await _outboundOrderService.Db.Queryable<Dt_OutboundOrder>().FirstAsync(x => x.OrderNo == orderNo); |
| | | if (outboundOrder != null && outboundOrder.IsBatch == 0) |
| | | { |
| | | var result = await HandleOutboundOrderToMESCompletion(outboundOrder, orderNo); |
| | | return result; |
| | | } |
| | | else if (outboundOrder != null && outboundOrder.IsBatch == 1) |
| | | { |
| | | var result = await HandleOutboundOrderBatchToMESCompletion(outboundOrder, orderNo); |
| | | return result; |
| | | } |
| | | } |
| | | |
| | | } |
| | | } |
| | | finally |
| | | { |
| | | // 2. ãéæ¾å
åéãæ è®ºæå失败ï¼å¿
须鿾 |
| | | MemoryLockManager.ReleaseLock(orderNos[0]); |
| | | } |
| | | } |
| | | else if (inout == 2) |
| | | else |
| | | { |
| | | foreach (var orderNo in orderNos) |
| | | { |
| | | var outboundOrder = await _outboundOrderService.Db.Queryable<Dt_OutboundOrder>().FirstAsync(x => x.OrderNo == orderNo); |
| | | if (outboundOrder != null && outboundOrder.IsBatch == 0) |
| | | { |
| | | var result = await HandleOutboundOrderToMESCompletion(outboundOrder, orderNo); |
| | | return result; |
| | | } |
| | | else if (outboundOrder != null && outboundOrder.IsBatch == 1) |
| | | { |
| | | var result = await HandleOutboundOrderBatchToMESCompletion(outboundOrder, orderNo); |
| | | return result; |
| | | } |
| | | } |
| | | // æ¢é失败ï¼è¯´ææå¦ä¸ä¸ªçº¿ç¨ï¼WCSåè°æäººå·¥æä½ï¼æ£å¨å¤ç |
| | | |
| | | return WebResponseContent.Instance.Error("WMSæ£å¨å¤çæ¤åä¼ ä»»å¡ï¼è¯·å¿é夿ä½ã"); |
| | | } |
| | | return WebResponseContent.Instance.OK(); |
| | | } |
| | |
| | | return WebResponseContent.Instance.Error("没æéè¦åä¼ çåæ£è®°å½"); |
| | | |
| | | |
| | | var documentNo = UniqueValueGenerator.Generate(); |
| | | |
| | | |
| | | var feedModel = new FeedbackOutboundRequestModel |
| | | var groups = pickingRecords.GroupBy(x => x.FeedBackMesDocumentNo).ToList(); |
| | | foreach (var group in groups) |
| | | { |
| | | reqCode = Guid.NewGuid().ToString(), |
| | | reqTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), |
| | | business_type = outboundOrder.BusinessType, |
| | | factoryArea = outboundOrder.FactoryArea, |
| | | operationType = 1, |
| | | Operator = outboundOrder.Operator!=""? outboundOrder.Operator:App.User.UserName, |
| | | orderNo = outboundOrder.UpperOrderNo, |
| | | documentsNO = documentNo, |
| | | status = outboundOrder.OrderStatus, |
| | | details = new List<FeedbackOutboundDetailsModel>() |
| | | }; |
| | | var detailIds = new List<int>(); |
| | | // å¡«å
æç»åæ¡ç ä¿¡æ¯ |
| | | foreach (var detail in orderDetails) |
| | | { |
| | | // æ¥è¯¢è¯¥æç»å¯¹åºçé宿¡ç è®°å½ |
| | | var detailPicks = pickingRecords.Where(x => x.OrderNo == orderNo |
| | | && detail.Id == x.OrderDetailId).ToList(); |
| | | if (!detailPicks.Any()) |
| | | { |
| | | continue; |
| | | } |
| | | var detailModel = new FeedbackOutboundDetailsModel |
| | | { |
| | | materialCode = detail.MaterielCode, |
| | | lineNo = detail.lineNo, |
| | | warehouseCode = detail.WarehouseCode, |
| | | qty = detail.BarcodeQty, |
| | | currentDeliveryQty = 0, |
| | | unit = detail.BarcodeUnit, |
| | | barcodes = new List<WIDESEA_DTO.Outbound.BarcodesModel>() |
| | | }; |
| | | |
| | | // å¡«å
æ¡ç ä¿¡æ¯ï¼å«åä½è½¬æ¢ï¼ |
| | | foreach (var item in detailPicks) |
| | | List<Dt_PickingRecord> records = group.ToList(); // 该åç»ä¸çææè®°å½ |
| | | if (string.IsNullOrEmpty(group.Key)) |
| | | { |
| | | if (item.PickQuantity <= 0) |
| | | var emptydocumentNo = UniqueValueGenerator.Generate(); |
| | | records.ForEach(x => { x.FeedBackMesDocumentNo = emptydocumentNo; }); |
| | | var result = await _pickingRecoreRepository.Db.Updateable(records).ExecuteCommandAsync(); |
| | | |
| | | var interfacelog = new Dt_InterfaceLog |
| | | { |
| | | continue; |
| | | } |
| | | var barModel = new WIDESEA_DTO.Outbound.BarcodesModel |
| | | { |
| | | barcode = item.Barcode, |
| | | supplyCode = item.SupplyCode, |
| | | batchNo = item.BatchNo, |
| | | unit = item.BarcodeUnit, |
| | | qty = item.PickQuantity |
| | | Content = JsonConvert.SerializeObject(records), |
| | | DocumentNo = emptydocumentNo, |
| | | OrderNo = orderNo, |
| | | OrderType = "2", |
| | | }; |
| | | _interfacelogRepository.AddData(interfacelog); |
| | | |
| | | // åä½ä¸ä¸è´æ¶è½¬æ¢ |
| | | if (detail.BarcodeUnit != detail.Unit) |
| | | if (result > 0) |
| | | { |
| | | var convertResult = await _materialUnitService.ConvertAsync( |
| | | item.MaterielCode, item.PickQuantity, detail.Unit, detail.BarcodeUnit); |
| | | barModel.unit = convertResult.Unit; |
| | | barModel.qty = convertResult.Quantity; |
| | | } |
| | | else |
| | | { |
| | | barModel.qty = item.PickQuantity; |
| | | } |
| | | detailModel.currentDeliveryQty += barModel.qty; |
| | | detailModel.barcodes.Add(barModel); |
| | | } |
| | | detailIds.Add(detail.Id); |
| | | feedModel.details.Add(detailModel); |
| | | } |
| | | (bool _flowControl, WebResponseContent _value) = await FeedBackBatchToMes(outboundOrder, orderNo, orderDetails, pickingRecords, emptydocumentNo); |
| | | |
| | | feedModel.details = feedModel.details.GroupBy(item => new { item.materialCode, item.lineNo, item.warehouseCode, item.unit,item.qty }).Select(group => new FeedbackOutboundDetailsModel |
| | | { |
| | | materialCode = group.Key.materialCode, |
| | | lineNo = group.Key.lineNo, |
| | | warehouseCode = group.Key.warehouseCode, |
| | | qty = group.Key.qty, |
| | | currentDeliveryQty = group.Sum(x => x.currentDeliveryQty), |
| | | unit = group.Key.unit, |
| | | barcodes = group.SelectMany(x => x.barcodes.GroupBy(o => new { o.barcode, o.supplyCode, o.batchNo, o.unit }).Select(row => new WIDESEA_DTO.Outbound.BarcodesModel |
| | | { |
| | | barcode = row.Key.barcode, |
| | | supplyCode = row.Key.supplyCode, |
| | | batchNo = row.Key.batchNo, |
| | | unit = row.Key.unit, |
| | | qty = row.Sum(y => y.qty) |
| | | })).ToList() |
| | | }).ToList(); |
| | | return _value; |
| | | |
| | | var allCompleted = true; |
| | | |
| | | // çéå¾
åä¼ çæç»ï¼ReturnToMESStatus=0ï¼ |
| | | var pendingDetails = orderDetails.Where(x => x.ReturnToMESStatus == 0).ToList(); |
| | | foreach (var detail in pendingDetails) |
| | | { |
| | | if (detail.OverOutQuantity < detail.NeedOutQuantity) |
| | | { |
| | | allCompleted = false; |
| | | } |
| | | } |
| | | |
| | | // åå¨åä¼ å¤±è´¥çæç»ï¼ReturnToMESStatus=2ï¼ï¼æ è®°æªå®æ |
| | | if (orderDetails.Any(x => x.ReturnToMESStatus == 2)) |
| | | { |
| | | allCompleted = false; |
| | | } |
| | | |
| | | // æ´æ°è®¢åç¶æ |
| | | int newStatus = allCompleted ? (int)OutOrderStatusEnum.åºåºå®æ : (int)OutOrderStatusEnum.åºåºä¸; |
| | | if (outboundOrder.OrderStatus != newStatus) |
| | | { |
| | | |
| | | int updateCount = await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>() |
| | | .SetColumns(x => x.OrderStatus == newStatus) |
| | | .Where(x => x.OrderNo == orderNo) |
| | | .ExecuteCommandAsync(); |
| | | |
| | | if (updateCount <= 0) |
| | | { |
| | | _logger.LogWarning($"æ´æ°åºåºåç¶æå¤±è´¥ - OrderNo: {orderNo}, ç®æ ç¶æ: {newStatus}"); |
| | | |
| | | } |
| | | } |
| | | |
| | | |
| | | // è°ç¨MESåä¼ æ¥å£ |
| | | var mesResult = await FeedbackOutbound(feedModel); |
| | | if (mesResult == null || mesResult.code != 200) |
| | | { |
| | | |
| | | // æ´æ°æç»ä¸ºåä¼ å¤±è´¥ï¼ReturnToMESStatus=2ï¼ |
| | | await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>() |
| | | .SetColumns(it => new Dt_OutboundOrderDetail |
| | | { |
| | | ReturnToMESStatus = 2, |
| | | documentsNO = documentNo, |
| | | }) |
| | | .Where(x => detailIds.Contains(x.Id)) |
| | | .ExecuteCommandAsync(); |
| | | |
| | | return WebResponseContent.Instance.Error($"åä¼ MES失败"); |
| | | } |
| | | foreach (var record in pickingRecords.Where(x => detailIds.Contains(x.OrderDetailId)).ToList()) |
| | | { |
| | | record.ReturnToMESStatus = 1; |
| | | } |
| | | var updates = pickingRecords.Where(x => detailIds.Contains(x.OrderDetailId)).ToList(); |
| | | updates.ForEach(x => |
| | | { |
| | | x.ReturnToMESStatus = 1; |
| | | }); |
| | | await _pickingRecoreRepository.Db.Updateable(updates).ExecuteCommandAsync(); |
| | | if (allCompleted) |
| | | { |
| | | //MESåä¼ æåï¼æ´æ°æç»ä¸ºåä¼ æåç¶æ |
| | | await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>() |
| | | .SetColumns(it => new Dt_OutboundOrderDetail |
| | | { |
| | | ReturnToMESStatus = 1, |
| | | documentsNO = documentNo, |
| | | }) |
| | | .Where(x => detailIds.Contains(x.Id)) |
| | | .ExecuteCommandAsync(); |
| | | } |
| | | // æ ¡éªæ¯å¦æææç»é½å®æï¼æ´æ°è®¢åæç»ç¶æ |
| | | if (allCompleted && newStatus == (int)OutOrderStatusEnum.åºåºå®æ) |
| | | { |
| | | await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>() |
| | | .SetColumns(x => new Dt_OutboundOrder |
| | | { |
| | | ReturnToMESStatus = 1, |
| | | OrderStatus = newStatus |
| | | }) |
| | | .Where(x => x.OrderNo == orderNo) |
| | | .ExecuteCommandAsync(); |
| | | } |
| | | else |
| | | { |
| | | // äºæ¬¡æ ¡éªæ¯å¦æææªåä¼ æç»é½å·²å®æ |
| | | var dbOrderDetails = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | .LeftJoin<Dt_OutboundOrder>((o, item) => o.OrderId == item.Id) |
| | | .Where((o, item) => item.OrderNo == orderNo && item.ReturnToMESStatus != 1) |
| | | .Select((o, item) => o) |
| | | .ToListAsync(); |
| | | |
| | | var secAllCompleted = true; |
| | | foreach (var detail in dbOrderDetails.Where(x => x.ReturnToMESStatus == 0).ToList()) |
| | | { |
| | | if (detail.OverOutQuantity < detail.NeedOutQuantity) |
| | | { |
| | | secAllCompleted = false; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | if (secAllCompleted) |
| | | else |
| | | { |
| | | await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>() |
| | | .SetColumns(it => new Dt_OutboundOrder |
| | | var ilog = _interfacelogRepository.QueryFirst(x => x.DocumentNo == group.Key); |
| | | if (ilog == null) |
| | | { |
| | | var interfacelog = new Dt_InterfaceLog |
| | | { |
| | | ReturnToMESStatus = 1, |
| | | OrderStatus = OutOrderStatusEnum.åºåºå®æ.ObjToInt(), |
| | | }) |
| | | .Where(x => x.OrderNo == orderNo) |
| | | .ExecuteCommandAsync(); |
| | | Content = JsonConvert.SerializeObject(records), |
| | | DocumentNo = group.Key, |
| | | OrderNo = orderNo, |
| | | OrderType = "2", |
| | | }; |
| | | _interfacelogRepository.AddData(interfacelog); |
| | | } |
| | | (bool _flowControl, WebResponseContent _value) = await FeedBackBatchToMes(outboundOrder, orderNo, orderDetails, pickingRecords, group.Key); |
| | | |
| | | return _value; |
| | | |
| | | } |
| | | } |
| | | |
| | | |
| | | //var documentNo = UniqueValueGenerator.Generate(); |
| | | |
| | | //(bool flowControl, WebResponseContent value) = await FeedBackBatchToMes(outboundOrder, orderNo, orderDetails, pickingRecords, documentNo); |
| | | //if (!flowControl) |
| | | //{ |
| | | // return value; |
| | | //} |
| | | |
| | | // åä¼ æåçæç»è¿å |
| | | response = WebResponseContent.Instance.OK($"åä¼ MESæåï¼åæ®å·ï¼{documentNo}"); |
| | | response = WebResponseContent.Instance.OK($"åä¼ MESæåï¼åæ®å·ï¼{orderNo}"); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | |
| | | } |
| | | |
| | | return response; |
| | | } |
| | | |
| | | private async Task<(bool flowControl, WebResponseContent value)> FeedBackBatchToMes(Dt_OutboundOrder outboundOrder, string orderNo, List<Dt_OutboundOrderDetail> orderDetails, List<Dt_PickingRecord> pickingRecords, string documentNo) |
| | | { |
| | | var feedModel = new FeedbackOutboundRequestModel |
| | | { |
| | | reqCode = Guid.NewGuid().ToString(), |
| | | reqTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), |
| | | business_type = outboundOrder.BusinessType, |
| | | factoryArea = outboundOrder.FactoryArea, |
| | | operationType = 1, |
| | | Operator = outboundOrder.Operator != "" ? outboundOrder.Operator : App.User.UserName, |
| | | orderNo = outboundOrder.UpperOrderNo, |
| | | documentsNO = documentNo, |
| | | status = outboundOrder.OrderStatus, |
| | | details = new List<FeedbackOutboundDetailsModel>() |
| | | }; |
| | | var detailIds = new List<int>(); |
| | | // å¡«å
æç»åæ¡ç ä¿¡æ¯ |
| | | foreach (var detail in orderDetails) |
| | | { |
| | | // æ¥è¯¢è¯¥æç»å¯¹åºçé宿¡ç è®°å½ |
| | | var detailPicks = pickingRecords.Where(x => x.OrderNo == orderNo |
| | | && detail.Id == x.OrderDetailId).ToList(); |
| | | if (!detailPicks.Any()) |
| | | { |
| | | continue; |
| | | } |
| | | var detailModel = new FeedbackOutboundDetailsModel |
| | | { |
| | | materialCode = detail.MaterielCode, |
| | | lineNo = detail.lineNo, |
| | | warehouseCode = detail.WarehouseCode, |
| | | qty = detail.BarcodeQty, |
| | | currentDeliveryQty = 0, |
| | | unit = detail.BarcodeUnit, |
| | | barcodes = new List<WIDESEA_DTO.Outbound.BarcodesModel>() |
| | | }; |
| | | |
| | | // å¡«å
æ¡ç ä¿¡æ¯ï¼å«åä½è½¬æ¢ï¼ |
| | | foreach (var item in detailPicks) |
| | | { |
| | | if (item.PickQuantity <= 0) |
| | | { |
| | | continue; |
| | | } |
| | | var barModel = new WIDESEA_DTO.Outbound.BarcodesModel |
| | | { |
| | | barcode = item.Barcode, |
| | | supplyCode = item.SupplyCode, |
| | | batchNo = item.BatchNo, |
| | | unit = item.BarcodeUnit, |
| | | qty = item.PickQuantity |
| | | }; |
| | | |
| | | // åä½ä¸ä¸è´æ¶è½¬æ¢ |
| | | if (detail.BarcodeUnit != detail.Unit) |
| | | { |
| | | var convertResult = await _materialUnitService.ConvertAsync( |
| | | item.MaterielCode, item.PickQuantity, detail.Unit, detail.BarcodeUnit); |
| | | barModel.unit = convertResult.Unit; |
| | | barModel.qty = convertResult.Quantity; |
| | | } |
| | | else |
| | | { |
| | | barModel.qty = item.PickQuantity; |
| | | } |
| | | detailModel.currentDeliveryQty += barModel.qty; |
| | | detailModel.barcodes.Add(barModel); |
| | | } |
| | | detailIds.Add(detail.Id); |
| | | feedModel.details.Add(detailModel); |
| | | } |
| | | |
| | | feedModel.details = feedModel.details.GroupBy(item => new { item.materialCode, item.lineNo, item.warehouseCode, item.unit, item.qty }).Select(group => new FeedbackOutboundDetailsModel |
| | | { |
| | | materialCode = group.Key.materialCode, |
| | | lineNo = group.Key.lineNo, |
| | | warehouseCode = group.Key.warehouseCode, |
| | | qty = group.Key.qty, |
| | | currentDeliveryQty = group.Sum(x => x.currentDeliveryQty), |
| | | unit = group.Key.unit, |
| | | barcodes = group.SelectMany(x => x.barcodes.GroupBy(o => new { o.barcode, o.supplyCode, o.batchNo, o.unit }).Select(row => new WIDESEA_DTO.Outbound.BarcodesModel |
| | | { |
| | | barcode = row.Key.barcode, |
| | | supplyCode = row.Key.supplyCode, |
| | | batchNo = row.Key.batchNo, |
| | | unit = row.Key.unit, |
| | | qty = row.Sum(y => y.qty) |
| | | })).ToList() |
| | | }).ToList(); |
| | | |
| | | var allCompleted = true; |
| | | |
| | | // çéå¾
åä¼ çæç»ï¼ReturnToMESStatus=0ï¼ |
| | | var pendingDetails = orderDetails.Where(x => x.ReturnToMESStatus == 0).ToList(); |
| | | foreach (var detail in pendingDetails) |
| | | { |
| | | if (detail.OverOutQuantity < detail.NeedOutQuantity) |
| | | { |
| | | allCompleted = false; |
| | | } |
| | | } |
| | | |
| | | // åå¨åä¼ å¤±è´¥çæç»ï¼ReturnToMESStatus=2ï¼ï¼æ è®°æªå®æ |
| | | if (orderDetails.Any(x => x.ReturnToMESStatus == 2)) |
| | | { |
| | | allCompleted = false; |
| | | } |
| | | |
| | | // æ´æ°è®¢åç¶æ |
| | | int newStatus = allCompleted ? (int)OutOrderStatusEnum.åºåºå®æ : (int)OutOrderStatusEnum.åºåºä¸; |
| | | if (outboundOrder.OrderStatus != newStatus) |
| | | { |
| | | |
| | | int updateCount = await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>() |
| | | .SetColumns(x => x.OrderStatus == newStatus) |
| | | .Where(x => x.OrderNo == orderNo) |
| | | .ExecuteCommandAsync(); |
| | | |
| | | if (updateCount <= 0) |
| | | { |
| | | _logger.LogWarning($"æ´æ°åºåºåç¶æå¤±è´¥ - OrderNo: {orderNo}, ç®æ ç¶æ: {newStatus}"); |
| | | |
| | | } |
| | | } |
| | | |
| | | |
| | | // è°ç¨MESåä¼ æ¥å£ |
| | | var mesResult = await FeedbackOutbound(feedModel); |
| | | if (mesResult == null || mesResult.code != 200) |
| | | { |
| | | |
| | | // æ´æ°æç»ä¸ºåä¼ å¤±è´¥ï¼ReturnToMESStatus=2ï¼ |
| | | await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>() |
| | | .SetColumns(it => new Dt_OutboundOrderDetail |
| | | { |
| | | ReturnToMESStatus = 2, |
| | | documentsNO = documentNo, |
| | | }) |
| | | .Where(x => detailIds.Contains(x.Id)) |
| | | .ExecuteCommandAsync(); |
| | | |
| | | return (flowControl: false, value: WebResponseContent.Instance.Error($"åä¼ MES失败")); |
| | | } |
| | | foreach (var record in pickingRecords.Where(x => detailIds.Contains(x.OrderDetailId)).ToList()) |
| | | { |
| | | record.ReturnToMESStatus = 1; |
| | | } |
| | | var updates = pickingRecords.Where(x => detailIds.Contains(x.OrderDetailId)).ToList(); |
| | | updates.ForEach(x => |
| | | { |
| | | x.ReturnToMESStatus = 1; |
| | | }); |
| | | await _pickingRecoreRepository.Db.Updateable(updates).ExecuteCommandAsync(); |
| | | await _interfacelogRepository.Db.Updateable<Dt_InterfaceLog>() |
| | | .SetColumns(x => x.ReturnToMESStatus == 1) |
| | | .Where(x => x.OrderNo == orderNo) |
| | | .ExecuteCommandAsync(); |
| | | |
| | | if (allCompleted) |
| | | { |
| | | //MESåä¼ æåï¼æ´æ°æç»ä¸ºåä¼ æåç¶æ |
| | | await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>() |
| | | .SetColumns(it => new Dt_OutboundOrderDetail |
| | | { |
| | | ReturnToMESStatus = 1, |
| | | documentsNO = documentNo, |
| | | }) |
| | | .Where(x => detailIds.Contains(x.Id)) |
| | | .ExecuteCommandAsync(); |
| | | } |
| | | // æ ¡éªæ¯å¦æææç»é½å®æï¼æ´æ°è®¢åæç»ç¶æ |
| | | if (allCompleted && newStatus == (int)OutOrderStatusEnum.åºåºå®æ) |
| | | { |
| | | await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>() |
| | | .SetColumns(x => new Dt_OutboundOrder |
| | | { |
| | | ReturnToMESStatus = 1, |
| | | OrderStatus = newStatus |
| | | }) |
| | | .Where(x => x.OrderNo == orderNo) |
| | | .ExecuteCommandAsync(); |
| | | } |
| | | else |
| | | { |
| | | // äºæ¬¡æ ¡éªæ¯å¦æææªåä¼ æç»é½å·²å®æ |
| | | var dbOrderDetails = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | .LeftJoin<Dt_OutboundOrder>((o, item) => o.OrderId == item.Id) |
| | | .Where((o, item) => item.OrderNo == orderNo && item.ReturnToMESStatus != 1) |
| | | .Select((o, item) => o) |
| | | .ToListAsync(); |
| | | |
| | | var secAllCompleted = true; |
| | | foreach (var detail in dbOrderDetails.Where(x => x.ReturnToMESStatus == 0).ToList()) |
| | | { |
| | | if (detail.OverOutQuantity < detail.NeedOutQuantity) |
| | | { |
| | | secAllCompleted = false; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | if (secAllCompleted) |
| | | { |
| | | await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>() |
| | | .SetColumns(it => new Dt_OutboundOrder |
| | | { |
| | | ReturnToMESStatus = 1, |
| | | OrderStatus = OutOrderStatusEnum.åºåºå®æ.ObjToInt(), |
| | | }) |
| | | .Where(x => x.OrderNo == orderNo) |
| | | .ExecuteCommandAsync(); |
| | | } |
| | | } |
| | | |
| | | return (flowControl: true, value: null); |
| | | } |
| | | |
| | | private async Task<WebResponseContent> HandleOutboundOrderToMESCompletion(Dt_OutboundOrder outboundOrder, string orderNo) |
| | |
| | | return WebResponseContent.Instance.Error("å¤çåä¼ MESæ¶åçå¼å¸¸ï¼è¯·è系管çå"); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | public static class UniqueValueGenerator |
| | | { |
| | |
| | | // æ¼æ¥ï¼è®¡æ°å¨è¡¥0为3ä½ï¼é¿å
使°ä¸ä¸è´ï¼ |
| | | return $"{datePart}{ticksPart}"; |
| | | } |
| | | |
| | | |
| | | public static string GenerateCount() |
| | | { |
| | | var now = DateTime.Now; |
| | | var now = DateTime.Now; |
| | | string datePart = now.ToString("yyyyMMddHHmmss"); |
| | | |
| | | |
| | |
| | | return $"{datePart}{counterPart:D3}"; |
| | | } |
| | | } |
| | | |
| | | |
| | | public static class MemoryLockManager |
| | | { |
| | | // åå¨èµæºIDåå
¶å¯¹åºçé对象ãä½¿ç¨ ConcurrentDictionary ç¡®ä¿å¯¹åå
¸æä½æ¬èº«ç线ç¨å®å
¨ã |
| | | private static readonly ConcurrentDictionary<string, object> _resourceLocks = new ConcurrentDictionary<string, object>(); |
| | | |
| | | // å
¨å±éæéï¼ç¨äºä¿æ¤ _resourceLocks åå
¸ä¸ GetOrAdd æ TryRemove æ¶çç«äº |
| | | private static readonly object _globalLocker = new object(); |
| | | |
| | | /// <summary> |
| | | /// å°è¯éå®ä¸ä¸ªèµæºIDã |
| | | /// </summary> |
| | | /// <param name="resourceId">è¦éå®çèµæºIDï¼ä¾å¦ InboundRecord IDï¼</param> |
| | | /// <returns>æ¯å¦æåè·åé</returns> |
| | | public static bool TryAcquireLock(string resourceId) |
| | | { |
| | | object lockObject = null; |
| | | |
| | | // æ ¸å¿æè·¯ï¼ä¸ºæ¯ä¸ªèµæºå建ä¸ä¸ªå¯ä¸çé对象 |
| | | lock (_globalLocker) |
| | | { |
| | | // å¦æèµæºIDä¸å¨åå
¸ä¸ï¼åæ·»å ä¸ä¸ªæ°çé对象 |
| | | // å¦åï¼ä½¿ç¨å·²åå¨çé对象 |
| | | lockObject = _resourceLocks.GetOrAdd(resourceId, new object()); |
| | | } |
| | | |
| | | // å°è¯è·åèµæºç¹å®çé |
| | | // ä½¿ç¨ Monitor.TryEnter é¿å
é»å¡ï¼å¹¶å®ç°éé»å¡çæ¢é |
| | | return Monitor.TryEnter(lockObject); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// éæ¾èµæºIDçéå®ã |
| | | /// </summary> |
| | | /// <param name="resourceId">è¦éæ¾çèµæºID</param> |
| | | public static void ReleaseLock(string resourceId) |
| | | { |
| | | if (_resourceLocks.TryGetValue(resourceId, out object lockObject)) |
| | | { |
| | | // ç¡®ä¿éæ¾çæ¯å½åçº¿ç¨ææçé |
| | | if (Monitor.IsEntered(lockObject)) |
| | | { |
| | | Monitor.Exit(lockObject); |
| | | |
| | | // éæ¾éåï¼å°è¯ä»åå
¸ä¸ç§»é¤è¿ä¸ªéå¯¹è±¡ï¼æ¸
çå
åã |
| | | // å¿
é¡»å¨ Monitor.Exit ä¹åæ§è¡ã |
| | | lock (_globalLocker) |
| | | { |
| | | _resourceLocks.TryRemove(resourceId, out _); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | List<string> lockLocationCodes = locationCaches.Select(x => x.LocationCode).ToList(); |
| | | |
| | | //Dictionary<string, SqlSugar.OrderByType> orderBy = new Dictionary<string, OrderByType>() |
| | | //{ |
| | | // { nameof(Dt_LocationInfo.RoadwayNo),OrderByType.Asc }, |
| | | // { nameof(Dt_LocationInfo.Layer),OrderByType.Asc }, |
| | | // { nameof(Dt_LocationInfo.Column),OrderByType.Asc }, |
| | | // { nameof(Dt_LocationInfo.Depth),OrderByType.Desc }, |
| | | // { nameof(Dt_LocationInfo.Row),OrderByType.Asc } |
| | | //}; |
| | | |
| | | Dictionary<string, SqlSugar.OrderByType> orderBy = new Dictionary<string, OrderByType>() |
| | | { |
| | | { nameof(Dt_LocationInfo.RoadwayNo),OrderByType.Asc }, |
| | | //{ nameof(Dt_LocationInfo.RoadwayNo),OrderByType.Asc }, |
| | | { nameof(Dt_LocationInfo.Layer),OrderByType.Asc }, |
| | | { nameof(Dt_LocationInfo.Row),OrderByType.Asc }, |
| | | { nameof(Dt_LocationInfo.Column),OrderByType.Asc }, |
| | | { nameof(Dt_LocationInfo.Depth),OrderByType.Desc }, |
| | | { nameof(Dt_LocationInfo.Row),OrderByType.Asc } |
| | | |
| | | }; |
| | | |
| | | |
| | | var first = BaseDal.QueryFirst(x => x.LocationType == locationType && x.LocationStatus == LocationStatusEnum.Free.ObjToInt() && x.EnableStatus != EnableStatusEnum.Disable.ObjToInt() && !lockLocationCodes.Contains(x.LocationCode), orderBy);//æ¥è¯¢ç©ºè´§ä½ä¿¡æ¯å¹¶æé¤5åéå
åé
çè´§ä½,æ ¹æ®å±ãåãæ·±åº¦ãè¡æåº |
| | | if (first != null) |
| | |
| | | { |
| | | LocationStatus = (int)LocationStatusEnum.InStockLock, |
| | | }).Where(x => x.Id == first.Id).ExecuteCommand(); |
| | | } |
| | | } |
| | | |
| | | return first; |
| | | } |
| | |
| | | { |
| | | return Repository.QueryData(x => locationCodes.Contains(x.LocationCode)); |
| | | } |
| | | |
| | | |
| | | public List<LocationTypeDto> GetLocationTypes() |
| | | { |
| | | return _locationTypeRepository.Db.Queryable<Dt_LocationType>().Select(x => |
| | |
| | | { |
| | | return WebResponseContent.Instance.Error($"æªæ¾å°åä¿¡æ¯"); |
| | | } |
| | | var isupdate = false; |
| | | if (recheckOrder.SignSeq == model.SignSeq) |
| | | { |
| | | isupdate = true; |
| | | } |
| | | recheckOrder.OrderNo = model.OrderNo; |
| | | recheckOrder.MaterielCode = model.MaterielCode; |
| | | recheckOrder.BatchNo = model.BatchNo; |
| | |
| | | |
| | | BaseDal.UpdateData(recheckOrder); |
| | | |
| | | _outboundService.OutboundOrderService.Db.Deleteable<Dt_OutboundOrder>().Where(x => x.OrderNo == model.OrderNo).ExecuteCommand(); |
| | | _outboundService.OutboundOrderDetailService.Db.Deleteable<Dt_OutboundOrderDetail>() |
| | | .Where(p => SqlFunc.Subqueryable<Dt_OutboundOrder>().Where(s => s.Id == p.OrderId && s.OrderNo == model.OrderNo).Any()).ExecuteCommand(); |
| | | if (isupdate) |
| | | { |
| | | _outboundService.OutboundOrderService.Db.Deleteable<Dt_OutboundOrder>().Where(x => x.OrderNo == model.OrderNo).ExecuteCommand(); |
| | | _outboundService.OutboundOrderDetailService.Db.Deleteable<Dt_OutboundOrderDetail>() |
| | | .Where(p => SqlFunc.Subqueryable<Dt_OutboundOrder>().Where(s => s.Id == p.OrderId && s.OrderNo == model.OrderNo).Any()).ExecuteCommand(); |
| | | |
| | | var outboundOrders = ConvertToOutboundOrders(model); |
| | | |
| | | await _outboundService.OutboundOrderService.ReceiveOutboundOrder(outboundOrders, 1); |
| | | |
| | | var outboundOrders = ConvertToOutboundOrders(model); |
| | | await _outboundService.OutboundOrderService.ReceiveOutboundOrder(outboundOrders, 1); |
| | | } |
| | | return WebResponseContent.Instance.OK(); |
| | | } |
| | | catch (Exception ex) |
| | |
| | | [Description("AGVæ§è¡ä¸")] |
| | | AGV_Executing = 310, |
| | | |
| | | [Description("AGVåè´§ä¸")] |
| | | AGV_Pull = 315, |
| | | /// <summary> |
| | | /// AGVå¾
ç»§ç»æ§è¡ |
| | | /// </summary> |
| | |
| | | else if (propertyInfo.Name == nameof(BaseEntity.ModifyDate)) |
| | | { |
| | | propertyInfo.SetValue(obj, DateTime.Now); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | propertyInfo.SetValue(obj, property.GetValue(entity)); |
| | |
| | | } |
| | | } |
| | | return DeleteData(entity); |
| | | |
| | | |
| | | } |
| | | |
| | | //public bool DeleteAndMoveIntoHty(TEntity entity, OperateTypeEnum operateType) |
| | | //{ |
| | | // // æ ¸å¿é»è¾ï¼ç¨äºå¡ä¿è¯ååæ§ï¼å¼å¸¸æè·é¿å
æµç¨ä¸æï¼æ¥å¿è¾
å©ææ¥ |
| | | // bool isSuccess = false; |
| | | // string entityTypeName = entity?.GetType().Name ?? "æªç¥å®ä½"; |
| | | |
| | | // try |
| | | // { |
| | | // // åç½®æ ¡éªï¼å®ä½ä¸è½ä¸ºç©º |
| | | // if (entity == null) |
| | | // { |
| | | // return false; |
| | | // } |
| | | |
| | | // Type entityType = entity.GetType(); |
| | | // Assembly assembly = entityType.Assembly; |
| | | // string htyTypeName = $"{entityType.FullName}_Hty"; |
| | | // Type? htyType = assembly.GetType(htyTypeName); |
| | | |
| | | // // 1. æ£æ¥åå²è¡¨ç±»åæ¯å¦åå¨ |
| | | // if (htyType == null) |
| | | // { |
| | | |
| | | // return false; |
| | | // } |
| | | |
| | | // // 2. å建åå²è¡¨å®ä¾ï¼å¤çæ åæé 彿°ä¸åå¨çæ
åµï¼ |
| | | // object? htyObj; |
| | | // try |
| | | // { |
| | | // htyObj = Activator.CreateInstance(htyType); |
| | | // } |
| | | // catch (Exception ex) |
| | | // { |
| | | // // _logger.LogError(ex, "DeleteAndMoveIntoHtyï¼å建åå²è¡¨å®ä¾ {HtyTypeName} 失败", htyTypeName); |
| | | // return false; |
| | | // } |
| | | // if (htyObj == null) |
| | | // { |
| | | // // _logger.LogWarning("DeleteAndMoveIntoHtyï¼åå²è¡¨å®ä¾ {HtyTypeName} åå»ºç»æä¸ºnull", htyTypeName); |
| | | // return false; |
| | | // } |
| | | |
| | | // // 3. è·åæ ¸å¿å±æ§ï¼æå®BindingFlagsç¡®ä¿è·åå
Œ
±å®ä¾å±æ§ï¼ |
| | | // BindingFlags propFlags = BindingFlags.Public | BindingFlags.Instance; |
| | | // PropertyInfo? keyPro = typeof(TEntity).GetKeyProperty(); // èªå®ä¹æ¹æ³éç¡®ä¿è¿åéç©ºï¼æ¤å¤å¢å å¤ç©º |
| | | // PropertyInfo? operateTypePro = htyType.GetProperty(nameof(IBaseHistoryEntity.OperateType), propFlags); |
| | | // PropertyInfo? sourceIdPro = htyType.GetProperty(nameof(IBaseHistoryEntity.SourceId), propFlags); |
| | | |
| | | // // æ ¡éªæ ¸å¿å±æ§æ¯å¦åå¨ |
| | | // if (keyPro == null) |
| | | // { |
| | | // //_logger.LogError("DeleteAndMoveIntoHtyï¼å®ä½ {EntityType} æªæ¾å°ä¸»é®å±æ§", entityType.FullName); |
| | | // return false; |
| | | // } |
| | | // if (operateTypePro == null) |
| | | // { |
| | | // //_logger.LogError("DeleteAndMoveIntoHtyï¼åå²è¡¨ {HtyTypeName} æªæ¾å°OperateType屿§", htyTypeName); |
| | | // return false; |
| | | // } |
| | | // if (sourceIdPro == null) |
| | | // { |
| | | // // _logger.LogError("DeleteAndMoveIntoHtyï¼åå²è¡¨ {HtyTypeName} æªæ¾å°SourceId屿§", htyTypeName); |
| | | // return false; |
| | | // } |
| | | |
| | | // // 4. èµå¼æ ¸å¿å±æ§ï¼æ ¡éªç±»åå¹é
ï¼é¿å
SetValueæå¼å¸¸ï¼ |
| | | // try |
| | | // { |
| | | // // å¤çOperateTypeç±»åå¹é
ï¼è¥åå²è¡¨å±æ§æ¯æä¸¾ç±»åï¼ç´æ¥ä¼ æä¸¾èéå符串 |
| | | // if (operateTypePro.PropertyType == typeof(OperateTypeEnum)) |
| | | // { |
| | | // operateTypePro.SetValue(htyObj, operateType); |
| | | // } |
| | | // else if (operateTypePro.PropertyType == typeof(string)) |
| | | // { |
| | | // operateTypePro.SetValue(htyObj, operateType.ToString()); |
| | | // } |
| | | // else |
| | | // { |
| | | // //_logger.LogError("DeleteAndMoveIntoHtyï¼åå²è¡¨ {HtyTypeName} çOperateType屿§ç±»å {PropType} ä¸å¹é
ï¼ä»
æ¯ææä¸¾/å符串ï¼", htyTypeName, operateTypePro.PropertyType.FullName); |
| | | // return false; |
| | | // } |
| | | |
| | | // // èµå¼SourceIdï¼æ ¡éªç±»åå¹é
ï¼ |
| | | // object sourceIdValue = keyPro.GetValue(entity)!; |
| | | // if (sourceIdPro.PropertyType != sourceIdValue.GetType()) |
| | | // { |
| | | // sourceIdValue = Convert.ChangeType(sourceIdValue, sourceIdPro.PropertyType); // ç±»åè½¬æ¢ |
| | | // } |
| | | // sourceIdPro.SetValue(htyObj, sourceIdValue); |
| | | // } |
| | | // catch (Exception ex) |
| | | // { |
| | | // // _logger.LogError(ex, "DeleteAndMoveIntoHtyï¼åå²è¡¨ {HtyTypeName} æ ¸å¿å±æ§èµå¼å¤±è´¥", htyTypeName); |
| | | // return false; |
| | | // } |
| | | |
| | | // // 5. èµå¼å
¶ä»å±æ§ï¼æé¤æ ¸å¿å±æ§ï¼ |
| | | // List<PropertyInfo> htyProperties = htyType.GetProperties(propFlags) |
| | | // .Where(x => x.Name != operateTypePro.Name |
| | | // && x.Name != sourceIdPro.Name |
| | | // && x.Name != keyPro.Name) |
| | | // .ToList(); |
| | | |
| | | // foreach (PropertyInfo htyProp in htyProperties) |
| | | // { |
| | | // PropertyInfo? entityProp = entityType.GetProperty(htyProp.Name, propFlags); |
| | | // if (entityProp == null) continue; // å®ä½æ è¯¥å±æ§åè·³è¿ |
| | | |
| | | // try |
| | | // { |
| | | // object propValue; |
| | | // // å¤çä¿®æ¹äººï¼é¿å
App.User空å¼ç¨ |
| | | // if (htyProp.Name == nameof(BaseEntity.Modifier)) |
| | | // { |
| | | // propValue = App.User?.UserId > 0 ? App.User?.UserName : "System"; |
| | | // } |
| | | // // å¤çä¿®æ¹æ¶é´ |
| | | // else if (htyProp.Name == nameof(BaseEntity.ModifyDate)) |
| | | // { |
| | | // propValue = DateTime.Now; |
| | | // } |
| | | // // å
¶ä»å±æ§ä»åå®ä½åå¼ |
| | | // else |
| | | // { |
| | | // propValue = entityProp.GetValue(entity) ?? DBNull.Value; // å¤çnullå¼ |
| | | // } |
| | | |
| | | // // ç±»å转æ¢åèµå¼ï¼é¿å
ç±»åä¸å¹é
ï¼ |
| | | // if (propValue != DBNull.Value && propValue != null) |
| | | // { |
| | | // propValue = Convert.ChangeType(propValue, htyProp.PropertyType); |
| | | // } |
| | | // htyProp.SetValue(htyObj, propValue); |
| | | // } |
| | | // catch (Exception ex) |
| | | // { |
| | | // // _logger.LogWarning(ex, "DeleteAndMoveIntoHtyï¼åå²è¡¨ {HtyTypeName} 屿§ {PropName} èµå¼å¤±è´¥ï¼è·³è¿è¯¥å±æ§", htyTypeName, htyProp.Name); |
| | | // } |
| | | // } |
| | | // try |
| | | // { |
| | | // // æ§è¡æå
¥åå²è¡¨ |
| | | // int insertRows = _db.InsertableByObject(htyObj).AS(entityType.Name + "_Hty").ExecuteCommand(); |
| | | |
| | | // if (insertRows <= 0) |
| | | // { |
| | | // // _logger.LogError("DeleteAndMoveIntoHtyï¼åå²è¡¨ {HtyTypeName} æå
¥å¤±è´¥ï¼å½±åè¡æ°0ï¼", htyTypeName); |
| | | // _db.InsertableByObject(htyObj).AS(entityType.Name + "_Hty").ExecuteCommand(); |
| | | // return false; |
| | | // } |
| | | // // æå
¥æååæ§è¡å é¤ |
| | | // bool deleteSuccess = DeleteData(entity); |
| | | // if (!deleteSuccess) |
| | | // { |
| | | // //_logger.LogError("DeleteAndMoveIntoHtyï¼å®ä½ {EntityType} å é¤å¤±è´¥", entityType.FullName); |
| | | // DeleteData(entity); |
| | | // return false; |
| | | // } |
| | | // // æäº¤äºå¡ |
| | | |
| | | // isSuccess = true; |
| | | // //_logger.LogInformation("DeleteAndMoveIntoHtyï¼å®ä½ {EntityType} å·²æåç§»å
¥åå²è¡¨å¹¶å é¤åæ°æ®", entityType.FullName); |
| | | // } |
| | | // catch (Exception ex) |
| | | // { |
| | | |
| | | // // _logger.LogError(ex, "DeleteAndMoveIntoHtyï¼äºå¡æ§è¡å¤±è´¥ï¼æå
¥åå²è¡¨/å é¤åæ°æ®ï¼", entityType.FullName); |
| | | // return false; |
| | | // } |
| | | // } |
| | | // catch (Exception ex) |
| | | // { |
| | | // // _logger.LogError(ex, "DeleteAndMoveIntoHtyï¼å¤çå®ä½ {EntityTypeName} æ¶åçæªæè·å¼å¸¸", entityTypeName); |
| | | // return false; |
| | | // } |
| | | |
| | | // return isSuccess; |
| | | //} |
| | | |
| | | |
| | | |
| | | public bool DeleteAndMoveIntoHty(List<TEntity> entities, OperateTypeEnum operateType) |
| | | { |
| | | Type type = typeof(TEntity); |
| | | Assembly assembly = type.Assembly; |
| | | Type? htyType = assembly.GetType(type.FullName + "_Hty"); |
| | | if (htyType != null) |
| | | { |
| | | object? obj2 = Activator.CreateInstance(htyType); |
| | | PropertyInfo keyPro = typeof(TEntity).GetKeyProperty(); |
| | | PropertyInfo? operateTypePro = htyType.GetProperty(nameof(IBaseHistoryEntity.OperateType)); |
| | | PropertyInfo? sourceIdPro = htyType.GetProperty(nameof(IBaseHistoryEntity.SourceId)); |
| | | if (obj2 != null && keyPro != null && operateTypePro != null && sourceIdPro != null) |
| | | { |
| | | Type type = typeof(TEntity); |
| | | Assembly assembly = type.Assembly; |
| | | Type? htyType = assembly.GetType(type.FullName + "_Hty"); |
| | | if (htyType != null) |
| | | List<PropertyInfo> propertyInfos = htyType.GetProperties().Where(x => x.Name != operateTypePro.Name && x.Name != sourceIdPro.Name && x.Name != keyPro.Name).ToList(); |
| | | List<object> list = new List<object>(); |
| | | foreach (var item in entities) |
| | | { |
| | | object? obj2 = Activator.CreateInstance(htyType); |
| | | PropertyInfo keyPro = typeof(TEntity).GetKeyProperty(); |
| | | PropertyInfo? operateTypePro = htyType.GetProperty(nameof(IBaseHistoryEntity.OperateType)); |
| | | PropertyInfo? sourceIdPro = htyType.GetProperty(nameof(IBaseHistoryEntity.SourceId)); |
| | | if (obj2 != null && keyPro != null && operateTypePro != null && sourceIdPro != null) |
| | | object? obj = Activator.CreateInstance(htyType); |
| | | if (obj != null) |
| | | { |
| | | List<PropertyInfo> propertyInfos = htyType.GetProperties().Where(x => x.Name != operateTypePro.Name && x.Name != sourceIdPro.Name && x.Name != keyPro.Name).ToList(); |
| | | List<object> list = new List<object>(); |
| | | foreach (var item in entities) |
| | | operateTypePro.SetValue(obj, operateType.ToString()); |
| | | sourceIdPro.SetValue(obj, keyPro.GetValue(item)); |
| | | for (int i = 0; i < propertyInfos.Count; i++) |
| | | { |
| | | object? obj = Activator.CreateInstance(htyType); |
| | | if (obj != null) |
| | | { |
| | | operateTypePro.SetValue(obj, operateType.ToString()); |
| | | sourceIdPro.SetValue(obj, keyPro.GetValue(item)); |
| | | for (int i = 0; i < propertyInfos.Count; i++) |
| | | { |
| | | PropertyInfo propertyInfo = propertyInfos[i]; |
| | | PropertyInfo? property = type.GetProperty(propertyInfo.Name); |
| | | PropertyInfo propertyInfo = propertyInfos[i]; |
| | | PropertyInfo? property = type.GetProperty(propertyInfo.Name); |
| | | |
| | | if (property != null) |
| | | { |
| | | if (propertyInfo.Name == nameof(BaseEntity.Modifier)) |
| | | { |
| | | propertyInfo.SetValue(obj, App.User.UserId > 0 ? App.User.UserName : "System"); |
| | | } |
| | | else if (propertyInfo.Name == nameof(BaseEntity.ModifyDate)) |
| | | { |
| | | propertyInfo.SetValue(obj, DateTime.Now); |
| | | } |
| | | else |
| | | { |
| | | propertyInfo.SetValue(obj, property.GetValue(item)); |
| | | } |
| | | } |
| | | if (property != null) |
| | | { |
| | | if (propertyInfo.Name == nameof(BaseEntity.Modifier)) |
| | | { |
| | | propertyInfo.SetValue(obj, App.User.UserId > 0 ? App.User.UserName : "System"); |
| | | } |
| | | list.Add(obj); |
| | | else if (propertyInfo.Name == nameof(BaseEntity.ModifyDate)) |
| | | { |
| | | propertyInfo.SetValue(obj, DateTime.Now); |
| | | } |
| | | else |
| | | { |
| | | propertyInfo.SetValue(obj, property.GetValue(item)); |
| | | } |
| | | } |
| | | } |
| | | if (list.Count > 0) |
| | | _db.InsertableByObject(list).AS(type.Name + "_Hty").ExecuteCommand(); |
| | | |
| | | list.Add(obj); |
| | | } |
| | | } |
| | | return DeleteData(entities); |
| | | if (list.Count > 0) |
| | | _db.InsertableByObject(list).AS(type.Name + "_Hty").ExecuteCommand(); |
| | | |
| | | } |
| | | } |
| | | return DeleteData(entities); |
| | | } |
| | | //List<TResult> QueryMuch<T, T2, T3, TResult>( |
| | | // Expression<Func<T, T2, T3, object[]>> joinExpression, |
| | | // Expression<Func<T, T2, T3, TResult>> selectExpression, |
| | |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | using WIDESEA_Common.CommonEnum; |
| | | using WIDESEA_Common.TaskEnum; |
| | | using WIDESEA_Core; |
| | | using WIDESEA_Core.BaseRepository; |
| | | using WIDESEA_Core.BaseServices; |
| | |
| | | |
| | | Task<WebResponseContent> TaskCompleted(string taskNum); |
| | | |
| | | Task TaskStatusChange(string taskNum, TaskStatusEnum taskStatusEnum); |
| | | |
| | | Task<WebResponseContent> GenerateOutboundTasksAsync(int[] keys, string outStation); |
| | | |
| | | Task<WebResponseContent> GenerateOutboundTask(int orderDetailId, List<StockSelectViewDTO> stockSelectViews,string station=null); |
| | |
| | | |
| | | public interface ITask_HtyService : IService<Dt_Task_Hty> |
| | | { |
| | | bool DeleteAndMoveIntoHty(Dt_Task task, OperateTypeEnum operateType); |
| | | } |
| | |
| | | |
| | | namespace WIDESEA_Model.Models |
| | | { |
| | | |
| | | |
| | | /// <summary> |
| | | /// æ£éè®°å½è¡¨ |
| | | /// </summary> |
| | | |
| | | |
| | | [SugarTable(nameof(Dt_PickingRecord), "æ£éè®°å½è¡¨")] |
| | | |
| | | public class Dt_PickingRecord : BaseEntity |
| | |
| | | [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] |
| | | public int Id { get; set; } |
| | | |
| | | public int TaskNo { get; set; } |
| | | public int TaskNo { get; set; } |
| | | public string OrderNo { get; set; } |
| | | public int OrderDetailId { get; set; } |
| | | |
| | |
| | | public decimal BarcodeMoveQty { get; set; } |
| | | |
| | | public int ReturnToMESStatus { get; set; } |
| | | |
| | | public string FeedBackMesDocumentNo { get; set; } |
| | | } |
| | | |
| | | |
| | |
| | | /// ååºæ°é |
| | | /// </summary> |
| | | public decimal ReturnQty { get; set; } |
| | | |
| | | |
| | | public DateTime ReturnTime { get; set; } |
| | | /// <summary> |
| | | /// 0-å¾
ååº 1-å·²ååº |
| | |
| | | /// æå
è®°å½è¡¨ |
| | | /// </summary> |
| | | [SugarTable("Dt_SplitPackageRecord")] |
| | | public class Dt_SplitPackageRecord: BaseEntity |
| | | public class Dt_SplitPackageRecord : BaseEntity |
| | | { |
| | | [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] |
| | | public int Id { get; set; } |
| | |
| | | public int OutStockLockInfoId { get; set; } // å
³èçåºåºéå®ä¿¡æ¯ |
| | | public string OriginalBarcode { get; set; } // åæ¡ç |
| | | public string NewBarcode { get; set; } // æ°æ¡ç |
| | | |
| | | public string FactoryArea { get; set; } |
| | | |
| | | public string FactoryArea { get; set; } |
| | | /// <summary> |
| | | /// æåæ°éï¼æ°æ¡ç æ°éï¼ |
| | | /// </summary> |
| | |
| | | [SugarColumn(IsNullable = true)] |
| | | public decimal? OriginalStockQuantity { get; set; } |
| | | |
| | | public decimal StockBeforeSplit { get; set; } |
| | | public decimal StockBeforeSplit { get; set; } |
| | | public decimal AssignBeforeSplit { get; set; } |
| | | } |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using Newtonsoft.Json; |
| | | using SqlSugar; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.ComponentModel.DataAnnotations; |
| | | using System.Linq; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | using WIDESEA_Core.DB.Models; |
| | | |
| | | namespace WIDESEA_Model.Models.Outbound |
| | | { |
| | | |
| | | /// <summary> |
| | | /// æ¥å£æ¥å¿è®°å½è¡¨ |
| | | /// </summary> |
| | | [SugarTable("Dt_InterfaceLog")] |
| | | public class Dt_InterfaceLog : BaseEntity |
| | | { |
| | | /// <summary> |
| | | /// 主é®IDï¼èªå¢ï¼ |
| | | /// </summary> |
| | | [SugarColumn(ColumnName = "Id", IsPrimaryKey = true, IsIdentity = true)] |
| | | public long Id { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 订åå· |
| | | /// </summary> |
| | | [SugarColumn(ColumnName = "OrderNo", Length = 100, IsNullable = false)] |
| | | [Required(ErrorMessage = "订åå·ä¸è½ä¸ºç©º")] |
| | | public string OrderNo { get; set; } |
| | | |
| | | /// <summary> |
| | | /// ææ¡£å· |
| | | /// </summary> |
| | | [SugarColumn(ColumnName = "DocumentNo", Length = 100, IsNullable = true)] |
| | | public string? DocumentNo { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 订åç±»å |
| | | /// </summary> |
| | | [SugarColumn(ColumnName = "OrderType", Length = 50, IsNullable = true)] |
| | | [Required(ErrorMessage = "订åç±»åä¸è½ä¸ºç©º")] |
| | | public string OrderType { get; set; } |
| | | |
| | | /// <summary> |
| | | /// JSONå
容 |
| | | /// </summary> |
| | | [SugarColumn(ColumnName = "Content", IsNullable = true, ColumnDataType = "nvarchar(max)")] |
| | | [Required(ErrorMessage = "å
容ä¸è½ä¸ºç©º")] |
| | | public string Content { get; set; } |
| | | |
| | | |
| | | |
| | | public int ReturnToMESStatus { get; set; } |
| | | /// <summary> |
| | | /// 软å 餿 å¿ |
| | | /// </summary> |
| | | [SugarColumn(ColumnName = "IsDeleted", IsNullable = false)] |
| | | public bool IsDeleted { get; set; } = false; |
| | | |
| | | |
| | | } |
| | | |
| | | } |
| | |
| | | using System; |
| | | using Newtonsoft.Json; |
| | | using SqlSugar; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.ComponentModel.DataAnnotations; |
| | | using System.Linq; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | |
| | | public List<string> BarCodeSubmit { get; set; } |
| | | } |
| | | |
| | | |
| | | } |
| | |
| | | using WIDESEA_IBasicService; |
| | | using WIDESEA_IOutboundService; |
| | | using WIDESEA_IStockService; |
| | | using WIDESEA_ITaskInfoService; |
| | | using WIDESEA_Model.Models; |
| | | using WIDESEA_Model.Models.Basic; |
| | | using WIDESEA_Model.Models.Outbound; |
| | |
| | | private readonly IDailySequenceService _dailySequenceService; |
| | | private readonly IAllocateService _allocateService; |
| | | private readonly IRepository<Dt_OutboundBatch> _outboundBatchRepository; |
| | | private readonly ITask_HtyService _task_HtyService; |
| | | private readonly ILogger<OutboundPickingService> _logger; |
| | | |
| | | private Dictionary<string, string> stations = new Dictionary<string, string> |
| | |
| | | public OutboundBatchPickingService(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, IESSApiService eSSApiService, ILogger<OutboundPickingService> logger, IInvokeMESService invokeMESService, IDailySequenceService dailySequenceService, IAllocateService allocateService, IRepository<Dt_OutboundBatch> outboundBatchRepository) : base(BaseDal) |
| | | IRepository<Dt_Task> taskRepository, IESSApiService eSSApiService, ILogger<OutboundPickingService> logger, IInvokeMESService invokeMESService, IDailySequenceService dailySequenceService, IAllocateService allocateService, IRepository<Dt_OutboundBatch> outboundBatchRepository, ITask_HtyService task_HtyService) : base(BaseDal) |
| | | { |
| | | _unitOfWorkManage = unitOfWorkManage; |
| | | _stockInfoService = stockInfoService; |
| | |
| | | _dailySequenceService = dailySequenceService; |
| | | _allocateService = allocateService; |
| | | _outboundBatchRepository = outboundBatchRepository; |
| | | _task_HtyService = task_HtyService; |
| | | } |
| | | |
| | | // <summary> |
| | |
| | | |
| | | // æ´æ°éå®è®°å½ç¶æä¸ºå·²ååº |
| | | lockInfo.Status = (int)OutLockStockStatusEnum.å·²ååº; |
| | | lockInfo.Operator = App.User.UserName; |
| | | lockInfo.Operator = App.User.UserName; |
| | | |
| | | await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync(); |
| | | |
| | |
| | | |
| | | // æ´æ°éå®è®°å½ç¶æä¸ºå·²ååº |
| | | lockInfo.Status = (int)OutLockStockStatusEnum.å·²ååº; |
| | | lockInfo.Operator = App.User.UserName; |
| | | lockInfo.Operator = App.User.UserName; |
| | | |
| | | await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync(); |
| | | |
| | |
| | | PalletType = stockInfo.PalletType, |
| | | WarehouseId = currentTask.WarehouseId |
| | | }; |
| | | try |
| | | { |
| | | await _taskRepository.Db.Insertable(returnTask).ExecuteCommandAsync(); |
| | | |
| | | await _taskRepository.Db.Insertable(returnTask).ExecuteCommandAsync(); |
| | | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _logger.LogInformation($"å建ååºä»»å¡å¤±è´¥ - 订å: {orderNo}, æç: {palletCode}"); |
| | | throw new Exception($"å建ååºä»»å¡å¤±è´¥ - 订å: {orderNo}, æç: {palletCode}"); |
| | | |
| | | } |
| | | // åéESSå½ä»¤ |
| | | await SendESSCommands(palletCode, currentTask.TargetAddress, returnTask); |
| | | |
| | |
| | | // åé
æ°éå¨è®¢åæç»å±é¢ç»ä¸å¤ç |
| | | var originalStatus = lockInfo.Status; |
| | | lockInfo.Status = (int)OutLockStockStatusEnum.å·²ååº; |
| | | lockInfo.Operator = App.User.UserName; |
| | | lockInfo.Operator = App.User.UserName; |
| | | |
| | | await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync(); |
| | | |
| | |
| | | /// <summary> |
| | | /// å¤çæªåæ£çéå®è®°å½ååº |
| | | /// </summary> |
| | | |
| | | |
| | | |
| | | /// <summary> |
| | | /// å¤çæçä¸çåºåè´§ç©ååº |
| | |
| | | |
| | | }; |
| | | // ä¿åååºä»»å¡ |
| | | await _taskRepository.Db.Insertable(returnTask).ExecuteCommandAsync(); |
| | | var insertcount = await _taskRepository.Db.Insertable(returnTask).ExecuteCommandAsync(); |
| | | if (insertcount <= 0) |
| | | { |
| | | throw new Exception("å建任å¡å¤±è´¥ï¼"); |
| | | } |
| | | var targetAddress = originalTask.TargetAddress; |
| | | |
| | | // å é¤åå§åºåºä»»å¡ |
| | | _taskRepository.DeleteAndMoveIntoHty(originalTask, OperateTypeEnum.èªå¨å®æ); |
| | | //_taskRepository.DeleteAndMoveIntoHty(originalTask, OperateTypeEnum.èªå¨å®æ); |
| | | _task_HtyService.DeleteAndMoveIntoHty(originalTask, OperateTypeEnum.人工å é¤); |
| | | await _taskRepository.Db.Deleteable(originalTask).ExecuteCommandAsync(); |
| | | |
| | | |
| | |
| | | using Microsoft.Extensions.Logging; |
| | | using Autofac.Core; |
| | | using Microsoft.Extensions.Logging; |
| | | using SqlSugar; |
| | | using WIDESEA_Common.LocationEnum; |
| | | using WIDESEA_Common.OrderEnum; |
| | |
| | | |
| | | // æ´æ°åºåºåæç»ç¶æ |
| | | UpdateOrderDetailStatus(item.Details, allocatedQuantity, needQuantity); |
| | | |
| | | |
| | | // æ´æ°åºååæçç¶æ |
| | | UpdateNormalStocksAndPalletsStatus(autoAssignStocks, stockAllocations); |
| | | } |
| | | |
| | | if (outStocks.Any()) |
| | |
| | | |
| | | return (outStocks, outboundOrderDetails, outStockLockInfos, locationInfos); |
| | | } |
| | | /// <summary> |
| | | /// æ´æ°åºååæçç¶æ |
| | | /// </summary> |
| | | private void UpdateNormalStocksAndPalletsStatus(List<Dt_StockInfo> stocks, Dictionary<int, decimal> stockAllocations) |
| | | { |
| | | foreach (var stock in stocks) |
| | | { |
| | | var stockDetail = stock.Details.First(); |
| | | if (stockAllocations.TryGetValue(stockDetail.Id, out decimal allocatedQty) && allocatedQty > 0) |
| | | { |
| | | |
| | | _stockService.StockInfoService.Db.Updateable<Dt_StockInfo>() |
| | | .SetColumns(x => new Dt_StockInfo |
| | | { |
| | | StockStatus = (int)StockStatusEmun.åºåºéå®, |
| | | }) |
| | | .Where(x => x.Id == stock.Id) |
| | | .ExecuteCommand(); |
| | | } |
| | | } |
| | | } |
| | | /// <summary> |
| | | /// æ£æ¥è®¢åæ¯å¦å
è®¸éæ°åé
|
| | | /// </summary> |
| | |
| | | |
| | | // æ´æ°åºåºåæç»ç¶æ |
| | | UpdateOrderDetailStatus(item.Details, allocatedQuantity, needQuantity); |
| | | |
| | | // æ´æ°åºååæçç¶æä¸ºåºåºéå® |
| | | await UpdateStocksAndPalletsStatus(autoAssignStocks, stockAllocations); |
| | | } |
| | | |
| | | if (outStocks.Any()) |
| | |
| | | |
| | | return (outStocks, groupDetails.SelectMany(x => x.Details).ToList(), outStockLockInfos, locationInfos); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ´æ°åºååæçç¶æ |
| | | /// </summary> |
| | | private async Task UpdateStocksAndPalletsStatus(List<Dt_StockInfo> stocks, Dictionary<int, decimal> stockAllocations) |
| | | { |
| | | foreach (var stock in stocks) |
| | | { |
| | | var stockDetail = stock.Details.First(); |
| | | if (stockAllocations.TryGetValue(stockDetail.Id, out decimal allocatedQty) && allocatedQty > 0) |
| | | { |
| | | |
| | | await _stockService.StockInfoService.Db.Updateable<Dt_StockInfo>() |
| | | .SetColumns(x => new Dt_StockInfo |
| | | { |
| | | StockStatus = (int)StockStatusEmun.åºåºéå®, |
| | | }) |
| | | .Where(x => x.Id == stock.Id) |
| | | .ExecuteCommandAsync(); |
| | | } |
| | | } |
| | | } |
| | | /// <summary> |
| | | /// æå
è¿å
åºåååé
é宿°é |
| | | /// </summary> |
| | |
| | | if (userSelection == null) continue; |
| | | |
| | | // 计ç®è¯¥æçå®é
å¯ç¨æ°é |
| | | var availableQuantity = CalculateAvailableQuantity(stock, outboundOrderDetail.MaterielCode, |
| | | outboundOrderDetail.BatchNo, outboundOrderDetail.SupplyCode); |
| | | var availableQuantity = CalculateAvailableQuantityByBarcode(stock, outboundOrderDetail.MaterielCode, |
| | | outboundOrderDetail.BatchNo, outboundOrderDetail.SupplyCode, userSelection.Barcode); |
| | | |
| | | // ç¡®å®åé
æ°éï¼åç¨æ·éæ©æ°éãå¯ç¨æ°éåå©ä½éæ±çæå°å¼ |
| | | var assignQuantity = Math.Min(Math.Min(userSelection.UseableQuantity, availableQuantity),remainingNeedQuantity); |
| | | var assignQuantity = Math.Min(Math.Min(userSelection.UseableQuantity, availableQuantity), remainingNeedQuantity); |
| | | |
| | | if (assignQuantity <= 0) continue; |
| | | |
| | | // æ§è¡åé
|
| | | var actualAssigned = AssignStockQuantity(stock, outboundOrderDetail, assignQuantity); |
| | | // æ§è¡åé
ï¼ä½¿ç¨ç¨æ·éæ©çæ¡ç |
| | | var actualAssigned = AssignStockQuantity(stock, outboundOrderDetail, assignQuantity, userSelection.Barcode); |
| | | |
| | | if (actualAssigned > 0) |
| | | { |
| | | outStocks.Add(stock); |
| | | totalAssignedFromUserSelection += actualAssigned; |
| | | remainingNeedQuantity -= actualAssigned; |
| | | |
| | | // å建éå®è®°å½ |
| | | var lockInfo = CreateOutStockLockInfo(outboundOrder, outboundOrderDetail, stock, actualAssigned); |
| | | // å建éå®è®°å½ï¼ä½¿ç¨ç¨æ·éæ©çæ¡ç |
| | | var lockInfo = CreateOutStockLockInfo(outboundOrder, outboundOrderDetail, stock, actualAssigned, userSelection.Barcode); |
| | | outStockLockInfos.Add(lockInfo); |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | // æ´æ°é宿°é |
| | | outboundOrderDetail.LockQuantity += totalAssignedFromUserSelection + totalAssignedFromUserSelection; |
| | | outboundOrderDetail.LockQuantity += totalAssignedFromUserSelection; |
| | | |
| | | // æ´æ°ç¶æ |
| | | UpdateOrderDetailStatus(outboundOrderDetail, remainingNeedQuantity); |
| | |
| | | |
| | | return (outStocks, outboundOrderDetail, outStockLockInfos, locationInfos); |
| | | } |
| | | private decimal CalculateAvailableQuantityByBarcode(Dt_StockInfo stock, string materielCode, string batchNo, string supplyCode, string barcode) |
| | | { |
| | | var query = stock.Details.AsQueryable() |
| | | .Where(d => d.MaterielCode == materielCode && |
| | | (d.StockQuantity - d.OutboundQuantity) > 0 && |
| | | d.Barcode == barcode); |
| | | |
| | | if (!string.IsNullOrEmpty(batchNo)) |
| | | { |
| | | query = query.Where(x => x.BatchNo == batchNo); |
| | | } |
| | | |
| | | if (!string.IsNullOrEmpty(supplyCode)) |
| | | { |
| | | query = query.Where(d => d.SupplyCode == supplyCode); |
| | | } |
| | | |
| | | return query.Sum(d => d.StockQuantity - d.OutboundQuantity); |
| | | } |
| | | // è¾
婿¹æ³ |
| | | private decimal CalculateAvailableQuantity(Dt_StockInfo stock, string materielCode, string batchNo, string supplyCode) |
| | | { |
| | |
| | | return relevantDetails.Sum(d => d.StockQuantity - d.OutboundQuantity); |
| | | } |
| | | |
| | | private decimal AssignStockQuantity(Dt_StockInfo stock, Dt_OutboundOrderDetail detail, decimal assignQuantity) |
| | | private decimal AssignStockQuantity(Dt_StockInfo stock, Dt_OutboundOrderDetail detail, decimal assignQuantity, string barcode) |
| | | { |
| | | decimal remainingAssign = assignQuantity; |
| | | |
| | | // æå
è¿å
åºåé
æå®æ¡ç çåºåæç» |
| | | var query = stock.Details.AsQueryable() |
| | | .Where(d => d.MaterielCode == detail.MaterielCode && |
| | | (d.StockQuantity - d.OutboundQuantity) > 0 && |
| | | d.Barcode == barcode); // åªåé
æå®æ¡ç |
| | | |
| | | if (!string.IsNullOrEmpty(detail.BatchNo)) |
| | | { |
| | | query = query.Where(x => x.BatchNo == detail.BatchNo); |
| | | } |
| | | // 妿åºåºåæä¾åºåè¦æ±ï¼æä¾åºåè¿æ»¤ |
| | | if (!string.IsNullOrEmpty(detail.SupplyCode)) |
| | | { |
| | | query = query.Where(d => d.SupplyCode == detail.SupplyCode); |
| | | } |
| | | var sortedDetails = query.ToList().OrderBy(d => d.CreateDate); |
| | | |
| | | foreach (var stockDetail in sortedDetails) |
| | | { |
| | | if (remainingAssign <= 0) break; |
| | | |
| | | var available = stockDetail.StockQuantity - stockDetail.OutboundQuantity; |
| | | var assign = Math.Min(available, remainingAssign); |
| | | |
| | | stockDetail.OutboundQuantity += assign; |
| | | remainingAssign -= assign; |
| | | } |
| | | |
| | | return assignQuantity - remainingAssign; // è¿åå®é
åé
æ°é |
| | | } |
| | | |
| | | private (decimal assignedQuantity, string barcode) AssignStockQuantity(Dt_StockInfo stock, Dt_OutboundOrderDetail detail, decimal assignQuantity) |
| | | { |
| | | decimal remainingAssign = assignQuantity; |
| | | string assignedBarcode = string.Empty; |
| | | |
| | | // æå
è¿å
åºåé
åºåæç» |
| | | var query = stock.Details.AsQueryable() |
| | |
| | | |
| | | stockDetail.OutboundQuantity += assign; |
| | | remainingAssign -= assign; |
| | | if (string.IsNullOrEmpty(assignedBarcode) && assign > 0) |
| | | { |
| | | assignedBarcode = stockDetail.Barcode; |
| | | } |
| | | } |
| | | |
| | | return assignQuantity - remainingAssign; // è¿åå®é
åé
æ°é |
| | | |
| | | return (assignQuantity - remainingAssign, assignedBarcode); |
| | | } |
| | | |
| | | private Dt_OutStockLockInfo CreateOutStockLockInfo(Dt_OutboundOrder outboundOrder, Dt_OutboundOrderDetail detail, |
| | | Dt_StockInfo stock, decimal quantity) |
| | | Dt_StockInfo stock, decimal quantity,string barcode="") |
| | | { |
| | | var barcode = stock.Details |
| | | .Where(d => !string.IsNullOrEmpty(d.Barcode)) |
| | | .Select(d => d.Barcode) |
| | | .FirstOrDefault(); |
| | | |
| | | |
| | | return _outStockLockInfoService.GetOutStockLockInfo(outboundOrder, detail, stock, quantity, barcode); |
| | | } |
| | |
| | | return (false, $"æç[{selection.PalletCode}]ä¸åå¨"); |
| | | } |
| | | |
| | | var available = CalculateAvailableQuantity(stock, outboundOrderDetail.MaterielCode, |
| | | outboundOrderDetail.BatchNo, outboundOrderDetail.SupplyCode); |
| | | var available = CalculateAvailableQuantityByBarcode(stock, outboundOrderDetail.MaterielCode, |
| | | outboundOrderDetail.BatchNo, outboundOrderDetail.SupplyCode,selection.Barcode); |
| | | |
| | | if (available <= 0) |
| | | { |
| | |
| | | } |
| | | var data = BaseDal.Db.Queryable<Dt_OutboundOrder>() |
| | | .WhereIF(!wheres.IsNullOrEmpty(), wheres) |
| | | .Where(x => x.OrderType == 0 || x.OrderType == 116) |
| | | .OrderBy(orderByModels) |
| | | .ToPageList(options.Page, options.Rows, ref totalCount); |
| | | |
| | |
| | | using WIDESEA_IInboundService; |
| | | using WIDESEA_IOutboundService; |
| | | using WIDESEA_IStockService; |
| | | using WIDESEA_ITaskInfoService; |
| | | using WIDESEA_Model.Models; |
| | | using WIDESEA_Model.Models.Basic; |
| | | using WIDESEA_Model.Models.Check; |
| | |
| | | private readonly IInboundOrderDetailService _inboundOrderDetailService; |
| | | private readonly IRepository<Dt_WarehouseArea> _warehouseAreaRepository; |
| | | private readonly IReCheckOrderService _reCheckOrderService; |
| | | private readonly ITask_HtyService _task_HtyService; |
| | | private readonly ILogger<OutboundPickingService> _logger; |
| | | |
| | | private Dictionary<string, string> stations = new Dictionary<string, string> |
| | |
| | | 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, IESSApiService eSSApiService, ILogger<OutboundPickingService> logger, IInvokeMESService invokeMESService, IDailySequenceService dailySequenceService, IAllocateService allocateService, IRepository<Dt_InboundOrder> inboundOrderRepository, IInboundOrderDetailService inboundOrderDetailService, IRepository<Dt_WarehouseArea> warehouseAreaRepository, IReCheckOrderService reCheckOrderService) : base(BaseDal) |
| | | IRepository<Dt_Task> taskRepository, IESSApiService eSSApiService, ILogger<OutboundPickingService> logger, IInvokeMESService invokeMESService, IDailySequenceService dailySequenceService, IAllocateService allocateService, IRepository<Dt_InboundOrder> inboundOrderRepository, IInboundOrderDetailService inboundOrderDetailService, IRepository<Dt_WarehouseArea> warehouseAreaRepository, IReCheckOrderService reCheckOrderService, ITask_HtyService task_HtyService) : base(BaseDal) |
| | | { |
| | | _unitOfWorkManage = unitOfWorkManage; |
| | | _stockInfoService = stockInfoService; |
| | |
| | | _inboundOrderDetailService = inboundOrderDetailService; |
| | | _warehouseAreaRepository = warehouseAreaRepository; |
| | | _reCheckOrderService = reCheckOrderService; |
| | | _task_HtyService = task_HtyService; |
| | | } |
| | | |
| | | |
| | |
| | | { |
| | | // è·åææ°ç订åæç»æ°æ®ï¼å¸¦éï¼ |
| | | var currentOrderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | .With(SqlWith.RowLock) |
| | | //.With(SqlWith.RowLock) |
| | | .FirstAsync(x => x.Id == orderDetailId); |
| | | |
| | | decimal newOverOutQuantity = currentOrderDetail.OverOutQuantity - cancelQty; |
| | |
| | | WarehouseId = originalTask.WarehouseId |
| | | |
| | | }; |
| | | // ä¿åååºä»»å¡ |
| | | await _taskRepository.Db.Insertable(returnTask).ExecuteCommandAsync(); |
| | | try |
| | | { |
| | | // ä¿åååºä»»å¡ |
| | | var insertcount = await _taskRepository.Db.Insertable(returnTask).ExecuteCommandAsync(); |
| | | if (insertcount <= 0) |
| | | { |
| | | throw new Exception("å建任å¡å¤±è´¥ï¼"); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _logger.LogInformation($"CreateReturnTaskAndHandleESS å建任å¡å¤±è´¥: {orderNo} ï¼ {palletCode}"); |
| | | throw new Exception("å建任å¡å¤±è´¥ï¼"); |
| | | } |
| | | var targetAddress = originalTask.TargetAddress; |
| | | |
| | | // å é¤åå§åºåºä»»å¡ |
| | | _taskRepository.DeleteAndMoveIntoHty(originalTask, OperateTypeEnum.èªå¨å®æ); |
| | | await _taskRepository.Db.Deleteable(originalTask).ExecuteCommandAsync(); |
| | | |
| | | // _taskRepository.DeleteAndMoveIntoHty(originalTask, OperateTypeEnum.èªå¨å®æ); |
| | | var result = _task_HtyService.DeleteAndMoveIntoHty(originalTask, OperateTypeEnum.人工å é¤); |
| | | if (!result) |
| | | { |
| | | await _taskRepository.Db.Deleteable(originalTask).ExecuteCommandAsync(); |
| | | } |
| | | |
| | | |
| | | // ç» ESS åéæµå¨ä¿¡å·ååå»ºä»»å¡ |
| | |
| | | { |
| | | // 1. å é¤åºåæ°é为0çæç»è®°å½ |
| | | var deleteDetailCount = await _stockInfoDetailService.Db.Deleteable<Dt_StockInfoDetail>() |
| | | .Where(x => x.StockId == stockId && x.StockQuantity == 0 && (x.Status == StockStatusEmun.åºåºå®æ.ObjToInt() || x.Status == |
| | | StockStatusEmun.å
¥åºå®æ.ObjToInt())) |
| | | .Where(x => x.StockId == stockId && x.StockQuantity == 0) |
| | | .ExecuteCommandAsync(); |
| | | |
| | | await _stockInfoService.Db.Deleteable<Dt_StockInfo>() |
| | |
| | | TaskNum = 0, |
| | | Status = (int)OutLockStockStatusEnum.æ£é宿, |
| | | Unit = outboundOrderDetail.Unit, |
| | | SupplyCode = outboundOrderDetail.SupplyCode?? "æ ", |
| | | SupplyCode = outboundOrderDetail.SupplyCode ?? "æ ", |
| | | OrderType = outboundOrder.OrderType, |
| | | CurrentBarcode = inboundOrderDetail.Barcode, |
| | | IsSplitted = 1, |
| | | Operator = App.User.UserName, |
| | | lineNo= outboundOrderDetail.lineNo, |
| | | lineNo = outboundOrderDetail.lineNo, |
| | | WarehouseCode = outboundOrderDetail.WarehouseCode ?? "æ ", |
| | | BarcodeQty=outboundOrderDetail.NoStockOutQty, |
| | | BarcodeUnit =outboundOrderDetail.BarcodeUnit, |
| | | BarcodeQty = outboundOrderDetail.NoStockOutQty, |
| | | BarcodeUnit = outboundOrderDetail.BarcodeUnit, |
| | | BatchNo = outboundOrderDetail.BatchNo |
| | | }; |
| | | _outStockLockInfoService.AddData(newLockInfo); |
| | |
| | | var documentNo = UniqueValueGenerator.Generate(); |
| | | |
| | | var outfeedmodel = new FeedbackOutboundRequestModel |
| | | { |
| | | reqCode = Guid.NewGuid().ToString(), |
| | | reqTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), |
| | | business_type = outboundOrder.BusinessType, |
| | | factoryArea = outboundOrder.FactoryArea, |
| | | operationType = 1, |
| | | Operator = App.User.UserName, |
| | | orderNo = outboundOrder.UpperOrderNo, |
| | | documentsNO = documentNo, |
| | | status = outboundOrder.OrderStatus, |
| | | details = new List<FeedbackOutboundDetailsModel>() |
| | | }; |
| | | { |
| | | reqCode = Guid.NewGuid().ToString(), |
| | | reqTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), |
| | | business_type = outboundOrder.BusinessType, |
| | | factoryArea = outboundOrder.FactoryArea, |
| | | operationType = 1, |
| | | Operator = App.User.UserName, |
| | | orderNo = outboundOrder.UpperOrderNo, |
| | | documentsNO = documentNo, |
| | | status = outboundOrder.OrderStatus, |
| | | details = new List<FeedbackOutboundDetailsModel>() |
| | | }; |
| | | foreach (var detail in outboundOrder.Details) |
| | | { |
| | | // è·å该æç»å¯¹åºçæ¡ç ä¿¡æ¯ï¼ä»éå®è®°å½ï¼ |
| | |
| | | (x.Status == (int)OutLockStockStatusEnum.æ£é宿 || x.Status == (int)OutLockStockStatusEnum.å·²ååº)) |
| | | .ToListAsync(); |
| | | |
| | | var groupdata = detailLocks.GroupBy(item => new { item.MaterielCode, item.lineNo, item.BarcodeUnit, item.WarehouseCode }) |
| | | .Select(group => new FeedbackOutboundDetailsModel |
| | | { |
| | | var groupdata = detailLocks.GroupBy(item => new { item.MaterielCode, item.lineNo, item.BarcodeUnit, item.WarehouseCode }) |
| | | .Select(group => new FeedbackOutboundDetailsModel |
| | | { |
| | | |
| | | materialCode = group.Key.MaterielCode, |
| | | lineNo = group.Key.lineNo, |
| | | warehouseCode = group.Key.WarehouseCode, |
| | | qty = group.Sum(x => x.PickedQty), |
| | | currentDeliveryQty = group.Sum(x => x.PickedQty), |
| | | unit = group.Key.BarcodeUnit, |
| | | barcodes = group.Select(lockInfo => new WIDESEA_DTO.Outbound.BarcodesModel |
| | | { |
| | | barcode = lockInfo.CurrentBarcode, |
| | | supplyCode = lockInfo.SupplyCode, |
| | | batchNo = lockInfo.BatchNo, |
| | | unit = lockInfo.BarcodeUnit, |
| | | qty = lockInfo.PickedQty |
| | | }).ToList() |
| | | }).ToList(); |
| | | outfeedmodel.details.AddRange(groupdata); |
| | | } |
| | | var result = await _invokeMESService.FeedbackOutbound(outfeedmodel); |
| | | if (result != null && result.code == 200) |
| | | { |
| | | await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>() |
| | | .SetColumns(x => x.ReturnToMESStatus == 1) |
| | | .Where(x => x.OrderId == outboundOrder.Id) |
| | | .ExecuteCommandAsync(); |
| | | materialCode = group.Key.MaterielCode, |
| | | lineNo = group.Key.lineNo, |
| | | warehouseCode = group.Key.WarehouseCode, |
| | | qty = group.Sum(x => x.PickedQty), |
| | | currentDeliveryQty = group.Sum(x => x.PickedQty), |
| | | unit = group.Key.BarcodeUnit, |
| | | barcodes = group.Select(lockInfo => new WIDESEA_DTO.Outbound.BarcodesModel |
| | | { |
| | | barcode = lockInfo.CurrentBarcode, |
| | | supplyCode = lockInfo.SupplyCode, |
| | | batchNo = lockInfo.BatchNo, |
| | | unit = lockInfo.BarcodeUnit, |
| | | qty = lockInfo.PickedQty |
| | | }).ToList() |
| | | }).ToList(); |
| | | outfeedmodel.details.AddRange(groupdata); |
| | | } |
| | | var result = await _invokeMESService.FeedbackOutbound(outfeedmodel); |
| | | if (result != null && result.code == 200) |
| | | { |
| | | await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>() |
| | | .SetColumns(x => x.ReturnToMESStatus == 1) |
| | | .Where(x => x.OrderId == outboundOrder.Id) |
| | | .ExecuteCommandAsync(); |
| | | |
| | | await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>() |
| | | .SetColumns(x => x.ReturnToMESStatus == 1) |
| | |
| | | { |
| | | return content.Error("åªææ¿å°éæ£ç»ææè½å
¥åºï¼"); |
| | | } |
| | | |
| | | |
| | | } |
| | | // Dt_InboundOrder inboundOrder = GetInboundOrder(materielGroupDTO.OrderNo); |
| | | |
| | |
| | | stockInfo.Details = new List<Dt_StockInfoDetail>(); |
| | | } |
| | | var inboindId = 0; Dt_InboundOrder dt_InboundOrder = null; |
| | | var dbinbound = _inboundOrderRepository.QueryData(x => x.InboundOrderNo == dbinboundOrderDetails.First().OrderNo).First(); |
| | | var orderno = dbinboundOrderDetails.First().OrderNo; |
| | | var dbinbound = _inboundOrderRepository.QueryData(x => x.InboundOrderNo == orderno).FirstOrDefault(); |
| | | if (dbinbound == null) |
| | | { |
| | | dt_InboundOrder = new Dt_InboundOrder |
| | |
| | | FactoryArea = item.FactoryArea, |
| | | Status = 0, |
| | | OrderNo = item.OrderNo, |
| | | BusinessType = InOrderTypeEnum.InternalAllocat.ObjToInt().ToString() |
| | | BusinessType = materielGroupDTO.orderTypes.ToString() |
| | | |
| | | }); |
| | | item.WarehouseCode = item.WarehouseCode; |
| | |
| | | <ProjectReference Include="..\WIDESEA_IOutboundService\WIDESEA_IOutboundService.csproj" /> |
| | | <ProjectReference Include="..\WIDESEA_IRecordService\WIDESEA_IRecordService.csproj" /> |
| | | <ProjectReference Include="..\WIDESEA_IStockService\WIDESEA_IStockService.csproj" /> |
| | | <ProjectReference Include="..\WIDESEA_ITaskInfoService\WIDESEA_ITaskInfoService.csproj" /> |
| | | </ItemGroup> |
| | | |
| | | </Project> |
| | |
| | | private readonly IRecordService _recordService; |
| | | private readonly IAllocateService _allocateService; |
| | | private readonly IInvokeMESService _invokeMESService; |
| | | private readonly ITask_HtyService _task_HtyService; |
| | | public IRepository<Dt_Task> Repository => BaseDal; |
| | | |
| | | private Dictionary<string, SqlSugar.OrderByType> _taskOrderBy = new() |
| | |
| | | |
| | | public List<int> TaskOutboundTypes => typeof(TaskTypeEnum).GetEnumIndexList(); |
| | | |
| | | public TaskService(IRepository<Dt_Task> BaseDal, IMapper mapper, IUnitOfWorkManage unitOfWorkManage, IRepository<Dt_StockInfo> stockRepository, ILocationInfoService locationInfoService, IInboundOrderService inboundOrderService, ILocationStatusChangeRecordService locationStatusChangeRecordService, IESSApiService eSSApiService, ILogger<TaskService> logger, IStockService stockService, IRecordService recordService, IInboundOrderDetailService inboundOrderDetailService, IOutboundOrderService outboundOrderService, IOutboundOrderDetailService outboundOrderDetailService, IInvokeMESService invokeMESService, IOutStockLockInfoService outStockLockInfoService, IAllocateService allocateService, IRepository<Dt_OutboundBatch> outboundBatchRepository, IRepository<Dt_ReCheckOrder> reCheckOrderRepository, IRepository<Dt_AllocateOrderDetail> allocateOrderDetailRepository, IRepository<Dt_AllocateOrder> allocateOrderRepository, IMaterialUnitService materialUnitService) : base(BaseDal) |
| | | public TaskService(IRepository<Dt_Task> BaseDal, IMapper mapper, IUnitOfWorkManage unitOfWorkManage, IRepository<Dt_StockInfo> stockRepository, ILocationInfoService locationInfoService, IInboundOrderService inboundOrderService, ILocationStatusChangeRecordService locationStatusChangeRecordService, IESSApiService eSSApiService, ILogger<TaskService> logger, IStockService stockService, IRecordService recordService, IInboundOrderDetailService inboundOrderDetailService, IOutboundOrderService outboundOrderService, IOutboundOrderDetailService outboundOrderDetailService, IInvokeMESService invokeMESService, IOutStockLockInfoService outStockLockInfoService, IAllocateService allocateService, IRepository<Dt_OutboundBatch> outboundBatchRepository, IRepository<Dt_ReCheckOrder> reCheckOrderRepository, IRepository<Dt_AllocateOrderDetail> allocateOrderDetailRepository, IRepository<Dt_AllocateOrder> allocateOrderRepository, IMaterialUnitService materialUnitService, ITask_HtyService task_HtyService) : base(BaseDal) |
| | | { |
| | | _mapper = mapper; |
| | | _unitOfWorkManage = unitOfWorkManage; |
| | |
| | | _allocateOrderDetailRepository = allocateOrderDetailRepository; |
| | | _allocateOrderRepository = allocateOrderRepository; |
| | | _materialUnitService = materialUnitService; |
| | | _task_HtyService = task_HtyService; |
| | | } |
| | | |
| | | public async Task TaskStatusChange(string taskNum,TaskStatusEnum taskStatusEnum) |
| | | { |
| | | if (int.TryParse(taskNum, out var newTaskNum)) |
| | | { |
| | | await Db.Updateable<Dt_Task>().SetColumns(it => new Dt_Task { |
| | | TaskStatus = taskStatusEnum.ObjToInt() |
| | | }) |
| | | .Where(it => it.TaskNum == newTaskNum) |
| | | .ExecuteCommandAsync(); |
| | | } |
| | | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// |
| | |
| | | |
| | | task.TaskStatus = TaskStatusEnum.Finish.ObjToInt(); |
| | | |
| | | BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.èªå¨å®æ : OperateTypeEnum.äººå·¥å®æ); |
| | | |
| | | // BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.èªå¨å®æ : OperateTypeEnum.äººå·¥å®æ); |
| | | var result = _task_HtyService.DeleteAndMoveIntoHty(task, OperateTypeEnum.人工å é¤); |
| | | if (!result) |
| | | { |
| | | await Db.Deleteable(task).ExecuteCommandAsync(); |
| | | } |
| | | _locationStatusChangeRecordService.AddLocationStatusChangeRecord(locationInfo, beforeStatus, StockChangeType.Inbound.ObjToInt(), "", task.TaskNum); |
| | | |
| | | _recordService.StockQuantityChangeRecordService.AddStockChangeRecord(stockInfo, stockInfo.Details, beforeQuantity, stockInfo.Details.Sum(x => x.StockQuantity) + beforeQuantity, WIDESEA_Common.StockEnum.StockChangeType.MaterielGroup); |
| | |
| | | }).ToList(); |
| | | allocatefeedmodel.Details = groupedData; |
| | | |
| | | var result = await _invokeMESService.FeedbackAllocate(allocatefeedmodel); |
| | | if (result != null && result.code == 200) |
| | | var feedbackresult = await _invokeMESService.FeedbackAllocate(allocatefeedmodel); |
| | | if (feedbackresult != null && feedbackresult.code == 200) |
| | | { |
| | | _inboundOrderService.Db.Updateable<Dt_InboundOrder>().SetColumns(it => new Dt_InboundOrder { ReturnToMESStatus = 1 }) |
| | | .Where(it => it.Id == inboundOrder.Id).ExecuteCommand(); |
| | |
| | | }).ToList(); |
| | | allocatefeedmodel.Details = groupedData; |
| | | |
| | | var result = await _invokeMESService.FeedbackAllocate(allocatefeedmodel); |
| | | if (result != null && result.code == 200) |
| | | var feedbackresult = await _invokeMESService.FeedbackAllocate(allocatefeedmodel); |
| | | if (feedbackresult != null && feedbackresult.code == 200) |
| | | { |
| | | _inboundOrderService.Db.Updateable<Dt_InboundOrder>().SetColumns(it => new Dt_InboundOrder { ReturnToMESStatus = 1 }) |
| | | .Where(it => it.Id == inboundOrder.Id).ExecuteCommand(); |
| | |
| | | }).ToList(); |
| | | feedmodel.details = groupedData; |
| | | |
| | | var result = await _invokeMESService.FeedbackInbound(feedmodel); |
| | | if (result != null && result.code == 200) |
| | | var feedbackresult = await _invokeMESService.FeedbackInbound(feedmodel); |
| | | if (feedbackresult != null && feedbackresult.code == 200) |
| | | { |
| | | _inboundOrderService.Db.Updateable<Dt_InboundOrder>().SetColumns(it => new Dt_InboundOrder { ReturnToMESStatus = 1 }) |
| | | .Where(it => it.Id == inboundOrder.Id).ExecuteCommand(); |
| | |
| | | var outboundOrder = _outboundOrderService.Db.Queryable<Dt_OutboundOrder>().First(x => x.OrderNo == task.OrderNo); |
| | | |
| | | task.TaskStatus = TaskStatusEnum.Finish.ObjToInt(); |
| | | BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? WIDESEA_Core.Enums.OperateTypeEnum.èªå¨å®æ : OperateTypeEnum.äººå·¥å®æ); |
| | | |
| | | // BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? WIDESEA_Core.Enums.OperateTypeEnum.èªå¨å®æ : OperateTypeEnum.äººå·¥å®æ); |
| | | var result = _task_HtyService.DeleteAndMoveIntoHty(task, OperateTypeEnum.人工å é¤); |
| | | if (!result) |
| | | { |
| | | await Db.Deleteable(task).ExecuteCommandAsync(); |
| | | } |
| | | _locationStatusChangeRecordService.AddLocationStatusChangeRecord(locationInfo, beforelocationStatus, StockChangeType.Inbound.ObjToInt(), "", task.TaskNum); |
| | | |
| | | |
| | |
| | | task.TaskStatus = TaskStatusEnum.Finish.ObjToInt(); |
| | | |
| | | // å é¤ä»»å¡è®°å½ |
| | | BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.èªå¨å®æ : OperateTypeEnum.äººå·¥å®æ); |
| | | BaseDal.DeleteData(task); |
| | | |
| | | //BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.èªå¨å®æ : OperateTypeEnum.äººå·¥å®æ); |
| | | //BaseDal.DeleteData(task); |
| | | var result = _task_HtyService.DeleteAndMoveIntoHty(task, OperateTypeEnum.人工å é¤); |
| | | if (!result) |
| | | { |
| | | await Db.Deleteable(task).ExecuteCommandAsync(); |
| | | } |
| | | // è®°å½è´§ä½ç¶æåæ´ |
| | | _locationStatusChangeRecordService.AddLocationStatusChangeRecord( |
| | | locationInfo, |
| | |
| | | //ä¸ç¨åä¼ |
| | | } |
| | | else |
| | | { |
| | | { |
| | | if (outboundOrder != null && outboundOrder.IsBatch == 0) |
| | | { |
| | | var feedmodel = new FeedbackOutboundRequestModel |
| | |
| | | } |
| | | else if (outboundOrder != null && outboundOrder.IsBatch == 1) |
| | | { |
| | | await _invokeMESService.BatchOrderFeedbackToMes(new List<string>(){outboundOrder.OrderNo },2); |
| | | await _invokeMESService.BatchOrderFeedbackToMes(new List<string>() { outboundOrder.OrderNo }, 2); |
| | | } |
| | | |
| | | } |
| | |
| | | |
| | | |
| | | task.TaskStatus = TaskStatusEnum.Finish.ObjToInt(); |
| | | BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.èªå¨å®æ : OperateTypeEnum.äººå·¥å®æ); |
| | | _stockService.StockInfoService.Repository.DeleteAndMoveIntoHty(stockInfo, App.User.UserId == 0 ? OperateTypeEnum.èªå¨å®æ : OperateTypeEnum.äººå·¥å®æ); |
| | | //_stockRepository.Db.Deleteable(stockInfo).ExecuteCommand(); |
| | | // BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.èªå¨å®æ : OperateTypeEnum.äººå·¥å®æ); |
| | | var result = _task_HtyService.DeleteAndMoveIntoHty(task, OperateTypeEnum.人工å é¤); |
| | | if (!result) |
| | | { |
| | | await Db.Deleteable(task).ExecuteCommandAsync(); |
| | | } |
| | | |
| | | var stockresult = _stockService.StockInfoService.Repository.DeleteAndMoveIntoHty(stockInfo, App.User.UserId == 0 ? OperateTypeEnum.èªå¨å®æ : OperateTypeEnum.äººå·¥å®æ); |
| | | if (!stockresult) |
| | | { |
| | | _stockRepository.Db.Deleteable(stockInfo).ExecuteCommand(); |
| | | } |
| | | _stockService.StockInfoService.DeleteData(stockInfo); |
| | | _locationStatusChangeRecordService.AddLocationStatusChangeRecord(locationInfo, beforeStatus, StockChangeType.Outbound.ObjToInt(), stockInfo.Details.FirstOrDefault()?.OrderNo ?? "", task.TaskNum); |
| | | |
| | |
| | | using Newtonsoft.Json; |
| | | using OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup; |
| | | using System; |
| | | using System.Collections.Concurrent; |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | | using System.Text; |
| | |
| | | List<Dt_LocationInfo>? locationInfos = null; |
| | | |
| | | CleanupPreviousInvalidLocks(outboundOrderDetails); |
| | | |
| | | (List<Dt_StockInfo>, List<Dt_OutboundOrderDetail>, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>) result = _outboundOrderDetailService.AssignStockOutbound(outboundOrderDetails); |
| | | if (result.Item1 != null && result.Item1.Count > 0) |
| | | // å¼å¯äºå¡ï¼ä½¿ç¨æ°æ®åºè¡çº§é |
| | | using (var transaction = _outboundOrderDetailService.Db.Ado.UseTran()) |
| | | { |
| | | Dt_OutboundOrder outboundOrder = _outboundOrderService.Repository.QueryFirst(x => x.Id == outboundOrderDetails.FirstOrDefault().OrderId); |
| | | TaskTypeEnum typeEnum = outboundOrder.OrderType switch |
| | | try |
| | | { |
| | | (int)OutOrderTypeEnum.Issue => TaskTypeEnum.Outbound, |
| | | (int)OutOrderTypeEnum.Allocate => TaskTypeEnum.OutAllocate, |
| | | (int)OutOrderTypeEnum.Quality => TaskTypeEnum.OutQuality, |
| | | _ => TaskTypeEnum.Outbound |
| | | }; |
| | | tasks = GetTasks(result.Item1, typeEnum, outStation); |
| | | tasks.ForEach(x => |
| | | { |
| | | x.OrderNo = outboundOrder.OrderNo; |
| | | }); |
| | | result.Item2.ForEach(x => |
| | | { |
| | | x.OrderDetailStatus = OrderDetailStatusEnum.Outbound.ObjToInt(); |
| | | }); |
| | | result.Item3.ForEach(x => |
| | | { |
| | | x.Status = OutLockStockStatusEnum.åºåºä¸.ObjToInt(); |
| | | }); |
| | | // ä½¿ç¨æ²è§ééå®è®¢åæç» |
| | | var lockedOrderDetails = new List<Dt_OutboundOrderDetail>(); |
| | | foreach (var key in keys) |
| | | { |
| | | var detail = _outboundOrderDetailService.Db.Ado.SqlQuerySingle<Dt_OutboundOrderDetail>( |
| | | "SELECT * FROM Dt_OutboundOrderDetail WITH (UPDLOCK) WHERE Id = @Id", |
| | | new { Id = key }); |
| | | |
| | | stockInfos = result.Item1; |
| | | orderDetails = result.Item2; |
| | | outStockLockInfos = result.Item3; |
| | | locationInfos = result.Item4; |
| | | if (detail != null) |
| | | { |
| | | lockedOrderDetails.Add(detail); |
| | | } |
| | | } |
| | | |
| | | if (!lockedOrderDetails.Any()) |
| | | { |
| | | throw new Exception("æªæ¾å°åºåºåæç»ä¿¡æ¯"); |
| | | } |
| | | (List<Dt_StockInfo>, List<Dt_OutboundOrderDetail>, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>) result = _outboundOrderDetailService.AssignStockOutbound(outboundOrderDetails); |
| | | if (result.Item1 != null && result.Item1.Count > 0) |
| | | { |
| | | Dt_OutboundOrder outboundOrder = _outboundOrderService.Repository.QueryFirst(x => x.Id == outboundOrderDetails.FirstOrDefault().OrderId); |
| | | TaskTypeEnum typeEnum = outboundOrder.OrderType switch |
| | | { |
| | | (int)OutOrderTypeEnum.Issue => TaskTypeEnum.Outbound, |
| | | (int)OutOrderTypeEnum.Allocate => TaskTypeEnum.OutAllocate, |
| | | (int)OutOrderTypeEnum.Quality => TaskTypeEnum.OutQuality, |
| | | _ => TaskTypeEnum.Outbound |
| | | }; |
| | | tasks = GetTasks(result.Item1, typeEnum, outStation); |
| | | tasks.ForEach(x => |
| | | { |
| | | x.OrderNo = outboundOrder.OrderNo; |
| | | }); |
| | | result.Item2.ForEach(x => |
| | | { |
| | | x.OrderDetailStatus = OrderDetailStatusEnum.Outbound.ObjToInt(); |
| | | }); |
| | | result.Item3.ForEach(x => |
| | | { |
| | | x.Status = OutLockStockStatusEnum.åºåºä¸.ObjToInt(); |
| | | }); |
| | | |
| | | stockInfos = result.Item1; |
| | | orderDetails = result.Item2; |
| | | outStockLockInfos = result.Item3; |
| | | locationInfos = result.Item4; |
| | | transaction.CommitTran(); |
| | | } |
| | | else |
| | | { |
| | | transaction.RollbackTran(); |
| | | throw new Exception("æ åºå"); |
| | | } |
| | | } |
| | | catch (Exception) |
| | | { |
| | | transaction.RollbackTran(); |
| | | throw; |
| | | } |
| | | return (tasks, stockInfos, orderDetails, outStockLockInfos, locationInfos); |
| | | } |
| | | else |
| | | { |
| | | throw new Exception("æ åºå"); |
| | | } |
| | | return (tasks, stockInfos, orderDetails, outStockLockInfos, locationInfos); |
| | | } |
| | | /// <summary> |
| | | /// æ¸
çä¹åçæ æéå®è®°å½ |
| | |
| | | // TaskNum = BaseDal.GetTaskNum(nameof(SequenceEnum.SeqTaskNum)), |
| | | PalletType = stockInfo.PalletType, |
| | | WarehouseId = stockInfo.WarehouseId, |
| | | |
| | | }; |
| | | //if (taskType != TaskTypeEnum.OutEmpty) |
| | | //{ |
| | |
| | | return tasks; |
| | | } |
| | | |
| | | public List<Dt_Task> GetTasks(List<Dt_StockInfo> stockInfos, TaskTypeEnum taskType) |
| | | |
| | | |
| | | #region å
åé管çå¨ |
| | | private static readonly ConcurrentDictionary<string, SemaphoreSlim> _normalmaterialLocks = |
| | | new ConcurrentDictionary<string, SemaphoreSlim>(); |
| | | private static readonly ConcurrentDictionary<string, DateTime> _normallockLastUsed = |
| | | new ConcurrentDictionary<string, DateTime>(); |
| | | private static readonly object _normalcleanupLock = new object(); |
| | | private static DateTime _normallastCleanupTime = DateTime.MinValue; |
| | | |
| | | /// <summary> |
| | | /// è·åç©æçº§å
åé |
| | | /// </summary> |
| | | private SemaphoreSlim GetNormalMaterialSemaphore(string materialCode, string batchNo, string supplyCode) |
| | | { |
| | | List<Dt_Task> tasks = new List<Dt_Task>(); |
| | | List<Dt_LocationInfo> locationInfos = _locationInfoService.Repository.QueryData(x => stockInfos.Select(x => x.LocationCode).Contains(x.LocationCode)); |
| | | for (int i = 0; i < stockInfos.Count; i++) |
| | | // å建éé®ï¼ç©æ+æ¹æ¬¡+ä¾åºå |
| | | string lockKey = $"MaterialLock_{materialCode}_{batchNo}_{supplyCode}"; |
| | | |
| | | // æ¸
çé¿æ¶é´ä¸ç¨çéï¼æ¯å°æ¶æ¸
ç䏿¬¡ï¼ |
| | | var now = DateTime.Now; |
| | | if ((now - _normallastCleanupTime).TotalHours >= 1) |
| | | { |
| | | Dt_StockInfo stockInfo = stockInfos[i]; |
| | | |
| | | if (stockInfo != null) |
| | | lock (_normalcleanupLock) |
| | | { |
| | | Dt_LocationInfo? locationInfo = locationInfos.FirstOrDefault(x => x.LocationCode == stockInfo.LocationCode); |
| | | if (!tasks.Exists(x => x.PalletCode == stockInfo.PalletCode)) |
| | | if ((now - _normallastCleanupTime).TotalHours >= 1) |
| | | { |
| | | Dt_Task task = new() |
| | | { |
| | | CurrentAddress = stockInfo.LocationCode, |
| | | Grade = 0, |
| | | PalletCode = stockInfo.PalletCode, |
| | | NextAddress = "", |
| | | Roadway = locationInfo.RoadwayNo, |
| | | SourceAddress = stockInfo.LocationCode, |
| | | TargetAddress = "", |
| | | TaskStatus = TaskStatusEnum.New.ObjToInt(), |
| | | TaskType = taskType.ObjToInt(), |
| | | //TaskNum = BaseDal.GetTaskNum(nameof(SequenceEnum.SeqTaskNum)), |
| | | PalletType = stockInfo.PalletType, |
| | | WarehouseId = stockInfo.WarehouseId, |
| | | var keysToRemove = _normallockLastUsed |
| | | .Where(kvp => (now - kvp.Value).TotalHours > 2) |
| | | .Select(kvp => kvp.Key) |
| | | .ToList(); |
| | | |
| | | }; |
| | | //if (taskType != TaskTypeEnum.OutEmpty) |
| | | //{ |
| | | // task.MaterielCode = stockInfo.Details?.Where(x => x.StockId == stockInfo.Id).FirstOrDefault()?.MaterielCode; |
| | | // task.Quantity = (float)stockInfo.Details?.Where(x => x.StockId == stockInfo.Id).Sum(x => x.StockQuantity); |
| | | // task.BatchNo = stockInfo.Details?.Where(x => x.StockId == stockInfo.Id).FirstOrDefault()?.BatchNo; |
| | | //} |
| | | //if (stockInfo.StockLength > 0) |
| | | //{ |
| | | // task.TaskLength = stockInfo.StockLength; |
| | | //} |
| | | tasks.Add(task); |
| | | foreach (var key in keysToRemove) |
| | | { |
| | | if (_normalmaterialLocks.TryRemove(key, out var _semaphore)) |
| | | { |
| | | _semaphore.Dispose(); |
| | | } |
| | | _normallockLastUsed.TryRemove(key, out _); |
| | | } |
| | | |
| | | _normallastCleanupTime = now; |
| | | } |
| | | } |
| | | } |
| | | return tasks; |
| | | |
| | | // è·åæå建信å·é |
| | | var semaphore = _normalmaterialLocks.GetOrAdd(lockKey, _ => new SemaphoreSlim(1, 1)); |
| | | _normallockLastUsed[lockKey] = now; |
| | | |
| | | return semaphore; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ´æ°å
åéæåä½¿ç¨æ¶é´ |
| | | /// </summary> |
| | | private void UpdateNormalMaterialLockUsedTime(string materialCode, string batchNo, string supplyCode) |
| | | { |
| | | string lockKey = $"MaterialLock_{materialCode}_{batchNo}_{supplyCode}"; |
| | | _normallockLastUsed[lockKey] = DateTime.Now; |
| | | } |
| | | #endregion |
| | | /// <summary> |
| | | /// çæåºåºä»»å¡ |
| | | /// </summary> |
| | |
| | | List<Dt_OutboundOrderDetail> outboundOrderDetails = new List<Dt_OutboundOrderDetail>(); |
| | | List<Dt_OutStockLockInfo> outStockLockInfos = new List<Dt_OutStockLockInfo>(); |
| | | List<Dt_LocationInfo> locationInfos = new List<Dt_LocationInfo>(); |
| | | |
| | | (List<Dt_Task>, List<Dt_StockInfo>?, List<Dt_OutboundOrderDetail>?, List<Dt_OutStockLockInfo>?, List<Dt_LocationInfo>?) result = OutboundTaskDataHandle(keys, outStation); |
| | | if (result.Item2 != null && result.Item2.Count > 0) |
| | | // å
è·åææè®¢åæç»ï¼ç¡®å®éè¦éå®çç©æ |
| | | var orderDetails = _outboundOrderDetailService.Repository.QueryData(x => keys.Contains(x.Id)); |
| | | if (orderDetails == null || orderDetails.Count == 0) |
| | | { |
| | | stockInfos.AddRange(result.Item2); |
| | | } |
| | | if (result.Item3 != null && result.Item3.Count > 0) |
| | | { |
| | | outboundOrderDetails.AddRange(result.Item3); |
| | | } |
| | | if (result.Item4 != null && result.Item4.Count > 0) |
| | | { |
| | | outStockLockInfos.AddRange(result.Item4); |
| | | } |
| | | if (result.Item5 != null && result.Item5.Count > 0) |
| | | { |
| | | locationInfos.AddRange(result.Item5); |
| | | } |
| | | if (result.Item1 != null && result.Item1.Count > 0) |
| | | { |
| | | tasks.AddRange(result.Item1); |
| | | return WebResponseContent.Instance.Error("æªæ¾å°åºåºåæç»ä¿¡æ¯"); |
| | | } |
| | | |
| | | WebResponseContent content = await GenerateOutboundTaskDataUpdateAsync(tasks, stockInfos, outboundOrderDetails, outStockLockInfos, locationInfos); |
| | | return content; |
| | | // è·åææéè¦éå®çç©æåç» |
| | | var materialGroups = orderDetails |
| | | .GroupBy(x => new { x.MaterielCode, x.BatchNo, x.SupplyCode }) |
| | | .Select(g => new |
| | | { |
| | | g.Key.MaterielCode, |
| | | g.Key.BatchNo, |
| | | g.Key.SupplyCode, |
| | | Count = g.Count() |
| | | }) |
| | | .ToList(); |
| | | |
| | | // æé¡ºåºè·åææç©æçå
åéï¼æç©æä»£ç æåºä»¥é¿å
æ»éï¼ |
| | | var semaphores = new List<SemaphoreSlim>(); |
| | | var acquiredLocks = new List<(string MaterialCode, string BatchNo, string SupplyCode)>(); |
| | | |
| | | try |
| | | { |
| | | foreach (var group in materialGroups.OrderBy(g => g.MaterielCode).ThenBy(g => g.BatchNo)) |
| | | { |
| | | var semaphore = GetMaterialSemaphore(group.MaterielCode, group.BatchNo, group.SupplyCode); |
| | | |
| | | // çå¾
è·åéï¼æå¤çå¾
30ç§ |
| | | bool lockAcquired = await semaphore.WaitAsync(TimeSpan.FromSeconds(30)); |
| | | |
| | | if (!lockAcquired) |
| | | { |
| | | // 妿è·åé失败ï¼éæ¾å·²è·åçææé |
| | | foreach (var acquiredSemaphore in semaphores) |
| | | { |
| | | acquiredSemaphore.Release(); |
| | | } |
| | | return WebResponseContent.Instance.Error($"ç©æ[{group.MaterielCode}]æ¹æ¬¡[{group.BatchNo}]åé
ç¹å¿ï¼è¯·ç¨åéè¯"); |
| | | } |
| | | |
| | | semaphores.Add(semaphore); |
| | | acquiredLocks.Add((group.MaterielCode, group.BatchNo, group.SupplyCode)); |
| | | } |
| | | |
| | | (List<Dt_Task>, List<Dt_StockInfo>?, List<Dt_OutboundOrderDetail>?, List<Dt_OutStockLockInfo>?, List<Dt_LocationInfo>?) result = OutboundTaskDataHandle(keys, outStation); |
| | | if (result.Item2 != null && result.Item2.Count > 0) |
| | | { |
| | | stockInfos.AddRange(result.Item2); |
| | | } |
| | | if (result.Item3 != null && result.Item3.Count > 0) |
| | | { |
| | | outboundOrderDetails.AddRange(result.Item3); |
| | | } |
| | | if (result.Item4 != null && result.Item4.Count > 0) |
| | | { |
| | | outStockLockInfos.AddRange(result.Item4); |
| | | } |
| | | if (result.Item5 != null && result.Item5.Count > 0) |
| | | { |
| | | locationInfos.AddRange(result.Item5); |
| | | } |
| | | if (result.Item1 != null && result.Item1.Count > 0) |
| | | { |
| | | tasks.AddRange(result.Item1); |
| | | } |
| | | |
| | | WebResponseContent content = await GenerateOutboundTaskDataUpdateAsync(tasks, stockInfos, outboundOrderDetails, outStockLockInfos, locationInfos); |
| | | return content; |
| | | } |
| | | finally |
| | | { |
| | | // éæ¾ææå
åéå¹¶æ´æ°ä½¿ç¨æ¶é´ |
| | | foreach (var semaphore in semaphores) |
| | | { |
| | | semaphore.Release(); |
| | | } |
| | | |
| | | foreach (var lockInfo in acquiredLocks) |
| | | { |
| | | UpdateMaterialLockUsedTime(lockInfo.MaterialCode, lockInfo.BatchNo, lockInfo.SupplyCode); |
| | | } |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | |
| | | { |
| | | return WebResponseContent.Instance.Error("æ¾ä¸å°åºåºåæ®"); |
| | | } |
| | | |
| | | var orderdetail = outboundOrder.Details.Where(outItem => allocorder.Details .Any(allocItem => allocItem.MaterielCode == outItem.MaterielCode && allocItem.LineNo == outItem.lineNo |
| | | && allocItem.BarcodeQty==outItem.BarcodeQty && allocItem.WarehouseCode==outItem.WarehouseCode && allocItem.BarcodeUnit==outItem.BarcodeUnit) ) .First(); |
| | | |
| | | var orderdetail = outboundOrder.Details.Where(outItem => allocorder.Details.Any(allocItem => allocItem.MaterielCode == outItem.MaterielCode && allocItem.LineNo == outItem.lineNo |
| | | && allocItem.BarcodeQty == outItem.BarcodeQty && allocItem.WarehouseCode == outItem.WarehouseCode && allocItem.BarcodeUnit == outItem.BarcodeUnit)).First(); |
| | | if (orderdetail == null) |
| | | { |
| | | return WebResponseContent.Instance.Error("æ¾ä¸å°åºåºæç»åæ®"); |
| | | } |
| | | |
| | | (List<Dt_Task>, List<Dt_StockInfo>?, List<Dt_OutboundOrderDetail>?, List<Dt_OutStockLockInfo>?, List<Dt_LocationInfo>?) result = OutboundTaskDataHandle(outboundOrder.Details.First().Id, stockSelectViews,station); |
| | | (List<Dt_Task>, List<Dt_StockInfo>?, List<Dt_OutboundOrderDetail>?, List<Dt_OutStockLockInfo>?, List<Dt_LocationInfo>?) result = OutboundTaskDataHandle(outboundOrder.Details.First().Id, stockSelectViews, station); |
| | | |
| | | WebResponseContent content =await GenerateOutboundTaskDataUpdate(result.Item1, result.Item2, result.Item3, result.Item4, result.Item5); |
| | | WebResponseContent content = await GenerateOutboundTaskDataUpdate(result.Item1, result.Item2, result.Item3, result.Item4, result.Item5); |
| | | |
| | | return content; |
| | | } |
| | |
| | | /// <param name="orderDetailId"></param> |
| | | /// <param name="stockSelectViews"></param> |
| | | /// <returns></returns> |
| | | public async Task<WebResponseContent> GenerateOutboundTask(int orderDetailId, List<StockSelectViewDTO> stockSelectViews,string station=null) |
| | | public async Task<WebResponseContent> GenerateOutboundTask(int orderDetailId, List<StockSelectViewDTO> stockSelectViews, string station = null) |
| | | { |
| | | try |
| | | { |
| | |
| | | { |
| | | return WebResponseContent.Instance.Error("æ¾ä¸å°åæ®"); |
| | | } |
| | | (List<Dt_Task>, List<Dt_StockInfo>?, List<Dt_OutboundOrderDetail>?, List<Dt_OutStockLockInfo>?, List<Dt_LocationInfo>?) result = OutboundTaskDataHandle(outboundOrder.Details.First().Id, stockSelectViews,station); |
| | | (List<Dt_Task>, List<Dt_StockInfo>?, List<Dt_OutboundOrderDetail>?, List<Dt_OutStockLockInfo>?, List<Dt_LocationInfo>?) result = OutboundTaskDataHandle(outboundOrder.Details.First().Id, stockSelectViews, station); |
| | | |
| | | WebResponseContent content =await GenerateOutboundTaskDataUpdate(result.Item1, result.Item2, result.Item3, result.Item4, result.Item5); |
| | | WebResponseContent content = await GenerateOutboundTaskDataUpdate(result.Item1, result.Item2, result.Item3, result.Item4, result.Item5); |
| | | |
| | | return content; |
| | | } |
| | |
| | | /// <param name="stockSelectViews"></param> |
| | | /// <returns></returns> |
| | | /// <exception cref="Exception"></exception> |
| | | public (List<Dt_Task>, List<Dt_StockInfo>?, List<Dt_OutboundOrderDetail>?, List<Dt_OutStockLockInfo>?, List<Dt_LocationInfo>?) OutboundTaskDataHandle(int orderDetailId, List<StockSelectViewDTO> stockSelectViews,string station=null) |
| | | public (List<Dt_Task>, List<Dt_StockInfo>?, List<Dt_OutboundOrderDetail>?, List<Dt_OutStockLockInfo>?, List<Dt_LocationInfo>?) OutboundTaskDataHandle(int orderDetailId, List<StockSelectViewDTO> stockSelectViews, string station = null) |
| | | { |
| | | List<Dt_Task> tasks = new List<Dt_Task>(); |
| | | Dt_OutboundOrderDetail outboundOrderDetail = _outboundOrderDetailService.Repository.QueryFirst(x => x.Id == orderDetailId); |
| | |
| | | Dt_OutboundOrderDetail? orderDetail = null; |
| | | List<Dt_OutStockLockInfo>? outStockLockInfos = null; |
| | | List<Dt_LocationInfo>? locationInfos = null; |
| | | if (outboundOrderDetail.OrderDetailStatus == OrderDetailStatusEnum.New.ObjToInt()) |
| | | if (outboundOrderDetail.OrderDetailStatus == OrderDetailStatusEnum.New.ObjToInt() || |
| | | outboundOrderDetail.OrderDetailStatus == OrderDetailStatusEnum.Outbound.ObjToInt()) |
| | | { |
| | | (List<Dt_StockInfo>, Dt_OutboundOrderDetail, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>) result = _outboundOrderDetailService.AssignStockOutbound(outboundOrderDetail, stockSelectViews); |
| | | if (result.Item1 != null && result.Item1.Count > 0) |
| | | { |
| | | Dt_OutboundOrder outboundOrder = _outboundOrderService.Repository.QueryFirst(x => x.Id == outboundOrderDetail.OrderId); |
| | | Dt_OutboundOrder outboundOrder = _outboundOrderService.Repository.QueryFirst(x => x.Id == outboundOrderDetail.OrderId); |
| | | TaskTypeEnum typeEnum = outboundOrder.OrderType switch |
| | | { |
| | | (int)OutOrderTypeEnum.Issue => TaskTypeEnum.Outbound, |
| | |
| | | (int)OutOrderTypeEnum.Quality => TaskTypeEnum.OutQuality, |
| | | _ => TaskTypeEnum.Outbound |
| | | }; |
| | | tasks = GetTasks(result.Item1, typeEnum,station); |
| | | tasks = GetTasks(result.Item1, typeEnum, station); |
| | | result.Item2.OrderDetailStatus = OrderDetailStatusEnum.Outbound.ObjToInt(); |
| | | result.Item3.ForEach(x => |
| | | { |
| | |
| | | if (stockLockInfos != null && stockLockInfos.Count > 0) |
| | | { |
| | | List<Dt_StockInfo> stocks = _stockService.StockInfoService.GetStockInfosByPalletCodes(stockLockInfos.Select(x => x.PalletCode).Distinct().ToList()); |
| | | tasks = GetTasks(stocks, TaskTypeEnum.Outbound); |
| | | tasks = GetTasks(stocks, TaskTypeEnum.Outbound,station); |
| | | } |
| | | } |
| | | |
| | |
| | | /// <param name="outStockLockInfos"></param> |
| | | /// <param name="locationInfos"></param> |
| | | /// <returns></returns> |
| | | public async Task< WebResponseContent> GenerateOutboundTaskDataUpdate(List<Dt_Task> tasks, List<Dt_StockInfo>? stockInfos = null, List<Dt_OutboundOrderDetail>? outboundOrderDetails = null, List<Dt_OutStockLockInfo>? outStockLockInfos = null, List<Dt_LocationInfo>? locationInfos = null) |
| | | public async Task<WebResponseContent> GenerateOutboundTaskDataUpdate(List<Dt_Task> tasks, List<Dt_StockInfo>? stockInfos = null, List<Dt_OutboundOrderDetail>? outboundOrderDetails = null, List<Dt_OutStockLockInfo>? outStockLockInfos = null, List<Dt_LocationInfo>? locationInfos = null) |
| | | { |
| | | try |
| | | { |
| | |
| | | { |
| | | return WebResponseContent.Instance.Error("ä¸åæºå¨äººä»»å¡å¤±è´¥ï¼"); |
| | | } |
| | | |
| | | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | |
| | | |
| | | |
| | | #region åæ¹åé
åºå |
| | | #region å
åé管çå¨ |
| | | private static readonly ConcurrentDictionary<string, SemaphoreSlim> _materialLocks = |
| | | new ConcurrentDictionary<string, SemaphoreSlim>(); |
| | | private static readonly ConcurrentDictionary<string, DateTime> _lockLastUsed = |
| | | new ConcurrentDictionary<string, DateTime>(); |
| | | private static readonly object _cleanupLock = new object(); |
| | | private static DateTime _lastCleanupTime = DateTime.MinValue; |
| | | |
| | | /// <summary> |
| | | /// è·åç©æçº§å
åé |
| | | /// </summary> |
| | | private SemaphoreSlim GetMaterialSemaphore(string materialCode, string batchNo, string supplyCode) |
| | | { |
| | | // å建éé®ï¼ç©æ+æ¹æ¬¡+ä¾åºå |
| | | string lockKey = $"MaterialLock_{materialCode}_{batchNo}_{supplyCode}"; |
| | | |
| | | // æ¸
çé¿æ¶é´ä¸ç¨çéï¼æ¯å°æ¶æ¸
ç䏿¬¡ï¼ |
| | | var now = DateTime.Now; |
| | | if ((now - _lastCleanupTime).TotalHours >= 1) |
| | | { |
| | | lock (_cleanupLock) |
| | | { |
| | | if ((now - _lastCleanupTime).TotalHours >= 1) |
| | | { |
| | | var keysToRemove = _lockLastUsed |
| | | .Where(kvp => (now - kvp.Value).TotalHours > 2) |
| | | .Select(kvp => kvp.Key) |
| | | .ToList(); |
| | | |
| | | foreach (var key in keysToRemove) |
| | | { |
| | | if (_materialLocks.TryRemove(key, out var _semaphore)) |
| | | { |
| | | _semaphore.Dispose(); |
| | | } |
| | | _lockLastUsed.TryRemove(key, out _); |
| | | } |
| | | |
| | | _lastCleanupTime = now; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // è·åæå建信å·é |
| | | var semaphore = _materialLocks.GetOrAdd(lockKey, _ => new SemaphoreSlim(1, 1)); |
| | | _lockLastUsed[lockKey] = now; |
| | | |
| | | return semaphore; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// éæ¾å
åéå¹¶æ´æ°æåä½¿ç¨æ¶é´ |
| | | /// </summary> |
| | | private void UpdateMaterialLockUsedTime(string materialCode, string batchNo, string supplyCode) |
| | | { |
| | | string lockKey = $"MaterialLock_{materialCode}_{batchNo}_{supplyCode}"; |
| | | _lockLastUsed[lockKey] = DateTime.Now; |
| | | } |
| | | #endregion |
| | | /// <summary> |
| | | /// åæ¹åé
åºå |
| | | /// </summary> |
| | |
| | | { |
| | | try |
| | | { |
| | | List<Dt_Task> tasks = new List<Dt_Task>(); |
| | | List<Dt_StockInfo> stockInfos = new List<Dt_StockInfo>(); |
| | | List<Dt_OutboundOrderDetail> outboundOrderDetails = new List<Dt_OutboundOrderDetail>(); |
| | | List<Dt_OutStockLockInfo> outStockLockInfos = new List<Dt_OutStockLockInfo>(); |
| | | List<Dt_LocationInfo> locationInfos = new List<Dt_LocationInfo>(); |
| | | // å
è·å订åæç»ä¿¡æ¯ï¼ç¡®å®ç©æ |
| | | var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | .FirstAsync(x => x.Id == orderDetailId); |
| | | |
| | | (List<Dt_Task>, List<Dt_StockInfo>?, List<Dt_OutboundOrderDetail>?, List<Dt_OutStockLockInfo>?, List<Dt_LocationInfo>?) result = await BatchAllocateStockDataHandle(orderDetailId, batchQuantity, outStation); |
| | | if (orderDetail == null) |
| | | return WebResponseContent.Instance.Error("æªæ¾å°è®¢åæç»ä¿¡æ¯"); |
| | | |
| | | if (result.Item2 != null && result.Item2.Count > 0) |
| | | { |
| | | stockInfos.AddRange(result.Item2); |
| | | } |
| | | if (result.Item3 != null && result.Item3.Count > 0) |
| | | { |
| | | outboundOrderDetails.AddRange(result.Item3); |
| | | } |
| | | if (result.Item4 != null && result.Item4.Count > 0) |
| | | { |
| | | outStockLockInfos.AddRange(result.Item4); |
| | | } |
| | | if (result.Item5 != null && result.Item5.Count > 0) |
| | | { |
| | | locationInfos.AddRange(result.Item5); |
| | | } |
| | | if (result.Item1 != null && result.Item1.Count > 0) |
| | | { |
| | | tasks.AddRange(result.Item1); |
| | | } |
| | | // è·åç©æçº§å
åé |
| | | var semaphore = GetMaterialSemaphore(orderDetailId + orderDetail.MaterielCode, orderDetail.BatchNo, orderDetail.SupplyCode); |
| | | |
| | | WebResponseContent content = await GenerateOutboundTaskDataUpdateAsync(tasks, stockInfos, outboundOrderDetails, outStockLockInfos, locationInfos); |
| | | return content; |
| | | // çå¾
è·åå
åéï¼æå¤çå¾
30ç§ |
| | | bool memoryLockAcquired = await semaphore.WaitAsync(TimeSpan.FromSeconds(30)); |
| | | |
| | | if (!memoryLockAcquired) |
| | | return WebResponseContent.Instance.Error("ç³»ç»ç¹å¿ï¼è¯·ç¨åéè¯"); |
| | | |
| | | try |
| | | { |
| | | List<Dt_Task> tasks = new List<Dt_Task>(); |
| | | List<Dt_StockInfo> stockInfos = new List<Dt_StockInfo>(); |
| | | List<Dt_OutboundOrderDetail> outboundOrderDetails = new List<Dt_OutboundOrderDetail>(); |
| | | List<Dt_OutStockLockInfo> outStockLockInfos = new List<Dt_OutStockLockInfo>(); |
| | | List<Dt_LocationInfo> locationInfos = new List<Dt_LocationInfo>(); |
| | | |
| | | (List<Dt_Task>, List<Dt_StockInfo>?, List<Dt_OutboundOrderDetail>?, List<Dt_OutStockLockInfo>?, List<Dt_LocationInfo>?) result = await BatchAllocateStockDataHandle(orderDetailId, batchQuantity, outStation); |
| | | |
| | | if (result.Item2 != null && result.Item2.Count > 0) |
| | | { |
| | | stockInfos.AddRange(result.Item2); |
| | | } |
| | | if (result.Item3 != null && result.Item3.Count > 0) |
| | | { |
| | | outboundOrderDetails.AddRange(result.Item3); |
| | | } |
| | | if (result.Item4 != null && result.Item4.Count > 0) |
| | | { |
| | | outStockLockInfos.AddRange(result.Item4); |
| | | } |
| | | if (result.Item5 != null && result.Item5.Count > 0) |
| | | { |
| | | locationInfos.AddRange(result.Item5); |
| | | } |
| | | if (result.Item1 != null && result.Item1.Count > 0) |
| | | { |
| | | tasks.AddRange(result.Item1); |
| | | } |
| | | |
| | | WebResponseContent content = await GenerateOutboundTaskDataUpdateAsync(tasks, stockInfos, outboundOrderDetails, outStockLockInfos, locationInfos); |
| | | return content; |
| | | } |
| | | finally |
| | | { |
| | | // éæ¾å
åé |
| | | semaphore.Release(); |
| | | UpdateMaterialLockUsedTime(orderDetail.MaterielCode, orderDetail.BatchNo, orderDetail.SupplyCode); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | |
| | | List<Dt_Task> tasks = new List<Dt_Task>(); |
| | | |
| | | // è·å订åæç» |
| | | var outboundOrderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | var outboundOrderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>().With("UPDLOCK") |
| | | .FirstAsync(x => x.Id == orderDetailId); |
| | | |
| | | if (outboundOrderDetail == null) |
| | |
| | | using WIDESEA_Core.BaseRepository; |
| | | using AutoMapper; |
| | | using Microsoft.Extensions.Logging; |
| | | using System.Transactions; |
| | | using WIDESEA_Core; |
| | | using WIDESEA_Core.BaseRepository; |
| | | using WIDESEA_Core.BaseServices; |
| | | using WIDESEA_Core.Enums; |
| | | using WIDESEA_ITaskInfoService; |
| | | using WIDESEA_Model.Models; |
| | | |
| | |
| | | |
| | | public class Task_HtyService : ServiceBase<Dt_Task_Hty, IRepository<Dt_Task_Hty>>, ITask_HtyService |
| | | { |
| | | public Task_HtyService(IRepository<Dt_Task_Hty> BaseDal) : base(BaseDal) |
| | | private readonly ILogger<Task_HtyService> _logger; |
| | | |
| | | private readonly IMapper _mapper; // AutoMapperå®ä¾ |
| | | public Task_HtyService(IRepository<Dt_Task_Hty> BaseDal, IMapper mapper, ILogger<Task_HtyService> logger) : base(BaseDal) |
| | | { |
| | | _mapper = mapper; |
| | | _logger = logger; |
| | | } |
| | | public bool DeleteAndMoveIntoHty(Dt_Task task, OperateTypeEnum operateType) |
| | | { |
| | | // using var transaction = Db.Ado.UseTran(); |
| | | try |
| | | { |
| | | var historyEntity = _mapper.Map<Dt_Task_Hty>(task); |
| | | |
| | | // 2. å¡«å
åå²å®ä½æ ¸å¿å段 |
| | | historyEntity.SourceId = task.TaskId; |
| | | historyEntity.OperateType = App.User?.UserName != null ? OperateTypeEnum.èªå¨å®æ.ToString() : OperateTypeEnum.äººå·¥å®æ.ToString(); |
| | | historyEntity.Creater = App.User?.UserName != null ? App.User.UserName : "System"; |
| | | |
| | | // è¦çä¿®æ¹äºº/ä¿®æ¹æ¶é´ï¼ä¼å
级é«äºæ å°ï¼ |
| | | // historyEntity.Modifier = App.User?.UserId > 0 ? App.User?.UserName : "System"; |
| | | // historyEntity.ModifyDate = DateTime.Now; |
| | | |
| | | // 3. æå
¥åå²è¡¨ï¼ç±»åå®å
¨ï¼æ åå°æ¼æ¥è¡¨åï¼ |
| | | |
| | | int insertCount = Db.Insertable(historyEntity).ExecuteCommand(); |
| | | |
| | | if (insertCount <= 0) |
| | | { |
| | | _logger.LogError($"ä»»å¡åå²è¡¨Dt_Task_Hty [{task.TaskNum}]æå
¥å¤±è´¥ï¼å½±åè¡æ°ä¸º0"); |
| | | // transaction.RollbackTran(); |
| | | return false; |
| | | } |
| | | |
| | | // 4. å é¤åå®ä½ï¼ç±»åå®å
¨ï¼ |
| | | int deleteCount = Db.Deleteable(task).ExecuteCommand(); |
| | | if (deleteCount <= 0) |
| | | { |
| | | _logger.LogError("ä»»å¡ä¸å¡å®ä½[{0}]å é¤å¤±è´¥ï¼å½±åè¡æ°ä¸º0", task.TaskNum); |
| | | // transaction.RollbackTran(); |
| | | return false; |
| | | } |
| | | //transaction.CommitTran(); |
| | | _logger.LogInformation("ä»»å¡å®ä½[{0}]å·²æåç§»å
¥åå²è¡¨[{1}]å¹¶å é¤åæ°æ®", task.TaskNum); |
| | | return true; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | // transaction.RollbackTran(); |
| | | _logger.LogError(ex, "ä»»å¡å é¤å®ä½[{0}]å¹¶ç§»å
¥åå²è¡¨å¤±è´¥", task.TaskNum); |
| | | return false; |
| | | } |
| | | } |
| | | } |
| | |
| | | /// </summary> |
| | | private async Task HandleTaskSuspended(StatusCallbackRequest request) |
| | | { |
| | | _logger.LogWarning("ä»»å¡æèµ·: TaskCode={TaskCode}, ç³»ç»ä»»å¡ç ={SysTaskCode}, åå ={Message}", |
| | | request.TaskCode, request.SysTaskCode, request.Message); |
| | | _logger.LogWarning("ä»»å¡æèµ·: TaskCode={TaskCode}, ç³»ç»ä»»å¡ç ={SysTaskCode}, åå ={Message}",request.TaskCode, request.SysTaskCode, request.Message); |
| | | |
| | | // è¿éæ·»å æ¨çæèµ·å¤çé»è¾ |
| | | await Task.CompletedTask; |
| | |
| | | /// </summary> |
| | | private async Task HandleTaskAllocated(StatusCallbackRequest request) |
| | | { |
| | | _logger.LogInformation("ä»»å¡åé
: TaskCode={TaskCode}, Robot={Robot}", |
| | | request.TaskCode, request.RobotCode); |
| | | _logger.LogInformation("ä»»å¡åé
: TaskCode={TaskCode}, Robot={Robot}",request.TaskCode, request.RobotCode); |
| | | |
| | | // è¿éæ·»å æ¨çä»»å¡åé
å¤çé»è¾ |
| | | await Task.CompletedTask; |
| | |
| | | { |
| | | if (request.Status == WIDESEA_DTO.Basic.TaskStatus.success) |
| | | { |
| | | _logger.LogInformation("åç®±å®æ: Container={Container}, Location={Location}", |
| | | request.ContainerCode, request.LocationCode); |
| | | _logger.LogInformation("åç®±å®æ: Container={Container}, Location={Location}", request.ContainerCode, request.LocationCode); |
| | | |
| | | await _taskService.TaskStatusChange(request.TaskCode, WIDESEA_Common.TaskEnum.TaskStatusEnum.AGV_Pull); |
| | | } |
| | | else |
| | | { |
| | |
| | | { |
| | | if (request.Status == WIDESEA_DTO.Basic.TaskStatus.success) |
| | | { |
| | | _logger.LogInformation("æ¾ç®±å®æ: Container={Container}, Location={Location}", |
| | | request.ContainerCode, request.LocationCode); |
| | | _logger.LogInformation("æ¾ç®±å®æ: Container={Container}, Location={Location}", request.ContainerCode, request.LocationCode); |
| | | await _taskService.TaskStatusChange(request.TaskCode, WIDESEA_Common.TaskEnum.TaskStatusEnum.AGV_Puting); |
| | | } |
| | | else |
| | | { |
| | |
| | | using WIDESEA_Core; |
| | | using WIDESEA_Core.Attributes; |
| | | using WIDESEA_Core.BaseController; |
| | | using WIDESEA_Core.BaseRepository; |
| | | using WIDESEA_Core.Enums; |
| | | using WIDESEA_DTO.Allocate; |
| | | using WIDESEA_DTO.Inbound; |
| | | using WIDESEA_DTO.Mes; |
| | |
| | | using WIDESEA_IInboundService; |
| | | using WIDESEA_InboundService; |
| | | using WIDESEA_IOutboundService; |
| | | using WIDESEA_ITaskInfoService; |
| | | using WIDESEA_Model.Models; |
| | | using WIDESEA_OutboundService; |
| | | |
| | |
| | | private readonly IMaterialUnitService _materialUnitService; |
| | | private readonly IOutStockLockInfoService _outStockLockInfoService; |
| | | private readonly IOutboundOrderDetailService _outboundOrderDetailService; |
| | | private readonly IRepository<Dt_Task> _taskRepository; |
| | | private readonly ITask_HtyService _task_HtyService; |
| | | private readonly ILogger<InboundOrderController> _logger; |
| | | public InboundOrderController(IInboundOrderService service, WIDESEA_IBasicService.IErpApiService erpApiService, WIDESEA_IBasicService.IInvokeMESService invokeMESService, IESSApiService eSSApiService, IDailySequenceService dailySequenceService, ILocationInfoService locationInfoService, ILogger<InboundOrderController> logger, IMaterialUnitService materialUnitService, IInboundService inboundService, IOutStockLockInfoService outStockLockInfoService, IOutboundOrderDetailService outboundOrderDetailService) : base(service) |
| | | public InboundOrderController(IInboundOrderService service, WIDESEA_IBasicService.IErpApiService erpApiService, WIDESEA_IBasicService.IInvokeMESService invokeMESService, IESSApiService eSSApiService, IDailySequenceService dailySequenceService, ILocationInfoService locationInfoService, ILogger<InboundOrderController> logger, IMaterialUnitService materialUnitService, IInboundService inboundService, IOutStockLockInfoService outStockLockInfoService, IOutboundOrderDetailService outboundOrderDetailService, IRepository<Dt_Task> taskRepository, ITask_HtyService task_HtyService) : base(service) |
| | | { |
| | | this.erpApiService = erpApiService; |
| | | _invokeMESService = invokeMESService; |
| | |
| | | _inboundService = inboundService; |
| | | _outStockLockInfoService = outStockLockInfoService; |
| | | _outboundOrderDetailService = outboundOrderDetailService; |
| | | _taskRepository = taskRepository; |
| | | _task_HtyService = task_HtyService; |
| | | } |
| | | |
| | | [HttpPost, Route("Test"), AllowAnonymous, MethodParamsValidate] |
| | | public async Task<WebResponseContent> Test() |
| | | { |
| | | |
| | | |
| | | var originalTask = _taskRepository.Db.Queryable<Dt_Task>().First(); |
| | | |
| | | var result = _task_HtyService.DeleteAndMoveIntoHty(originalTask, OperateTypeEnum.人工å é¤); |
| | | if (result) |
| | | { |
| | | var sddd = "trueee"; |
| | | } |
| | | //var originalTask = _taskRepository.Db.Queryable<Dt_Task>().First(); |
| | | //_taskRepository.DeleteAndMoveIntoHty(originalTask, OperateTypeEnum.èªå¨å®æ); |
| | | // Service.Db.Deleteable<Dt_InboundOrder>().Where(x=>x.UpperOrderNo== "12020251100040").ExecuteCommand(); |
| | | //_inboundService.InboundOrderDetailService.Db.Deleteable<Dt_InboundOrderDetail>() |
| | | // .Where(p => SqlFunc.Subqueryable<Dt_InboundOrder>().Where(s => s.Id == p.OrderId && s.UpperOrderNo == "12020251100040").Any()).ExecuteCommand(); |
| | | |
| | | var purchaseToStockResult = await _materialUnitService.ConvertPurchaseToStockAsync("100513-00303", 1); |
| | | //var purchaseToStockResult = await _materialUnitService.ConvertPurchaseToStockAsync("100513-00303", 1); |
| | | |
| | | var pdddurchaseToStockResult = await _materialUnitService.ConvertFromToStockAsync("100513-00303", "W013", 1); |
| | | //var pdddurchaseToStockResult = await _materialUnitService.ConvertFromToStockAsync("100513-00303", "W013", 1); |
| | | |
| | | //var sddd = _locationInfoService.AssignLocation(); |
| | | //var sddd = _locationInfoService.AssignLocation(1); |
| | | //var code = sddd.LocationCode; |
| | | //var ssss=await _dailySequenceService.GetNextSequenceAsync(); |
| | | //var ddddssss = "WSLOT" + DateTime.Now.ToString("yyyyMMddHHmmss") + ssss.ToString().PadLeft(5, '0'); |
| | |
| | | //await erpApiService.GetMaterialInfoAsync(new WIDESEA_DTO.Basic.MaterialRequest()); |
| | | |
| | | |
| | | return WebResponseContent.Instance.OK(); |
| | | return WebResponseContent.Instance.OK(result?1:0 ); |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | [HttpPost, Route("ReceiveInboundOrder"), AllowAnonymous, MethodParamsValidate] |
| | | public async Task<WebResponseContent> ReceiveInboundOrder([FromBody] InboundRequestModel model) |
| | | { |
| | | if(model.inBounds == null || !model.inBounds.Any()) |
| | | if (model.inBounds == null || !model.inBounds.Any()) |
| | | { |
| | | return WebResponseContent.Instance.Error("å
¥åºåä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | _logger.LogInformation("InboundOrderController ReceiveInboundOrder: " + JsonConvert.SerializeObject(model)); |
| | | _logger.LogInformation("InboundOrderController ReceiveInboundOrder: " + JsonConvert.SerializeObject(model)); |
| | | List<Dt_InboundOrder> inboundOrders = new List<Dt_InboundOrder>(); |
| | | |
| | | foreach (var item in model.inBounds) |
| | |
| | | inboundOrders.Add(dt_InboundOrder); |
| | | } |
| | | |
| | | var content =await Service.ReceiveInboundOrder(inboundOrders, model.operationType); |
| | | var content = await Service.ReceiveInboundOrder(inboundOrders, model.operationType); |
| | | |
| | | if (content.Status) return WebResponseContent.Instance.OK(200); |
| | | else return WebResponseContent.Instance.Error(content.Message); |
| | |
| | | } |
| | | |
| | | [HttpPost, Route("BatchOrderFeedbackToMes"), AllowAnonymous] |
| | | public async Task<WebResponseContent> BatchOrderFeedbackToMes([FromBody] BatchOrderFeedbackToMesDto request) |
| | | public async Task<WebResponseContent> BatchOrderFeedbackToMes([FromBody] BatchOrderFeedbackToMesDto request) |
| | | { |
| | | return await _invokeMESService.BatchOrderFeedbackToMes(request.orderNos, request.inout); |
| | | return await _invokeMESService.BatchOrderFeedbackToMes(request.orderNos, request.inout); |
| | | } |
| | | |
| | | } |
| | |
| | | using System.Threading.Tasks; |
| | | using WIDESEA_Common.OrderEnum; |
| | | using WIDESEA_Core.Helper; |
| | | using WIDESEA_Core.HttpContextUser; |
| | | using WIDESEA_DTO; |
| | | using WIDESEA_DTO.Inbound; |
| | | using WIDESEA_DTO.Outbound; |
| | |
| | | CreateMap<Dt_ReceiveOrderDetail, Dt_CheckOrder>().ForMember(a => a.ReceivedQuantity, b => b.MapFrom(x => x.ReceivedQuantity)).ForMember(a => a.MaterielCode, b => b.MapFrom(x => x.MaterielCode)).ForMember(a => a.CheckOrderStatus, b => b.MapFrom(x => CheckOrderStatusEnum.NotCheck.ObjToInt())); |
| | | |
| | | CreateMap<Dt_Task, WMSTaskDTO>(); |
| | | |
| | | CreateMap<Dt_Task, Dt_Task_Hty>() |
| | | .ForMember(dest => dest.SourceId, opt => opt.Ignore()) // æå¨å¡«å
ï¼å¿½ç¥æ å° |
| | | .ForMember(dest => dest.OperateType, opt => opt.Ignore()); // æå¨å¡«å
ï¼å¿½ç¥æ å° |
| | | } |
| | | } |
| | | } |