| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div> |
| | | <vol-box |
| | | v-model="showDetialBox" |
| | | :lazy="true" |
| | | width="60%" |
| | | :padding="15" |
| | | title="æå®åºå" |
| | | > |
| | | <div class="box-head"> |
| | | <el-alert :closable="false" style="width: 100%"> |
| | | <el-row> |
| | | <el-col :span="16"> |
| | | <span class="less-style">ç©æåç§°ï¼ {{ row.materielName }} </span> |
| | | <el-divider direction="vertical"></el-divider> |
| | | <span class="less-style">ç©æç¼å·ï¼ {{ row.materielCode }} </span> |
| | | <el-divider direction="vertical"></el-divider> |
| | | <span class="less-style">éæ±æ°éï¼ {{ row.qty }} </span> |
| | | <el-divider direction="vertical"></el-divider> |
| | | <span :class="selectionClass">已鿰éï¼ {{ selectionSum }} </span> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-link |
| | | type="primary" |
| | | size="small" |
| | | style="float: right; height: 20px; margin-right: 10px" |
| | | @click="getData" |
| | | >å·æ°</el-link |
| | | > |
| | | <el-link |
| | | type="primary" |
| | | size="small" |
| | | style="float: right; height: 20px; margin-right: 10px" |
| | | @click="openOutboundDialog" |
| | | >ç´æ¥åºåº</el-link |
| | | > |
| | | </el-col> |
| | | </el-row> |
| | | </el-alert> |
| | | </div> |
| | | <div class="box-table" style="margin-top: 1%"> |
| | | <el-table |
| | | ref="singleTable" |
| | | :data="tableData" |
| | | style="width: 100%; height: 100%" |
| | | highlight-current-row |
| | | @row-click="handleRowClick" |
| | | height="500px" |
| | | @selection-change="handleSelectionChange" |
| | | > |
| | | <el-table-column type="selection" width="55"> </el-table-column> |
| | | <el-table-column |
| | | label="åºå·" |
| | | type="index" |
| | | fixed="left" |
| | | width="55" |
| | | align="center" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | v-for="(item, index) in tableColumns.filter((x) => !x.hidden)" |
| | | :key="index" |
| | | :prop="item.prop" |
| | | :label="item.title" |
| | | :width="item.width" |
| | | align="center" |
| | | > |
| | | <template #default="scoped" v-if="item.type == 'icon'"> |
| | | <el-tooltip |
| | | class="item" |
| | | effect="dark" |
| | | :content="item.title" |
| | | placement="bottom" |
| | | ><el-button |
| | | type="text" |
| | | @click="tableButtonClick(scoped.row, item)" |
| | | ><i :class="item.icon" style="font-size: 22px"></i></el-button |
| | | ></el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | <template #footer> |
| | | <el-button type="danger" size="small" @click="showDetialBox = false" |
| | | >å
³é</el-button |
| | | > |
| | | </template> |
| | | </vol-box> |
| | | |
| | | <!-- åºåºç«å°éæ©å¼¹çªï¼éææ¨¡æ¿å®ç°ï¼ --> |
| | | <el-dialog |
| | | v-model="showOutboundDialog" |
| | | title="åºåºæä½ - éæ©åºåºç«å°" |
| | | width="500px" |
| | | :append-to-body="true" |
| | | > |
| | | <el-form |
| | | :model="outboundForm" |
| | | :rules="outboundRules" |
| | | ref="outboundFormRef" |
| | | label-width="100px" |
| | | style="padding: 0 20px" |
| | | > |
| | | <el-form-item label="åºåºç«å°" prop="selectedPlatform" style="margin-bottom: 24px"> |
| | | <el-select |
| | | v-model="outboundForm.selectedPlatform" |
| | | placeholder="è¯·éæ©åºåºç«å°ï¼3-12ï¼" |
| | | style="width: 100%; height: 40px" |
| | | > |
| | | <el-option |
| | | v-for="platform in platformOptions" |
| | | :key="platform.value" |
| | | :label="platform.label" |
| | | :value="platform.value" |
| | | ></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button @click="showOutboundDialog = false" style="margin-right: 8px">åæ¶</el-button> |
| | | <el-button type="primary" @click="confirmOutbound">ç¡®å®åºåº</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import VolBox from "@/components/basic/VolBox.vue"; |
| | | import { ElMessage } from "element-plus"; |
| | | |
| | | export default { |
| | | components: { VolBox }, |
| | | data() { |
| | | return { |
| | | row: null, |
| | | showDetialBox: false, |
| | | tableData: [], |
| | | tableColumns: [ |
| | | { prop: "materielCode", title: "ç©æç¼å·", type: "string", width: 150 }, |
| | | { prop: "barcode", title: "ç©ææ¡ç ", type: "string", width: 150 }, |
| | | { prop: "palletCode", title: "æçç¼å·", type: "string", width: 150 }, |
| | | { prop: "locationCode", title: "è´§ä½ç¼å·", type: "string", width: 180 }, |
| | | { prop: "useableQuantity", title: "å¯ç¨æ°é", type: "string" }, |
| | | ], |
| | | selection: [], |
| | | selectionSum: 0, |
| | | selectionClass: "less-style", |
| | | originalQuantity: 0, |
| | | |
| | | // åºåºå¼¹çªç¸å
³æ°æ® |
| | | showOutboundDialog: false, |
| | | outboundForm: { selectedPlatform: "" }, // 表åç»å®æ°æ® |
| | | outboundRules: { |
| | | selectedPlatform: [ |
| | | { required: true, message: "è¯·éæ©åºåºç«å°", trigger: "change" }, |
| | | ], |
| | | }, |
| | | platformOptions: [ |
| | | { label: "ç«å°2", value: "2-1" }, |
| | | { label: "ç«å°3", value: "3-1" }, |
| | | ], |
| | | }; |
| | | }, |
| | | methods: { |
| | | open(row) { |
| | | this.row = row; |
| | | this.showDetialBox = true; |
| | | this.getData(); |
| | | console.log(row.id) |
| | | this.updateSelectionClass(); // åå§åå·²éæ°éæ ·å¼ |
| | | }, |
| | | |
| | | lockStock() { |
| | | this.http |
| | | .post( |
| | | "api/OutboundOrderDetail/LockOutboundStock?id=" + this.row.id, |
| | | this.selection, |
| | | "æ°æ®å¤çä¸" |
| | | ) |
| | | .then((x) => { |
| | | if (!x.status) return ElMessage.error(x.message); |
| | | ElMessage.success("æä½æå"); |
| | | this.showDetialBox = false; |
| | | this.$emit("parentCall", ($vue) => { |
| | | $vue.getData(); |
| | | }); |
| | | }); |
| | | }, |
| | | |
| | | // æå¼åºåºå¼¹çª |
| | | openOutboundDialog() { |
| | | if (this.selection.length === 0) { |
| | | return ElMessage.error("è¯·éæ©åæ®æç»"); |
| | | } |
| | | // é置表åé¿å
æ®çå¼ |
| | | this.outboundForm.selectedPlatform = ""; |
| | | this.showOutboundDialog = true; |
| | | }, |
| | | |
| | | // 确认åºåºæä½ |
| | | confirmOutbound() { |
| | | this.$refs.outboundFormRef.validate((valid) => { |
| | | if (!valid) return; |
| | | |
| | | |
| | | if (this.selection.length <= 0) { |
| | | return this.$message.error("请å¾é"); |
| | | } |
| | | let url = this.pkcx |
| | | ? "api/Task/GenerateOutboundTask?orderDetailId=" |
| | | : "api/Task/GenerateOutboundTask?orderDetailId="; |
| | | this.http |
| | | .post(url + this.row.id, this.selection, "æ°æ®å¤çä¸") |
| | | .then((x) => { |
| | | if (!x.status) return this.$message.error(x.message); |
| | | this.$message.success("æä½æå"); |
| | | this.showDetialBox = false; |
| | | this.$emit("parentCall", ($vue) => { |
| | | $vue.getData(); |
| | | }); |
| | | }); |
| | | |
| | | }); |
| | | }, |
| | | |
| | | // åºå®æ¥è¯¢ç«åºåºå |
| | | getData() { |
| | | const url = "api/StockInfo/GetStockSelectViews?materielCode="; |
| | | this.http |
| | | .post( |
| | | url + this.row.materielCode + "&orderId=" + this.row.id, |
| | | null, |
| | | "æ¥è¯¢ä¸" |
| | | ) |
| | | .then((x) => { |
| | | this.tableData = x; |
| | | // å·æ°åæ¸
空ä¹åçéæ©åè®¡æ° |
| | | this.clearSelection(); |
| | | this.selectionSum = 0; |
| | | this.originalQuantity = 0; |
| | | this.updateSelectionClass(); |
| | | }); |
| | | }, |
| | | |
| | | revokeAssign() { |
| | | this.http |
| | | .post( |
| | | "api/OutboundOrderDetail/RevokeLockOutboundStock?id=" + this.row.id, |
| | | null, |
| | | "æ°æ®å¤çä¸" |
| | | ) |
| | | .then((x) => { |
| | | if (!x.status) return ElMessage.error(x.message); |
| | | ElMessage.success("æä½æå"); |
| | | this.showDetialBox = false; |
| | | this.$emit("parentCall", ($vue) => { |
| | | $vue.getData(); |
| | | }); |
| | | }); |
| | | }, |
| | | |
| | | handleSelectionChange(val) { |
| | | this.selection = val; |
| | | // 计ç®å·²éæ°éï¼è½¬æ°åé¿å
åç¬¦ä¸²æ¼æ¥ï¼ |
| | | this.selectionSum = val.reduce( |
| | | (acc, curr) => acc + Number(curr.useableQuantity || 0), |
| | | 0 |
| | | ) + this.originalQuantity; |
| | | this.updateSelectionClass(); |
| | | }, |
| | | |
| | | // æ´æ°å·²éæ°éæ ·å¼ |
| | | updateSelectionClass() { |
| | | if (!this.row) return; |
| | | if (this.selectionSum === this.row.orderQuantity) { |
| | | this.selectionClass = "equle-style"; |
| | | } else if (this.selectionSum < this.row.orderQuantity) { |
| | | this.selectionClass = "less-style"; |
| | | } else { |
| | | this.selectionClass = "more-style"; |
| | | } |
| | | }, |
| | | |
| | | toggleSelection(rows) { |
| | | rows ? rows.forEach((row) => this.$refs.singleTable.toggleRowSelection(row)) : this.clearSelection(); |
| | | }, |
| | | |
| | | clearSelection() { |
| | | if (this.$refs.singleTable) { |
| | | this.$refs.singleTable.clearSelection(); |
| | | } |
| | | }, |
| | | |
| | | handleRowClick(row) { |
| | | this.$refs.singleTable.toggleRowSelection(row); |
| | | }, |
| | | |
| | | // 徿 æé®ç¹å»å 使¹æ³ï¼å¯æ ¹æ®éæ±æ©å±ï¼ |
| | | tableButtonClick(row, item) { |
| | | console.log("徿 æé®ç¹å»ï¼", item.title, row); |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .less-style { |
| | | color: black; |
| | | } |
| | | |
| | | .equle-style { |
| | | color: green; |
| | | } |
| | | |
| | | .more-style { |
| | | color: red; |
| | | } |
| | | </style> |
| | | |
| | | <style> |
| | | .text-button:hover { |
| | | background-color: #f0f9eb !important; |
| | | } |
| | | |
| | | .el-table .warning-row { |
| | | background: oldlace; |
| | | } |
| | | |
| | | .box-table .el-table tbody tr:hover > td { |
| | | background-color: #d8e0d4 !important; |
| | | } |
| | | |
| | | .box-table .el-table tbody tr.current-row > td { |
| | | background-color: #f0f9eb !important; |
| | | } |
| | | |
| | | .el-table .success-row { |
| | | background: #f0f9eb; |
| | | } |
| | | |
| | | .box-table .el-table { |
| | | border: 1px solid #ebeef5; |
| | | } |
| | | |
| | | .box-head .el-alert__content { |
| | | width: 100%; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | /***************************************************************************************** |
| | | ** Author:jxx 2022 |
| | | ** QQ:283591387 |
| | | **宿´ææ¡£è§ï¼http://v2.volcore.xyz/document/api ã代ç çæé¡µé¢ViewGridã |
| | | **常ç¨ç¤ºä¾è§ï¼http://v2.volcore.xyz/document/vueDev |
| | | **åå°æä½è§ï¼http://v2.volcore.xyz/document/netCoreDev |
| | | *****************************************************************************************/ |
| | | //æ¤jsæä»¶æ¯ç¨æ¥èªå®ä¹æ©å±ä¸å¡ä»£ç ï¼å¯ä»¥æ©å±ä¸äºèªå®ä¹é¡µé¢æè
éæ°é
ç½®çæç代ç |
| | | import gridBody from './extend/StockSelect.vue' |
| | | |
| | | let extension = { |
| | | components: { |
| | | //æ¥è¯¢ç颿©å±ç»ä»¶ |
| | | gridHeader: '', |
| | | gridBody: gridBody, |
| | | gridFooter: '', |
| | | //æ°å»ºãç¼è¾å¼¹åºæ¡æ©å±ç»ä»¶ |
| | | modelHeader: '', |
| | | modelBody: '', |
| | | modelFooter: '' |
| | | }, |
| | | tableAction: '', //æå®æå¼ 表çæé(è¿éå¡«å表å,é»è®¤ä¸ç¨å¡«å) |
| | | buttons: { view: [], box: [], detail: [] }, //æ©å±çæé® |
| | | methods: { |
| | | //ä¸é¢è¿äºæ¹æ³å¯ä»¥ä¿çä¹å¯ä»¥å é¤ |
| | | onInit() { //æ¡æ¶åå§åé
ç½®åï¼ |
| | | this.columns.push({ |
| | | field: 'æä½', |
| | | title: 'æä½', |
| | | width: 90, |
| | | fixed: 'right', |
| | | align: 'center', |
| | | formatter: (row) => { |
| | | return ( |
| | | '<i style="cursor: pointer;color: #2d8cf0;"class="el-icon-view">æå®åºå</i>' |
| | | ); |
| | | }, |
| | | click: (row) => { |
| | | const table = this.$refs.table.$refs.table; |
| | | if (table) { |
| | | table.clearSelection(); |
| | | table.toggleRowSelection(row, true); |
| | | } |
| | | this.$refs.gridBody.open(row); |
| | | } |
| | | }); |
| | | }, |
| | | onInited() { |
| | | //æ¡æ¶åå§åé
ç½®å |
| | | //妿è¦é
ç½®æç»è¡¨,卿¤æ¹æ³æä½ |
| | | //this.detailOptions.columns.forEach(column=>{ }); |
| | | }, |
| | | searchBefore(param) { |
| | | //ç颿¥è¯¢å,å¯ä»¥ç»param.wheresæ·»å æ¥è¯¢åæ° |
| | | //è¿åfalseï¼åä¸ä¼æ§è¡æ¥è¯¢ |
| | | return true; |
| | | }, |
| | | searchAfter(result) { |
| | | //æ¥è¯¢åï¼resultè¿åçæ¥è¯¢æ°æ®,å¯ä»¥å¨æ¾ç¤ºå°è¡¨æ ¼åå¤çè¡¨æ ¼çå¼ |
| | | return true; |
| | | }, |
| | | addBefore(formData) { |
| | | //æ°å»ºä¿ååformData为对象ï¼å
æ¬æç»è¡¨ï¼å¯ä»¥ç»ç»è¡¨å设置å¼ï¼èªå·±è¾åºçformDataçå¼ |
| | | return true; |
| | | }, |
| | | updateBefore(formData) { |
| | | //ç¼è¾ä¿ååformData为对象ï¼å
æ¬æç»è¡¨ãå é¤è¡çId |
| | | return true; |
| | | }, |
| | | rowClick({ row, column, event }) { |
| | | //æ¥è¯¢çé¢ç¹å»è¡äºä»¶ |
| | | // this.$refs.table.$refs.table.toggleRowSelection(row); //åå»è¡æ¶éä¸å½åè¡; |
| | | }, |
| | | modelOpenAfter(row) { |
| | | //ç¹å»ç¼è¾ãæ°å»ºæé®å¼¹åºæ¡åï¼å¯ä»¥å¨æ¤å¤åé»è¾ï¼å¦ï¼ä»åå°è·åæ°æ® |
| | | //(1)夿æ¯ç¼è¾è¿æ¯æ°å»ºæä½ï¼ this.currentAction=='Add'; |
| | | //(2)ç»å¼¹åºæ¡è®¾ç½®é»è®¤å¼ |
| | | //(3)this.editFormFields.åæ®µ='xxx'; |
| | | //妿éè¦ç»ä¸ææ¡è®¾ç½®é»è®¤å¼ï¼è¯·éåthis.editFormOptionsæ¾å°å段é
置对åºdata屿§çkeyå¼ |
| | | //ç䏿就æè¾åºçï¼console.log(this.editFormOptions) |
| | | } |
| | | } |
| | | }; |
| | | export default extension; |
| | |
| | | |
| | | const targetRow = selectedRows[0]; |
| | | |
| | | this.$emit('openPalletDialog', targetRow.inboundOrderNo); |
| | | this.$emit('openPalletDialog', targetRow.orderNo); |
| | | } |
| | | }, |
| | | { |
| | |
| | | // åèµ·æ¤éç»çè¯·æ± |
| | | try { |
| | | //console.log('åèµ·æ¤éç»ç请æ±ï¼æçå·ï¼', formData.palletCode.trim()); |
| | | const response = await http.post('/api/InboundOrder/CancelPalletGroup', { |
| | | palletCode: formData.palletCode.trim() |
| | | }); |
| | | const response = await http.post('/api/InboundOrder/UndoPalletGroup?palletCode='+formData.palletCode.trim()); |
| | | |
| | | |
| | | const { status, message, data } = response; |
| | | if (status) { |
| | |
| | | <template> |
| | | <vol-box |
| | | v-model="groupPalletVisible" |
| | | :title="'ç»çæä½ - åæ®å·ï¼' + currentDocNo" |
| | | :height="1000" |
| | | :width="1100" |
| | | :padding="20" |
| | | :modal="true" |
| | | |
| | | @open="handleDialogOpen" |
| | | @close="handleDialogClose" |
| | | > |
| | | <div class="barcode-scanner-container"> |
| | | |
| | | <vol-box v-model="groupPalletVisible" :title="'ç»çæä½ - åæ®å·ï¼' + currentDocNo" :height="1000" :width="1100" :padding="20" |
| | | :modal="true" @open="handleDialogOpen" @close="handleDialogClose"> |
| | | <div class="barcode-scanner-container"> |
| | | |
| | | <!-- ä»åºéæ© - ç´§åå¸å± --> |
| | | <div class="location-section compact"> |
| | | <el-form :model="form" :rules="rules" ref="locationForm" class="compact-form"> |
| | | <el-form-item label="ä»åº" prop="warehouseType" class="location-select compact-item"> |
| | | <el-select |
| | | v-model="form.warehouseType" |
| | | placeholder="è¯·éæ©ä»åº" |
| | | clearable |
| | | filterable |
| | | @change="handleWarehouseChange" |
| | | style="width: 100%" |
| | | :loading="warehouseLoading" |
| | | size="medium" |
| | | > |
| | | <el-option |
| | | v-for="item in warehouseTypes" |
| | | :key="item.warehouseType" |
| | | :label="item.warehouseTypeDesc" |
| | | :value="item.warehouseType" |
| | | /> |
| | | <el-select v-model="form.warehouseType" placeholder="è¯·éæ©ä»åº" clearable filterable |
| | | @change="handleWarehouseChange" style="width: 100%" :loading="warehouseLoading" size="medium"> |
| | | <el-option v-for="item in warehouseTypes" :key="item.warehouseType" :label="item.warehouseTypeDesc" |
| | | :value="item.warehouseType" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-form> |
| | |
| | | <div class="location-section compact"> |
| | | <el-form :model="form" :rules="rules" ref="locationForm" class="compact-form"> |
| | | <el-form-item label="ä»åºåºå" prop="locationType" class="location-select compact-item"> |
| | | <el-select |
| | | v-model="form.locationType" |
| | | placeholder="请å
éæ©ä»åº" |
| | | clearable |
| | | filterable |
| | | @change="handleLocationChange" |
| | | style="width: 100%" |
| | | :loading="locationLoading" |
| | | size="medium" |
| | | > |
| | | <el-option |
| | | v-for="item in locationTypes" |
| | | :key="item.locationType" |
| | | :label="item.locationTypeDesc" |
| | | :value="item.locationType" |
| | | /> |
| | | <el-select v-model="form.locationType" placeholder="请å
éæ©ä»åº" clearable filterable |
| | | @change="handleLocationChange" style="width: 100%" :loading="locationLoading" size="medium"> |
| | | <el-option v-for="item in locationTypes" :key="item.locationType" :label="item.locationTypeDesc" |
| | | :value="item.locationType" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | |
| | | |
| | | <!-- æçä¿¡æ¯æ¾ç¤º - ç´§åå¸å± --> |
| | | <div class="tray-info compact" v-if="trayBarcode"> |
| | | <i class="el-icon-s-management"></i> å½åæç®±: {{ trayBarcode }} |
| | | <span class="location-info" v-if="form.warehouseType"> |
| | | | ä»åº: {{ currentWarehouseName }} |
| | | | ä»åº: {{ currentWarehouseName }} |
| | | </span> |
| | | <span class="location-info" v-if="form.locationType"> |
| | | | ä»åºåºå: {{ currentLocationDesc }} |
| | | </span> |
| | | </div> |
| | | |
| | | |
| | | <!-- æ«ç åºå - ç´§åå¸å± --> |
| | | <div class="input-section compact"> |
| | | <el-card shadow="hover" class="compact-card"> |
| | |
| | | {{ form.locationType && form.warehouseType ? 'æ«ç 就绪' : '请å
éæ©ä»åºåä»åºåºå' }} |
| | | </span> |
| | | </div> |
| | | |
| | | |
| | | <!-- æçæ¡ç è¾å
¥ --> |
| | | <div class="input-wrapper custom-input-group compact-input"> |
| | | <div class="input-label">æç®±ç </div> |
| | | <el-input |
| | | ref="trayInput" |
| | | v-model="trayBarcode" |
| | | placeholder="è¯·æ«ææè¾å
¥æç®±ç åæå车é®" |
| | | clearable |
| | | :disabled="!form.locationType || !form.warehouseType" |
| | | @keyup.enter.native="handleTraySubmit" |
| | | @clear="handleTrayClear" |
| | | @input="handleTrayInput" |
| | | class="custom-input" |
| | | size="medium" |
| | | > |
| | | <el-input ref="trayInput" v-model="trayBarcode" placeholder="è¯·æ«ææè¾å
¥æç®±ç åæå车é®" clearable |
| | | :disabled="!form.locationType || !form.warehouseType" @keyup.enter.native="handleTraySubmit" |
| | | @clear="handleTrayClear" @input="handleTrayInput" class="custom-input" size="medium"> |
| | | <template slot="append"> |
| | | <el-button |
| | | @click="handleTraySubmit" |
| | | type="primary" |
| | | icon="el-icon-position" |
| | | :disabled="!form.locationType || !trayBarcode || !form.warehouseType" |
| | | size="medium" |
| | | > |
| | | <el-button @click="handleTraySubmit" type="primary" icon="el-icon-position" |
| | | :disabled="!form.locationType || !trayBarcode || !form.warehouseType" size="medium"> |
| | | 确认 |
| | | </el-button> |
| | | </template> |
| | | </el-input> |
| | | </div> |
| | | |
| | | |
| | | <!-- ç©ææ¡ç è¾å
¥ --> |
| | | <div class="input-wrapper custom-input-group compact-input"> |
| | | <div class="input-label">ç©ææ¡ç </div> |
| | | <el-input |
| | | ref="barcodeInput" |
| | | v-model="barcode" |
| | | placeholder="è¯·æ«ææè¾å
¥ç©ææ¡ç åæå车é®" |
| | | clearable |
| | | <el-input ref="barcodeInput" v-model="barcode" placeholder="è¯·æ«ææè¾å
¥ç©ææ¡ç åæå车é®" clearable |
| | | :disabled="!form.locationType || !trayBarcode || !form.warehouseType" |
| | | @keyup.enter.native="handleBarcodeSubmit" |
| | | @clear="handleClear" |
| | | @input="handleBarcodeInput" |
| | | class="custom-input" |
| | | size="medium" |
| | | > |
| | | @keyup.enter.native="handleBarcodeSubmit" @clear="handleClear" @input="handleBarcodeInput" |
| | | class="custom-input" size="medium"> |
| | | <template slot="append"> |
| | | <el-button |
| | | :loading="loading" |
| | | @click="handleBarcodeSubmit" |
| | | type="primary" |
| | | icon="el-icon-search" |
| | | :disabled="!form.locationType || !trayBarcode || !barcode || !from.warehouseType" |
| | | size="medium" |
| | | > |
| | | <el-button :loading="loading" @click="handleBarcodeSubmit" type="primary" icon="el-icon-search" |
| | | :disabled="!form.locationType || !trayBarcode || !barcode || !from.warehouseType" size="medium"> |
| | | {{ loading ? 'æ¥è¯¢ä¸...' : 'æ¥è¯¢' }} |
| | | </el-button> |
| | | </template> |
| | | </el-input> |
| | | </div> |
| | | |
| | | |
| | | <div class="input-tips compact-tips"> |
| | | <p>æç¤ºï¼è¯·å
éæ©ä»åº â éæ©ä»åºåºå â è¾å
¥æç®±ç â è¾å
¥ç©ææ¡ç </p> |
| | | <p v-if="!form.warehouseType" class="warning-text">â ï¸ è¯·å
éæ©ä»åº</p> |
| | | <p v-if="!form.locationType && !form.warehouseType" class="warning-text">â ï¸ è¯·å
éæ©ä»åºåºå</p> |
| | | <p v-if="form.warehouseType && form.locationType && !trayBarcode" class="warning-text">â ï¸ è¯·å
è¾å
¥æç®±ç </p> |
| | | </div> |
| | | |
| | | |
| | | </el-card> |
| | | </div> |
| | | |
| | |
| | | |
| | | <!-- é误æç¤º --> |
| | | <div v-if="error" class="error-message compact"> |
| | | <el-alert |
| | | :title="error" |
| | | type="error" |
| | | show-icon |
| | | closable |
| | | @close="error = ''" |
| | | /> |
| | | <el-alert :title="error" type="error" show-icon closable @close="error = ''" /> |
| | | </div> |
| | | |
| | | <!-- ç©æå表 - åºå®é«åº¦å¸¦æ»å¨æ¡ --> |
| | |
| | | <el-tag v-if="form.locationType" type="info" size="small">åºå: {{ currentLocationDesc }}</el-tag> |
| | | </span> |
| | | </div> |
| | | |
| | | |
| | | <div v-if="materials.length === 0" class="empty-state compact"> |
| | | <i class="el-icon-document"></i> |
| | | <p v-if="!form.warehouseType">请å
éæ©ä»åº</p> |
| | |
| | | <p v-else-if="!trayBarcode">请å
è¾å
¥æç®±æ¡ç </p> |
| | | <p v-else>ææ ç©ææ°æ®ï¼è¯·æ«ææè¾å
¥ç©ææ¡ç </p> |
| | | </div> |
| | | |
| | | |
| | | <div class="table-container" v-else> |
| | | <el-table |
| | | :data="materials" |
| | | stripe |
| | | style="width: 100%" |
| | | height="100%" |
| | | size="small" |
| | | > |
| | | <el-table :data="materials" stripe style="width: 100%" height="100%" size="small"> |
| | | <el-table-column type="index" label="åºå·" width="60" align="center"></el-table-column> |
| | | <el-table-column prop="barcode" label="æ¡ç " min-width="140" show-overflow-tooltip></el-table-column> |
| | | <el-table-column prop="materielCode" label="ç©æç¼ç " min-width="150" show-overflow-tooltip></el-table-column> |
| | |
| | | </el-card> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- <div slot="footer" class="dialog-footer"> |
| | | |
| | | <!-- <div slot="footer" class="dialog-footer"> |
| | | <el-button @click="handleCancel">åæ¶</el-button> |
| | | <el-button type="primary" @click="handleConfirm">确认</el-button> |
| | | </div> --> |
| | | </vol-box> |
| | | </vol-box> |
| | | </template> |
| | | <script> |
| | | import http from '@/api/http.js'; |
| | | import VolBox from '@/components/basic/VolBox.vue'; |
| | | import VolForm from '@/components/basic/VolForm.vue'; |
| | | import VolTable from '@/components/basic/VolTable.vue'; |
| | | import { ElLoading, ElMessage,ElMessageBox } from 'element-plus'; |
| | | import { ElLoading, ElMessage, ElMessageBox } from 'element-plus'; |
| | | import { ref, onMounted, onUnmounted } from 'vue' |
| | | import InboundOrder from '../../../views/inbound/inboundOrder.vue'; |
| | | import { th } from 'element-plus/es/locales.mjs'; |
| | |
| | | |
| | | data() { |
| | | return { |
| | | palletVisible: this.visible, |
| | | trayBarcode: '', |
| | | barcode: '', |
| | | materials: [], |
| | | loading: false, |
| | | error: '', |
| | | debugMode: false, |
| | | currentFocus: 'warehouse', |
| | | |
| | | // æ«ç æªç¸å
³åé |
| | | scanCode: '', |
| | | lastKeyTime: null, |
| | | isManualInput: false, |
| | | isScanning: false, |
| | | scanTimer: null, |
| | | manualInputTimer: null, |
| | | scanTarget: 'tray', // å½åæ«ç ç®æ : tray æ material |
| | | palletVisible: this.visible, |
| | | trayBarcode: '', |
| | | barcode: '', |
| | | materials: [], |
| | | loading: false, |
| | | error: '', |
| | | debugMode: false, |
| | | currentFocus: 'warehouse', |
| | | |
| | | // åºåç»è®¡ç¸å
³åé |
| | | totalStockSum: 0, |
| | | totalStockCount: 0, |
| | | uniqueUnit: '', |
| | | sumLoading: false, |
| | | sumError: '', |
| | | // ä»åºç¸å
³åé |
| | | warehouseTypes: [], |
| | | warehouseLoading: false, |
| | | // ä»åºåºåç¸å
³åé |
| | | locationTypes: [], |
| | | locationLoading: false, |
| | | form: { |
| | | warehouseType: null, |
| | | locationType: null |
| | | }, |
| | | rules: { |
| | | locationType: [ |
| | | { |
| | | validator: this.validateLocationType, |
| | | trigger: 'change' |
| | | } |
| | | ], |
| | | warehouseType: [ |
| | | { |
| | | massage:'è¯·éæ©ä»åº', |
| | | // æ«ç æªç¸å
³åé |
| | | scanCode: '', |
| | | lastKeyTime: null, |
| | | isManualInput: false, |
| | | isScanning: false, |
| | | scanTimer: null, |
| | | manualInputTimer: null, |
| | | scanTarget: 'tray', // å½åæ«ç ç®æ : tray æ material |
| | | |
| | | // åºåç»è®¡ç¸å
³åé |
| | | totalStockSum: 0, |
| | | totalStockCount: 0, |
| | | uniqueUnit: '', |
| | | sumLoading: false, |
| | | sumError: '', |
| | | // ä»åºç¸å
³åé |
| | | warehouseTypes: [], |
| | | warehouseLoading: false, |
| | | // ä»åºåºåç¸å
³åé |
| | | locationTypes: [], |
| | | locationLoading: false, |
| | | form: { |
| | | warehouseType: null, |
| | | locationType: null |
| | | }, |
| | | rules: { |
| | | locationType: [ |
| | | { |
| | | validator: this.validateLocationType, |
| | | trigger: 'change' |
| | | } |
| | | ], |
| | | warehouseType: [ |
| | | { |
| | | massage: 'è¯·éæ©ä»åº', |
| | | trigger: 'change' |
| | | } |
| | | ] |
| | |
| | | set(newVal) { this.$emit('update:visible', newVal); } |
| | | }, |
| | | currentDocNo() { return this.docNo; }, |
| | | // å½åéæ©çä»åºåç§° |
| | | // å½åéæ©çä»åºåç§° |
| | | currentWarehouseName() { |
| | | const warehouse = this.warehouseTypes.find(item => item.warehouseType === this.form.warehouseType); |
| | | return warehouse ? warehouse.warehouseTypeDesc : ''; |
| | | }, |
| | | // å½åéæ©çä»åºåºåæè¿° |
| | | // å½åéæ©çä»åºåºåæè¿° |
| | | currentLocationDesc() { |
| | | const location = this.locationTypes.find(item => item.locationType === this.form.locationType) |
| | | return location ? location.locationTypeDesc : '' |
| | | const location = this.locationTypes.find(item => item.locationType === this.form.locationType) |
| | | return location ? location.locationTypeDesc : '' |
| | | } |
| | | }, |
| | | watch: { |
| | | visible(newVal, oldVal) { |
| | | this.palletVisible = newVal; |
| | | |
| | | // å½ä» false å为 true æ¶ï¼è¡¨ç¤ºå¼¹æ¡æå¼ |
| | | if (newVal === true && oldVal === false) { |
| | | console.log('å¼¹æ¡æå¼ï¼éç½®æ°æ®'); |
| | | this.resetData(); |
| | | this.$nextTick(() => { |
| | | setTimeout(() => { |
| | | // this.focusTrayInput(); |
| | | this.initwarehouseTypes(); // åå§åä»åº |
| | | this.initLocationTypes(); // åå§åä»åºåºå |
| | | this.fetchStockStatistics(); // å è½½ç»è®¡æ°æ® |
| | | }, 300); |
| | | }); |
| | | } |
| | | |
| | | // å½ä» true å为 false æ¶ï¼è¡¨ç¤ºå¼¹æ¡å
³é |
| | | if (newVal === false && oldVal === true) { |
| | | console.log('å¼¹æ¡å
³éï¼éç½®æ°æ®'); |
| | | this.resetData(); |
| | | } |
| | | }, |
| | | palletVisible(newVal) { |
| | | this.$emit('update:visible', newVal); |
| | | }, |
| | | this.palletVisible = newVal; |
| | | |
| | | // å½ä» false å为 true æ¶ï¼è¡¨ç¤ºå¼¹æ¡æå¼ |
| | | if (newVal === true && oldVal === false) { |
| | | console.log('å¼¹æ¡æå¼ï¼éç½®æ°æ®'); |
| | | this.resetData(); |
| | | this.$nextTick(() => { |
| | | setTimeout(() => { |
| | | // this.focusTrayInput(); |
| | | this.initwarehouseTypes(); // åå§åä»åº |
| | | this.initLocationTypes(); // åå§åä»åºåºå |
| | | this.fetchStockStatistics(); // å è½½ç»è®¡æ°æ® |
| | | }, 300); |
| | | }); |
| | | } |
| | | |
| | | // å½ä» true å为 false æ¶ï¼è¡¨ç¤ºå¼¹æ¡å
³é |
| | | if (newVal === false && oldVal === true) { |
| | | console.log('å¼¹æ¡å
³éï¼éç½®æ°æ®'); |
| | | this.resetData(); |
| | | } |
| | | }, |
| | | palletVisible(newVal) { |
| | | this.$emit('update:visible', newVal); |
| | | }, |
| | | docNo(newVal) { |
| | | if (newVal) { |
| | | this.palletForm = { palletCode: '', barcode: '' }; |
| | |
| | | } |
| | | }, |
| | | 'form.warehouseType'(newVal) { |
| | | if (newVal) { |
| | | this.form.locationType = null; |
| | | if (newVal) { |
| | | this.form.locationType = null; |
| | | } else { |
| | | this.locationTypes = []; |
| | | } |
| | | }, |
| | | |
| | | mounted() { |
| | | |
| | | // æ·»å å
¨å±é®ççå¬ |
| | | document.addEventListener('keypress', this.handleKeyPress); |
| | | |
| | | // 使ç¨setTimeoutç¡®ä¿DOMå®å
¨æ¸²æååèç¦ |
| | | setTimeout(() => { |
| | | // this.focusTrayInput(); |
| | | this.focusLocationSelect(); |
| | | }, 300); |
| | | }, |
| | | beforeDestroy() { |
| | | // æ¸
çäºä»¶çå¬ |
| | | document.removeEventListener('keypress', this.handleKeyPress); |
| | | this.clearAllTimers(); |
| | | }, |
| | | methods: { |
| | | /** |
| | | * èªå®ä¹ä»åºåºåéªè¯ |
| | | * å
许å¼ä¸º0ï¼å 为0æ¯åæ³çlocationType |
| | | */ |
| | | validateLocationType(rule, value, callback) { |
| | | // æ£æ¥å¼æ¯å¦ä¸ºnullãundefinedæç©ºå符串ï¼ä½å
许æ°å0 |
| | | if (!this.form.warehouseType) { |
| | | callback(new Error('请å
éæ©ä»åº')); |
| | | } else if (value === null || value === undefined || value === '') { |
| | | callback(new Error('è¯·éæ©ä»åºåºå')); |
| | | } else { |
| | | this.locationTypes = []; |
| | | callback(); |
| | | } |
| | | }, |
| | | /** |
| | | * åå§åä»åºåºåæ°æ® |
| | | */ |
| | | async initLocationTypes() { |
| | | this.locationLoading = true; |
| | | this.error = ''; |
| | | |
| | | try { |
| | | const response = await http.post('/api/LocationInfo/GetLocationTypes'); |
| | | |
| | | if (response.status && Array.isArray(response.data)) { |
| | | this.locationTypes = response.data; |
| | | if (this.locationTypes.length === 0) { |
| | | this.error = 'æªè·åå°ä»åºåºåæ°æ®'; |
| | | } else { |
| | | // 妿æé»è®¤åºåï¼å¯ä»¥å¨è¿é设置 |
| | | // this.form.locationType = this.locationTypes[0].locationType; |
| | | } |
| | | } else { |
| | | this.error = 'è·åä»åºåºåæ°æ®å¤±è´¥'; |
| | | } |
| | | } catch (error) { |
| | | console.error('è·åä»åºåºå失败:', error); |
| | | this.error = `è·åä»åºåºå失败: ${error.message || 'ç½ç»é误'}`; |
| | | } finally { |
| | | this.locationLoading = false; |
| | | } |
| | | }, |
| | | |
| | | mounted() { |
| | | |
| | | // æ·»å å
¨å±é®ççå¬ |
| | | document.addEventListener('keypress', this.handleKeyPress); |
| | | |
| | | // 使ç¨setTimeoutç¡®ä¿DOMå®å
¨æ¸²æååèç¦ |
| | | setTimeout(() => { |
| | | // this.focusTrayInput(); |
| | | this.focusLocationSelect(); |
| | | }, 300); |
| | | }, |
| | | beforeDestroy() { |
| | | // æ¸
çäºä»¶çå¬ |
| | | document.removeEventListener('keypress', this.handleKeyPress); |
| | | this.clearAllTimers(); |
| | | }, |
| | | methods: { |
| | | /** |
| | | * èªå®ä¹ä»åºåºåéªè¯ |
| | | * å
许å¼ä¸º0ï¼å 为0æ¯åæ³çlocationType |
| | | */ |
| | | validateLocationType(rule, value, callback) { |
| | | // æ£æ¥å¼æ¯å¦ä¸ºnullãundefinedæç©ºå符串ï¼ä½å
许æ°å0 |
| | | if (!this.form.warehouseType) { |
| | | callback(new Error('请å
éæ©ä»åº')); |
| | | } else if (value === null || value === undefined || value === '') { |
| | | callback(new Error('è¯·éæ©ä»åºåºå')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | /** |
| | | * åå§åä»åºåºåæ°æ® |
| | | */ |
| | | async initLocationTypes() { |
| | | this.locationLoading = true; |
| | | this.error = ''; |
| | | |
| | | try { |
| | | const response = await http.post('/api/LocationInfo/GetLocationTypes'); |
| | | |
| | | if (response.status && Array.isArray(response.data)) { |
| | | this.locationTypes = response.data; |
| | | if (this.locationTypes.length === 0) { |
| | | this.error = 'æªè·åå°ä»åºåºåæ°æ®'; |
| | | } else { |
| | | // 妿æé»è®¤åºåï¼å¯ä»¥å¨è¿é设置 |
| | | // this.form.locationType = this.locationTypes[0].locationType; |
| | | } |
| | | } else { |
| | | this.error = 'è·åä»åºåºåæ°æ®å¤±è´¥'; |
| | | } |
| | | } catch (error) { |
| | | console.error('è·åä»åºåºå失败:', error); |
| | | this.error = `è·åä»åºåºå失败: ${error.message || 'ç½ç»é误'}`; |
| | | } finally { |
| | | this.locationLoading = false; |
| | | } |
| | | }, |
| | | /** |
| | | * åå§åä»åºæ°æ® |
| | | */ |
| | | async initwarehouseTypes() { |
| | | this.warehouseLoading = true; |
| | | this.error = ''; |
| | | |
| | | /** |
| | | * åå§åä»åºæ°æ® |
| | | */ |
| | | async initwarehouseTypes() { |
| | | this.warehouseLoading = true; |
| | | this.error = ''; |
| | | |
| | | try { |
| | | const response = await http.post('/api/Warehouse/GetwarehouseTypes'); |
| | | |
| | | if (response.status && Array.isArray(response.data)) { |
| | | this.warehouseTypes = response.data; |
| | | if (this.warehouseTypes.length === 0) { |
| | | this.error = 'æªè·åå°ä»åºæ°æ®'; |
| | | } else { |
| | | // 妿æé»è®¤åºåï¼å¯ä»¥å¨è¿é设置 |
| | | // this.form.locationType = this.locationTypes[0].locationType; |
| | | } |
| | | } else { |
| | | this.error = 'è·åä»åºæ°æ®å¤±è´¥'; |
| | | } |
| | | } catch (error) { |
| | | console.error('è·åä»åºå¤±è´¥:', error); |
| | | this.error = `è·åä»åºå¤±è´¥: ${error.message || 'ç½ç»é误'}`; |
| | | } finally { |
| | | this.warehouseLoading = false; |
| | | } |
| | | }, |
| | | try { |
| | | const response = await http.post('/api/Warehouse/GetwarehouseTypes'); |
| | | |
| | | if (response.status && Array.isArray(response.data)) { |
| | | this.warehouseTypes = response.data; |
| | | if (this.warehouseTypes.length === 0) { |
| | | this.error = 'æªè·åå°ä»åºæ°æ®'; |
| | | } else { |
| | | // 妿æé»è®¤åºåï¼å¯ä»¥å¨è¿é设置 |
| | | // this.form.locationType = this.locationTypes[0].locationType; |
| | | } |
| | | } else { |
| | | this.error = 'è·åä»åºæ°æ®å¤±è´¥'; |
| | | } |
| | | } catch (error) { |
| | | console.error('è·åä»åºå¤±è´¥:', error); |
| | | this.error = `è·åä»åºå¤±è´¥: ${error.message || 'ç½ç»é误'}`; |
| | | } finally { |
| | | this.warehouseLoading = false; |
| | | } |
| | | }, |
| | | |
| | | |
| | | /** |
| | | * ä»åºåºååæ´å¤ç |
| | | */ |
| | | handleLocationChange(value) { |
| | | console.log('éæ©ä»åºåºå:', value, 'ç±»å:', typeof value, this.currentLocationDesc); |
| | | |
| | | // ç«å³æ¸
é¤éè¯¯ä¿¡æ¯ |
| | | this.error = ''; |
| | | |
| | | // æå¨è§¦å表åéªè¯æ´æ° |
| | | this.$nextTick(() => { |
| | | if (this.$refs.locationForm) { |
| | | // æ¸
é¤è¯¥å段çéªè¯ç¶æï¼ç¶åéæ°éªè¯ |
| | | this.$refs.locationForm.clearValidate('locationType'); |
| | | |
| | | // çæå»¶è¿åéæ°éªè¯ï¼ç¡®ä¿DOMå·²æ´æ° |
| | | setTimeout(() => { |
| | | this.$refs.locationForm.validateField('locationType', (errorMsg) => { |
| | | if (!errorMsg && (value === 0 || value)) { |
| | | console.log('ä»åºåºåéªè¯éè¿:', value); |
| | | // åºåéæ©åï¼èªå¨èç¦å°æçè¾å
¥æ¡ |
| | | this.focusLocationSelect(); |
| | | } |
| | | }); |
| | | }, 100); |
| | | } |
| | | }); |
| | | }, |
| | | /** |
| | | * ä»åºåºååæ´å¤ç |
| | | */ |
| | | handleLocationChange(value) { |
| | | console.log('éæ©ä»åºåºå:', value, 'ç±»å:', typeof value, this.currentLocationDesc); |
| | | |
| | | /** |
| | | * ä»åºåæ´å¤ç |
| | | */ |
| | | handleWarehouseChange(value) { |
| | | console.log('éæ©ä»åº:', value, 'ç±»å:', typeof value, this.currentWarehouseName); |
| | | |
| | | // ç«å³æ¸
é¤éè¯¯ä¿¡æ¯ |
| | | this.error = ''; |
| | | |
| | | // æå¨è§¦å表åéªè¯æ´æ° |
| | | this.$nextTick(() => { |
| | | if (this.$refs.locationForm) { |
| | | // æ¸
é¤è¯¥å段çéªè¯ç¶æï¼ç¶åéæ°éªè¯ |
| | | this.$refs.locationForm.clearValidate('warehouseType'); |
| | | |
| | | // çæå»¶è¿åéæ°éªè¯ï¼ç¡®ä¿DOMå·²æ´æ° |
| | | setTimeout(() => { |
| | | this.$refs.locationForm.validateField('warehouseType', (errorMsg) => { |
| | | if (!errorMsg && (value === 0 || value)) { |
| | | console.log('ä»åºéªè¯éè¿:', value); |
| | | this.focusLocationSelect(); |
| | | } |
| | | }); |
| | | }, 100); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // ç«å³æ¸
é¤éè¯¯ä¿¡æ¯ |
| | | this.error = ''; |
| | | |
| | | // æå¨è§¦å表åéªè¯æ´æ° |
| | | this.$nextTick(() => { |
| | | if (this.$refs.locationForm) { |
| | | // æ¸
é¤è¯¥å段çéªè¯ç¶æï¼ç¶åéæ°éªè¯ |
| | | this.$refs.locationForm.clearValidate('locationType'); |
| | | |
| | | // çæå»¶è¿åéæ°éªè¯ï¼ç¡®ä¿DOMå·²æ´æ° |
| | | setTimeout(() => { |
| | | this.$refs.locationForm.validateField('locationType', (errorMsg) => { |
| | | if (!errorMsg && (value === 0 || value)) { |
| | | console.log('ä»åºåºåéªè¯éè¿:', value); |
| | | // åºåéæ©åï¼èªå¨èç¦å°æçè¾å
¥æ¡ |
| | | this.focusLocationSelect(); |
| | | } |
| | | }); |
| | | }, 100); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * ä»åºåæ´å¤ç |
| | | */ |
| | | handleWarehouseChange(value) { |
| | | console.log('éæ©ä»åº:', value, 'ç±»å:', typeof value, this.currentWarehouseName); |
| | | |
| | | // ç«å³æ¸
é¤éè¯¯ä¿¡æ¯ |
| | | this.error = ''; |
| | | |
| | | // æå¨è§¦å表åéªè¯æ´æ° |
| | | this.$nextTick(() => { |
| | | if (this.$refs.locationForm) { |
| | | // æ¸
é¤è¯¥å段çéªè¯ç¶æï¼ç¶åéæ°éªè¯ |
| | | this.$refs.locationForm.clearValidate('warehouseType'); |
| | | |
| | | // çæå»¶è¿åéæ°éªè¯ï¼ç¡®ä¿DOMå·²æ´æ° |
| | | setTimeout(() => { |
| | | this.$refs.locationForm.validateField('warehouseType', (errorMsg) => { |
| | | if (!errorMsg && (value === 0 || value)) { |
| | | console.log('ä»åºéªè¯éè¿:', value); |
| | | this.focusLocationSelect(); |
| | | } |
| | | }); |
| | | }, 100); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | async fetchStockStatistics() { |
| | | // åæ®å·ä¸ºç©ºæ¶ä¸æ¥è¯¢ |
| | | if (!this.docNo) { |
| | |
| | | this.sumError = ''; |
| | | try { |
| | | // è°ç¨å端ç»è®¡æ¥å£ï¼æ¿æ¢ä¸ºä½ çå®é
æ¥å£è·¯å¾ï¼ |
| | | const response = await http.post('/api/InboundOrder/UnPalletQuantity?orderNo='+this.docNo, { |
| | | |
| | | const response = await http.post('/api/InboundOrder/UnPalletQuantity?orderNo=' + this.docNo, { |
| | | |
| | | }); |
| | | |
| | | // ç»å®æ°æ®ï¼å¹é
PalletSumQuantityDTO ç»æï¼ |
| | |
| | | this.sumLoading = false; |
| | | } |
| | | }, |
| | | /** |
| | | * 表åéªè¯ |
| | | */ |
| | | async validateForm() { |
| | | return new Promise((resolve) => { |
| | | if (!this.$refs.locationForm) { |
| | | this.error = 'è¡¨åæªåå§å'; |
| | | this.$message.warning('请å
éæ©ä»åºåºå'); |
| | | resolve(false); |
| | | return; |
| | | } |
| | | /** |
| | | * 表åéªè¯ |
| | | */ |
| | | async validateForm() { |
| | | return new Promise((resolve) => { |
| | | if (!this.$refs.locationForm) { |
| | | this.error = 'è¡¨åæªåå§å'; |
| | | this.$message.warning('请å
éæ©ä»åºåºå'); |
| | | resolve(false); |
| | | return; |
| | | } |
| | | |
| | | this.$refs.locationForm.validate((valid) => { |
| | | if (valid) { |
| | | this.error = ''; |
| | | resolve(true); |
| | | } else { |
| | | // æå¨æ£æ¥locationTypeï¼æ£ç¡®å¤çå¼ä¸º0çæ
åµ |
| | | if(!this.from.warehouseType){ |
| | | this.error='请å
éæ©ä»åº'; |
| | | this.$refs.locationForm.validate((valid) => { |
| | | if (valid) { |
| | | this.error = ''; |
| | | resolve(true); |
| | | } else { |
| | | // æå¨æ£æ¥locationTypeï¼æ£ç¡®å¤çå¼ä¸º0çæ
åµ |
| | | if (!this.from.warehouseType) { |
| | | this.error = '请å
éæ©ä»åº'; |
| | | } |
| | | else if (this.form.locationType === null || this.form.locationType === undefined || this.form.locationType === '') { |
| | | this.error = '请å
éæ©ä»åºåºå'; |
| | | //this.$message.warning('请å
éæ©ä»åºåºå'); |
| | | } else { |
| | | // 妿å¼åå¨ï¼å
æ¬0ï¼ï¼ä½éªè¯ä¸éè¿ï¼å¯è½æ¯å
¶ä»éªè¯é误 |
| | | this.error = 'è¯·æ£æ¥è¡¨å填忝妿£ç¡®'; |
| | | } |
| | | resolve(false); |
| | | } |
| | | }); |
| | | }); |
| | | }, |
| | | focusWarehouseSelect() { |
| | | if (this.$refs.locationForm) { |
| | | const selectEl = this.$el.querySelector('.location-select:first-child .el-input__inner'); |
| | | if (selectEl) { |
| | | selectEl.focus(); |
| | | this.currentFocus = 'warehouse'; |
| | | } |
| | | else if(this.form.locationType === null || this.form.locationType === undefined || this.form.locationType === '') { |
| | | this.error = '请å
éæ©ä»åºåºå'; |
| | | //this.$message.warning('请å
éæ©ä»åºåºå'); |
| | | } else { |
| | | // 妿å¼åå¨ï¼å
æ¬0ï¼ï¼ä½éªè¯ä¸éè¿ï¼å¯è½æ¯å
¶ä»éªè¯é误 |
| | | this.error = 'è¯·æ£æ¥è¡¨å填忝妿£ç¡®'; |
| | | } |
| | | resolve(false); |
| | | } |
| | | }); |
| | | }); |
| | | }, |
| | | focusWarehouseSelect() { |
| | | if (this.$refs.locationForm) { |
| | | const selectEl = this.$el.querySelector('.location-select:first-child .el-input__inner'); |
| | | if (selectEl) { |
| | | selectEl.focus(); |
| | | this.currentFocus = 'warehouse'; |
| | | } |
| | | } |
| | | }, |
| | | // èç¦å°ä»åºåºåéæ© |
| | | focusLocationSelect() { |
| | | if (this.$refs.locationForm) { |
| | | const selectEl = this.$el.querySelector('.location-select:nth-child(2) .el-input__inner'); |
| | | if (selectEl) { |
| | | selectEl.focus(); |
| | | this.currentFocus = 'location'; |
| | | } |
| | | } |
| | | }, |
| | | // èç¦å°æçè¾å
¥æ¡ |
| | | focusTrayInput() { |
| | | if (this.$refs.trayInput && this.$refs.trayInput.$el) { |
| | | const inputEl = this.$refs.trayInput.$el.querySelector('input'); |
| | | if (inputEl) { |
| | | inputEl.focus(); |
| | | this.currentFocus = 'tray'; |
| | | this.scanTarget = 'tray'; |
| | | } |
| | | } |
| | | }, |
| | | |
| | | // èç¦å°ç©æè¾å
¥æ¡ |
| | | focusBarcodeInput() { |
| | | if (this.$refs.barcodeInput && this.$refs.barcodeInput.$el) { |
| | | const inputEl = this.$refs.barcodeInput.$el.querySelector('input'); |
| | | if (inputEl) { |
| | | inputEl.focus(); |
| | | this.currentFocus = 'material'; |
| | | this.scanTarget = 'material'; |
| | | } |
| | | } |
| | | }, |
| | | // éç½®æææ°æ® |
| | | }, |
| | | // èç¦å°ä»åºåºåéæ© |
| | | focusLocationSelect() { |
| | | if (this.$refs.locationForm) { |
| | | const selectEl = this.$el.querySelector('.location-select:nth-child(2) .el-input__inner'); |
| | | if (selectEl) { |
| | | selectEl.focus(); |
| | | this.currentFocus = 'location'; |
| | | } |
| | | } |
| | | }, |
| | | // èç¦å°æçè¾å
¥æ¡ |
| | | focusTrayInput() { |
| | | if (this.$refs.trayInput && this.$refs.trayInput.$el) { |
| | | const inputEl = this.$refs.trayInput.$el.querySelector('input'); |
| | | if (inputEl) { |
| | | inputEl.focus(); |
| | | this.currentFocus = 'tray'; |
| | | this.scanTarget = 'tray'; |
| | | } |
| | | } |
| | | }, |
| | | |
| | | // èç¦å°ç©æè¾å
¥æ¡ |
| | | focusBarcodeInput() { |
| | | if (this.$refs.barcodeInput && this.$refs.barcodeInput.$el) { |
| | | const inputEl = this.$refs.barcodeInput.$el.querySelector('input'); |
| | | if (inputEl) { |
| | | inputEl.focus(); |
| | | this.currentFocus = 'material'; |
| | | this.scanTarget = 'material'; |
| | | |
| | | |
| | | inputEl.select(); |
| | | console.log('ç©æè¾å
¥æ¡å
容已éä¸'); |
| | | |
| | | } |
| | | } |
| | | }, |
| | | |
| | | |
| | | |
| | | |
| | | // éç½®æææ°æ® |
| | | resetData() { |
| | | console.log('éç½®å¼¹æ¡æ°æ®'); |
| | | this.trayBarcode = ''; |
| | |
| | | this.totalStockCount = 0; |
| | | this.sumLoading = false; |
| | | this.sumError = ''; |
| | | this.form={ |
| | | warehouseType:null, |
| | | locationType:null |
| | | this.form = { |
| | | warehouseType: null, |
| | | locationType: null |
| | | } |
| | | this.warehouseTypes = []; |
| | | this.locationTypes = []; |
| | | // æ¸
é¤è¡¨åéªè¯ç¶æ |
| | | this.$nextTick(() => { |
| | | if (this.$refs.locationForm) { |
| | | this.$refs.locationForm.clearValidate(); |
| | | } |
| | | this.warehouseTypes=[]; |
| | | this.locationTypes=[]; |
| | | // æ¸
é¤è¡¨åéªè¯ç¶æ |
| | | this.$nextTick(() => { |
| | | if (this.$refs.locationForm) { |
| | | this.$refs.locationForm.clearValidate(); |
| | | } |
| | | }); |
| | | }); |
| | | }, |
| | | |
| | | |
| | | // æ¸
餿æè®¡æ¶å¨ |
| | | clearAllTimers() { |
| | | if (this.manualInputTimer) { |
| | |
| | | this.scanTimer = null; |
| | | } |
| | | }, |
| | | |
| | | |
| | | // å¼¹æ¡æå¼æ¶éç½®æ°æ® |
| | | handleDialogOpen() { |
| | | console.log('å¼¹æ¡æå¼ï¼éç½®æ°æ®'); |
| | |
| | | // 使ç¨setTimeoutç¡®ä¿DOMå®å
¨æ¸²æååèç¦ |
| | | this.$nextTick(() => { |
| | | setTimeout(() => { |
| | | this.initwarehouseTypes(); |
| | | this.initLocationTypes(); // åå§åä»åºåºå |
| | | // ç¡®ä¿è¡¨åå¼ç¨åå¨ååèç¦ |
| | | if (this.$refs.locationForm) { |
| | | this.focusWarehouseSelect(); |
| | | } else { |
| | | // å¦æè¡¨åå¼ç¨è¿ä¸åå¨ï¼ç¨åéè¯ |
| | | setTimeout(() => { |
| | | this.focusWarehouseSelect(); |
| | | }, 500); |
| | | } |
| | | this.initwarehouseTypes(); |
| | | this.initLocationTypes(); // åå§åä»åºåºå |
| | | // ç¡®ä¿è¡¨åå¼ç¨åå¨ååèç¦ |
| | | if (this.$refs.locationForm) { |
| | | this.focusWarehouseSelect(); |
| | | } else { |
| | | // å¦æè¡¨åå¼ç¨è¿ä¸åå¨ï¼ç¨åéè¯ |
| | | setTimeout(() => { |
| | | this.focusWarehouseSelect(); |
| | | }, 500); |
| | | } |
| | | }, 300); |
| | | }); |
| | | }, |
| | | |
| | | |
| | | // å¼¹æ¡å
³éæ¶éç½®æ°æ® |
| | | handleDialogClose() { |
| | | console.log('å¼¹æ¡å
³éï¼éç½®æ°æ®'); |
| | | this.resetData(); |
| | | }, |
| | | |
| | | |
| | | // åæ¶æé® |
| | | handleCancel() { |
| | | this.palletVisible = false; |
| | | }, |
| | | |
| | | |
| | | // 确认æé® |
| | | async handleConfirm() { |
| | | if (!await this.validateForm()) return; |
| | | async handleConfirm() { |
| | | if (!await this.validateForm()) return; |
| | | |
| | | if (this.materials.length === 0) { |
| | | this.$message.warning('请è³å°æ·»å ä¸ä¸ªç©æ'); |
| | | return; |
| | | } |
| | | |
| | | |
| | | if (!this.trayBarcode) { |
| | | this.$message.warning('请è¾å
¥æçæ¡ç '); |
| | | return; |
| | | } |
| | | |
| | | |
| | | const result = { |
| | | warehouseType:this.form.warehouseType, |
| | | warehouseName:this.currentWarehouseName, |
| | | warehouseType: this.form.warehouseType, |
| | | warehouseName: this.currentWarehouseName, |
| | | locationType: this.form.locationType, |
| | | locationDesc: this.currentLocationDesc, |
| | | trayBarcode: this.trayBarcode, |
| | | materials: this.materials, |
| | | docNo: this.docNo |
| | | }; |
| | | |
| | | |
| | | // 触åç¶ç»ä»¶ç back-success äºä»¶ |
| | | this.$emit('back-success', result); |
| | | this.palletVisible = false; |
| | | }, |
| | | // å¤çæçè¾å
¥ |
| | | handleTrayInput() { |
| | | // æ 记为æå¨è¾å
¥æ¨¡å¼ |
| | | this.isManualInput = true; |
| | | this.isScanning = false; |
| | | |
| | | // æ¸
é¤ä¹åç计æ¶å¨ |
| | | if (this.manualInputTimer) { |
| | | clearTimeout(this.manualInputTimer); |
| | | } |
| | | |
| | | // 设置计æ¶å¨ï¼å¦æä¸æ®µæ¶é´å
没æè¾å
¥ï¼åé置为æ«ç æ¨¡å¼ |
| | | this.manualInputTimer = setTimeout(() => { |
| | | this.isManualInput = false; |
| | | }, 1000); |
| | | }, |
| | | |
| | | // å¤çç©æè¾å
¥ |
| | | handleBarcodeInput() { |
| | | // æ 记为æå¨è¾å
¥æ¨¡å¼ |
| | | this.isManualInput = true; |
| | | this.isScanning = false; |
| | | |
| | | // æ¸
é¤ä¹åç计æ¶å¨ |
| | | if (this.manualInputTimer) { |
| | | clearTimeout(this.manualInputTimer); |
| | | } |
| | | |
| | | // 设置计æ¶å¨ï¼å¦æä¸æ®µæ¶é´å
没æè¾å
¥ï¼åé置为æ«ç æ¨¡å¼ |
| | | this.manualInputTimer = setTimeout(() => { |
| | | this.isManualInput = false; |
| | | }, 1000); |
| | | }, |
| | | |
| | | // å¤çæçæ¡ç æäº¤ |
| | | async handleTraySubmit() { |
| | | // å
ç´æ¥æ£æ¥locationTypeï¼é¿å
表åéªè¯ç弿¥é®é¢ |
| | | if (!this.form.warehouseType) { |
| | | this.error = '请å
éæ©ä»åº'; |
| | | return; |
| | | } |
| | | if (!this.form.locationType) { |
| | | this.error = '请å
éæ©ä»åºåºå'; |
| | | //this.$message.warning('请å
éæ©ä»åºåºå'); |
| | | return; |
| | | } |
| | | |
| | | // ç¶ååè¿è¡å®æ´ç表åéªè¯ |
| | | if (!await this.validateForm()) return; |
| | | |
| | | const currentTrayBarcode = this.trayBarcode.trim(); |
| | | |
| | | if (!currentTrayBarcode) { |
| | | this.error = '请è¾å
¥ææ«ææçæ¡ç '; |
| | | return; |
| | | } |
| | | handleTrayInput() { |
| | | // æ 记为æå¨è¾å
¥æ¨¡å¼ |
| | | this.isManualInput = true; |
| | | this.isScanning = false; |
| | | |
| | | this.error = ''; |
| | | |
| | | // 设置æçæ¡ç åï¼èªå¨èç¦å°ç©æè¾å
¥æ¡ |
| | | this.focusBarcodeInput(); |
| | | |
| | | this.$message({ |
| | | message: `æçæ¡ç 已设置: ${currentTrayBarcode}`, |
| | | type: 'success', |
| | | duration: 2000 |
| | | }); |
| | | }, |
| | | |
| | | // æ¸
餿ç |
| | | clearTray() { |
| | | this.trayBarcode = ''; |
| | | this.materials = []; |
| | | this.focusTrayInput(); |
| | | // æ¸
é¤ä¹åç计æ¶å¨ |
| | | if (this.manualInputTimer) { |
| | | clearTimeout(this.manualInputTimer); |
| | | } |
| | | |
| | | // 设置计æ¶å¨ï¼å¦æä¸æ®µæ¶é´å
没æè¾å
¥ï¼åé置为æ«ç æ¨¡å¼ |
| | | this.manualInputTimer = setTimeout(() => { |
| | | this.isManualInput = false; |
| | | }, 1000); |
| | | }, |
| | | |
| | | // å¤çç©æè¾å
¥ |
| | | handleBarcodeInput() { |
| | | // æ 记为æå¨è¾å
¥æ¨¡å¼ |
| | | this.isManualInput = true; |
| | | this.isScanning = false; |
| | | |
| | | // æ¸
é¤ä¹åç计æ¶å¨ |
| | | if (this.manualInputTimer) { |
| | | clearTimeout(this.manualInputTimer); |
| | | } |
| | | |
| | | // 设置计æ¶å¨ï¼å¦æä¸æ®µæ¶é´å
没æè¾å
¥ï¼åé置为æ«ç æ¨¡å¼ |
| | | this.manualInputTimer = setTimeout(() => { |
| | | this.isManualInput = false; |
| | | }, 1000); |
| | | }, |
| | | |
| | | // å¤çæçæ¡ç æäº¤ |
| | | async handleTraySubmit() { |
| | | // å
ç´æ¥æ£æ¥locationTypeï¼é¿å
表åéªè¯ç弿¥é®é¢ |
| | | if (!this.form.warehouseType) { |
| | | this.error = '请å
éæ©ä»åº'; |
| | | return; |
| | | } |
| | | if (!this.form.locationType) { |
| | | this.error = '请å
éæ©ä»åºåºå'; |
| | | //this.$message.warning('请å
éæ©ä»åºåºå'); |
| | | return; |
| | | } |
| | | |
| | | // ç¶ååè¿è¡å®æ´ç表åéªè¯ |
| | | if (!await this.validateForm()) return; |
| | | |
| | | const currentTrayBarcode = this.trayBarcode.trim(); |
| | | |
| | | if (!currentTrayBarcode) { |
| | | this.error = '请è¾å
¥ææ«ææçæ¡ç '; |
| | | return; |
| | | } |
| | | |
| | | this.error = ''; |
| | | |
| | | // 设置æçæ¡ç åï¼èªå¨èç¦å°ç©æè¾å
¥æ¡ |
| | | this.focusBarcodeInput(); |
| | | |
| | | this.$message({ |
| | | message: `æçæ¡ç 已设置: ${currentTrayBarcode}`, |
| | | type: 'success', |
| | | duration: 2000 |
| | | }); |
| | | }, |
| | | |
| | | // æ¸
餿ç |
| | | clearTray() { |
| | | this.trayBarcode = ''; |
| | | this.materials = []; |
| | | this.focusTrayInput(); |
| | | this.$message({ |
| | | message: 'æçæ¡ç å·²æ¸
é¤', |
| | | type: 'info', |
| | | duration: 2000 |
| | | }); |
| | | }, |
| | | |
| | | // æ¸
空æçè¾å
¥ |
| | | handleTrayClear() { |
| | | this.error = ''; |
| | | }, |
| | | |
| | | // æ¸
空è¾å
¥ |
| | | handleClear() { |
| | | this.error = ''; |
| | | this.scanCode = ''; |
| | | this.isManualInput = false; |
| | | this.isScanning = false; |
| | | }, |
| | | |
| | | |
| | | // å¤çç©ææ¡ç æäº¤ |
| | | async handleBarcodeSubmit() { |
| | | if (!await this.validateForm()) return; |
| | | const currentBarcode = this.barcode.trim(); |
| | | |
| | | if (!this.trayBarcode) { |
| | | this.error = '请å
è¾å
¥æçæ¡ç '; |
| | | this.focusTrayInput(); |
| | | return; |
| | | } |
| | | |
| | | if (!currentBarcode) { |
| | | this.error = '请è¾å
¥ææ«æç©ææ¡ç '; |
| | | return; |
| | | } |
| | | |
| | | this.focusBarcodeInput(); |
| | | this.error = ''; |
| | | this.loading = true; |
| | | |
| | | try { |
| | | // è°ç¨APIæ¥è¯¢ç©æä¿¡æ¯ |
| | | const materialData = await this.fetchMaterialData(currentBarcode); |
| | | if (!materialData || materialData.length === 0) { |
| | | |
| | | |
| | | return; |
| | | } |
| | | // æ£æ¥æ¯å¦å·²åå¨ç¸åç©æç¼ç çè®°å½ |
| | | const exists = this.materials.some(item => |
| | | item.barcode === this.trayBarcode |
| | | ); |
| | | console.log('API:', materialData) |
| | | if (exists) { |
| | | this.$message({ |
| | | message: 'æçæ¡ç å·²æ¸
é¤', |
| | | type: 'info', |
| | | message: '该æ¡ç å·²åå¨å½åæççå表ä¸', |
| | | type: 'warning', |
| | | duration: 2000 |
| | | }); |
| | | }, |
| | | |
| | | // æ¸
空æçè¾å
¥ |
| | | handleTrayClear() { |
| | | this.error = ''; |
| | | }, |
| | | |
| | | // æ¸
空è¾å
¥ |
| | | handleClear() { |
| | | this.error = ''; |
| | | this.scanCode = ''; |
| | | this.isManualInput = false; |
| | | this.isScanning = false; |
| | | }, |
| | | |
| | | // å¤çç©ææ¡ç æäº¤ |
| | | async handleBarcodeSubmit() { |
| | | if (!await this.validateForm()) return; |
| | | const currentBarcode = this.barcode.trim(); |
| | | |
| | | if (!this.trayBarcode) { |
| | | this.error = '请å
è¾å
¥æçæ¡ç '; |
| | | this.focusTrayInput(); |
| | | return; |
| | | } |
| | | |
| | | if (!currentBarcode) { |
| | | this.error = '请è¾å
¥ææ«æç©ææ¡ç '; |
| | | return; |
| | | } |
| | | } else { |
| | | |
| | | this.error = ''; |
| | | this.loading = true; |
| | | materialData.forEach(item => { |
| | | |
| | | try { |
| | | // è°ç¨APIæ¥è¯¢ç©æä¿¡æ¯ |
| | | const materialData = await this.fetchMaterialData(currentBarcode); |
| | | if (!materialData || materialData.length === 0) { |
| | | |
| | | |
| | | return; |
| | | } |
| | | // æ£æ¥æ¯å¦å·²åå¨ç¸åç©æç¼ç çè®°å½ |
| | | const exists = this.materials.some(item => |
| | | item.barcode === this.trayBarcode |
| | | ); |
| | | console.log('API:',materialData) |
| | | if (exists) { |
| | | this.$message({ |
| | | message: '该æ¡ç å·²åå¨å½åæççå表ä¸', |
| | | type: 'warning', |
| | | duration: 2000 |
| | | }); |
| | | } else { |
| | | |
| | | materialData.forEach(item => { |
| | | |
| | | // 妿ä¸åå¨ï¼æ·»å æ°ç©æ |
| | | this.materials.push({ |
| | | ...item, |
| | | trayCode: this.trayBarcode, |
| | | locationType: this.form.locationType, |
| | | locationDesc: this.currentLocationDesc, |
| | | scanTime: this.formatTime(new Date()) |
| | | // 妿ä¸åå¨ï¼æ·»å æ°ç©æ |
| | | this.materials.push({ |
| | | ...item, |
| | | trayCode: this.trayBarcode, |
| | | locationType: this.form.locationType, |
| | | locationDesc: this.currentLocationDesc, |
| | | scanTime: this.formatTime(new Date()) |
| | | }); |
| | | }); |
| | | }); |
| | | |
| | | |
| | | |
| | | |
| | | this.$message({ |
| | | message: `æåæ·»å æ¡ç : ${currentBarcode}`, |
| | | type: 'success', |
| | | duration: 2000 |
| | | }); |
| | | |
| | | this.fetchStockStatistics(); |
| | | // æ¸
ç©ºç©æè¾å
¥æ¡å¹¶ä¿æèç¦ |
| | | this.barcode = ''; |
| | | this.scanCode = ''; // æ¸
空æ«ç ç¼å |
| | | this.isScanning = false; |
| | | |
| | | setTimeout(() => { |
| | | this.focusBarcodeInput(); |
| | | }, 100); |
| | | } |
| | | } catch (err) { |
| | | this.error = err.message || 'æ¥è¯¢æ¡ç ä¿¡æ¯å¤±è´¥ï¼è¯·éè¯'; |
| | | } finally { |
| | | this.loading = false; |
| | | } |
| | | }, |
| | | |
| | | // APIè¯·æ± - æ¿æ¢ä¸ºå®é
çAPIè°ç¨ |
| | | async fetchMaterialData(barcode) { |
| | | try { |
| | | const response = await http.post('/api/InboundOrder/BarcodeMaterielGroup', |
| | | { |
| | | |
| | | this.$message({ |
| | | message: `æåæ·»å æ¡ç : ${currentBarcode}`, |
| | | type: 'success', |
| | | duration: 2000 |
| | | }); |
| | | |
| | | this.fetchStockStatistics(); |
| | | // æ¸
ç©ºç©æè¾å
¥æ¡å¹¶ä¿æèç¦ |
| | | this.barcode = ''; |
| | | this.scanCode = ''; // æ¸
空æ«ç ç¼å |
| | | this.isScanning = false; |
| | | |
| | | setTimeout(() => { |
| | | this.focusBarcodeInput(); |
| | | }, 100); |
| | | } |
| | | } catch (err) { |
| | | this.error = err.message || 'æ¥è¯¢æ¡ç ä¿¡æ¯å¤±è´¥ï¼è¯·éè¯'; |
| | | this.focusBarcodeInput(); |
| | | setTimeout(() => { |
| | | // éä¸è¾å
¥æ¡å
çé误å
容ï¼ç¡®ä¿focus宿忧è¡ï¼ |
| | | const inputEl = this.$refs.barcodeInput?.$el?.querySelector('input'); |
| | | if (inputEl) inputEl.select(); |
| | | }, 100); |
| | | } finally { |
| | | this.loading = false; |
| | | } |
| | | }, |
| | | |
| | | // APIè¯·æ± - æ¿æ¢ä¸ºå®é
çAPIè°ç¨ |
| | | async fetchMaterialData(barcode) { |
| | | try { |
| | | const response = await http.post('/api/InboundOrder/BarcodeMaterielGroup', |
| | | { |
| | | palletCode: this.trayBarcode, |
| | | orderNo: this.docNo, |
| | | barcodes: barcode, |
| | | locationTypeDesc: this.currentLocationDesc, |
| | | locationTypeDesc: this.currentLocationDesc, |
| | | locationType: this.form.locationType, // æ·»å ä»åºåºåä¿¡æ¯ |
| | | warehouseType:this.form.warehouseType |
| | | } |
| | | warehouseType: this.form.warehouseType |
| | | } |
| | | ); |
| | | |
| | | |
| | | |
| | | |
| | | let materialData; |
| | | |
| | | |
| | | if (typeof response.data === 'string') { |
| | | |
| | | |
| | | try { |
| | | materialData = JSON.parse(response.data); |
| | | } catch (e) { |
| | | |
| | | |
| | | } |
| | | } else { |
| | | // 妿è¿åçæ¯JSON对象ï¼ç´æ¥ä½¿ç¨ |
| | | materialData = response.data; |
| | | } |
| | | if(!response.status){ |
| | | this.error = response.message || 'æ¥è¯¢æ¡ç ä¿¡æ¯å¤±è´¥ï¼è¯·éè¯'; |
| | | } |
| | | if (!response.status) { |
| | | this.error = response.message || 'æ¥è¯¢æ¡ç ä¿¡æ¯å¤±è´¥ï¼è¯·éè¯'; |
| | | } |
| | | |
| | | return materialData; |
| | | |
| | | return materialData; |
| | | |
| | | } catch (error) { |
| | | console.error('APIè°ç¨å¤±è´¥:', error); |
| | | |
| | | |
| | | } |
| | | }, |
| | | |
| | | // å¤çæ«ç æªè¾å
¥ |
| | | handleKeyPress(event) { |
| | | // å¦ææ¯æå¨è¾å
¥æ¨¡å¼ï¼ä¸å¤çæ«ç æªé»è¾ |
| | | if (this.isManualInput) { |
| | | return; |
| | | } |
| | | |
| | | const key = event.key; |
| | | const currentTime = new Date().getTime(); |
| | | |
| | | // 忽ç¥ç´æ¥æä¸çå车é®ï¼ç±handleBarcodeSubmitå¤çï¼ |
| | | if (key === 'Enter') { |
| | | if (this.scanCode.length > 0) { |
| | | // 黿¢é»è®¤å车è¡ä¸ºï¼é¿å
表åæäº¤ |
| | | event.preventDefault(); |
| | | |
| | | // æ«ç 宿ï¼èªå¨è§¦åæ¥è¯¢ |
| | | this.isScanning = false; |
| | | |
| | | // æ ¹æ®å½åæ«ç ç®æ 设置ç¸åºçè¾å
¥æ¡å¼ |
| | | if (this.scanTarget === 'tray') { |
| | | this.trayBarcode = this.scanCode; |
| | | this.handleTraySubmit(); |
| | | } else if (this.scanTarget === 'material') { |
| | | this.barcode = this.scanCode; |
| | | this.handleBarcodeSubmit(); |
| | | } |
| | | } |
| | | this.scanCode = ''; |
| | | this.lastKeyTime = null; |
| | | return; |
| | | } |
| | | |
| | | // æå»ºæ«ç å
容ï¼å¿«éè¿ç»è¾å
¥è§ä¸ºæ«ç ï¼ |
| | | if (this.lastKeyTime && currentTime - this.lastKeyTime < 50) { |
| | | this.scanCode += key; |
| | | this.isScanning = true; |
| | | } else { |
| | | this.scanCode = key; |
| | | this.isScanning = true; |
| | | } |
| | | |
| | | // 设置计æ¶å¨ï¼å¦æä¸æ®µæ¶é´å
没æè¾å
¥ï¼åéç½®æ«æç¶æ |
| | | if (this.scanTimer) { |
| | | clearTimeout(this.scanTimer); |
| | | } |
| | | this.scanTimer = setTimeout(() => { |
| | | this.isScanning = false; |
| | | }, 100); |
| | | |
| | | this.lastKeyTime = currentTime; |
| | | }, |
| | | |
| | | // å é¤ç©æ |
| | | removeMaterial(index) { |
| | | this.$confirm('ç¡®å®è¦å é¤è¿æ¡ç©æè®°å½å?', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | this.materials.splice(index, 1); |
| | | this.$message({ |
| | | type: 'success', |
| | | message: 'å 餿å!' |
| | | }); |
| | | this.fetchStockStatistics(); |
| | | |
| | | }).catch(() => { |
| | | // åæ¶å é¤ |
| | | }); |
| | | }, |
| | | |
| | | // æ¸
空ææç©æ |
| | | clearAllMaterials() { |
| | | if (this.materials.length === 0) return; |
| | | |
| | | this.$confirm('ç¡®å®è¦æ¸
空ææç©æè®°å½å?', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | this.materials = []; |
| | | this.$message({ |
| | | type: 'success', |
| | | message: 'å·²æ¸
空ææè®°å½!' |
| | | }); |
| | | }).catch(() => { |
| | | // åæ¶æ¸
空 |
| | | }); |
| | | }, |
| | | |
| | | // æ ¼å¼åæ¶é´ |
| | | formatTime(date) { |
| | | const year = date.getFullYear(); |
| | | const month = String(date.getMonth() + 1).padStart(2, '0'); |
| | | const day = String(date.getDate()).padStart(2, '0'); |
| | | const hours = String(date.getHours()).padStart(2, '0'); |
| | | const minutes = String(date.getMinutes()).padStart(2, '0'); |
| | | const seconds = String(date.getSeconds()).padStart(2, '0'); |
| | | |
| | | return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; |
| | | } |
| | | |
| | | } |
| | | }, |
| | | |
| | | // å¤çæ«ç æªè¾å
¥ |
| | | handleKeyPress(event) { |
| | | // å¦ææ¯æå¨è¾å
¥æ¨¡å¼ï¼ä¸å¤çæ«ç æªé»è¾ |
| | | if (this.isManualInput) { |
| | | return; |
| | | } |
| | | |
| | | const key = event.key; |
| | | const currentTime = new Date().getTime(); |
| | | |
| | | // 忽ç¥ç´æ¥æä¸çå车é®ï¼ç±handleBarcodeSubmitå¤çï¼ |
| | | if (key === 'Enter') { |
| | | if (this.scanCode.length > 0) { |
| | | // 黿¢é»è®¤å车è¡ä¸ºï¼é¿å
表åæäº¤ |
| | | event.preventDefault(); |
| | | |
| | | // æ«ç 宿ï¼èªå¨è§¦åæ¥è¯¢ |
| | | this.isScanning = false; |
| | | |
| | | // æ ¹æ®å½åæ«ç ç®æ 设置ç¸åºçè¾å
¥æ¡å¼ |
| | | if (this.scanTarget === 'tray') { |
| | | this.trayBarcode = this.scanCode; |
| | | this.handleTraySubmit(); |
| | | } else if (this.scanTarget === 'material') { |
| | | this.barcode = this.scanCode; |
| | | this.handleBarcodeSubmit(); |
| | | } |
| | | } |
| | | this.scanCode = ''; |
| | | this.lastKeyTime = null; |
| | | return; |
| | | } |
| | | |
| | | // æå»ºæ«ç å
容ï¼å¿«éè¿ç»è¾å
¥è§ä¸ºæ«ç ï¼ |
| | | if (this.lastKeyTime && currentTime - this.lastKeyTime < 50) { |
| | | this.scanCode += key; |
| | | this.isScanning = true; |
| | | } else { |
| | | this.scanCode = key; |
| | | this.isScanning = true; |
| | | } |
| | | |
| | | // 设置计æ¶å¨ï¼å¦æä¸æ®µæ¶é´å
没æè¾å
¥ï¼åéç½®æ«æç¶æ |
| | | if (this.scanTimer) { |
| | | clearTimeout(this.scanTimer); |
| | | } |
| | | this.scanTimer = setTimeout(() => { |
| | | this.isScanning = false; |
| | | }, 100); |
| | | |
| | | this.lastKeyTime = currentTime; |
| | | }, |
| | | |
| | | // å é¤ç©æ |
| | | removeMaterial(index) { |
| | | this.$confirm('ç¡®å®è¦å é¤è¿æ¡ç©æè®°å½å?', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | this.materials.splice(index, 1); |
| | | this.$message({ |
| | | type: 'success', |
| | | message: 'å 餿å!' |
| | | }); |
| | | this.fetchStockStatistics(); |
| | | |
| | | }).catch(() => { |
| | | // åæ¶å é¤ |
| | | }); |
| | | }, |
| | | |
| | | // æ¸
空ææç©æ |
| | | clearAllMaterials() { |
| | | if (this.materials.length === 0) return; |
| | | |
| | | this.$confirm('ç¡®å®è¦æ¸
空ææç©æè®°å½å?', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | this.materials = []; |
| | | this.$message({ |
| | | type: 'success', |
| | | message: 'å·²æ¸
空ææè®°å½!' |
| | | }); |
| | | }).catch(() => { |
| | | // åæ¶æ¸
空 |
| | | }); |
| | | }, |
| | | |
| | | // æ ¼å¼åæ¶é´ |
| | | formatTime(date) { |
| | | const year = date.getFullYear(); |
| | | const month = String(date.getMonth() + 1).padStart(2, '0'); |
| | | const day = String(date.getDate()).padStart(2, '0'); |
| | | const hours = String(date.getHours()).padStart(2, '0'); |
| | | const minutes = String(date.getMinutes()).padStart(2, '0'); |
| | | const seconds = String(date.getSeconds()).padStart(2, '0'); |
| | | |
| | | return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .barcode-scanner-container { |
| | | max-width: 1200px; |
| | | margin: 0 auto; |
| | | padding: 10px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | height: 100%; |
| | | gap: 8px; |
| | | } |
| | | |
| | | /* ç´§åå¸å±æ ·å¼ */ |
| | | .compact { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .compact-form { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .compact-item { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .compact-card { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .compact-card >>> .el-card__body { |
| | | padding: 12px; |
| | | } |
| | | |
| | | .compact-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 0 !important; |
| | | } |
| | | |
| | | .compact-header >>> .el-card__header { |
| | | padding: 8px 12px; |
| | | } |
| | | |
| | | .compact-input { |
| | | margin: 8px 0; |
| | | } |
| | | |
| | | .compact-tips { |
| | | margin-top: 8px; |
| | | font-size: 11px; |
| | | } |
| | | |
| | | /* ä»åºåºåéæ© - ç´§å */ |
| | | .location-section.compact { |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .location-section.compact >>> .el-form-item { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | /* æçä¿¡æ¯ - ç´§å */ |
| | | .tray-info.compact { |
| | | padding: 6px 10px; |
| | | margin-bottom: 8px; |
| | | font-size: 13px; |
| | | } |
| | | |
| | | /* æ«ç åºå - ç´§å */ |
| | | .input-section.compact { |
| | | margin-bottom: 8px; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | /* ç©æå表 - åºå®é«åº¦å¸¦æ»å¨ */ |
| | | .material-list.compact { |
| | | flex: 1; |
| | | min-height: 0; /* éè¦ï¼å
许flexå项æ¶ç¼© */ |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .material-list.compact >>> .el-card { |
| | | display: flex; |
| | | flex-direction: column; |
| | | height: 100%; |
| | | } |
| | | |
| | | .material-list.compact >>> .el-card__body { |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | padding: 0; |
| | | min-height: 0; |
| | | } |
| | | |
| | | .table-container { |
| | | flex: 1; |
| | | min-height: 0; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .material-list.compact >>> .el-table { |
| | | flex: 1; |
| | | } |
| | | |
| | | .material-list.compact >>> .el-table__body-wrapper { |
| | | overflow-y: auto; |
| | | } |
| | | |
| | | /* ç´§åçç©ºç¶æ */ |
| | | .empty-state.compact { |
| | | padding: 20px 0; |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | align-items: center; |
| | | } |
| | | |
| | | .empty-state.compact i { |
| | | font-size: 36px; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .empty-state.compact p { |
| | | font-size: 13px; |
| | | } |
| | | |
| | | /* å
¶ä»åææ ·å¼è°æ´ */ |
| | | .page-title { |
| | | text-align: center; |
| | | margin-bottom: 15px; |
| | | } |
| | | |
| | | .scan-status { |
| | | font-size: 12px; |
| | | color: #67C23A; |
| | | } |
| | | |
| | | .scan-indicator { |
| | | display: inline-block; |
| | | width: 8px; |
| | | height: 8px; |
| | | border-radius: 50%; |
| | | background-color: #67C23A; |
| | | margin-right: 5px; |
| | | animation: pulse 1.5s infinite; |
| | | } |
| | | |
| | | @keyframes pulse { |
| | | 0% { opacity: 1; } |
| | | 50% { opacity: 0.4; } |
| | | 100% { opacity: 1; } |
| | | } |
| | | |
| | | .input-wrapper { |
| | | position: relative; |
| | | } |
| | | |
| | | .input-tips { |
| | | margin-top: 6px; |
| | | color: #909399; |
| | | } |
| | | |
| | | .warning-text { |
| | | color: #E6A23C; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .loading.compact { |
| | | text-align: center; |
| | | margin: 10px 0; |
| | | padding: 5px; |
| | | } |
| | | |
| | | .loading.compact p { |
| | | margin-top: 5px; |
| | | color: #409EFF; |
| | | font-size: 12px; |
| | | } |
| | | |
| | | .error-message.compact { |
| | | margin: 5px 0; |
| | | } |
| | | |
| | | .error-message.compact >>> .el-alert { |
| | | padding: 6px 12px; |
| | | } |
| | | |
| | | .list-actions { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 4px; |
| | | } |
| | | |
| | | .list-actions >>> .el-tag { |
| | | height: 24px; |
| | | line-height: 22px; |
| | | padding: 0 6px; |
| | | } |
| | | |
| | | .clear-all-btn { |
| | | margin-left: 8px; |
| | | } |
| | | |
| | | .material-code { |
| | | font-family: 'Courier New', monospace; |
| | | font-weight: bold; |
| | | color: #409EFF; |
| | | } |
| | | |
| | | .location-info { |
| | | color: #606266; |
| | | font-weight: normal; |
| | | } |
| | | |
| | | .debug-info { |
| | | background: #f5f7fa; |
| | | padding: 8px; |
| | | border-radius: 4px; |
| | | margin-top: 8px; |
| | | font-size: 11px; |
| | | color: #909399; |
| | | } |
| | | |
| | | .small-button { |
| | | padding: 6px 8px; |
| | | font-size: 11px; |
| | | } |
| | | .barcode-scanner-container { |
| | | max-width: 1200px; |
| | | margin: 0 auto; |
| | | padding: 10px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | height: 100%; |
| | | gap: 8px; |
| | | } |
| | | |
| | | /* è¾å
¥æ¡ç»æ ·å¼è°æ´ */ |
| | | .custom-input-group { |
| | | display: flex; |
| | | align-items: center; |
| | | width: 100%; |
| | | margin: 8px 0; |
| | | border: 1px solid #DCDFE6; |
| | | border-radius: 4px; |
| | | overflow: hidden; |
| | | background: #fff; |
| | | } |
| | | /* ç´§åå¸å±æ ·å¼ */ |
| | | .compact { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .input-label { |
| | | padding: 0 12px; |
| | | background: #F5F7FA; |
| | | border-right: 1px solid #DCDFE6; |
| | | color: #606266; |
| | | font-size: 13px; |
| | | white-space: nowrap; |
| | | height: 36px; |
| | | line-height: 36px; |
| | | flex-shrink: 0; |
| | | min-width: 70px; |
| | | text-align: center; |
| | | } |
| | | .compact-form { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .input-container { |
| | | display: flex; |
| | | flex: 1; |
| | | align-items: center; |
| | | } |
| | | .compact-item { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .custom-input { |
| | | flex: 1; |
| | | } |
| | | .compact-card { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .custom-input >>> .el-input__inner { |
| | | border: none; |
| | | border-radius: 0; |
| | | height: 36px; |
| | | line-height: 36px; |
| | | font-size: 13px; |
| | | } |
| | | |
| | | /* ååºå¼è°æ´ */ |
| | | @media (max-width: 768px) { |
| | | .barcode-scanner-container { |
| | | padding: 5px; |
| | | } |
| | | |
| | | .custom-input-group { |
| | | flex-direction: column; |
| | | border: none; |
| | | } |
| | | |
| | | .input-label { |
| | | width: 100%; |
| | | border-right: none; |
| | | border-bottom: 1px solid #DCDFE6; |
| | | margin-bottom: 5px; |
| | | } |
| | | |
| | | .input-container { |
| | | width: 100%; |
| | | border: 1px solid #DCDFE6; |
| | | border-radius: 4px; |
| | | } |
| | | } |
| | | .compact-card>>>.el-card__body { |
| | | padding: 12px; |
| | | } |
| | | |
| | | .compact-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 0 !important; |
| | | } |
| | | |
| | | .compact-header>>>.el-card__header { |
| | | padding: 8px 12px; |
| | | } |
| | | |
| | | .compact-input { |
| | | margin: 8px 0; |
| | | } |
| | | |
| | | .compact-tips { |
| | | margin-top: 8px; |
| | | font-size: 11px; |
| | | } |
| | | |
| | | /* ä»åºåºåéæ© - ç´§å */ |
| | | .location-section.compact { |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .location-section.compact>>>.el-form-item { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | /* æçä¿¡æ¯ - ç´§å */ |
| | | .tray-info.compact { |
| | | padding: 6px 10px; |
| | | margin-bottom: 8px; |
| | | font-size: 13px; |
| | | } |
| | | |
| | | /* æ«ç åºå - ç´§å */ |
| | | .input-section.compact { |
| | | margin-bottom: 8px; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | /* ç©æå表 - åºå®é«åº¦å¸¦æ»å¨ */ |
| | | .material-list.compact { |
| | | flex: 1; |
| | | min-height: 0; |
| | | /* éè¦ï¼å
许flexå项æ¶ç¼© */ |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .material-list.compact>>>.el-card { |
| | | display: flex; |
| | | flex-direction: column; |
| | | height: 100%; |
| | | } |
| | | |
| | | .material-list.compact>>>.el-card__body { |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | padding: 0; |
| | | min-height: 0; |
| | | } |
| | | |
| | | .table-container { |
| | | flex: 1; |
| | | min-height: 0; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .material-list.compact>>>.el-table { |
| | | flex: 1; |
| | | } |
| | | |
| | | .material-list.compact>>>.el-table__body-wrapper { |
| | | overflow-y: auto; |
| | | } |
| | | |
| | | /* ç´§åçç©ºç¶æ */ |
| | | .empty-state.compact { |
| | | padding: 20px 0; |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | align-items: center; |
| | | } |
| | | |
| | | .empty-state.compact i { |
| | | font-size: 36px; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .empty-state.compact p { |
| | | font-size: 13px; |
| | | } |
| | | |
| | | /* å
¶ä»åææ ·å¼è°æ´ */ |
| | | .page-title { |
| | | text-align: center; |
| | | margin-bottom: 15px; |
| | | } |
| | | |
| | | .scan-status { |
| | | font-size: 12px; |
| | | color: #67C23A; |
| | | } |
| | | |
| | | .scan-indicator { |
| | | display: inline-block; |
| | | width: 8px; |
| | | height: 8px; |
| | | border-radius: 50%; |
| | | background-color: #67C23A; |
| | | margin-right: 5px; |
| | | animation: pulse 1.5s infinite; |
| | | } |
| | | |
| | | @keyframes pulse { |
| | | 0% { |
| | | opacity: 1; |
| | | } |
| | | |
| | | 50% { |
| | | opacity: 0.4; |
| | | } |
| | | |
| | | 100% { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | |
| | | .input-wrapper { |
| | | position: relative; |
| | | } |
| | | |
| | | .input-tips { |
| | | margin-top: 6px; |
| | | color: #909399; |
| | | } |
| | | |
| | | .warning-text { |
| | | color: #E6A23C; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .loading.compact { |
| | | text-align: center; |
| | | margin: 10px 0; |
| | | padding: 5px; |
| | | } |
| | | |
| | | .loading.compact p { |
| | | margin-top: 5px; |
| | | color: #409EFF; |
| | | font-size: 12px; |
| | | } |
| | | |
| | | .error-message.compact { |
| | | margin: 5px 0; |
| | | } |
| | | |
| | | .error-message.compact>>>.el-alert { |
| | | padding: 6px 12px; |
| | | } |
| | | |
| | | .list-actions { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 4px; |
| | | } |
| | | |
| | | .list-actions>>>.el-tag { |
| | | height: 24px; |
| | | line-height: 22px; |
| | | padding: 0 6px; |
| | | } |
| | | |
| | | .clear-all-btn { |
| | | margin-left: 8px; |
| | | } |
| | | |
| | | .material-code { |
| | | font-family: 'Courier New', monospace; |
| | | font-weight: bold; |
| | | color: #409EFF; |
| | | } |
| | | |
| | | .location-info { |
| | | color: #606266; |
| | | font-weight: normal; |
| | | } |
| | | |
| | | .debug-info { |
| | | background: #f5f7fa; |
| | | padding: 8px; |
| | | border-radius: 4px; |
| | | margin-top: 8px; |
| | | font-size: 11px; |
| | | color: #909399; |
| | | } |
| | | |
| | | .small-button { |
| | | padding: 6px 8px; |
| | | font-size: 11px; |
| | | } |
| | | |
| | | /* è¾å
¥æ¡ç»æ ·å¼è°æ´ */ |
| | | .custom-input-group { |
| | | display: flex; |
| | | align-items: center; |
| | | width: 100%; |
| | | margin: 8px 0; |
| | | border: 1px solid #DCDFE6; |
| | | border-radius: 4px; |
| | | overflow: hidden; |
| | | background: #fff; |
| | | } |
| | | |
| | | .input-label { |
| | | padding: 0 12px; |
| | | background: #F5F7FA; |
| | | border-right: 1px solid #DCDFE6; |
| | | color: #606266; |
| | | font-size: 13px; |
| | | white-space: nowrap; |
| | | height: 36px; |
| | | line-height: 36px; |
| | | flex-shrink: 0; |
| | | min-width: 70px; |
| | | text-align: center; |
| | | } |
| | | |
| | | .input-container { |
| | | display: flex; |
| | | flex: 1; |
| | | align-items: center; |
| | | } |
| | | |
| | | .custom-input { |
| | | flex: 1; |
| | | } |
| | | |
| | | .custom-input>>>.el-input__inner { |
| | | border: none; |
| | | border-radius: 0; |
| | | height: 36px; |
| | | line-height: 36px; |
| | | font-size: 13px; |
| | | } |
| | | |
| | | /* ååºå¼è°æ´ */ |
| | | @media (max-width: 768px) { |
| | | .barcode-scanner-container { |
| | | padding: 5px; |
| | | } |
| | | |
| | | .custom-input-group { |
| | | flex-direction: column; |
| | | border: none; |
| | | } |
| | | |
| | | .input-label { |
| | | width: 100%; |
| | | border-right: none; |
| | | border-bottom: 1px solid #DCDFE6; |
| | | margin-bottom: 5px; |
| | | } |
| | | |
| | | .input-container { |
| | | width: 100%; |
| | | border: 1px solid #DCDFE6; |
| | | border-radius: 4px; |
| | | } |
| | | } |
| | | </style> |
| | |
| | | :lazy="true" |
| | | width="75%" |
| | | :padding="15" |
| | | title="åºåºè¯¦æ
" |
| | | title="è°æ¨åºåºè¯¦æ
" |
| | | > |
| | | <div class="box-head"> |
| | | <el-alert :closable="false" style="width: 100%"> |
| | |
| | | "æ¥è¯¢ä¸" |
| | | ) |
| | | .then((x) => { |
| | | |
| | | var label=[ |
| | | { label: 'å·²åé
', value: 0 }, |
| | | { label: 'åºåºä¸', value: 1 }, |
| | | { label: 'åºåºå®æ', value: 2 }, |
| | | { label: 'æ£é宿', value: 3 }, |
| | | { label: 'é¨åæ£é', value: 2 }, |
| | | { label: 'å·²æ£é', value: 3 }, |
| | | { label: 'å·²åºåº', value: 4 }, |
| | | { label: 'åºåºå®æ', value: 5 }, |
| | | { label: 'æ£é宿', value: 6 }, |
| | | { label: 'ååºä¸', value: 7 }, |
| | | { label: 'å·²ååº', value: 8 }, |
| | | { label: 'æ¤é', value: 99 } |
| | | ] |
| | | |
| | | this.tableData=x.map((i) => ({ |
| | | ...i, |
| | | status:label.find((j) => j.value === i.status).label |
| | |
| | | data() { |
| | | return { |
| | | row: null, |
| | | showDetialBox: false, |
| | | showDetialBox: false, |
| | | tableData: [], |
| | | tableColumns: [ |
| | | { prop: "materielCode", title: "ç©æç¼å·", type: "string", width: 150 }, |
| | | { prop: "materielName", title: "ç©æåç§°", type: "string", width: 150 }, |
| | | { prop: "barcode", title: "ç©ææ¡ç ", type: "string", width: 150 }, |
| | | { prop: "palletCode", title: "æçç¼å·", type: "string", width: 150 }, |
| | | { prop: "locationCode", title: "è´§ä½ç¼å·", type: "string", width: 180 }, |
| | | { prop: "useableQuantity", title: "å¯ç¨æ°é", type: "string" }, |
| | |
| | | if (!valid) return; |
| | | |
| | | |
| | | // æé 请æ±åæ° |
| | | const keys = this.selection.map((item) => item.id); |
| | | const requestParams = { |
| | | taskIds: keys, |
| | | outboundPlatform: this.outboundForm.selectedPlatform, |
| | | }; |
| | | console.log(this.selection) |
| | | // è°ç¨åºåºæ¥å£ |
| | | this.http |
| | | .post("api/Task/GenerateOutboundTasks", requestParams, "æ°æ®å¤çä¸") |
| | | .then((x) => { |
| | | if (!x.status) return ElMessage.error(x.message); |
| | | |
| | | ElMessage.success("æä½æå"); |
| | | this.showOutboundDialog = false; |
| | | this.showDetialBox = false; |
| | | this.$emit("parentCall", ($vue) => { |
| | | $vue.getData(); |
| | | }); |
| | | }) |
| | | .catch((error) => { |
| | | console.error("åºåºè¯·æ±å¤±è´¥:", error); |
| | | ElMessage.error("请æ±å¤±è´¥ï¼è¯·ç¨åéè¯"); |
| | | if (this.selection.length <= 0) { |
| | | return this.$message.error("请å¾é"); |
| | | } |
| | | let url = this.pkcx |
| | | ? "api/Task/GenerateOutboundTask?orderDetailId=" |
| | | : "api/Task/GenerateOutboundTask?orderDetailId="; |
| | | this.http |
| | | .post(url + this.row.id, this.selection, "æ°æ®å¤çä¸") |
| | | .then((x) => { |
| | | if (!x.status) return this.$message.error(x.message); |
| | | this.$message.success("æä½æå"); |
| | | this.showDetialBox = false; |
| | | this.$emit("parentCall", ($vue) => { |
| | | $vue.getData(); |
| | | }); |
| | | }); |
| | | |
| | | }); |
| | | }, |
| | | |
| | |
| | | @click="handleOpenPicking" |
| | | >æ£é</el-link> |
| | | |
| | | <el-link |
| | | <!-- <el-link |
| | | type="primary" |
| | | size="small" |
| | | style="float: right; height: 20px; margin-right: 10px" |
| | | @click="outbound" |
| | | >ç´æ¥åºåº</el-link |
| | | > |
| | | > --> |
| | | <el-link |
| | | type="primary" |
| | | size="small" |
| | |
| | | // åèµ·æ¤éç»çè¯·æ± |
| | | try { |
| | | //console.log('åèµ·æ¤éç»ç请æ±ï¼æçå·ï¼', formData.palletCode.trim()); |
| | | const response = await http.post('/api/InboundOrder/CancelPalletGroup', { |
| | | palletCode: formData.palletCode.trim() |
| | | }); |
| | | const response = await http.post('/api/InboundOrder/UndoPalletGroup?palletCode='+formData.palletCode.trim()); |
| | | |
| | | |
| | | const { status, message, data } = response; |
| | | if (status) { |
| | |
| | | searchBefore(param) { |
| | | //ç颿¥è¯¢å,å¯ä»¥ç»param.wheresæ·»å æ¥è¯¢åæ° |
| | | //è¿åfalseï¼åä¸ä¼æ§è¡æ¥è¯¢ |
| | | this.searchFormFields.orderType=[0] |
| | | // this.searchFormFields.orderType=[0] |
| | | let wheres = [{ |
| | | 'name': 'orderType', |
| | | 'value': '0', |
| | | 'displayType': 'text'}]; |
| | | |
| | | |
| | | param.wheres.push(...wheres); |
| | | return true; |
| | | }, |
| | | searchAfter(result) { |
| | |
| | | width: 90, |
| | | }, |
| | | { |
| | | prop: "currentBarcode", |
| | | title: "æ¡ç ", |
| | | type: "string", |
| | | width: 90, |
| | | }, |
| | | { |
| | | prop: "batchNo", |
| | | title: "æ¹æ¬¡å·", |
| | | type: "string", |
| | |
| | | .then((x) => { |
| | | |
| | | var label=[ |
| | | { label: 'å·²åé
', value: 0 }, |
| | | { label: 'å·²åé
', value: 0 }, |
| | | { label: 'åºåºä¸', value: 1 }, |
| | | { label: 'åºåºå®æ', value: 2 }, |
| | | { label: 'æ£é宿', value: 3 }, |
| | | { label: 'é¨åæ£é', value: 2 }, |
| | | { label: 'å·²æ£é', value: 3 }, |
| | | { label: 'å·²åºåº', value: 4 }, |
| | | { label: 'åºåºå®æ', value: 5 }, |
| | | { label: 'æ£é宿', value: 6 }, |
| | | { label: 'ååºä¸', value: 7 }, |
| | | { label: 'å·²ååº', value: 8 }, |
| | | { label: 'æ¤é', value: 99 } |
| | | ] |
| | | ]; |
| | | this.tableData=x.map((i) => ({ |
| | | ...i, |
| | | status:label.find((j) => j.value === i.status).label |
| | |
| | | style="float: right; height: 20px" |
| | | @click="handleOpenPicking" |
| | | >æ£é</el-link> |
| | | |
| | | <el-link |
| | | type="primary" |
| | | size="small" |
| | | style="float: right; height: 20px; margin-right: 10px" |
| | | @click="handleOpenBatchPicking" |
| | | >åæ¹æ£é</el-link> |
| | | <el-link |
| | | type="primary" |
| | | size="small" |
| | | style="float: right; height: 20px; margin-right: 10px" |
| | | @click="outbound" |
| | | >ç´æ¥åºåº</el-link |
| | | > |
| | | <el-link |
| | | type="primary" |
| | | size="small" |
| | | style="float: right; height: 20px; margin-right: 10px" |
| | | @click="outboundbatch" |
| | | >åæ¹åºåº</el-link |
| | | > |
| | | <el-link |
| | | type="primary" |
| | |
| | | import SelectedStock from "./SelectedStock.vue"; |
| | | import NoStockOut from "./NoStockOut.vue"; |
| | | import { h,createVNode, render,reactive } from 'vue'; |
| | | import { ElDialog , ElForm, ElFormItem, ElSelect,ElOption, ElButton, ElMessage } from 'element-plus'; |
| | | import { ElDialog , ElForm, ElFormItem, ElSelect,ElOption, ElButton, ElInput, ElMessage } from 'element-plus'; |
| | | import { th } from 'element-plus/es/locale'; |
| | | |
| | | export default { |
| | | components: { VolBox, VolForm, StockSelect, SelectedStock,NoStockOut}, |
| | | data() { |
| | |
| | | title: "æå®åºå", |
| | | type: "icon", |
| | | width: 90, |
| | | hidden:true, |
| | | icon: "el-icon-s-grid", |
| | | }, |
| | | { |
| | |
| | | path: '/outbound/picking', |
| | | query: { orderId: this.row.id ,orderNo:this.row.orderNo} |
| | | }) |
| | | }, |
| | | handleOpenBatchPicking() { |
| | | this.$router.push({ |
| | | path: '/outbound/batchpicking', |
| | | query: { orderId: this.row.id ,orderNo:this.row.orderNo}}) |
| | | }, |
| | | outbound() { |
| | | if (this.selection.length === 0) { |
| | |
| | | vnode.appContext = this.$.appContext; |
| | | render(vnode, mountNode); |
| | | }, |
| | | outboundbatch() { |
| | | if (this.selection.length === 0) { |
| | | return this.$message.error("è¯·éæ©åæ®æç»"); |
| | | } |
| | | if (this.selection.length>1) { |
| | | return this.$message.error("åªè½éæ©ä¸æ¡åæ®æç»è¿è¡åæ¹åºåº"); |
| | | } |
| | | const platformOptions = [{label:'ç«å°2',value:'2-1'},{label:'ç«å°3',value:'3-1'}]; |
| | | const mountNode = document.createElement('div'); |
| | | document.body.appendChild(mountNode); |
| | | |
| | | // 2. è¡¨åæ°æ®ï¼é»è®¤éä¸ç«å°3ï¼æ°å¢å°æ°åæ®µï¼ |
| | | const formData = reactive({ |
| | | selectedPlatform: platformOptions[0].value, // é»è®¤ç»å®ãç«å°3ãçvalue |
| | | outboundDecimal: '' // æ°å¢ï¼å°æ°è¾å
¥æ¡å段 |
| | | }); |
| | | |
| | | // 3. 卿å建弹çªç»ä»¶ |
| | | const vnode = createVNode(ElDialog, { |
| | | title: 'åºåºæä½ - éæ©åºåºç«å°', |
| | | width: '500px', |
| | | modelValue: true, |
| | | appendToBody: true, |
| | | 'onUpdate:modelValue': (isVisible) => { |
| | | if (!isVisible) { |
| | | render(null, mountNode); |
| | | document.body.removeChild(mountNode); |
| | | } |
| | | }, |
| | | style: { |
| | | padding: '20px 0', |
| | | borderRadius: '8px' |
| | | } |
| | | }, { |
| | | default: () => h(ElForm, { |
| | | model: formData, |
| | | rules: { |
| | | selectedPlatform: [ |
| | | { required: true, message: 'è¯·éæ©åºåºç«å°', trigger: 'change' } |
| | | ], |
| | | // æ°å¢ï¼å°æ°å段éªè¯è§åï¼å¿
å¡« + ææå°æ°æ ¼å¼ï¼ |
| | | outboundDecimal: [ |
| | | { required: true, message: '请è¾å
¥å°æ°æ°å¼', trigger: 'blur' }, |
| | | { |
| | | validator: (rule, value, callback) => { |
| | | // éªè¯è§åï¼æ£æ°ãæ¯æå°æ°ç¹åæå¤2ä½ï¼å¯æ ¹æ®éæ±è°æ´å°æ°ä½æ°ï¼ |
| | | const decimalReg = /^(([1-9]\d*)|0)(\.\d{1,2})?$/; |
| | | if (value && !decimalReg.test(value)) { |
| | | callback(new Error('请è¾å
¥ææçå°æ°ï¼æ£æ°ï¼æå¤2ä½å°æ°ï¼')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | trigger: 'blur' |
| | | } |
| | | ] |
| | | }, |
| | | ref: 'outboundForm', |
| | | labelWidth: '100px', |
| | | style: { |
| | | padding: '0 30px' |
| | | } |
| | | }, [ |
| | | // åºåºç«å°éæ©é¡¹ï¼æ ¸å¿è¡¨åé¡¹ï¼ |
| | | h(ElFormItem, { |
| | | label: 'åºåºç«å°', |
| | | prop: 'selectedPlatform', |
| | | style: { |
| | | marginBottom: '24px' |
| | | } |
| | | }, [ |
| | | h(ElSelect, { |
| | | placeholder: 'è¯·éæ©åºåºç«å°ï¼3-12ï¼', |
| | | modelValue: formData.selectedPlatform, |
| | | 'onUpdate:modelValue': (val) => { |
| | | formData.selectedPlatform = val; |
| | | }, |
| | | style: { |
| | | width: '100%', |
| | | height: '40px', |
| | | borderRadius: '4px', |
| | | borderColor: '#dcdfe6' |
| | | } |
| | | }, platformOptions.map(platform => |
| | | h(ElOption, { label: platform.label, value: platform.value }) |
| | | )) |
| | | ]), |
| | | // æ°å¢ï¼å°æ°è¾å
¥æ¡è¡¨å项 |
| | | h(ElFormItem, { |
| | | label: 'åºåºæ°', // 坿 ¹æ®ä¸å¡éæ±ä¿®æ¹æ ç¾åï¼å¦âåºåºæ°éââééâçï¼ |
| | | prop: 'outboundDecimal', |
| | | style: { |
| | | marginBottom: '24px' |
| | | } |
| | | }, [ |
| | | h(ElInput, { |
| | | type: 'number', // æ°åç±»åï¼åçæ¯æå°æ°è¾å
¥ |
| | | placeholder: '请è¾å
¥å°æ°æ°å¼ï¼æå¤2ä½å°æ°ï¼', |
| | | modelValue: formData.outboundDecimal, |
| | | 'onUpdate:modelValue': (val) => { |
| | | formData.outboundDecimal = val; |
| | | }, |
| | | style: { |
| | | width: '100%', |
| | | height: '40px', |
| | | borderRadius: '4px', |
| | | borderColor: '#dcdfe6' |
| | | }, |
| | | step: '0.01', // æ¥é¿0.01ï¼ç¹å»ä¸ä¸ç®å¤´æ¶æ0.01å¢å |
| | | precision: 2, // éå¶æå¤è¾å
¥2ä½å°æ°ï¼Element Plus屿§ï¼ |
| | | min: 0.01, // å¯éï¼éå¶æå°å¼ä¸º0.01ï¼é¿å
è¾å
¥0æè´æ° |
| | | }) |
| | | ]), |
| | | // åºé¨æé®åº |
| | | h('div', { |
| | | style: { |
| | | textAlign: 'right', |
| | | marginTop: '8px', |
| | | paddingRight: '4px' |
| | | } |
| | | }, [ |
| | | h(ElButton, { |
| | | type: 'text', |
| | | onClick: () => { |
| | | render(null, mountNode); |
| | | document.body.removeChild(mountNode); |
| | | ElMessage.info('åæ¶åæ¹åºåºæä½'); |
| | | }, |
| | | style: { |
| | | marginRight: '8px', |
| | | color: '#606266' |
| | | } |
| | | }, 'åæ¶'), |
| | | h(ElButton, { |
| | | type: 'primary', |
| | | onClick: async () => { |
| | | const formRef = vnode.component.refs.outboundForm; |
| | | try { |
| | | // è¡¨åæ ¡éªï¼ä¼åæ¶æ ¡éªåºåºç«å°åå°æ°åæ®µï¼ |
| | | await formRef.validate(); |
| | | } catch (err) { |
| | | return; |
| | | } |
| | | console.log(this.selection); |
| | | // 4. æé 请æ±åæ°ï¼æ°å¢å°æ°åæ®µï¼ |
| | | const keys = this.selection.map((item) => item.id); |
| | | const requestParams = { |
| | | orderDetailId: keys[0], // åæ¹åºåºä»
æ¯æåæ¡æç» |
| | | outboundPlatform: formData.selectedPlatform, // åºåºç«å° |
| | | batchQuantity: formData.outboundDecimal // æ°å¢ï¼å°æ°åæ®µä¼ ç»å端 |
| | | }; |
| | | |
| | | // 5. è°ç¨åºåºæ¥å£ |
| | | this.http |
| | | .post("api/Task/GenerateOutboundBatchTasks", requestParams, "æ°æ®å¤çä¸") |
| | | .then((x) => { |
| | | if (!x.status) return ElMessage.error(x.message); |
| | | |
| | | ElMessage.success("æä½æå"); |
| | | this.showDetialBox = false; // å
³é详æ
æ¡ |
| | | this.$emit("parentCall", ($vue) => { |
| | | $vue.getData(); // éç¥ç¶ç»ä»¶å·æ° |
| | | }); |
| | | // å
³éå¼¹çª |
| | | render(null, mountNode); |
| | | document.body.removeChild(mountNode); |
| | | }) |
| | | .catch(() => { |
| | | ElMessage.error('请æ±å¤±è´¥ï¼è¯·ç¨åéè¯'); |
| | | }); |
| | | }, |
| | | style: { |
| | | borderRadius: '4px', |
| | | padding: '8px 20px' |
| | | } |
| | | }, 'ç¡®å®åæ¹åºåº') |
| | | ]) |
| | | ]) |
| | | }); |
| | | |
| | | // ç»å®appä¸ä¸æï¼ç¡®ä¿Elç»ä»¶æ£å¸¸å·¥ä½ |
| | | vnode.appContext = this.$.appContext; |
| | | render(vnode, mountNode); |
| | | }, |
| | | |
| | | |
| | | setCurrent(row) { |
| | | this.$refs.singleTable.setCurrentRow(row); |
| | | }, |
| | |
| | | }, |
| | | methods: { |
| | | generateQr(item) { |
| | | return `${item.materialCode}_${item.supplierCode}_${item.purchaseOrderNo}_${item.materialName}_${item.batch}_${item.batchNumber}_${item.factory}_${item.date}`; |
| | | return `${item.batchNumber}`; |
| | | }, |
| | | |
| | | open(rows) { |
| | |
| | | this.$refs.gridBody.open(row); |
| | | } |
| | | }); |
| | | |
| | | let TaskHandCompletedBtn = this.buttons.find(x => x.value == 'NoStockOut'); |
| | | if (TaskHandCompletedBtn) { |
| | | TaskHandCompletedBtn.onClick = function () { |
| | | this.$refs.gridHeader.open(); |
| | | } |
| | | } |
| | | |
| | | |
| | | }, |
| | | onInited() { |
| | | //æ¡æ¶åå§åé
ç½®å |
| | |
| | | searchBefore(param) { |
| | | //ç颿¥è¯¢å,å¯ä»¥ç»param.wheresæ·»å æ¥è¯¢åæ° |
| | | //è¿åfalseï¼åä¸ä¼æ§è¡æ¥è¯¢ |
| | | |
| | | let wheres = [{ |
| | | 'name': 'orderType', |
| | | 'value': '0', |
| | | 'displayType': 'text'}]; |
| | | |
| | | |
| | | param.wheres.push(...wheres); |
| | | return true; |
| | | |
| | | return true; |
| | | }, |
| | | searchAfter(result) { |
| | |
| | | name: 'PickingConfirm', |
| | | component: () => import('@/views/outbound/PickingConfirm.vue'), |
| | | meta: { title: 'æ£é确认', keepAlive: false } |
| | | },{ |
| | | }, |
| | | { |
| | | path: '/outbound/batchpicking', |
| | | name: 'BatchPickingConfirm', |
| | | component: () => import('@/views/outbound/BatchPickingConfirm.vue'), |
| | | meta: { title: 'æ£é确认', keepAlive: false } |
| | | }, |
| | | { |
| | | path: '/stockInfo', |
| | | name: 'stockInfo', |
| | | component: () => import('@/views/stock/stockInfo.vue') |
| | |
| | | component: () => import('@/views/inbound/allocateinboundOrder.vue') |
| | | |
| | | },{ |
| | | path:'allocateoutboundOrder', |
| | | path:'/allocateoutboundOrder', |
| | | name: 'allocateoutboundOrder', |
| | | component: () => import('@/views/outbound/allocateoutboundOrder.vue') |
| | | }, |
| | |
| | | path: '/allocateOrder', |
| | | name: 'Dt_AllocateOrder', |
| | | component: () => import('@/views/inbound/Dt_AllocateOrder.vue') |
| | | }, |
| | | { |
| | | path: '/reCheckOrder', |
| | | name: 'Dt_ReCheckOrder', |
| | | component: () => import('@/views/check/ReCheckOrder.vue') |
| | | } |
| | | ] |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <!-- |
| | | *Authorï¼jxx |
| | | *Contactï¼283591387@qq.com |
| | | *代ç ç±æ¡æ¶çæ,任使´æ¹é½å¯è½å¯¼è´è¢«ä»£ç çæå¨è¦ç |
| | | *ä¸å¡è¯·å¨@/extension/widesea_wcs/order/Dt_CheckOrder.jsæ¤å¤ç¼å |
| | | --> |
| | | <template> |
| | | <view-grid ref="grid" :columns="columns" :editFormFields="editFormFields" |
| | | :editFormOptions="editFormOptions" :searchFormFields="searchFormFields" :searchFormOptions="searchFormOptions" |
| | | :table="table" :extend="extend"> |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/check/recheckOrder.js"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | | const table = ref({ |
| | | key: 'id', |
| | | footer: "Foots", |
| | | cnName: '鿣å', |
| | | name: 'Dt_ReCheckOrder', |
| | | url: "/ReCheckOrder/", |
| | | sortName: "id" |
| | | }); |
| | | |
| | | |
| | | const editFormFields = ref({ |
| | | OrderNo: "", |
| | | MaterielCode: "", |
| | | BatchNo: "", |
| | | WarehouseCode: "", |
| | | Unit: "", |
| | | FactoryArea: "", |
| | | Result: 0, |
| | | InspectionNumber: 0, |
| | | Qty: 0, |
| | | SignSeq: 0 |
| | | }); |
| | | |
| | | |
| | | const editFormOptions = ref([ |
| | | [ |
| | | { title: "夿£åå·", field: "OrderNo", type: "input", require: true }, |
| | | { title: "ç©æç¼å·", field: "MaterielCode", type: "input", require: true }, |
| | | { title: "æ¹æ¬¡å·", field: "BatchNo", type: "input", require: true }, |
| | | { title: "ä»åºç¼ç ", field: "WarehouseCode", type: "input", require: true } |
| | | ], |
| | | [ |
| | | { title: "åä½", field: "Unit", type: "input", require: true }, |
| | | { title: "ååº", field: "FactoryArea", type: "input", require: true }, |
| | | { title: "æ£éªç»æ", field: "Result", type: "select", require: true,dataKey: "inOrderType",data: []}, |
| | | { title: "æ£éªæ¬¡æ°", field: "InspectionNumber", type: "number", require: true, min: 1 } |
| | | ], |
| | | [ |
| | | { title: "æ°é", field: "Qty", type: "number", require: true, min: 0 }, |
| | | { title: "ç¾å顺åº", field: "SignSeq", type: "number", require: true, min: 1 } |
| | | ] |
| | | ]); |
| | | |
| | | |
| | | const searchFormFields = ref({ |
| | | OrderNo: "", |
| | | MaterielCode: "", |
| | | BatchNo: "", |
| | | WarehouseCode: "", |
| | | FactoryArea: "", |
| | | Result: "" |
| | | }); |
| | | |
| | | |
| | | const searchFormOptions = ref([ |
| | | [ |
| | | { title: "夿£åå·", field: "OrderNo", type: "like" }, |
| | | { title: "ç©æç¼å·", field: "MaterielCode", type: "like" }, |
| | | { title: "æ¹æ¬¡å·", field: "BatchNo", type: "like" }, |
| | | { title: "ä»åºç¼ç ", field: "WarehouseCode", type: "like" } |
| | | ], |
| | | [ |
| | | { title: "ååº", field: "FactoryArea", type: "like" }, |
| | | { title: "æ£éªç»æ", field: "Result", type: "select",dataKey: "inOrderType", data: []} |
| | | ] |
| | | ]); |
| | | |
| | | |
| | | const columns = ref([ |
| | | { field: 'id', title: '主é®', type: 'int', width: 150, hidden: true, readonly: true, require: true, align: 'left' }, |
| | | { field: 'orderNo', title: '夿£åå·', type: 'string', width: 160, require: true, align: 'left', sort: true }, |
| | | { field: 'materielCode', title: 'ç©æç¼å·', type: 'string', width: 160, require: true, align: 'left' }, |
| | | { field: 'batchNo', title: 'æ¹æ¬¡å·', type: 'string', width: 160, require: true, align: 'left' }, |
| | | { field: 'warehouseCode', title: 'ä»åºç¼ç ', type: 'string', width: 160, require: true, align: 'left' }, |
| | | { field: 'unit', title: 'åä½', type: 'string', width: 100, require: true, align: 'left' }, |
| | | { field: 'factoryArea', title: 'ååº', type: 'string', width: 120, require: true, align: 'left' }, |
| | | { field: 'result', title: 'æ£éªç»æ', type: 'int', width: 110, require: true, align: 'left',bind: { key: "inOrderType", data: [] },}, |
| | | { field: 'inspectionNumber', title: 'æ£éªæ¬¡æ°', type: 'int', width: 110, require: true, align: 'left' }, |
| | | { field: 'qty', title: 'æ°é', type: 'float', width: 110, require: true, align: 'left' }, |
| | | { field: 'signSeq', title: 'ç¾å顺åº', type: 'int', width: 110, require: true, align: 'left' }, |
| | | { field: 'creater', title: 'å建è
', type: 'string', width: 110, require: true, align: 'left' }, |
| | | { field: 'createDate', title: 'å建æ¶é´', type: 'datetime', width: 150, require: true, align: 'left', sort: true }, |
| | | { field: 'modifier', title: 'ä¿®æ¹äºº', type: 'string', width: 100, align: 'left' }, |
| | | { field: 'modifyDate', title: 'ä¿®æ¹æ¥æ', type: 'datetime', width: 150, align: 'left', sort: true }, |
| | | ]); |
| | | |
| | | return { |
| | | table, |
| | | extend, |
| | | editFormFields, |
| | | editFormOptions, |
| | | searchFormFields, |
| | | searchFormOptions, |
| | | columns |
| | | }; |
| | | }, |
| | | }); |
| | | </script> |
| | |
| | | *ä¸å¡è¯·å¨@/extension/widesea_wcs/order/Dt_CheckOrder.jsæ¤å¤ç¼å |
| | | --> |
| | | <template> |
| | | <view-grid ref="grid" |
| | | :columns="columns" |
| | | :detail="detail" |
| | | :editFormFields="editFormFields" |
| | | :editFormOptions="editFormOptions" |
| | | :searchFormFields="searchFormFields" |
| | | :searchFormOptions="searchFormOptions" |
| | | :table="table" |
| | | :extend="extend"> |
| | | <view-grid ref="grid" :columns="columns" :detail="detail" :editFormFields="editFormFields" |
| | | :editFormOptions="editFormOptions" :searchFormFields="searchFormFields" :searchFormOptions="searchFormOptions" |
| | | :table="table" :extend="extend"> |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/check/checkOrder.js"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | | const table = ref({ |
| | | key: 'checkOrderId', |
| | | footer: "Foots", |
| | | cnName: 'æ£éªå', |
| | | name: 'checkOrder', |
| | | url: "/CheckOrder/", |
| | | sortName: "checkOrderId" |
| | | }); |
| | | const editFormFields = ref({}); |
| | | const editFormOptions = ref([]); |
| | | const searchFormFields = ref({ |
| | | checkOrderNo:"", |
| | | receiveOrderNo:"", |
| | | checkOrderStatus:"", |
| | | auditStatus:"" |
| | | }); |
| | | const searchFormOptions = ref([ |
| | | [ |
| | | {title:"æ£éªåå·", field:"checkOrderNo",type:"like"}, |
| | | {title:"æ¶è´§åå·", field:"receiveOrderNo",type:"like"}, |
| | | {title:"è´¨æ£åç¶æ", field:"checkOrderStatus",type:"select",dataKey:"",data:[]}, |
| | | {title:"审æ¹ç¶æ", field:"auditStatus",type:"select",dataKey:"",data:[]}, |
| | | ], |
| | | [ |
| | | {title:"æ¶è´§åæç»è¡å·", field:"receiveDetailRowNo",type:"like"}, |
| | | {title:"ç©æç¼å·", field:"materielCode",type:"like"}, |
| | | {title:"æ£éªç»æ", field:"result",type:"like"}, |
| | | ] |
| | | ]); |
| | | const columns = ref([{field:'checkOrderId',title:'主é®',type:'int',width:150,hidden:true,readonly:true,require:true,align:'left'}, |
| | | {field:'checkOrderNo',title:'æ£éªåå·',type:'string',width:160,require:true,align:'left',sort:true}, |
| | | {field:'receiveOrderNo',title:'æ¶è´§åå·',type:'string',width:160,require:true,align:'left'}, |
| | | {field:'checkOrderStatus',title:'è´¨æ£åç¶æ',type:'int',width:110,require:true,align:'left'}, |
| | | {field:'auditStatus',title:'审æ¹ç¶æ',type:'int',width:110,require:true,align:'left'}, |
| | | {field:'receiveDetailRowNo',title:'æ¶è´§åæç»è¡å·',type:'int',width:110,require:true,align:'left'}, |
| | | {field:'materielCode',title:'ç©æç¼å·',type:'string',width:110,require:true,align:'left'}, |
| | | {field:'qualifiedQuantity',title:'åæ ¼æ°é',type:'float',width:110,align:'left'}, |
| | | {field:'defectedQuantity',title:'ç¹éæ°é',type:'float',width:110,align:'left'}, |
| | | {field:'returnQuantity',title:'éè´§æ°é',type:'float',width:110,align:'left'}, |
| | | {field:'scrappedQuantity',title:'æ¥åºæ°é',type:'float',width:110,align:'left'}, |
| | | {field:'receivedQuantity',title:'æ£éªæ»æ°',type:'float',width:110,require:true,align:'left'}, |
| | | {field:'result',title:'æ£éªç»æ',type:'string',width:110,align:'left'}, |
| | | {field:'defectedNote',title:'ç¹é说æ',type:'string',width:110,align:'left'}, |
| | | {field:'checkUserName',title:'æ£éªäºº',type:'string',width:110,align:'left'}, |
| | | {field:'creater',title:'å建è
',type:'string',width:110,require:true,align:'left'}, |
| | | {field:'createDate',title:'å建æ¶é´',type:'datetime',width:150,require:true,align:'left',sort:true}, |
| | | {field:'modifier',title:'ä¿®æ¹äºº',type:'string',width:100,align:'left'}, |
| | | {field:'modifyDate',title:'ä¿®æ¹æ¥æ',type:'datetime',width:150,align:'left',sort:true}]); |
| | | const detail = ref({ |
| | | cnName: "æ£éªç»æ", |
| | | table: "CheckOrderResult", |
| | | columns: [ |
| | | {field:'id',title:'主é®',type:'int',width:110,hidden:true,readonly:true,require:true,align:'left'}, |
| | | {field:'checkOrderId',title:'æ£éªå主é®',type:'int',width:110,require:true,align:'left',sort:true}, |
| | | {field:'defectCode',title:'缺é·ä»£ç ',type:'string',width:110,require:true,align:'left'}, |
| | | {field:'result',title:'æ£éªç»æ',type:'string',width:110,require:true,align:'left'}, |
| | | {field:'quantity',title:'æ°é',type:'float',width:110,require:true,align:'left'}, |
| | | {field:'note',title:'夿³¨',type:'string',width:220,align:'left'}, |
| | | {field:'creater',title:'å建è
',type:'string',width:110,require:true,align:'left'}, |
| | | {field:'createDate',title:'å建æ¶é´',type:'datetime',width:150,require:true,align:'left',sort:true}, |
| | | {field:'modifier',title:'ä¿®æ¹äºº',type:'string',width:100,align:'left'}, |
| | | {field:'modifyDate',title:'ä¿®æ¹æ¥æ',type:'datetime',width:150,align:'left',sort:true} |
| | | ], |
| | | sortName: "id", |
| | | key: "id" |
| | | }); |
| | | return { |
| | | table, |
| | | extend, |
| | | editFormFields, |
| | | editFormOptions, |
| | | searchFormFields, |
| | | searchFormOptions, |
| | | columns, |
| | | detail, |
| | | }; |
| | | }, |
| | | }); |
| | | import extend from "@/extension/check/checkOrder.js"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | | const table = ref({ |
| | | key: 'checkOrderId', |
| | | footer: "Foots", |
| | | cnName: 'æ£éªå', |
| | | name: 'checkOrder', |
| | | url: "/CheckOrder/", |
| | | sortName: "checkOrderId" |
| | | }); |
| | | const editFormFields = ref({}); |
| | | const editFormOptions = ref([]); |
| | | const searchFormFields = ref({ |
| | | checkOrderNo: "", |
| | | receiveOrderNo: "", |
| | | checkOrderStatus: "", |
| | | auditStatus: "" |
| | | }); |
| | | const searchFormOptions = ref([ |
| | | [ |
| | | { title: "æ£éªåå·", field: "checkOrderNo", type: "like" }, |
| | | { title: "æ¶è´§åå·", field: "receiveOrderNo", type: "like" }, |
| | | { title: "è´¨æ£åç¶æ", field: "checkOrderStatus", type: "select", dataKey: "", data: [] }, |
| | | { title: "审æ¹ç¶æ", field: "auditStatus", type: "select", dataKey: "", data: [] }, |
| | | ], |
| | | [ |
| | | { title: "æ¶è´§åæç»è¡å·", field: "receiveDetailRowNo", type: "like" }, |
| | | { title: "ç©æç¼å·", field: "materielCode", type: "like" }, |
| | | { title: "æ£éªç»æ", field: "result", type: "like" }, |
| | | ] |
| | | ]); |
| | | const columns = ref([{ field: 'checkOrderId', title: '主é®', type: 'int', width: 150, hidden: true, readonly: true, require: true, align: 'left' }, |
| | | { field: 'checkOrderNo', title: 'æ£éªåå·', type: 'string', width: 160, require: true, align: 'left', sort: true }, |
| | | { field: 'receiveOrderNo', title: 'æ¶è´§åå·', type: 'string', width: 160, require: true, align: 'left' }, |
| | | { field: 'checkOrderStatus', title: 'è´¨æ£åç¶æ', type: 'int', width: 110, require: true, align: 'left' }, |
| | | { field: 'auditStatus', title: '审æ¹ç¶æ', type: 'int', width: 110, require: true, align: 'left' }, |
| | | { field: 'receiveDetailRowNo', title: 'æ¶è´§åæç»è¡å·', type: 'int', width: 110, require: true, align: 'left' }, |
| | | { field: 'materielCode', title: 'ç©æç¼å·', type: 'string', width: 110, require: true, align: 'left' }, |
| | | { field: 'qualifiedQuantity', title: 'åæ ¼æ°é', type: 'float', width: 110, align: 'left' }, |
| | | { field: 'defectedQuantity', title: 'ç¹éæ°é', type: 'float', width: 110, align: 'left' }, |
| | | { field: 'returnQuantity', title: 'éè´§æ°é', type: 'float', width: 110, align: 'left' }, |
| | | { field: 'scrappedQuantity', title: 'æ¥åºæ°é', type: 'float', width: 110, align: 'left' }, |
| | | { field: 'receivedQuantity', title: 'æ£éªæ»æ°', type: 'float', width: 110, require: true, align: 'left' }, |
| | | { field: 'result', title: 'æ£éªç»æ', type: 'string', width: 110, align: 'left' }, |
| | | { field: 'defectedNote', title: 'ç¹é说æ', type: 'string', width: 110, align: 'left' }, |
| | | { field: 'checkUserName', title: 'æ£éªäºº', type: 'string', width: 110, align: 'left' }, |
| | | { field: 'creater', title: 'å建è
', type: 'string', width: 110, require: true, align: 'left' }, |
| | | { field: 'createDate', title: 'å建æ¶é´', type: 'datetime', width: 150, require: true, align: 'left', sort: true }, |
| | | { field: 'modifier', title: 'ä¿®æ¹äºº', type: 'string', width: 100, align: 'left' }, |
| | | { field: 'modifyDate', title: 'ä¿®æ¹æ¥æ', type: 'datetime', width: 150, align: 'left', sort: true }]); |
| | | const detail = ref({ |
| | | cnName: "æ£éªç»æ", |
| | | table: "CheckOrderResult", |
| | | columns: [ |
| | | { field: 'id', title: '主é®', type: 'int', width: 110, hidden: true, readonly: true, require: true, align: 'left' }, |
| | | { field: 'checkOrderId', title: 'æ£éªå主é®', type: 'int', width: 110, require: true, align: 'left', sort: true }, |
| | | { field: 'defectCode', title: '缺é·ä»£ç ', type: 'string', width: 110, require: true, align: 'left' }, |
| | | { field: 'result', title: 'æ£éªç»æ', type: 'string', width: 110, require: true, align: 'left' }, |
| | | { field: 'quantity', title: 'æ°é', type: 'float', width: 110, require: true, align: 'left' }, |
| | | { field: 'note', title: '夿³¨', type: 'string', width: 220, align: 'left' }, |
| | | { field: 'creater', title: 'å建è
', type: 'string', width: 110, require: true, align: 'left' }, |
| | | { field: 'createDate', title: 'å建æ¶é´', type: 'datetime', width: 150, require: true, align: 'left', sort: true }, |
| | | { field: 'modifier', title: 'ä¿®æ¹äºº', type: 'string', width: 100, align: 'left' }, |
| | | { field: 'modifyDate', title: 'ä¿®æ¹æ¥æ', type: 'datetime', width: 150, align: 'left', sort: true } |
| | | ], |
| | | sortName: "id", |
| | | key: "id" |
| | | }); |
| | | return { |
| | | table, |
| | | extend, |
| | | editFormFields, |
| | | editFormOptions, |
| | | searchFormFields, |
| | | searchFormOptions, |
| | | columns, |
| | | detail, |
| | | }; |
| | | }, |
| | | }); |
| | | </script> |
| | |
| | | key: "id", |
| | | footer: "Foots", |
| | | cnName: "è°æ¨å", |
| | | name: "Dt_AllocateOrder", |
| | | name: "AllocateOrder", |
| | | url: "/AllocateOrder/", |
| | | sortName: "id", |
| | | }); |
| | |
| | | const table = ref({ |
| | | key: "id", |
| | | footer: "Foots", |
| | | cnName: "è°æ¨å(æºä»è°å¤é¨ä»åº)", |
| | | name: "inboundOrder", |
| | | url: "/InboundOrder/", |
| | | cnName: "è°æ¨å(å¤é¨ä»è°å
¥æºä»)", |
| | | name: "AllocateOrder", |
| | | url: "/AllocateOrder/", |
| | | sortName: "id", |
| | | }); |
| | | const editFormFields = ref({ |
| | | orderType: "", |
| | | inboundOrderNo: "", |
| | | orderNo: "", |
| | | upperOrderNo: "", |
| | | remark: "", |
| | | }); |
| | |
| | | data: [], |
| | | }, |
| | | { |
| | | field: "inboundOrderNo", |
| | | field: "orderNo", |
| | | title: "åæ®ç¼å·", |
| | | type: "string", |
| | | }, |
| | |
| | | ], |
| | | ]); |
| | | const searchFormFields = ref({ |
| | | inboundOrderNo: "", |
| | | orderNo: "", |
| | | upperOrderNo: "", |
| | | orderType: "115", |
| | | orderStatus: "", |
| | |
| | | }); |
| | | const searchFormOptions = ref([ |
| | | [ |
| | | { title: "åæ®ç¼å·", field: "inboundOrderNo", type: "like" }, |
| | | { title: "åæ®ç¼å·", field: "orderNo", type: "like" }, |
| | | { title: "䏿¸¸åæ®ç¼å·", field: "upperOrderNo", type: "like" }, |
| | | { |
| | | title: "åæ®ç±»å", |
| | |
| | | align: "left", |
| | | }, |
| | | { |
| | | field: "inboundOrderNo", |
| | | field: "orderNo", |
| | | title: "åæ®ç¼å·", |
| | | type: "string", |
| | | width: 120, |
| | |
| | | type: "select", |
| | | dataKey: "inOrderType", |
| | | data: [], |
| | | hidden:true |
| | | }, |
| | | { |
| | | field: "inboundOrderNo", |
| | |
| | | type: "select", |
| | | dataKey: "inOrderType", |
| | | data: [0], |
| | | hidden:true |
| | | }, |
| | | { |
| | | title: "åæ®ç¶æ", |
| | |
| | | width: 150, |
| | | align: "left", |
| | | bind: { key: "inOrderType", data: [] }, |
| | | hidden:true |
| | | }, |
| | | { |
| | | field: "businessType", |
| | |
| | | field: "materielCode", |
| | | title: "ç©æç¼å·", |
| | | type: "select", |
| | | width: 150, |
| | | width: 120, |
| | | align: "left", |
| | | edit: { type: "" }, |
| | | required: true, |
| | |
| | | field: "materielCode", |
| | | title: "ç©æåç§°", |
| | | type: "string", |
| | | width: 100, |
| | | width: 120, |
| | | align: "left", |
| | | bind: { key: "MaterielNames", data: [] }, |
| | | }, |
| | |
| | | field: "batchNo", |
| | | title: "æ¹æ¬¡å·", |
| | | type: "decimal", |
| | | width: 90, |
| | | width: 150, |
| | | align: "left", |
| | | edit: { type: "" }, |
| | | required: true, |
| | |
| | | field: "supplyCode", |
| | | title: "ä¾åºåç¼å·", |
| | | type: "decimal", |
| | | width: 90, |
| | | width: 100, |
| | | align: "left", |
| | | edit: { type: "" }, |
| | | required: true, |
| | |
| | | field: "barcode", |
| | | title: "æ¡ç ", |
| | | type: "decimal", |
| | | width: 90, |
| | | width: 180, |
| | | align: "left", |
| | | edit: { type: "" }, |
| | | required: true, |
| | |
| | | field: "receiptQuantity", |
| | | title: "ç»çæ°é", |
| | | type: "int", |
| | | width: 120, |
| | | width: 90, |
| | | align: "left", |
| | | }, |
| | | { |
| | | field: "overInQuantity", |
| | | title: "䏿¶æ°é", |
| | | type: "string", |
| | | width: 200, |
| | | width: 90, |
| | | align: "left", |
| | | }, |
| | | { |
| | | field: "orderDetailStatus", |
| | | title: "订åæç»ç¶æ", |
| | | type: "string", |
| | | width: 180, |
| | | width: 100, |
| | | align: "left", |
| | | bind: { key: "orderDetailStatusEnum", data: [] }, |
| | | }, |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="OutboundPicking-container"> |
| | | <div class="page-header"> |
| | | <el-page-header @back="goBack"> |
| | | <template #content> |
| | | <span class="title">åºåºæ£é确认 - {{ this.$route.query.orderNo }}</span> |
| | | </template> |
| | | </el-page-header> |
| | | </div> |
| | | |
| | | <!-- æ«ç åºå --> |
| | | <div class="scanner-area"> |
| | | <el-card> |
| | | <div class="scanner-form"> |
| | | <el-input |
| | | ref="palletInput" |
| | | v-model="scanData.palletCode" |
| | | placeholder="æ«ææçç " |
| | | @change="onPalletScan" |
| | | @keyup.enter.native="onPalletScan"> |
| | | </el-input> |
| | | <el-input |
| | | ref="barcodeInput" |
| | | v-model="scanData.barcode" |
| | | placeholder="æ«æç©ææ¡ç " |
| | | @change="onBarcodeScan" |
| | | @keyup.enter.native="onBarcodeScan"> |
| | | </el-input> |
| | | <el-button type="success" @click="confirmPicking">确认æ£é</el-button> |
| | | <el-button type="warning" @click="openSplitDialog">æå
</el-button> |
| | | <el-button type="info" @click="openRevertSplitDialog">æ¤éæå
</el-button> |
| | | <el-button type="info" @click="handleEmptyPallet">å空箱</el-button> |
| | | <el-button type="primary" @click="openBatchReturnDialog">ååº</el-button> |
| | | </div> |
| | | </el-card> |
| | | </div> |
| | | |
| | | <!-- æ±æ»ä¿¡æ¯ --> |
| | | <div class="summary-area"> |
| | | <el-card> |
| | | <div class="summary-info"> |
| | | <el-tag type="warning">æªæ£éæ¡æ°: {{summary.unpickedCount}}</el-tag> |
| | | <el-tag type="danger">æªæ£éæ°é: {{summary.unpickedQuantity}}</el-tag> |
| | | <el-tag type="info">æçç¶æ: {{palletStatus}}</el-tag> |
| | | </div> |
| | | </el-card> |
| | | </div> |
| | | |
| | | <!-- æ°æ®å表 --> |
| | | <div class="content-area"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-card header="æªæ£éå表"> |
| | | <el-table :data="unpickedList" border height="440"> |
| | | <el-table-column prop="materielCode" label="ç©æç¼ç " width="120"></el-table-column> |
| | | <el-table-column prop="assignQuantity" label="åé
æ°é" width="100"></el-table-column> |
| | | <el-table-column prop="pickedQty" label="å·²æ£æ°é" width="100"></el-table-column> |
| | | <el-table-column prop="remainQuantity" label="å©ä½æ°é" width="100"></el-table-column> |
| | | <el-table-column prop="locationCode" label="è´§ä½" width="100"></el-table-column> |
| | | <el-table-column prop="currentBarcode" label="æ¡ç "></el-table-column> |
| | | </el-table> |
| | | </el-card> |
| | | </el-col> |
| | | |
| | | <el-col :span="12"> |
| | | <el-card header="å·²æ£éå表"> |
| | | <div class="table-actions"> |
| | | <el-button |
| | | size="mini" |
| | | type="danger" |
| | | :disabled="selectedPickedRows.length === 0" |
| | | @click="batchCancelSelected"> |
| | | åæ¶æ£é |
| | | </el-button> |
| | | <span class="selection-count">已鿩 {{selectedPickedRows.length}} 项</span> |
| | | </div> |
| | | <el-table |
| | | :data="pickedList" |
| | | border |
| | | height="400" |
| | | style="width: 100%" |
| | | @selection-change="handlePickedSelectionChange"> |
| | | <el-table-column type="selection" width="55"></el-table-column> |
| | | <el-table-column prop="materielCode" label="ç©æç¼ç " width="120"></el-table-column> |
| | | <el-table-column prop="pickedQty" label="å·²æ£æ°é" width="100"></el-table-column> |
| | | <el-table-column prop="locationCode" label="è´§ä½" width="100"></el-table-column> |
| | | <el-table-column prop="currentBarcode" label="æ¡ç "></el-table-column> |
| | | </el-table> |
| | | </el-card> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | |
| | | <!-- æå
å¼¹çª --> |
| | | <div v-if="showCustomSplitDialog" class="custom-dialog-overlay"> |
| | | <div class="custom-dialog-wrapper"> |
| | | <div class="custom-dialog"> |
| | | <div class="custom-dialog-header"> |
| | | <h3>æå
æä½</h3> |
| | | <el-button type="text" @click="closeCustomSplitDialog" class="close-button">X</el-button> |
| | | </div> |
| | | <div class="custom-dialog-body"> |
| | | <el-form :model="splitForm" :rules="splitFormRules" ref="splitFormRef" label-width="100px"> |
| | | <el-form-item label="订åç¼å·"> |
| | | <el-input v-model="splitForm.orderNo" disabled></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="æçç¼å·"> |
| | | <el-input v-model="splitForm.palletCode" disabled></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="åæ¡ç " prop="originalBarcode"> |
| | | <div style="display: flex; align-items: center; gap: 10px;"> |
| | | <el-input |
| | | v-model="splitForm.originalBarcode" |
| | | placeholder="æ«æåæ¡ç " |
| | | @keyup.enter.native="onSplitBarcodeScan" |
| | | @change="onSplitBarcodeScan" |
| | | clearable |
| | | style="flex: 1;"> |
| | | </el-input> |
| | | <!-- æ°å¢ï¼æ¥çæå
é¾æé® --> |
| | | <el-button |
| | | type="primary" |
| | | @click="viewSplitChainFromSplit(splitForm.originalBarcode)" |
| | | :disabled="!splitForm.originalBarcode" |
| | | :loading="splitChainLoading"> |
| | | æ¥çæå
é¾ |
| | | </el-button> |
| | | </div> |
| | | </el-form-item> |
| | | <el-form-item label="ç©æç¼ç "> |
| | | <el-input v-model="splitForm.materielCode" disabled></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="å©ä½æ°é"> |
| | | <el-input v-model="splitForm.maxQuantity" disabled></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="æå
æ°é" prop="splitQuantity"> |
| | | <el-input-number |
| | | v-model="splitForm.splitQuantity" |
| | | :min="1" |
| | | :max="splitForm.maxQuantity" |
| | | :precision="2" |
| | | :step="1" |
| | | style="width: 100%"> |
| | | </el-input-number> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | <div class="custom-dialog-footer"> |
| | | <el-button @click="closeCustomSplitDialog">åæ¶</el-button> |
| | | <el-button type="primary" @click="handleSplitPackage" :loading="splitLoading">确认æå
</el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- æ¤éæå
å¼¹çª --> |
| | | <div v-if="showRevertSplitDialog" class="custom-dialog-overlay"> |
| | | <div class="custom-dialog-wrapper"> |
| | | <div class="custom-dialog"> |
| | | <div class="custom-dialog-header"> |
| | | <h3>æ¤éæå
</h3> |
| | | <el-button type="text" @click="closeRevertSplitDialog" class="close-button">Ã</el-button> |
| | | </div> |
| | | <div class="custom-dialog-body"> |
| | | <el-form :model="revertSplitForm" :rules="revertSplitFormRules" ref="revertSplitFormRef" label-width="100px"> |
| | | <el-form-item label="æ°æ¡ç " prop="newBarcode"> |
| | | <div style="display: flex; align-items: center; gap: 10px;"> |
| | | <el-input |
| | | v-model="revertSplitForm.newBarcode" |
| | | placeholder="æ«ææ°æ¡ç " |
| | | @keyup.enter.native="onRevertSplitBarcodeScan" |
| | | @change="onRevertSplitBarcodeScan" |
| | | clearable |
| | | style="flex: 1;"> |
| | | </el-input> |
| | | <!-- æ°å¢ï¼æ¥çæå
é¾æé® --> |
| | | <el-button |
| | | type="primary" |
| | | @click="viewSplitChain(revertSplitForm.newBarcode)" |
| | | :disabled="!revertSplitForm.newBarcode"> |
| | | æ¥çæå
é¾ |
| | | </el-button> |
| | | </div> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <!-- æ°å¢ï¼æå
é¾ç®è¦ä¿¡æ¯æ¾ç¤º --> |
| | | <div v-if="splitChainInfo.splitChain && splitChainInfo.splitChain.length > 0" |
| | | style="margin-top: 15px; padding: 10px; background: #f0f9ff; border-radius: 4px;"> |
| | | <div style="font-size: 14px; color: #606266;"> |
| | | <div>æå
é¾ä¿¡æ¯: å
± {{ splitChainInfo.totalSplitTimes }} 次æå
</div> |
| | | <div style="margin-top: 5px;"> |
| | | <el-tag |
| | | v-for="item in splitChainInfo.splitChain.slice(0, 3)" |
| | | :key="item.newBarcode" |
| | | :type="item.isReverted ? 'success' : 'primary'" |
| | | size="small" |
| | | style="margin-right: 5px;"> |
| | | {{ item.newBarcode }} ({{ item.splitQuantity }}) |
| | | </el-tag> |
| | | <span v-if="splitChainInfo.splitChain.length > 3" style="color: #909399;"> |
| | | ç {{ splitChainInfo.splitChain.length }} 个æ¡ç |
| | | </span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="custom-dialog-footer"> |
| | | <el-button @click="closeRevertSplitDialog">åæ¶</el-button> |
| | | <el-button type="primary" @click="handleRevertSplit" :loading="revertSplitLoading">确认æ¤é</el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- æå
é¾ä¿¡æ¯å¼¹çª --> |
| | | <div v-if="showSplitChainDialog" class="custom-dialog-overlay"> |
| | | <div class="custom-dialog-wrapper"> |
| | | <div class="custom-dialog" style="width: 750px;"> |
| | | <div class="custom-dialog-header"> |
| | | <h3>æå
é¾ä¿¡æ¯</h3> |
| | | <el-button type="text" @click="closeSplitChainDialog" class="close-button">Ã</el-button> |
| | | </div> |
| | | <div class="custom-dialog-body"> |
| | | <!-- æ°å¢ï¼æå
é¾è¯´æ --> |
| | | <div style="margin-bottom: 15px; padding: 10px; background: #f0f9ff; border-radius: 4px;"> |
| | | <div style="display: flex; justify-content: space-between; align-items: center;"> |
| | | <div> |
| | | <div style="font-weight: bold; color: #303133;">æå
é¾è¯´æ</div> |
| | | <div style="font-size: 12px; color: #606266; margin-top: 5px;"> |
| | | å½åæ¾ç¤ºçæ¯ä» <el-tag type="primary" size="small">{{ splitChainInfo.originalBarcode }}</el-tag> å¼å§çæå
é¾ |
| | | <br>å
± {{ splitChainInfo.totalSplitTimes }} 次æå
æä½ï¼æ¶å {{ splitChainInfo.splitChain.length }} 个æ¡ç |
| | | </div> |
| | | </div> |
| | | <el-button |
| | | type="primary" |
| | | size="small" |
| | | @click="findRootChain(splitChainInfo.originalBarcode)" |
| | | v-if="splitChainInfo.chainType !== 'root'"> |
| | | æ¥æ¾å®æ´æå
é¾ |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | |
| | | <div style="margin-bottom: 15px;"> |
| | | <el-tag type="info">æ»æå
次æ°: {{ splitChainInfo.totalSplitTimes }}</el-tag> |
| | | <el-tag type="warning" style="margin-left: 10px;"> |
| | | åå§æ¡ç : {{ splitChainInfo.originalBarcode }} |
| | | </el-tag> |
| | | <el-tag :type="splitChainInfo.chainType === 'root' ? 'success' : 'warning'" style="margin-left: 10px;"> |
| | | {{ splitChainInfo.chainType === 'root' ? '宿´é¾' : '忝é¾' }} |
| | | </el-tag> |
| | | </div> |
| | | |
| | | <el-table :data="splitChainInfo.splitChain" border height="300"> |
| | | <el-table-column type="index" label="åºå·" width="60" align="center"></el-table-column> |
| | | <el-table-column prop="splitTime" label="æå
æ¶é´" width="160"> |
| | | <template #default="scope"> |
| | | {{ formatDateTime(scope.row.splitTime) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="originalBarcode" label="åæ¡ç " width="140"> |
| | | <template #default="scope"> |
| | | <el-tag |
| | | :type="scope.row.originalBarcode === splitChainInfo.rootBarcode ? 'success' : 'primary'" |
| | | size="small"> |
| | | {{ scope.row.originalBarcode }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="newBarcode" label="æ°æ¡ç " width="140"> |
| | | <template #default="scope"> |
| | | <el-tag |
| | | :type="scope.row.isReverted ? 'info' : 'warning'" |
| | | size="small"> |
| | | {{ scope.row.newBarcode }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="splitQuantity" label="æå
æ°é" width="100" align="right"> |
| | | <template #default="scope"> |
| | | {{ scope.row.splitQuantity.toFixed(2) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="operator" label="æä½å" width="100"></el-table-column> |
| | | <el-table-column prop="isReverted" label="ç¶æ" width="80" align="center"> |
| | | <template #default="scope"> |
| | | <el-tag |
| | | :type="scope.row.isReverted ? 'success' : 'danger'" |
| | | size="small"> |
| | | {{ scope.row.isReverted ? 'å·²æ¤é' : 'ææ' }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æä½" width="120" align="center"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | v-if="!scope.row.isReverted" |
| | | type="danger" |
| | | size="mini" |
| | | @click="cancelSingleSplit(scope.row.newBarcode)" |
| | | :disabled="hasPicked(scope.row.newBarcode)"> |
| | | åæ¶ |
| | | </el-button> |
| | | <span v-else style="color: #909399;">å·²æ¤é</span> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <!-- æ¹éæä½åºå --> |
| | | <div style="margin-top: 15px; padding: 10px; background: #f5f7fa; border-radius: 4px;"> |
| | | <div style="display: flex; justify-content: space-between; align-items: center;"> |
| | | <div> |
| | | <span style="font-size: 14px; color: #606266;"> |
| | | æ¹éæä½: å¯ä»¥åæ¶æ´ä¸ªæå
龿鿩å个æå
è®°å½åæ¶ |
| | | </span> |
| | | <div style="font-size: 12px; color: #909399; margin-top: 5px;"> |
| | | 宿´æå
é¾å
å«ä»æåå§æ¡ç å¼å§çæææå
æä½ |
| | | </div> |
| | | </div> |
| | | <div> |
| | | <el-button |
| | | type="danger" |
| | | @click="cancelWholeSplitChain" |
| | | :disabled="!canCancelWholeChain" |
| | | :loading="revertSplitLoading"> |
| | | åæ¶æ´ä¸ªæå
é¾ |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="custom-dialog-footer"> |
| | | <el-button @click="closeSplitChainDialog">å
³é</el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- æ¹éååºå¼¹çª --> |
| | | <div v-if="showBatchReturnDialog" class="custom-dialog-overlay"> |
| | | <div class="custom-dialog-wrapper"> |
| | | <div class="custom-dialog"> |
| | | <div class="custom-dialog-header"> |
| | | <h3>æçååº</h3> |
| | | <el-button type="text" @click="closeBatchReturnDialog" class="close-button">Ã</el-button> |
| | | </div> |
| | | <div class="custom-dialog-body"> |
| | | <el-form :model="batchReturnForm" :rules="batchReturnFormRules" ref="batchReturnFormRef" label-width="100px"> |
| | | <el-form-item label="订åç¼å·"> |
| | | <el-input v-model="batchReturnForm.orderNo" disabled></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="æçç¼å·"> |
| | | <el-input v-model="batchReturnForm.palletCode" disabled></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="æªæ£éæ°é"> |
| | | <el-input v-model="batchReturnForm.unpickedQuantity" disabled></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="æªæ£éæ¡æ°"> |
| | | <el-input v-model="batchReturnForm.unpickedCount" disabled></el-input> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | <div class="custom-dialog-footer"> |
| | | <el-button @click="closeBatchReturnDialog">åæ¶</el-button> |
| | | <el-button type="primary" @click="handleBatchReturnConfirm" :loading="batchReturnLoading">确认ååº</el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- åèµ°ç©ºç®±å¼¹çª --> |
| | | <div v-if="showEmptyPalletDialog" class="custom-dialog-overlay"> |
| | | <div class="custom-dialog-wrapper"> |
| | | <div class="custom-dialog"> |
| | | <div class="custom-dialog-header"> |
| | | <h3>å走空箱</h3> |
| | | <el-button type="text" @click="closeEmptyPalletDialog" class="close-button">Ã</el-button> |
| | | </div> |
| | | <div class="custom-dialog-body"> |
| | | <el-form :model="emptypalletOutForm" :rules="emptypalletOutFormRules" ref="emptypalletOutFormRef" label-width="100px"> |
| | | <el-form-item label="订åç¼å·"> |
| | | <el-input v-model="emptypalletOutForm.orderNo" disabled></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="æçç¼å·" prop="palletCode"> |
| | | <el-input |
| | | v-model="emptypalletOutForm.palletCode" |
| | | placeholder="æ«ææçç " |
| | | @keyup.enter.native="onEmptyPalletScan" |
| | | @change="onEmptyPalletScan" |
| | | clearable> |
| | | </el-input> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | <div class="custom-dialog-footer"> |
| | | <el-button @click="closeEmptyPalletDialog">åæ¶</el-button> |
| | | <el-button type="primary" @click="handleEmptyPalletConfirm" :loading="emptypalletOutLoading">确认å走空箱</el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <print-view ref="childs" @parentcall="parentcall"></print-view> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import http from '@/api/http.js' |
| | | import { ref, defineComponent } from "vue"; |
| | | import { ElMessage } from 'element-plus' |
| | | import { useRoute } from 'vue-router' |
| | | import printView from "@/extension/outbound/extend/printView.vue" |
| | | |
| | | export default defineComponent({ |
| | | name: 'BatchOutboundPicking', |
| | | components: {printView}, |
| | | data() { |
| | | return { |
| | | scanData: { |
| | | orderNo: '', |
| | | palletCode: '', |
| | | barcode: '' |
| | | }, |
| | | unpickedList: [], |
| | | pickedList: [], |
| | | selectedPickedRows: [], |
| | | summary: { |
| | | unpickedCount: 0, |
| | | unpickedQuantity: 0, |
| | | pickedCount: 0 |
| | | }, |
| | | palletStatus: 'æªç¥', |
| | | |
| | | // å¼¹çªç¶æ |
| | | showCustomSplitDialog: false, |
| | | showRevertSplitDialog: false, |
| | | showBatchReturnDialog: false, |
| | | showEmptyPalletDialog: false, |
| | | showSplitChainDialog: false, // æ°å¢ï¼æå
é¾ä¿¡æ¯å¼¹çª |
| | | |
| | | // å è½½ç¶æ |
| | | splitLoading: false, |
| | | revertSplitLoading: false, |
| | | batchReturnLoading: false, |
| | | emptypalletOutLoading: false, |
| | | splitChainLoading: false, // æ°å¢ï¼æå
é¾å è½½ç¶æ |
| | | |
| | | // è¡¨åæ°æ® |
| | | splitForm: { |
| | | orderNo: '', |
| | | palletCode: '', |
| | | originalBarcode: '', |
| | | materielCode: '', |
| | | splitQuantity: 0, |
| | | maxQuantity: 0 |
| | | }, |
| | | |
| | | revertSplitForm: { |
| | | newBarcode: '' |
| | | }, |
| | | |
| | | batchReturnForm: { |
| | | orderNo: '', |
| | | palletCode: '', |
| | | unpickedCount: 0, |
| | | unpickedQuantity: 0 |
| | | }, |
| | | |
| | | emptypalletOutForm: { |
| | | orderNo: '', |
| | | palletCode: '' |
| | | }, |
| | | |
| | | // æ°å¢ï¼æå
é¾ç¸å
³æ°æ® |
| | | splitChainInfo: { |
| | | originalBarcode: '', |
| | | totalSplitTimes: 0, |
| | | splitChain: [] |
| | | }, |
| | | |
| | | // éªè¯è§å |
| | | splitFormRules: { |
| | | originalBarcode: [ |
| | | { required: true, message: '请è¾å
¥åæ¡ç ', trigger: 'blur' } |
| | | ], |
| | | splitQuantity: [ |
| | | { required: true, message: '请è¾å
¥æå
æ°é', trigger: 'blur' }, |
| | | { type: 'number', min: 0.01, message: 'æå
æ°éå¿
须大äº0', trigger: 'blur' } |
| | | ] |
| | | }, |
| | | |
| | | revertSplitFormRules: { |
| | | newBarcode: [ |
| | | { required: true, message: '请è¾å
¥æ°æ¡ç ', trigger: 'blur' } |
| | | ] |
| | | }, |
| | | |
| | | emptypalletOutFormRules: { |
| | | palletCode: [ |
| | | { required: true, message: '请è¾å
¥æçç ', trigger: 'blur' } |
| | | ] |
| | | }, |
| | | |
| | | isProcessing: false |
| | | } |
| | | }, |
| | | computed: { |
| | | // æ¯å¦å¯ä»¥åæ¶æ´ä¸ªæå
é¾ |
| | | canCancelWholeChain() { |
| | | return this.splitChainInfo.splitChain && |
| | | this.splitChainInfo.splitChain.some(item => !item.isReverted); |
| | | } |
| | | }, |
| | | mounted() { |
| | | if (this.$route.query.orderNo) { |
| | | this.scanData.orderNo = this.$route.query.orderNo; |
| | | this.splitForm.orderNo = this.$route.query.orderNo; |
| | | this.batchReturnForm.orderNo = this.$route.query.orderNo; |
| | | this.emptypalletOutForm.orderNo = this.$route.query.orderNo; |
| | | } |
| | | this.$nextTick(() => { |
| | | this.$refs.palletInput.focus(); |
| | | }); |
| | | }, |
| | | methods: { |
| | | goBack(){ |
| | | this.$router.back() |
| | | }, |
| | | |
| | | // 忣ç¸å
³æ¹æ³ |
| | | async confirmPicking() { |
| | | if (this.isProcessing) return; |
| | | |
| | | if (!this.scanData.orderNo || !this.scanData.palletCode || !this.scanData.barcode) { |
| | | this.$message.warning('请å
æ«ææçç åç©ææ¡ç '); |
| | | this.focusBarcodeInput(); |
| | | return; |
| | | } |
| | | |
| | | this.isProcessing = true; |
| | | |
| | | try { |
| | | const res = await http.post('/api/OutboundBatchPicking/confirm-picking', { |
| | | orderNo: this.scanData.orderNo, |
| | | palletCode: this.scanData.palletCode, |
| | | barcode: this.scanData.barcode |
| | | }); |
| | | if (res.status) { |
| | | this.$message.success('æ£é确认æå'); |
| | | this.scanData.barcode = ''; |
| | | await this.loadPalletData(); |
| | | if(res.data && res.data.splitResults && res.data.splitResults.length>0){ |
| | | this.$refs.childs.open(res.data.splitResults); |
| | | } |
| | | this.$nextTick(() => { |
| | | this.$refs.barcodeInput.focus(); |
| | | }); |
| | | } else { |
| | | this.$message.error(res.message || 'æ£é确认失败'); |
| | | this.focusBarcodeInput(true); |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('æ£é确认失败: ' + (error.message || 'ç½ç»é误')); |
| | | this.focusBarcodeInput(true); |
| | | } finally { |
| | | this.isProcessing = false; |
| | | } |
| | | }, |
| | | |
| | | // æå
ç¸å
³æ¹æ³ |
| | | openSplitDialog() { |
| | | 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; |
| | | }, |
| | | |
| | | async onSplitBarcodeScan() { |
| | | if (!this.splitForm.originalBarcode) return; |
| | | this.splitForm.originalBarcode = this.splitForm.originalBarcode.replace(/\n/g, '').trim(); |
| | | |
| | | try { |
| | | const res = await http.post('/api/OutboundBatchPicking/split-package-info', { |
| | | orderNo: this.splitForm.orderNo, |
| | | palletCode: this.splitForm.palletCode, |
| | | barcode: this.splitForm.originalBarcode |
| | | }); |
| | | |
| | | if (res.status) { |
| | | this.splitForm.materielCode = res.data.materielCode; |
| | | this.splitForm.maxQuantity = res.data.remainQuantity; |
| | | this.splitForm.splitQuantity = Math.min(1, this.splitForm.maxQuantity); |
| | | } else { |
| | | this.$message.error(res.message || 'è·åæå
ä¿¡æ¯å¤±è´¥'); |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('è·åæå
ä¿¡æ¯å¤±è´¥'); |
| | | } |
| | | }, |
| | | |
| | | async handleSplitPackage() { |
| | | if (this.$refs.splitFormRef) { |
| | | this.$refs.splitFormRef.validate(async (valid) => { |
| | | if (valid) { |
| | | this.splitLoading = true; |
| | | try { |
| | | const res = await http.post('/api/OutboundBatchPicking/split-package', { |
| | | orderNo: this.splitForm.orderNo, |
| | | palletCode: this.splitForm.palletCode, |
| | | originalBarcode: this.splitForm.originalBarcode, |
| | | splitQuantity: this.splitForm.splitQuantity |
| | | }); |
| | | if (res.status) { |
| | | this.$message.success('æå
æå'); |
| | | this.showCustomSplitDialog = false; |
| | | await this.loadPalletData(); |
| | | } else { |
| | | this.$message.error(res.message || 'æå
失败'); |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('æå
失败'); |
| | | } finally { |
| | | this.splitLoading = false; |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | }, |
| | | // 卿å
å¼¹çªä¸æ¥çæå
é¾ |
| | | async viewSplitChainFromSplit(barcode) { |
| | | if (!barcode) { |
| | | this.$message.warning('请å
è¾å
¥æ¡ç '); |
| | | return; |
| | | } |
| | | |
| | | // å
å
³éæå
å¼¹çª |
| | | this.closeCustomSplitDialog(); |
| | | |
| | | await this.$nextTick(); |
| | | |
| | | // ç¶åæå¼æå
é¾ä¿¡æ¯å¼¹çª |
| | | await this.viewSplitChain(barcode); |
| | | }, |
| | | // æ¤éæå
|
| | | 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 (this.$refs.revertSplitFormRef) { |
| | | this.$refs.revertSplitFormRef.validate(async (valid) => { |
| | | if (valid) { |
| | | this.revertSplitLoading = true; |
| | | try { |
| | | const res = await http.post('/api/OutboundBatchPicking/cancel-split', { |
| | | orderNo: this.scanData.orderNo, |
| | | palletCode: this.scanData.palletCode, |
| | | newBarcode: this.revertSplitForm.newBarcode |
| | | }); |
| | | if (res.status) { |
| | | this.$message.success('æ¤éæå
æå'); |
| | | this.showRevertSplitDialog = false; |
| | | await this.loadPalletData(); |
| | | } else { |
| | | this.$message.error(res.message || 'æ¤éæå
失败'); |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('æ¤éæå
失败'); |
| | | } finally { |
| | | this.revertSplitLoading = false; |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | }, |
| | | // æ¥æ¾å®æ´æå
é¾ï¼ä»æ ¹æ¡ç å¼å§ï¼ |
| | | 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 = "忝æå
é¾"; |
| | | } |
| | | |
| | | 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; |
| | | } |
| | | }, |
| | | |
| | | // å
³éæå
é¾ä¿¡æ¯å¼¹çª |
| | | 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 |
| | | } |
| | | ); |
| | | |
| | | // ç¨æ·ç¡®è®¤åæ§è¡åæ¶æä½ |
| | | 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; |
| | | } |
| | | }, |
| | | |
| | | // æ£æ¥æ¡ç æ¯å¦å·²è¢«åæ£ |
| | | hasPicked(barcode) { |
| | | return this.pickedList.some(item => item.currentBarcode === barcode); |
| | | }, |
| | | |
| | | // æ ¼å¼åæ¥ææ¶é´ |
| | | formatDateTime(dateTime) { |
| | | if (!dateTime) return ''; |
| | | const date = new Date(dateTime); |
| | | 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')}`; |
| | | }, |
| | | |
| | | // ååºç¸å
³æ¹æ³ |
| | | 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; |
| | | }, |
| | | |
| | | async handleBatchReturnConfirm() { |
| | | this.batchReturnLoading = true; |
| | | try { |
| | | const res = await http.post('/api/OutboundBatchPicking/return-stock', { |
| | | orderNo: this.scanData.orderNo, |
| | | palletCode: this.scanData.palletCode |
| | | }); |
| | | if (res.status) { |
| | | this.$message.success('ååºæå'); |
| | | this.showBatchReturnDialog = false; |
| | | await this.loadPalletData(); |
| | | } else { |
| | | this.$message.error(res.message || 'ååºå¤±è´¥'); |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('ååºå¤±è´¥'); |
| | | } finally { |
| | | this.batchReturnLoading = false; |
| | | } |
| | | }, |
| | | |
| | | // åç©ºç®±æ¹æ³ |
| | | handleEmptyPallet() { |
| | | this.showEmptyPalletDialog = true; |
| | | this.emptypalletOutForm.orderNo = this.scanData.orderNo; |
| | | this.emptypalletOutForm.palletCode = ''; |
| | | }, |
| | | |
| | | async handleEmptyPalletConfirm() { |
| | | this.emptypalletOutLoading = true; |
| | | try { |
| | | const res = await http.post('/api/OutboundBatchPicking/remove-empty-pallet', { |
| | | orderNo: this.emptypalletOutForm.orderNo, |
| | | palletCode: this.emptypalletOutForm.palletCode |
| | | }); |
| | | if (res.status) { |
| | | this.$message.success('å走空箱æå'); |
| | | this.showEmptyPalletDialog = false; |
| | | await this.loadPalletData(); |
| | | } else { |
| | | this.$message.error(res.message || 'å走空箱失败'); |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('å走空箱失败'); |
| | | } finally { |
| | | this.emptypalletOutLoading = false; |
| | | } |
| | | }, |
| | | |
| | | // æ°æ®å è½½æ¹æ³ |
| | | async loadPalletData() { |
| | | if (!this.scanData.orderNo || !this.scanData.palletCode) return; |
| | | |
| | | await this.loadUnpickedList(); |
| | | await this.loadPickedList(); |
| | | await this.loadPalletStatus(); |
| | | }, |
| | | |
| | | async loadUnpickedList() { |
| | | try { |
| | | const res = await http.post('/api/OutboundBatchPicking/pallet-locks', { |
| | | orderNo: this.scanData.orderNo, |
| | | palletCode: this.scanData.palletCode |
| | | }); |
| | | if (res.status) { |
| | | this.unpickedList = res.data || []; |
| | | this.summary.unpickedCount = this.unpickedList.length; |
| | | this.summary.unpickedQuantity = this.unpickedList.reduce((sum, item) => sum + (item.remainQuantity || 0), 0); |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('å è½½æªæ£éå表失败'); |
| | | } |
| | | }, |
| | | |
| | | async loadPickedList() { |
| | | try { |
| | | const res = await http.post('/api/OutboundBatchPicking/pallet-picked-list', { |
| | | orderNo: this.scanData.orderNo, |
| | | palletCode: this.scanData.palletCode |
| | | }); |
| | | if (res.status) { |
| | | this.pickedList = res.data || []; |
| | | this.summary.pickedCount = this.pickedList.length; |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('å 载已æ£éå表失败'); |
| | | } |
| | | }, |
| | | |
| | | async loadPalletStatus() { |
| | | try { |
| | | const res = await http.post('/api/OutboundBatchPicking/pallet-status', { |
| | | orderNo: this.scanData.orderNo, |
| | | palletCode: this.scanData.palletCode |
| | | }); |
| | | if (res.status) { |
| | | this.palletStatus = res.data.statusText || 'æªç¥'; |
| | | } |
| | | } catch (error) { |
| | | this.palletStatus = 'æªç¥'; |
| | | } |
| | | }, |
| | | |
| | | // æ«ç ç¸å
³æ¹æ³ |
| | | onPalletScan() { |
| | | this.scanData.palletCode = this.scanData.palletCode.replace(/\n/g, '').trim(); |
| | | if (!this.scanData.palletCode) return; |
| | | |
| | | this.loadPalletData(); |
| | | this.$nextTick(() => { |
| | | this.$refs.barcodeInput.focus(); |
| | | }); |
| | | }, |
| | | |
| | | onBarcodeScan() { |
| | | this.scanData.barcode = this.scanData.barcode.replace(/\n/g, '').trim(); |
| | | if (!this.scanData.barcode) return; |
| | | this.confirmPicking(); |
| | | }, |
| | | |
| | | focusBarcodeInput(selectText = false) { |
| | | this.$nextTick(() => { |
| | | const input = this.$refs.barcodeInput; |
| | | if (input && input.$el && input.$el.querySelector('input')) { |
| | | const inputEl = input.$el.querySelector('input'); |
| | | inputEl.focus(); |
| | | if (selectText) { |
| | | inputEl.select(); |
| | | } |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | handlePickedSelectionChange(selection) { |
| | | this.selectedPickedRows = selection; |
| | | }, |
| | | |
| | | async batchCancelSelected() { |
| | | if (this.selectedPickedRows.length === 0) { |
| | | this.$message.warning('请å
éæ©è¦åæ¶ç项'); |
| | | return; |
| | | } |
| | | |
| | | this.$confirm(`ç¡®å®è¦åæ¶éä¸ç ${this.selectedPickedRows.length} 项åï¼`, 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | }).then(async () => { |
| | | try { |
| | | for (const row of this.selectedPickedRows) { |
| | | try { |
| | | const res = await http.post('/api/OutboundBatchPicking/cancel-picking', { |
| | | orderNo: this.scanData.orderNo, |
| | | palletCode: this.scanData.palletCode, |
| | | barcode: row.currentBarcode |
| | | }); |
| | | if (!res.status) { |
| | | this.$message.warning(`åæ¶æ£é失败: ${row.currentBarcode} - ${res.message}`); |
| | | } |
| | | } catch (error) { |
| | | this.$message.warning(`åæ¶æ£é失败: ${row.currentBarcode} - ${error.message}`); |
| | | } |
| | | } |
| | | this.$message.success('æ¹é忶宿'); |
| | | await this.loadPalletData(); |
| | | this.selectedPickedRows = []; |
| | | } catch (error) { |
| | | this.$message.error('æ¹éåæ¶æä½å¤±è´¥'); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // éç½®æ¹æ³ |
| | | resetSplitForm() { |
| | | this.splitForm.originalBarcode = ''; |
| | | this.splitForm.materielCode = ''; |
| | | this.splitForm.splitQuantity = 0; |
| | | this.splitForm.maxQuantity = 0; |
| | | }, |
| | | |
| | | closeCustomSplitDialog() { |
| | | this.showCustomSplitDialog = false; |
| | | this.resetSplitForm(); |
| | | }, |
| | | |
| | | openRevertSplitDialog() { |
| | | this.showRevertSplitDialog = true; |
| | | this.revertSplitForm.newBarcode = ''; |
| | | }, |
| | | |
| | | closeRevertSplitDialog() { |
| | | this.showRevertSplitDialog = false; |
| | | this.revertSplitForm.newBarcode = ''; |
| | | }, |
| | | |
| | | closeBatchReturnDialog() { |
| | | this.showBatchReturnDialog = false; |
| | | }, |
| | | |
| | | onEmptyPalletScan() { |
| | | if (!this.emptypalletOutForm.palletCode) return; |
| | | this.emptypalletOutForm.palletCode = this.emptypalletOutForm.palletCode.replace(/\n/g, '').trim(); |
| | | }, |
| | | |
| | | closeEmptyPalletDialog() { |
| | | this.showEmptyPalletDialog = false; |
| | | this.emptypalletOutForm.palletCode = ''; |
| | | }, |
| | | |
| | | parentcall() { |
| | | // æå°åè° |
| | | } |
| | | } |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .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; |
| | | } |
| | | |
| | | /* èªå®ä¹å¼¹çªæ ·å¼ */ |
| | | :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; |
| | | 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; /* ä¿æä¸ä¸ªåçç z-index */ |
| | | } |
| | | |
| | | .custom-dialog-wrapper { |
| | | position: relative; |
| | | z-index: 2001; |
| | | } |
| | | |
| | | .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; |
| | | } |
| | | /* ç¡®ä¿ç¡®è®¤å¯¹è¯æ¡å¨æåé¢ */ |
| | | .el-message-box__wrapper { |
| | | z-index: 10001 !important; |
| | | } |
| | | |
| | | .el-message { |
| | | z-index: 10002 !important; |
| | | } |
| | | .scanner-form .el-input { |
| | | width: 100%; |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <el-button type="success" @click="confirmPicking">确认æ£é</el-button> |
| | | <!-- <el-button type="warning" @click="openSplitDialog">æå
</el-button> |
| | | <el-button type="info" @click="openRevertSplitDialog">æ¤éæå
</el-button> --> |
| | | |
| | | <el-button type="info" @click="handleEmptyPallet">å空箱</el-button> |
| | | <el-button type="primary" @click="openBatchReturnDialog">ååº</el-button> |
| | | <!-- <el-button type="danger" @click="handleDirectOutbound">ç´æ¥åºåº</el-button> --> |
| | | |
| | |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- å走空箱--> |
| | | <div v-if="showEmptyPalletDialog" class="custom-dialog-overlay"> |
| | | <div class="custom-dialog-wrapper"> |
| | | <div class="custom-dialog"> |
| | | <div class="custom-dialog-header"> |
| | | <h3>å走空箱</h3> |
| | | <el-button |
| | | type="text" |
| | | @click="closeEmptyPalletDialog" |
| | | class="close-button"> |
| | | Ã |
| | | </el-button> |
| | | </div> |
| | | <div class="custom-dialog-body"> |
| | | <el-form |
| | | :model="emptypalletOutForm" |
| | | :rules="emptypalletOutFormRules" |
| | | ref="emptypalletOutFormRef" |
| | | label-width="100px"> |
| | | <el-form-item label="订åç¼å·"> |
| | | <el-input v-model="emptypalletOutForm.orderNo" disabled></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="æçç¼å·" prop="palletCode"> |
| | | <el-input |
| | | v-model="emptypalletOutForm.palletCode" |
| | | placeholder="æ«ææçç " |
| | | @keyup.enter.native="onEmptyPalletScan" |
| | | @change="onEmptyPalletScan" |
| | | clearable> |
| | | </el-input> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | <div class="custom-dialog-footer"> |
| | | <el-button @click="closeEmptyPalletDialog">åæ¶</el-button> |
| | | <el-button type="primary" @click="handleEmptyPalletConfirm" :loading="emptypalletOutLoading">确认å走空箱</el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- ç´æ¥åºåºå¼¹çª --> |
| | | <div v-if="showDirectOutDialog" class="custom-dialog-overlay"> |
| | | <div class="custom-dialog-wrapper"> |
| | |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <print-view ref="childs" @parentcall="parentcall"></print-view> |
| | | </template> |
| | | |
| | |
| | | { required: true, validator: validateDirectOutPalletCode, trigger: 'blur' } |
| | | ] |
| | | }, |
| | | |
| | | showEmptyPalletDialog: false, // åèµ°ç©ºç®±å¼¹çªæ¾ç¤ºç¶æ |
| | | emptypalletOutLoading: false, // å走空箱å è½½ç¶æ |
| | | emptypalletOutForm: { |
| | | orderNo: '', |
| | | palletCode: '' |
| | | }, |
| | | emptypalletOutFormRules: { |
| | | palletCode: [ |
| | | { required: true, validator: validateDirectOutPalletCode, trigger: 'blur' } |
| | | ] |
| | | }, |
| | | |
| | | |
| | | returnForm: { |
| | | orderNo: '', |
| | | palletCode: '', |
| | |
| | | }); |
| | | |
| | | if (res.status) { |
| | | this.$message.success('ååºæå'); |
| | | this.$message.success(res.message); |
| | | this.showBatchReturnDialog = false; |
| | | this.loadData(); |
| | | } else { |
| | |
| | | handleDirectOutbound() { |
| | | this.openDirectOutDialog(); |
| | | }, |
| | | |
| | | // æå¼åèµ°ç©ºç®±å¼¹çª |
| | | openEmptyPalletDialog() { |
| | | console.log('æå¼å走空箱弹çª'); |
| | | this.showEmptyPalletDialog = true; |
| | | |
| | | // é置表å |
| | | this.resetEmptyPalletForm(); |
| | | |
| | | // 设置订åä¿¡æ¯ |
| | | this.emptypalletOutForm.orderNo = this.scanData.orderNo; |
| | | |
| | | // æ¸
é¤è¡¨åéªè¯ |
| | | this.$nextTick(() => { |
| | | if (this.$refs.emptyPalletFormRef) { |
| | | this.$refs.emptyPalletFormRef.clearValidate(); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // å
³éåèµ°ç©ºç®±å¼¹çª |
| | | closeEmptyPalletDialog() { |
| | | this.showEmptyPalletDialog = false; |
| | | this.resetEmptyPalletForm(); |
| | | |
| | | // æ¸
é¤è¡¨åéªè¯ |
| | | if (this.$refs.emptyPalletFormRef) { |
| | | this.$refs.emptyPalletFormRef.clearValidate(); |
| | | } |
| | | }, |
| | | |
| | | // å走空箱æçç æ«ç |
| | | onEmptyPalletScan() { |
| | | if (!this.emptypalletOutForm.palletCode) return; |
| | | |
| | | this.emptypalletOutForm.palletCode = this.emptypalletOutForm.palletCode.replace(/\n/g, '').trim(); |
| | | |
| | | // æ¸
é¤éªè¯ç¶æ |
| | | if (this.$refs.emptyPalletFormRef) { |
| | | this.$refs.emptyPalletFormRef.clearValidate(['palletCode']); |
| | | } |
| | | }, |
| | | |
| | | // å走空箱确认 |
| | | async handleEmptyPalletConfirm() { |
| | | // 表åéªè¯ |
| | | if (this.$refs.emptyPalletFormRef) { |
| | | this.$refs.emptyPalletFormRef.validate((valid) => { |
| | | if (valid) { |
| | | this.submitEmptyPallet(); |
| | | } else { |
| | | this.$message.warning('è¯·æ«ææçç '); |
| | | return false; |
| | | } |
| | | }); |
| | | } else { |
| | | // å¦ææ²¡æè¡¨åå¼ç¨ï¼ä½¿ç¨åæçéªè¯ |
| | | if (!this.emptypalletOutForm.palletCode) { |
| | | this.$message.warning('è¯·æ«ææçç '); |
| | | return; |
| | | } |
| | | |
| | | this.submitEmptyPallet(); |
| | | } |
| | | }, |
| | | |
| | | // æäº¤åèµ°ç©ºç®±è¯·æ± |
| | | async submitEmptyPallet() { |
| | | this.emptypalletOutLoading = true; |
| | | |
| | | try { |
| | | const res = await this.http.post('/api/OutboundPicking/remove-empty-pallet', { |
| | | orderNo: this.emptypalletOutForm.orderNo, |
| | | palletCode: this.emptypalletOutForm.palletCode |
| | | }); |
| | | debugger; |
| | | if (res.status) { |
| | | this.$message.success('å走空箱æå'); |
| | | this.showEmptyPalletDialog = false; |
| | | this.loadData(); |
| | | } else { |
| | | this.$message.error(res.message || 'å走空箱失败'); |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('å走空箱失败'); |
| | | } finally { |
| | | this.emptypalletOutLoading = false; |
| | | } |
| | | }, |
| | | |
| | | // éç½®å走空箱表å |
| | | resetEmptyPalletForm() { |
| | | this.emptypalletOutForm.palletCode = ''; |
| | | }, |
| | | |
| | | // ä¿®æ¹åæçå走空箱æé®ç¹å»äºä»¶ |
| | | handleEmptyPallet() { |
| | | this.openEmptyPalletDialog(); |
| | | }, |
| | | |
| | | |
| | | |
| | | |
| | | async loadData() { |
| | | if (!this.scanData.orderNo || !this.scanData.palletCode) { |
| | | return; |
| | |
| | | |
| | | if (res.status) { |
| | | successCount++; |
| | | this.$message.success(`æååæ¶`); |
| | | } else { |
| | | errorCount++; |
| | | console.error(`åæ¶æ£é失败: ${row.Barcode}`, res.message); |
| | | this.$message.warning(`åæ¶æ£é失败: ${row.currentBarcode} - ${res.message}`); |
| | | } |
| | | } catch (error) { |
| | | errorCount++; |
| | | console.error(`åæ¶æ£é失败: ${row.Barcode}`, error); |
| | | this.$message.warning(`åæ¶æ£é失败: ${row.currentBarcode} - ${error.message}` ); |
| | | } |
| | | } |
| | | |
| | | if (errorCount === 0) { |
| | | this.$message.success(`æååæ¶ ${successCount} 项`); |
| | | } else { |
| | | this.$message.warning(`æååæ¶ ${successCount} 项ï¼å¤±è´¥ ${errorCount} 项`); |
| | | } |
| | | } |
| | | |
| | | this.loadData(); |
| | | this.selectedPickedRows = []; |
| | |
| | | const table = ref({ |
| | | key: "id", |
| | | footer: "Foots", |
| | | cnName: "è°æ¨å(å¤é¨ä»åºè°æºä»)", |
| | | cnName: "è°æ¨å(æºä»è°åºå¤é¨ä»)", |
| | | name: "outboundOrder", |
| | | url: "/OutboundOrder/", |
| | | sortName: "id", |
| | |
| | | type: "select", |
| | | dataKey: "outOrderType", |
| | | data: [], |
| | | hidden:true |
| | | }, |
| | | { |
| | | title: "åæ®ç¶æ", |
| | |
| | | width: 150, |
| | | align: "left", |
| | | bind: { key: "outOrderType", data: [] }, |
| | | hidden:true |
| | | }, |
| | | { |
| | | field: "businessType", |
| | |
| | | }); |
| | | const searchFormOptions = ref([ |
| | | [ |
| | | { title: "è´§ä½å·", field: "locationCode" }, |
| | | { title: "åæ®ç¼å·", field: "orderNo" }, |
| | | { title: "ä»»å¡å·", field: "taskNum" }, |
| | | { title: "è´§ä½å·", field: "locationCode" ,type:"like"}, |
| | | { title: "åæ®ç¼å·", field: "orderNo",type:"like"}, |
| | | { title: "ä»»å¡å·", field: "taskNum" ,type:"like"}, |
| | | ], |
| | | [ |
| | | { |
| | |
| | | }); |
| | | const searchFormOptions = ref([ |
| | | [ |
| | | { title: "æçå·", field: "palleCode" }, |
| | | { title: "ç©æç¼å·", field: "materielCode" }, |
| | | { title: "åæ®ç¼å·", field: "orderNo" }, |
| | | { title: "æçå·", field: "palleCode" ,type:"like"}, |
| | | { title: "ç©æç¼å·", field: "materielCode",type:"like" }, |
| | | { title: "åæ®ç¼å·", field: "orderNo" ,type:"like"}, |
| | | { title: "åå¨ç±»å", field: "changeType" ,type: "selectList",dataKey: "stockChangeType",data: [],}, |
| | | ], |
| | | [ |
| | | { title: "æ¹æ¬¡å·", field: "batchNo" }, |
| | | { title: "ä»»å¡å·", field: "taskNum" }, |
| | | { title: "åºåå·", field: "serilNumber" }, |
| | | { title: "æ¹æ¬¡å·", field: "batchNo" ,type:"like"}, |
| | | { title: "ä»»å¡å·", field: "taskNum" ,type:"like"}, |
| | | { title: "åºåå·", field: "serilNumber" ,type:"like"}, |
| | | ], |
| | | ]); |
| | | const columns = ref([ |
| | |
| | | align: "left", |
| | | }, |
| | | { |
| | | field: "barcode", |
| | | title: "æ¡ç ", |
| | | type: "string", |
| | | width: 150, |
| | | align: "left", |
| | | }, |
| | | { |
| | | field: "batchNo", |
| | | title: "æ¹æ¬¡å·", |
| | | type: "string", |
| | |
| | | width: 100, |
| | | align: "left", |
| | | bind: { key: "warehouses", data: [] }, |
| | | hidden:true |
| | | }, |
| | | { |
| | | field: "creater", |
| | |
| | | type: "string", |
| | | width: 100, |
| | | align: "left", |
| | | hidden:true |
| | | // hidden:true |
| | | }, |
| | | { |
| | | field: "modifyDate", |
| | |
| | | type: "datetime", |
| | | width: 160, |
| | | align: "left", |
| | | hidden:true |
| | | // hidden:true |
| | | }, |
| | | { |
| | | field: "remark", |
| | |
| | | using Microsoft.Extensions.Logging; |
| | | using Autofac.Core; |
| | | using MailKit.Search; |
| | | using Microsoft.Extensions.Logging; |
| | | using SqlSugar; |
| | | using SqlSugar.Extensions; |
| | | using System; |
| | |
| | | { |
| | | 1 => await AddAllocateOrder(allocateOrder), |
| | | 2 => await UpdateAllocateOrder(allocateOrder), |
| | | 3 => DeleteAllocateOrder(allocateOrder), |
| | | 3 => await DeleteAllocateOrder(allocateOrder), |
| | | |
| | | _ => WebResponseContent.Instance.OK(), |
| | | }; |
| | |
| | | } |
| | | allocateOrder.OrderNo = CreateCodeByRule(nameof(RuleCodeEnum.AllocateOrderCodeRule)); |
| | | Db.InsertNav(allocateOrder).Include(x => x.Details).ExecuteCommand(); |
| | | if (Enum.TryParse<BusinessTypeEnum>(allocateOrder.BusinessType, out var businessType)) |
| | | { |
| | | if (businessType == BusinessTypeEnum.æºä»è°å¤é¨ä»åº) |
| | | { |
| | | var inboundOrders = ConvertToInboundOrders(allocateOrder); |
| | | await _inboundService.InbounOrderService.ReceiveInboundOrder(inboundOrders, 1); |
| | | } |
| | | else if (businessType == BusinessTypeEnum.å¤é¨ä»åºè°æºä») |
| | | { |
| | | var outboundOrders = ConvertToOutboundOrders(allocateOrder); |
| | | await _outboundService.OutboundOrderService.ReceiveOutboundOrder(outboundOrders, 1); |
| | | } |
| | | else |
| | | { |
| | | // å¤çæªå®ä¹çæä¸¾å¼ï¼å¦æªæ¥æ°å¢ä½æªå®ç°çç±»åï¼ |
| | | throw new NotSupportedException($"䏿¯æçä¸å¡ç±»åæä¸¾å¼: {businessType}"); |
| | | } |
| | | } |
| | | await AddInOutData(allocateOrder); |
| | | return WebResponseContent.Instance.OK(); |
| | | } |
| | | catch (Exception ex) |
| | |
| | | return WebResponseContent.Instance.Error(ex.Message); |
| | | } |
| | | } |
| | | |
| | | private async Task AddInOutData(Dt_AllocateOrder allocateOrder) |
| | | { |
| | | if (Enum.TryParse<BusinessTypeEnum>(allocateOrder.BusinessType, out var businessType)) |
| | | { |
| | | if (businessType == BusinessTypeEnum.å¤é¨ä»åºè°æºä») |
| | | { |
| | | allocateOrder.OrderType = InOrderTypeEnum.AllocatInbound.ObjToInt(); |
| | | var inboundOrders = ConvertToInboundOrders(allocateOrder); |
| | | await _inboundService.InbounOrderService.ReceiveInboundOrder(inboundOrders, 1); |
| | | } |
| | | else if (businessType == BusinessTypeEnum.æºä»è°å¤é¨ä»åº || businessType == BusinessTypeEnum.æºä»è°æºä») |
| | | { |
| | | if (businessType == BusinessTypeEnum.æºä»è°å¤é¨ä»åº) |
| | | { |
| | | allocateOrder.OrderType = InOrderTypeEnum.AllocatOutbound.ObjToInt(); |
| | | } |
| | | else if (businessType == BusinessTypeEnum.æºä»è°æºä») |
| | | { |
| | | allocateOrder.OrderType = InOrderTypeEnum.InternalAllocat.ObjToInt(); |
| | | } |
| | | |
| | | var outboundOrders = ConvertToOutboundOrders(allocateOrder); |
| | | await _outboundService.OutboundOrderService.ReceiveOutboundOrder(outboundOrders, 1); |
| | | } |
| | | else |
| | | { |
| | | // å¤çæªå®ä¹çæä¸¾å¼ï¼å¦æªæ¥æ°å¢ä½æªå®ç°çç±»åï¼ |
| | | throw new NotSupportedException($"䏿¯æçä¸å¡ç±»åæä¸¾å¼: {businessType}"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | public async Task<WebResponseContent> UpdateAllocateOrder(Dt_AllocateOrder model) |
| | | { |
| | | try |
| | |
| | | _unitOfWorkManage.BeginTran(); |
| | | foreach (var item in deletePurchaseOrderDetails) |
| | | { |
| | | // _allocateOrderDetailRepository.DeleteAndMoveIntoHty(item, OperateTypeEnum.èªå¨å é¤); |
| | | // _allocateOrderDetailRepository.DeleteAndMoveIntoHty(item, OperateTypeEnum.èªå¨å é¤); |
| | | _allocateOrderDetailRepository.DeleteData(item); |
| | | } |
| | | |
| | |
| | | _allocateOrderDetailRepository.AddData(allocateOrderDetails); |
| | | |
| | | BaseDal.UpdateData(allocateOrder); |
| | | |
| | | DeleteInOutData(model.UpperOrderNo, allocateOrder); |
| | | await AddInOutData(allocateOrder); |
| | | |
| | | _unitOfWorkManage.CommitTran(); |
| | | |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | public WebResponseContent DeleteAllocateOrder(Dt_AllocateOrder model) |
| | | public async Task<WebResponseContent> DeleteAllocateOrder(Dt_AllocateOrder model) |
| | | { |
| | | try |
| | | { |
| | |
| | | _allocateOrderDetailRepository.DeleteData(item); |
| | | } |
| | | BaseDal.DeleteData(allocateOrder); |
| | | |
| | | DeleteInOutData(model.UpperOrderNo, allocateOrder); |
| | | |
| | | _unitOfWorkManage.CommitTran(); |
| | | return WebResponseContent.Instance.OK(); |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | private void DeleteInOutData(string upperOrderNo, Dt_AllocateOrder allocateOrder) |
| | | { |
| | | if (Enum.TryParse<BusinessTypeEnum>(allocateOrder.BusinessType, out var businessType)) |
| | | { |
| | | if (businessType == BusinessTypeEnum.å¤é¨ä»åºè°æºä») |
| | | { |
| | | _inboundService.InbounOrderService.Db.Deleteable<Dt_InboundOrder>().Where(x => x.UpperOrderNo == upperOrderNo).ExecuteCommand(); |
| | | |
| | | _inboundService.InboundOrderDetailService.Db.Deleteable<Dt_InboundOrderDetail>() |
| | | .Where(p => SqlFunc.Subqueryable<Dt_InboundOrder>().Where(s => s.Id == p.OrderId && s.UpperOrderNo == upperOrderNo).Any()).ExecuteCommand(); |
| | | } |
| | | else if (businessType == BusinessTypeEnum.æºä»è°å¤é¨ä»åº || businessType == BusinessTypeEnum.æºä»è°æºä») |
| | | { |
| | | _outboundService.OutboundOrderService.Db.Deleteable<Dt_OutboundOrder>().Where(x => x.UpperOrderNo == upperOrderNo).ExecuteCommand(); |
| | | _outboundService.OutboundOrderDetailService.Db.Deleteable<Dt_OutboundOrderDetail>() |
| | | .Where(p => SqlFunc.Subqueryable<Dt_OutboundOrder>().Where(s => s.Id == p.OrderId && s.UpperOrderNo == upperOrderNo).Any()).ExecuteCommand(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | public List<Dt_InboundOrder> ConvertToInboundOrders(Dt_AllocateOrder allocateOrder) |
| | | { |
| | | var distinctDetails = allocateOrder.Details |
| | | .GroupBy(d => d.Barcode) |
| | | .Select(g => g.First()) |
| | | .ToList(); |
| | | |
| | | return new List<Dt_InboundOrder>() |
| | | { |
| | | new Dt_InboundOrder(){ |
| | |
| | | InboundOrderNo=allocateOrder.OrderNo, |
| | | UpperOrderNo=allocateOrder.UpperOrderNo, |
| | | SupplierId=allocateOrder.SupplierId, |
| | | OrderType=InOrderTypeEnum.Allocat.ObjToInt(), |
| | | OrderType= allocateOrder.OrderType , |
| | | OrderStatus=allocateOrder.OrderStatus, |
| | | CreateType=allocateOrder.CreateType, |
| | | BusinessType=allocateOrder.BusinessType, |
| | | IsBatch=allocateOrder.IsBatch, |
| | | FactoryArea=allocateOrder.FactoryArea, |
| | | Remark=allocateOrder.Remark, |
| | | Details=allocateOrder.Details.Select(detail=>new Dt_InboundOrderDetail |
| | | Details=distinctDetails.Select(detail=>new Dt_InboundOrderDetail |
| | | { |
| | | OrderId= detail.OrderId, |
| | | OrderId= 0, |
| | | MaterielCode=detail.MaterielCode, |
| | | MaterielName="", |
| | | BatchNo=detail.BatchNo, |
| | |
| | | OrderDetailStatus=detail.OrderDetailStatus, |
| | | Unit=detail.Unit, |
| | | RowNo=0, |
| | | lineNo=detail.LineNo, |
| | | SupplyCode=detail.SupplyCode, |
| | | WarehouseCode=detail.WarehouseCode, |
| | | Barcode=detail.Barcode, |
| | |
| | | |
| | | public Dt_OutboundOrder ConvertToOutboundOrders(Dt_AllocateOrder allocateOrder) |
| | | { |
| | | |
| | | var distinctDetails = allocateOrder.Details |
| | | .GroupBy(d => string.IsNullOrEmpty(d.Barcode) |
| | | ? $"{d.MaterielCode}_{d.BatchNo}_{d.SupplyCode}_{d.WarehouseCode}" |
| | | : d.Barcode) |
| | | .Select(g => new |
| | | { |
| | | Detail = g.First(), |
| | | //æ±æ»åç»å
çæ°é |
| | | Qty = g.Sum(x => x.BarcodeQty ?? x.OrderQuantity) |
| | | }).ToList(); |
| | | |
| | | return new Dt_OutboundOrder() |
| | | { |
| | | WarehouseId = allocateOrder.WarehouseId, |
| | | OrderNo = allocateOrder.OrderNo, |
| | | UpperOrderNo = allocateOrder.UpperOrderNo, |
| | | OrderType = OutOrderTypeEnum.Allocate.ObjToInt(), |
| | | OrderType = allocateOrder.OrderType, |
| | | OrderStatus = allocateOrder.OrderStatus, |
| | | CreateType = allocateOrder.CreateType, |
| | | BusinessType = allocateOrder.BusinessType, |
| | |
| | | Remark = allocateOrder.Remark, |
| | | DepartmentCode = "", |
| | | DepartmentName = "", |
| | | Details = allocateOrder.Details.Select(detail => new Dt_OutboundOrderDetail |
| | | Details = distinctDetails.Select(item => new Dt_OutboundOrderDetail |
| | | { |
| | | OrderId = detail.OrderId, |
| | | MaterielCode = detail.MaterielCode, |
| | | OrderId = 0, |
| | | MaterielCode = item.Detail.MaterielCode, |
| | | MaterielName = "", |
| | | BatchNo = detail.BatchNo, |
| | | OrderQuantity = detail.OrderQuantity, |
| | | BatchNo = item.Detail.BatchNo, |
| | | OrderQuantity = item.Detail.OrderQuantity, |
| | | BarcodeQty = (decimal)item.Detail.BarcodeQty, |
| | | BarcodeUnit = item.Detail.BarcodeUnit, |
| | | LockQuantity = 0, |
| | | lineNo = item.Detail.LineNo, |
| | | OverOutQuantity = 0, |
| | | OrderDetailStatus = detail.OrderDetailStatus, |
| | | Unit = detail.Unit, |
| | | OrderDetailStatus = item.Detail.OrderDetailStatus, |
| | | Unit = item.Detail.Unit, |
| | | RowNo = 0, |
| | | SupplyCode = detail.SupplyCode, |
| | | WarehouseCode = detail.WarehouseCode, |
| | | SupplyCode = item.Detail.SupplyCode, |
| | | WarehouseCode = item.Detail.WarehouseCode, |
| | | |
| | | }).ToList() |
| | | }; |
| | |
| | | using System.Threading.Tasks; |
| | | using WIDESEA_Core.BaseRepository; |
| | | using WIDESEA_Core.BaseServices; |
| | | using WIDESEA_Core.Seed; |
| | | using WIDESEA_IBasicService; |
| | | using WIDESEA_Model.Models; |
| | | using WIDESEA_Model.Models.Basic; |
| | |
| | | |
| | | private async Task UpdateSequenceInDatabase(DateTime date, string sequenceKey, int value) |
| | | { |
| | | var sequence = await Repository.Db.Queryable<DT_DailySequence>() |
| | | .Where(x => x.SequenceDate == date && x.SequenceKey == sequenceKey) |
| | | .FirstAsync(); |
| | | |
| | | if (sequence != null) |
| | | try |
| | | { |
| | | sequence.CurrentValue = value; |
| | | |
| | | await Repository.Db.Updateable(sequence).ExecuteCommandAsync(); |
| | | } |
| | | else |
| | | { |
| | | // å¦ææ°æ®åºè®°å½ä¸åå¨ï¼åå建 |
| | | sequence = new DT_DailySequence |
| | | using SqlSugarClient sugarClient = new SqlSugarClient(new ConnectionConfig |
| | | { |
| | | SequenceDate = date, |
| | | SequenceKey = sequenceKey, |
| | | CurrentValue = value, |
| | | IsAutoCloseConnection = true, |
| | | DbType = DbType.SqlServer, |
| | | ConnectionString = DBContext.ConnectionString |
| | | }); |
| | | var result = await sugarClient.Updateable<DT_DailySequence>() |
| | | .SetColumns(it => new DT_DailySequence() |
| | | { |
| | | CurrentValue = value, |
| | | }) |
| | | .Where(it => it.SequenceDate == date && it.SequenceKey == sequenceKey) |
| | | .ExecuteCommandAsync(); |
| | | |
| | | }; |
| | | await Repository.Db.Insertable(sequence).ExecuteCommandAsync(); |
| | | if (result == 0) |
| | | { |
| | | // å¦ææ²¡ææ´æ°å°è®°å½ï¼å¯è½æ¯é¦æ¬¡ä½¿ç¨ï¼æå
¥æ°è®°å½ |
| | | var newSequence = new DT_DailySequence |
| | | { |
| | | SequenceKey = sequenceKey, |
| | | SequenceDate = date, |
| | | CurrentValue = value, |
| | | Creater="admin", |
| | | CreateDate=DateTime.Now, |
| | | }; |
| | | await sugarClient.Insertable(newSequence).ExecuteCommandAsync(); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | // è®°å½æ¥å¿å¹¶éæ°æåºå¼å¸¸ |
| | | Console.WriteLine($"æ´æ°åºå失败: {ex.Message}"); |
| | | throw; |
| | | } |
| | | |
| | | } |
| | | |
| | | public async Task CleanOldSequencesAsync(int keepDays = 30) |
| | |
| | | using System.Security.Policy; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | using WIDESEA_Common.OrderEnum; |
| | | using WIDESEA_Common.StockEnum; |
| | | using WIDESEA_Core; |
| | | using WIDESEA_Core.BaseRepository; |
| | | using WIDESEA_DTO.Allocate; |
| | |
| | | using WIDESEA_DTO.Inbound; |
| | | using WIDESEA_DTO.Outbound; |
| | | using WIDESEA_IBasicService; |
| | | using WIDESEA_IOutboundService; |
| | | using WIDESEA_Model.Models; |
| | | |
| | | namespace WIDESEA_BasicService |
| | |
| | | private readonly IRepository<Dt_StockInfoDetail> _stockInfoDetailRepository; |
| | | private readonly IRepository<Dt_StockInfo> _stockInfoRepository; |
| | | private readonly IRepository<Dt_InboundOrder> _inboundOrderRepository; |
| | | public InvokeMESService(IHttpClientFactory httpClientFactory, ILogger<InvokeMESService> logger, IRepository<Dt_FeedbackToMes> feedbacktomesRepository, IRepository<Dt_StockInfoDetail> stockInfoDetailRepository, IRepository<Dt_StockInfo> stockInfoRepository, IRepository<Dt_InboundOrder> inboundOrderRepository) |
| | | |
| | | 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) |
| | | { |
| | | _httpClientFactory = httpClientFactory; |
| | | _logger = logger; |
| | |
| | | _stockInfoDetailRepository = stockInfoDetailRepository; |
| | | _stockInfoRepository = stockInfoRepository; |
| | | _inboundOrderRepository = inboundOrderRepository; |
| | | _outboundOrderService = outboundOrderService; |
| | | _outboundOrderDetailService = outboundOrderDetailService; |
| | | _outStockLockInfoService = outStockLockInfoService; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | /// <exception cref="HttpRequestException"></exception> |
| | | public async Task<ResponseModel> FeedbackInbound(FeedbackInboundRequestModel model) |
| | | { |
| | | string json =JsonConvert.SerializeObject(model, new JsonSerializerSettings |
| | | { |
| | | string json = JsonConvert.SerializeObject(model, new JsonSerializerSettings |
| | | { |
| | | ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver() |
| | | }); |
| | | var content = new StringContent(json, Encoding.UTF8, "application/json"); |
| | |
| | | |
| | | return JsonConvert.DeserializeObject<ResponseModel>(body); |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// åºåºåé¦ |
| | | /// </summary> |
| | |
| | | .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 (unreports != null && !unreports.Any()) |
| | | { |
| | | return WebResponseContent.Instance.Error("没æéè¦åä¼ çæ°æ®"); |
| | | } |
| | | foreach (var item in unreports) |
| | |
| | | reqTime = DateTime.Now.ToString(), |
| | | business_type = inboundOrder.BusinessType, |
| | | factoryArea = inboundOrder.FactoryArea, |
| | | operationType=1, |
| | | Operator= inboundOrder.Operator, |
| | | 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 |
| | | { |
| | |
| | | supplyCode = group.Key.SupplyCode, |
| | | batchNo = group.Key.BatchNo, |
| | | lineNo = group.Key.InboundOrderRowNo, |
| | | qty = group.Sum(x=>x.BarcodeQty), |
| | | qty = group.Sum(x => x.BarcodeQty), |
| | | // warehouseCode = group.Key.WarehouseCode=="0"?"1072": group.Key.WarehouseCode, |
| | | warehouseCode =group.Key.WarehouseCode, |
| | | warehouseCode = group.Key.WarehouseCode, |
| | | unit = group.Key.BarcodeUnit, |
| | | barcodes = group.Select(row => new FeedbackBarcodesModel |
| | | { |
| | |
| | | |
| | | } |
| | | } |
| | | else if (inout == 2) |
| | | { |
| | | foreach (var orderNo in orderNos) |
| | | { |
| | | var outboundOrder = await _outboundOrderService.Db.Queryable<Dt_OutboundOrder>().FirstAsync(x => x.OrderNo == orderNo); |
| | | if (outboundOrder != null && outboundOrder.IsBatch == 0) |
| | | { |
| | | await HandleOutboundOrderToMESCompletion(outboundOrder, orderNo); |
| | | } |
| | | else if (outboundOrder != null && outboundOrder.IsBatch == 1) |
| | | { |
| | | await HandleOutboundOrderBatchToMESCompletion(outboundOrder, orderNo); |
| | | } |
| | | } |
| | | |
| | | } |
| | | return WebResponseContent.Instance.OK(); |
| | | } |
| | | private async Task HandleOutboundOrderBatchToMESCompletion(Dt_OutboundOrder outboundOrder, string orderNo) |
| | | { |
| | | |
| | | try |
| | | { |
| | | if (outboundOrder.ReturnToMESStatus == 1) |
| | | { |
| | | return; |
| | | } |
| | | var orderDetails = 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 detailids = new List<int>(); |
| | | var allCompleted = true; |
| | | foreach (var detail in orderDetails.Where(x => x.ReturnToMESStatus == 0).ToList()) |
| | | { |
| | | if (detail.OverOutQuantity >= detail.NeedOutQuantity) |
| | | { |
| | | detailids.Add(detail.Id); |
| | | } |
| | | else |
| | | { |
| | | allCompleted = false; |
| | | } |
| | | } |
| | | if (orderDetails.Any(x => x.ReturnToMESStatus == 2)) |
| | | { |
| | | allCompleted = false; |
| | | } |
| | | |
| | | int newStatus = allCompleted ? (int)OutOrderStatusEnum.åºåºå®æ : (int)OutOrderStatusEnum.åºåºä¸; |
| | | |
| | | if (outboundOrder.OrderStatus != newStatus) |
| | | { |
| | | await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>() |
| | | .SetColumns(x => x.OrderStatus == newStatus) |
| | | .Where(x => x.OrderNo == orderNo) |
| | | .ExecuteCommandAsync(); |
| | | |
| | | } |
| | | var documentno = UniqueValueGenerator.Generate(); |
| | | 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, |
| | | orderNo = outboundOrder.UpperOrderNo, |
| | | documentsNO = documentno, |
| | | status = outboundOrder.OrderStatus, |
| | | details = new List<FeedbackOutboundDetailsModel>() |
| | | }; |
| | | |
| | | |
| | | foreach (var detail in orderDetails.Where(x => detailids.Contains(x.Id)).ToList()) |
| | | { |
| | | // è·å该æç»å¯¹åºçæ¡ç ä¿¡æ¯ï¼ä»éå®è®°å½ï¼ |
| | | var detailLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.OrderNo == orderNo && detailids.Contains(x.OrderDetailId) && |
| | | x.Status == (int)OutLockStockStatusEnum.æ£é宿) |
| | | .ToListAsync(); |
| | | |
| | | var detailModel = new FeedbackOutboundDetailsModel |
| | | { |
| | | materialCode = detail.MaterielCode, |
| | | lineNo = detail.lineNo, // 注æï¼è¿éå¯è½éè¦è°æ´å段å |
| | | warehouseCode = detail.WarehouseCode, |
| | | qty = detail.OverOutQuantity, // 使ç¨è®¢åæç»çå·²åºåºæ°é |
| | | currentDeliveryQty = detail.OverOutQuantity, |
| | | unit = detail.Unit, |
| | | barcodes = detailLocks.Select(lockInfo => new WIDESEA_DTO.Outbound.BarcodesModel |
| | | { |
| | | barcode = lockInfo.CurrentBarcode, |
| | | supplyCode = lockInfo.SupplyCode, |
| | | batchNo = lockInfo.BatchNo, |
| | | unit = lockInfo.Unit, |
| | | qty = lockInfo.PickedQty // æ¡ç 级å«çæ°éä»ç¨éå®è®°å½ |
| | | }).ToList() |
| | | }; |
| | | |
| | | feedmodel.details.Add(detailModel); |
| | | } |
| | | |
| | | var result = await FeedbackOutbound(feedmodel); |
| | | if (result != null && result.code == 200) |
| | | { |
| | | |
| | | 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 => x.ReturnToMESStatus == 1) |
| | | .Where(x => x.OrderNo == orderNo) |
| | | .ExecuteCommandAsync(); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>() |
| | | .SetColumns(it => new Dt_OutboundOrderDetail |
| | | { |
| | | ReturnToMESStatus = 2, |
| | | documentsNO = documentno, |
| | | }) |
| | | .Where(x => detailids.Contains(x.Id)) |
| | | .ExecuteCommandAsync(); |
| | | } |
| | | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _logger.LogError($"CheckAndUpdateOrderStatus失败 - OrderNo: {orderNo}, Error: {ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | |
| | | private async Task HandleOutboundOrderToMESCompletion(Dt_OutboundOrder outboundOrder, string orderNo) |
| | | { |
| | | |
| | | try |
| | | { |
| | | if (outboundOrder.ReturnToMESStatus == 1) |
| | | { |
| | | return; |
| | | } |
| | | var orderDetails = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | .LeftJoin<Dt_OutboundOrder>((o, item) => o.OrderId == item.Id) |
| | | .Where((o, item) => item.OrderNo == orderNo) |
| | | .Select((o, item) => o) |
| | | .ToListAsync(); |
| | | |
| | | bool allCompleted = true; |
| | | foreach (var detail in orderDetails) |
| | | { |
| | | if (detail.OverOutQuantity < detail.NeedOutQuantity) |
| | | { |
| | | allCompleted = false; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | int newStatus = allCompleted ? (int)OutOrderStatusEnum.åºåºå®æ : (int)OutOrderStatusEnum.åºåºä¸; |
| | | |
| | | if (outboundOrder.OrderStatus != newStatus) |
| | | { |
| | | await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>() |
| | | .SetColumns(x => x.OrderStatus == newStatus) |
| | | .Where(x => x.OrderNo == orderNo) |
| | | .ExecuteCommandAsync(); |
| | | |
| | | } |
| | | //åªææ£å¸¸åæ£å®ææ¶æåMESåé¦ |
| | | if (allCompleted && newStatus == (int)OutOrderStatusEnum.åºåºå®æ) |
| | | { |
| | | 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, |
| | | orderNo = outboundOrder.UpperOrderNo, |
| | | documentsNO = outboundOrder.OrderNo, |
| | | status = outboundOrder.OrderStatus, |
| | | details = new List<FeedbackOutboundDetailsModel>() |
| | | }; |
| | | |
| | | |
| | | foreach (var detail in orderDetails) |
| | | { |
| | | // è·å该æç»å¯¹åºçæ¡ç ä¿¡æ¯ï¼ä»éå®è®°å½ï¼ |
| | | var detailLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.OrderNo == orderNo && |
| | | x.OrderDetailId == detail.Id && |
| | | x.Status == (int)OutLockStockStatusEnum.æ£é宿) |
| | | .ToListAsync(); |
| | | |
| | | var detailModel = new FeedbackOutboundDetailsModel |
| | | { |
| | | materialCode = detail.MaterielCode, |
| | | lineNo = detail.lineNo, // 注æï¼è¿éå¯è½éè¦è°æ´å段å |
| | | warehouseCode = detail.WarehouseCode, |
| | | qty = detail.OverOutQuantity, // 使ç¨è®¢åæç»çå·²åºåºæ°é |
| | | currentDeliveryQty = detail.OverOutQuantity, |
| | | unit = detail.Unit, |
| | | barcodes = detailLocks.Select(lockInfo => new WIDESEA_DTO.Outbound.BarcodesModel |
| | | { |
| | | barcode = lockInfo.CurrentBarcode, |
| | | supplyCode = lockInfo.SupplyCode, |
| | | batchNo = lockInfo.BatchNo, |
| | | unit = lockInfo.Unit, |
| | | qty = lockInfo.PickedQty // æ¡ç 级å«çæ°éä»ç¨éå®è®°å½ |
| | | }).ToList() |
| | | }; |
| | | |
| | | feedmodel.details.Add(detailModel); |
| | | } |
| | | |
| | | var result = await FeedbackOutbound(feedmodel); |
| | | 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) |
| | | .Where(x => x.OrderNo == orderNo) |
| | | .ExecuteCommandAsync(); |
| | | } |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _logger.LogError($"CheckAndUpdateOrderStatus失败 - OrderNo: {orderNo}, Error: {ex.Message}"); |
| | | } |
| | | |
| | | } |
| | | |
| | | } |
| | | |
| | | public static class UniqueValueGenerator |
| | | { |
| | | // åå计æ°å¨ï¼çº¿ç¨å®å
¨ï¼æ¯æ¬¡éå¢1ï¼é¿å
åä¸Tickséå¤ï¼ |
| | | private static long _counter = 0; |
| | | |
| | | /// <summary> |
| | | /// çæå¯ä¸å¼ï¼æ¯æé«å¹¶åï¼ |
| | | /// </summary> |
| | | /// <returns>æ ¼å¼ï¼yyyyMMdd + Ticks + 3ä½è®¡æ°å¨ï¼å¦2025112563867890123001ï¼</returns> |
| | | public static string Generate() |
| | | { |
| | | var now = DateTime.Now; |
| | | string datePart = now.ToString("yyyyMMdd"); |
| | | long ticksPart = now.Ticks; |
| | | |
| | | // ååéå¢è®¡æ°å¨ï¼å模1000ï¼ç¡®ä¿è®¡æ°å¨ä»
3ä½ï¼æ§å¶é¿åº¦ï¼ |
| | | long counterPart = Interlocked.Increment(ref _counter) % 1000; |
| | | |
| | | // æ¼æ¥ï¼è®¡æ°å¨è¡¥0为3ä½ï¼é¿å
使°ä¸ä¸è´ï¼ |
| | | return $"{datePart}{ticksPart}{counterPart:D3}"; |
| | | } |
| | | } |
| | | } |
| | |
| | | if (first != null) |
| | | { |
| | | locationCaches.Add(new LocationCache { LocationCode = first.LocationCode, DateTime = DateTime.Now }); |
| | | Db.Updateable<Dt_LocationInfo>().SetColumns(x => new Dt_LocationInfo |
| | | { |
| | | 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 ConvertAsync(materialData, quantity, materialData.PurchaseUnit, materialData.StockUnit); |
| | | } |
| | | |
| | | public async Task<MaterialWithUnitConversionResult> ConvertFromToStockAsync(string materialCode,string fromUom, decimal quantity) |
| | | { |
| | | var materialData = await GetMaterialWithUnitsAsync(materialCode); |
| | | |
| | | // 妿颿åä½ååºååä½ç¸åï¼ç´æ¥è¿å |
| | | if (fromUom.Equals(materialData.StockUnit, StringComparison.OrdinalIgnoreCase)) |
| | | return new MaterialWithUnitConversionResult(quantity, materialData.StockUnit, false); |
| | | |
| | | return ConvertAsync(materialData, quantity, fromUom, materialData.StockUnit); |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// 颿åä½è½¬åºååä½ |
| | | /// </summary> |
| | |
| | | |
| | | <ItemGroup> |
| | | <ProjectReference Include="..\WIDESEA_IBasicService\WIDESEA_IBasicService.csproj" /> |
| | | <ProjectReference Include="..\WIDESEA_IOutboundService\WIDESEA_IOutboundService.csproj" /> |
| | | <ProjectReference Include="..\WIDESEA_IRecordService\WIDESEA_IRecordService.csproj" /> |
| | | </ItemGroup> |
| | | |
| | |
| | | /// </summary> |
| | | LargestPallet = 4 |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | public enum PalletStatusEnum |
| | | { |
| | | æªå¼å§ = 0, |
| | | æ£éä¸ = 1, |
| | | 已宿 = 2, |
| | | æ ä»»å¡ = 3 |
| | | } |
| | | |
| | | |
| | | |
| | | } |
| | |
| | | /// è°æ¨å
¥åºå |
| | | /// </summary> |
| | | [Description("è°æ¨å
¥åºå")] |
| | | Allocat = 115, |
| | | AllocatInbound = 115, |
| | | |
| | | [Description("è°æ¨åºåºå")] |
| | | AllocatOutbound = 215, |
| | | |
| | | [Description("鿣ååº")] |
| | | ReCheck =116, |
| | | |
| | | [Description("æºä»è°æºä»å
¥åºå")] |
| | | InternalAllocat = 117, |
| | | |
| | | /// <summary> |
| | | /// éå®éè´§å |
| | | /// </summary> |
| | |
| | | [Description("åºåºä¸")] |
| | | åºåºä¸ = 1, |
| | | |
| | | |
| | | |
| | | /// <summary> |
| | | /// åºåºå®æ |
| | | /// </summary> |
| | | [Description("åºåºå®æ")] |
| | | åºåºå®æ = 2, |
| | | |
| | | [Description("é¨å宿")] |
| | | |
| | | é¨å宿 =3, |
| | | |
| | | /// <summary> |
| | | /// å
³é |
| | |
| | | [Description("å
¶ä»åºåºå")] |
| | | Other = 235 |
| | | } |
| | | |
| | | |
| | | } |
| | |
| | | // å·²åºåº = 4, |
| | | // å·²ååº = 5 |
| | | //} |
| | | |
| | | // æä¸¾å®ä¹ |
| | | public enum BatchStatusEnum |
| | | { |
| | | åé
ä¸ = 0, |
| | | æ§è¡ä¸ = 1, |
| | | 已宿 = 2, |
| | | å·²ååº = 3, |
| | | 已忶 = 4, |
| | | |
| | | } |
| | | |
| | | public enum SplitPackageStatusEnum |
| | | { |
| | | å·²æå
= 1, |
| | |
| | | å·²æ£é = 3, |
| | | å·²ååº = 4, |
| | | } |
| | | |
| | | |
| | | public enum OutLockStockStatusEnum |
| | | { |
| | | [Description("å·²åé
")] |
| | |
| | | [Description("å·²ååº")] |
| | | å·²ååº =8, |
| | | |
| | | [Description("已鿾")] |
| | | 已鿾 =9, |
| | | |
| | | [Description("å·²åèµ°")] |
| | | å·²åèµ° =10, |
| | | |
| | | [Description("æ¤é")] |
| | | æ¤é = 99 |
| | | } |
| | |
| | | Lock, |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | /// <summary> |
| | | /// åºåç¶æï¼ <br/> |
| | | /// 1ï¼ç»çæå<br/> |
| | |
| | | [Description("çç¹åºå宿")] |
| | | çç¹åºå宿 = 32, |
| | | |
| | | [Description("ç»çæ¤é")] |
| | | [Description("å·²æ¸
ç")] |
| | | å·²æ¸
ç = 33, |
| | | |
| | | [Description("ç»çæ¤é")] |
| | | ç»çæ¤é = 99, |
| | | |
| | | [Description("å
¥åºæ¤é")] |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using SqlSugar; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | using WIDESEA_Core.DB; |
| | | using WIDESEA_Core.Seed; |
| | | |
| | | namespace WIDESEA_Core.Helper |
| | | { |
| | | public class SqlSugarHelper |
| | | { |
| | | //å¤åºæ
åµä¸ä½¿ç¨è¯´æï¼ |
| | | //妿æ¯åºå®å¤åºå¯ä»¥ä¼ new SqlSugarScope(List<ConnectionConfig>,db=>{}) ææ¡£ï¼å¤ç§æ· |
| | | //妿æ¯ä¸åºå®å¤åº å¯ä»¥çææ¡£Saasååº |
| | | //ç¨å便¨¡å¼ |
| | | public static SqlSugarScope DbWMS = new SqlSugarScope(new ConnectionConfig() |
| | | { |
| | | ConnectionString = DBContext.GetMainConnectionDb().Connection, |
| | | //ConnectionString = AppSettings.app(MainDb.ConnectionStringWCS), |
| | | DbType = DbType.SqlServer,//æ°æ®åºç±»å |
| | | IsAutoCloseConnection = true //ä¸è®¾ætrueè¦æå¨close |
| | | }, |
| | | db => |
| | | { |
| | | }); |
| | | } |
| | | } |
| | |
| | | /// </summary> |
| | | [JsonProperty("unit")] |
| | | public string Unit { get; set; } |
| | | |
| | | public DateTime validDate { get; set; } |
| | | } |
| | | |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using SqlSugar; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.ComponentModel.DataAnnotations; |
| | | using System.Linq; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | |
| | | namespace WIDESEA_DTO.Outbound |
| | | { |
| | | |
| | | |
| | | public class PalletLockInfoDto |
| | | { |
| | | public int Id { get; set; } |
| | | public string OrderNo { get; set; } |
| | | public string BatchNo { get; set; } |
| | | public string MaterielCode { get; set; } |
| | | public string CurrentBarcode { get; set; } |
| | | public decimal AssignQuantity { get; set; } |
| | | public decimal PickedQty { get; set; } |
| | | public int Status { get; set; } |
| | | public string LocationCode { get; set; } |
| | | public string PalletCode { get; set; } |
| | | public bool CanSplit { get; set; } |
| | | public bool CanPick { get; set; } |
| | | } |
| | | |
| | | #region 请æ±DTO |
| | | |
| | | public class ConfirmPickingRequest |
| | | { |
| | | [Required(ErrorMessage = "订åå·ä¸è½ä¸ºç©º")] |
| | | public string OrderNo { get; set; } |
| | | |
| | | [Required(ErrorMessage = "æçå·ä¸è½ä¸ºç©º")] |
| | | public string PalletCode { get; set; } |
| | | |
| | | [Required(ErrorMessage = "æ¡ç ä¸è½ä¸ºç©º")] |
| | | public string Barcode { get; set; } |
| | | } |
| | | |
| | | public class CancelPickingRequest |
| | | { |
| | | [Required(ErrorMessage = "订åå·ä¸è½ä¸ºç©º")] |
| | | public string OrderNo { get; set; } |
| | | |
| | | [Required(ErrorMessage = "æçå·ä¸è½ä¸ºç©º")] |
| | | public string PalletCode { get; set; } |
| | | |
| | | [Required(ErrorMessage = "æ¡ç ä¸è½ä¸ºç©º")] |
| | | public string Barcode { get; set; } |
| | | |
| | | public int PickingHistoryId { get; set; } |
| | | } |
| | | |
| | | |
| | | |
| | | public class CancelSplitRequest |
| | | { |
| | | [Required(ErrorMessage = "订åå·ä¸è½ä¸ºç©º")] |
| | | public string OrderNo { get; set; } |
| | | |
| | | [Required(ErrorMessage = "æçå·ä¸è½ä¸ºç©º")] |
| | | public string PalletCode { get; set; } |
| | | |
| | | [Required(ErrorMessage = "æ°æ¡ç ä¸è½ä¸ºç©º")] |
| | | public string NewBarcode { get; set; } |
| | | } |
| | | |
| | | public class ReturnStockRequest |
| | | { |
| | | [Required(ErrorMessage = "订åå·ä¸è½ä¸ºç©º")] |
| | | public string OrderNo { get; set; } |
| | | |
| | | [Required(ErrorMessage = "æçå·ä¸è½ä¸ºç©º")] |
| | | public string PalletCode { get; set; } |
| | | } |
| | | public class CancelSplitDto |
| | | { |
| | | [Required(ErrorMessage = "订åå·ä¸è½ä¸ºç©º")] |
| | | public string OrderNo { get; set; } |
| | | |
| | | [Required(ErrorMessage = "æçå·ä¸è½ä¸ºç©º")] |
| | | public string PalletCode { get; set; } |
| | | |
| | | [Required(ErrorMessage = "æ°æ¡ç ä¸è½ä¸ºç©º")] |
| | | public string NewBarcode { get; set; } |
| | | } |
| | | |
| | | public class ReturnStockDto |
| | | { |
| | | [Required(ErrorMessage = "订åå·ä¸è½ä¸ºç©º")] |
| | | public string OrderNo { get; set; } |
| | | |
| | | [Required(ErrorMessage = "æçå·ä¸è½ä¸ºç©º")] |
| | | public string PalletCode { get; set; } |
| | | } |
| | | |
| | | public class PalletLocksDto |
| | | { |
| | | [Required(ErrorMessage = "订åå·ä¸è½ä¸ºç©º")] |
| | | public string OrderNo { get; set; } |
| | | |
| | | [Required(ErrorMessage = "æçå·ä¸è½ä¸ºç©º")] |
| | | public string PalletCode { get; set; } |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region DTOç±» |
| | | |
| | | public class PalletPickedInfoDto |
| | | { |
| | | public int Id { get; set; } |
| | | public string OrderNo { get; set; } |
| | | public int OrderDetailId { get; set; } |
| | | public string PalletCode { get; set; } |
| | | public string Barcode { get; set; } |
| | | public string MaterielCode { get; set; } |
| | | public decimal PickedQty { get; set; } |
| | | public DateTime PickTime { get; set; } |
| | | public string Operator { get; set; } |
| | | public string LocationCode { get; set; } |
| | | } |
| | | |
| | | public class PalletStatusDto |
| | | { |
| | | public string OrderNo { get; set; } |
| | | public string PalletCode { get; set; } |
| | | public int Status { get; set; } |
| | | public string StatusText { get; set; } |
| | | public int TotalItems { get; set; } |
| | | public int CompletedItems { get; set; } |
| | | public int PendingItems { get; set; } |
| | | } |
| | | |
| | | public class SplitPackageInfoDto |
| | | { |
| | | public string OrderNo { get; set; } |
| | | public string PalletCode { get; set; } |
| | | public string Barcode { get; set; } |
| | | public string MaterielCode { get; set; } |
| | | public decimal RemainQuantity { get; set; } |
| | | public decimal AssignQuantity { get; set; } |
| | | public decimal PickedQty { get; set; } |
| | | } |
| | | |
| | | public class EmptyPalletRemovalDto |
| | | { |
| | | public string OrderNo { get; set; } |
| | | public string PalletCode { get; set; } |
| | | public DateTime RemovalTime { get; set; } |
| | | public string Operator { get; set; } |
| | | public int CompletedItemsCount { get; set; } |
| | | public decimal TotalPickedQuantity { get; set; } |
| | | } |
| | | |
| | | public class RemoveEmptyPalletDto |
| | | { |
| | | [Required(ErrorMessage = "订åå·ä¸è½ä¸ºç©º")] |
| | | public string OrderNo { get; set; } |
| | | |
| | | [Required(ErrorMessage = "æçå·ä¸è½ä¸ºç©º")] |
| | | public string PalletCode { get; set; } |
| | | } |
| | | #endregion |
| | | |
| | | } |
| | |
| | | /// </summary> |
| | | public string orderNo { get; set; } |
| | | |
| | | public string documentsNO { get; set; } |
| | | |
| | | public string business_type { get; set; } |
| | | |
| | | public int status { get; set; } |
| | | |
| | | public string factoryArea { get; set; } |
| | | public string Operator { get; set; } |
| | | public List<FeedbackOutboundDetailsModel> details { get; set; } |
| | | |
| | | public List<FeedbackOutboundDetailsModel> details { get; set; } |
| | | |
| | | } |
| | | |
| | |
| | | using Newtonsoft.Json; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.ComponentModel.DataAnnotations; |
| | | using System.Linq; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | |
| | | { |
| | | public int OutStockLockInfoId { get; set; } |
| | | public string MaterielCode { get; set; } |
| | | public decimal SplitQuantity { get; set; } |
| | | |
| | | public string Operator { get; set; } |
| | | |
| | | [Required(ErrorMessage = "订åå·ä¸è½ä¸ºç©º")] |
| | | public string OrderNo { get; set; } |
| | | |
| | | [Required(ErrorMessage = "æçå·ä¸è½ä¸ºç©º")] |
| | | public string PalletCode { get; set; } |
| | | |
| | | [Required(ErrorMessage = "åæ¡ç ä¸è½ä¸ºç©º")] |
| | | public string OriginalBarcode { get; set; } |
| | | |
| | | [Range(0.001, double.MaxValue, ErrorMessage = "æå
æ°éå¿
须大äº0")] |
| | | public decimal SplitQuantity { get; set; } |
| | | } |
| | | public class ConfirmPickingDto |
| | | { |
| | |
| | | public string OrderNo { get; set; } |
| | | } |
| | | |
| | | public class CancelPickingRequest |
| | | { |
| | | public int PickingHistoryId { get; set; } |
| | | } |
| | | |
| | | |
| | | public class BackToStockRequest |
| | | { |
| | |
| | | public string Barcode { get; set; } |
| | | } |
| | | |
| | | |
| | | |
| | | public class CancelSplitChainDto |
| | | { |
| | | [Required(ErrorMessage = "订åå·ä¸è½ä¸ºç©º")] |
| | | public string OrderNo { get; set; } |
| | | |
| | | [Required(ErrorMessage = "æçå·ä¸è½ä¸ºç©º")] |
| | | public string PalletCode { get; set; } |
| | | |
| | | [Required(ErrorMessage = "èµ·å§æ¡ç ä¸è½ä¸ºç©º")] |
| | | public string StartBarcode { get; set; } |
| | | } |
| | | |
| | | public class SplitPackageChainInfoRequestDto |
| | | { |
| | | [Required(ErrorMessage = "订åå·ä¸è½ä¸ºç©º")] |
| | | public string OrderNo { get; set; } |
| | | |
| | | [Required(ErrorMessage = "æ¡ç ä¸è½ä¸ºç©º")] |
| | | public string Barcode { get; set; } |
| | | } |
| | | |
| | | public class SplitPackageDto |
| | | { |
| | | public string OrderNo { get; set; } |
| | |
| | | //public decimal SplitQuantity { get; set; } |
| | | //public decimal RemainQuantity { get; set; } |
| | | } |
| | | |
| | | |
| | | } |
| | |
| | | |
| | | public string LocationCode { get; set; } |
| | | |
| | | |
| | | |
| | | public string Barcode { get; set; } |
| | | |
| | | |
| | | public string BatchNo { get; set; } |
| | | public string SupplyCode { get; set; } |
| | | public DateTime StockCreateDate { get; set; } |
| | | public int StockId { get; set; } |
| | | public int? OrderDetailId { get; set; } |
| | | } |
| | | } |
| | |
| | | public int[] taskIds { get; set; } |
| | | |
| | | } |
| | | |
| | | public class GenerateOutboundBatchTasksDto |
| | | { |
| | | public string orderNo { get; set; } |
| | | |
| | | public int orderDetailId { get; set; } |
| | | |
| | | public decimal batchQuantity { get; set; } |
| | | |
| | | public string outboundPlatform { get; set; } |
| | | } |
| | | } |
| | |
| | | Task<Dictionary<string, MaterialWithUnitConversionResult>> BatchConvertPurchaseToStockAsync(List<BatchConversionRequest> requests); |
| | | Task<MaterialWithUnitConversionResult> ConvertAsync(string materialCode, decimal quantity, string fromUnit, string toUnit); |
| | | Task<MaterialWithUnitConversionResult> ConvertIssueToStockAsync(string materialCode, decimal quantity); |
| | | |
| | | Task<MaterialWithUnitConversionResult> ConvertFromToStockAsync(string materialCode, string fromUom, decimal quantity); |
| | | Task<MaterialWithUnitConversionResult> ConvertPurchaseToStockAsync(string materialCode, decimal quantity); |
| | | Task<decimal?> GetConversionRatioAsync(string materialCode, string fromUnit, string toUnit); |
| | | Task<string> GetIssueUnitAsync(string materialCode); |
| | |
| | | Task<List<Dt_OutStockLockInfo>> GetByPalletCode(string palletCode, int? status = null); |
| | | |
| | | Task<LockInfoDetailDto> GetLockInfoDetail(int lockInfoId); |
| | | Dt_OutStockLockInfo GetOutStockLockInfo(Dt_OutboundOrder outboundOrder,Dt_OutboundOrderDetail outboundOrderDetail,Dt_StockInfo outStock, decimal assignQuantity, string barcode = null); |
| | | Dt_OutStockLockInfo GetOutStockLockInfo(Dt_OutboundOrder outboundOrder,Dt_OutboundOrderDetail outboundOrderDetail,Dt_StockInfo outStock, decimal assignQuantity, string barcode = null, string outboundBatchNo = ""); |
| | | |
| | | List<Dt_OutStockLockInfo> GetOutStockLockInfos(Dt_OutboundOrder outboundOrder, Dt_OutboundOrderDetail outboundOrderDetail, List<Dt_StockInfo> outStocks, int? taskNum = null); |
| | | Task<List<Dt_OutStockLockInfo>> GetPalletLockInfos(string palletCode); |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using WIDESEA_Core; |
| | | using WIDESEA_Core.BaseRepository; |
| | | using WIDESEA_DTO.Outbound; |
| | | using WIDESEA_Model.Models; |
| | | |
| | | namespace WIDESEA_IOutboundService |
| | | { |
| | | public interface IOutboundBatchPickingService |
| | | { |
| | | IRepository<Dt_PickingRecord> Repository { get; } |
| | | |
| | | Task<WebResponseContent> BatchReturnStock(string orderNo, string palletCode); |
| | | Task<WebResponseContent> CancelPicking(string orderNo, string palletCode, string barcode); |
| | | Task<WebResponseContent> CancelSplitPackage(string orderNo, string palletCode, string newBarcode); |
| | | |
| | | Task<WebResponseContent> CancelSplitPackageChain(string orderNo, string palletCode, string startBarcode); |
| | | |
| | | Task<List<Dt_SplitPackageRecord>> GetSplitPackageChain(string orderNo, string startBarcode); |
| | | Task<string> FindRootBarcode(string orderNo, string startBarcode); |
| | | Task<WebResponseContent> GetSplitPackageChainInfo(string orderNo, string barcode); |
| | | Task<WebResponseContent> ConfirmBatchPicking(string orderNo, string palletCode, string barcode); |
| | | Task<List<PalletLockInfoDto>> GetPalletLockInfos(string orderNo, string palletCode); |
| | | Task<List<PalletPickedInfoDto>> GetPalletPickedList(string orderNo, string palletCode); |
| | | Task<PalletStatusDto> GetPalletStatus(string orderNo, string palletCode); |
| | | Task<SplitPackageInfoDto> GetSplitPackageInfo(string orderNo, string palletCode, string barcode); |
| | | Task<WebResponseContent> ManualSplitPackage(string orderNo, string palletCode, string originalBarcode, decimal splitQuantity); |
| | | Task<WebResponseContent> RemoveEmptyPallet(string orderNo, string palletCode); |
| | | } |
| | | } |
| | |
| | | WebResponseContent LockOutboundStockDataUpdate(List<Dt_StockInfo> stockInfos, List<Dt_OutboundOrderDetail> outboundOrderDetails, List<Dt_OutStockLockInfo> outStockLockInfos, List<Dt_LocationInfo> locationInfos, LocationStatusEnum locationStatus = LocationStatusEnum.Lock, List<Dt_Task>? tasks = null); |
| | | (List<Dt_StockInfo>, Dt_OutboundOrderDetail, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>) AssignStockOutbound(Dt_OutboundOrderDetail outboundOrderDetail, List<StockSelectViewDTO> stockSelectViews); |
| | | //List<Dt_OutboundOrderDetail> GetOutboundStockDataById(int id); |
| | | |
| | | Task<(List<Dt_StockInfo>, List<Dt_OutboundOrderDetail>, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>)> AssignStockForBatch(Dt_OutboundOrderDetail orderDetail, decimal batchQuantity, string batchNo); |
| | | } |
| | | } |
| | |
| | | List<Dt_StockInfo> GetStockInfos(string materielCode, string lotNo, string supplyCode, List<string> locationCodes); |
| | | |
| | | List<Dt_StockInfo> GetUseableStocks(string materielCode, string batchNo,string supplyCode); |
| | | |
| | | |
| | | Dt_StockInfo GetStockInfoByPalletCode(string palletCode); |
| | | void AddMaterielGroup(Dt_StockInfo stockInfo); |
| | | (List<Dt_StockInfo>, Dictionary<int, decimal>) GetOutboundStocks(List<Dt_StockInfo> stockInfos, string materielCode, decimal needQuantity, out decimal residueQuantity); |
| | | |
| | |
| | | |
| | | WebResponseContent GenerateOutboundTask(int orderDetailId, List<StockSelectViewDTO> stockSelectViews); |
| | | |
| | | Task<WebResponseContent> GenerateOutboundBatchTasksAsync(int orderDetailId, decimal batchQuantity, string outStation); |
| | | |
| | | |
| | | } |
| | | } |
| | |
| | | item.Unit = purchaseToStockResult.Unit; |
| | | item.OrderQuantity = purchaseToStockResult.Quantity; |
| | | } |
| | | if (model.OrderType != InOrderTypeEnum.AllocatInbound.ObjToInt()) |
| | | { |
| | | model.InboundOrderNo = CreateCodeByRule(nameof(RuleCodeEnum.InboundOrderRule)); |
| | | } |
| | | |
| | | model.InboundOrderNo = CreateCodeByRule(nameof(RuleCodeEnum.InboundOrderRule)); |
| | | Db.InsertNav(model).Include(x => x.Details).ExecuteCommand(); |
| | | } |
| | | return WebResponseContent.Instance.OK(); |
| | |
| | | if (inboundOrder.Details == null || inboundOrder.Details.Count == 0) |
| | | { |
| | | return WebResponseContent.Instance.Error($"æªæ¾å°å
¥åºåæç»ä¿¡æ¯"); |
| | | } |
| | | if (inboundOrder.OrderStatus != InOrderStatusEnum.æªå¼å§.ObjToInt()) |
| | | { |
| | | return WebResponseContent.Instance.Error($"该订åç¶æä¸å
许修æ¹"); |
| | | } |
| | | List<Dt_InboundOrderDetail> inboundOrderDetails = new List<Dt_InboundOrderDetail>(); |
| | | List<Dt_InboundOrderDetail> updateInboundOrderDetails = new List<Dt_InboundOrderDetail>(); |
| | |
| | | { |
| | | return WebResponseContent.Instance.Error($"æªæ¾å°å
¥åºåæç»ä¿¡æ¯"); |
| | | } |
| | | if (inboundOrder.OrderStatus != InOrderStatusEnum.æªå¼å§.ObjToInt()) |
| | | { |
| | | return WebResponseContent.Instance.Error($"该订åç¶æä¸å
许å é¤"); |
| | | } |
| | | //Db.DeleteNav(inboundOrder).Include(x => x.Details).ExecuteCommand(); |
| | | _unitOfWorkManage.BeginTran(); |
| | | //BaseDal.DeleteAndMoveIntoHty(inboundOrder, OperateTypeEnum.èªå¨å é¤); |
| | |
| | | if (!result2.Item1) return content = WebResponseContent.Instance.Error(result2.Item2); |
| | | |
| | | // materielGroupDTO.WarehouseCode |
| | | var code = _warehouseAreaRepository.Db.Queryable<Dt_WarehouseArea>().Where(x => x.Code == materielGroupDTO.WarehouseType).Select(x=>x.Code).First(); |
| | | if(string.IsNullOrEmpty(code)) |
| | | var code = _warehouseAreaRepository.Db.Queryable<Dt_WarehouseArea>().Where(x => x.Code == materielGroupDTO.WarehouseType).Select(x => x.Code).First(); |
| | | if (string.IsNullOrEmpty(code)) |
| | | { |
| | | return content = WebResponseContent.Instance.Error($"ä»åºä¸æ²¡æè¯¥{materielGroupDTO.WarehouseType}ç¼å·ã"); |
| | | } |
| | | |
| | | |
| | | |
| | | Dt_InboundOrder inboundOrder = GetInboundOrder(materielGroupDTO.OrderNo); |
| | | |
| | |
| | | |
| | | if (stockInfo == null) |
| | | { |
| | | stockInfo = new Dt_StockInfo() { PalletType = (int)PalletTypeEnum.None,LocationType=materielGroupDTO.locationType.ObjToInt() }; |
| | | stockInfo = new Dt_StockInfo() { PalletType = (int)PalletTypeEnum.None, LocationType = materielGroupDTO.locationType.ObjToInt() }; |
| | | stockInfo.Details = new List<Dt_StockInfoDetail>(); |
| | | } |
| | | |
| | | |
| | | foreach (var item in dbinboundOrderDetails) |
| | | { |
| | | stockInfo.Details.Add(new Dt_StockInfoDetail |
| | |
| | | SupplyCode = item.SupplyCode, |
| | | WarehouseCode = materielGroupDTO.WarehouseType, |
| | | StockQuantity = item.OrderQuantity, |
| | | BarcodeQty=item.BarcodeQty, |
| | | BarcodeUnit=item.BarcodeUnit, |
| | | FactoryArea= inboundOrder.FactoryArea, |
| | | Status = 0, |
| | | BarcodeQty = item.BarcodeQty, |
| | | BarcodeUnit = item.BarcodeUnit, |
| | | FactoryArea = inboundOrder.FactoryArea, |
| | | Status = 0, |
| | | OrderNo = inboundOrder.InboundOrderNo, |
| | | BusinessType = inboundOrder.BusinessType, |
| | | |
| | | |
| | | }); |
| | | |
| | | |
| | | item.ReceiptQuantity = item.BarcodeQty; |
| | | item.OrderDetailStatus = OrderDetailStatusEnum.Over.ObjToInt(); |
| | | item.WarehouseCode = materielGroupDTO.WarehouseType; |
| | |
| | | |
| | | WebResponseContent content = new WebResponseContent(); |
| | | try |
| | | { |
| | | { |
| | | (bool, string, object?) result2 = ModelValidate.ValidateModelData(materielGroupDTO); |
| | | if (!result2.Item1) return content = WebResponseContent.Instance.Error(result2.Item2); |
| | | |
| | |
| | | return content = WebResponseContent.Instance.Error($"åºå䏿²¡æè¯¥{materielGroupDTO.WarehouseCode}ç¼å·ã"); |
| | | } |
| | | |
| | | if(_stockRepository.QueryFirst(x=>x.PalletCode == materielGroupDTO.PalletCode)!=null){ |
| | | if (_stockRepository.QueryFirst(x => x.PalletCode == materielGroupDTO.PalletCode) != null) |
| | | { |
| | | return WebResponseContent.Instance.Error("该æçå·²ç»ç»è¿ç"); |
| | | } |
| | | |
| | |
| | | { |
| | | if (stockInfo == null) |
| | | { |
| | | stockInfo = new Dt_StockInfo() { PalletType = PalletTypeEnum.Empty.ObjToInt(), StockStatus = StockStatusEmun.ç»çæå.ObjToInt(), PalletCode = materielGroupDTO.PalletCode,LocationType= materielGroupDTO.WarehouseCode.ObjToInt() }; |
| | | stockInfo = new Dt_StockInfo() { PalletType = PalletTypeEnum.Empty.ObjToInt(), StockStatus = StockStatusEmun.ç»çæå.ObjToInt(), PalletCode = materielGroupDTO.PalletCode, LocationType = materielGroupDTO.WarehouseCode.ObjToInt() }; |
| | | stockInfo.Details = new List<Dt_StockInfoDetail>(); |
| | | } |
| | | else |
| | |
| | | { |
| | | return WebResponseContent.Instance.Error("æçå·ä¸è½ä¸ºç©º"); |
| | | } |
| | | var stock= _stockRepository.Db.Queryable<Dt_StockInfo>().Includes(o=>o.Details).First(x => x.PalletCode == palletCode ); |
| | | var stock = _stockRepository.Db.Queryable<Dt_StockInfo>().Includes(o => o.Details).First(x => x.PalletCode == palletCode && x.StockStatus == (int)StockStatusEmun.ç»çæå); |
| | | if (stock == null) |
| | | { |
| | | return WebResponseContent.Instance.Error($"æªæ¾å°æçå·{palletCode}对åºçåºåè®°å½"); |
| | | } |
| | | |
| | | if (stock.Details == null || !stock.Details.Any()) |
| | | { |
| | | _stockRepository.DeleteData(stock); |
| | | return WebResponseContent.Instance.OK(); |
| | | } |
| | | // è·ååºå详æ
å
³èçææå
¥åºåå· |
| | | var relatedOrderNos = stock.Details.Select(d => d.OrderNo).First(); |
| | | // æ¥è¯¢ææå
³èçå
¥åºåï¼å«è¯¦æ
ï¼ |
| | | var inboundOrders = _inboundOrderRepository.Db.Queryable<Dt_InboundOrder>() |
| | | .Includes(x => x.Details) |
| | | .Where(x => relatedOrderNos==x.InboundOrderNo) |
| | | .Includes(x => x.Details) |
| | | .Where(x => relatedOrderNos == x.InboundOrderNo) |
| | | .First(); |
| | | |
| | | var barcodes = stock.Details.Select(d => d.Barcode).ToList(); |
| | | |
| | | // å¹é
åºåæ¡ç 对åºçå
¥åºåæç» |
| | | var matchedInboundDetails = inboundOrders.Details |
| | | ?.Where(d => barcodes.Contains(d.Barcode)) |
| | | .ToList(); |
| | | // å¹é
åºåæ¡ç 对åºçå
¥åºåæç» |
| | | var matchedInboundDetails = inboundOrders.Details |
| | | ?.Where(d => barcodes.Contains(d.Barcode)) |
| | | .ToList(); |
| | | foreach (var detail in matchedInboundDetails) |
| | | { |
| | | detail.ReceiptQuantity = 0; |
| | |
| | | _stockDetailRepository.DeleteData(stock.Details); |
| | | _stockRepository.DeleteData(stock); |
| | | |
| | | return WebResponseContent.Instance.OK(); |
| | | |
| | | return WebResponseContent.Instance.OK("æçæ¤éæå"); |
| | | } |
| | | } |
| | | } |
| | |
| | | /// </summary> |
| | | [SugarColumn(IsNullable = true, ColumnDescription = "åä¼ MES")] |
| | | public int ReturnToMESStatus { get; set; } = 0; |
| | | [SugarColumn(IsNullable = true, ColumnDescription = "è¿ææ¥æ")] |
| | | public DateTime ValidDate { get; set; } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using SqlSugar; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | using WIDESEA_Core.DB.Models; |
| | | |
| | | namespace WIDESEA_Model.Models.Outbound |
| | | { |
| | | |
| | | |
| | | /// <summary> |
| | | /// åºåºæ¹æ¬¡è¡¨ |
| | | /// </summary> |
| | | [SugarTable("Dt_OutboundBatch")] |
| | | public class Dt_OutboundBatch : BaseEntity |
| | | { |
| | | /// <summary> |
| | | /// 主é®IDï¼èªå¢ï¼ |
| | | /// </summary> |
| | | [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] // |
| | | public int Id { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æ¹æ¬¡å· |
| | | /// </summary> |
| | | [SugarColumn(ColumnName = "BatchNo", Length = 50, IsNullable = false)] |
| | | public string BatchNo { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 订åå· |
| | | /// </summary> |
| | | [SugarColumn(ColumnName = "OrderNo", Length = 50, IsNullable = false)] |
| | | public string OrderNo { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 订åæç»ID |
| | | /// </summary> |
| | | [SugarColumn(ColumnName = "OrderDetailId", IsNullable = false)] |
| | | public int OrderDetailId { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æ¹æ¬¡åé
æ°é |
| | | /// </summary> |
| | | [SugarColumn(ColumnName = "BatchQuantity", IsNullable = false)] // 精度18ï¼å°æ°ä½2 |
| | | public decimal BatchQuantity { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 已宿æ°éï¼é»è®¤0ï¼ |
| | | /// </summary> |
| | | [SugarColumn(ColumnName = "CompletedQuantity", DefaultValue = "0")] // é»è®¤å¼0 |
| | | public decimal CompletedQuantity { get; set; } = 0; // 代ç å±é»è®¤å¼ï¼ä¸æ°æ®åºé»è®¤å¼ä¸è´ |
| | | |
| | | /// <summary> |
| | | /// æ¹æ¬¡ç¶æï¼é»è®¤0ï¼ |
| | | /// </summary> |
| | | [SugarColumn(ColumnName = "BatchStatus", DefaultValue = "0")] |
| | | public int BatchStatus { get; set; } = 0; |
| | | |
| | | |
| | | /// <summary> |
| | | /// æä½äºº |
| | | /// </summary> |
| | | [SugarColumn(ColumnName = "Operator", Length = 50, IsNullable = true)] // å¯ç©º |
| | | public string Operator { get; set; } |
| | | } |
| | | } |
| | |
| | | [SugarColumn(IsNullable = false, Length = 50, ColumnDescription = "æä½è
")] |
| | | public string Operator { get; set; } |
| | | |
| | | |
| | | public decimal BarcodeQty { get; set; } |
| | | |
| | | public string BarcodeUnit { get; set; } |
| | | |
| | | public string OutboundBatchNo { get; set; } |
| | | |
| | | [Navigate(NavigateType.OneToOne, nameof(StockInfo))]//ä¸å¯¹ä¸ SchoolIdæ¯StudentAç±»éé¢ç |
| | | public Dt_StockInfo StockInfo { get; set; } //ä¸è½èµå¼åªè½æ¯null |
| | | |
| | |
| | | public string Operator { get; set; } |
| | | |
| | | /// <summary> |
| | | /// åä¼ MES |
| | | /// åä¼ MES 0æªåä¼ ï¼1åä¼ æåï¼ 2åä¼ å¤±è´¥ |
| | | /// </summary> |
| | | [SugarColumn(IsNullable = true, ColumnDescription = "åä¼ MES")] |
| | | public int ReturnToMESStatus { get; set; } = 0; |
| | |
| | | public decimal NeedOutQuantity => OrderQuantity - MoveQty; |
| | | |
| | | public decimal PickedQty { get; set; } |
| | | /// <summary> |
| | | /// èæåºå
¥åºæ°é |
| | | /// </summary> |
| | | public decimal NoStockOutQty { get; set; } |
| | | |
| | | public string documentsNO { get; set; } |
| | | |
| | | public decimal AllocatedQuantity { get; set; } |
| | | |
| | | public string BatchAllocateStatus { get; set; } |
| | | } |
| | | } |
| | |
| | | |
| | | public int StockId { get; set; } |
| | | |
| | | public string BatchNo { get; set; } |
| | | |
| | | public bool IsCancelled { get; set; } |
| | | |
| | | public DateTime? CancelTime { get; set; } |
| | | |
| | | public string CancelOperator { get; set; } |
| | | public string FactoryArea { get; set; } |
| | | } |
| | | |
| | |
| | | |
| | | public DateTime RevertTime { get; set; } |
| | | |
| | | public string RevertOperator { get; set; } |
| | | public int PreviousSplitRecordId { get; set; } |
| | | |
| | | [SugarColumn(IsNullable = true)] |
| | |
| | | public decimal StockBeforeSplit { get; set; } |
| | | public decimal AssignBeforeSplit { get; set; } |
| | | } |
| | | |
| | | |
| | | |
| | | /// <summary> |
| | | /// 空箱åèµ°è®°å½è¡¨ |
| | | /// </summary> |
| | | public class Dt_EmptyPalletRemoval |
| | | { |
| | | [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] |
| | | public int Id { get; set; } |
| | | |
| | | public string OrderNo { get; set; } |
| | | |
| | | public string PalletCode { get; set; } |
| | | |
| | | public DateTime RemovalTime { get; set; } |
| | | |
| | | public string Operator { get; set; } |
| | | |
| | | public int CompletedItemsCount { get; set; } |
| | | |
| | | public decimal TotalPickedQuantity { get; set; } |
| | | } |
| | | |
| | | |
| | | } |
| | |
| | | Dt_OutboundOrderDetail outboundOrderDetail, |
| | | Dt_StockInfo outStock, |
| | | decimal assignQuantity, |
| | | string barcode = null) |
| | | string barcode = null,string outboundBatchNo = "") |
| | | { |
| | | // è·ååºåæç»ä¿¡æ¯ |
| | | var stockDetails = outStock.Details |
| | |
| | | MaterielCode = outboundOrderDetail.MaterielCode, |
| | | BatchNo = firstAvailableDetail.BatchNo, |
| | | Unit = firstAvailableDetail.Unit, |
| | | BarcodeQty = firstAvailableDetail.BarcodeQty, |
| | | BarcodeUnit = firstAvailableDetail.BarcodeUnit, |
| | | FactoryArea = firstAvailableDetail.FactoryArea, |
| | | lineNo = outboundOrderDetail.lineNo, |
| | | OutboundBatchNo= outboundBatchNo |
| | | }; |
| | | } |
| | | |
| | |
| | | |
| | | public List<Dt_OutStockLockInfo> GetByOrderDetailId(int orderDetailId, OutLockStockStatusEnum? outStockStatus) |
| | | { |
| | | return BaseDal.QueryData(x => x.OrderDetailId == orderDetailId && outStockStatus == null ? true : x.Status == outStockStatus.ObjToInt()); |
| | | return BaseDal.QueryData(x => x.OrderDetailId == orderDetailId ); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using Microsoft.Extensions.Logging; |
| | | using SqlSugar; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | using WIDESEA_BasicService; |
| | | using WIDESEA_Common.CommonEnum; |
| | | using WIDESEA_Common.OrderEnum; |
| | | using WIDESEA_Common.StockEnum; |
| | | using WIDESEA_Core; |
| | | using WIDESEA_Core.BaseRepository; |
| | | using WIDESEA_Core.BaseServices; |
| | | using WIDESEA_DTO.Outbound; |
| | | using WIDESEA_IAllocateService; |
| | | using WIDESEA_IBasicService; |
| | | using WIDESEA_IOutboundService; |
| | | using WIDESEA_IStockService; |
| | | using WIDESEA_Model.Models; |
| | | using WIDESEA_Model.Models.Basic; |
| | | using WIDESEA_Model.Models.Outbound; |
| | | using static WIDESEA_OutboundService.OutboundBatchPickingService; |
| | | |
| | | namespace WIDESEA_OutboundService |
| | | { |
| | | public class OutboundBatchPickingService : ServiceBase<Dt_PickingRecord, IRepository<Dt_PickingRecord>>, IOutboundBatchPickingService |
| | | { |
| | | |
| | | |
| | | private readonly IUnitOfWorkManage _unitOfWorkManage; |
| | | public IRepository<Dt_PickingRecord> Repository => BaseDal; |
| | | |
| | | private readonly IStockInfoService _stockInfoService; |
| | | private readonly IStockService _stockService; |
| | | private readonly IOutStockLockInfoService _outStockLockInfoService; |
| | | private readonly IStockInfoDetailService _stockInfoDetailService; |
| | | private readonly ILocationInfoService _locationInfoService; |
| | | private readonly IOutboundOrderDetailService _outboundOrderDetailService; |
| | | private readonly IOutboundOrderService _outboundOrderService; |
| | | private readonly ISplitPackageService _splitPackageService; |
| | | private readonly IRepository<Dt_Task> _taskRepository; |
| | | private readonly IESSApiService _eSSApiService; |
| | | private readonly IInvokeMESService _invokeMESService; |
| | | private readonly IDailySequenceService _dailySequenceService; |
| | | private readonly IAllocateService _allocateService; |
| | | private readonly IRepository<Dt_OutboundBatch> _outboundBatchRepository; |
| | | private readonly ILogger<OutboundPickingService> _logger; |
| | | |
| | | private Dictionary<string, string> stations = new Dictionary<string, string> |
| | | { |
| | | {"2-1","2-9" }, |
| | | {"3-1","3-9" }, |
| | | |
| | | }; |
| | | |
| | | private Dictionary<string, string> movestations = new Dictionary<string, string> |
| | | { |
| | | {"2-1","2-5" }, |
| | | {"3-1","3-5" }, |
| | | |
| | | }; |
| | | |
| | | 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) |
| | | { |
| | | _unitOfWorkManage = unitOfWorkManage; |
| | | _stockInfoService = stockInfoService; |
| | | _stockService = stockService; |
| | | _outStockLockInfoService = outStockLockInfoService; |
| | | _stockInfoDetailService = stockInfoDetailService; |
| | | _locationInfoService = locationInfoService; |
| | | _outboundOrderDetailService = outboundOrderDetailService; |
| | | _splitPackageService = splitPackageService; |
| | | _outboundOrderService = outboundOrderService; |
| | | _taskRepository = taskRepository; |
| | | _eSSApiService = eSSApiService; |
| | | _logger = logger; |
| | | _invokeMESService = invokeMESService; |
| | | _dailySequenceService = dailySequenceService; |
| | | _allocateService = allocateService; |
| | | _outboundBatchRepository = outboundBatchRepository; |
| | | } |
| | | |
| | | // <summary> |
| | | /// è·åæççéå®ä¿¡æ¯ |
| | | /// </summary> |
| | | public async Task<List<PalletLockInfoDto>> GetPalletLockInfos(string orderNo, string palletCode) |
| | | { |
| | | var lockInfos = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.OrderNo == orderNo && x.PalletCode == palletCode) |
| | | .Select(x => new |
| | | { |
| | | x.Id, |
| | | x.OrderNo, |
| | | x.BatchNo, |
| | | x.MaterielCode, |
| | | x.CurrentBarcode, |
| | | x.AssignQuantity, |
| | | x.PickedQty, |
| | | x.Status, |
| | | x.LocationCode, |
| | | x.PalletCode |
| | | }).ToListAsync(); |
| | | |
| | | var lockInfoDtos = lockInfos.Select(x => new PalletLockInfoDto |
| | | { |
| | | Id = x.Id, |
| | | OrderNo = x.OrderNo, |
| | | BatchNo = x.BatchNo, |
| | | MaterielCode = x.MaterielCode, |
| | | CurrentBarcode = x.CurrentBarcode, |
| | | AssignQuantity = x.AssignQuantity, |
| | | PickedQty = x.PickedQty, |
| | | Status = x.Status, |
| | | LocationCode = x.LocationCode, |
| | | PalletCode = x.PalletCode, |
| | | CanSplit = (x.Status == (int)OutLockStockStatusEnum.åºåºä¸ && x.AssignQuantity - x.PickedQty > 0), |
| | | CanPick = (x.Status == (int)OutLockStockStatusEnum.åºåºä¸ && x.PickedQty < x.AssignQuantity) |
| | | }).ToList(); |
| | | |
| | | return lockInfoDtos; |
| | | } |
| | | #region æ¥è¯¢æ¹æ³ |
| | | |
| | | /// <summary> |
| | | /// è·åæççå·²æ£éå表 |
| | | /// </summary> |
| | | public async Task<List<PalletPickedInfoDto>> GetPalletPickedList(string orderNo, string palletCode) |
| | | { |
| | | var pickedList = await Db.Queryable<Dt_PickingRecord>() |
| | | .Where(x => x.OrderNo == orderNo && |
| | | x.PalletCode == palletCode && |
| | | !x.IsCancelled) |
| | | .Select(x => new PalletPickedInfoDto |
| | | { |
| | | Id = x.Id, |
| | | OrderNo = x.OrderNo, |
| | | OrderDetailId = x.OrderDetailId, |
| | | PalletCode = x.PalletCode, |
| | | Barcode = x.Barcode, |
| | | MaterielCode = x.MaterielCode, |
| | | PickedQty = x.PickQuantity, |
| | | PickTime = x.PickTime, |
| | | Operator = x.Operator, |
| | | LocationCode = x.LocationCode |
| | | }) |
| | | .ToListAsync(); |
| | | |
| | | return pickedList; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è·åæçç¶æ |
| | | /// </summary> |
| | | public async Task<PalletStatusDto> GetPalletStatus(string orderNo, string palletCode) |
| | | { |
| | | // è·åæççéå®ä¿¡æ¯ |
| | | var lockInfos = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.OrderNo == orderNo && x.PalletCode == palletCode) |
| | | .ToListAsync(); |
| | | |
| | | if (!lockInfos.Any()) |
| | | { |
| | | return new PalletStatusDto |
| | | { |
| | | OrderNo = orderNo, |
| | | PalletCode = palletCode, |
| | | Status = (int)PalletStatusEnum.æ ä»»å¡, |
| | | StatusText = "æ ä»»å¡", |
| | | TotalItems = 0, |
| | | CompletedItems = 0, |
| | | PendingItems = 0 |
| | | }; |
| | | } |
| | | |
| | | var totalItems = lockInfos.Count; |
| | | var completedItems = lockInfos.Count(x => x.Status == (int)OutLockStockStatusEnum.æ£é宿); |
| | | var pendingItems = lockInfos.Count(x => x.Status == (int)OutLockStockStatusEnum.åºåºä¸); |
| | | |
| | | var status = PalletStatusEnum.æ£éä¸; |
| | | if (pendingItems == 0 && completedItems > 0) |
| | | { |
| | | status = PalletStatusEnum.已宿; |
| | | } |
| | | else if (pendingItems > 0 && completedItems == 0) |
| | | { |
| | | status = PalletStatusEnum.æªå¼å§; |
| | | } |
| | | else if (pendingItems > 0 && completedItems > 0) |
| | | { |
| | | status = PalletStatusEnum.æ£éä¸; |
| | | } |
| | | |
| | | return new PalletStatusDto |
| | | { |
| | | OrderNo = orderNo, |
| | | PalletCode = palletCode, |
| | | Status = (int)status, |
| | | StatusText = GetPalletStatusText(status), |
| | | TotalItems = totalItems, |
| | | CompletedItems = completedItems, |
| | | PendingItems = pendingItems |
| | | }; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è·åæå
ä¿¡æ¯ |
| | | /// </summary> |
| | | public async Task<SplitPackageInfoDto> GetSplitPackageInfo(string orderNo, string palletCode, string barcode) |
| | | { |
| | | // æ¥æ¾éå®ä¿¡æ¯ |
| | | var lockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.OrderNo == orderNo && |
| | | x.PalletCode == palletCode && |
| | | x.CurrentBarcode == barcode |
| | | //&& x.Status == (int)OutLockStockStatusEnum.åºåºä¸ |
| | | ) |
| | | .FirstAsync(); |
| | | |
| | | if (lockInfo == null) |
| | | throw new Exception("æªæ¾å°ææçéå®ä¿¡æ¯"); |
| | | |
| | | // 计ç®å©ä½å¯ææ°é |
| | | var remainQuantity = lockInfo.AssignQuantity - lockInfo.PickedQty; |
| | | |
| | | return new SplitPackageInfoDto |
| | | { |
| | | OrderNo = orderNo, |
| | | PalletCode = palletCode, |
| | | Barcode = barcode, |
| | | MaterielCode = lockInfo.MaterielCode, |
| | | RemainQuantity = remainQuantity, |
| | | AssignQuantity = lockInfo.AssignQuantity, |
| | | PickedQty = lockInfo.PickedQty |
| | | }; |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region å走空箱é»è¾ |
| | | |
| | | /// <summary> |
| | | /// å走空箱 - æ¸
ç已宿æ£éçæçæ°æ® |
| | | /// </summary> |
| | | public async Task<WebResponseContent> RemoveEmptyPallet(string orderNo, string palletCode) |
| | | { |
| | | try |
| | | { |
| | | _unitOfWorkManage.BeginTran(); |
| | | |
| | | // éªè¯æçæ¯å¦å¯ä»¥åèµ°ï¼å¿
é¡»å
¨é¨å®ææ£éï¼ |
| | | var validationResult = await ValidateEmptyPalletRemoval(orderNo, palletCode); |
| | | if (!validationResult.IsValid) |
| | | return WebResponseContent.Instance.Error(validationResult.ErrorMessage); |
| | | |
| | | var completedLocks = validationResult.Data; |
| | | |
| | | // æ¸
çéå®è®°å½ï¼æ è®°ä¸ºå·²å®æï¼ |
| | | await CleanupCompletedLocks(completedLocks); |
| | | |
| | | // æ´æ°ç¸å
³è®¢åç¶æ |
| | | await UpdateOrderStatusAfterPalletRemoval(orderNo); |
| | | |
| | | // è®°å½æä½åå² |
| | | // await RecordEmptyPalletRemoval(orderNo, palletCode, completedLocks); |
| | | |
| | | _unitOfWorkManage.CommitTran(); |
| | | |
| | | return WebResponseContent.Instance.OK("å走空箱æå"); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _unitOfWorkManage.RollbackTran(); |
| | | _logger.LogError($"å走空箱失败 - OrderNo: {orderNo}, PalletCode: {palletCode}, Error: {ex.Message}"); |
| | | return WebResponseContent.Instance.Error($"å走空箱失败ï¼{ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// éªè¯ç©ºç®±åèµ°æ¡ä»¶ |
| | | /// </summary> |
| | | private async Task<ValidationResult<List<Dt_OutStockLockInfo>>> ValidateEmptyPalletRemoval(string orderNo, string palletCode) |
| | | { |
| | | // è·åæççææéå®è®°å½ |
| | | var lockInfos = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.OrderNo == orderNo && x.PalletCode == palletCode) |
| | | .ToListAsync(); |
| | | |
| | | if (!lockInfos.Any()) |
| | | return ValidationResult<List<Dt_OutStockLockInfo>>.Error("该æç没æéå®è®°å½"); |
| | | |
| | | // æ£æ¥æ¯å¦ææªå®æçéå®è®°å½ |
| | | var unfinishedLocks = lockInfos.Where(x => |
| | | x.Status == (int)OutLockStockStatusEnum.åºåºä¸ || |
| | | x.Status == (int)OutLockStockStatusEnum.ååºä¸).ToList(); |
| | | |
| | | if (unfinishedLocks.Any()) |
| | | { |
| | | var unfinishedCount = unfinishedLocks.Count; |
| | | var unfinishedQty = unfinishedLocks.Sum(x => x.AssignQuantity - x.PickedQty); |
| | | return ValidationResult<List<Dt_OutStockLockInfo>>.Error( |
| | | $"æçè¿æ{unfinishedCount}æ¡æªå®æè®°å½ï¼å©ä½æ°é{unfinishedQty}ï¼ä¸è½å走空箱"); |
| | | } |
| | | |
| | | // è·å已宿çéå®è®°å½ |
| | | var completedLocks = lockInfos.Where(x => |
| | | x.Status == (int)OutLockStockStatusEnum.æ£é宿).ToList(); |
| | | |
| | | if (!completedLocks.Any()) |
| | | return ValidationResult<List<Dt_OutStockLockInfo>>.Error("该æç没æå·²å®ææ£éçè®°å½"); |
| | | |
| | | return ValidationResult<List<Dt_OutStockLockInfo>>.Success(completedLocks); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ¸
ç已宿çéå®è®°å½ |
| | | /// </summary> |
| | | private async Task CleanupCompletedLocks(List<Dt_OutStockLockInfo> completedLocks) |
| | | { |
| | | foreach (var lockInfo in completedLocks) |
| | | { |
| | | // æ è®°éå®è®°å½ä¸ºå·²åèµ°ï¼å¯ä»¥æ°å¢ç¶ææç´æ¥å é¤ï¼æ ¹æ®ä¸å¡éæ±ï¼ |
| | | // è¿éæä»¬å°å
¶ç¶ææ´æ°ä¸º"å·²åèµ°"ï¼å¹¶è®°å½åèµ°æ¶é´ |
| | | lockInfo.Status = (int)OutLockStockStatusEnum.å·²åèµ°; |
| | | lockInfo.Operator = App.User.UserName; |
| | | await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync(); |
| | | |
| | | // åæ¶æ¸
ç对åºçåºåè®°å½ç¶æ |
| | | await CleanupStockInfo(lockInfo); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ¸
çåºåä¿¡æ¯ |
| | | /// </summary> |
| | | private async Task CleanupStockInfo(Dt_OutStockLockInfo lockInfo) |
| | | { |
| | | var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .FirstAsync(x => x.Barcode == lockInfo.CurrentBarcode && x.StockId == lockInfo.StockId); |
| | | |
| | | if (stockDetail != null) |
| | | { |
| | | // 妿åºåå·²ç»åºåºå®æï¼æ 记为已æ¸
ç |
| | | if (stockDetail.Status == (int)StockStatusEmun.åºåºå®æ) |
| | | { |
| | | stockDetail.Status = (int)StockStatusEmun.å·²æ¸
ç; |
| | | await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ´æ°è®¢åç¶æ |
| | | /// </summary> |
| | | private async Task UpdateOrderStatusAfterPalletRemoval(string orderNo) |
| | | { |
| | | // æ£æ¥è®¢åæ¯å¦æææçé½å·²å®æ |
| | | var allLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.OrderNo == orderNo) |
| | | .ToListAsync(); |
| | | |
| | | var unfinishedPallets = allLocks |
| | | .GroupBy(x => x.PalletCode) |
| | | .Where(g => g.Any(x => x.Status == (int)OutLockStockStatusEnum.åºåºä¸ || |
| | | x.Status == (int)OutLockStockStatusEnum.ååºä¸)) |
| | | .ToList(); |
| | | |
| | | // å¦ææ²¡ææªå®æçæçï¼æ´æ°è®¢åç¶æä¸ºåºåºå®æ |
| | | if (!unfinishedPallets.Any()) |
| | | { |
| | | await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>() |
| | | .SetColumns(x => new Dt_OutboundOrder |
| | | { |
| | | OrderStatus = (int)OutOrderStatusEnum.åºåºå®æ, |
| | | }) |
| | | .Where(x => x.OrderNo == orderNo) |
| | | .ExecuteCommandAsync(); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è®°å½ç©ºç®±åèµ°åå² |
| | | /// </summary> |
| | | private async Task RecordEmptyPalletRemoval(string orderNo, string palletCode, List<Dt_OutStockLockInfo> completedLocks) |
| | | { |
| | | var removalRecord = new Dt_EmptyPalletRemoval |
| | | { |
| | | OrderNo = orderNo, |
| | | PalletCode = palletCode, |
| | | RemovalTime = DateTime.Now, |
| | | Operator = App.User.UserName, |
| | | CompletedItemsCount = completedLocks.Count, |
| | | TotalPickedQuantity = completedLocks.Sum(x => x.PickedQty) |
| | | }; |
| | | |
| | | await Db.Insertable(removalRecord).ExecuteCommandAsync(); |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region è¾
婿¹æ³ |
| | | |
| | | private string GetPalletStatusText(PalletStatusEnum status) |
| | | { |
| | | return status switch |
| | | { |
| | | PalletStatusEnum.æªå¼å§ => "æªå¼å§", |
| | | PalletStatusEnum.æ£éä¸ => "æ£éä¸", |
| | | PalletStatusEnum.已宿 => "已宿", |
| | | PalletStatusEnum.æ ä»»å¡ => "æ ä»»å¡", |
| | | _ => "æªç¥" |
| | | }; |
| | | } |
| | | |
| | | #endregion |
| | | #region 忹忣 |
| | | |
| | | /// <summary> |
| | | /// åæ¹åæ£ç¡®è®¤ |
| | | /// </summary> |
| | | public async Task<WebResponseContent> ConfirmBatchPicking(string orderNo, string palletCode, string barcode) |
| | | { |
| | | try |
| | | { |
| | | _unitOfWorkManage.BeginTran(); |
| | | |
| | | // 1. éªè¯åæ£è¯·æ± |
| | | var validationResult = await ValidatePickingRequest(orderNo, palletCode, barcode); |
| | | if (!validationResult.IsValid) |
| | | return WebResponseContent.Instance.Error(validationResult.ErrorMessage); |
| | | |
| | | var (lockInfo, orderDetail, stockDetail, batch) = validationResult.Data; |
| | | |
| | | // 使ç¨éå®ä¿¡æ¯çåé
æ°éä½ä¸ºå®é
忣æ°é |
| | | var actualPickedQty = lockInfo.AssignQuantity; |
| | | |
| | | // 2. æ§è¡åæ£é»è¾ |
| | | var pickingResult = await ExecutePickingLogic(lockInfo, orderDetail, stockDetail, actualPickedQty); |
| | | |
| | | // 3. æ´æ°æ¹æ¬¡åè®¢åæ°æ® |
| | | await UpdateBatchAndOrderData(batch, orderDetail, actualPickedQty, orderNo); |
| | | |
| | | // 4. è®°å½æ£éåå² |
| | | await RecordPickingHistory(pickingResult, orderNo, palletCode); |
| | | |
| | | _unitOfWorkManage.CommitTran(); |
| | | |
| | | return WebResponseContent.Instance.OK("忣æå", new |
| | | { |
| | | PickedQuantity = actualPickedQty, |
| | | Barcode = barcode, |
| | | MaterialCode = lockInfo.MaterielCode |
| | | }); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _unitOfWorkManage.RollbackTran(); |
| | | _logger.LogError($"åæ£å¤±è´¥ - OrderNo: {orderNo}, PalletCode: {palletCode}, Barcode: {barcode}, Error: {ex.Message}"); |
| | | return WebResponseContent.Instance.Error($"åæ£å¤±è´¥ï¼{ex.Message}"); |
| | | } |
| | | } |
| | | /// <summary> |
| | | /// 忶忣 |
| | | /// </summary> |
| | | public async Task<WebResponseContent> CancelPicking(string orderNo, string palletCode, string barcode) |
| | | { |
| | | try |
| | | { |
| | | _unitOfWorkManage.BeginTran(); |
| | | |
| | | // æ¥æ¾åæ£è®°å½ |
| | | var pickingRecord = await Db.Queryable<Dt_PickingRecord>() |
| | | .Where(x => x.OrderNo == orderNo && |
| | | x.PalletCode == palletCode && |
| | | x.Barcode == barcode && |
| | | !x.IsCancelled) |
| | | .OrderByDescending(x => x.PickTime) |
| | | .FirstAsync(); |
| | | |
| | | if (pickingRecord == null) |
| | | return WebResponseContent.Instance.Error("æªæ¾å°åæ£è®°å½"); |
| | | |
| | | // æ¢å¤éå®ä¿¡æ¯ååºå |
| | | await RevertPickingData(pickingRecord); |
| | | |
| | | //æ´æ°æ¹æ¬¡åè®¢åæ°æ® |
| | | await RevertBatchAndOrderData(pickingRecord); |
| | | |
| | | // æ è®°åæ£è®°å½ä¸ºå·²åæ¶ |
| | | pickingRecord.IsCancelled = true; |
| | | pickingRecord.CancelTime = DateTime.Now; |
| | | pickingRecord.CancelOperator = App.User.UserName; |
| | | await Db.Updateable(pickingRecord).ExecuteCommandAsync(); |
| | | |
| | | _unitOfWorkManage.CommitTran(); |
| | | |
| | | return WebResponseContent.Instance.OK("忶忣æå"); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _unitOfWorkManage.RollbackTran(); |
| | | _logger.LogError($"åæ¶åæ£å¤±è´¥ - OrderNo: {orderNo}, PalletCode: {palletCode}, Error: {ex.Message}"); |
| | | return WebResponseContent.Instance.Error($"åæ¶åæ£å¤±è´¥ï¼{ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region æå¨æå
|
| | | |
| | | /// <summary> |
| | | /// æå¨æå
|
| | | /// </summary> |
| | | public async Task<WebResponseContent> ManualSplitPackage(string orderNo, string palletCode, string originalBarcode, decimal splitQuantity) |
| | | { |
| | | try |
| | | { |
| | | _unitOfWorkManage.BeginTran(); |
| | | |
| | | // éªè¯æå
è¯·æ± |
| | | var validationResult = await ValidateSplitRequest(orderNo, palletCode, originalBarcode, splitQuantity); |
| | | if (!validationResult.IsValid) |
| | | return WebResponseContent.Instance.Error(validationResult.ErrorMessage); |
| | | |
| | | var (lockInfo, stockDetail) = validationResult.Data; |
| | | |
| | | // . æ§è¡æå
é»è¾ |
| | | var splitResult = await ExecuteSplitLogic(lockInfo, stockDetail, splitQuantity, palletCode); |
| | | |
| | | _unitOfWorkManage.CommitTran(); |
| | | |
| | | return WebResponseContent.Instance.OK("æå¨æå
æå", new |
| | | { |
| | | NewBarcode = splitResult.NewBarcode, |
| | | OriginalBarcode = originalBarcode, |
| | | SplitQuantity = splitQuantity |
| | | }); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _unitOfWorkManage.RollbackTran(); |
| | | _logger.LogError($"æå¨æå
失败 - OrderNo: {orderNo}, Barcode: {originalBarcode}, Error: {ex.Message}"); |
| | | return WebResponseContent.Instance.Error($"æå¨æå
失败ï¼{ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region åæ¶æå
|
| | | |
| | | #region åæ¶æå
- ä¿®å¤çæ¬ |
| | | |
| | | /// <summary> |
| | | /// åæ¶æå
- æ¯æå¤æ¬¡æå
çæ
åµ |
| | | /// </summary> |
| | | public async Task<WebResponseContent> CancelSplitPackage(string orderNo, string palletCode, string newBarcode) |
| | | { |
| | | try |
| | | { |
| | | _unitOfWorkManage.BeginTran(); |
| | | |
| | | // 1. æ¥æ¾æå
è®°å½å¹¶éªè¯ |
| | | var validationResult = await ValidateCancelSplitRequest(orderNo, palletCode, newBarcode); |
| | | if (!validationResult.IsValid) |
| | | return WebResponseContent.Instance.Error(validationResult.ErrorMessage); |
| | | |
| | | var (splitRecord, newLockInfo, newStockDetail) = validationResult.Data; |
| | | |
| | | // 2. æ¥æ¾åå§éå®ä¿¡æ¯ |
| | | var originalLockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .FirstAsync(x => x.Id == splitRecord.OutStockLockInfoId); |
| | | |
| | | // 3. æ£æ¥è¯¥æ¡ç æ¯å¦è¢«å次æå
|
| | | var childSplitRecords = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>() |
| | | .Where(x => x.OriginalBarcode == newBarcode && !x.IsReverted) |
| | | .ToListAsync(); |
| | | |
| | | if (childSplitRecords.Any()) |
| | | { |
| | | return WebResponseContent.Instance.Error("该æ¡ç å·²è¢«åæ¬¡æå
ï¼è¯·å
åæ¶åç»çæå
æä½"); |
| | | } |
| | | |
| | | // 4. æ§è¡åæ¶æå
é»è¾ |
| | | await ExecuteCancelSplitLogic(splitRecord, originalLockInfo, newLockInfo, newStockDetail); |
| | | |
| | | _unitOfWorkManage.CommitTran(); |
| | | |
| | | return WebResponseContent.Instance.OK("åæ¶æå
æå"); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _unitOfWorkManage.RollbackTran(); |
| | | _logger.LogError($"åæ¶æå
失败 - OrderNo: {orderNo}, PalletCode: {palletCode}, Barcode: {newBarcode}, Error: {ex.Message}"); |
| | | return WebResponseContent.Instance.Error($"åæ¶æå
失败ï¼{ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ§è¡åæ¶æå
é»è¾ - ä¿®å¤çæ¬ |
| | | /// </summary> |
| | | private async Task ExecuteCancelSplitLogic(Dt_SplitPackageRecord splitRecord, |
| | | Dt_OutStockLockInfo originalLockInfo, Dt_OutStockLockInfo newLockInfo, |
| | | Dt_StockInfoDetail newStockDetail) |
| | | { |
| | | // 1. æ¢å¤åéå®ä¿¡æ¯ |
| | | // 注æï¼è¿ééè¦ç´¯å ï¼è䏿¯ç®åçèµå¼ï¼å 为å¯è½æå¤æ¬¡æå
|
| | | originalLockInfo.AssignQuantity += splitRecord.SplitQty; |
| | | originalLockInfo.OrderQuantity += splitRecord.SplitQty; |
| | | |
| | | // 妿åéå®ä¿¡æ¯çç¶ææ¯æ£é宿ï¼éè¦éæ°è®¾ç½®ä¸ºåºåºä¸ |
| | | if (originalLockInfo.Status == (int)OutLockStockStatusEnum.æ£é宿) |
| | | { |
| | | originalLockInfo.Status = (int)OutLockStockStatusEnum.åºåºä¸; |
| | | } |
| | | |
| | | await _outStockLockInfoService.Db.Updateable(originalLockInfo).ExecuteCommandAsync(); |
| | | |
| | | // 2. æ¢å¤ååºåæç» |
| | | var originalStock = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .FirstAsync(x => x.Barcode == splitRecord.OriginalBarcode && x.StockId == splitRecord.StockId); |
| | | |
| | | originalStock.StockQuantity += splitRecord.SplitQty; |
| | | |
| | | // 妿ååºåç¶ææ¯åºåºå®æï¼éè¦éæ°è®¾ç½®ä¸ºåºåºéå® |
| | | if (originalStock.Status == (int)StockStatusEmun.åºåºå®æ) |
| | | { |
| | | originalStock.Status = (int)StockStatusEmun.åºåºéå®; |
| | | } |
| | | |
| | | await _stockInfoDetailService.Db.Updateable(originalStock).ExecuteCommandAsync(); |
| | | |
| | | // 3. å 餿°éå®ä¿¡æ¯ |
| | | await _outStockLockInfoService.Db.Deleteable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.Id == newLockInfo.Id) |
| | | .ExecuteCommandAsync(); |
| | | |
| | | // 4. å 餿°åºåæç» |
| | | await _stockInfoDetailService.Db.Deleteable<Dt_StockInfoDetail>() |
| | | .Where(x => x.Barcode == newLockInfo.CurrentBarcode) |
| | | .ExecuteCommandAsync(); |
| | | |
| | | // 5. æ è®°æå
è®°å½ä¸ºå·²æ¤é |
| | | splitRecord.IsReverted = true; |
| | | splitRecord.RevertTime = DateTime.Now; |
| | | splitRecord.RevertOperator = App.User.UserName; |
| | | await _splitPackageService.Db.Updateable(splitRecord).ExecuteCommandAsync(); |
| | | |
| | | // 6. æ£æ¥å¹¶æ´æ°æ¹æ¬¡å订åç¶æ |
| | | await CheckAndUpdateBatchStatus(originalLockInfo.BatchNo); |
| | | await CheckAndUpdateOrderStatus(originalLockInfo.OrderNo); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// éªè¯åæ¶æå
è¯·æ± - å¢å¼ºçæ¬ |
| | | /// </summary> |
| | | private async Task<ValidationResult<(Dt_SplitPackageRecord, Dt_OutStockLockInfo, Dt_StockInfoDetail)>> ValidateCancelSplitRequest( |
| | | string orderNo, string palletCode, string newBarcode) |
| | | { |
| | | // æ¥æ¾æå
è®°å½ |
| | | var splitRecord = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>() |
| | | .Where(x => x.NewBarcode == newBarcode && |
| | | x.OrderNo == orderNo && |
| | | !x.IsReverted) |
| | | .FirstAsync(); |
| | | |
| | | if (splitRecord == null) |
| | | return ValidationResult<(Dt_SplitPackageRecord, Dt_OutStockLockInfo, Dt_StockInfoDetail)>.Error("æªæ¾å°æå
è®°å½"); |
| | | |
| | | // æ¥æ¾æ°éå®ä¿¡æ¯ |
| | | var newLockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.CurrentBarcode == newBarcode && |
| | | x.PalletCode == palletCode && |
| | | x.OrderNo == orderNo) |
| | | .FirstAsync(); |
| | | |
| | | if (newLockInfo == null) |
| | | return ValidationResult<(Dt_SplitPackageRecord, Dt_OutStockLockInfo, Dt_StockInfoDetail)>.Error("æªæ¾å°æ°éå®ä¿¡æ¯"); |
| | | |
| | | // æ£æ¥æ°æ¡ç æ¯å¦å·²è¢«åæ£ |
| | | var pickingRecord = await Db.Queryable<Dt_PickingRecord>() |
| | | .Where(x => x.Barcode == newBarcode && !x.IsCancelled) |
| | | .FirstAsync(); |
| | | |
| | | if (pickingRecord != null) |
| | | return ValidationResult<(Dt_SplitPackageRecord, Dt_OutStockLockInfo, Dt_StockInfoDetail)>.Error("该æ¡ç å·²è¢«åæ£ï¼æ æ³åæ¶æå
"); |
| | | |
| | | // æ£æ¥æ°æ¡ç æ¯å¦è¢«å次æå
|
| | | var childSplitRecords = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>() |
| | | .Where(x => x.OriginalBarcode == newBarcode && !x.IsReverted) |
| | | .ToListAsync(); |
| | | |
| | | if (childSplitRecords.Any()) |
| | | { |
| | | var childBarcodes = string.Join(", ", childSplitRecords.Select(x => x.NewBarcode)); |
| | | return ValidationResult<(Dt_SplitPackageRecord, Dt_OutStockLockInfo, Dt_StockInfoDetail)>.Error( |
| | | $"该æ¡ç å·²è¢«åæ¬¡æå
ï¼çæçæ°æ¡ç ï¼{childBarcodes}ï¼è¯·å
åæ¶åç»æå
"); |
| | | } |
| | | |
| | | var newStockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .FirstAsync(x => x.Barcode == newBarcode); |
| | | |
| | | return ValidationResult<(Dt_SplitPackageRecord, Dt_OutStockLockInfo, Dt_StockInfoDetail)>.Success((splitRecord, newLockInfo, newStockDetail)); |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region æ¹éåæ¶æå
é¾ |
| | | |
| | | /// <summary> |
| | | /// æ¹éåæ¶æå
é¾ - åæ¶æä¸ªæ¡ç åå
¶ææåç»æå
|
| | | /// </summary> |
| | | public async Task<WebResponseContent> CancelSplitPackageChain(string orderNo, string palletCode, string startBarcode) |
| | | { |
| | | try |
| | | { |
| | | _unitOfWorkManage.BeginTran(); |
| | | |
| | | // 1. æ¥æ¾ææç¸å
³çæå
è®°å½ï¼å½¢ææå
é¾ï¼ |
| | | var splitChain = await GetSplitPackageChain(orderNo, startBarcode); |
| | | |
| | | if (!splitChain.Any()) |
| | | return WebResponseContent.Instance.Error("æªæ¾å°æå
è®°å½"); |
| | | |
| | | // 2. ææå
顺åºååºåæ¶ï¼ä»ææ°çå¼å§åæ¶ï¼ |
| | | var reversedChain = splitChain.OrderByDescending(x => x.SplitTime).ToList(); |
| | | |
| | | foreach (var splitRecord in reversedChain) |
| | | { |
| | | await CancelSingleSplitPackage(splitRecord, palletCode); |
| | | } |
| | | |
| | | _unitOfWorkManage.CommitTran(); |
| | | |
| | | return WebResponseContent.Instance.OK($"æååæ¶æå
é¾ï¼å
±{reversedChain.Count}次æå
æä½"); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _unitOfWorkManage.RollbackTran(); |
| | | _logger.LogError($"åæ¶æå
é¾å¤±è´¥ - OrderNo: {orderNo}, StartBarcode: {startBarcode}, Error: {ex.Message}"); |
| | | return WebResponseContent.Instance.Error($"åæ¶æå
é¾å¤±è´¥ï¼{ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è·åæå
é¾ - æ¥æ¾æä¸ªæ¡ç çæææå
è®°å½ï¼å
æ¬åç»æå
ï¼ |
| | | /// </summary> |
| | | public async Task<List<Dt_SplitPackageRecord>> GetSplitPackageChain(string orderNo, string startBarcode) |
| | | { |
| | | var allSplitRecords = new List<Dt_SplitPackageRecord>(); |
| | | var visitedBarcodes = new HashSet<string>(); // 鲿¢å¾ªç¯å¼ç¨ |
| | | |
| | | // 使ç¨éåè¿è¡å¹¿åº¦ä¼å
æç´¢ |
| | | var queue = new Queue<string>(); |
| | | queue.Enqueue(startBarcode); |
| | | visitedBarcodes.Add(startBarcode); |
| | | |
| | | while (queue.Count > 0) |
| | | { |
| | | var currentBarcode = queue.Dequeue(); |
| | | |
| | | // æ¥æ¾ä»¥å½åæ¡ç ä¸ºåæ¡ç çæææå
è®°å½ |
| | | var splitRecords = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>() |
| | | .Where(x => x.OriginalBarcode == currentBarcode && |
| | | x.OrderNo == orderNo && |
| | | !x.IsReverted) |
| | | .ToListAsync(); |
| | | |
| | | foreach (var record in splitRecords) |
| | | { |
| | | // é¿å
éå¤å¤ç |
| | | if (!visitedBarcodes.Contains(record.NewBarcode)) |
| | | { |
| | | allSplitRecords.Add(record); |
| | | queue.Enqueue(record.NewBarcode); |
| | | visitedBarcodes.Add(record.NewBarcode); |
| | | } |
| | | } |
| | | } |
| | | |
| | | return allSplitRecords; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// åæ¶å个æå
è®°å½ |
| | | /// </summary> |
| | | private async Task CancelSingleSplitPackage(Dt_SplitPackageRecord splitRecord, string palletCode) |
| | | { |
| | | // æ¥æ¾ç¸å
³æ°æ® |
| | | var newLockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.CurrentBarcode == splitRecord.NewBarcode && |
| | | x.PalletCode == palletCode) |
| | | .FirstAsync(); |
| | | |
| | | var newStockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .FirstAsync(x => x.Barcode == splitRecord.NewBarcode); |
| | | |
| | | var originalLockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .FirstAsync(x => x.Id == splitRecord.OutStockLockInfoId); |
| | | |
| | | // æ§è¡åæ¶é»è¾ |
| | | await ExecuteCancelSplitLogic(splitRecord, originalLockInfo, newLockInfo, newStockDetail); |
| | | } |
| | | #endregion |
| | | |
| | | #region æå
ä¿¡æ¯æ¥è¯¢å¢å¼º |
| | | |
| | | /// <summary> |
| | | /// è·åæå
é¾ä¿¡æ¯ |
| | | /// </summary> |
| | | public async Task<WebResponseContent> GetSplitPackageChainInfo(string orderNo, string barcode) |
| | | { |
| | | try |
| | | { |
| | | var splitChain = await GetSplitPackageChain(orderNo, barcode); |
| | | |
| | | var chainInfo = new SplitPackageChainInfoDto |
| | | { |
| | | OriginalBarcode = barcode, |
| | | TotalSplitTimes = splitChain.Count, |
| | | SplitChain = splitChain.Select(x => new SplitChainItemDto |
| | | { |
| | | SplitTime = x.SplitTime, |
| | | OriginalBarcode = x.OriginalBarcode, |
| | | NewBarcode = x.NewBarcode, |
| | | SplitQuantity = x.SplitQty, |
| | | Operator = x.Operator, |
| | | IsReverted = x.IsReverted |
| | | }).ToList() |
| | | }; |
| | | |
| | | return WebResponseContent.Instance.OK("è·åæå", chainInfo); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _logger.LogError($"è·åæå
é¾ä¿¡æ¯å¤±è´¥ - OrderNo: {orderNo}, Barcode: {barcode}, Error: {ex.Message}"); |
| | | return WebResponseContent.Instance.Error("è·åæå
é¾ä¿¡æ¯å¤±è´¥"); |
| | | } |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// æ¥æ¾æ ¹æ¡ç |
| | | /// </summary> |
| | | public async Task<string> FindRootBarcode(string orderNo, string startBarcode) |
| | | { |
| | | var currentBarcode = startBarcode; |
| | | var visited = new HashSet<string>(); |
| | | |
| | | while (!string.IsNullOrEmpty(currentBarcode) && !visited.Contains(currentBarcode)) |
| | | { |
| | | visited.Add(currentBarcode); |
| | | |
| | | // æ¥æ¾å½åæ¡ç æ¯å¦æ¯ç±å
¶ä»æ¡ç æå
èæ¥ |
| | | var parentRecord = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>() |
| | | .Where(x => x.NewBarcode == currentBarcode && |
| | | x.OrderNo == orderNo && |
| | | !x.IsReverted) |
| | | .FirstAsync(); |
| | | |
| | | if (parentRecord == null) |
| | | { |
| | | // 没æç¶çº§æå
è®°å½ï¼è¯´æè¿æ¯æ ¹æ¡ç |
| | | return currentBarcode; |
| | | } |
| | | |
| | | currentBarcode = parentRecord.OriginalBarcode; |
| | | } |
| | | |
| | | // 妿åºç°å¾ªç¯å¼ç¨ï¼è¿åèµ·å§æ¡ç |
| | | return startBarcode; |
| | | } |
| | | #endregion |
| | | |
| | | #region æ´æ°æ¹æ¬¡ç¶ææ£æ¥ |
| | | |
| | | /// <summary> |
| | | /// æ£æ¥å¹¶æ´æ°æ¹æ¬¡ç¶æ |
| | | /// </summary> |
| | | private async Task CheckAndUpdateBatchStatus(string batchNo) |
| | | { |
| | | var batch = await _outboundBatchRepository.Db.Queryable<Dt_OutboundBatch>() |
| | | .FirstAsync(x => x.BatchNo == batchNo); |
| | | |
| | | if (batch != null) |
| | | { |
| | | // éæ°è®¡ç®æ¹æ¬¡å®ææ°é |
| | | var batchLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.BatchNo == batchNo) |
| | | .ToListAsync(); |
| | | |
| | | var completedQuantity = batchLocks.Where(x => x.Status == (int)OutLockStockStatusEnum.æ£é宿) |
| | | .Sum(x => x.PickedQty); |
| | | |
| | | batch.CompletedQuantity = completedQuantity; |
| | | |
| | | // æ´æ°æ¹æ¬¡ç¶æ |
| | | if (batch.CompletedQuantity >= batch.BatchQuantity) |
| | | { |
| | | batch.BatchStatus = (int)BatchStatusEnum.已宿; |
| | | } |
| | | else if (batch.CompletedQuantity > 0) |
| | | { |
| | | batch.BatchStatus = (int)BatchStatusEnum.æ§è¡ä¸; |
| | | } |
| | | else |
| | | { |
| | | batch.BatchStatus = (int)BatchStatusEnum.åé
ä¸; |
| | | } |
| | | |
| | | await _outboundBatchRepository.Db.Updateable(batch).ExecuteCommandAsync(); |
| | | } |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region DTOç±» |
| | | |
| | | |
| | | |
| | | public class SplitPackageChainInfoDto |
| | | { |
| | | public string OriginalBarcode { get; set; } |
| | | public string RootBarcode { get; set; } // æ°å¢ï¼æ ¹æ¡ç |
| | | public int TotalSplitTimes { get; set; } |
| | | public string ChainType { get; set; } // "root" æ "branch" |
| | | public List<SplitChainItemDto> SplitChain { get; set; } |
| | | } |
| | | |
| | | public class SplitChainItemDto |
| | | { |
| | | public DateTime SplitTime { get; set; } |
| | | public string OriginalBarcode { get; set; } |
| | | public string NewBarcode { get; set; } |
| | | public decimal SplitQuantity { get; set; } |
| | | public string Operator { get; set; } |
| | | public bool IsReverted { get; set; } |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #endregion |
| | | |
| | | #region åæ¹ååº |
| | | |
| | | /// <summary> |
| | | /// åæ¹ååº - éæ¾æªæ£éçåºå |
| | | /// </summary> |
| | | public async Task<WebResponseContent> BatchReturnStock(string orderNo, string palletCode) |
| | | { |
| | | try |
| | | { |
| | | _unitOfWorkManage.BeginTran(); |
| | | |
| | | // æ¥æ¾æç䏿ªå®æçéå®è®°å½ |
| | | var unfinishedLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.OrderNo == orderNo && |
| | | x.PalletCode == palletCode && |
| | | x.Status == (int)OutLockStockStatusEnum.åºåºä¸) |
| | | .ToListAsync(); |
| | | |
| | | if (!unfinishedLocks.Any()) |
| | | return WebResponseContent.Instance.Error("该æçæ²¡ææªå®æçéå®è®°å½"); |
| | | |
| | | // ææ¹æ¬¡åç»å¤ç |
| | | var batchGroups = unfinishedLocks.GroupBy(x => x.BatchNo); |
| | | |
| | | foreach (var batchGroup in batchGroups) |
| | | { |
| | | var batchNo = batchGroup.Key; |
| | | var batchLocks = batchGroup.ToList(); |
| | | |
| | | // éæ¾åºååéå®è®°å½ |
| | | foreach (var lockInfo in batchLocks) |
| | | { |
| | | await ReleaseLockAndStock(lockInfo); |
| | | } |
| | | |
| | | // æ´æ°æ¹æ¬¡ç¶æ |
| | | await UpdateBatchStatusForReturn(batchNo, batchLocks); |
| | | |
| | | // æ´æ°è®¢åæç»çå·²åé
æ°é |
| | | await UpdateOrderDetailAfterReturn(batchLocks); |
| | | } |
| | | |
| | | _unitOfWorkManage.CommitTran(); |
| | | |
| | | return WebResponseContent.Instance.OK("åæ¹ååºæå"); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _unitOfWorkManage.RollbackTran(); |
| | | _logger.LogError($"åæ¹ååºå¤±è´¥ - OrderNo: {orderNo}, PalletCode: {palletCode}, Error: {ex.Message}"); |
| | | return WebResponseContent.Instance.Error($"åæ¹ååºå¤±è´¥ï¼{ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region éªè¯æ¹æ³ |
| | | private async Task<ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail, Dt_OutboundBatch)>> ValidatePickingRequest( |
| | | string orderNo, string palletCode, string barcode) |
| | | { |
| | | // æ¥æ¾éå®ä¿¡æ¯ |
| | | var lockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.OrderNo == orderNo && |
| | | x.PalletCode == palletCode && |
| | | x.CurrentBarcode == barcode && |
| | | x.Status == (int)OutLockStockStatusEnum.åºåºä¸) |
| | | .FirstAsync(); |
| | | |
| | | if (lockInfo == null) |
| | | return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail, Dt_OutboundBatch)>.Error("æªæ¾å°ææçéå®ä¿¡æ¯"); |
| | | |
| | | // æ£æ¥æ¯å¦å·²ç»åæ£å®æ |
| | | if (lockInfo.PickedQty >= lockInfo.AssignQuantity) |
| | | return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail, Dt_OutboundBatch)>.Error("该æ¡ç 已忣宿"); |
| | | |
| | | // è·åå
³èæ°æ® |
| | | var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | .FirstAsync(x => x.Id == lockInfo.OrderDetailId); |
| | | |
| | | var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .FirstAsync(x => x.Barcode == barcode && x.StockId == lockInfo.StockId); |
| | | |
| | | // éªè¯åºåæ°é |
| | | if (stockDetail.StockQuantity < lockInfo.AssignQuantity) |
| | | return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail, Dt_OutboundBatch)>.Error( |
| | | $"åºåæ°éä¸è¶³ï¼éè¦ï¼{lockInfo.AssignQuantity}ï¼å®é
ï¼{stockDetail.StockQuantity}"); |
| | | |
| | | var batch = await _outboundBatchRepository.Db.Queryable<Dt_OutboundBatch>() |
| | | .FirstAsync(x => x.BatchNo == lockInfo.OutboundBatchNo); |
| | | |
| | | return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail, Dt_OutboundBatch)>.Success((lockInfo, orderDetail, stockDetail, batch)); |
| | | } |
| | | |
| | | private async Task<ValidationResult<(Dt_OutStockLockInfo, Dt_StockInfoDetail)>> ValidateSplitRequest( |
| | | string orderNo, string palletCode, string originalBarcode, decimal splitQuantity) |
| | | { |
| | | var lockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.OrderNo == orderNo && |
| | | x.PalletCode == palletCode && |
| | | x.CurrentBarcode == originalBarcode && |
| | | x.Status == (int)OutLockStockStatusEnum.åºåºä¸) |
| | | .FirstAsync(); |
| | | |
| | | if (lockInfo == null) |
| | | return ValidationResult<(Dt_OutStockLockInfo, Dt_StockInfoDetail)>.Error("æªæ¾å°ææçéå®ä¿¡æ¯"); |
| | | |
| | | var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .FirstAsync(x => x.Barcode == originalBarcode && x.StockId == lockInfo.StockId); |
| | | |
| | | if (stockDetail.StockQuantity < splitQuantity) |
| | | return ValidationResult<(Dt_OutStockLockInfo, Dt_StockInfoDetail)>.Error("æå
æ°éä¸è½å¤§äºåºåæ°é"); |
| | | |
| | | if (lockInfo.AssignQuantity - lockInfo.PickedQty < splitQuantity) |
| | | return ValidationResult<(Dt_OutStockLockInfo, Dt_StockInfoDetail)>.Error("æå
æ°éä¸è½å¤§äºæªæ£éæ°é"); |
| | | |
| | | return ValidationResult<(Dt_OutStockLockInfo, Dt_StockInfoDetail)>.Success((lockInfo, stockDetail)); |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region æ ¸å¿é»è¾æ¹æ³ |
| | | |
| | | private async Task<PickingResult> ExecutePickingLogic( |
| | | Dt_OutStockLockInfo lockInfo, Dt_OutboundOrderDetail orderDetail, |
| | | Dt_StockInfoDetail stockDetail, decimal actualPickedQty) |
| | | { |
| | | // æ´æ°éå®ä¿¡æ¯ |
| | | lockInfo.PickedQty += actualPickedQty; |
| | | if (lockInfo.PickedQty >= lockInfo.AssignQuantity) |
| | | { |
| | | lockInfo.Status = (int)OutLockStockStatusEnum.æ£é宿; |
| | | } |
| | | await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync(); |
| | | |
| | | // æ´æ°åºå |
| | | stockDetail.StockQuantity -= actualPickedQty; |
| | | stockDetail.OutboundQuantity += actualPickedQty; |
| | | |
| | | if (stockDetail.StockQuantity <= 0) |
| | | { |
| | | stockDetail.Status = (int)StockStatusEmun.åºåºå®æ; |
| | | } |
| | | await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync(); |
| | | |
| | | return new PickingResult |
| | | { |
| | | FinalLockInfo = lockInfo, |
| | | ActualPickedQty = actualPickedQty |
| | | }; |
| | | } |
| | | |
| | | private async Task<RevertPickingResult> RevertPickingData(Dt_PickingRecord pickingRecord) |
| | | { |
| | | // æ¢å¤éå®ä¿¡æ¯ |
| | | var lockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .FirstAsync(x => x.Id == pickingRecord.OutStockLockId); |
| | | |
| | | lockInfo.PickedQty -= pickingRecord.PickQuantity; |
| | | lockInfo.Status = (int)OutLockStockStatusEnum.åºåºä¸; |
| | | await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync(); |
| | | |
| | | // æ¢å¤åºå |
| | | var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .FirstAsync(x => x.Barcode == pickingRecord.Barcode); |
| | | |
| | | stockDetail.StockQuantity += pickingRecord.PickQuantity; |
| | | stockDetail.OutboundQuantity -= pickingRecord.PickQuantity; |
| | | stockDetail.Status = (int)StockStatusEmun.åºåºéå®; |
| | | await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync(); |
| | | |
| | | return new RevertPickingResult |
| | | { |
| | | LockInfo = lockInfo, |
| | | StockDetail = stockDetail |
| | | }; |
| | | } |
| | | |
| | | private async Task<SplitResultDto> ExecuteSplitLogic(Dt_OutStockLockInfo lockInfo, Dt_StockInfoDetail stockDetail, |
| | | decimal splitQuantity, string palletCode) |
| | | { |
| | | // çææ°æ¡ç |
| | | string newBarcode = await GenerateNewBarcode(); |
| | | |
| | | // å建æ°åºåæç» |
| | | var newStockDetail = new Dt_StockInfoDetail |
| | | { |
| | | StockId = stockDetail.StockId, |
| | | MaterielCode = stockDetail.MaterielCode, |
| | | OrderNo = stockDetail.OrderNo, |
| | | BatchNo = stockDetail.BatchNo, |
| | | StockQuantity = splitQuantity, |
| | | OutboundQuantity = 0, |
| | | Barcode = newBarcode, |
| | | Status = (int)StockStatusEmun.åºåºéå®, |
| | | SupplyCode = stockDetail.SupplyCode, |
| | | Unit = stockDetail.Unit, |
| | | BarcodeQty=stockDetail.BarcodeQty, |
| | | BarcodeUnit=stockDetail.BarcodeUnit, |
| | | BusinessType=stockDetail.BusinessType, |
| | | InboundOrderRowNo=stockDetail.InboundOrderRowNo, |
| | | |
| | | |
| | | }; |
| | | await _stockInfoDetailService.Db.Insertable(newStockDetail).ExecuteCommandAsync(); |
| | | |
| | | // æ´æ°ååºåæç» |
| | | stockDetail.StockQuantity -= splitQuantity; |
| | | await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync(); |
| | | |
| | | |
| | | var newLockInfo = new Dt_OutStockLockInfo |
| | | { |
| | | OrderNo = lockInfo.OrderNo, |
| | | OrderDetailId = lockInfo.OrderDetailId, |
| | | BatchNo = lockInfo.BatchNo, |
| | | MaterielCode = lockInfo.MaterielCode, |
| | | MaterielName = lockInfo.MaterielName, |
| | | StockId = lockInfo.StockId, |
| | | OrderQuantity = splitQuantity, |
| | | //OriginalQuantity = quantity, |
| | | AssignQuantity = splitQuantity, |
| | | PickedQty = 0, |
| | | LocationCode = lockInfo.LocationCode, |
| | | PalletCode = lockInfo.PalletCode, |
| | | TaskNum = lockInfo.TaskNum, |
| | | Status = (int)OutLockStockStatusEnum.åºåºä¸, |
| | | Unit = lockInfo.Unit, |
| | | SupplyCode = lockInfo.SupplyCode, |
| | | OrderType = lockInfo.OrderType, |
| | | CurrentBarcode = newBarcode, |
| | | // OriginalLockQuantity = quantity, |
| | | IsSplitted = 1, |
| | | ParentLockId = lockInfo.Id, |
| | | Operator = App.User.UserName, |
| | | FactoryArea = lockInfo.FactoryArea, |
| | | lineNo = lockInfo.lineNo, |
| | | WarehouseCode = lockInfo.WarehouseCode, |
| | | BarcodeQty = lockInfo.BarcodeQty, |
| | | BarcodeUnit = lockInfo.BarcodeUnit, |
| | | |
| | | }; |
| | | |
| | | await _outStockLockInfoService.Db.Insertable(newLockInfo).ExecuteCommandAsync(); |
| | | |
| | | // æ´æ°åéå®ä¿¡æ¯ |
| | | lockInfo.AssignQuantity -= splitQuantity; |
| | | lockInfo.OrderQuantity -= splitQuantity; |
| | | await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync(); |
| | | |
| | | // è®°å½æå
åå² |
| | | await RecordSplitHistory(lockInfo, stockDetail, splitQuantity, newBarcode); |
| | | |
| | | return new SplitResultDto { NewBarcode = newBarcode }; |
| | | } |
| | | |
| | | private async Task ExecuteCancelSplitLogic(Dt_SplitPackageRecord splitRecord, Dt_OutStockLockInfo newLockInfo, Dt_StockInfoDetail newStockDetail) |
| | | { |
| | | // æ¢å¤ååºå |
| | | var originalStock = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .FirstAsync(x => x.Barcode == splitRecord.OriginalBarcode && x.StockId == splitRecord.StockId); |
| | | |
| | | originalStock.StockQuantity += splitRecord.SplitQty; |
| | | await _stockInfoDetailService.Db.Updateable(originalStock).ExecuteCommandAsync(); |
| | | |
| | | // æ¢å¤åéå®ä¿¡æ¯ |
| | | var originalLockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .FirstAsync(x => x.Id == splitRecord.OutStockLockInfoId); |
| | | |
| | | originalLockInfo.AssignQuantity += splitRecord.SplitQty; |
| | | originalLockInfo.OrderQuantity += splitRecord.SplitQty; |
| | | await _outStockLockInfoService.Db.Updateable(originalLockInfo).ExecuteCommandAsync(); |
| | | |
| | | // å 餿°åºåæç» |
| | | await _stockInfoDetailService.Db.Deleteable<Dt_StockInfoDetail>() |
| | | .Where(x => x.Barcode == newLockInfo.CurrentBarcode) |
| | | .ExecuteCommandAsync(); |
| | | |
| | | // å 餿°éå®ä¿¡æ¯ |
| | | await _outStockLockInfoService.Db.Deleteable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.Id == newLockInfo.Id) |
| | | .ExecuteCommandAsync(); |
| | | |
| | | // æ è®°æå
è®°å½ä¸ºå·²æ¤é |
| | | splitRecord.IsReverted = true; |
| | | splitRecord.RevertTime = DateTime.Now; |
| | | splitRecord.RevertOperator = App.User.UserName; |
| | | await _splitPackageService.Db.Updateable(splitRecord).ExecuteCommandAsync(); |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region æ°æ®æ´æ°æ¹æ³ |
| | | |
| | | private async Task UpdateBatchAndOrderData(Dt_OutboundBatch batch, Dt_OutboundOrderDetail orderDetail, decimal pickedQty, string orderNo) |
| | | { |
| | | // æ´æ°æ¹æ¬¡å®ææ°é |
| | | batch.CompletedQuantity += pickedQty; |
| | | if (batch.CompletedQuantity >= batch.BatchQuantity) |
| | | { |
| | | batch.BatchStatus = (int)BatchStatusEnum.已宿; |
| | | } |
| | | await _outboundBatchRepository.Db.Updateable(batch).ExecuteCommandAsync(); |
| | | |
| | | // æ´æ°è®¢åæç» |
| | | orderDetail.OverOutQuantity += pickedQty; |
| | | orderDetail.AllocatedQuantity -= pickedQty; |
| | | await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync(); |
| | | |
| | | // æ£æ¥è®¢åç¶æ |
| | | await CheckAndUpdateOrderStatus(orderNo); |
| | | } |
| | | |
| | | private async Task RevertBatchAndOrderData(Dt_PickingRecord pickingRecord) |
| | | { |
| | | // æ¢å¤æ¹æ¬¡å®ææ°é |
| | | var batch = await _outboundBatchRepository.Db.Queryable<Dt_OutboundBatch>() |
| | | .FirstAsync(x => x.BatchNo == pickingRecord.BatchNo); |
| | | |
| | | batch.CompletedQuantity -= pickingRecord.PickQuantity; |
| | | batch.BatchStatus = (int)BatchStatusEnum.æ§è¡ä¸; |
| | | await _outboundBatchRepository.Db.Updateable(batch).ExecuteCommandAsync(); |
| | | |
| | | // æ¢å¤è®¢åæç» |
| | | var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | .FirstAsync(x => x.Id == pickingRecord.OrderDetailId); |
| | | |
| | | orderDetail.OverOutQuantity -= pickingRecord.PickQuantity; |
| | | orderDetail.AllocatedQuantity += pickingRecord.PickQuantity; |
| | | await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync(); |
| | | |
| | | // éæ°æ£æ¥è®¢åç¶æ |
| | | await CheckAndUpdateOrderStatus(pickingRecord.OrderNo); |
| | | } |
| | | |
| | | private async Task ReleaseLockAndStock(Dt_OutStockLockInfo lockInfo) |
| | | { |
| | | // æ¢å¤åºåç¶æ |
| | | var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .FirstAsync(x => x.Barcode == lockInfo.CurrentBarcode && x.StockId == lockInfo.StockId); |
| | | |
| | | if (stockDetail != null) |
| | | { |
| | | stockDetail.Status = (int)StockStatusEmun.å
¥åºå®æ; |
| | | await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync(); |
| | | } |
| | | |
| | | // æ´æ°éå®è®°å½ç¶æä¸ºååº |
| | | lockInfo.Status = (int)OutLockStockStatusEnum.å·²ååº; |
| | | await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync(); |
| | | } |
| | | |
| | | private async Task UpdateBatchStatusForReturn(string batchNo, List<Dt_OutStockLockInfo> returnedLocks) |
| | | { |
| | | var batch = await _outboundBatchRepository.Db.Queryable<Dt_OutboundBatch>() |
| | | .FirstAsync(x => x.BatchNo == batchNo); |
| | | |
| | | // 计ç®ååºæ°é |
| | | var returnedQty = returnedLocks.Sum(x => x.AssignQuantity - x.PickedQty); |
| | | batch.CompletedQuantity -= returnedQty; |
| | | |
| | | if (batch.CompletedQuantity <= 0) |
| | | { |
| | | batch.BatchStatus = (int)BatchStatusEnum.å·²ååº; |
| | | } |
| | | else |
| | | { |
| | | batch.BatchStatus = (int)BatchStatusEnum.æ§è¡ä¸; |
| | | } |
| | | |
| | | batch.Operator = App.User.UserName; |
| | | await _outboundBatchRepository.Db.Updateable(batch).ExecuteCommandAsync(); |
| | | } |
| | | |
| | | private async Task UpdateOrderDetailAfterReturn(List<Dt_OutStockLockInfo> returnedLocks) |
| | | { |
| | | var orderDetailGroups = returnedLocks.GroupBy(x => x.OrderDetailId); |
| | | |
| | | foreach (var group in orderDetailGroups) |
| | | { |
| | | var orderDetailId = group.Key; |
| | | var returnedQty = group.Sum(x => x.AssignQuantity - x.PickedQty); |
| | | |
| | | await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>() |
| | | .SetColumns(x => x.AllocatedQuantity == x.AllocatedQuantity - returnedQty) |
| | | .Where(x => x.Id == orderDetailId) |
| | | .ExecuteCommandAsync(); |
| | | } |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region è¾
婿¹æ³ |
| | | |
| | | private async Task<string> GenerateNewBarcode() |
| | | { |
| | | var seq = await _dailySequenceService.GetNextSequenceAsync(); |
| | | return "WSLOT" + DateTime.Now.ToString("yyyyMMdd") + seq.ToString().PadLeft(5, '0'); |
| | | } |
| | | |
| | | private async Task RecordSplitHistory(Dt_OutStockLockInfo lockInfo, Dt_StockInfoDetail stockDetail, decimal splitQty, string newBarcode) |
| | | { |
| | | var splitHistory = new Dt_SplitPackageRecord |
| | | { |
| | | OrderNo = lockInfo.OrderNo, |
| | | OutStockLockInfoId = lockInfo.Id, |
| | | StockId = stockDetail.StockId, |
| | | Operator = App.User.UserName, |
| | | OriginalBarcode = stockDetail.Barcode, |
| | | NewBarcode = newBarcode, |
| | | SplitQty = splitQty, |
| | | SplitTime = DateTime.Now, |
| | | Status = (int)SplitPackageStatusEnum.å·²æå
|
| | | }; |
| | | |
| | | await _splitPackageService.Db.Insertable(splitHistory).ExecuteCommandAsync(); |
| | | } |
| | | |
| | | private async Task RecordPickingHistory(PickingResult result, string orderNo, string palletCode) |
| | | { |
| | | var pickingRecord = new Dt_PickingRecord |
| | | { |
| | | OrderNo = orderNo, |
| | | // BatchNo = result.FinalLockInfo.BatchNo, |
| | | OrderDetailId = result.FinalLockInfo.OrderDetailId, |
| | | PalletCode = palletCode, |
| | | Barcode = result.FinalLockInfo.CurrentBarcode, |
| | | MaterielCode = result.FinalLockInfo.MaterielCode, |
| | | PickQuantity = result.ActualPickedQty, |
| | | PickTime = DateTime.Now, |
| | | Operator = App.User.UserName, |
| | | OutStockLockId = result.FinalLockInfo.Id, |
| | | // IsCancelled = false |
| | | }; |
| | | |
| | | await Db.Insertable(pickingRecord).ExecuteCommandAsync(); |
| | | } |
| | | |
| | | private async Task CheckAndUpdateOrderStatus(string orderNo) |
| | | { |
| | | var orderDetails = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | .LeftJoin<Dt_OutboundOrder>((detail, order) => detail.OrderId == order.Id) |
| | | .Where((detail, order) => order.OrderNo == orderNo) |
| | | .Select((detail, order) => detail) |
| | | .ToListAsync(); |
| | | |
| | | bool allCompleted = orderDetails.All(x => x.OverOutQuantity >= x.NeedOutQuantity); |
| | | |
| | | var orderStatus = allCompleted ? (int)OutOrderStatusEnum.åºåºå®æ : (int)OutOrderStatusEnum.åºåºä¸; |
| | | |
| | | await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>() |
| | | .SetColumns(x => x.OrderStatus == orderStatus) |
| | | .Where(x => x.OrderNo == orderNo) |
| | | .ExecuteCommandAsync(); |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region DTOç±» |
| | | |
| | | public class PickingResult |
| | | { |
| | | public Dt_OutStockLockInfo FinalLockInfo { get; set; } |
| | | public decimal ActualPickedQty { get; set; } |
| | | } |
| | | |
| | | public class RevertPickingResult |
| | | { |
| | | public Dt_OutStockLockInfo LockInfo { get; set; } |
| | | public Dt_StockInfoDetail StockDetail { get; set; } |
| | | } |
| | | |
| | | public class SplitResultDto |
| | | { |
| | | public string NewBarcode { get; set; } |
| | | } |
| | | |
| | | public class ValidationResult<T> |
| | | { |
| | | public bool IsValid { get; set; } |
| | | public string ErrorMessage { get; set; } |
| | | public T Data { get; set; } |
| | | |
| | | public static ValidationResult<T> Success(T data) => new ValidationResult<T> { IsValid = true, Data = data }; |
| | | public static ValidationResult<T> Error(string message) => new ValidationResult<T> { IsValid = false, ErrorMessage = message }; |
| | | } |
| | | |
| | | #endregion |
| | | } |
| | | |
| | | |
| | | // æ¯æç±» |
| | | public class SplitResultDto |
| | | { |
| | | public string NewBarcode { get; set; } |
| | | } |
| | | } |
| | |
| | | private readonly IUnitOfWorkManage _unitOfWorkManage; |
| | | public IRepository<Dt_OutboundOrderDetail> Repository => BaseDal; |
| | | |
| | | |
| | | |
| | | private readonly IStockService _stockService; |
| | | |
| | | |
| | | private readonly IOutStockLockInfoService _outStockLockInfoService; |
| | | private readonly ILocationInfoService _locationInfoService; |
| | | private readonly IBasicService _basicService; |
| | |
| | | /// <summary> |
| | | /// åé
åºåºåºå æå
è¿å
åºåååé
|
| | | /// </summary> |
| | | public (List<Dt_StockInfo>, List<Dt_OutboundOrderDetail>, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>) AssignStockOutbound(List<Dt_OutboundOrderDetail> outboundOrderDetails) |
| | | public (List<Dt_StockInfo>, List<Dt_OutboundOrderDetail>, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>) |
| | | AssignStockOutbound(List<Dt_OutboundOrderDetail> outboundOrderDetails) |
| | | { |
| | | if (!outboundOrderDetails.Any()) |
| | | { |
| | |
| | | throw new Exception("请å¿åæ¶æä½å¤ä¸ªåæ®æç»"); |
| | | } |
| | | |
| | | var orderId = outboundOrderDetails.First().OrderId; |
| | | var outboundOrder = _outboundOrderService.Db.Queryable<Dt_OutboundOrder>() |
| | | .First(x => x.Id == outboundOrderDetails.First().OrderId); |
| | | .First(x => x.Id == orderId); |
| | | |
| | | if (!CanReassignOrder(outboundOrder)) |
| | | { |
| | | throw new Exception($"订å{outboundOrder.OrderNo}ç¶æä¸å
è®¸éæ°åé
åºå"); |
| | | } |
| | | |
| | | List<Dt_StockInfo> outStocks = new List<Dt_StockInfo>(); |
| | | List<Dt_OutStockLockInfo> outStockLockInfos = new List<Dt_OutStockLockInfo>(); |
| | |
| | | |
| | | // æç©æåæ¹æ¬¡åç»å¤ç |
| | | var groupDetails = outboundOrderDetails |
| | | .GroupBy(x => new { x.MaterielCode, x.BatchNo ,x.SupplyCode}) |
| | | .GroupBy(x => new { x.MaterielCode, x.BatchNo, x.SupplyCode }) |
| | | .Select(x => new |
| | | { |
| | | MaterielCode = x.Key.MaterielCode, |
| | | BatchNo = x.Key.BatchNo, |
| | | SupplyCode = x.Key.SupplyCode, |
| | | Details = x.ToList(), |
| | | TotalNeedQuantity = x.Sum(v => v.OrderQuantity - v.OverOutQuantity - v.LockQuantity-v.MoveQty) |
| | | TotalNeedQuantity = CalculateReassignNeedQuantity(x.ToList()) |
| | | }) |
| | | .Where(x => x.TotalNeedQuantity > 0) |
| | | .ToList(); |
| | |
| | | var needQuantity = item.TotalNeedQuantity; |
| | | |
| | | // è·åå¯ç¨åºåï¼æå
è¿å
åºæåºï¼ |
| | | List<Dt_StockInfo> stockInfos = _stockService.StockInfoService.GetUseableStocks(item.MaterielCode, item.BatchNo,item.SupplyCode); |
| | | List<Dt_StockInfo> stockInfos = _stockService.StockInfoService.GetUseableStocks(item.MaterielCode, item.BatchNo, item.SupplyCode); |
| | | |
| | | if (!stockInfos.Any()) |
| | | { |
| | | throw new Exception($"ç©æ[{item.MaterielCode}]æ¹æ¬¡[{item.BatchNo}]æªæ¾å°å¯åé
åºå"); |
| | | throw new Exception($"ç©æ[{item.MaterielCode}]æ¹æ¬¡[{item.BatchNo}]ä¾åºå[{item.SupplyCode}]æªæ¾å°å¯åé
åºå"); |
| | | } |
| | | |
| | | // åé
åºåï¼æå
è¿å
åºï¼ |
| | | var (autoAssignStocks, stockAllocations) = _stockService.StockInfoService.GetOutboundStocks( |
| | | stockInfos, item.MaterielCode, needQuantity, out decimal residueQuantity); |
| | | var (autoAssignStocks, stockAllocations) = _stockService.StockInfoService.GetOutboundStocks(stockInfos, item.MaterielCode, needQuantity, out decimal residueQuantity); |
| | | |
| | | if (residueQuantity > 0 && residueQuantity == needQuantity) |
| | | // æ£æ¥åé
ç»æï¼å¦æå®å
¨æ æ³åé
ï¼åé
æ°é为0ï¼ï¼åæ¥é |
| | | decimal allocatedQuantity = needQuantity - residueQuantity; |
| | | if (allocatedQuantity <= 0) |
| | | { |
| | | throw new Exception($"ç©æ[{item.MaterielCode}]åºåä¸è¶³ï¼éè¦{needQuantity}ï¼å¯ç¨{needQuantity - residueQuantity}"); |
| | | throw new Exception($"ç©æ[{item.MaterielCode}]æ¹æ¬¡[{item.BatchNo}]åºåä¸è¶³ï¼éè¦{needQuantity}ï¼ä½æ æ³åé
ä»»ä½åºå"); |
| | | } |
| | | |
| | | outStocks.AddRange(autoAssignStocks); |
| | | |
| | | // æå
è¿å
åºåååé
é宿°éå°å个æç» |
| | | DistributeLockQuantityByFIFO(item.Details, autoAssignStocks, stockAllocations, outStockLockInfos, outboundOrder); |
| | | var distributionResult = DistributeLockQuantityByFIFO(item.Details, autoAssignStocks, stockAllocations, outStockLockInfos, outboundOrder); |
| | | |
| | | if (!distributionResult.success) |
| | | { |
| | | throw new Exception(distributionResult.message); |
| | | } |
| | | |
| | | // æ´æ°åºåºåæç»ç¶æ |
| | | UpdateOrderDetailStatus(item.Details, allocatedQuantity, needQuantity); |
| | | } |
| | | |
| | | locationInfos.AddRange(_locationInfoService.GetLocationInfos(outStocks.Select(x => x.LocationCode).Distinct().ToList())); |
| | | if (outStocks.Any()) |
| | | { |
| | | locationInfos.AddRange(_locationInfoService.GetLocationInfos( |
| | | outStocks.Select(x => x.LocationCode).Distinct().ToList())); |
| | | } |
| | | |
| | | return (outStocks, outboundOrderDetails, outStockLockInfos, locationInfos); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æå
è¿å
åºåååé
é宿°éå°å个æç» |
| | | /// æ£æ¥è®¢åæ¯å¦å
è®¸éæ°åé
|
| | | /// </summary> |
| | | private void DistributeLockQuantityByFIFO( |
| | | List<Dt_OutboundOrderDetail> details, |
| | | List<Dt_StockInfo> assignStocks, |
| | | Dictionary<int, decimal> stockAllocations, |
| | | List<Dt_OutStockLockInfo> outStockLockInfos, |
| | | Dt_OutboundOrder outboundOrder) |
| | | private bool CanReassignOrder(Dt_OutboundOrder outboundOrder) |
| | | { |
| | | // æå
è¿å
åºæåºåºåºåæç»ï¼å设å
å建çæç»éè¦ä¼å
æ»¡è¶³ï¼ |
| | | // å
è®¸éæ°åé
çç¶æ |
| | | var allowedStatus = new[] {OutOrderStatusEnum.æªå¼å§, OutOrderStatusEnum.åºåºä¸,OutOrderStatusEnum.é¨å宿}; |
| | | |
| | | return allowedStatus.Contains((OutOrderStatusEnum)outboundOrder.OrderStatus); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// éæ°è®¡ç®éæ±æ°éï¼èèéæ°åé
çåºæ¯ï¼ |
| | | /// </summary> |
| | | private decimal CalculateReassignNeedQuantity(List<Dt_OutboundOrderDetail> details) |
| | | { |
| | | decimal totalNeed = 0; |
| | | |
| | | foreach (var detail in details) |
| | | { |
| | | // å
³é®ä¿®æ¹ï¼éæ°åé
æ¶ï¼åªèèæªåºåºçé¨åï¼å¿½ç¥é宿°é |
| | | // å 为é宿°éå¨ååºæ¶å·²ç»è¢«éç½® |
| | | decimal remainingNeed = detail.OrderQuantity - detail.OverOutQuantity - detail.MoveQty; |
| | | |
| | | if (remainingNeed > 0) |
| | | { |
| | | totalNeed += remainingNeed; |
| | | } |
| | | } |
| | | |
| | | return totalNeed; |
| | | } |
| | | private (bool success, string message) DistributeLockQuantityByFIFO( |
| | | List<Dt_OutboundOrderDetail> details, |
| | | List<Dt_StockInfo> assignStocks, |
| | | Dictionary<int, decimal> stockAllocations, |
| | | List<Dt_OutStockLockInfo> outStockLockInfos, |
| | | Dt_OutboundOrder outboundOrder) |
| | | { |
| | | // æå
è¿å
åºæåºåºåºåæç»ï¼Idå°çä¼å
ï¼ |
| | | var sortedDetails = details |
| | | .Where(d => d.OrderQuantity - d.OverOutQuantity - d.LockQuantity -d.MoveQty> 0) // åªå¤çè¿éè¦åé
çæ°é |
| | | .Where(d => d.OrderQuantity - d.OverOutQuantity - d.LockQuantity - d.MoveQty > 0) |
| | | .OrderBy(x => x.Id) |
| | | .ToList(); |
| | | |
| | | if (!sortedDetails.Any()) return; |
| | | if (!sortedDetails.Any()) |
| | | return (true, "æ éåé
"); |
| | | |
| | | // è·åææåé
äºåºåçæç»ï¼æå
è¿å
åºæåº |
| | | var allocatedStockDetails = assignStocks |
| | | .SelectMany(x => x.Details) |
| | | .Where(x => stockAllocations.ContainsKey(x.Id)) |
| | | .Where(x => stockAllocations.ContainsKey(x.Id) && stockAllocations[x.Id] > 0) |
| | | .OrderBy(x => x.CreateDate) |
| | | .ThenBy(x => x.StockId) |
| | | .ToList(); |
| | | |
| | | if (!allocatedStockDetails.Any()) |
| | | { |
| | | return (false, "没æå¯åé
çåºåæç»"); |
| | | } |
| | | |
| | | decimal totalNeedQuantity = sortedDetails.Sum(d => |
| | | d.OrderQuantity - d.OverOutQuantity - d.LockQuantity - d.MoveQty); |
| | | decimal allocatedQuantity = 0; |
| | | |
| | | // 为æ¯ä¸ªåºåæç»å建åé
è®°å½ |
| | | foreach (var stockDetail in allocatedStockDetails) |
| | | { |
| | | if (!stockAllocations.TryGetValue(stockDetail.Id, out decimal allocatedQuantity)) |
| | | if (!stockAllocations.TryGetValue(stockDetail.Id, out decimal allocatedQuantityForStock)) |
| | | continue; |
| | | |
| | | if (allocatedQuantity <= 0) continue; |
| | | if (allocatedQuantityForStock <= 0) continue; |
| | | |
| | | var stockInfo = assignStocks.First(x => x.Id == stockDetail.StockId); |
| | | decimal remainingAllocate = allocatedQuantity; |
| | | decimal remainingAllocate = allocatedQuantityForStock; |
| | | |
| | | // æé¡ºåºåé
ç»å个åºåºåæç» |
| | | foreach (var detail in sortedDetails) |
| | |
| | | if (remainingAllocate <= 0) break; |
| | | |
| | | // 计ç®è¿ä¸ªæç»è¿éè¦åé
çæ°é |
| | | var detailNeed = detail.OrderQuantity - detail.OverOutQuantity - detail.LockQuantity-detail.MoveQty; |
| | | var detailNeed = detail.OrderQuantity - detail.OverOutQuantity - detail.LockQuantity - detail.MoveQty; |
| | | if (detailNeed <= 0) continue; |
| | | |
| | | // åé
æ°é |
| | |
| | | // éªè¯æ¡ç æ¯å¦åå¨ |
| | | if (string.IsNullOrEmpty(stockDetail.Barcode)) |
| | | { |
| | | throw new Exception($"åºåæç»ID[{stockDetail.Id}]çæ¡ç 为空"); |
| | | return (false, $"åºåæç»ID[{stockDetail.Id}]çæ¡ç 为空"); |
| | | } |
| | | |
| | | // å建åºåºéå®ä¿¡æ¯ |
| | |
| | | // æ´æ°æç»çé宿°é |
| | | detail.LockQuantity += assignQuantity; |
| | | remainingAllocate -= assignQuantity; |
| | | allocatedQuantity += assignQuantity; |
| | | } |
| | | |
| | | // å¦æè¿æå©ä½åé
æ°éï¼éæ°åé
æè®°å½è¦å |
| | | // å¦æè¿æå©ä½åé
æ°éï¼è®°å½è¦å |
| | | if (remainingAllocate > 0) |
| | | { |
| | | // éæ°åé
ç»å
¶ä»éè¦åé
çæç» |
| | | foreach (var detail in sortedDetails) |
| | | _logger.LogWarning($"åºååé
å仿å©ä½æ°éæªåé
: {remainingAllocate}, æ¡ç : {stockDetail.Barcode}"); |
| | | } |
| | | } |
| | | |
| | | // éªè¯æ¯å¦è³å°åé
äºä¸é¨å |
| | | if (allocatedQuantity <= 0) |
| | | { |
| | | return (false, "åºååé
å¤±è´¥ï¼æ æ³åé
任使°é"); |
| | | } |
| | | |
| | | // è®°å½åé
ç»æ |
| | | if (allocatedQuantity < totalNeedQuantity) |
| | | { |
| | | _logger.LogWarning($"åºåé¨ååé
ï¼éè¦{totalNeedQuantity}ï¼å®é
åé
{allocatedQuantity}"); |
| | | } |
| | | else |
| | | { |
| | | _logger.LogInformation($"åºåå®å
¨åé
ï¼åé
æ°é{allocatedQuantity}"); |
| | | } |
| | | |
| | | return (true, "åé
æå"); |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// ä¸ºåæ¹åé
åºå |
| | | /// </summary> |
| | | public async Task<(List<Dt_StockInfo>, List<Dt_OutboundOrderDetail>, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>)> |
| | | AssignStockForBatch(Dt_OutboundOrderDetail orderDetail, decimal batchQuantity, string batchNo) |
| | | { |
| | | if (orderDetail == null) |
| | | { |
| | | throw new Exception("æªæ¾å°åºåºåæç»ä¿¡æ¯"); |
| | | } |
| | | |
| | | var outboundOrder = await _outboundOrderService.Db.Queryable<Dt_OutboundOrder>() |
| | | .FirstAsync(x => x.Id == orderDetail.OrderId); |
| | | |
| | | List<Dt_StockInfo> outStocks = new List<Dt_StockInfo>(); |
| | | List<Dt_OutStockLockInfo> outStockLockInfos = new List<Dt_OutStockLockInfo>(); |
| | | List<Dt_LocationInfo> locationInfos = new List<Dt_LocationInfo>(); |
| | | |
| | | // æç©æåæ¹æ¬¡åç»å¤çï¼è¿éåªæä¸ä¸ªæç»ï¼ |
| | | var groupDetails = new List<Dt_OutboundOrderDetail> { orderDetail } |
| | | .GroupBy(x => new { x.MaterielCode, x.BatchNo, x.SupplyCode }) |
| | | .Select(x => new |
| | | { |
| | | MaterielCode = x.Key.MaterielCode, |
| | | BatchNo = x.Key.BatchNo, |
| | | SupplyCode = x.Key.SupplyCode, |
| | | Details = x.ToList(), |
| | | TotalNeedQuantity = batchQuantity // 使ç¨åæ¹æ°é |
| | | }) |
| | | .Where(x => x.TotalNeedQuantity > 0) |
| | | .ToList(); |
| | | |
| | | foreach (var item in groupDetails) |
| | | { |
| | | var needQuantity = item.TotalNeedQuantity; |
| | | |
| | | // è·åå¯ç¨åºåï¼æå
è¿å
åºæåºï¼ |
| | | List<Dt_StockInfo> stockInfos = _stockService.StockInfoService.GetUseableStocks(item.MaterielCode, item.BatchNo, item.SupplyCode); |
| | | if (!stockInfos.Any()) |
| | | { |
| | | throw new Exception($"ç©æ[{item.MaterielCode}]æ¹æ¬¡[{item.BatchNo}]æªæ¾å°å¯åé
åºå"); |
| | | } |
| | | |
| | | // åé
åºåï¼æå
è¿å
åºï¼ |
| | | var (autoAssignStocks, stockAllocations) = _stockService.StockInfoService.GetOutboundStocks(stockInfos, item.MaterielCode, needQuantity, out decimal residueQuantity); |
| | | |
| | | // æ£æ¥åé
ç»æ |
| | | decimal allocatedQuantity = needQuantity - residueQuantity; |
| | | if (allocatedQuantity <= 0) |
| | | { |
| | | throw new Exception($"ç©æ[{item.MaterielCode}]æ¹æ¬¡[{item.BatchNo}]åºåä¸è¶³ï¼éè¦{needQuantity}ï¼ä½æ æ³åé
ä»»ä½åºå"); |
| | | } |
| | | |
| | | outStocks.AddRange(autoAssignStocks); |
| | | |
| | | // æå
è¿å
åºåååé
é宿°éå°å个æç» |
| | | var distributionResult = DistributeLockQuantityByFIFO(item.Details, autoAssignStocks, stockAllocations, outStockLockInfos, outboundOrder, batchNo); |
| | | |
| | | if (!distributionResult.success) |
| | | { |
| | | throw new Exception(distributionResult.message); |
| | | } |
| | | |
| | | // æ´æ°åºåºåæç»ç¶æ |
| | | UpdateOrderDetailStatus(item.Details, allocatedQuantity, needQuantity); |
| | | } |
| | | |
| | | if (outStocks.Any()) |
| | | { |
| | | locationInfos.AddRange(_locationInfoService.GetLocationInfos( |
| | | outStocks.Select(x => x.LocationCode).Distinct().ToList())); |
| | | |
| | | |
| | | } |
| | | |
| | | return (outStocks, groupDetails.SelectMany(x => x.Details).ToList(), outStockLockInfos, locationInfos); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æå
è¿å
åºåååé
é宿°é |
| | | /// </summary> |
| | | private (bool success, string message) DistributeLockQuantityByFIFO( |
| | | List<Dt_OutboundOrderDetail> details, |
| | | List<Dt_StockInfo> assignStocks, |
| | | Dictionary<int, decimal> stockAllocations, |
| | | List<Dt_OutStockLockInfo> outStockLockInfos, |
| | | Dt_OutboundOrder outboundOrder, |
| | | string batchNo) |
| | | { |
| | | var sortedDetails = details |
| | | .Where(d => d.OrderQuantity - d.OverOutQuantity - d.AllocatedQuantity > 0) |
| | | .OrderBy(x => x.Id) |
| | | .ToList(); |
| | | |
| | | if (!sortedDetails.Any()) |
| | | return (true, "æ éåé
"); |
| | | |
| | | // è·åææåé
äºåºåçæç»ï¼æå
è¿å
åºæåº |
| | | var allocatedStockDetails = assignStocks |
| | | .SelectMany(x => x.Details) |
| | | .Where(x => stockAllocations.ContainsKey(x.Id) && stockAllocations[x.Id] > 0) |
| | | .OrderBy(x => x.CreateDate) |
| | | .ThenBy(x => x.StockId) |
| | | .ToList(); |
| | | |
| | | if (!allocatedStockDetails.Any()) |
| | | { |
| | | return (false, "没æå¯åé
çåºåæç»"); |
| | | } |
| | | |
| | | decimal totalNeedQuantity = sortedDetails.Sum(d => |
| | | d.OrderQuantity - d.OverOutQuantity - d.AllocatedQuantity); |
| | | decimal allocatedQuantity = 0; |
| | | |
| | | // 为æ¯ä¸ªåºåæç»å建åé
è®°å½ |
| | | foreach (var stockDetail in allocatedStockDetails) |
| | | { |
| | | if (!stockAllocations.TryGetValue(stockDetail.Id, out decimal allocatedQuantityForStock)) |
| | | continue; |
| | | |
| | | if (allocatedQuantityForStock <= 0) continue; |
| | | |
| | | var stockInfo = assignStocks.First(x => x.Id == stockDetail.StockId); |
| | | decimal remainingAllocate = allocatedQuantityForStock; |
| | | |
| | | // æé¡ºåºåé
ç»å个åºåºåæç» |
| | | foreach (var detail in sortedDetails) |
| | | { |
| | | if (remainingAllocate <= 0) break; |
| | | |
| | | // 计ç®è¿ä¸ªæç»è¿éè¦åé
çæ°é |
| | | var detailNeed = detail.OrderQuantity - detail.OverOutQuantity - detail.AllocatedQuantity; |
| | | if (detailNeed <= 0) continue; |
| | | |
| | | // åé
æ°é |
| | | var assignQuantity = Math.Min(remainingAllocate, detailNeed); |
| | | |
| | | // éªè¯æ¡ç æ¯å¦åå¨ |
| | | if (string.IsNullOrEmpty(stockDetail.Barcode)) |
| | | { |
| | | if (remainingAllocate <= 0) break; |
| | | |
| | | var detailNeed = detail.OrderQuantity - detail.OverOutQuantity - detail.LockQuantity; |
| | | if (detailNeed <= 0) continue; |
| | | |
| | | var assignQuantity = Math.Min(remainingAllocate, detailNeed); |
| | | |
| | | var lockInfo = _outStockLockInfoService.GetOutStockLockInfo( |
| | | outboundOrder, detail, stockInfo, assignQuantity, stockDetail.Barcode); |
| | | outStockLockInfos.Add(lockInfo); |
| | | |
| | | detail.LockQuantity += assignQuantity; |
| | | remainingAllocate -= assignQuantity; |
| | | return (false, $"åºåæç»ID[{stockDetail.Id}]çæ¡ç 为空"); |
| | | } |
| | | |
| | | // å¦æè¿æå©ä½ï¼è®°å½è¦åä½ä¸æåºå¼å¸¸ |
| | | if (remainingAllocate > 0) |
| | | { |
| | | _logger.LogWarning($"åºååé
å仿å©ä½æ°éæªåé
: {remainingAllocate}, æ¡ç : {stockDetail.Barcode}"); |
| | | } |
| | | |
| | | // å建åºåºéå®ä¿¡æ¯ |
| | | var lockInfo = _outStockLockInfoService.GetOutStockLockInfo( |
| | | outboundOrder, detail, stockInfo, assignQuantity, stockDetail.Barcode, batchNo); |
| | | outStockLockInfos.Add(lockInfo); |
| | | |
| | | // æ´æ°æç»çå·²åé
æ°é |
| | | detail.AllocatedQuantity += assignQuantity; |
| | | remainingAllocate -= assignQuantity; |
| | | allocatedQuantity += assignQuantity; |
| | | } |
| | | |
| | | // å¦æè¿æå©ä½åé
æ°éï¼è®°å½è¦å |
| | | if (remainingAllocate > 0) |
| | | { |
| | | _logger.LogWarning($"åºååé
å仿å©ä½æ°éæªåé
: {remainingAllocate}, æ¡ç : {stockDetail.Barcode}"); |
| | | } |
| | | } |
| | | |
| | | // éªè¯æ¯å¦è³å°åé
äºä¸é¨å |
| | | if (allocatedQuantity <= 0) |
| | | { |
| | | return (false, "åºååé
å¤±è´¥ï¼æ æ³åé
任使°é"); |
| | | } |
| | | |
| | | // è®°å½åé
ç»æ |
| | | if (allocatedQuantity < totalNeedQuantity) |
| | | { |
| | | _logger.LogWarning($"åºåé¨ååé
ï¼éè¦{totalNeedQuantity}ï¼å®é
åé
{allocatedQuantity}"); |
| | | } |
| | | else |
| | | { |
| | | _logger.LogInformation($"åºåå®å
¨åé
ï¼åé
æ°é{allocatedQuantity}"); |
| | | } |
| | | |
| | | return (true, "åé
æå"); |
| | | } |
| | | |
| | | |
| | | private void UpdateOrderDetailStatus(List<Dt_OutboundOrderDetail> details, |
| | | decimal allocatedQuantity, decimal needQuantity) |
| | | { |
| | | foreach (var detail in details) |
| | | { |
| | | var detailNeed = detail.OrderQuantity - detail.LockQuantity - detail.OverOutQuantity - detail.MoveQty; |
| | | |
| | | if (detailNeed <= 0) |
| | | { |
| | | // 该æç»å·²å®å
¨åé
|
| | | detail.OrderDetailStatus = OrderDetailStatusEnum.AssignOver.ObjToInt(); |
| | | } |
| | | else if (allocatedQuantity < needQuantity) |
| | | { |
| | | // æ´ä½é¨ååé
ï¼è¯¥æç»å¯è½è¿æéæ± |
| | | detail.OrderDetailStatus = OrderDetailStatusEnum.AssignOverPartial.ObjToInt(); |
| | | } |
| | | else |
| | | { |
| | | // æ´ä½å®å
¨åé
|
| | | detail.OrderDetailStatus = OrderDetailStatusEnum.AssignOver.ObjToInt(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// åºåºåºååé
åï¼æ´æ°æ°æ®åºæ°æ® |
| | | /// </summary> |
| | |
| | | /// <param name="locationStatus"></param> |
| | | /// <param name="tasks"></param> |
| | | /// <returns></returns> |
| | | public WebResponseContent LockOutboundStockDataUpdate(List<Dt_StockInfo> stockInfos, List<Dt_OutboundOrderDetail> outboundOrderDetails, |
| | | List<Dt_OutStockLockInfo> outStockLockInfos, List<Dt_LocationInfo> locationInfos, |
| | | public WebResponseContent LockOutboundStockDataUpdate(List<Dt_StockInfo> stockInfos, List<Dt_OutboundOrderDetail> outboundOrderDetails, |
| | | List<Dt_OutStockLockInfo> outStockLockInfos, List<Dt_LocationInfo> locationInfos, |
| | | LocationStatusEnum locationStatus = LocationStatusEnum.Lock, List<Dt_Task>? tasks = null) |
| | | { |
| | | try |
| | |
| | | // æ´æ°åºåç¶æ |
| | | stockInfos.ForEach(x => x.StockStatus = (int)StockStatusEmun.åºåºéå®); |
| | | _stockService.StockInfoService.Repository.UpdateData(stockInfos); |
| | | |
| | | |
| | | // æ´æ°åºåæç» |
| | | var stockDetails = stockInfos.SelectMany(x => x.Details).ToList(); |
| | | _stockService.StockInfoDetailService.Repository.UpdateData(stockDetails); |
| | |
| | | SearchParameters? searchParameters = searchParametersList.FirstOrDefault(x => x.Name == nameof(Dt_InboundOrderDetail.OrderId).FirstLetterToLower()); |
| | | if (searchParameters != null) |
| | | { |
| | | sugarQueryable1 = sugarQueryable1.Where(x => x.OrderId== searchParameters.Value.ObjToInt()); |
| | | var dataList = sugarQueryable1.ToPageList(options.Page, options.Rows, ref totalCount); |
| | | sugarQueryable1 = sugarQueryable1.Where(x => x.OrderId == searchParameters.Value.ObjToInt()); |
| | | var dataList = sugarQueryable1.ToPageList(options.Page, options.Rows, ref totalCount); |
| | | return new PageGridData<Dt_OutboundOrderDetail>(totalCount, dataList); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | } |
| | | } |
| | | return new PageGridData<Dt_OutboundOrderDetail> (); |
| | | return new PageGridData<Dt_OutboundOrderDetail>(); |
| | | } |
| | | |
| | | |
| | | public (List<Dt_StockInfo>, Dt_OutboundOrderDetail, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>) AssignStockOutbound(Dt_OutboundOrderDetail outboundOrderDetail, List<StockSelectViewDTO> stockSelectViews) |
| | | public (List<Dt_StockInfo>, Dt_OutboundOrderDetail, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>) |
| | | AssignStockOutbound(Dt_OutboundOrderDetail outboundOrderDetail, List<StockSelectViewDTO> stockSelectViews) |
| | | { |
| | | // éªè¯ç¨æ·éæ© |
| | | (bool, string) checkResult = CheckSelectStockDeital(outboundOrderDetail, stockSelectViews); |
| | | if (!checkResult.Item1) throw new Exception(checkResult.Item2); |
| | | |
| | | Dt_OutboundOrder outboundOrder = _outboundOrderService.Repository.QueryFirst(x => x.Id == outboundOrderDetail.OrderId); |
| | | var originalNeedQuantity = outboundOrderDetail.OrderQuantity - outboundOrderDetail.LockQuantity; |
| | | var originalNeedQuantity = outboundOrderDetail.OrderQuantity - outboundOrderDetail.LockQuantity - outboundOrderDetail.MoveQty; |
| | | |
| | | var needQuantity = originalNeedQuantity; |
| | | List<Dt_StockInfo> outStocks = new List<Dt_StockInfo>(); |
| | | List<Dt_OutStockLockInfo> outStockLockInfos = new List<Dt_OutStockLockInfo>(); |
| | | |
| | | List<Dt_StockInfo> outStocks = _stockService.StockInfoService.GetStockInfosByPalletCodes(stockSelectViews.Select(x => x.PalletCode).ToList()); |
| | | var assignQuantity =0m; |
| | | outStocks.ForEach(x => |
| | | { |
| | | x.Details.ForEach(v => |
| | | { |
| | | assignQuantity += v.StockQuantity - v.OutboundQuantity; |
| | | }); |
| | | }); |
| | | decimal remainingNeedQuantity = originalNeedQuantity; |
| | | decimal totalAssignedFromUserSelection = 0; |
| | | |
| | | outboundOrderDetail.LockQuantity += assignQuantity; |
| | | outStocks.ForEach(x => |
| | | // æå
è¿å
åºæåºç¨æ·éæ©çåºå |
| | | var userSelectedStocks = _stockService.StockInfoService.GetStockInfosByPalletCodes( |
| | | stockSelectViews.Select(x => x.PalletCode).ToList()); |
| | | |
| | | var sortedUserSelectedStocks = userSelectedStocks |
| | | .OrderBy(x => x.CreateDate) |
| | | .ToList(); |
| | | |
| | | // åé
ç¨æ·éæ©çåºå |
| | | foreach (var stock in sortedUserSelectedStocks) |
| | | { |
| | | x.Details.ForEach(v => |
| | | if (remainingNeedQuantity <= 0) break; |
| | | |
| | | // è·åç¨æ·å¯¹è¯¥æççéæ©æ°é |
| | | var userSelection = stockSelectViews.FirstOrDefault(x => x.PalletCode == stock.PalletCode); |
| | | if (userSelection == null) continue; |
| | | |
| | | // 计ç®è¯¥æçå®é
å¯ç¨æ°é |
| | | var availableQuantity = CalculateAvailableQuantity(stock, outboundOrderDetail.MaterielCode, |
| | | outboundOrderDetail.BatchNo, outboundOrderDetail.SupplyCode); |
| | | |
| | | // ç¡®å®åé
æ°éï¼åç¨æ·éæ©æ°éãå¯ç¨æ°éåå©ä½éæ±çæå°å¼ |
| | | var assignQuantity = Math.Min( |
| | | Math.Min(userSelection.UseableQuantity, availableQuantity), |
| | | remainingNeedQuantity); |
| | | |
| | | if (assignQuantity <= 0) continue; |
| | | |
| | | // æ§è¡åé
|
| | | var actualAssigned = AssignStockQuantity(stock, outboundOrderDetail, assignQuantity); |
| | | if (actualAssigned > 0) |
| | | { |
| | | v.OutboundQuantity = v.StockQuantity; |
| | | }); |
| | | }); |
| | | needQuantity -= assignQuantity; |
| | | if (outboundOrderDetail.OrderQuantity > outboundOrderDetail.LockQuantity) |
| | | { |
| | | List<Dt_StockInfo> stockInfos = _stockService.StockInfoService.GetUseableStocks(outboundOrderDetail.MaterielCode, outboundOrderDetail.BatchNo,""); |
| | | stockInfos = stockInfos.Where(x => !stockSelectViews.Select(v => v.PalletCode).Contains(x.PalletCode)).ToList(); |
| | | var (autoAssignStocks, stockAllocations) = _stockService.StockInfoService.GetOutboundStocks(stockInfos, outboundOrderDetail.MaterielCode, needQuantity, out decimal residueQuantity); |
| | | outboundOrderDetail.LockQuantity += needQuantity - residueQuantity; |
| | | outStocks.AddRange(autoAssignStocks); |
| | | outboundOrderDetail.OrderDetailStatus = OrderDetailStatusEnum.AssignOver.ObjToInt(); |
| | | if (residueQuantity > 0) |
| | | { |
| | | outboundOrderDetail.OrderDetailStatus = OrderDetailStatusEnum.AssignOverPartial.ObjToInt(); |
| | | outStocks.Add(stock); |
| | | totalAssignedFromUserSelection += actualAssigned; |
| | | remainingNeedQuantity -= actualAssigned; |
| | | |
| | | // å建éå®è®°å½ |
| | | var lockInfo = CreateOutStockLockInfo(outboundOrder, outboundOrderDetail, stock, actualAssigned); |
| | | outStockLockInfos.Add(lockInfo); |
| | | } |
| | | } |
| | | |
| | | List<Dt_OutStockLockInfo> outStockLockInfos = _outStockLockInfoService.GetOutStockLockInfos(outboundOrder, outboundOrderDetail, outStocks); |
| | | // æ£æ¥ç¨æ·éæ©æ¯å¦è³å°åé
äºä¸é¨å |
| | | if (totalAssignedFromUserSelection <= 0) |
| | | { |
| | | throw new Exception("ç¨æ·éæ©çåºåæ æ³åé
任使°é"); |
| | | } |
| | | |
| | | // å¦æç¨æ·éæ©çåºåä¸å¤ï¼èªå¨åé
å©ä½é¨å |
| | | decimal autoAssignedQuantity = 0; |
| | | if (remainingNeedQuantity > 0) |
| | | { |
| | | List<Dt_StockInfo> autoStocks = _stockService.StockInfoService.GetUseableStocks( |
| | | outboundOrderDetail.MaterielCode, outboundOrderDetail.BatchNo, ""); |
| | | |
| | | // æé¤ç¨æ·å·²éæ©çæç |
| | | autoStocks = autoStocks |
| | | .Where(x => !stockSelectViews.Select(v => v.PalletCode).Contains(x.PalletCode)) |
| | | .ToList(); |
| | | |
| | | var (autoAssignStocks, stockAllocations) = _stockService.StockInfoService.GetOutboundStocks( |
| | | autoStocks, outboundOrderDetail.MaterielCode, remainingNeedQuantity, out decimal residueQuantity); |
| | | |
| | | // æ£æ¥èªå¨åé
ç»æ |
| | | autoAssignedQuantity = remainingNeedQuantity - residueQuantity; |
| | | if (autoAssignedQuantity <= 0 && remainingNeedQuantity > 0) |
| | | { |
| | | // é¨ååé
æ¯å¯ä»¥æ¥åçï¼è®°å½è¦åä½ä¸æ¥é |
| | | _logger.LogWarning($"èªå¨åé
失败ï¼å©ä½éæ±{remainingNeedQuantity}æ æ³æ»¡è¶³"); |
| | | } |
| | | else if (autoAssignedQuantity > 0) |
| | | { |
| | | outStocks.AddRange(autoAssignStocks); |
| | | |
| | | // 为èªå¨åé
çåºåå建éå®è®°å½ |
| | | var autoLockInfos = CreateLockInfosForAutoAssign(outboundOrder, outboundOrderDetail, autoAssignStocks, stockAllocations); |
| | | outStockLockInfos.AddRange(autoLockInfos); |
| | | } |
| | | } |
| | | |
| | | // æ´æ°é宿°é |
| | | outboundOrderDetail.LockQuantity += totalAssignedFromUserSelection + autoAssignedQuantity; |
| | | |
| | | // æ´æ°ç¶æ |
| | | UpdateOrderDetailStatus(outboundOrderDetail, remainingNeedQuantity - autoAssignedQuantity); |
| | | |
| | | List<Dt_LocationInfo> locationInfos = _locationInfoService.GetLocationInfos(outStocks.Select(x => x.LocationCode).ToList()); |
| | | |
| | | return (outStocks, outboundOrderDetail, outStockLockInfos, locationInfos); |
| | | } |
| | | private (bool, string) CheckSelectStockDeital(Dt_OutboundOrderDetail outboundOrderDetail, List<StockSelectViewDTO> stockSelectViews) |
| | | |
| | | // è¾
婿¹æ³ |
| | | private decimal CalculateAvailableQuantity(Dt_StockInfo stock, string materielCode, string batchNo, string supplyCode) |
| | | { |
| | | if (outboundOrderDetail == null) |
| | | { |
| | | return (false, "æªæ¾å°åºåºåæç»ä¿¡æ¯"); |
| | | } |
| | | if (outboundOrderDetail.OrderDetailStatus != OrderDetailStatusEnum.New.ObjToInt() && outboundOrderDetail.OrderDetailStatus != OrderDetailStatusEnum.AssignOverPartial.ObjToInt()) |
| | | { |
| | | return (false, "该æç»ä¸å¯æä½"); |
| | | } |
| | | if (stockSelectViews.Sum(x => x.UseableQuantity) > outboundOrderDetail.OrderQuantity - outboundOrderDetail.LockQuantity) |
| | | { |
| | | return (false, "éæ©æ°éè¶
åºåæ®æ°é"); |
| | | } |
| | | return (true, "æå"); |
| | | var relevantDetails = stock.Details |
| | | .Where(d => d.MaterielCode == materielCode && |
| | | (string.IsNullOrEmpty(batchNo) || d.BatchNo == batchNo) && |
| | | (string.IsNullOrEmpty(supplyCode) || d.SupplyCode == supplyCode)) |
| | | .ToList(); |
| | | |
| | | return relevantDetails.Sum(d => d.StockQuantity - d.OutboundQuantity); |
| | | } |
| | | |
| | | private decimal AssignStockQuantity(Dt_StockInfo stock, Dt_OutboundOrderDetail detail, decimal assignQuantity) |
| | | { |
| | | decimal remainingAssign = assignQuantity; |
| | | |
| | | // æå
è¿å
åºåé
åºåæç» |
| | | var sortedDetails = stock.Details |
| | | .Where(d => d.MaterielCode == detail.MaterielCode && |
| | | d.BatchNo == detail.BatchNo && |
| | | (d.StockQuantity - d.OutboundQuantity) > 0) |
| | | .OrderBy(d => d.CreateDate) |
| | | .ToList(); |
| | | |
| | | 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 Dt_OutStockLockInfo CreateOutStockLockInfo(Dt_OutboundOrder outboundOrder, Dt_OutboundOrderDetail detail, |
| | | Dt_StockInfo stock, decimal quantity) |
| | | { |
| | | var barcode = stock.Details |
| | | .Where(d => !string.IsNullOrEmpty(d.Barcode)) |
| | | .Select(d => d.Barcode) |
| | | .FirstOrDefault(); |
| | | |
| | | return _outStockLockInfoService.GetOutStockLockInfo(outboundOrder, detail, stock, quantity, barcode); |
| | | } |
| | | |
| | | private List<Dt_OutStockLockInfo> CreateLockInfosForAutoAssign(Dt_OutboundOrder outboundOrder, |
| | | Dt_OutboundOrderDetail detail, List<Dt_StockInfo> stocks, Dictionary<int, decimal> allocations) |
| | | { |
| | | var lockInfos = new List<Dt_OutStockLockInfo>(); |
| | | |
| | | foreach (var stock in stocks.OrderBy(x => x.CreateDate)) |
| | | { |
| | | if (allocations.TryGetValue(stock.Id, out decimal quantity) && quantity > 0) |
| | | { |
| | | var lockInfo = CreateOutStockLockInfo(outboundOrder, detail, stock, quantity); |
| | | lockInfos.Add(lockInfo); |
| | | } |
| | | } |
| | | |
| | | return lockInfos; |
| | | } |
| | | |
| | | private void UpdateOrderDetailStatus(Dt_OutboundOrderDetail detail, decimal remainingQuantity) |
| | | { |
| | | if (remainingQuantity <= 0) |
| | | { |
| | | detail.OrderDetailStatus = OrderDetailStatusEnum.AssignOver.ObjToInt(); |
| | | } |
| | | else |
| | | { |
| | | detail.OrderDetailStatus = OrderDetailStatusEnum.AssignOverPartial.ObjToInt(); |
| | | } |
| | | } |
| | | |
| | | private (bool, string) CheckSelectStockDeital(Dt_OutboundOrderDetail outboundOrderDetail, List<StockSelectViewDTO> stockSelectViews) |
| | | { |
| | | var needQuantity = outboundOrderDetail.OrderQuantity - outboundOrderDetail.LockQuantity - outboundOrderDetail.MoveQty; |
| | | |
| | | if (needQuantity <= 0) |
| | | { |
| | | return (false, "åºåºåæç»æ éåé
åºå"); |
| | | } |
| | | |
| | | // æ£æ¥æ»éæ©æ°éæ¯å¦å¤§äº0 |
| | | var totalSelected = stockSelectViews.Sum(x => x.UseableQuantity); |
| | | if (totalSelected <= 0) |
| | | { |
| | | return (false, "ç¨æ·éæ©çåºåæ°éå¿
须大äº0"); |
| | | } |
| | | |
| | | // æ£æ¥æ¯ä¸ªæççå¯ç¨æ°é |
| | | foreach (var selection in stockSelectViews) |
| | | { |
| | | if (selection.UseableQuantity <= 0) |
| | | { |
| | | return (false, $"æç[{selection.PalletCode}]çéæ©æ°éå¿
须大äº0"); |
| | | } |
| | | |
| | | var stock = _stockService.StockInfoService.GetStockInfoByPalletCode(selection.PalletCode); |
| | | if (stock == null) |
| | | { |
| | | return (false, $"æç[{selection.PalletCode}]ä¸åå¨"); |
| | | } |
| | | |
| | | var available = CalculateAvailableQuantity(stock, outboundOrderDetail.MaterielCode, |
| | | outboundOrderDetail.BatchNo, outboundOrderDetail.SupplyCode); |
| | | |
| | | if (available <= 0) |
| | | { |
| | | return (false, $"æç[{selection.PalletCode}]没æå¯ç¨åºå"); |
| | | } |
| | | } |
| | | |
| | | return (true, "éªè¯éè¿"); |
| | | } |
| | | } |
| | | } |
| | |
| | | using Microsoft.AspNetCore.Mvc; |
| | | using Microsoft.Extensions.Logging; |
| | | using SqlSugar; |
| | | using SqlSugar.Extensions; |
| | | using WIDESEA_Common.OrderEnum; |
| | | using WIDESEA_Core; |
| | | using WIDESEA_Core.BaseRepository; |
| | | using WIDESEA_Core.BaseServices; |
| | |
| | | } |
| | | foreach (var item in model.Details) |
| | | { |
| | | var issueoStockResult = await _materialUnitService.ConvertIssueToStockAsync(item.MaterielCode, item.BarcodeQty); |
| | | var issueoStockResult = await _materialUnitService.ConvertFromToStockAsync(item.MaterielCode,item.BarcodeUnit, item.BarcodeQty); |
| | | item.Unit = issueoStockResult.Unit; |
| | | item.OrderQuantity = issueoStockResult.Quantity; |
| | | var moveissueoStockResult = await _materialUnitService.ConvertIssueToStockAsync(item.MaterielCode, item.BarcodeMoveQty); |
| | | var moveissueoStockResult = await _materialUnitService.ConvertFromToStockAsync(item.MaterielCode, item.BarcodeUnit, item.BarcodeMoveQty); |
| | | item.MoveQty = moveissueoStockResult.Quantity; |
| | | } |
| | | |
| | | |
| | | model.OrderNo = CreateCodeByRule(nameof(RuleCodeEnum.OutboundOrderRule)); |
| | | if (model.OrderType != InOrderTypeEnum.AllocatOutbound.ObjToInt() || model.OrderType != InOrderTypeEnum.InternalAllocat.ObjToInt()) |
| | | { |
| | | model.OrderNo = CreateCodeByRule(nameof(RuleCodeEnum.OutboundOrderRule)); |
| | | } |
| | | Db.InsertNav(model).Include(x => x.Details).ExecuteCommand(); |
| | | |
| | | return WebResponseContent.Instance.OK(); |
| | |
| | | if (outboundOrder.Details == null || outboundOrder.Details.Count == 0) |
| | | { |
| | | return WebResponseContent.Instance.Error($"æªæ¾å°åºåºåæç»ä¿¡æ¯"); |
| | | } |
| | | if (outboundOrder.OrderStatus != OutOrderStatusEnum.æªå¼å§.ObjToInt()) |
| | | { |
| | | return WebResponseContent.Instance.Error($"该订åç¶æä¸å
许修æ¹"); |
| | | } |
| | | List<Dt_OutboundOrderDetail> outboundOrderDetails = new List<Dt_OutboundOrderDetail>(); |
| | | List<Dt_OutboundOrderDetail> updateoutboundOrderDetails = new List<Dt_OutboundOrderDetail>(); |
| | |
| | | BarcodeQty = item.OrderQuantity, |
| | | BarcodeUnit = item.Unit, |
| | | }; |
| | | var issueoStockResult = await _materialUnitService.ConvertIssueToStockAsync(item.MaterielCode, item.BarcodeQty); |
| | | var issueoStockResult = await _materialUnitService.ConvertFromToStockAsync(item.MaterielCode,item.BarcodeUnit, item.BarcodeQty); |
| | | item.Unit = issueoStockResult.Unit; |
| | | item.OrderQuantity = issueoStockResult.Quantity; |
| | | var moveissueoStockResult = await _materialUnitService.ConvertIssueToStockAsync(item.MaterielCode, item.BarcodeMoveQty); |
| | | var moveissueoStockResult = await _materialUnitService.ConvertFromToStockAsync(item.MaterielCode, item.BarcodeUnit, item.BarcodeMoveQty); |
| | | item.MoveQty = moveissueoStockResult.Quantity; |
| | | |
| | | outboundOrderDetails.Add(outboundOrderDetail); |
| | |
| | | outboundOrderDetail.BarcodeMoveQty = item.MoveQty; |
| | | outboundOrderDetail.BarcodeQty = item.OrderQuantity; |
| | | outboundOrderDetail.BarcodeUnit = item.Unit; |
| | | var issueoStockResult = await _materialUnitService.ConvertIssueToStockAsync(item.MaterielCode, item.BarcodeQty); |
| | | var issueoStockResult = await _materialUnitService.ConvertFromToStockAsync(item.MaterielCode, item.BarcodeUnit, item.BarcodeQty); |
| | | outboundOrderDetail.Unit = issueoStockResult.Unit; |
| | | outboundOrderDetail.OrderQuantity = issueoStockResult.Quantity; |
| | | var moveissueoStockResult = await _materialUnitService.ConvertIssueToStockAsync(item.MaterielCode, item.BarcodeMoveQty); |
| | | var moveissueoStockResult = await _materialUnitService.ConvertFromToStockAsync(item.MaterielCode, item.BarcodeUnit, item.BarcodeMoveQty); |
| | | outboundOrderDetail.MoveQty = moveissueoStockResult.Quantity; |
| | | |
| | | |
| | |
| | | { |
| | | return WebResponseContent.Instance.Error($"æªæ¾å°åºåºåæç»ä¿¡æ¯"); |
| | | } |
| | | |
| | | if (outboundOrder.OrderStatus != OutOrderStatusEnum.æªå¼å§.ObjToInt()) |
| | | { |
| | | return WebResponseContent.Instance.Error($"该订åç¶æä¸å
许å é¤"); |
| | | } |
| | | _unitOfWorkManage.BeginTran(); |
| | | //BaseDal.DeleteAndMoveIntoHty(outboundOrder, OperateTypeEnum.èªå¨å é¤); |
| | | foreach (var item in outboundOrder.Details) |
| | |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | | using System.Text; |
| | | using System.Text.Json; |
| | | using System.Threading.Tasks; |
| | | using WIDESEA_Common.CommonEnum; |
| | | using WIDESEA_Common.LocationEnum; |
| | | using WIDESEA_Common.OrderEnum; |
| | | using WIDESEA_Common.StockEnum; |
| | |
| | | using WIDESEA_Core; |
| | | using WIDESEA_Core.BaseRepository; |
| | | using WIDESEA_Core.BaseServices; |
| | | using WIDESEA_Core.Enums; |
| | | using WIDESEA_Core.Helper; |
| | | using WIDESEA_DTO.Allocate; |
| | | using WIDESEA_DTO.Basic; |
| | | using WIDESEA_DTO.Inbound; |
| | | using WIDESEA_DTO.Outbound; |
| | | using WIDESEA_IAllocateService; |
| | | using WIDESEA_IBasicService; |
| | | using WIDESEA_IInboundService; |
| | | using WIDESEA_IOutboundService; |
| | |
| | | private readonly IESSApiService _eSSApiService; |
| | | private readonly IInvokeMESService _invokeMESService; |
| | | private readonly IDailySequenceService _dailySequenceService; |
| | | private readonly IRepository<Dt_InboundOrder> _inboundOrderRepository; |
| | | private readonly IInboundOrderDetailService _inboundOrderDetailService; |
| | | |
| | | 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, IRepository<Dt_InboundOrder> inboundOrderRepository, IInboundOrderDetailService inboundOrderDetailService) : base(BaseDal) |
| | | IRepository<Dt_Task> taskRepository, IESSApiService eSSApiService, ILogger<OutboundPickingService> logger, IInvokeMESService invokeMESService, IDailySequenceService dailySequenceService) : base(BaseDal) |
| | | { |
| | | _unitOfWorkManage = unitOfWorkManage; |
| | | _stockInfoService = stockInfoService; |
| | |
| | | _logger = logger; |
| | | _invokeMESService = invokeMESService; |
| | | _dailySequenceService = dailySequenceService; |
| | | _inboundOrderRepository = inboundOrderRepository; |
| | | _inboundOrderDetailService = inboundOrderDetailService; |
| | | } |
| | | |
| | | |
| | | #region æ¥è¯¢æ¹æ³ |
| | | // è·åæªæ£éå表 |
| | | public async Task<List<Dt_OutStockLockInfo>> GetUnpickedList(string orderNo, string palletCode) |
| | | { |
| | |
| | | return summary; |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region æ ¸å¿ä¸å¡æµç¨ |
| | | /// <summary> |
| | | /// æ£é |
| | |
| | | try |
| | | { |
| | | _unitOfWorkManage.BeginTran(); |
| | | |
| | | |
| | | var validationResult = await ValidatePickingRequest(orderNo, palletCode, barcode); |
| | | if (!validationResult.IsValid) |
| | | return WebResponseContent.Instance.Error(validationResult.ErrorMessage); |
| | |
| | | return WebResponseContent.Instance.Error(overPickingValidation.ErrorMessage); |
| | | } |
| | | |
| | | // æ§è¡åæ£é»è¾ |
| | | // æ§è¡åæ£é»è¾ï¼åªå¤çåºååéå®ï¼ä¸å¤ç订åï¼ |
| | | var pickingResult = await ExecutePickingLogic(lockInfo, orderDetail, stockDetail, orderNo, palletCode, barcode, actualQty); |
| | | |
| | | // æ´æ°ç¸å
³æ°æ® |
| | | // ç»ä¸æ´æ°è®¢åæ°æ®ï¼ææåæ¯é½å¨è¿éæ´æ°ï¼ |
| | | await UpdateOrderRelatedData(orderDetail.Id, pickingResult.ActualPickedQty, orderNo); |
| | | |
| | | // è®°å½æä½åå² |
| | |
| | | return WebResponseContent.Instance.Error($"æ£é确认失败ï¼{ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// åæ¶æ£é |
| | | /// </summary> |
| | |
| | | } |
| | | _unitOfWorkManage.BeginTran(); |
| | | |
| | | // 1. åç½®éªè¯ |
| | | // åç½®éªè¯ |
| | | var validationResult = await ValidateCancelRequest(orderNo, palletCode, barcode); |
| | | if (!validationResult.IsValid) |
| | | return WebResponseContent.Instance.Error(validationResult.ErrorMessage); |
| | | |
| | | var (pickingRecord, lockInfo, orderDetail) = validationResult.Data; |
| | | |
| | | // 2. æ§è¡åæ¶é»è¾ |
| | | //æ§è¡åæ¶é»è¾ |
| | | await ExecuteCancelLogic(lockInfo, pickingRecord, orderDetail, orderNo); |
| | | |
| | | _unitOfWorkManage.CommitTran(); |
| | | |
| | | return WebResponseContent.Instance.OK($"忶忣æåï¼æ¢å¤æ°éï¼{pickingRecord.PickQuantity}"); |
| | | return WebResponseContent.Instance.OK($"忶忣æå"); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | |
| | | { |
| | | _unitOfWorkManage.BeginTran(); |
| | | |
| | | // 1. åºç¡éªè¯ |
| | | |
| | | if (string.IsNullOrEmpty(orderNo) || string.IsNullOrEmpty(palletCode)) |
| | | return WebResponseContent.Instance.Error("订åå·åæçç ä¸è½ä¸ºç©º"); |
| | | |
| | | // 2. è·ååºååä»»å¡ä¿¡æ¯ |
| | | // è·ååºååä»»å¡ä¿¡æ¯ |
| | | var stockInfo = await _stockInfoService.Db.Queryable<Dt_StockInfo>().FirstAsync(x => x.PalletCode == palletCode); |
| | | |
| | | if (stockInfo == null) |
| | |
| | | if (task == null) |
| | | return WebResponseContent.Instance.Error("æªæ¾å°å¯¹åºçä»»å¡ä¿¡æ¯"); |
| | | |
| | | // 3. åæéè¦ååºçè´§ç© |
| | | var returnAnalysis = await AnalyzeReturnItems(orderNo, palletCode, stockInfo.Id); |
| | | if (!returnAnalysis.HasItemsToReturn) |
| | | return await HandleNoReturnItems(orderNo, palletCode,task); |
| | | //åæéè¦ååºçè´§ç© |
| | | //var returnAnalysis = await AnalyzeReturnItems(orderNo, palletCode, stockInfo.Id); |
| | | //if (!returnAnalysis.HasItemsToReturn) |
| | | // return await HandleNoReturnItems(orderNo, palletCode, task); |
| | | |
| | | // 4. æ§è¡ååºæä½ |
| | | await ExecuteReturnOperations(orderNo, palletCode, stockInfo, task, returnAnalysis); |
| | | var statusAnalysis = await AnalyzePalletStatus(orderNo, palletCode, stockInfo.Id); |
| | | if (!statusAnalysis.HasItemsToReturn) |
| | | return await HandleNoReturnItems(orderNo, palletCode, task, stockInfo.Id); |
| | | |
| | | // 5. å建ååºä»»å¡ |
| | | await CreateReturnTaskAndHandleESS(orderNo, palletCode, task, returnAnalysis); |
| | | // 4. æ£æ¥æ¯å¦æè¿è¡ä¸çä»»å¡ |
| | | if (statusAnalysis.HasActiveTasks) |
| | | { |
| | | return WebResponseContent.Instance.Error($"æç {palletCode} æè¿è¡ä¸çä»»å¡ï¼ä¸è½æ§è¡ååºæä½"); |
| | | } |
| | | |
| | | //æ§è¡ååºæä½ |
| | | await ExecuteReturnOperations(orderNo, palletCode, stockInfo, task, statusAnalysis); |
| | | |
| | | await ReleaseAllLocksForReallocation(orderNo, palletCode, statusAnalysis); |
| | | |
| | | _unitOfWorkManage.CommitTran(); |
| | | |
| | | // 6. æ´æ°è®¢åç¶æï¼ä¸è§¦åMESåä¼ ï¼ |
| | | |
| | | // å建ååºä»»å¡ |
| | | await CreateReturnTaskAndHandleESS(orderNo, palletCode, task, TaskTypeEnum.InPick, task.PalletType); |
| | | |
| | | // æ´æ°è®¢åç¶æï¼ä¸è§¦åMESåä¼ ï¼ |
| | | await UpdateOrderStatusForReturn(orderNo); |
| | | |
| | | return WebResponseContent.Instance.OK($"ååºæä½æåï¼å
±ååºæ°éï¼{returnAnalysis.TotalReturnQty}"); |
| | | return WebResponseContent.Instance.OK($"ååºæä½æå"); |
| | | //return WebResponseContent.Instance.OK($"ååºæä½æåï¼å
±ååºæ°éï¼{statusAnalysis.TotalReturnQty}"); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 空æçåèµ°æ¥å£ï¼å¸¦è®¢åå·ï¼ |
| | | /// éªè¯æçæ¯å¦ççä¸ºç©ºï¼æ¸
çæ°æ®ï¼æ´æ°è®¢åç¶æï¼å建åæçä»»å¡ |
| | | /// </summary> |
| | | public async Task<WebResponseContent> RemoveEmptyPallet(string orderNo, string palletCode) |
| | | { |
| | | try |
| | | { |
| | | _unitOfWorkManage.BeginTran(); |
| | | |
| | | if (string.IsNullOrEmpty(orderNo) || string.IsNullOrEmpty(palletCode)) |
| | | return WebResponseContent.Instance.Error("订åå·åæçç ä¸è½ä¸ºç©º"); |
| | | |
| | | // æ£æ¥è®¢åæ¯å¦åå¨ |
| | | var order = await _outboundOrderService.Db.Queryable<Dt_OutboundOrder>() |
| | | .Where(x => x.OrderNo == orderNo) |
| | | .FirstAsync(); |
| | | |
| | | if (order == null) |
| | | return WebResponseContent.Instance.Error($"æªæ¾å°è®¢å {orderNo}"); |
| | | |
| | | //æ£æ¥æçæ¯å¦åå¨ä¸å±äºè¯¥è®¢å |
| | | var stockInfo = await _stockInfoService.Db.Queryable<Dt_StockInfo>() |
| | | .Where(x => x.PalletCode == palletCode) |
| | | .FirstAsync(); |
| | | |
| | | if (stockInfo == null) |
| | | return WebResponseContent.Instance.Error($"æªæ¾å°æç {palletCode} 对åºçåºåä¿¡æ¯"); |
| | | |
| | | var statusAnalysis = await AnalyzePalletStatus(orderNo, palletCode, stockInfo.Id); |
| | | |
| | | if (!statusAnalysis.CanRemove) |
| | | { |
| | | if (!statusAnalysis.IsEmptyPallet) |
| | | { |
| | | return WebResponseContent.Instance.Error($"æç {palletCode} ä¸è¿æè´§ç©ï¼ä¸è½åèµ°"); |
| | | } |
| | | if (statusAnalysis.HasActiveTasks) |
| | | { |
| | | return WebResponseContent.Instance.Error($"æç {palletCode} è¿æè¿è¡ä¸çä»»å¡ï¼ä¸è½åèµ°"); |
| | | } |
| | | } |
| | | // æ¸
çé¶åºåæ°æ® |
| | | await CleanupZeroStockData(stockInfo.Id); |
| | | |
| | | // å 餿忶ç¸å
³ä»»å¡ |
| | | await HandleTaskCleanup(orderNo, palletCode); |
| | | |
| | | // æ´æ°è®¢åç¸å
³æ°æ® |
| | | await UpdateOrderData(orderNo, palletCode); |
| | | |
| | | |
| | | _unitOfWorkManage.CommitTran(); |
| | | |
| | | _logger.LogInformation($"空æçåèµ°æä½æå - 订å: {orderNo}, æç: {palletCode}, æä½äºº: {App.User.UserName}"); |
| | | |
| | | return WebResponseContent.Instance.OK("空æçåèµ°æä½æå"); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _unitOfWorkManage.RollbackTran(); |
| | | _logger.LogError($"RemoveEmptyPallet失败 - OrderNo: {orderNo}, PalletCode: {palletCode}, Error: {ex.Message}"); |
| | | return WebResponseContent.Instance.Error($"空æçå走失败: {ex.Message}"); |
| | | } |
| | | } |
| | | #endregion |
| | | |
| | | #region åæ£ç¡®è®¤ç§ææ¹æ³ |
| | |
| | | { |
| | | // æ¥æ¾åä¸è®¢åä¸çè®°å½ |
| | | lockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(it => it.OrderNo == orderNo && it.CurrentBarcode == barcode && it.Status == (int)OutLockStockStatusEnum.åºåºä¸ && it.AssignQuantity > it.PickedQty).FirstAsync(); |
| | | .Where(it => it.OrderNo == orderNo && it.CurrentBarcode == barcode && it.Status == (int)OutLockStockStatusEnum.åºåºä¸ && it.AssignQuantity > it.PickedQty).FirstAsync(); |
| | | |
| | | if (lockInfo == null) |
| | | { |
| | |
| | | adjustedReason = adjustedReason != null |
| | | ? $"{adjustedReason}ï¼é²è¶
æ£éå¶ï¼æç»è°æ´ä¸º{actualQty}" |
| | | : $"é²è¶
æ£éå¶ï¼ä»{plannedQty}è°æ´ä¸º{actualQty}"; |
| | | } |
| | | } |
| | | |
| | | if (adjustedReason != null) |
| | | { |
| | |
| | | |
| | | return ValidationResult<bool>.Success(true); |
| | | } |
| | | |
| | | |
| | | private async Task<PickingResult> ExecutePickingLogic( |
| | | Dt_OutStockLockInfo lockInfo, Dt_OutboundOrderDetail orderDetail, Dt_StockInfoDetail stockDetail, |
| | | string orderNo, string palletCode, string barcode, decimal actualQty) |
| | | Dt_OutStockLockInfo lockInfo, Dt_OutboundOrderDetail orderDetail, Dt_StockInfoDetail stockDetail, |
| | | string orderNo, string palletCode, string barcode, decimal actualQty) |
| | | { |
| | | decimal stockQuantity = stockDetail.StockQuantity; |
| | | var result = new PickingResult |
| | |
| | | if (actualQty < stockQuantity) |
| | | { |
| | | await HandleSplitPacking(lockInfo, stockDetail, actualQty, stockQuantity, result); |
| | | // æå
åºæ¯è¿åå®é
æ£éæ°é |
| | | result.ActualPickedQty = actualQty; |
| | | } |
| | | else if (actualQty == stockQuantity) |
| | | { |
| | | await HandleFullPicking(lockInfo, stockDetail, actualQty, result); |
| | | // æ´å
æ£éè¿åå®é
æ£éæ°é |
| | | result.ActualPickedQty = actualQty; |
| | | } |
| | | else |
| | | { |
| | | await HandlePartialPicking(lockInfo, stockDetail, actualQty, stockQuantity, result); |
| | | // é¨åæ£éè¿åè°æ´åçæ°é |
| | | result.ActualPickedQty = result.ActualPickedQty; // å·²ç»å¨æ¹æ³å
è°æ´ |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | private async Task HandleSplitPacking(Dt_OutStockLockInfo lockInfo, Dt_StockInfoDetail stockDetail, |
| | | decimal actualQty, decimal stockQuantity, PickingResult result) |
| | | decimal actualQty, decimal stockQuantity, PickingResult result) |
| | | { |
| | | decimal remainingStockQty = stockQuantity - actualQty; |
| | | |
| | | // 1. æ´æ°åæ¡ç åºå |
| | | // æ´æ°åæ¡ç åºå |
| | | stockDetail.StockQuantity = remainingStockQty; |
| | | stockDetail.OutboundQuantity = remainingStockQty; |
| | | await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync(); |
| | | |
| | | // 2. çææ°æ¡ç |
| | | // çææ°æ¡ç |
| | | string newBarcode = await GenerateNewBarcode(); |
| | | |
| | | // 3. å建æ°éå®ä¿¡æ¯ |
| | | // å建æ°éå®ä¿¡æ¯ |
| | | var newLockInfo = await CreateSplitLockInfo(lockInfo, actualQty, newBarcode); |
| | | |
| | | // 4. è®°å½æå
åå² |
| | | // è®°å½æå
åå² |
| | | await RecordSplitHistory(lockInfo, stockDetail, actualQty, remainingStockQty, newBarcode); |
| | | |
| | | // 5. æ´æ°åéå®ä¿¡æ¯ |
| | | // æ´æ°åéå®ä¿¡æ¯ |
| | | lockInfo.AssignQuantity = remainingStockQty; |
| | | lockInfo.PickedQty = 0; |
| | | lockInfo.Operator = App.User.UserName; |
| | | await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync(); |
| | | |
| | | // 6. è®¾ç½®ç»æ |
| | | // è®¾ç½®ç»æ |
| | | result.FinalLockInfo = newLockInfo; |
| | | result.FinalBarcode = newBarcode; |
| | | result.SplitResults.AddRange(CreateSplitResults(lockInfo, actualQty, remainingStockQty, newBarcode, stockDetail.Barcode)); |
| | | } |
| | | |
| | | |
| | | |
| | | _logger.LogInformation($"æå
忣宿 - OrderDetailId: {lockInfo.OrderDetailId}, 忣æ°é: {actualQty}"); |
| | | } |
| | | private async Task HandleFullPicking(Dt_OutStockLockInfo lockInfo, Dt_StockInfoDetail stockDetail, |
| | | decimal actualQty, PickingResult result) |
| | | { |
| | |
| | | |
| | | if (newOverOutQuantity > currentOrderDetail.NeedOutQuantity) |
| | | { |
| | | |
| | | |
| | | _logger.LogError($"é²è¶
æ£æ£æ¥å¤±è´¥ - OrderDetailId: {orderDetailId}, å·²åºåº: {newOverOutQuantity}, éæ±: {currentOrderDetail.NeedOutQuantity}, æ¬æ¬¡åæ£: {pickedQty}"); |
| | | |
| | | |
| | | |
| | | decimal adjustedQty = currentOrderDetail.NeedOutQuantity - currentOrderDetail.OverOutQuantity; |
| | | |
| | | if (adjustedQty > 0) |
| | |
| | | #endregion |
| | | |
| | | #region åæ¶åæ£ç§ææ¹æ³ |
| | | private async Task<ValidationResult<bool>> ValidateDataConsistencyBeforeCancel(CancelPickingContext context) |
| | | { |
| | | try |
| | | { |
| | | // éªè¯è®¢åæç»æ°æ® |
| | | var currentOrderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | .FirstAsync(x => x.Id == context.OrderDetail.Id); |
| | | |
| | | if (currentOrderDetail.OverOutQuantity < context.PickingRecord.PickQuantity) |
| | | return ValidationResult<bool>.Error($"订åæç»å·²åºåºæ°é({currentOrderDetail.OverOutQuantity})å°äºåæ¶æ°é({context.PickingRecord.PickQuantity})"); |
| | | |
| | | if (currentOrderDetail.PickedQty < context.PickingRecord.PickQuantity) |
| | | return ValidationResult<bool>.Error($"订åæç»å·²æ£éæ°é({currentOrderDetail.PickedQty})å°äºåæ¶æ°é({context.PickingRecord.PickQuantity})"); |
| | | |
| | | // éªè¯éå®ä¿¡æ¯æ°æ® |
| | | var currentLockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .FirstAsync(x => x.Id == context.LockInfo.Id); |
| | | |
| | | if (currentLockInfo.PickedQty < context.PickingRecord.PickQuantity) |
| | | return ValidationResult<bool>.Error($"éå®ä¿¡æ¯å·²æ£éæ°é({currentLockInfo.PickedQty})å°äºåæ¶æ°é({context.PickingRecord.PickQuantity})"); |
| | | |
| | | ////// éªè¯åºåæ°æ® |
| | | ////var currentStockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | //// .FirstAsync(x => x.Barcode == context.PickingRecord.Barcode && x.StockId == context.PickingRecord.StockId); |
| | | |
| | | ////if (currentStockDetail == null) |
| | | //// return ValidationResult<bool>.Error($"æªæ¾å°å¯¹åºçåºåæç»è®°å½"); |
| | | |
| | | ////if (currentStockDetail.Status == StockStatusEmun.å
¥åºç¡®è®¤.ObjToInt() || |
| | | //// currentStockDetail.Status == StockStatusEmun.å
¥åºå®æ.ObjToInt()) |
| | | //// return ValidationResult<bool>.Error($"æ¡ç {context.PickingRecord.Barcode}å·²ç»ååºï¼æ æ³åæ¶åæ£"); |
| | | |
| | | // éªè¯ç¶ææµè½¬çåæ³æ§ |
| | | if (!await CanCancelPicking(currentLockInfo, null)) |
| | | return ValidationResult<bool>.Error($"å½åç¶æä¸å
è®¸åæ¶åæ£"); |
| | | |
| | | return ValidationResult<bool>.Success(true); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _logger.LogError($"åæ¶åæ£æ°æ®ä¸è´æ§éªè¯å¤±è´¥: {ex.Message}"); |
| | | return ValidationResult<bool>.Error($"æ°æ®éªè¯å¤±è´¥: {ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | private async Task<bool> CanCancelPicking(Dt_OutStockLockInfo lockInfo, Dt_StockInfoDetail stockDetail) |
| | | { |
| | | // éå®ä¿¡æ¯ç¶ææ£æ¥ |
| | | if (lockInfo.Status != (int)OutLockStockStatusEnum.æ£é宿) |
| | | return false; |
| | | |
| | | ////// åºåç¶ææ£æ¥ |
| | | ////if (stockDetail.Status == StockStatusEmun.åºåºå®æ.ObjToInt()) |
| | | //// return false; |
| | | |
| | | // å¦ææ¯æå
è®°å½ï¼è¿éè¦æ£æ¥ç¶éå®ä¿¡æ¯ç¶æ |
| | | if (lockInfo.IsSplitted == 1 && lockInfo.ParentLockId.HasValue) |
| | | { |
| | | var parentLock = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .FirstAsync(x => x.Id == lockInfo.ParentLockId.Value); |
| | | |
| | | if (parentLock == null || parentLock.Status == (int)OutLockStockStatusEnum.ååºä¸) |
| | | return false; |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | private async Task<ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>> ValidateCancelRequest(string orderNo, string palletCode, string barcode) |
| | | { |
| | | // åºç¡åæ°éªè¯ |
| | |
| | | |
| | | if (lockInfo == null) |
| | | return ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>.Error("æªæ¾å°å¯¹åºçåºåºéå®ä¿¡æ¯"); |
| | | |
| | | |
| | | if (lockInfo.PickedQty < pickingRecord.PickQuantity) |
| | | { |
| | | return ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>.Error( |
| | |
| | | { |
| | | return ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>.Error($"æ¡ç {barcode}å·²ç»ååºï¼ä¸è½åæ¶åæ£"); |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | return ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>.Success((pickingRecord, lockInfo, orderDetail)); |
| | | } |
| | | /// <summary> |
| | |
| | | stockDetail.Status == StockStatusEmun.å
¥åºå®æ.ObjToInt(); |
| | | } |
| | | private async Task ExecuteCancelLogic(Dt_OutStockLockInfo lockInfo, Dt_PickingRecord pickingRecord, |
| | | Dt_OutboundOrderDetail orderDetail, string orderNo) |
| | | Dt_OutboundOrderDetail orderDetail, string orderNo) |
| | | { |
| | | decimal cancelQty = pickingRecord.PickQuantity; |
| | | |
| | | var currentStockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .Where(it => it.Barcode == pickingRecord.Barcode && it.StockId == pickingRecord.StockId) |
| | | .FirstAsync(); |
| | | |
| | | if (currentStockDetail != null && |
| | | (currentStockDetail.Status == StockStatusEmun.å
¥åºç¡®è®¤.ObjToInt() || |
| | | currentStockDetail.Status == StockStatusEmun.å
¥åºå®æ.ObjToInt())) |
| | | // æ°æ®ä¸è´æ§éªè¯ |
| | | var context = new CancelPickingContext |
| | | { |
| | | throw new Exception($"æ¡ç {pickingRecord.Barcode}å·²ç»ååºï¼æ æ³åæ¶åæ£"); |
| | | } |
| | | // æ£æ¥åæ¶åæ°éä¸ä¼ä¸ºè´æ° |
| | | decimal newOverOutQuantity = orderDetail.OverOutQuantity - cancelQty; |
| | | decimal newPickedQty = orderDetail.PickedQty - cancelQty; |
| | | LockInfo = lockInfo, |
| | | PickingRecord = pickingRecord, |
| | | OrderDetail = orderDetail, |
| | | OrderNo = orderNo, |
| | | CancelQuantity = cancelQty |
| | | }; |
| | | |
| | | if (newOverOutQuantity < 0 || newPickedQty < 0) |
| | | { |
| | | throw new Exception($"忶忣å°å¯¼è´æ°æ®å¼å¸¸ï¼å·²åºåº{newOverOutQuantity}ï¼å·²æ£é{newPickedQty}"); |
| | | } |
| | | var validationResult = await ValidateDataConsistencyBeforeCancel(context); |
| | | if (!validationResult.IsValid) |
| | | throw new Exception(validationResult.ErrorMessage); |
| | | |
| | | // å¤çä¸åç±»åçåæ¶ |
| | | // å¤çä¸åç±»åçåæ¶ |
| | | if (lockInfo.IsSplitted == 1 && lockInfo.ParentLockId.HasValue) |
| | | { |
| | | await HandleSplitBarcodeCancel(lockInfo, pickingRecord, cancelQty); |
| | |
| | | await HandleNormalBarcodeCancel(lockInfo, pickingRecord, cancelQty); |
| | | } |
| | | |
| | | // æ´æ°è®¢åæç» |
| | | // æ´æ°è®¢åæç» |
| | | await UpdateOrderDetailOnCancel(pickingRecord.OrderDetailId, cancelQty); |
| | | |
| | | // å 餿£éè®°å½ |
| | | await Db.Deleteable<Dt_PickingRecord>() |
| | | var deleteResult = await Db.Deleteable<Dt_PickingRecord>() |
| | | .Where(x => x.Id == pickingRecord.Id) |
| | | .ExecuteCommandAsync(); |
| | | |
| | | // éæ°æ£æ¥è®¢åç¶æ |
| | | if (deleteResult <= 0) |
| | | throw new Exception("å 餿£éè®°å½å¤±è´¥"); |
| | | |
| | | _logger.LogInformation($"å 餿£éè®°å½ - è®°å½ID: {pickingRecord.Id}, æ¡ç : {pickingRecord.Barcode}"); |
| | | |
| | | // éæ°æ£æ¥è®¢åç¶æ |
| | | await UpdateOrderStatusForReturn(orderNo); |
| | | |
| | | |
| | | } |
| | | |
| | | private async Task HandleSplitBarcodeCancel(Dt_OutStockLockInfo lockInfo, Dt_PickingRecord pickingRecord, decimal cancelQty) |
| | |
| | | if (parentLockInfo == null) |
| | | throw new Exception("æªæ¾å°ç¶éå®ä¿¡æ¯ï¼æ æ³åæ¶æå
忣"); |
| | | |
| | | // æ£æ¥ç¶æ¡ç åæå
æ¡ç çç¶æ |
| | | if (await IsLockInfoReturned(parentLockInfo)) |
| | | { |
| | | throw new Exception($"ç¶æ¡ç {parentLockInfo.CurrentBarcode}å·²ç»ååºï¼æ æ³åæ¶æå
忣"); |
| | | } |
| | | |
| | | if (await IsLockInfoReturned(lockInfo)) |
| | | { |
| | | throw new Exception($"æå
æ¡ç {lockInfo.CurrentBarcode}å·²ç»ååºï¼æ æ³åæ¶æå
忣"); |
| | | } |
| | | |
| | | // æ¢å¤ç¶éå®ä¿¡æ¯çåé
æ°é |
| | | parentLockInfo.AssignQuantity += cancelQty; |
| | | parentLockInfo.Status = (int)OutLockStockStatusEnum.åºåºä¸; // æ¢å¤ä¸ºåºåºä¸ç¶æ |
| | | await _outStockLockInfoService.Db.Updateable(parentLockInfo).ExecuteCommandAsync(); |
| | | |
| | | // æ¢å¤åºå |
| | | var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | // æ¢å¤ç¶æ¡ç åºå |
| | | var parentStockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .Where(x => x.Barcode == parentLockInfo.CurrentBarcode && x.StockId == parentLockInfo.StockId) |
| | | .FirstAsync(); |
| | | |
| | | if (stockDetail != null) |
| | | if (parentStockDetail != null) |
| | | { |
| | | stockDetail.StockQuantity += cancelQty; |
| | | stockDetail.OutboundQuantity = stockDetail.StockQuantity; |
| | | stockDetail.Status = StockStatusEmun.åºåºéå®.ObjToInt(); |
| | | await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync(); |
| | | parentStockDetail.StockQuantity += cancelQty; |
| | | parentStockDetail.OutboundQuantity = parentStockDetail.StockQuantity; |
| | | parentStockDetail.Status = StockStatusEmun.åºåºéå®.ObjToInt(); |
| | | await _stockInfoDetailService.Db.Updateable(parentStockDetail).ExecuteCommandAsync(); |
| | | |
| | | _logger.LogInformation($"æ¢å¤ç¶æ¡ç åºå - æ¡ç : {parentStockDetail.Barcode}, æ¢å¤æ°é: {cancelQty}, æ°åºå: {parentStockDetail.StockQuantity}"); |
| | | } |
| | | |
| | | // å¤çæå
产ççæ°æ¡ç åºå |
| | | var splitStockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .Where(x => x.Barcode == lockInfo.CurrentBarcode && x.StockId == lockInfo.StockId) |
| | | .FirstAsync(); |
| | | |
| | | if (splitStockDetail != null) |
| | | { |
| | | // å 餿å
产ççæ°æ¡ç åºåè®°å½ |
| | | await _stockInfoDetailService.Db.Deleteable(splitStockDetail).ExecuteCommandAsync(); |
| | | _logger.LogInformation($"å 餿å
æ°æ¡ç åºå - æ¡ç : {splitStockDetail.Barcode}"); |
| | | } |
| | | |
| | | // æ´æ°æå
è®°å½ç¶æ |
| | | await _splitPackageService.Db.Updateable<Dt_SplitPackageRecord>() |
| | | var updateCount = await _splitPackageService.Db.Updateable<Dt_SplitPackageRecord>() |
| | | .SetColumns(x => new Dt_SplitPackageRecord |
| | | { |
| | | Status = (int)SplitPackageStatusEnum.å·²æ¤é, |
| | | IsReverted = true, |
| | | Operator = App.User.UserName, |
| | | RevertTime = DateTime.Now |
| | | }) |
| | | .Where(x => x.NewBarcode == lockInfo.CurrentBarcode && !x.IsReverted) |
| | | .ExecuteCommandAsync(); |
| | | |
| | | _logger.LogInformation($"æ´æ°æå
è®°å½ç¶æ - æ´æ°è®°å½æ°: {updateCount}"); |
| | | |
| | | // å 餿å
产ççéå®ä¿¡æ¯ |
| | | await _outStockLockInfoService.Db.Deleteable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.Id == lockInfo.Id) |
| | | .ExecuteCommandAsync(); |
| | | } |
| | | |
| | | _logger.LogInformation($"å 餿å
éå®ä¿¡æ¯ - éå®ID: {lockInfo.Id}, æ¡ç : {lockInfo.CurrentBarcode}"); |
| | | } |
| | | private async Task HandleNormalBarcodeCancel(Dt_OutStockLockInfo lockInfo, Dt_PickingRecord pickingRecord, decimal cancelQty) |
| | | { |
| | | if (await IsLockInfoReturned(lockInfo)) |
| | | { |
| | | throw new Exception($"æ¡ç {lockInfo.CurrentBarcode}å·²ç»ååºï¼æ æ³åæ¶åæ£"); |
| | | } |
| | | |
| | | // æ¢å¤éå®ä¿¡æ¯ |
| | | lockInfo.PickedQty -= cancelQty; |
| | | if (lockInfo.PickedQty < 0) lockInfo.PickedQty = 0; |
| | | |
| | | lockInfo.Status = (int)OutLockStockStatusEnum.åºåºä¸; |
| | | // åªæå½æ£éæ°éå®å
¨åæ¶æ¶ææ¢å¤ç¶æ |
| | | if (lockInfo.PickedQty == 0) |
| | | { |
| | | lockInfo.Status = (int)OutLockStockStatusEnum.åºåºä¸; |
| | | } |
| | | |
| | | lockInfo.Operator = App.User.UserName; |
| | | await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync(); |
| | | |
| | | _logger.LogInformation($"æ¢å¤éå®ä¿¡æ¯ - éå®ID: {lockInfo.Id}, æ£åæ£éæ°é: {cancelQty}, æ°å·²æ£éæ°é: {lockInfo.PickedQty}"); |
| | | |
| | | // æ¢å¤åºå |
| | | var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | |
| | | { |
| | | stockDetail.StockQuantity += cancelQty; |
| | | stockDetail.OutboundQuantity = stockDetail.StockQuantity; |
| | | stockDetail.Status = StockStatusEmun.åºåºéå®.ObjToInt(); |
| | | |
| | | // æ¢å¤åºåç¶æ |
| | | if (stockDetail.Status == StockStatusEmun.åºåºå®æ.ObjToInt()) |
| | | { |
| | | stockDetail.Status = StockStatusEmun.åºåºéå®.ObjToInt(); |
| | | } |
| | | |
| | | await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync(); |
| | | |
| | | _logger.LogInformation($"æ¢å¤åºå - æ¡ç : {stockDetail.Barcode}, æ¢å¤æ°é: {cancelQty}, " + |
| | | $"æ°åºå: {stockDetail.StockQuantity}, æ°ç¶æ: {stockDetail.Status}"); |
| | | } |
| | | else |
| | | { |
| | | _logger.LogWarning($"æªæ¾å°åºåè®°å½ - æ¡ç : {pickingRecord.Barcode}, åºåID: {pickingRecord.StockId}"); |
| | | } |
| | | } |
| | | |
| | | private async Task UpdateOrderDetailOnCancel(int orderDetailId, decimal cancelQty) |
| | | { |
| | | // è·åææ°ç订åæç»æ°æ® |
| | | // è·åææ°ç订åæç»æ°æ®ï¼å¸¦éï¼ |
| | | var currentOrderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | .With(SqlWith.RowLock) |
| | | .FirstAsync(x => x.Id == orderDetailId); |
| | | |
| | | decimal newOverOutQuantity = currentOrderDetail.OverOutQuantity - cancelQty; |
| | | decimal newPickedQty = currentOrderDetail.PickedQty - cancelQty; |
| | | |
| | | // æ£æ¥åæ¶åæ°éä¸ä¼ä¸ºè´æ° |
| | | if (newOverOutQuantity < 0 || newPickedQty < 0) |
| | | { |
| | | throw new Exception($"忶忣å°å¯¼è´å·²åºåºæ°é({newOverOutQuantity})æå·²æ£éæ°é({newPickedQty})ä¸ºè´æ°"); |
| | | } |
| | | // ä¸¥æ ¼æ£æ¥åæ¶åæ°éä¸ä¼ä¸ºè´æ° |
| | | if (newOverOutQuantity < 0) |
| | | throw new Exception($"忶忣å°å¯¼è´å·²åºåºæ°é({newOverOutQuantity})ä¸ºè´æ°"); |
| | | |
| | | await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>() |
| | | if (newPickedQty < 0) |
| | | throw new Exception($"忶忣å°å¯¼è´å·²æ£éæ°é({newPickedQty})ä¸ºè´æ°"); |
| | | |
| | | // æ´æ°è®¢åæç» |
| | | var updateResult = await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>() |
| | | .SetColumns(it => new Dt_OutboundOrderDetail |
| | | { |
| | | PickedQty = newPickedQty, |
| | | OverOutQuantity = newOverOutQuantity, |
| | | OverOutQuantity = newOverOutQuantity |
| | | }) |
| | | .Where(it => it.Id == orderDetailId) |
| | | .ExecuteCommandAsync(); |
| | | } |
| | | |
| | | if (updateResult <= 0) |
| | | throw new Exception("æ´æ°è®¢åæç»å¤±è´¥"); |
| | | |
| | | _logger.LogInformation($"æ´æ°è®¢åæç» - OrderDetailId: {orderDetailId}, " + |
| | | $"æ£åå·²åºåº: {cancelQty}, æ°å·²åºåº: {newOverOutQuantity}, " + |
| | | $"æ£åå·²æ£é: {cancelQty}, æ°å·²æ£é: {newPickedQty}"); |
| | | } |
| | | #endregion |
| | | |
| | | #region ååºæä½ç§ææ¹æ³ |
| | |
| | | return task; |
| | | } |
| | | |
| | | private async Task<ReturnAnalysisResult> AnalyzeReturnItems(string orderNo, string palletCode, int stockId) |
| | | { |
| | | var result = new ReturnAnalysisResult(); |
| | | |
| | | // æ
åµ1ï¼è·åæªåæ£çåºåºéå®è®°å½ |
| | | var remainingLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(it => it.OrderNo == orderNo && |
| | | it.PalletCode == palletCode && |
| | | it.Status == (int)OutLockStockStatusEnum.åºåºä¸) |
| | | .ToListAsync(); |
| | | |
| | | if (remainingLocks.Any()) |
| | | { |
| | | result.HasRemainingLocks = true; |
| | | result.RemainingLocks = remainingLocks; |
| | | result.RemainingLocksReturnQty = remainingLocks.Sum(x => x.AssignQuantity - x.PickedQty); |
| | | } |
| | | |
| | | // æ
åµ2ï¼æ£æ¥æç䏿¯å¦æå
¶ä»åºåè´§ç© |
| | | var palletStockGoods = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .Where(it => it.StockId == stockId && |
| | | (it.Status == StockStatusEmun.å
¥åºç¡®è®¤.ObjToInt() || |
| | | it.Status == StockStatusEmun.å
¥åºå®æ.ObjToInt() || |
| | | it.Status == StockStatusEmun.åºåºéå®.ObjToInt())) |
| | | .Where(it => it.StockQuantity > 0) |
| | | .ToListAsync(); |
| | | |
| | | if (palletStockGoods.Any()) |
| | | { |
| | | result.HasPalletStockGoods = true; |
| | | result.PalletStockGoods = palletStockGoods; |
| | | result.PalletStockReturnQty = palletStockGoods.Sum(x => x.StockQuantity); |
| | | } |
| | | |
| | | // æ
åµ3ï¼æ£æ¥æå
è®°å½ |
| | | var splitRecords = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>() |
| | | .Where(it => it.OrderNo == orderNo && it.PalletCode == palletCode && !it.IsReverted && it.Status != (int)SplitPackageStatusEnum.å·²ååº) |
| | | .ToListAsync(); |
| | | |
| | | if (splitRecords.Any()) |
| | | { |
| | | result.HasSplitRecords = true; |
| | | result.SplitRecords = splitRecords; |
| | | result.SplitReturnQty = await CalculateSplitReturnQuantity(splitRecords, stockId); |
| | | } |
| | | |
| | | result.TotalReturnQty = result.RemainingLocksReturnQty + result.PalletStockReturnQty + result.SplitReturnQty; |
| | | result.HasItemsToReturn = result.TotalReturnQty > 0; |
| | | |
| | | return result; |
| | | } |
| | | |
| | | private async Task<decimal> CalculateSplitReturnQuantity(List<Dt_SplitPackageRecord> splitRecords, int stockId) |
| | | { |
| | | decimal totalQty = 0; |
| | |
| | | |
| | | foreach (var splitRecord in splitRecords) |
| | | { |
| | | if (splitRecord.Status != (int)SplitPackageStatusEnum.å·²æ¤é) |
| | | continue; |
| | | // æ£æ¥åæ¡ç |
| | | if (!processedBarcodes.Contains(splitRecord.OriginalBarcode)) |
| | | { |
| | | var originalStock = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .Where(it => it.Barcode == splitRecord.OriginalBarcode && it.StockId == stockId) |
| | | .Where(it => it.Barcode == splitRecord.OriginalBarcode && it.StockId == stockId && |
| | | it.Status != StockStatusEmun.åºåºå®æ.ObjToInt()) |
| | | .FirstAsync(); |
| | | |
| | | if (originalStock != null && originalStock.StockQuantity > 0) |
| | |
| | | if (!processedBarcodes.Contains(splitRecord.NewBarcode)) |
| | | { |
| | | var newStock = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .Where(it => it.Barcode == splitRecord.NewBarcode && it.StockId == stockId) |
| | | .Where(it => it.Barcode == splitRecord.NewBarcode && it.StockId == stockId && it.Status != StockStatusEmun.åºåºå®æ.ObjToInt()) |
| | | .FirstAsync(); |
| | | |
| | | if (newStock != null && newStock.StockQuantity > 0) |
| | |
| | | return totalQty; |
| | | } |
| | | |
| | | private async Task<WebResponseContent> HandleNoReturnItems(string orderNo, string palletCode,Dt_Task originalTask) |
| | | private async Task<WebResponseContent> HandleNoReturnItems(string orderNo, string palletCode, Dt_Task originalTask, int stockInfoId) |
| | | { |
| | | // æ£æ¥æ¯å¦ææè´§ç©é½å·²æ£é宿 |
| | | var allPicked = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(it => it.OrderNo == orderNo && it.PalletCode == palletCode) |
| | | .AnyAsync(it => it.Status == (int)OutLockStockStatusEnum.æ£é宿); |
| | | //var allPicked = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | // .Where(it => it.OrderNo == orderNo && it.PalletCode == palletCode) |
| | | // .AnyAsync(it => it.Status == (int)OutLockStockStatusEnum.æ£é宿); |
| | | |
| | | if (allPicked) |
| | | //if (allPicked) |
| | | //{ |
| | | // // å é¤åå§åºåºä»»å¡ ç»ç©ºç 空çååº |
| | | // //await _taskRepository.Db.Deleteable(originalTask).ExecuteCommandAsync(); |
| | | // return WebResponseContent.Instance.OK("ææè´§ç©å·²æ£éå®æï¼æç为空"); |
| | | //} |
| | | //else |
| | | //{ |
| | | // // å é¤åå§åºåºä»»å¡ |
| | | // //await _taskRepository.Db.Deleteable(originalTask).ExecuteCommandAsync(); |
| | | // return WebResponseContent.Instance.Error("没æéè¦ååºçå©ä½è´§ç©"); |
| | | //} |
| | | try |
| | | { |
| | | // å é¤åå§åºåºä»»å¡ |
| | | await _taskRepository.Db.Deleteable(originalTask).ExecuteCommandAsync(); |
| | | return WebResponseContent.Instance.OK("ææè´§ç©å·²æ£éå®æï¼æç为空"); |
| | | var locationtype = 0; |
| | | var stockInfo = await _stockInfoService.Db.Queryable<Dt_StockInfo>() |
| | | .Where(x => x.PalletCode == palletCode) |
| | | .FirstAsync(); |
| | | |
| | | if (stockInfo == null) |
| | | { |
| | | var firstLocation = await _locationInfoService.Db.Queryable<Dt_LocationInfo>().FirstAsync(x => x.LocationCode == originalTask.SourceAddress); |
| | | locationtype = firstLocation?.LocationType ?? 1; |
| | | } |
| | | else |
| | | { |
| | | locationtype = stockInfo.LocationType; |
| | | _stockInfoService.DeleteData(stockInfo); |
| | | } |
| | | |
| | | var targetAddress = originalTask.TargetAddress; |
| | | |
| | | await CleanupZeroStockData(stockInfoId); |
| | | |
| | | |
| | | var emptystockInfo = new Dt_StockInfo() { PalletType = PalletTypeEnum.Empty.ObjToInt(), StockStatus = StockStatusEmun.ç»çæå.ObjToInt(), PalletCode = palletCode, LocationType = locationtype }; |
| | | emptystockInfo.Details = new List<Dt_StockInfoDetail>(); |
| | | _stockInfoService.AddMaterielGroup(emptystockInfo); |
| | | //空æçå¦ä½å¤ç è¿æä¸ä¸ªåºåºä»»å¡è¦å¤çã |
| | | originalTask.PalletType = PalletTypeEnum.Empty.ObjToInt(); |
| | | |
| | | await CreateReturnTaskAndHandleESS(orderNo, palletCode, originalTask, TaskTypeEnum.InEmpty, PalletTypeEnum.Empty.ObjToInt()); |
| | | |
| | | } |
| | | else |
| | | catch (Exception ex) |
| | | { |
| | | // å é¤åå§åºåºä»»å¡ |
| | | await _taskRepository.Db.Deleteable(originalTask).ExecuteCommandAsync(); |
| | | return WebResponseContent.Instance.Error("没æéè¦ååºçå©ä½è´§ç©"); |
| | | _logger.LogError($" HandleNoReturnItems 失败: {ex.Message}"); |
| | | return WebResponseContent.Instance.Error($" ååºç©ºæç失败ï¼"); |
| | | } |
| | | //空æçå¦ä½å¤ç è¿æä¸ä¸ªåºåºä»»å¡è¦å¤çã |
| | | |
| | | return WebResponseContent.Instance.OK("空æçååºä»»å¡å建æå"); |
| | | |
| | | } |
| | | |
| | | private async Task ExecuteReturnOperations(string orderNo, string palletCode, Dt_StockInfo stockInfo, |
| | | Dt_Task task, ReturnAnalysisResult analysis) |
| | | Dt_Task task, PalletStatusAnalysis analysis) |
| | | { |
| | | // æ
åµ1ï¼å¤çæªåæ£çåºåºéå®è®°å½ |
| | | if (analysis.HasRemainingLocks) |
| | | { |
| | | await HandleRemainingLocksReturn(analysis.RemainingLocks, stockInfo.Id); |
| | | |
| | | // å
³é®ï¼æ´æ°è®¢åæç»çå·²æ£éæ°é |
| | | await UpdateOrderDetailsOnReturn(analysis.RemainingLocks); |
| | | // await UpdateOrderDetailsOnReturn(analysis.RemainingLocks); |
| | | } |
| | | |
| | | // å¤çæçä¸å
¶ä»åºåè´§ç© |
| | | if (analysis.HasPalletStockGoods) |
| | | { |
| | | await HandlePalletStockGoodsReturn(analysis.PalletStockGoods); |
| | | var validStockGoods = analysis.PalletStockGoods |
| | | .Where(x => x.Status != StockStatusEmun.åºåºå®æ.ObjToInt()) |
| | | .ToList(); |
| | | |
| | | if (validStockGoods.Any()) |
| | | { |
| | | await HandlePalletStockGoodsReturn(analysis.PalletStockGoods); |
| | | } |
| | | else |
| | | { |
| | | _logger.LogInformation("æ²¡æææçåºåè´§ç©éè¦ååº"); |
| | | } |
| | | } |
| | | |
| | | // å¤çæå
è®°å½ |
| | | if (analysis.HasSplitRecords) |
| | | { |
| | | await HandleSplitRecordsReturn(analysis.SplitRecords, orderNo, palletCode); |
| | | var validSplitRecords = analysis.SplitRecords |
| | | .Where(x => x.Status != (int)SplitPackageStatusEnum.å·²æ£é) |
| | | .ToList(); |
| | | |
| | | if (validSplitRecords.Any()) |
| | | { |
| | | await HandleSplitRecordsReturn(analysis.SplitRecords, orderNo, palletCode); |
| | | } |
| | | else |
| | | { |
| | | _logger.LogInformation("æ²¡æææçæå
è®°å½éè¦å¤ç"); |
| | | } |
| | | } |
| | | |
| | | // æ´æ°åºåä¸»è¡¨ç¶æ |
| | | await UpdateStockInfoStatus(stockInfo); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// å®å
¨éæ¾éå®ï¼å
è®¸éæ°åé
åºå |
| | | /// </summary> |
| | | private async Task ReleaseAllLocksForReallocation(string orderNo, string palletCode, PalletStatusAnalysis analysis) |
| | | { |
| | | _logger.LogInformation($"å¼å§éæ¾éå®ä»¥ä¾¿éæ°åé
- 订å: {orderNo}, æç: {palletCode}"); |
| | | |
| | | // 1. å¤çæªåæ£çåºåºéå®è®°å½ - å®å
¨éæ¾ |
| | | if (analysis.HasRemainingLocks) |
| | | { |
| | | await ReleaseRemainingLocks(analysis.RemainingLocks); |
| | | } |
| | | |
| | | // 2. å¤çå·²ååºçéå®è®°å½ - å 餿æ è®°ä¸ºæ æ |
| | | await CleanupReturnedLocks(orderNo, palletCode); |
| | | |
| | | // 3. é置订åæç»çé宿°é |
| | | await ResetOrderDetailLockQuantities(analysis); |
| | | |
| | | _logger.LogInformation($"éå®éæ¾å®æ - 订å: {orderNo}, æç: {palletCode}"); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// éæ¾æªåæ£çéå®è®°å½ |
| | | /// </summary> |
| | | private async Task ReleaseRemainingLocks(List<Dt_OutStockLockInfo> remainingLocks) |
| | | { |
| | | var lockIds = remainingLocks.Select(x => x.Id).ToList(); |
| | | |
| | | // å°éå®è®°å½ç¶ææ¹ä¸º"已鿾"ï¼æè
ç´æ¥å é¤ |
| | | // æ è®°ä¸ºå·²éæ¾ |
| | | await _outStockLockInfoService.Db.Updateable<Dt_OutStockLockInfo>() |
| | | .SetColumns(it => new Dt_OutStockLockInfo |
| | | { |
| | | Status = (int)OutLockStockStatusEnum.已鿾, // éè¦æ°å¢è¿ä¸ªç¶æ |
| | | // ReleaseTime = DateTime.Now, |
| | | Operator = App.User.UserName |
| | | }) |
| | | .Where(it => lockIds.Contains(it.Id)) |
| | | .ExecuteCommandAsync(); |
| | | |
| | | // ç´æ¥å é¤ï¼æ´å½»åºï¼ |
| | | // await _outStockLockInfoService.Db.Deleteable<Dt_OutStockLockInfo>() |
| | | // .Where(it => lockIds.Contains(it.Id)) |
| | | // .ExecuteCommandAsync(); |
| | | |
| | | _logger.LogInformation($"éæ¾{remainingLocks.Count}æ¡æªåæ£éå®è®°å½"); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ¸
çå·²ååºçéå®è®°å½ |
| | | /// </summary> |
| | | private async Task CleanupReturnedLocks(string orderNo, string palletCode) |
| | | { |
| | | // æ¥æ¾ææç¶æä¸ºååºä¸çéå®è®°å½å¹¶éæ¾ |
| | | var returnedLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(it => it.OrderNo == orderNo && |
| | | it.PalletCode == palletCode && |
| | | it.Status == (int)OutLockStockStatusEnum.ååºä¸) |
| | | .ToListAsync(); |
| | | |
| | | if (returnedLocks.Any()) |
| | | { |
| | | var returnedLockIds = returnedLocks.Select(x => x.Id).ToList(); |
| | | |
| | | await _outStockLockInfoService.Db.Updateable<Dt_OutStockLockInfo>() |
| | | .SetColumns(it => new Dt_OutStockLockInfo |
| | | { |
| | | Status = (int)OutLockStockStatusEnum.已鿾, |
| | | //ReleaseTime = DateTime.Now, |
| | | Operator = App.User.UserName |
| | | }) |
| | | .Where(it => returnedLockIds.Contains(it.Id)) |
| | | .ExecuteCommandAsync(); |
| | | |
| | | _logger.LogInformation($"æ¸
ç{returnedLocks.Count}æ¡ååºä¸éå®è®°å½"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// é置订åæç»çé宿°é |
| | | /// </summary> |
| | | private async Task ResetOrderDetailLockQuantities(PalletStatusAnalysis analysis) |
| | | { |
| | | // æ¶éææåå½±åç订åæç»ID |
| | | var affectedOrderDetailIds = new HashSet<int>(); |
| | | |
| | | if (analysis.HasRemainingLocks) |
| | | { |
| | | foreach (var lockInfo in analysis.RemainingLocks) |
| | | { |
| | | affectedOrderDetailIds.Add(lockInfo.OrderDetailId); |
| | | } |
| | | } |
| | | |
| | | // éç½®è¿äºè®¢åæç»çé宿°é |
| | | foreach (var orderDetailId in affectedOrderDetailIds) |
| | | { |
| | | await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>() |
| | | .SetColumns(it => new Dt_OutboundOrderDetail |
| | | { |
| | | LockQuantity = 0, // éç½®é宿°é |
| | | OrderDetailStatus = OrderDetailStatusEnum.New.ObjToInt() // éç½®ç¶æä¸ºæ°å»º |
| | | }) |
| | | .Where(it => it.Id == orderDetailId) |
| | | .ExecuteCommandAsync(); |
| | | } |
| | | |
| | | _logger.LogInformation($"éç½®{affectedOrderDetailIds.Count}个订åæç»çé宿°é"); |
| | | } |
| | | private async Task HandleRemainingLocksReturn(List<Dt_OutStockLockInfo> remainingLocks, int stockId) |
| | | { |
| | | var lockIds = remainingLocks.Select(x => x.Id).ToList(); |
| | |
| | | foreach (var lockInfo in remainingLocks) |
| | | { |
| | | decimal returnQty = lockInfo.AssignQuantity - lockInfo.PickedQty; |
| | | if (returnQty <= 0) |
| | | { |
| | | _logger.LogWarning($"éå®è®°å½{lockInfo.Id}æ éååºï¼åé
æ°é: {lockInfo.AssignQuantity}, å·²æ£é: {lockInfo.PickedQty}"); |
| | | continue; |
| | | } |
| | | |
| | | _logger.LogInformation($"å¤çéå®è®°å½ååº - éå®ID: {lockInfo.Id}, æ¡ç : {lockInfo.CurrentBarcode}, ååºæ°é: {returnQty}"); |
| | | // æ¥æ¾å¯¹åºçåºåæç» |
| | | var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .Where(it => it.Barcode == lockInfo.CurrentBarcode && it.StockId == lockInfo.StockId) |
| | |
| | | else |
| | | { |
| | | // å建æ°çåºåè®°å½ |
| | | var newStockDetail = new Dt_StockInfoDetail |
| | | { |
| | | StockId = lockInfo.StockId, |
| | | MaterielCode = lockInfo.MaterielCode, |
| | | MaterielName = lockInfo.MaterielName, |
| | | OrderNo = lockInfo.OrderNo, |
| | | BatchNo = lockInfo.BatchNo, |
| | | StockQuantity = returnQty, |
| | | OutboundQuantity = 0, |
| | | Barcode = lockInfo.CurrentBarcode, |
| | | InboundOrderRowNo = "", |
| | | Status = StockStatusEmun.å
¥åºç¡®è®¤.ObjToInt(), |
| | | SupplyCode = lockInfo.SupplyCode, |
| | | WarehouseCode = lockInfo.WarehouseCode, |
| | | Unit = lockInfo.Unit, |
| | | }; |
| | | await _stockInfoDetailService.Db.Insertable(newStockDetail).ExecuteCommandAsync(); |
| | | //var newStockDetail = new Dt_StockInfoDetail |
| | | //{ |
| | | // StockId = lockInfo.StockId, |
| | | // MaterielCode = lockInfo.MaterielCode, |
| | | // MaterielName = lockInfo.MaterielName, |
| | | // OrderNo = lockInfo.OrderNo, |
| | | // BatchNo = lockInfo.BatchNo, |
| | | // StockQuantity = returnQty, |
| | | // OutboundQuantity = 0, |
| | | // Barcode = lockInfo.CurrentBarcode, |
| | | // InboundOrderRowNo = "", |
| | | // Status = StockStatusEmun.å
¥åºç¡®è®¤.ObjToInt(), |
| | | // SupplyCode = lockInfo.SupplyCode, |
| | | // WarehouseCode = lockInfo.WarehouseCode, |
| | | // Unit = lockInfo.Unit, |
| | | //}; |
| | | //await _stockInfoDetailService.Db.Insertable(newStockDetail).ExecuteCommandAsync(); |
| | | } |
| | | } |
| | | } |
| | |
| | | foreach (var stockGood in palletStockGoods) |
| | | { |
| | | _logger.LogInformation($"å¾
ååºè´§ç© - æ¡ç : {stockGood.Barcode}, æ°é: {stockGood.StockQuantity}, å½åç¶æ: {stockGood.Status}"); |
| | | |
| | | // æ¢å¤åºåç¶æ |
| | | stockGood.OutboundQuantity = 0; |
| | | stockGood.Status = StockStatusEmun.å
¥åºç¡®è®¤.ObjToInt(); |
| | | |
| | | await _stockInfoDetailService.Db.Updateable(stockGood).ExecuteCommandAsync(); |
| | | if (stockGood.Status != StockStatusEmun.åºåºå®æ.ObjToInt()) |
| | | { |
| | | stockGood.OutboundQuantity = 0; |
| | | stockGood.Status = StockStatusEmun.å
¥åºç¡®è®¤.ObjToInt(); |
| | | await _stockInfoDetailService.Db.Updateable(stockGood).ExecuteCommandAsync(); |
| | | |
| | | _logger.LogInformation($"åºåè´§ç©ååºå®æ - æ¡ç : {stockGood.Barcode}, æ°ç¶æ: {stockGood.Status}"); |
| | | } |
| | | else |
| | | { |
| | | _logger.LogWarning($"è·³è¿å·²åºåºå®æçè´§ç© - æ¡ç : {stockGood.Barcode}"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private async Task HandleSplitRecordsReturn(List<Dt_SplitPackageRecord> splitRecords, string orderNo, string palletCode) |
| | | { |
| | | var validRecords = splitRecords.Where(x => x.Status != (int)SplitPackageStatusEnum.å·²æ£é).ToList(); |
| | | |
| | | if (!validRecords.Any()) |
| | | { |
| | | _logger.LogInformation("没æéè¦ååºçæå
è®°å½"); |
| | | return; |
| | | } |
| | | |
| | | _logger.LogInformation($"æ´æ°{validRecords.Count}æ¡æå
è®°å½ç¶æä¸ºå·²ååº"); |
| | | |
| | | // æ´æ°æå
è®°å½ç¶æ |
| | | await _splitPackageService.Db.Updateable<Dt_SplitPackageRecord>() |
| | | .SetColumns(x => new Dt_SplitPackageRecord |
| | | { |
| | | Status = (int)SplitPackageStatusEnum.å·²ååº, |
| | | Operator = App.User.UserName |
| | | }) |
| | | .Where(x => x.OrderNo == orderNo && x.PalletCode == palletCode && !x.IsReverted) |
| | | .Where(x => validRecords.Select(r => r.Id).Contains(x.Id)) |
| | | .ExecuteCommandAsync(); |
| | | } |
| | | |
| | |
| | | /// <param name="originalTask"></param> |
| | | /// <param name="analysis"></param> |
| | | /// <returns></returns> |
| | | private async Task CreateReturnTaskAndHandleESS(string orderNo, string palletCode, Dt_Task originalTask, ReturnAnalysisResult analysis) |
| | | private async Task CreateReturnTaskAndHandleESS(string orderNo, string palletCode, Dt_Task originalTask, TaskTypeEnum taskTypeEnum, int palletType) |
| | | { |
| | | var firstLocation = await _locationInfoService.Db.Queryable<Dt_LocationInfo>() |
| | | .FirstAsync(x => x.LocationCode == originalTask.SourceAddress); |
| | |
| | | Grade = 0, |
| | | PalletCode = palletCode, |
| | | NextAddress = "", |
| | | OrderNo = originalTask.OrderNo, |
| | | // OrderNo = originalTask.OrderNo, |
| | | OrderNo = orderNo, |
| | | Roadway = newLocation.RoadwayNo, |
| | | SourceAddress = stations[originalTask.TargetAddress], |
| | | TargetAddress = newLocation.LocationCode, |
| | | TaskStatus = TaskStatusEnum.New.ObjToInt(), |
| | | TaskType = TaskTypeEnum.InPick.ObjToInt(), |
| | | PalletType = originalTask.PalletType, |
| | | TaskType = taskTypeEnum.ObjToInt(), |
| | | PalletType = palletType, |
| | | WarehouseId = originalTask.WarehouseId |
| | | |
| | | }; |
| | | // ä¿åååºä»»å¡ |
| | | await _taskRepository.Db.Insertable(returnTask).ExecuteCommandAsync(); |
| | | var targetAddress = originalTask.TargetAddress; |
| | | |
| | | var targetAddress = originalTask.TargetAddress; |
| | | |
| | | // å é¤åå§åºåºä»»å¡ |
| | | await _taskRepository.Db.Deleteable(originalTask).ExecuteCommandAsync(); |
| | | _taskRepository.DeleteAndMoveIntoHty(originalTask, OperateTypeEnum.èªå¨å®æ); |
| | | // await _taskRepository.Db.Deleteable(originalTask).ExecuteCommandAsync(); |
| | | |
| | | |
| | | |
| | | // ç» ESS åéæµå¨ä¿¡å·ååå»ºä»»å¡ |
| | | await SendESSCommands(palletCode, targetAddress, returnTask); |
| | |
| | | containerCode = palletCode |
| | | }); |
| | | |
| | | if (moveResult) |
| | | //if (moveResult) |
| | | //{ |
| | | // 2. å建ååºä»»å¡ |
| | | var essTask = new TaskModel() |
| | | { |
| | | // 2. å建ååºä»»å¡ |
| | | var essTask = new TaskModel() |
| | | { |
| | | taskType = "putaway", |
| | | taskGroupCode = "", |
| | | groupPriority = 0, |
| | | tasks = new List<TasksType> |
| | | { |
| | | new() |
| | | { |
| | | taskType = "putaway", |
| | | taskGroupCode = "", |
| | | groupPriority = 0, |
| | | tasks = new List<TasksType>{ new() { |
| | | taskCode = returnTask.TaskNum.ToString(), |
| | | taskPriority = 0, |
| | | taskDescribe = new TaskDescribeType |
| | |
| | | deadline = 0, |
| | | storageTag = "" |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | } } |
| | | }; |
| | | |
| | | var resultTask = await _eSSApiService.CreateTaskAsync(essTask); |
| | | _logger.LogInformation($"ReturnRemaining åå»ºä»»å¡æå: {resultTask}"); |
| | | } |
| | | var resultTask = await _eSSApiService.CreateTaskAsync(essTask); |
| | | _logger.LogInformation($"ReturnRemaining åå»ºä»»å¡æå: {resultTask}"); |
| | | //} |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | |
| | | if (outboundOrder.OrderStatus != newStatus) |
| | | { |
| | | await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>() |
| | | .SetColumns(x => x.OrderStatus == newStatus) |
| | | .SetColumns(x => new Dt_OutboundOrder |
| | | { |
| | | OrderStatus = newStatus, |
| | | Operator = App.User.UserName, |
| | | }) |
| | | .Where(x => x.OrderNo == orderNo) |
| | | .ExecuteCommandAsync(); |
| | | |
| | | // åªææ£å¸¸åæ£å®ææ¶æåMESåé¦ |
| | | if (allCompleted && newStatus == (int)OutOrderStatusEnum.åºåºå®æ) |
| | | { |
| | | await HandleOrderCompletion(outboundOrder, orderNo); |
| | | } |
| | | //if (allCompleted && newStatus == (int)OutOrderStatusEnum.åºåºå®æ) |
| | | //{ |
| | | // await HandleOrderCompletion(outboundOrder, orderNo); |
| | | //} |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | |
| | | _logger.LogError($"CheckAndUpdateOrderStatus失败 - OrderNo: {orderNo}, Error: {ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | private async Task UpdateOrderStatusForReturn(string orderNo) |
| | | { |
| | |
| | | if (outboundOrder.OrderStatus != newStatus) |
| | | { |
| | | await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>() |
| | | .SetColumns(x => x.OrderStatus == newStatus) |
| | | .SetColumns(x => new Dt_OutboundOrder |
| | | { |
| | | OrderStatus = newStatus, |
| | | Operator = App.User.UserName, |
| | | }) |
| | | .Where(x => x.OrderNo == orderNo) |
| | | .ExecuteCommandAsync(); |
| | | |
| | |
| | | private async Task HandleOrderCompletion(Dt_OutboundOrder outboundOrder, string orderNo) |
| | | { |
| | | // è°æ¨åºåºå鿣åºåºä¸éè¦åé¦MES |
| | | if (outboundOrder.OrderType == OutOrderTypeEnum.Allocate.ObjToInt() || |
| | | outboundOrder.OrderType == OutOrderTypeEnum.ReCheck.ObjToInt()) |
| | | if (outboundOrder.OrderType == OutOrderTypeEnum.Allocate.ObjToInt()) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | try |
| | | { |
| | | var feedmodel = new FeedbackOutboundRequestModel |
| | | var allocate = _allocateService.Repository.QueryData(x => x.UpperOrderNo == outboundOrder.UpperOrderNo).First(); |
| | | var allocatefeedmodel = new AllocateDto |
| | | { |
| | | reqCode = Guid.NewGuid().ToString(), |
| | | reqTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), |
| | | business_type = outboundOrder.BusinessType, |
| | | factoryArea = outboundOrder.FactoryArea, |
| | | operationType = 1, |
| | | ReqCode = Guid.NewGuid().ToString(), |
| | | ReqTime = DateTime.Now.ToString(), |
| | | BusinessType = "3", |
| | | |
| | | FactoryArea = outboundOrder.FactoryArea, |
| | | OperationType = 1, |
| | | Operator = App.User.UserName, |
| | | orderNo = outboundOrder.UpperOrderNo, |
| | | status = outboundOrder.OrderStatus, |
| | | details = new List<FeedbackOutboundDetailsModel>() |
| | | }; |
| | | OrderNo = outboundOrder.UpperOrderNo, |
| | | // documentsNO = outboundOrder.OrderNo, |
| | | // status = outboundOrder.OrderStatus, |
| | | fromWarehouse = allocate?.FromWarehouse ?? "", |
| | | toWarehouse = allocate?.ToWarehouse ?? "", |
| | | Details = new List<AllocateDtoDetail>() |
| | | |
| | | }; |
| | | // åªè·åå·²æ£é宿çéå®è®°å½ |
| | | var lists = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.OrderNo == orderNo && x.Status == (int)OutLockStockStatusEnum.æ£é宿) |
| | | .ToListAsync(); |
| | | |
| | | var groupedData = lists.GroupBy(item => new { item.MaterielCode, item.lineNo, item.Unit, item.WarehouseCode }) |
| | | .Select(group => new FeedbackOutboundDetailsModel |
| | | .Select(group => new AllocateDtoDetail |
| | | { |
| | | 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.Unit, |
| | | barcodes = group.Select(row => new WIDESEA_DTO.Outbound.BarcodesModel |
| | | MaterialCode = group.Key.MaterielCode, |
| | | LineNo = group.Key.lineNo, |
| | | WarehouseCode = group.Key.WarehouseCode, |
| | | Qty = group.Sum(x => x.PickedQty), |
| | | |
| | | Unit = group.Key.Unit, |
| | | Barcodes = group.Select(row => new BarcodeInfo |
| | | { |
| | | barcode = row.CurrentBarcode, |
| | | supplyCode = row.SupplyCode, |
| | | batchNo = row.BatchNo, |
| | | unit = row.Unit, |
| | | qty = row.PickedQty |
| | | Barcode = row.CurrentBarcode, |
| | | SupplyCode = row.SupplyCode, |
| | | BatchNo = row.BatchNo, |
| | | Unit = row.Unit, |
| | | Qty = row.PickedQty |
| | | }).ToList() |
| | | |
| | | |
| | | }).ToList(); |
| | | allocatefeedmodel.Details = groupedData; |
| | | |
| | | feedmodel.details = groupedData; |
| | | |
| | | var result = await _invokeMESService.FeedbackOutbound(feedmodel); |
| | | var result = await _invokeMESService.FeedbackAllocate(allocatefeedmodel); |
| | | if (result != null && result.code == 200) |
| | | { |
| | | { |
| | | await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>() |
| | | .SetColumns(x => x.ReturnToMESStatus == 1) |
| | | .Where(x => x.OrderId == outboundOrder.Id) |
| | | .ExecuteCommandAsync(); |
| | | .SetColumns(x => x.ReturnToMESStatus == 1) |
| | | .Where(x => x.OrderId == outboundOrder.Id).ExecuteCommandAsync(); |
| | | |
| | | await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>() |
| | | .SetColumns(x => x.ReturnToMESStatus == 1) |
| | | .Where(x => x.OrderNo == orderNo) |
| | | .ExecuteCommandAsync(); |
| | | .SetColumns(x => new Dt_OutboundOrder |
| | | { |
| | | ReturnToMESStatus = 1, |
| | | Operator = App.User.UserName, |
| | | }).Where(x => x.OrderNo == orderNo).ExecuteCommandAsync(); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | else if (outboundOrder.OrderType == OutOrderTypeEnum.ReCheck.ObjToInt()) |
| | | { |
| | | _logger.LogError($"FeedbackOutbound失败 - OrderNo: {orderNo}, Error: {ex.Message}"); |
| | | |
| | | } |
| | | else |
| | | { |
| | | try |
| | | { |
| | | 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 = App.User.UserName, |
| | | orderNo = outboundOrder.UpperOrderNo, |
| | | documentsNO = outboundOrder.OrderNo, |
| | | status = outboundOrder.OrderStatus, |
| | | details = new List<FeedbackOutboundDetailsModel>() |
| | | }; |
| | | |
| | | // åªè·åå·²æ£é宿çéå®è®°å½ |
| | | var lists = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.OrderNo == orderNo && x.Status == (int)OutLockStockStatusEnum.æ£é宿) |
| | | .ToListAsync(); |
| | | |
| | | var groupedData = lists.GroupBy(item => new { item.MaterielCode, item.lineNo, item.Unit, 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.Unit, |
| | | barcodes = group.Select(row => new WIDESEA_DTO.Outbound.BarcodesModel |
| | | { |
| | | barcode = row.CurrentBarcode, |
| | | supplyCode = row.SupplyCode, |
| | | batchNo = row.BatchNo, |
| | | unit = row.Unit, |
| | | qty = row.PickedQty |
| | | }).ToList() |
| | | }).ToList(); |
| | | |
| | | feedmodel.details = groupedData; |
| | | |
| | | var result = await _invokeMESService.FeedbackOutbound(feedmodel); |
| | | 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 => new Dt_OutboundOrder |
| | | { |
| | | ReturnToMESStatus = 1, |
| | | Operator = App.User.UserName, |
| | | }) |
| | | |
| | | .Where(x => x.OrderNo == orderNo) |
| | | .ExecuteCommandAsync(); |
| | | } |
| | | |
| | | _logger.LogError($"FeedbackOutboundæå - OrderNo: {orderNo}, {JsonSerializer.Serialize(result)}"); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _logger.LogError($"FeedbackOutbound失败 - OrderNo: {orderNo}, Error: {ex.Message}"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region 空æç |
| | | |
| | | /// <summary> |
| | | /// æ¸
çé¶åºåæ°æ® |
| | | /// </summary> |
| | | private async Task CleanupZeroStockData(int stockId) |
| | | { |
| | | try |
| | | { |
| | | // 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())) |
| | | .ExecuteCommandAsync(); |
| | | |
| | | await _stockInfoService.Db.Deleteable<Dt_StockInfo>() |
| | | .Where(x => x.Id == stockId).ExecuteCommandAsync(); |
| | | |
| | | _logger.LogInformation($"æ¸
çé¶åºåæç»è®°å½ - StockId: {stockId}, å é¤è®°å½æ°: {deleteDetailCount}"); |
| | | |
| | | |
| | | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _logger.LogWarning($"æ¸
çé¶åºåæ°æ®å¤±è´¥ - StockId: {stockId}, Error: {ex.Message}"); |
| | | // 注æï¼æ¸
ç失败ä¸åºè¯¥å½±å主æµç¨ |
| | | } |
| | | } |
| | | /// <summary> |
| | | /// å¤ç任塿¸
çï¼æè®¢ååæçï¼ |
| | | /// </summary> |
| | | private async Task HandleTaskCleanup(string orderNo, string palletCode) |
| | | { |
| | | try |
| | | { |
| | | // 1. æ¥æ¾ææä¸è¯¥è®¢ååæçç¸å
³çä»»å¡ |
| | | var tasks = await _taskRepository.Db.Queryable<Dt_Task>().Where(x => x.OrderNo == orderNo && x.PalletCode == palletCode).ToListAsync(); |
| | | |
| | | if (tasks.Any()) |
| | | { |
| | | foreach (var task in tasks) |
| | | { |
| | | task.TaskStatus = (int)TaskStatusEnum.Finish; |
| | | } |
| | | // await _taskRepository.Db.Updateable(tasks).ExecuteCommandAsync(); |
| | | |
| | | _taskRepository.DeleteAndMoveIntoHty(tasks, OperateTypeEnum.èªå¨å®æ); |
| | | _logger.LogInformation($"宿{tasks.Count}个æçä»»å¡ - 订å: {orderNo}, æç: {palletCode}"); |
| | | } |
| | | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _logger.LogWarning($"å¤ç任塿¸
ç失败 - OrderNo: {orderNo}, PalletCode: {palletCode}, Error: {ex.Message}"); |
| | | throw new Exception($"任塿¸
ç失败: {ex.Message}"); |
| | | } |
| | | } |
| | | /// <summary> |
| | | /// æ´æ°è®¢åç¸å
³æ°æ® |
| | | /// </summary> |
| | | private async Task UpdateOrderData(string orderNo, string palletCode) |
| | | { |
| | | try |
| | | { |
| | | // æ£æ¥è®¢åæ¯å¦è¿æå
¶ä»æçå¨å¤çä¸ |
| | | var otherActivePallets = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.OrderNo == orderNo && |
| | | x.PalletCode != palletCode && |
| | | (x.Status == (int)OutLockStockStatusEnum.åºåºä¸ || x.Status == (int)OutLockStockStatusEnum.ååºä¸)) |
| | | .AnyAsync(); |
| | | |
| | | var otherActiveTasks = await _taskRepository.Db.Queryable<Dt_Task>() |
| | | .Where(x => x.OrderNo == orderNo && |
| | | x.PalletCode != palletCode |
| | | // && x.TaskStatus.In((int)TaskStatusEnum.å¾
æ§è¡, (int)TaskStatusEnum.æ§è¡ä¸) |
| | | ) |
| | | .AnyAsync(); |
| | | |
| | | // å¦ææ²¡æå
¶ä»æçå¨å¤çï¼æ£æ¥è®¢åæ¯å¦åºè¯¥å®æ |
| | | if (!otherActivePallets && !otherActiveTasks) |
| | | { |
| | | await CheckAndUpdateOrderCompletion(orderNo); |
| | | } |
| | | else |
| | | { |
| | | _logger.LogInformation($"订å {orderNo} è¿æå
¶ä»æçå¨å¤çï¼ä¸æ´æ°è®¢åç¶æ"); |
| | | } |
| | | |
| | | // 3. æ´æ°æ£éè®°å½ç¶æï¼å¯éï¼ |
| | | await UpdatePickingRecordsStatus(orderNo, palletCode); |
| | | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _logger.LogWarning($"æ´æ°è®¢åæ°æ®å¤±è´¥ - OrderNo: {orderNo}, PalletCode: {palletCode}, Error: {ex.Message}"); |
| | | throw new Exception($"æ´æ°è®¢åæ°æ®å¤±è´¥: {ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ£æ¥å¹¶æ´æ°è®¢åå®æç¶æ |
| | | /// </summary> |
| | | private async Task CheckAndUpdateOrderCompletion(string orderNo) |
| | | { |
| | | var orderDetails = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | .LeftJoin<Dt_OutboundOrder>((o, item) => o.OrderId == item.Id) |
| | | .Where((o, item) => item.OrderNo == orderNo) |
| | | .Select((o, item) => o) |
| | | .ToListAsync(); |
| | | |
| | | bool allCompleted = true; |
| | | foreach (var detail in orderDetails) |
| | | { |
| | | if (detail.OverOutQuantity < detail.NeedOutQuantity) |
| | | { |
| | | allCompleted = false; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | var outboundOrder = await _outboundOrderService.Db.Queryable<Dt_OutboundOrder>() |
| | | .FirstAsync(x => x.OrderNo == orderNo); |
| | | |
| | | if (outboundOrder != null && allCompleted && outboundOrder.OrderStatus != (int)OutOrderStatusEnum.åºåºå®æ) |
| | | { |
| | | outboundOrder.OrderStatus = (int)OutOrderStatusEnum.åºåºå®æ; |
| | | outboundOrder.Operator = App.User.UserName; |
| | | await _outboundOrderService.Db.Updateable(outboundOrder).ExecuteCommandAsync(); |
| | | |
| | | _logger.LogInformation($"订å {orderNo} å·²æ 记为åºåºå®æ"); |
| | | |
| | | // åMESåé¦è®¢å宿ï¼å¦æéè¦ï¼ |
| | | await HandleOrderCompletion(outboundOrder, orderNo); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ´æ°æ£éè®°å½ç¶æ |
| | | /// </summary> |
| | | private async Task UpdatePickingRecordsStatus(string orderNo, string palletCode) |
| | | { |
| | | try |
| | | { |
| | | // å¯ä»¥å°ç¸å
³çæ£éè®°å½æ è®°ä¸ºå·²å®æ |
| | | var pickingRecords = await Db.Queryable<Dt_PickingRecord>() |
| | | .Where(x => x.OrderNo == orderNo && x.PalletCode == palletCode) |
| | | .ToListAsync(); |
| | | |
| | | // è¿éå¯ä»¥æ ¹æ®éè¦æ´æ°æ£éè®°å½çç¶æåæ®µ |
| | | // ä¾å¦ï¼pickingRecord.Status = (int)PickingStatusEnum.已宿; |
| | | |
| | | _logger.LogInformation($"æ¾å°{pickingRecords.Count}æ¡æ£éè®°å½ - 订å: {orderNo}, æç: {palletCode}"); |
| | | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _logger.LogWarning($"æ´æ°æ£éè®°å½ç¶æå¤±è´¥: {ex.Message}"); |
| | | } |
| | | } |
| | | #endregion |
| | | |
| | | |
| | | |
| | | #region è¾
婿¹æ³ |
| | | /// <summary> |
| | | /// ç»ä¸åææçç¶æ - è¿åæçç宿´ç¶æä¿¡æ¯ |
| | | /// </summary> |
| | | private async Task<PalletStatusAnalysis> AnalyzePalletStatus(string orderNo, string palletCode, int stockId) |
| | | { |
| | | var result = new PalletStatusAnalysis |
| | | { |
| | | OrderNo = orderNo, |
| | | PalletCode = palletCode, |
| | | StockId = stockId |
| | | }; |
| | | |
| | | // åææªåæ£çåºåºéå®è®°å½ |
| | | var remainingLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(it => it.OrderNo == orderNo && |
| | | it.PalletCode == palletCode && |
| | | it.Status == (int)OutLockStockStatusEnum.åºåºä¸) |
| | | .ToListAsync(); |
| | | |
| | | if (remainingLocks.Any()) |
| | | { |
| | | result.HasRemainingLocks = true; |
| | | result.RemainingLocks = remainingLocks; |
| | | result.RemainingLocksReturnQty = remainingLocks.Sum(x => x.AssignQuantity - x.PickedQty); |
| | | _logger.LogInformation($"åç°{remainingLocks.Count}æ¡æªåæ£éå®è®°å½ï¼æ»æ°é: {result.RemainingLocksReturnQty}"); |
| | | } |
| | | |
| | | // åææçä¸çåºåè´§ç© |
| | | var palletStockGoods = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .Where(it => it.StockId == stockId && |
| | | (it.Status == StockStatusEmun.å
¥åºç¡®è®¤.ObjToInt() || |
| | | it.Status == StockStatusEmun.å
¥åºå®æ.ObjToInt() || |
| | | it.Status == StockStatusEmun.åºåºéå®.ObjToInt())) |
| | | .Where(it => it.StockQuantity > 0) |
| | | .ToListAsync(); |
| | | |
| | | if (palletStockGoods.Any()) |
| | | { |
| | | result.HasPalletStockGoods = true; |
| | | result.PalletStockGoods = palletStockGoods; |
| | | result.PalletStockReturnQty = palletStockGoods.Sum(x => x.StockQuantity); |
| | | _logger.LogInformation($"åç°{palletStockGoods.Count}个åºåè´§ç©ï¼æ»æ°é: {result.PalletStockReturnQty}"); |
| | | |
| | | // è®°å½è¯¦ç»ç¶æåå¸ |
| | | var statusGroups = palletStockGoods.GroupBy(x => x.Status); |
| | | foreach (var group in statusGroups) |
| | | { |
| | | _logger.LogInformation($"åºåç¶æ{group.Key}: {group.Count()}个货ç©ï¼æ°é: {group.Sum(x => x.StockQuantity)}"); |
| | | } |
| | | } |
| | | |
| | | //åææå
è®°å½ |
| | | var splitRecords = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>() |
| | | .Where(it => it.OrderNo == orderNo && |
| | | it.PalletCode == palletCode && |
| | | !it.IsReverted && it.Status != (int)SplitPackageStatusEnum.å·²æ£é && |
| | | it.Status != (int)SplitPackageStatusEnum.å·²ååº) |
| | | .ToListAsync(); |
| | | |
| | | if (splitRecords.Any()) |
| | | { |
| | | result.HasSplitRecords = true; |
| | | result.SplitRecords = splitRecords; |
| | | result.SplitReturnQty = await CalculateSplitReturnQuantity(splitRecords, stockId); |
| | | |
| | | _logger.LogInformation($"åç°{splitRecords.Count}æ¡æªæ£éæå
è®°å½ï¼æ»æ°é: {result.SplitReturnQty}"); |
| | | } |
| | | |
| | | // 4. è®¡ç®æ»ååºæ°éå空æçç¶æ |
| | | result.TotalReturnQty = result.RemainingLocksReturnQty + result.PalletStockReturnQty + result.SplitReturnQty; |
| | | result.HasItemsToReturn = result.TotalReturnQty > 0; |
| | | result.IsEmptyPallet = !result.HasItemsToReturn; |
| | | |
| | | // 5. æ£æ¥æ¯å¦æè¿è¡ä¸çä»»å¡ |
| | | result.HasActiveTasks = await _taskRepository.Db.Queryable<Dt_Task>() |
| | | .Where(x => x.OrderNo == orderNo && x.TaskType == TaskTypeEnum.InPick.ObjToInt() && |
| | | x.PalletCode == palletCode && |
| | | x.TaskStatus == (int)TaskStatusEnum.New) |
| | | .AnyAsync(); |
| | | |
| | | _logger.LogInformation($"æçç¶æåæå®æ - 订å: {orderNo}, æç: {palletCode}, " + |
| | | $"æ»ååºæ°é: {result.TotalReturnQty}, æ¯å¦ç©ºæç: {result.IsEmptyPallet}, " + |
| | | $"æè¿è¡ä¸ä»»å¡: {result.HasActiveTasks}"); |
| | | |
| | | return result; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ£æ¥æçæ¯å¦ä¸ºç©º |
| | | /// </summary> |
| | | private async Task<bool> IsPalletEmpty(string orderNo, string palletCode) |
| | | { |
| | | try |
| | | { |
| | | // è·ååºåä¿¡æ¯ |
| | | var stockInfo = await _stockInfoService.Db.Queryable<Dt_StockInfo>() |
| | | .Where(x => x.PalletCode == palletCode) |
| | | .FirstAsync(); |
| | | |
| | | if (stockInfo == null) |
| | | return false; |
| | | |
| | | // 使ç¨ç»ä¸çç¶æåæ |
| | | var statusAnalysis = await AnalyzePalletStatus(orderNo, palletCode, stockInfo.Id); |
| | | return statusAnalysis.IsEmptyPallet; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _logger.LogWarning($"æ£æ¥æçæ¯å¦ä¸ºç©ºå¤±è´¥ - OrderNo: {orderNo}, PalletCode: {palletCode}, Error: {ex.Message}"); |
| | | return false; |
| | | } |
| | | } |
| | | /// <summary> |
| | | /// æ£æ¥å¹¶å¤ç空æç |
| | | /// </summary> |
| | | private async Task<bool> CheckAndHandleEmptyPallet(string orderNo, string palletCode) |
| | | { |
| | | try |
| | | { |
| | | // 1. è·ååºåä¿¡æ¯ |
| | | var stockInfo = await _stockInfoService.Db.Queryable<Dt_StockInfo>() |
| | | .Where(x => x.PalletCode == palletCode) |
| | | .FirstAsync(); |
| | | |
| | | if (stockInfo == null) |
| | | { |
| | | _logger.LogWarning($"æªæ¾å°æç {palletCode} çåºåä¿¡æ¯"); |
| | | return false; |
| | | } |
| | | |
| | | // 2. 使ç¨ç»ä¸çç¶æåæ |
| | | var statusAnalysis = await AnalyzePalletStatus(orderNo, palletCode, stockInfo.Id); |
| | | |
| | | // 3. æ£æ¥æ¯å¦ä¸ºç©ºæç䏿²¡æè¿è¡ä¸çä»»å¡ |
| | | if (!statusAnalysis.IsEmptyPallet || statusAnalysis.HasActiveTasks) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | _logger.LogInformation($"æ£æµå°ç©ºæçï¼å¼å§èªå¨å¤ç - 订å: {orderNo}, æç: {palletCode}"); |
| | | |
| | | //// æ¸
çé¶åºåæ°æ® |
| | | //await CleanupZeroStockData(stockInfo.Id); |
| | | |
| | | //// æ´æ°åºåä¸»è¡¨ç¶æä¸ºç©ºæç |
| | | //await UpdateStockInfoAsEmpty(stockInfo); |
| | | |
| | | //// å¤çåºåºéå®è®°å½ |
| | | //await HandleOutStockLockRecords(orderNo, palletCode); |
| | | |
| | | //// å¤çä»»å¡ç¶æ |
| | | //await HandleTaskStatusForEmptyPallet(orderNo, palletCode); |
| | | |
| | | //// æ´æ°è®¢åæ°æ® |
| | | //await UpdateOrderDataForEmptyPallet(orderNo, palletCode); |
| | | |
| | | ////è®°å½æä½åå² |
| | | //await RecordAutoEmptyPalletOperation(orderNo, palletCode); |
| | | |
| | | _logger.LogInformation($"空æçèªå¨å¤ç宿 - 订å: {orderNo}, æç: {palletCode}"); |
| | | |
| | | return true; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _logger.LogError($"èªå¨å¤ç空æç失败 - OrderNo: {orderNo}, PalletCode: {palletCode}, Error: {ex.Message}"); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | private async Task<string> GenerateNewBarcode() |
| | | { |
| | |
| | | OriginalLockQuantity = quantity, |
| | | IsSplitted = 1, |
| | | ParentLockId = originalLock.Id, |
| | | Operator= App.User.UserName, |
| | | FactoryArea=originalLock.FactoryArea, |
| | | lineNo=originalLock.lineNo, |
| | | WarehouseCode=originalLock.WarehouseCode, |
| | | Operator = App.User.UserName, |
| | | FactoryArea = originalLock.FactoryArea, |
| | | lineNo = originalLock.lineNo, |
| | | WarehouseCode = originalLock.WarehouseCode, |
| | | BarcodeQty=originalLock.BarcodeQty, |
| | | BarcodeUnit=originalLock.BarcodeUnit, |
| | | |
| | | }; |
| | | |
| | |
| | | } |
| | | return WebResponseContent.Instance.OK("æ£é确认æå", new { SplitResults = new List<SplitResult>() }); |
| | | } |
| | | |
| | | |
| | | |
| | | #region èæåºå
¥åº |
| | |
| | | public List<Dt_StockInfoDetail> PalletStockGoods { get; set; } = new List<Dt_StockInfoDetail>(); |
| | | public List<Dt_SplitPackageRecord> SplitRecords { get; set; } = new List<Dt_SplitPackageRecord>(); |
| | | } |
| | | public class PalletStatusAnalysis |
| | | { |
| | | public string OrderNo { get; set; } |
| | | public string PalletCode { get; set; } |
| | | public int StockId { get; set; } |
| | | |
| | | // ååºç¸å
³å±æ§ |
| | | public bool HasItemsToReturn { get; set; } |
| | | public bool HasRemainingLocks { get; set; } |
| | | public bool HasPalletStockGoods { get; set; } |
| | | public bool HasSplitRecords { get; set; } |
| | | public decimal RemainingLocksReturnQty { get; set; } |
| | | public decimal PalletStockReturnQty { get; set; } |
| | | public decimal SplitReturnQty { get; set; } |
| | | public decimal TotalReturnQty { get; set; } |
| | | public List<Dt_OutStockLockInfo> RemainingLocks { get; set; } = new List<Dt_OutStockLockInfo>(); |
| | | public List<Dt_StockInfoDetail> PalletStockGoods { get; set; } = new List<Dt_StockInfoDetail>(); |
| | | public List<Dt_SplitPackageRecord> SplitRecords { get; set; } = new List<Dt_SplitPackageRecord>(); |
| | | |
| | | // 空æçç¸å
³å±æ§ |
| | | public bool IsEmptyPallet { get; set; } |
| | | public bool HasActiveTasks { get; set; } |
| | | |
| | | // ä¾¿å©æ¹æ³ |
| | | public bool CanReturn => HasItemsToReturn && !HasActiveTasks; |
| | | public bool CanRemove => IsEmptyPallet && !HasActiveTasks; |
| | | } |
| | | public class PickingContext |
| | | { |
| | | public string OrderNo { get; set; } |
| | | public string PalletCode { get; set; } |
| | | public string Barcode { get; set; } |
| | | public string Operator { get; set; } |
| | | public Dt_OutStockLockInfo LockInfo { get; set; } |
| | | public Dt_OutboundOrderDetail OrderDetail { get; set; } |
| | | public Dt_StockInfoDetail StockDetail { get; set; } |
| | | public decimal ActualQuantity { get; set; } |
| | | public string AdjustedReason { get; set; } |
| | | } |
| | | public class CancelPickingContext |
| | | { |
| | | public string OrderNo { get; set; } |
| | | public string PalletCode { get; set; } |
| | | public string Barcode { get; set; } |
| | | public string Operator { get; set; } |
| | | |
| | | public decimal CancelQuantity { get; set; } |
| | | public Dt_PickingRecord PickingRecord { get; set; } |
| | | public Dt_OutStockLockInfo LockInfo { get; set; } |
| | | public Dt_OutboundOrderDetail OrderDetail { get; set; } |
| | | } |
| | | #endregion |
| | | } |
| | |
| | | </PropertyGroup> |
| | | |
| | | <ItemGroup> |
| | | <ProjectReference Include="..\WIDESEA_BasicService\WIDESEA_BasicService.csproj" /> |
| | | <ProjectReference Include="..\WIDESEA_IAllocateService\WIDESEA_IAllocateService.csproj" /> |
| | | <ProjectReference Include="..\WIDESEA_IBasicService\WIDESEA_IBasicService.csproj" /> |
| | | <ProjectReference Include="..\WIDESEA_IInboundService\WIDESEA_IInboundService.csproj" /> |
| | | <ProjectReference Include="..\WIDESEA_IOutboundService\WIDESEA_IOutboundService.csproj" /> |
| | |
| | | public IRepository<Dt_StockInfo> Repository => BaseDal; |
| | | private readonly IRepository<Dt_StockInfoDetail> _stockInfoDetailRepository; |
| | | private readonly IOutboundOrderService _outboundOrderService; |
| | | //private readonly IOutboundOrderDetailService _outboundOrderDetailService; |
| | | private readonly ILocationInfoService _locationInfoService; |
| | | public StockInfoService(IRepository<Dt_StockInfo> BaseDal, IMapper mapper, IRepository<Dt_StockInfoDetail> stockInfoDetailRepository, IRecordService recordService, ILocationInfoService locationInfoService, IOutboundOrderService outboundOrderService) : base(BaseDal) |
| | | { |
| | |
| | | _recordService = recordService; |
| | | _locationInfoService = locationInfoService; |
| | | _outboundOrderService = outboundOrderService; |
| | | //_outboundOrderDetailService = outboundOrderDetailService; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | if (!string.IsNullOrEmpty(supplyCode)) |
| | | { |
| | | query = query.Where(x => x.Details.Any(d => d.SupplyCode == supplyCode)); |
| | | } |
| | | } |
| | | |
| | | var stocks = query.ToList(); |
| | | |
| | | return stocks.OrderBy(x => x.Details.Where(d => d.MaterielCode == materielCode && (string.IsNullOrEmpty(supplyCode) || d.SupplyCode == supplyCode) && |
| | | (string.IsNullOrEmpty(lotNo) || d.BatchNo == lotNo)).Min(d => d.CreateDate)).ToList(); |
| | | return query.OrderBy(x => x.CreateDate).ToList(); |
| | | //ISugarQueryable<Dt_LocationInfo> sugarQueryable = Db.Queryable<Dt_LocationInfo>().Where(x => locationCodes.Contains(x.LocationCode)); |
| | | //ISugarQueryable<Dt_StockInfo> sugarQueryable1 = Db.Queryable<Dt_StockInfo>().Includes(x => x.Details).Where(x => x.Details.Any(v => v.MaterielCode == materielCode)); |
| | | //return sugarQueryable.InnerJoin(sugarQueryable1, (a, b) => a.LocationCode == b.LocationCode).Select((a, b) => b).OrderBy(a => a.CreateDate).Includes(a => a.Details).ToList(); |
| | |
| | | |
| | | public List<Dt_StockInfo> GetStockInfosByPalletCodes(List<string> palletCodes) |
| | | { |
| | | return Db.Queryable<Dt_StockInfo>().Where(x => palletCodes.Contains(x.PalletCode)).Includes(x => x.Details).ToList(); |
| | | return Db.Queryable<Dt_StockInfo>().Where(x => palletCodes.Contains(x.PalletCode)).Includes(x => x.Details).OrderBy(x => x.CreateDate).ToList(); |
| | | } |
| | | // æ·»å è·åå个æçåºåçæ¹æ³ï¼å¦æä¸åå¨ï¼ |
| | | public Dt_StockInfo GetStockInfoByPalletCode(string palletCode) |
| | | { |
| | | return Db.Queryable<Dt_StockInfo>() |
| | | .Where(x => x.PalletCode == palletCode) |
| | | .Includes(x => x.Details) |
| | | .First(); |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// |
| | | /// </summary> |
| | | /// <param name="orderId"></param> |
| | | /// <param name="materielCode"></param> |
| | | /// <returns></returns> |
| | | //public List<StockSelectViewDTO> GetStockSelectViews(int orderId, string materielCode) |
| | | //{ |
| | | // try |
| | | // { |
| | | // Dt_OutboundOrder outboundOrder = _outboundOrderService.Repository.QueryFirst(x => x.Id == orderId); |
| | | // if (outboundOrder == null) |
| | | // { |
| | | // throw new Exception($"æªæ¾å°åºåºåä¿¡æ¯"); |
| | | // } |
| | | |
| | | // List<string> locationCodes = _locationInfoService.GetCanOutLocationCodes(); |
| | | |
| | | // return BaseDal.QueryTabs<Dt_StockInfo, Dt_StockInfoDetail, StockSelectViewDTO>((a, b) => a.Id == b.StockId, (a, b) => new StockSelectViewDTO |
| | | // { |
| | | // LocationCode = a.LocationCode, |
| | | // MaterielCode = b.MaterielCode, |
| | | // MaterielName = b.MaterielName, |
| | | // Barcode=b.Barcode, |
| | | // PalletCode = a.PalletCode, |
| | | // UseableQuantity = b.StockQuantity - b.OutboundQuantity |
| | | // }, a => locationCodes.Contains(a.LocationCode), b => b.StockQuantity > b.OutboundQuantity && b.MaterielCode == materielCode, x => true).GroupBy(x => x.PalletCode).Select(x => new StockSelectViewDTO |
| | | // { |
| | | // LocationCode = x.FirstOrDefault()?.LocationCode ?? "", |
| | | // MaterielCode = x.FirstOrDefault()?.MaterielCode ?? "", |
| | | // MaterielName = x.FirstOrDefault()?.MaterielName ?? "", |
| | | // Barcode=x.FirstOrDefault()?.Barcode??"", |
| | | // PalletCode = x.Key, |
| | | // UseableQuantity = x.Sum(x => x.UseableQuantity) |
| | | // }).ToList(); |
| | | // } |
| | | // catch (Exception ex) |
| | | // { |
| | | // return null; |
| | | // } |
| | | |
| | | //} |
| | | |
| | | public List<StockSelectViewDTO> GetStockSelectViews(int orderId, string materielCode) |
| | | { |
| | | try |
| | | Dt_OutboundOrder outboundOrder = _outboundOrderService.Repository.QueryFirst(x => x.Id == orderId); |
| | | if (outboundOrder == null) |
| | | { |
| | | Dt_OutboundOrder outboundOrder = _outboundOrderService.Repository.QueryFirst(x => x.Id == orderId); |
| | | if (outboundOrder == null) |
| | | throw new Exception($"æªæ¾å°ID为{orderId}çåºåºåä¿¡æ¯"); |
| | | } |
| | | |
| | | // è·ååºåºåæç»ï¼ç¨äºç¡®å®éè¦çæ¹æ¬¡åä¾åºå |
| | | var orderDetails = SqlSugarHelper.DbWMS.Queryable<Dt_OutboundOrderDetail>().Where(x => x.OrderId == orderId && x.MaterielCode == materielCode).ToList(); |
| | | |
| | | if (!orderDetails.Any()) |
| | | { |
| | | throw new Exception($"åºåºå{orderId}䏿ªæ¾å°ç©æ{materielCode}çæç»ä¿¡æ¯"); |
| | | } |
| | | |
| | | List<string> locationCodes = _locationInfoService.GetCanOutLocationCodes(); |
| | | var result = new List<StockSelectViewDTO>(); |
| | | |
| | | // 为æ¯ä¸ªåºåºåæç»æ¥è¯¢å¯¹åºçåºå |
| | | foreach (var orderDetail in orderDetails) |
| | | { |
| | | // æå»ºæ¥è¯¢æ¡ä»¶ |
| | | var stockQuery = Db.Queryable<Dt_StockInfo>() |
| | | .Where(x => locationCodes.Contains(x.LocationCode)) |
| | | .Where(x => x.StockStatus == (int)StockStatusEmun.å
¥åºå®æ) |
| | | .Includes(x => x.Details); |
| | | |
| | | // æ§è¡æ¥è¯¢å¹¶æå
è¿å
åºæåº |
| | | var stocks = stockQuery.ToList() |
| | | .Where(x => x.Details.Any(d => |
| | | d.MaterielCode == materielCode && |
| | | string.IsNullOrEmpty(orderDetail.BatchNo)?true: d.BatchNo == orderDetail.BatchNo&& |
| | | string.IsNullOrEmpty(orderDetail.BatchNo)?true:d.SupplyCode == orderDetail.SupplyCode && |
| | | d.StockQuantity > d.OutboundQuantity |
| | | )) |
| | | .OrderBy(x => x.CreateDate) |
| | | .ToList(); |
| | | |
| | | foreach (var stock in stocks) |
| | | { |
| | | throw new Exception($"æªæ¾å°åºåºåä¿¡æ¯"); |
| | | var relevantDetails = stock.Details |
| | | .Where(d => d.MaterielCode == materielCode && |
| | | string.IsNullOrEmpty(orderDetail.BatchNo) ? true : d.BatchNo == orderDetail.BatchNo && |
| | | string.IsNullOrEmpty(orderDetail.BatchNo) ? true : d.SupplyCode == orderDetail.SupplyCode && |
| | | d.StockQuantity > d.OutboundQuantity) |
| | | .ToList(); |
| | | |
| | | if (relevantDetails.Any()) |
| | | { |
| | | var firstDetail = relevantDetails.First(); |
| | | var useableQuantity = relevantDetails.Sum(d => d.StockQuantity - d.OutboundQuantity); |
| | | |
| | | result.Add(new StockSelectViewDTO |
| | | { |
| | | LocationCode = stock.LocationCode, |
| | | MaterielCode = materielCode, |
| | | MaterielName = firstDetail.MaterielName, |
| | | BatchNo = orderDetail.BatchNo, |
| | | SupplyCode = orderDetail.SupplyCode, |
| | | Barcode = firstDetail.Barcode, |
| | | PalletCode = stock.PalletCode, |
| | | UseableQuantity = useableQuantity, |
| | | StockCreateDate = stock.CreateDate, |
| | | StockId = stock.Id, |
| | | OrderDetailId = orderDetail.Id // å
³èå°å
·ä½çåºåºåæç» |
| | | }); |
| | | } |
| | | } |
| | | |
| | | List<string> locationCodes = _locationInfoService.GetCanOutLocationCodes(); |
| | | |
| | | return BaseDal.QueryTabs<Dt_StockInfo, Dt_StockInfoDetail, StockSelectViewDTO>((a, b) => a.Id == b.StockId, (a, b) => new StockSelectViewDTO |
| | | { |
| | | LocationCode = a.LocationCode, |
| | | MaterielCode = b.MaterielCode, |
| | | MaterielName = b.MaterielName, |
| | | PalletCode = a.PalletCode, |
| | | UseableQuantity = b.StockQuantity - b.OutboundQuantity |
| | | }, a => locationCodes.Contains(a.LocationCode), b => b.StockQuantity > b.OutboundQuantity && b.MaterielCode == materielCode, x => true).GroupBy(x => x.PalletCode).Select(x => new StockSelectViewDTO |
| | | { |
| | | LocationCode = x.FirstOrDefault()?.LocationCode ?? "", |
| | | MaterielCode = x.FirstOrDefault()?.MaterielCode ?? "", |
| | | MaterielName = x.FirstOrDefault()?.MaterielName ?? "", |
| | | PalletCode = x.Key, |
| | | UseableQuantity = x.Sum(x => x.UseableQuantity) |
| | | }).ToList(); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | return null; |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | } |
| | | } |
| | |
| | | using WIDESEA_DTO.Allocate; |
| | | using WIDESEA_DTO.Basic; |
| | | using WIDESEA_DTO.Inbound; |
| | | using WIDESEA_DTO.Outbound; |
| | | using WIDESEA_DTO.Task; |
| | | using WIDESEA_IAllocateService; |
| | | using WIDESEA_IBasicService; |
| | |
| | | using WIDESEA_IStockService; |
| | | using WIDESEA_ITaskInfoService; |
| | | using WIDESEA_Model.Models; |
| | | using WIDESEA_Model.Models.Outbound; |
| | | |
| | | namespace WIDESEA_TaskInfoService |
| | | { |
| | |
| | | private readonly IInboundOrderService _inboundOrderService; |
| | | private readonly IInboundOrderDetailService _inboundOrderDetailService; |
| | | |
| | | private readonly IRepository<Dt_OutboundBatch> _OutboundBatchRepository; |
| | | private readonly IOutboundOrderService _outboundOrderService; |
| | | private readonly IOutboundOrderDetailService _outboundOrderDetailService; |
| | | private readonly IOutStockLockInfoService _outStockLockInfoService; |
| | |
| | | |
| | | 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) : 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) : base(BaseDal) |
| | | { |
| | | _mapper = mapper; |
| | | _unitOfWorkManage = unitOfWorkManage; |
| | |
| | | _invokeMESService = invokeMESService; |
| | | _outStockLockInfoService = outStockLockInfoService; |
| | | _allocateService = allocateService; |
| | | _OutboundBatchRepository = outboundBatchRepository; |
| | | } |
| | | |
| | | |
| | |
| | | |
| | | if (int.TryParse(taskNum, out var newTaskNum)) |
| | | { |
| | | task = BaseDal.QueryFirst(x => x.TaskNum == newTaskNum); |
| | | task = await BaseDal.QueryFirstAsync(x => x.TaskNum == newTaskNum); |
| | | if (task == null) |
| | | { |
| | | return WebResponseContent.Instance.Error("æªæ¾å°ä»»å¡ä¿¡æ¯"); |
| | |
| | | MethodInfo? methodInfo = GetType().GetMethod(((TaskTypeEnum)task.TaskType) + "TaskCompleted"); |
| | | if (methodInfo != null) |
| | | { |
| | | WebResponseContent? responseContent = (WebResponseContent?)methodInfo.Invoke(this, new object[] { task }); |
| | | if (responseContent != null) |
| | | object? taskResult = methodInfo.Invoke(this, new object[] { task }); |
| | | if (taskResult is Task<WebResponseContent> asyncTask) |
| | | { |
| | | return responseContent; |
| | | try |
| | | { |
| | | // 3. 弿¥çå¾
Task 宿ï¼èªå¨è§£æåº WebResponseContent |
| | | WebResponseContent responseContent = await asyncTask; |
| | | if (responseContent != null) |
| | | { |
| | | return responseContent; |
| | | } |
| | | } |
| | | catch (AggregateException ex) |
| | | { |
| | | _logger.LogError($"TaskService TaskCompleted taskResult: {ex.Message} "); |
| | | return WebResponseContent.Instance.Error(ex.Message); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _logger.LogError(ex, $"Unexpected error in {task.TaskType}"); |
| | | return WebResponseContent.Instance.Error(ex.Message); |
| | | } |
| | | } |
| | | } |
| | | return WebResponseContent.Instance.Error("æªæ¾å°ä»»å¡ç±»å对åºä¸å¡å¤çé»è¾"); |
| | |
| | | { |
| | | foreach (var inboundOrder in inboundOrders) |
| | | { |
| | | if (inboundOrder.OrderType == InOrderTypeEnum.Allocat.ObjToInt())//è°æ¨å
¥åº |
| | | if (inboundOrder.OrderType == InOrderTypeEnum.AllocatInbound.ObjToInt())//è°æ¨å
¥åº |
| | | { |
| | | if (inboundOrder != null && inboundOrder.OrderStatus == InOrderStatusEnum.å
¥åºå®æ.ObjToInt()) |
| | | { |
| | | var allocate = _allocateService.Repository.QueryData(x => x.OrderNo == inboundOrder.InboundOrderNo).First(); |
| | | var feedmodel = new AllocateDto |
| | | var allocatefeedmodel = new AllocateDto |
| | | { |
| | | ReqCode = Guid.NewGuid().ToString(), |
| | | ReqTime = DateTime.Now.ToString(), |
| | |
| | | OperationType = 1, |
| | | Operator = inboundOrder.Operator, |
| | | OrderNo = inboundOrder.UpperOrderNo, |
| | | fromWarehouse = allocate?.FromWarehouse??"", |
| | | toWarehouse = allocate?.ToWarehouse??"", |
| | | fromWarehouse = allocate?.FromWarehouse ?? "", |
| | | toWarehouse = allocate?.ToWarehouse ?? "", |
| | | Details = new List<AllocateDtoDetail>() |
| | | |
| | | }; |
| | |
| | | Unit = row.Unit |
| | | }).ToList() |
| | | }).ToList(); |
| | | feedmodel.Details = groupedData; |
| | | allocatefeedmodel.Details = groupedData; |
| | | |
| | | var result = await _invokeMESService.FeedbackAllocate(feedmodel); |
| | | var result = await _invokeMESService.FeedbackAllocate(allocatefeedmodel); |
| | | if (result != null && result.code == 200) |
| | | { |
| | | _inboundOrderService.Db.Updateable<Dt_InboundOrder>().SetColumns(it => new Dt_InboundOrder { ReturnToMESStatus = 1 }) |
| | |
| | | return WebResponseContent.Instance.OK(); |
| | | } |
| | | |
| | | public WebResponseContent OutboundTaskCompleted(Dt_Task task) |
| | | |
| | | public async Task<WebResponseContent> OutAllocateTaskCompleted(Dt_Task task) |
| | | { |
| | | _logger.LogInformation($"TaskService OutAllocateTaskCompleted: {task.TaskNum}"); |
| | | |
| | | return await OutboundTaskCompleted(task); |
| | | } |
| | | public async Task<WebResponseContent> OutboundTaskCompleted(Dt_Task task) |
| | | { |
| | | _logger.LogInformation($"TaskService OutboundTaskCompleted: {task.TaskNum}"); |
| | | //æ¥è´§ä½ |
| | |
| | | locationInfo.LocationStatus = LocationStatusEnum.Free.ObjToInt(); |
| | | _locationInfoService.Repository.UpdateData(locationInfo); |
| | | |
| | | var outloks = _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>().Where(x => x.TaskNum == task.TaskNum).ToList(); |
| | | var outloks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>().Where(x => x.TaskNum == task.TaskNum).ToListAsync(); |
| | | |
| | | var stockids = outloks.Select(x => x.StockId).ToList(); |
| | | |
| | |
| | | stockInfo.StockStatus = StockStatusEmun.å
¥åºå®æ.ObjToInt(); |
| | | _stockRepository.UpdateData(stockInfo); |
| | | |
| | | 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.äººå·¥å®æ); |
| | | |
| | | _locationStatusChangeRecordService.AddLocationStatusChangeRecord(locationInfo, beforelocationStatus, StockChangeType.Inbound.ObjToInt(), "", task.TaskNum); |
| | | |
| | | |
| | | if (outboundOrder != null) |
| | | { |
| | | await HandleOutboundOrderToMESCompletion(outboundOrder, outboundOrder.OrderNo); |
| | | } |
| | | else |
| | | { |
| | | _logger.LogInformation($"TaskService InEmptyTaskCompleted: {task.TaskNum} ,æªæ¾å°åºåºåã "); |
| | | } |
| | | |
| | | return content; |
| | | } |
| | |
| | | public async Task<WebResponseContent> InPickTaskCompleted(Dt_Task task) |
| | | { |
| | | _logger.LogInformation($"TaskService InPickTaskCompleted: {task.TaskNum}"); |
| | | //æ¥åºå |
| | | Dt_StockInfo stockInfo = _stockRepository.Db.Queryable<Dt_StockInfo>().Includes(x => x.Details).Where(x => x.PalletCode == task.PalletCode).First(); |
| | | if (stockInfo == null) |
| | | try |
| | | { |
| | | return WebResponseContent.Instance.Error($"æªæ¾å°æç对åºçç»çä¿¡æ¯"); |
| | | //æ¥åºå |
| | | Dt_StockInfo stockInfo = await _stockRepository.Db.Queryable<Dt_StockInfo>().Includes(x => x.Details).Where(x => x.PalletCode == task.PalletCode).FirstAsync(); |
| | | if (stockInfo == null) |
| | | { |
| | | _logger.LogInformation($"TaskService InPickTaskCompleted: æªæ¾å°æç对åºçç»çä¿¡æ¯.{task.TaskNum}"); |
| | | return WebResponseContent.Instance.Error($"æªæ¾å°æç对åºçç»çä¿¡æ¯"); |
| | | } |
| | | if (stockInfo.Details.Count == 0 && stockInfo.PalletType != PalletTypeEnum.Empty.ObjToInt()) |
| | | { |
| | | _logger.LogInformation($"TaskService InPickTaskCompleted: æªæ¾å°è¯¥æçåºåæç»ä¿¡æ¯.{task.TaskNum}"); |
| | | return WebResponseContent.Instance.Error($"æªæ¾å°è¯¥æçåºåæç»ä¿¡æ¯"); |
| | | } |
| | | //æ¥è´§ä½ |
| | | Dt_LocationInfo locationInfo = _locationInfoService.Repository.QueryFirst(x => x.LocationCode == task.TargetAddress); |
| | | if (locationInfo == null) |
| | | { |
| | | _logger.LogInformation($"TaskService InPickTaskCompleted: æªæ¾å°å¯¹åºçç»ç¹è´§ä½ä¿¡æ¯ {task.TaskNum}."); |
| | | return WebResponseContent.Instance.Error($"æªæ¾å°å¯¹åºçç»ç¹è´§ä½ä¿¡æ¯"); |
| | | } |
| | | |
| | | var beforelocationStatus = locationInfo.LocationStatus; |
| | | // è·åææååºä¸çåºåºéå®è®°å½ |
| | | var returnLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(it => it.OrderNo == task.OrderNo && it.PalletCode == task.PalletCode && it.Status == (int)OutLockStockStatusEnum.ååºä¸) |
| | | .ToListAsync(); |
| | | // æ´æ°åºåºéå®è®°å½ç¶æä¸ºååºå®æ |
| | | foreach (var lockInfo in returnLocks) |
| | | { |
| | | lockInfo.Status = (int)OutLockStockStatusEnum.å·²ååº; |
| | | } |
| | | _outStockLockInfoService.Db.Updateable(returnLocks).ExecuteCommand(); |
| | | |
| | | stockInfo.LocationCode = task.TargetAddress; |
| | | stockInfo.StockStatus = StockStatusEmun.å
¥åºå®æ.ObjToInt(); |
| | | if (stockInfo.Details != null && stockInfo.Details.Any()) |
| | | { |
| | | stockInfo.Details.ForEach(x => |
| | | { |
| | | x.Status = StockStatusEmun.å
¥åºå®æ.ObjToInt(); |
| | | }); |
| | | _stockService.StockInfoDetailService.Repository.UpdateData(stockInfo.Details); |
| | | } |
| | | |
| | | _stockService.StockInfoService.Repository.UpdateData(stockInfo); |
| | | |
| | | await ProcessStockDetailsForReturn(task, stockInfo.Id); |
| | | |
| | | await DeleteZeroQuantityStockDetails(stockInfo.Id); |
| | | |
| | | if (stockInfo.PalletType == PalletTypeEnum.Empty.ObjToInt()) |
| | | { |
| | | locationInfo.LocationStatus = LocationStatusEnum.Pallet.ObjToInt(); |
| | | } |
| | | else |
| | | { |
| | | locationInfo.LocationStatus = LocationStatusEnum.InStock.ObjToInt(); |
| | | } |
| | | _locationInfoService.Repository.UpdateData(locationInfo); |
| | | 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 ? OperateTypeEnum.èªå¨å®æ : OperateTypeEnum.äººå·¥å®æ); |
| | | BaseDal.DeleteData(task); |
| | | _locationStatusChangeRecordService.AddLocationStatusChangeRecord(locationInfo, beforelocationStatus, StockChangeType.Inbound.ObjToInt(), "", task.TaskNum); |
| | | |
| | | if (outboundOrder != null) |
| | | { |
| | | await HandleOutboundOrderToMESCompletion(outboundOrder, outboundOrder.OrderNo); |
| | | } |
| | | else |
| | | { |
| | | _logger.LogInformation($"TaskService InPickTaskCompleted: {task.TaskNum} ,æªæ¾å°åºåºåã "); |
| | | } |
| | | } |
| | | if (stockInfo.Details.Count == 0 && stockInfo.PalletType != PalletTypeEnum.Empty.ObjToInt()) |
| | | catch (Exception ex) |
| | | { |
| | | return WebResponseContent.Instance.Error($"æªæ¾å°è¯¥æçåºåæç»ä¿¡æ¯"); |
| | | _logger.LogInformation($"TaskService InPickTaskCompleted: {task.TaskNum} , {ex.Message}"); |
| | | } |
| | | //æ¥è´§ä½ |
| | | Dt_LocationInfo locationInfo = _locationInfoService.Repository.QueryFirst(x => x.LocationCode == task.TargetAddress); |
| | | if (locationInfo == null) |
| | | return await Task.FromResult(WebResponseContent.Instance.OK()); |
| | | } |
| | | |
| | | |
| | | private async Task HandleOutboundOrderToMESCompletion(Dt_OutboundOrder outboundOrder, string orderNo) |
| | | { |
| | | try |
| | | { |
| | | return WebResponseContent.Instance.Error($"æªæ¾å°å¯¹åºçç»ç¹è´§ä½ä¿¡æ¯"); |
| | | var orderDetails = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | .LeftJoin<Dt_OutboundOrder>((o, item) => o.OrderId == item.Id) |
| | | .Where((o, item) => item.OrderNo == orderNo) |
| | | .Select((o, item) => o) |
| | | .ToListAsync(); |
| | | |
| | | bool allCompleted = true; |
| | | foreach (var detail in orderDetails) |
| | | { |
| | | if (detail.OverOutQuantity < detail.NeedOutQuantity) |
| | | { |
| | | allCompleted = false; |
| | | break; |
| | | } |
| | | } |
| | | _logger.LogInformation($"TaskService HandleOutboundOrderToMESCompletion: {outboundOrder.OrderNo} , {allCompleted}"); |
| | | int newStatus = allCompleted ? (int)OutOrderStatusEnum.åºåºå®æ : (int)OutOrderStatusEnum.åºåºä¸; |
| | | |
| | | if (outboundOrder.OrderStatus != newStatus) |
| | | { |
| | | await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>() |
| | | .SetColumns(x => x.OrderStatus == newStatus) |
| | | .Where(x => x.OrderNo == orderNo) |
| | | .ExecuteCommandAsync(); |
| | | |
| | | } |
| | | //åªææ£å¸¸åæ£å®ææ¶æåMESåé¦ |
| | | if (allCompleted && newStatus == (int)OutOrderStatusEnum.åºåºå®æ) |
| | | { |
| | | |
| | | if (outboundOrder.OrderType == OutOrderTypeEnum.Allocate.ObjToInt()) |
| | | { |
| | | var allocate = _allocateService.Repository.QueryData(x => x.UpperOrderNo == outboundOrder.UpperOrderNo).First(); |
| | | var allocatefeedmodel = new AllocateDto |
| | | { |
| | | ReqCode = Guid.NewGuid().ToString(), |
| | | ReqTime = DateTime.Now.ToString(), |
| | | BusinessType = "3", |
| | | FactoryArea = outboundOrder.FactoryArea, |
| | | OperationType = 1, |
| | | Operator = outboundOrder.Operator, |
| | | OrderNo = outboundOrder.UpperOrderNo, |
| | | // documentsNO = outboundOrder.OrderNo, |
| | | // status = outboundOrder.OrderStatus, |
| | | fromWarehouse = allocate?.FromWarehouse ?? "", |
| | | toWarehouse = allocate?.ToWarehouse ?? "", |
| | | Details = new List<AllocateDtoDetail>() |
| | | |
| | | }; |
| | | foreach (var detail in orderDetails) |
| | | { |
| | | // è·å该æç»å¯¹åºçæ¡ç ä¿¡æ¯ï¼ä»éå®è®°å½ï¼ |
| | | var detailLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.OrderNo == orderNo && |
| | | x.OrderDetailId == detail.Id && |
| | | x.Status == (int)OutLockStockStatusEnum.æ£é宿) |
| | | .ToListAsync(); |
| | | |
| | | var detailModel = new AllocateDtoDetail |
| | | { |
| | | MaterialCode = detail.MaterielCode, |
| | | LineNo = detail.lineNo, // 注æï¼è¿éå¯è½éè¦è°æ´å段å |
| | | WarehouseCode = detail.WarehouseCode, |
| | | Qty = detail.OverOutQuantity, // 使ç¨è®¢åæç»çå·²åºåºæ°é |
| | | //currentDeliveryQty = detail.OverOutQuantity, |
| | | Unit = detail.Unit, |
| | | Barcodes = detailLocks.Select(lockInfo => new BarcodeInfo |
| | | { |
| | | Barcode = lockInfo.CurrentBarcode, |
| | | SupplyCode = lockInfo.SupplyCode, |
| | | BatchNo = lockInfo.BatchNo, |
| | | Unit = lockInfo.Unit, |
| | | Qty = lockInfo.PickedQty // æ¡ç 级å«çæ°éä»ç¨éå®è®°å½ |
| | | }).ToList() |
| | | }; |
| | | |
| | | allocatefeedmodel.Details.Add(detailModel); |
| | | } |
| | | |
| | | var result = await _invokeMESService.FeedbackAllocate(allocatefeedmodel); |
| | | 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 => new Dt_OutboundOrder |
| | | { |
| | | ReturnToMESStatus = 1, |
| | | Operator = App.User.UserName, |
| | | }).Where(x => x.OrderNo == orderNo).ExecuteCommandAsync(); |
| | | } |
| | | } |
| | | else if (outboundOrder.OrderType == OutOrderTypeEnum.ReCheck.ObjToInt()) |
| | | { |
| | | |
| | | } |
| | | else |
| | | { |
| | | 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, |
| | | orderNo = outboundOrder.UpperOrderNo, |
| | | documentsNO = outboundOrder.OrderNo, |
| | | status = outboundOrder.OrderStatus, |
| | | details = new List<FeedbackOutboundDetailsModel>() |
| | | }; |
| | | |
| | | |
| | | foreach (var detail in orderDetails) |
| | | { |
| | | // è·å该æç»å¯¹åºçæ¡ç ä¿¡æ¯ï¼ä»éå®è®°å½ï¼ |
| | | var detailLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.OrderNo == orderNo && |
| | | x.OrderDetailId == detail.Id && |
| | | x.Status == (int)OutLockStockStatusEnum.æ£é宿) |
| | | .ToListAsync(); |
| | | |
| | | var detailModel = new FeedbackOutboundDetailsModel |
| | | { |
| | | materialCode = detail.MaterielCode, |
| | | lineNo = detail.lineNo, // 注æï¼è¿éå¯è½éè¦è°æ´å段å |
| | | warehouseCode = detail.WarehouseCode, |
| | | qty = detail.OverOutQuantity, // 使ç¨è®¢åæç»çå·²åºåºæ°é |
| | | currentDeliveryQty = detail.OverOutQuantity, |
| | | unit = detail.Unit, |
| | | barcodes = detailLocks.Select(lockInfo => new WIDESEA_DTO.Outbound.BarcodesModel |
| | | { |
| | | barcode = lockInfo.CurrentBarcode, |
| | | supplyCode = lockInfo.SupplyCode, |
| | | batchNo = lockInfo.BatchNo, |
| | | unit = lockInfo.Unit, |
| | | qty = lockInfo.PickedQty // æ¡ç 级å«çæ°éä»ç¨éå®è®°å½ |
| | | }).ToList() |
| | | }; |
| | | |
| | | feedmodel.details.Add(detailModel); |
| | | } |
| | | |
| | | var result = await _invokeMESService.FeedbackOutbound(feedmodel); |
| | | 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) |
| | | .Where(x => x.OrderNo == orderNo) |
| | | .ExecuteCommandAsync(); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | // è·åææååºä¸çåºåºéå®è®°å½ |
| | | var returnLocks = _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(it => it.OrderNo == task.OrderNo && it.PalletCode == task.PalletCode && it.Status == (int)OutLockStockStatusEnum.ååºä¸) |
| | | .ToList(); |
| | | // æ´æ°åºåºéå®è®°å½ç¶æä¸ºååºå®æ |
| | | foreach (var lockInfo in returnLocks) |
| | | catch (Exception ex) |
| | | { |
| | | lockInfo.Status = (int)OutLockStockStatusEnum.å·²ååº; |
| | | _logger.LogError($"CheckAndUpdateOrderStatus失败 - OrderNo: {orderNo}, Error: {ex.Message}"); |
| | | } |
| | | _outStockLockInfoService.Db.Updateable(returnLocks).ExecuteCommand(); |
| | | |
| | | await DeleteZeroQuantityStockDetails(stockInfo.Id); |
| | | |
| | | stockInfo.LocationCode = task.TargetAddress; |
| | | stockInfo.StockStatus = StockStatusEmun.å
¥åºå®æ.ObjToInt(); |
| | | stockInfo.Details.ForEach(x => |
| | | { |
| | | x.Status = StockStatusEmun.å
¥åºå®æ.ObjToInt(); |
| | | }); |
| | | _stockService.StockInfoService.Repository.UpdateData(stockInfo); |
| | | _stockService.StockInfoDetailService.Repository.UpdateData(stockInfo.Details); |
| | | await ProcessStockDetailsForReturn(task, stockInfo.Id); |
| | | |
| | | |
| | | |
| | | if (stockInfo.PalletType == PalletTypeEnum.Empty.ObjToInt()) |
| | | { |
| | | locationInfo.LocationStatus = LocationStatusEnum.Pallet.ObjToInt(); |
| | | } |
| | | else |
| | | { |
| | | locationInfo.LocationStatus = LocationStatusEnum.InStock.ObjToInt(); |
| | | } |
| | | _locationInfoService.Repository.UpdateData(locationInfo); |
| | | |
| | | task.TaskStatus = TaskStatusEnum.Finish.ObjToInt(); |
| | | |
| | | BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.èªå¨å®æ : OperateTypeEnum.äººå·¥å®æ); |
| | | |
| | | return WebResponseContent.Instance.OK(); |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | var deleteCount = await _stockService.StockInfoDetailService.Db.Deleteable<Dt_StockInfoDetail>() |
| | | .Where(x => x.StockId == stockId && |
| | | x.StockQuantity == 0 && |
| | | (x.Status==StockStatusEmun.åºåºå®æ.ObjToInt()|| x.Status== |
| | | (x.Status == StockStatusEmun.åºåºå®æ.ObjToInt() || x.Status == |
| | | StockStatusEmun.å
¥åºå®æ.ObjToInt())) // åªå é¤å·²å®æç¶æçé¶åºå |
| | | .ExecuteCommandAsync(); |
| | | |
| | |
| | | var stockDetails = await _stockService.StockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .Where(x => x.StockId == stockId && |
| | | x.StockQuantity > 0 && |
| | | ( x.Status == StockStatusEmun.åºåºéå®.ObjToInt()|| x.Status== |
| | | (x.Status == StockStatusEmun.åºåºéå®.ObjToInt() || x.Status == |
| | | StockStatusEmun.å
¥åºç¡®è®¤.ObjToInt())) // å
æ¬åºåºéå®åå
¥åºç¡®è®¤ç |
| | | .ToListAsync(); |
| | | |
| | | foreach (var detail in stockDetails) |
| | | { |
| | | |
| | | detail.Status = StockStatusEmun.å
¥åºå®æ.ObjToInt(); |
| | | |
| | | detail.Status = StockStatusEmun.å
¥åºå®æ.ObjToInt(); |
| | | detail.OutboundQuantity = 0; // æ¸
空åºåºæ°é |
| | | |
| | | _logger.LogInformation($"æ´æ°åºåæç»ç¶æ - æ¡ç : {detail.Barcode}, æ°é: {detail.StockQuantity}"); |
| | |
| | | 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(); |
| | | |
| | | //_stockRepository.Db.Deleteable(stockInfo).ExecuteCommand(); |
| | | _stockService.StockInfoService.DeleteData(stockInfo); |
| | | _locationStatusChangeRecordService.AddLocationStatusChangeRecord(locationInfo, beforeStatus, StockChangeType.Outbound.ObjToInt(), stockInfo.Details.FirstOrDefault()?.OrderNo ?? "", task.TaskNum); |
| | | |
| | | return WebResponseContent.Instance.OK(); |
| | | return await Task.FromResult(WebResponseContent.Instance.OK()); |
| | | |
| | | } |
| | | catch (Exception ex) |
| | |
| | | { |
| | | try |
| | | { |
| | | Dt_Task dbtask = Repository.QueryFirst(x => x.PalletCode == palletCode); |
| | | Dt_Task dbtask = Repository.Db.Queryable<Dt_Task>().Where(x => x.PalletCode == palletCode).OrderByDescending(x=>x.CreateDate).First(); |
| | | if (dbtask != null) |
| | | { |
| | | if (dbtask.TaskType == TaskTypeEnum.Outbound.ObjToInt()) |
| | | if (dbtask.TaskType == TaskTypeEnum.Outbound.ObjToInt() || dbtask.TaskType == TaskTypeEnum.OutAllocate.ObjToInt()) |
| | | { |
| | | return WebResponseContent.Instance.Error($"åºåºå¾
忣任å¡"); |
| | | } |
| | |
| | | { |
| | | return WebResponseContent.Instance.Error($"该æçå·²çæä»»å¡"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | Dt_StockInfo stockInfo = _stockRepository.Db.Queryable<Dt_StockInfo>().Where(x => x.PalletCode == palletCode).Includes(x => x.Details).First(); |
| | | if (stockInfo == null) |
| | |
| | | using System.Linq; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | using WIDESEA_BasicService; |
| | | using WIDESEA_Common.CommonEnum; |
| | | using WIDESEA_Common.LocationEnum; |
| | | using WIDESEA_Common.OrderEnum; |
| | |
| | | using WIDESEA_DTO.Basic; |
| | | using WIDESEA_DTO.Stock; |
| | | using WIDESEA_Model.Models; |
| | | using WIDESEA_Model.Models.Basic; |
| | | using WIDESEA_Model.Models.Outbound; |
| | | |
| | | namespace WIDESEA_TaskInfoService |
| | | { |
| | |
| | | { |
| | | throw new Exception("æªæ¾å°åºåºåæç»ä¿¡æ¯"); |
| | | } |
| | | if (outboundOrderDetails.FirstOrDefault(x => x.OrderDetailStatus > OrderDetailStatusEnum.New.ObjToInt() && x.OrderDetailStatus != OrderDetailStatusEnum.AssignOverPartial.ObjToInt()) != null) |
| | | //if (outboundOrderDetails.FirstOrDefault(x => x.OrderDetailStatus > OrderDetailStatusEnum.New.ObjToInt() && x.OrderDetailStatus != OrderDetailStatusEnum.AssignOverPartial.ObjToInt()) != null) |
| | | //{ |
| | | // throw new Exception("æéåºåºåæç»åå¨åºåºä¸æå·²å®æ"); |
| | | //} |
| | | |
| | | if (outboundOrderDetails.FirstOrDefault(x => x.OrderDetailStatus > OrderDetailStatusEnum.Outbound.ObjToInt() && x.OrderDetailStatus != OrderDetailStatusEnum.AssignOverPartial.ObjToInt()) != null) |
| | | { |
| | | throw new Exception("æéåºåºåæç»åå¨åºåºä¸æå·²å®æ"); |
| | | throw new Exception("æéåºåºåæç»åå¨å·²å®æç¶æï¼æ æ³éæ°åé
"); |
| | | } |
| | | |
| | | List<Dt_StockInfo>? stockInfos = null; |
| | | List<Dt_OutboundOrderDetail>? orderDetails = null; |
| | | List<Dt_OutStockLockInfo>? outStockLockInfos = null; |
| | | 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) |
| | |
| | | else |
| | | { |
| | | throw new Exception("æ åºå"); |
| | | } |
| | | } |
| | | return (tasks, stockInfos, orderDetails, outStockLockInfos, locationInfos); |
| | | } |
| | | /// <summary> |
| | | /// æ¸
çä¹åçæ æéå®è®°å½ |
| | | /// </summary> |
| | | private void CleanupPreviousInvalidLocks(List<Dt_OutboundOrderDetail> orderDetails) |
| | | { |
| | | var orderIds = orderDetails.Select(x => x.OrderId).Distinct().ToList(); |
| | | var orderNos = _outboundOrderService.Db.Queryable<Dt_OutboundOrder>() |
| | | .Where(x => orderIds.Contains(x.Id)) |
| | | .Select(x => x.OrderNo) |
| | | .ToList(); |
| | | |
| | | // æ¸
çç¶æä¸º"已鿾"æ"ååºä¸"çæ§éå®è®°å½ |
| | | foreach (var orderNo in orderNos) |
| | | { |
| | | _outStockLockInfoService.Db.Updateable<Dt_OutStockLockInfo>() |
| | | .SetColumns(x => new Dt_OutStockLockInfo |
| | | { |
| | | Status = (int)OutLockStockStatusEnum.已鿾 |
| | | }) |
| | | .Where(x => x.OrderNo == orderNo && |
| | | (x.Status == (int)OutLockStockStatusEnum.ååºä¸ || |
| | | x.Status == (int)OutLockStockStatusEnum.已鿾)) |
| | | .ExecuteCommand(); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// çæåºåºä»»å¡åæ°æ®æ´æ°å°æ°æ®åº |
| | |
| | | if (stockInfos != null && stockInfos.Count > 0 && outboundOrderDetails != null && outboundOrderDetails.Count > 0 && outStockLockInfos != null && outStockLockInfos.Count > 0 && locationInfos != null && locationInfos.Count > 0) |
| | | { |
| | | stockInfos.ForEach(x => |
| | | { |
| | | { |
| | | x.StockStatus = StockStatusEmun.åºåºéå®.ObjToInt(); |
| | | }); |
| | | outboundOrderDetails.ForEach(x => |
| | |
| | | { |
| | | _outboundOrderService.Repository.UpdateData(outboundOrder); |
| | | } |
| | | outboundOrder.Operator = App.User.UserName; |
| | | else |
| | | { |
| | | outboundOrder.OrderStatus = OutOrderStatusEnum.åºåºä¸.ObjToInt(); |
| | | } |
| | | outboundOrder.Operator = App.User.UserName; |
| | | _outboundOrderService.Repository.UpdateData(outboundOrder); |
| | | WebResponseContent content = _outboundOrderDetailService.LockOutboundStockDataUpdate(stockInfos, outboundOrderDetails, outStockLockInfos, locationInfos, tasks: tasks); |
| | | |
| | |
| | | { |
| | | _outboundOrderService.Repository.UpdateData(outboundOrder); |
| | | } |
| | | else |
| | | { |
| | | outboundOrder.OrderStatus = OutOrderStatusEnum.åºåºä¸.ObjToInt(); |
| | | } |
| | | outboundOrder.Operator = App.User.UserName; |
| | | _outboundOrderService.Repository.UpdateData(outboundOrder); |
| | | _outboundOrderDetailService.Repository.UpdateData(outboundOrderDetails); |
| | | } |
| | | _unitOfWorkManage.CommitTran(); |
| | |
| | | throw new Exception("æªæ¾å°åºåºåæç»ä¿¡æ¯"); |
| | | } |
| | | |
| | | if (stockSelectViews.Sum(x => x.UseableQuantity) > outboundOrderDetail.OrderQuantity - outboundOrderDetail.LockQuantity) |
| | | { |
| | | throw new Exception("éæ©æ°éè¶
åºåæ®æ°é"); |
| | | } |
| | | //if (stockSelectViews.Sum(x => x.UseableQuantity) > outboundOrderDetail.OrderQuantity - outboundOrderDetail.LockQuantity) |
| | | //{ |
| | | // throw new Exception("éæ©æ°éè¶
åºåæ®æ°é"); |
| | | //} |
| | | List<Dt_StockInfo>? stockInfos = null; |
| | | Dt_OutboundOrderDetail? orderDetail = null; |
| | | List<Dt_OutStockLockInfo>? outStockLockInfos = null; |
| | |
| | | (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, |
| | |
| | | |
| | | } |
| | | |
| | | |
| | | #region åæ¹åé
åºå |
| | | |
| | | /// <summary> |
| | | /// åæ¹åé
åºå |
| | | /// </summary> |
| | | public async Task<WebResponseContent> GenerateOutboundBatchTasksAsync(int orderDetailId, decimal batchQuantity, string outStation) |
| | | { |
| | | 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; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _unitOfWorkManage.RollbackTran(); |
| | | _logger.LogError($"åæ¹åé
åºå失败 - OrderDetailId: {orderDetailId}, Quantity: {batchQuantity}, Error: {ex.Message}"); |
| | | return WebResponseContent.Instance.Error($"åæ¹åé
失败ï¼{ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// åæ¹åé
åºåæ°æ®å¤ç |
| | | /// </summary> |
| | | public async Task<(List<Dt_Task>, List<Dt_StockInfo>?, List<Dt_OutboundOrderDetail>?, List<Dt_OutStockLockInfo>?, List<Dt_LocationInfo>?)> |
| | | BatchAllocateStockDataHandle( int orderDetailId, decimal batchQuantity, string outStation) |
| | | { |
| | | List<Dt_Task> tasks = new List<Dt_Task>(); |
| | | |
| | | // è·å订åæç» |
| | | var outboundOrderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | .FirstAsync(x => x.Id == orderDetailId ); |
| | | |
| | | if (outboundOrderDetail == null) |
| | | { |
| | | throw new Exception("æªæ¾å°åºåºåæç»ä¿¡æ¯"); |
| | | } |
| | | var outboundOrder = await _outboundOrderService.Db.Queryable<Dt_OutboundOrder>().FirstAsync(x => x.Id == outboundOrderDetail.OrderId); |
| | | if(outboundOrder == null) |
| | | { |
| | | throw new Exception("æªæ¾å°åºåºåä¿¡æ¯"); |
| | | } |
| | | // éªè¯è®¢åæç»ç¶æ |
| | | if (outboundOrderDetail.OrderDetailStatus > OrderDetailStatusEnum.New.ObjToInt() && |
| | | outboundOrderDetail.OrderDetailStatus != OrderDetailStatusEnum.AssignOverPartial.ObjToInt()) |
| | | { |
| | | throw new Exception("æéåºåºåæç»åå¨åºåºä¸æå·²å®æ"); |
| | | } |
| | | |
| | | // éªè¯åé
æ°é |
| | | decimal allocatedQty = outboundOrderDetail.AllocatedQuantity; |
| | | decimal overOutQty = outboundOrderDetail.OverOutQuantity; |
| | | decimal needOutQty = outboundOrderDetail.NeedOutQuantity; |
| | | decimal availableQty = needOutQty - allocatedQty - overOutQty; |
| | | |
| | | if (availableQty <= 0) |
| | | throw new Exception("æ å¯åé
æ°é"); |
| | | |
| | | if (batchQuantity > availableQty) |
| | | throw new Exception($"åé
æ°éä¸è½è¶
è¿å¯åé
æ°é{availableQty}"); |
| | | |
| | | List<Dt_StockInfo>? stockInfos = null; |
| | | List<Dt_OutboundOrderDetail>? orderDetails = null; |
| | | List<Dt_OutStockLockInfo>? outStockLockInfos = null; |
| | | List<Dt_LocationInfo>? locationInfos = null; |
| | | |
| | | // çææ¹æ¬¡å· |
| | | string batchNo = await GenerateBatchNo(); |
| | | |
| | | // åé
åºå |
| | | (List<Dt_StockInfo>, List<Dt_OutboundOrderDetail>, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>) allocateResult = |
| | | await _outboundOrderDetailService.AssignStockForBatch(outboundOrderDetail, batchQuantity, batchNo); |
| | | |
| | | if (allocateResult.Item1 != null && allocateResult.Item1.Count > 0) |
| | | { |
| | | // åå»ºåæ¹è®°å½ |
| | | await CreateBatchRecord(outboundOrder.OrderNo, orderDetailId, batchQuantity, batchNo); |
| | | |
| | | TaskTypeEnum typeEnum = outboundOrder.OrderType switch |
| | | { |
| | | (int)OutOrderTypeEnum.Issue => TaskTypeEnum.Outbound, |
| | | (int)OutOrderTypeEnum.Allocate => TaskTypeEnum.OutAllocate, |
| | | (int)OutOrderTypeEnum.Quality => TaskTypeEnum.OutQuality, |
| | | _ => TaskTypeEnum.Outbound |
| | | }; |
| | | |
| | | tasks = GetTasks(allocateResult.Item1, typeEnum, outStation); |
| | | tasks.ForEach(x => |
| | | { |
| | | x.OrderNo = outboundOrder.OrderNo; |
| | | }); |
| | | |
| | | allocateResult.Item2.ForEach(x => |
| | | { |
| | | x.OrderDetailStatus = OrderDetailStatusEnum.Outbound.ObjToInt(); |
| | | }); |
| | | |
| | | allocateResult.Item3.ForEach(x => |
| | | { |
| | | x.Status = OutLockStockStatusEnum.åºåºä¸.ObjToInt(); |
| | | }); |
| | | |
| | | stockInfos = allocateResult.Item1; |
| | | orderDetails = allocateResult.Item2; |
| | | outStockLockInfos = allocateResult.Item3; |
| | | locationInfos = allocateResult.Item4; |
| | | } |
| | | else |
| | | { |
| | | throw new Exception("æ åºå"); |
| | | } |
| | | |
| | | return (tasks, stockInfos, orderDetails, outStockLockInfos, locationInfos); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | /// <summary> |
| | | /// æ´æ°è®¢åæç»ç¶æ |
| | | /// </summary> |
| | | private void UpdateOrderDetailStatus(List<Dt_OutboundOrderDetail> details, decimal allocatedQuantity, decimal needQuantity) |
| | | { |
| | | foreach (var detail in details) |
| | | { |
| | | // æ ¹æ®åé
æ
嵿´æ°ç¶æ |
| | | if (allocatedQuantity >= needQuantity) |
| | | { |
| | | detail.OrderDetailStatus = OrderDetailStatusEnum.Outbound.ObjToInt(); |
| | | } |
| | | else |
| | | { |
| | | detail.OrderDetailStatus = OrderDetailStatusEnum.AssignOverPartial.ObjToInt(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | private async Task<string> GenerateBatchNo() |
| | | { |
| | | var batchNo = UniqueValueGenerator.Generate(); |
| | | |
| | | return $"Out{batchNo} "; |
| | | } |
| | | |
| | | private async Task<Dt_OutboundBatch> CreateBatchRecord(string orderNo, int orderDetailId, decimal batchQuantity, string batchNo) |
| | | { |
| | | var batchRecord = new Dt_OutboundBatch |
| | | { |
| | | BatchNo = batchNo, |
| | | OrderNo = orderNo, |
| | | OrderDetailId = orderDetailId, |
| | | BatchQuantity = batchQuantity, |
| | | BatchStatus = (int)BatchStatusEnum.åé
ä¸, |
| | | Operator = App.User.UserName |
| | | }; |
| | | |
| | | await _OutboundBatchRepository.Db.Insertable(batchRecord).ExecuteCommandAsync(); |
| | | return batchRecord; |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | |
| | | } |
| | | } |
| | |
| | | </PropertyGroup> |
| | | |
| | | <ItemGroup> |
| | | <ProjectReference Include="..\WIDESEA_BasicService\WIDESEA_BasicService.csproj" /> |
| | | <ProjectReference Include="..\WIDESEA_IAllocateService\WIDESEA_IAllocateService.csproj" /> |
| | | <ProjectReference Include="..\WIDESEA_IBasicService\WIDESEA_IBasicService.csproj" /> |
| | | <ProjectReference Include="..\WIDESEA_IInboundService\WIDESEA_IInboundService.csproj" /> |
| | |
| | | using Microsoft.AspNetCore.Authorization; |
| | | using Microsoft.AspNetCore.Mvc; |
| | | using Newtonsoft.Json; |
| | | using System.Data.Common; |
| | | using System.Diagnostics.Eventing.Reader; |
| | | using System.Threading.Tasks; |
| | |
| | | [HttpPost, Route("ReceiveAllocateOrder"), MethodParamsValidate, AllowAnonymous] |
| | | public async Task<WebResponseContent> ReceiveAllocateOrder([FromBody] AllocateDto model) |
| | | { |
| | | _logger.LogInformation("AllocateOrderController ReceiveAllocateOrder: " + JsonConvert.SerializeObject(model)); |
| | | Dt_AllocateOrder allocateOrder = new Dt_AllocateOrder |
| | | { |
| | | OrderNo = model.OrderNo, |
| | |
| | | FactoryArea = model.FactoryArea, |
| | | IsBatch = model.IsBatch, |
| | | CreateType = model.OperationType, |
| | | FromWarehouse=model.fromWarehouse, |
| | | ToWarehouse=model.toWarehouse, |
| | | FromWarehouse = model.fromWarehouse, |
| | | ToWarehouse = model.toWarehouse, |
| | | Details = new List<Dt_AllocateOrderDetail>() |
| | | }; |
| | | Enum.TryParse<BusinessTypeEnum>(allocateOrder.BusinessType, out var businessType); |
| | | |
| | | //allocateOrder.OrderType = businessType == BusinessTypeEnum.æºä»è°å¤é¨ä»åº ? 215 : 115; |
| | | if (businessType == BusinessTypeEnum.æºä»è°å¤é¨ä»åº) |
| | | { |
| | | allocateOrder.OrderType = 215; |
| | | } |
| | | else if (businessType == BusinessTypeEnum.å¤é¨ä»åºè°æºä») |
| | | { |
| | | allocateOrder.OrderType = 115; |
| | | } |
| | | |
| | | foreach (var detailDto in model.Details) |
| | | { |
| | |
| | | Barcode = barcodeDto.Barcode, |
| | | BatchNo = barcodeDto.BatchNo, |
| | | BarcodeQty = barcodeDto.Qty, |
| | | BarcodeUnit = barcodeDto.Unit |
| | | BarcodeUnit = barcodeDto.Unit, |
| | | ValidDate = barcodeDto.validDate, |
| | | |
| | | }; |
| | | allocateOrder.Details.Add(orderDetail); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using Microsoft.AspNetCore.Mvc; |
| | | using WIDESEA_Core.BaseController; |
| | | using WIDESEA_ICheckService; |
| | | using WIDESEA_Model.Models.Check; |
| | | |
| | | namespace WIDESEA_WMSServer.Controllers.Check |
| | | { |
| | | /// <summary> |
| | | /// 鿣å |
| | | /// </summary> |
| | | [Route("api/ReCheckOrder")] |
| | | [ApiController] |
| | | public class ReCheckOrderController : ApiBaseController<IReCheckOrderService, Dt_ReCheckOrder> |
| | | { |
| | | public ReCheckOrderController(IReCheckOrderService service) : base(service) |
| | | { |
| | | } |
| | | } |
| | | } |
| | |
| | | _logger.LogInformation(" ESSController ContainerArrivalReport : CallId={CallId},ContainerCode={ContainerCode},SlotCode={SlotCode}", request.CallId, request.ContainerCode, request.SlotCode); |
| | | var response = new ApiResponse<ContainerArrivalResponseData> |
| | | { |
| | | Code = 1 |
| | | |
| | | Code = 1, |
| | | Data = null, |
| | | |
| | | }; |
| | | |
| | | // çæè¯·æ±çå¯ä¸æ è¯ï¼åºäºcallId + æ¶é´æ³ï¼ |
| | |
| | | } |
| | | |
| | | WebResponseContent result = await _taskService.RequestInboundTask(request.ContainerCode, request.SlotCode); |
| | | if (result != null && !string.IsNullOrEmpty(result.Message)) |
| | | { |
| | | _logger.LogError(" ESSController ContainerArrivalReport RequestInboundTask: Message={Message}", result?.Message); |
| | | } |
| | | |
| | | |
| | | var cacheOptions = new MemoryCacheEntryOptions |
| | | { |
| | |
| | | { |
| | | Code = 0, |
| | | Msg = "", |
| | | Data = new ContainerArrivalResponseData |
| | | { |
| | | direction = "100" |
| | | } |
| | | Data = null, |
| | | }; |
| | | if (result != null && !string.IsNullOrEmpty( result.Message ) && result.Message.Contains("该æçå·²çæä»»å¡")) |
| | | { |
| | | |
| | | response.Data = new ContainerArrivalResponseData |
| | | { |
| | | direction = "100" |
| | | }; |
| | | return Ok(response); |
| | | } |
| | | if (result != null && result.Status) |
| | | { |
| | | { |
| | | response.Data = new ContainerArrivalResponseData |
| | | { |
| | | direction = "100" |
| | | }; |
| | | return Ok(response); |
| | | } |
| | | else |
| | |
| | | _logger.LogInformation("ä»»å¡å®æ: TaskCode={TaskCode}, Container={Container}, Robot={Robot}", |
| | | request.TaskCode, request.ContainerCode, request.RobotCode); |
| | | |
| | | _taskService.TaskCompleted(request.TaskCode); |
| | | await _taskService.TaskCompleted(request.TaskCode); |
| | | // æ ¹æ®ä¸åçä»»å¡ç±»åè¿è¡ç¹æ®å¤ç |
| | | if (request.Weight.HasValue) |
| | | { |
| | |
| | | private readonly WIDESEA_IBasicService.IErpApiService erpApiService; |
| | | |
| | | private readonly WIDESEA_IBasicService.IInvokeMESService _invokeMESService; |
| | | |
| | | public readonly IInboundService _inboundService; |
| | | private readonly IESSApiService _eSSApiService; |
| | | private readonly ILocationInfoService _locationInfoService; |
| | | private readonly IDailySequenceService _dailySequenceService; |
| | | private readonly IMaterialUnitService _materialUnitService; |
| | | 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) : 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) : base(service) |
| | | { |
| | | this.erpApiService = erpApiService; |
| | | _invokeMESService = invokeMESService; |
| | |
| | | _locationInfoService = locationInfoService; |
| | | _logger = logger; |
| | | _materialUnitService = materialUnitService; |
| | | _inboundService = inboundService; |
| | | } |
| | | |
| | | [HttpPost, Route("Test"), AllowAnonymous, MethodParamsValidate] |
| | | public async Task<WebResponseContent> Test() |
| | | { |
| | | // var purchaseToStockResult = await _materialUnitService.ConvertPurchaseToStockAsync("101001-00002", 10); |
| | | |
| | | // var pdddurchaseToStockResult = await _materialUnitService.ConvertPurchaseToStockAsync("100513-00210", 10); |
| | | // 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 sddd = _locationInfoService.AssignLocation(); |
| | | var code = sddd.LocationCode; |
| | | var purchaseToStockResult = await _materialUnitService.ConvertPurchaseToStockAsync("100513-00303", 1); |
| | | |
| | | var pdddurchaseToStockResult = await _materialUnitService.ConvertFromToStockAsync("100513-00303", "W013", 1); |
| | | |
| | | //var sddd = _locationInfoService.AssignLocation(); |
| | | //var code = sddd.LocationCode; |
| | | //var ssss=await _dailySequenceService.GetNextSequenceAsync(); |
| | | //var ddddssss = "WSLOT" + DateTime.Now.ToString("yyyyMMddHHmmss") + ssss.ToString().PadLeft(5, '0'); |
| | | //erpApiService.GetSuppliersAsync(); |
| | |
| | | //await erpApiService.GetMaterialInfoAsync(new WIDESEA_DTO.Basic.MaterialRequest()); |
| | | |
| | | |
| | | return WebResponseContent.Instance.OK(code); |
| | | return WebResponseContent.Instance.OK(); |
| | | } |
| | | |
| | | /// <summary> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using Microsoft.AspNetCore.Mvc; |
| | | using WIDESEA_Core; |
| | | using WIDESEA_Core.BaseController; |
| | | using WIDESEA_DTO.Outbound; |
| | | using WIDESEA_IOutboundService; |
| | | using WIDESEA_Model.Models; |
| | | using static WIDESEA_OutboundService.OutboundBatchPickingService; |
| | | |
| | | namespace WIDESEA_WMSServer.Controllers.Outbound |
| | | { |
| | | |
| | | [Route("api/OutboundBatchPicking")] |
| | | [ApiController] |
| | | public class OutboundBatchPickingController : ApiBaseController<IOutboundBatchPickingService, Dt_PickingRecord> |
| | | { |
| | | private readonly ISplitPackageService _splitPackageService; |
| | | private readonly IOutStockLockInfoService _outStockLockInfoService; |
| | | private readonly IOutboundBatchPickingService _outboundBatchPickingService; |
| | | |
| | | private readonly ILogger<OutboundBatchPickingController> _logger; |
| | | public OutboundBatchPickingController(IOutboundBatchPickingService service, ISplitPackageService splitPackageService, IOutStockLockInfoService outStockLockInfoService, IOutboundBatchPickingService outboundBatchPickingService, ILogger<OutboundBatchPickingController> logger) : base(service) |
| | | { |
| | | _splitPackageService = splitPackageService; |
| | | _outStockLockInfoService = outStockLockInfoService; |
| | | _outboundBatchPickingService = outboundBatchPickingService; |
| | | _logger = logger; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// åæ£ç¡®è®¤ |
| | | /// </summary> |
| | | [HttpPost("confirm-picking")] |
| | | public async Task<WebResponseContent> ConfirmPicking([FromBody] ConfirmPickingDto dto) |
| | | { |
| | | return await _outboundBatchPickingService.ConfirmBatchPicking(dto.OrderNo, dto.PalletCode, dto.Barcode); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 忶忣 |
| | | /// </summary> |
| | | [HttpPost("cancel-picking")] |
| | | public async Task<WebResponseContent> CancelPicking([FromBody] CancelPickingDto dto) |
| | | { |
| | | return await _outboundBatchPickingService.CancelPicking(dto.OrderNo, dto.PalletCode, dto.Barcode); |
| | | } |
| | | /// <summary> |
| | | /// åæ¶æå
é¾ |
| | | /// </summary> |
| | | [HttpPost("cancel-split-chain")] |
| | | public async Task<WebResponseContent> CancelSplitChain([FromBody] CancelSplitChainDto dto) |
| | | { |
| | | return await _outboundBatchPickingService.CancelSplitPackageChain(dto.OrderNo, dto.PalletCode, dto.StartBarcode); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è·åæå
é¾ä¿¡æ¯ |
| | | /// </summary> |
| | | [HttpPost("split-package-chain-info")] |
| | | public async Task<WebResponseContent> GetSplitPackageChainInfo([FromBody] SplitPackageChainInfoRequestDto dto) |
| | | { |
| | | return await _outboundBatchPickingService.GetSplitPackageChainInfo(dto.OrderNo, dto.Barcode); |
| | | } |
| | | /// <summary> |
| | | /// æ¥æ¾å®æ´æå
é¾ï¼ä»æ ¹æ¡ç å¼å§ï¼ |
| | | /// </summary> |
| | | [HttpPost("find-root-split-chain")] |
| | | public async Task<WebResponseContent> FindRootSplitChain([FromBody] SplitPackageChainInfoRequestDto dto) |
| | | { |
| | | try |
| | | { |
| | | // æ¥æ¾æ ¹æ¡ç |
| | | var rootBarcode = await _outboundBatchPickingService. FindRootBarcode(dto.OrderNo, dto.Barcode); |
| | | |
| | | // è·å宿´æå
é¾ |
| | | var splitChain = await _outboundBatchPickingService.GetSplitPackageChain(dto.OrderNo, rootBarcode); |
| | | |
| | | var chainInfo = new SplitPackageChainInfoDto |
| | | { |
| | | OriginalBarcode = rootBarcode, |
| | | RootBarcode = rootBarcode, |
| | | TotalSplitTimes = splitChain.Count, |
| | | ChainType = "root", |
| | | SplitChain = splitChain.Select(x => new SplitChainItemDto |
| | | { |
| | | SplitTime = x.SplitTime, |
| | | OriginalBarcode = x.OriginalBarcode, |
| | | NewBarcode = x.NewBarcode, |
| | | SplitQuantity = x.SplitQty, |
| | | Operator = x.Operator, |
| | | IsReverted = x.IsReverted |
| | | }).ToList() |
| | | }; |
| | | |
| | | return WebResponseContent.Instance.OK("è·åæå", chainInfo); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _logger.LogError($"æ¥æ¾å®æ´æå
é¾å¤±è´¥ - OrderNo: {dto.OrderNo}, Barcode: {dto.Barcode}, Error: {ex.Message}"); |
| | | return WebResponseContent.Instance.Error("æ¥æ¾å®æ´æå
é¾å¤±è´¥"); |
| | | } |
| | | } |
| | | /// <summary> |
| | | /// æå¨æå
|
| | | /// </summary> |
| | | [HttpPost("split-package")] |
| | | public async Task<WebResponseContent> SplitPackage([FromBody] SplitPackageDto dto) |
| | | { |
| | | return await _outboundBatchPickingService.ManualSplitPackage(dto.OrderNo, dto.PalletCode, dto.OriginalBarcode, dto.SplitQuantity); |
| | | } |
| | | /// <summary> |
| | | /// åæ¶æå
|
| | | /// </summary> |
| | | [HttpPost("cancel-split")] |
| | | public async Task<WebResponseContent> CancelSplit([FromBody] CancelSplitDto dto) |
| | | { |
| | | return await _outboundBatchPickingService.CancelSplitPackage(dto.OrderNo, dto.PalletCode, dto.NewBarcode); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// åæ¹ååº |
| | | /// </summary> |
| | | [HttpPost("return-stock")] |
| | | public async Task<WebResponseContent> ReturnStock([FromBody] ReturnStockDto dto) |
| | | { |
| | | return await _outboundBatchPickingService.BatchReturnStock(dto.OrderNo, dto.PalletCode); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è·åæççéå®ä¿¡æ¯ |
| | | /// </summary> |
| | | [HttpPost("pallet-locks")] |
| | | public async Task<WebResponseContent> GetPalletLocks([FromBody] PalletLocksDto dto) |
| | | { |
| | | try |
| | | { |
| | | var locks = await _outboundBatchPickingService.GetPalletLockInfos(dto.OrderNo, dto.PalletCode); |
| | | return WebResponseContent.Instance.OK("è·åæå", locks); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _logger.LogError(ex, $"è·åæçéå®ä¿¡æ¯å¼å¸¸ - OrderNo: {dto.OrderNo}, PalletCode: {dto.PalletCode}"); |
| | | return WebResponseContent.Instance.Error("ç³»ç»å¼å¸¸ï¼è¯·ç¨åéè¯" + ex.Message); |
| | | } |
| | | } |
| | | /// <summary> |
| | | /// è·åå·²æ£éå表 |
| | | /// </summary> |
| | | [HttpPost("pallet-picked-list")] |
| | | public async Task<WebResponseContent> GetPalletPickedList([FromBody] PalletLocksDto dto) |
| | | { |
| | | try |
| | | { |
| | | var pickedList = await _outboundBatchPickingService.GetPalletPickedList(dto.OrderNo, dto.PalletCode); |
| | | return WebResponseContent.Instance.OK("è·åæå", pickedList); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _logger.LogError(ex, $"è·åå·²æ£éå表å¼å¸¸ - OrderNo: {dto.OrderNo}, PalletCode: {dto.PalletCode}"); |
| | | return WebResponseContent.Instance.Error("ç³»ç»å¼å¸¸ï¼è¯·ç¨åéè¯" + ex.Message); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è·åæçç¶æ |
| | | /// </summary> |
| | | [HttpPost("pallet-status")] |
| | | public async Task<WebResponseContent> GetPalletStatus([FromBody] PalletLocksDto dto) |
| | | { |
| | | try |
| | | { |
| | | var status = await _outboundBatchPickingService.GetPalletStatus(dto.OrderNo, dto.PalletCode); |
| | | return WebResponseContent.Instance.OK("è·åæå", status); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _logger.LogError(ex, $"è·åæçç¶æå¼å¸¸ - OrderNo: {dto.OrderNo}, PalletCode: {dto.PalletCode}"); |
| | | return WebResponseContent.Instance.Error("ç³»ç»å¼å¸¸ï¼è¯·ç¨åéè¯" + ex.Message); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è·åæå
ä¿¡æ¯ |
| | | /// </summary> |
| | | [HttpPost("split-package-info")] |
| | | public async Task<WebResponseContent> GetSplitPackageInfo([FromBody] SplitPackageInfoDto dto) |
| | | { |
| | | try |
| | | { |
| | | var info = await _outboundBatchPickingService.GetSplitPackageInfo(dto.OrderNo, dto.PalletCode, dto.Barcode); |
| | | return WebResponseContent.Instance.OK("è·åæå", info); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _logger.LogError(ex, $"è·åæå
ä¿¡æ¯å¼å¸¸ - OrderNo: {dto.OrderNo}, PalletCode: {dto.PalletCode}, Barcode: {dto.Barcode}"); |
| | | return WebResponseContent.Instance.Error("ç³»ç»å¼å¸¸ï¼è¯·ç¨åéè¯" +ex.Message); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// å走空箱 |
| | | /// </summary> |
| | | [HttpPost("remove-empty-pallet")] |
| | | public async Task<WebResponseContent> RemoveEmptyPallet([FromBody] RemoveEmptyPalletDto dto) |
| | | { |
| | | try |
| | | { |
| | | var result = await _outboundBatchPickingService.RemoveEmptyPallet(dto.OrderNo, dto.PalletCode); |
| | | return result; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _logger.LogError(ex, $"å走空箱å¼å¸¸ - OrderNo: {dto.OrderNo}, PalletCode: {dto.PalletCode}"); |
| | | return WebResponseContent.Instance.Error("ç³»ç»å¼å¸¸ï¼è¯·ç¨åéè¯" +ex.Message); |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | } |
| | |
| | | return await Service.ReturnRemaining(dto.OrderNo, dto.PalletCode, ""); |
| | | } |
| | | |
| | | [HttpPost("remove-empty-pallet")] |
| | | public async Task<WebResponseContent> RemoveEmptyPallet ([FromBody] ConfirmPickingDto dto) |
| | | { |
| | | return await Service.RemoveEmptyPallet(dto.OrderNo, dto.PalletCode); |
| | | } |
| | | |
| | | |
| | | //[HttpPost("direct-outbound")] |
| | | //public async Task<WebResponseContent> DirectOutbound([FromBody] DirectOutboundRequest dto) |
| | | //{ |
| | | // return await Service.DirectOutbound(dto); |
| | | |
| | | |
| | | //} |
| | | |
| | | |
| | | /// <summary> |
| | | /// æ¤éæ£é |
| | | /// </summary> |
| | |
| | | /// <param name="orderId"></param> |
| | | /// <param name="materielCode"></param> |
| | | /// <returns></returns> |
| | | [HttpPost, HttpGet, Route("GetStockSelectViews")] |
| | | [HttpPost, HttpGet, Route("GetStockSelectViews"),AllowAnonymous] |
| | | public List<StockSelectViewDTO> GetStockSelectViews(int orderId, string materielCode) |
| | | { |
| | | return Service.GetStockSelectViews(orderId, materielCode); |
| | |
| | | using Microsoft.AspNetCore.Authorization; |
| | | using MailKit.Search; |
| | | using Microsoft.AspNetCore.Authorization; |
| | | using Microsoft.AspNetCore.Http; |
| | | using Microsoft.AspNetCore.Mvc; |
| | | using System.Diagnostics; |
| | | using System.Threading.Tasks; |
| | | using WIDESEA_Common.CommonEnum; |
| | | using WIDESEA_Common.TaskEnum; |
| | | using WIDESEA_Core; |
| | | using WIDESEA_Core.Attributes; |
| | | using WIDESEA_Core.BaseController; |
| | |
| | | { |
| | | } |
| | | |
| | | |
| | | [HttpPost, Route("AddTestTask"), AllowAnonymous, MethodParamsValidate] |
| | | public WebResponseContent AddTest(WMSTaskDTO wMSTaskDTO) |
| | | { |
| | | Dt_Task task = new Dt_Task |
| | | { |
| | | PalletCode = wMSTaskDTO.PalletCode, |
| | | PalletType = wMSTaskDTO.PalletType, |
| | | Roadway = "t", |
| | | TaskType = wMSTaskDTO.TaskType, |
| | | TaskStatus = wMSTaskDTO.TaskStatus, |
| | | SourceAddress = wMSTaskDTO.SourceAddress, |
| | | TargetAddress = wMSTaskDTO.TargetAddress, |
| | | CurrentAddress = "t", |
| | | NextAddress = "t", |
| | | WarehouseId = wMSTaskDTO.WarehouseId, |
| | | OrderNo = "testt", |
| | | Grade = wMSTaskDTO.Grade, |
| | | Dispatchertime = DateTime.Now, |
| | | |
| | | [HttpPost, Route("PalletOutboundTask"), AllowAnonymous, MethodParamsValidate] |
| | | }; |
| | | |
| | | Service.AddData(task); |
| | | |
| | | |
| | | |
| | | return WebResponseContent.Instance.OK(); |
| | | } |
| | | |
| | | [HttpPost, Route("PalletOutboundTask"), AllowAnonymous, MethodParamsValidate] |
| | | public async Task<WebResponseContent> PalletOutboundTask(string endStation, string palletCode = "") |
| | | { |
| | | |
| | | |
| | | var result = await Service.PalletOutboundTask(endStation, palletCode); |
| | | |
| | | return result; |
| | |
| | | [HttpPost, HttpGet, Route("GenerateOutboundTasks"), AllowAnonymous] |
| | | public async Task<WebResponseContent> GenerateOutboundTasks([FromBody] GenerateOutboundTasksDto data) |
| | | { |
| | | return await Service.GenerateOutboundTasksAsync(data.taskIds,data.outboundPlatform); |
| | | return await Service.GenerateOutboundTasksAsync(data.taskIds, data.outboundPlatform); |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | return Service.GenerateOutboundTask(orderDetailId, stockSelectViews); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// åæ¹çæåºåºä»»å¡ |
| | | /// </summary> |
| | | /// <param name="data"></param> |
| | | /// <returns></returns> |
| | | [HttpPost, HttpGet, Route("GenerateOutboundBatchTasks"), AllowAnonymous] |
| | | public async Task<WebResponseContent> GenerateOutboundBatchTasks([FromBody] GenerateOutboundBatchTasksDto data) |
| | | { |
| | | return await Service.GenerateOutboundBatchTasksAsync(data.orderDetailId,data.batchQuantity, data.outboundPlatform); |
| | | } |
| | | |
| | | |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using Quartz; |
| | | using SqlSugar; |
| | | |
| | | namespace WIDESEA_WMSServer.Jobs |
| | | { |
| | | [DisallowConcurrentExecution] |
| | | public class InventoryLockJob : IJob |
| | | { |
| | | private readonly ILogger<ErpJob> _logger; |
| | | private readonly ISqlSugarClient _db; |
| | | public InventoryLockJob(ILogger<ErpJob> logger, ISqlSugarClient db ) |
| | | { |
| | | _logger = logger; |
| | | _db = db; |
| | | |
| | | } |
| | | public Task Execute(IJobExecutionContext context) |
| | | { |
| | | return Task.CompletedTask; |
| | | } |
| | | } |
| | | } |
| | |
| | | .ForJob(jobKey) |
| | | .WithIdentity("ErpJob-trigger") |
| | | .WithCronSchedule("0 0 10,14,20 * * ?")); |
| | | |
| | | var inventoryLockJobKey = new JobKey("InventoryLockJob"); |
| | | q.AddJob<InventoryLockJob>(opts => opts.WithIdentity(inventoryLockJobKey)); |
| | | |
| | | q.AddTrigger(opts => opts |
| | | .ForJob(inventoryLockJobKey) |
| | | .WithIdentity("InventoryLockJob-trigger") |
| | | .WithCronSchedule("0 0/10 * * * ?")); // æ¯10åéæ§è¡ä¸æ¬¡ |
| | | |
| | | }); |
| | | |
| | | |