Commit c910edb458573fcd337fb3e8537f1c202f2a1114

Authored by 肖超群
2 parents e9673555 55cf91cf

Merge branch 'develop' of http://www.huahengrobot.com:90/wms/wms4 into develop

Showing 26 changed files with 350 additions and 84 deletions
ant-design-vue-jeecg/src/api/api.js
@@ -195,6 +195,8 @@ export const combination = (params) => postAction('/shipment/shipmentCombination @@ -195,6 +195,8 @@ export const combination = (params) => postAction('/shipment/shipmentCombination
195 export const backErpReceipt = (params) => postAction('/receipt/receiptHeader/backErpReceipt', params); 195 export const backErpReceipt = (params) => postAction('/receipt/receiptHeader/backErpReceipt', params);
196 //回传出库单 196 //回传出库单
197 export const backErpShipment = (params) => postAction('/shipment/shipmentHeader/backErpShipment', params); 197 export const backErpShipment = (params) => postAction('/shipment/shipmentHeader/backErpShipment', params);
  198 +//合并出库单
  199 +export const mergeShipment = (params) => postAction('/shipment/shipmentHeader/mergeShipment', params);
198 //首页取值 200 //首页取值
199 export const deliveringAmount = (params) => postAction("/sys/home/deliveringAmount", params); 201 export const deliveringAmount = (params) => postAction("/sys/home/deliveringAmount", params);
200 export const inventoryUtilization = (params) => postAction("/sys/home/inventoryUtilization", params); 202 export const inventoryUtilization = (params) => postAction("/sys/home/inventoryUtilization", params);
ant-design-vue-jeecg/src/views/system/config/BomHeaderList.vue
@@ -107,7 +107,7 @@ @@ -107,7 +107,7 @@
107 </div> 107 </div>
108 108
109 <a-tabs defaultActiveKey="1"> 109 <a-tabs defaultActiveKey="1">
110 - <a-tab-pane tab="bom子表" key="1"> 110 + <a-tab-pane tab="BOM详情" key="1">
111 <BomDetailList :mainId="selectedMainId"/> 111 <BomDetailList :mainId="selectedMainId"/>
112 </a-tab-pane> 112 </a-tab-pane>
113 </a-tabs> 113 </a-tabs>
@@ -136,7 +136,7 @@ export default { @@ -136,7 +136,7 @@ export default {
136 data() { 136 data() {
137 return { 137 return {
138 companyList: [], 138 companyList: [],
139 - description: 'bom主表管理页面', 139 + description: 'BOM主表管理页面',
140 // 表头 140 // 表头
141 columns: [ 141 columns: [
142 { 142 {
ant-design-vue-jeecg/src/views/system/inventory/InventoryDetailList.vue
@@ -286,6 +286,7 @@ export default { @@ -286,6 +286,7 @@ export default {
286 '报废品': 'purple', 286 '报废品': 'purple',
287 '待确认 ': 'grey', 287 '待确认 ': 'grey',
288 '次品': 'red', 288 '次品': 'red',
  289 + '锁定': 'red',
289 default: 'blue' 290 default: 'blue'
290 }; 291 };
291 return colors[status] || colors.default; 292 return colors[status] || colors.default;
ant-design-vue-jeecg/src/views/system/inventory/SimpleInventoryDetailList.vue
@@ -175,6 +175,12 @@ @@ -175,6 +175,12 @@
175 class="j-table-force-nowrap" 175 class="j-table-force-nowrap"
176 @change="handleTableChange" 176 @change="handleTableChange"
177 > 177 >
  178 + <span slot="containerStatus_dictText" slot-scope="containerStatus_dictText">
  179 + <a-tag :key="containerStatus_dictText" :color="getStatusColor(containerStatus_dictText)">
  180 + {{ containerStatus_dictText }}
  181 + </a-tag>
  182 + </span>
  183 +
178 <span slot="enable_dictText" slot-scope="enable_dictText"> 184 <span slot="enable_dictText" slot-scope="enable_dictText">
179 <a-tag :key="enable_dictText" :color="getStatusColor(enable_dictText)"> 185 <a-tag :key="enable_dictText" :color="getStatusColor(enable_dictText)">
180 {{ enable_dictText }} 186 {{ enable_dictText }}
@@ -282,6 +288,12 @@ export default { @@ -282,6 +288,12 @@ export default {
282 dataIndex: 'containerCode' 288 dataIndex: 'containerCode'
283 }, 289 },
284 { 290 {
  291 + title: '容器状态',
  292 + align: "center",
  293 + dataIndex: 'containerStatus_dictText',
  294 + scopedSlots: {customRender: 'containerStatus_dictText'}
  295 + },
  296 + {
285 title: '库位编码', 297 title: '库位编码',
286 align: 'center', 298 align: 'center',
287 dataIndex: 'locationCode' 299 dataIndex: 'locationCode'
@@ -416,6 +428,7 @@ export default { @@ -416,6 +428,7 @@ export default {
416 '报废品': 'purple', 428 '报废品': 'purple',
417 '待确认 ': 'grey', 429 '待确认 ': 'grey',
418 '次品': 'red', 430 '次品': 'red',
  431 + '锁定': 'red',
419 default: 'blue' 432 default: 'blue'
420 }; 433 };
421 return colors[status] || colors.default; 434 return colors[status] || colors.default;
ant-design-vue-jeecg/src/views/system/receipt/ReceiptContainerHeaderList.vue
@@ -346,40 +346,39 @@ export default { @@ -346,40 +346,39 @@ export default {
346 this.$refs.modalForm4.title = "选择容器状态"; 346 this.$refs.modalForm4.title = "选择容器状态";
347 }, 347 },
348 createBatchTask() { 348 createBatchTask() {
349 - if (this.selectedRowKeys.length <= 1) {  
350 - this.$message.warning('至少选择两条记录!') 349 + if (this.selectedRowKeys.length <= 0) {
  350 + this.$message.warning('至少选择一条记录!')
351 return 351 return
352 - } else {  
353 - var receiptContainerHeaderList = []  
354 - var receiptContainerHeader = null  
355 - for (var a = 0; a < this.selectedRowKeys.length; a++) {  
356 - if (this.selectionRows[a] != null && this.selectionRows[a].status == 0) {  
357 - if (receiptContainerHeader == null) {  
358 - receiptContainerHeader = this.selectionRows[a]  
359 - }  
360 - if (receiptContainerHeader.taskType == this.selectionRows[a].taskType) {  
361 - receiptContainerHeaderList.push(this.selectionRows[a])  
362 - } 352 + }
  353 + var receiptContainerHeaderList = []
  354 + var receiptContainerHeader = null
  355 + for (var a = 0; a < this.selectedRowKeys.length; a++) {
  356 + if (this.selectionRows[a] != null && this.selectionRows[a].status == 0) {
  357 + if (receiptContainerHeader == null) {
  358 + receiptContainerHeader = this.selectionRows[a]
363 } 359 }
364 - }  
365 - if (receiptContainerHeaderList.length > 1) {  
366 - if (receiptContainerHeader.taskType == 100) {  
367 - createReceiptBatchTask(receiptContainerHeaderList).then(res => {  
368 - this.loading = false  
369 - if (res.success) {  
370 - this.$message.success(res.message)  
371 - } else {  
372 - this.$message.error(res.message)  
373 - }  
374 - this.searchQuery()  
375 - })  
376 - } else {  
377 - this.$refs.modalForm2.batchEdit(receiptContainerHeaderList)  
378 - this.$refs.modalForm2.title = '选择出库口' 360 + if (receiptContainerHeader.taskType == this.selectionRows[a].taskType) {
  361 + receiptContainerHeaderList.push(this.selectionRows[a])
379 } 362 }
  363 + }
  364 + }
  365 + if (receiptContainerHeaderList.length > 0) {
  366 + if (receiptContainerHeader.taskType == 100) {
  367 + createReceiptBatchTask(receiptContainerHeaderList).then(res => {
  368 + this.loading = false
  369 + if (res.success) {
  370 + this.$message.success(res.message)
  371 + } else {
  372 + this.$message.error(res.message)
  373 + }
  374 + this.searchQuery()
  375 + })
380 } else { 376 } else {
381 - this.$message.error("至少选择两条符合条件的记录!") 377 + this.$refs.modalForm2.batchEdit(receiptContainerHeaderList)
  378 + this.$refs.modalForm2.title = '选择出库口'
382 } 379 }
  380 + } else {
  381 + this.$message.error("没有符合生成条件的记录!")
383 } 382 }
384 }, 383 },
385 cancelBatchTask() { 384 cancelBatchTask() {
@@ -388,7 +387,7 @@ export default { @@ -388,7 +387,7 @@ export default {
388 return 387 return
389 } 388 }
390 if (this.selectedRowKeys.length <= 0) { 389 if (this.selectedRowKeys.length <= 0) {
391 - this.$message.warning('选择一条记录!'); 390 + this.$message.warning('至少选择一条记录!');
392 return; 391 return;
393 } 392 }
394 var ids = ""; 393 var ids = "";
ant-design-vue-jeecg/src/views/system/receipt/ReceiptDetailList.vue
@@ -49,8 +49,14 @@ @@ -49,8 +49,14 @@
49 :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}" 49 :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
50 @change="handleTableChange"> 50 @change="handleTableChange">
51 51
  52 + <span slot="status_dictText" slot-scope="status_dictText">
  53 + <a-tag :key="status_dictText" :color="getStatusColor(status_dictText)">
  54 + {{ status_dictText }}
  55 + </a-tag>
  56 + </span>
  57 +
52 <span slot="inventoryStatus_dictText" slot-scope="inventoryStatus_dictText"> 58 <span slot="inventoryStatus_dictText" slot-scope="inventoryStatus_dictText">
53 - <a-tag :key="inventoryStatus_dictText" :color="getStatusColor(inventoryStatus_dictText)"> 59 + <a-tag :key="inventoryStatus_dictText" :color="getInventoryStatusColor(inventoryStatus_dictText)">
54 {{ inventoryStatus_dictText }} 60 {{ inventoryStatus_dictText }}
55 </a-tag> 61 </a-tag>
56 </span> 62 </span>
@@ -178,6 +184,7 @@ export default { @@ -178,6 +184,7 @@ export default {
178 title: '单据状态', 184 title: '单据状态',
179 align: "center", 185 align: "center",
180 dataIndex: 'status_dictText', 186 dataIndex: 'status_dictText',
  187 + scopedSlots: {customRender: 'status_dictText'}
181 }, 188 },
182 { 189 {
183 title: '创建人', 190 title: '创建人',
@@ -231,6 +238,19 @@ export default { @@ -231,6 +238,19 @@ export default {
231 methods: { 238 methods: {
232 getStatusColor(status) { 239 getStatusColor(status) {
233 const colors = { 240 const colors = {
  241 + '新建': 'green',
  242 + '收货': 'Skyblue',
  243 + '等待上架': 'blue',
  244 + '上架': 'darkorange',
  245 + '过账': 'purple',
  246 + '回传': 'grey',
  247 + '回传失败': 'red',
  248 + default: 'blue'
  249 + };
  250 + return colors[status] || colors.default;
  251 + },
  252 + getInventoryStatusColor(status) {
  253 + const colors = {
234 '良品': 'green', 254 '良品': 'green',
235 '报废品': 'purple', 255 '报废品': 'purple',
236 '待确认 ': 'grey', 256 '待确认 ': 'grey',
ant-design-vue-jeecg/src/views/system/receipt/ReceiptHeaderList.vue
@@ -187,10 +187,10 @@ @@ -187,10 +187,10 @@
187 <a-menu-item v-if="record.firstStatus > 0 && record.firstStatus <= 20 && flowOff=='1'"> 187 <a-menu-item v-if="record.firstStatus > 0 && record.firstStatus <= 20 && flowOff=='1'">
188 <a @click="openProcess(record)" type="primary">审核进度</a> 188 <a @click="openProcess(record)" type="primary">审核进度</a>
189 </a-menu-item> 189 </a-menu-item>
190 - <a-menu-item v-has="'receiptHeader:edit'"> 190 + <a-menu-item v-has="'receiptHeader:edit'" v-if="record.firstStatus == 0 && record.lastStatus == 0 && record.referCode == null">
191 <a @click="handleEdit(record)">编辑</a> 191 <a @click="handleEdit(record)">编辑</a>
192 </a-menu-item> 192 </a-menu-item>
193 - <a-menu-item v-has="'receiptHeader:delete'"> 193 + <a-menu-item v-has="'receiptHeader:delete'" v-if="record.firstStatus == 0 && record.lastStatus == 0 && record.referCode == null">
194 <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)"> 194 <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
195 <a>删除</a> 195 <a>删除</a>
196 </a-popconfirm> 196 </a-popconfirm>
@@ -505,7 +505,7 @@ export default { @@ -505,7 +505,7 @@ export default {
505 if (res.success) { 505 if (res.success) {
506 this.$message.success(res.message); 506 this.$message.success(res.message);
507 } else { 507 } else {
508 - that.$message.warning(res.message); 508 + this.$message.warning(res.message);
509 } 509 }
510 this.searchQuery(); 510 this.searchQuery();
511 }); 511 });
ant-design-vue-jeecg/src/views/system/shipment/ShipmentContainerHeaderList.vue
@@ -297,8 +297,8 @@ export default { @@ -297,8 +297,8 @@ export default {
297 this.$refs.modalForm2.title = "选择出库口"; 297 this.$refs.modalForm2.title = "选择出库口";
298 }, 298 },
299 createBatchTask() { 299 createBatchTask() {
300 - if (this.selectedRowKeys.length <= 1) {  
301 - this.$message.warning('至少选择两条记录!') 300 + if (this.selectedRowKeys.length <= 0) {
  301 + this.$message.warning('至少选择一条记录!')
302 return 302 return
303 } 303 }
304 var shipmentContainerHeaderList = [] 304 var shipmentContainerHeaderList = []
@@ -317,7 +317,7 @@ export default { @@ -317,7 +317,7 @@ export default {
317 this.$refs.modalForm2.batchEdit(shipmentContainerHeaderList) 317 this.$refs.modalForm2.batchEdit(shipmentContainerHeaderList)
318 this.$refs.modalForm2.title = '选择出库口' 318 this.$refs.modalForm2.title = '选择出库口'
319 } else { 319 } else {
320 - this.$message.error("至少选择两条符合条件的记录!") 320 + this.$message.error("没有符合生成条件的记录!")
321 } 321 }
322 }, 322 },
323 cancelBatchTask() { 323 cancelBatchTask() {
@@ -326,7 +326,7 @@ export default { @@ -326,7 +326,7 @@ export default {
326 return 326 return
327 } 327 }
328 if (this.selectedRowKeys.length <= 0) { 328 if (this.selectedRowKeys.length <= 0) {
329 - this.$message.warning('选择一条记录!') 329 + this.$message.warning('至少选择一条记录!')
330 return 330 return
331 } 331 }
332 var ids = '' 332 var ids = ''
ant-design-vue-jeecg/src/views/system/shipment/ShipmentDetailList.vue
@@ -48,8 +48,14 @@ @@ -48,8 +48,14 @@
48 :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}" 48 :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
49 @change="handleTableChange"> 49 @change="handleTableChange">
50 50
  51 + <span slot="status_dictText" slot-scope="status_dictText">
  52 + <a-tag :key="status_dictText" :color="getStatusColor(status_dictText)">
  53 + {{ status_dictText }}
  54 + </a-tag>
  55 + </span>
  56 +
51 <span slot="inventoryStatus_dictText" slot-scope="inventoryStatus_dictText"> 57 <span slot="inventoryStatus_dictText" slot-scope="inventoryStatus_dictText">
52 - <a-tag :key="inventoryStatus_dictText" :color="getStatusColor(inventoryStatus_dictText)"> 58 + <a-tag :key="inventoryStatus_dictText" :color="getInventoryStatusColor(inventoryStatus_dictText)">
53 {{ inventoryStatus_dictText }} 59 {{ inventoryStatus_dictText }}
54 </a-tag> 60 </a-tag>
55 </span> 61 </span>
@@ -218,6 +224,7 @@ export default { @@ -218,6 +224,7 @@ export default {
218 title: '单据状态', 224 title: '单据状态',
219 align: "center", 225 align: "center",
220 dataIndex: 'status_dictText', 226 dataIndex: 'status_dictText',
  227 + scopedSlots: {customRender: 'status_dictText'}
221 }, 228 },
222 { 229 {
223 title: '创建人', 230 title: '创建人',
@@ -272,6 +279,19 @@ export default { @@ -272,6 +279,19 @@ export default {
272 methods: { 279 methods: {
273 getStatusColor(status) { 280 getStatusColor(status) {
274 const colors = { 281 const colors = {
  282 + '新建': 'green',
  283 + '出库组盘': 'Skyblue',
  284 + '等待下架': 'blue',
  285 + '下架': 'darkorange',
  286 + '过账': 'purple',
  287 + '回传': 'grey',
  288 + '回传失败': 'red',
  289 + default: 'blue'
  290 + };
  291 + return colors[status] || colors.default;
  292 + },
  293 + getInventoryStatusColor(status) {
  294 + const colors = {
275 '良品': 'green', 295 '良品': 'green',
276 '报废品': 'purple', 296 '报废品': 'purple',
277 '待确认 ': 'grey', 297 '待确认 ': 'grey',
ant-design-vue-jeecg/src/views/system/shipment/ShipmentHeaderList.vue
@@ -105,9 +105,9 @@ @@ -105,9 +105,9 @@
105 <!-- 操作按钮区域 --> 105 <!-- 操作按钮区域 -->
106 <div class="table-operator"> 106 <div class="table-operator">
107 <a-button v-has="'shipmentHeader:add'" @click="handleAdd" type="primary" icon="plus">新增</a-button> 107 <a-button v-has="'shipmentHeader:add'" @click="handleAdd" type="primary" icon="plus">新增</a-button>
  108 + <a-button v-has="'shipmentHeader:mergeShipment'" @click="mergeShipment" type="primary">合并单据</a-button>
108 <a-button v-has="'shipmentHeader:export'" type="primary" icon="download" @click="handleExportXls('出库单')">导出</a-button> 109 <a-button v-has="'shipmentHeader:export'" type="primary" icon="download" @click="handleExportXls('出库单')">导出</a-button>
109 - <a-upload v-has="'shipmentHeader:import'" name="file" :showUploadList="false" :multiple="false" :headers="tokenHeader" :action="importExcelUrl"  
110 - @change="handleImportExcel"> 110 + <a-upload v-has="'shipmentHeader:import'" name="file" :showUploadList="false" :multiple="false" :headers="tokenHeader" :action="importExcelUrl" @change="handleImportExcel">
111 <a-button type="primary" icon="import">导入</a-button> 111 <a-button type="primary" icon="import">导入</a-button>
112 <a-button v-has="'shipmentHeader:print'" @click="batchPrint()" type="primary">打印</a-button> 112 <a-button v-has="'shipmentHeader:print'" @click="batchPrint()" type="primary">打印</a-button>
113 </a-upload> 113 </a-upload>
@@ -135,7 +135,7 @@ @@ -135,7 +135,7 @@
135 :dataSource="dataSource" 135 :dataSource="dataSource"
136 :pagination="ipagination" 136 :pagination="ipagination"
137 :loading="loading" 137 :loading="loading"
138 - :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange, type:'radio'}" 138 + :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange, type:'checkbox'}"
139 :customRow="clickThenSelect" 139 :customRow="clickThenSelect"
140 @change="handleTableChange"> 140 @change="handleTableChange">
141 141
@@ -202,10 +202,10 @@ @@ -202,10 +202,10 @@
202 <a-menu-item v-if="record.firstStatus > 0 && record.firstStatus <= 20 && flowOff=='1'"> 202 <a-menu-item v-if="record.firstStatus > 0 && record.firstStatus <= 20 && flowOff=='1'">
203 <a @click="openProcess(record)" type="primary">审核进度</a> 203 <a @click="openProcess(record)" type="primary">审核进度</a>
204 </a-menu-item> 204 </a-menu-item>
205 - <a-menu-item v-has="'shipmentHeader:edit'"> 205 + <a-menu-item v-has="'shipmentHeader:edit'" v-if="record.firstStatus == 0 && record.lastStatus == 0 && record.referCode == null">
206 <a @click="handleEdit(record)">编辑</a> 206 <a @click="handleEdit(record)">编辑</a>
207 </a-menu-item> 207 </a-menu-item>
208 - <a-menu-item v-has="'shipmentHeader:delete'"> 208 + <a-menu-item v-has="'shipmentHeader:delete'" v-if="record.firstStatus == 0 && record.lastStatus == 0 && record.referCode == null">
209 <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)"> 209 <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
210 <a>删除</a> 210 <a>删除</a>
211 </a-popconfirm> 211 </a-popconfirm>
@@ -241,7 +241,7 @@ import {getCompanyList, backErpShipment} from &#39;@/api/api&#39; @@ -241,7 +241,7 @@ import {getCompanyList, backErpShipment} from &#39;@/api/api&#39;
241 import {getShipmentTypeList} from '@/api/api' 241 import {getShipmentTypeList} from '@/api/api'
242 import {getCustomerList} from '@/api/api' 242 import {getCustomerList} from '@/api/api'
243 import {autoCombination} from '@/api/api' 243 import {autoCombination} from '@/api/api'
244 -import {createShipmentAuditFlow,getDocumentAduitFlow} from '@/api/api' 244 +import {createShipmentAuditFlow, getDocumentAduitFlow, mergeShipment} from '@/api/api'
245 import store from '@/store' 245 import store from '@/store'
246 import ShipmentAuditModal from "./modules/ShipmentAuditModal"; 246 import ShipmentAuditModal from "./modules/ShipmentAuditModal";
247 import FlowProcess from "../flow/FlowProcess"; 247 import FlowProcess from "../flow/FlowProcess";
@@ -400,6 +400,31 @@ export default { @@ -400,6 +400,31 @@ export default {
400 } 400 }
401 }, 401 },
402 methods: { 402 methods: {
  403 + mergeShipment() {
  404 + if (this.selectedRowKeys.length <= 1) {
  405 + this.$message.warning('至少选择两条记录!')
  406 + return
  407 + }
  408 + var shipmentHeaderList = []
  409 + for (var a = 0; a < this.selectedRowKeys.length; a++) {
  410 + if (this.selectionRows[a] != null && this.selectionRows[a].firstStatus == 0 && this.selectionRows[a].lastStatus == 0) {
  411 + shipmentHeaderList.push(this.selectionRows[a])
  412 + }
  413 + }
  414 + if (shipmentHeaderList.length > 0) {
  415 + mergeShipment(shipmentHeaderList).then(res => {
  416 + this.loading = false
  417 + if (res.success) {
  418 + this.$message.success(res.message)
  419 + this.searchQuery()
  420 + } else {
  421 + this.$message.error(res.message)
  422 + }
  423 + })
  424 + } else {
  425 + this.$message.error("至少选择两条符合条件的记录!")
  426 + }
  427 + },
403 getDocumentAduitFlowStaus(){ 428 getDocumentAduitFlowStaus(){
404 getDocumentAduitFlow().then((res) => { 429 getDocumentAduitFlow().then((res) => {
405 this.flowOff=res.message; 430 this.flowOff=res.message;
@@ -435,17 +460,21 @@ export default { @@ -435,17 +460,21 @@ export default {
435 this.selectedMainId = '' 460 this.selectedMainId = ''
436 }, 461 },
437 onSelectChange(selectedRowKeys, selectionRows) { 462 onSelectChange(selectedRowKeys, selectionRows) {
438 - this.selectedMainId = selectedRowKeys[0].toString(); 463 + if (selectedRowKeys.length > 0) {
  464 + this.selectedMainId = selectedRowKeys[0].toString();
  465 + }
439 this.selectedRowKeys = selectedRowKeys; 466 this.selectedRowKeys = selectedRowKeys;
440 this.selectionRows = selectionRows; 467 this.selectionRows = selectionRows;
441 - this.flowStatus = selectionRows[0].firstStatus.toString(); 468 + if (selectionRows.length > 0) {
  469 + this.flowStatus = selectionRows[0].firstStatus.toString();
  470 + }
442 }, 471 },
443 hanleBack(record) { 472 hanleBack(record) {
444 backErpShipment(record).then((res) => { 473 backErpShipment(record).then((res) => {
445 if (res.success) { 474 if (res.success) {
446 this.$message.success(res.message); 475 this.$message.success(res.message);
447 } else { 476 } else {
448 - that.$message.warning(res.message); 477 + this.$message.warning(res.message);
449 } 478 }
450 this.searchQuery(); 479 this.searchQuery();
451 }); 480 });
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/api/acs/controller/AcsController.java
@@ -40,11 +40,11 @@ public class AcsController extends HuahengBaseController { @@ -40,11 +40,11 @@ public class AcsController extends HuahengBaseController {
40 40
41 // @PassApiAuthentication 41 // @PassApiAuthentication
42 // @ApiLogger(apiName = "API接口第三方Token校验测试", from = "TEST") 42 // @ApiLogger(apiName = "API接口第三方Token校验测试", from = "TEST")
43 - @ResponseBody  
44 - @PostMapping(value = "/testTokenCheck")  
45 - public Result<?> testTokenCheck(@RequestBody Map<String, String> paramMap, HttpServletRequest request) {  
46 - return Result.ok();  
47 - } 43 +// @ResponseBody
  44 +// @PostMapping(value = "/testTokenCheck")
  45 +// public Result<?> testTokenCheck(@RequestBody Map<String, String> paramMap, HttpServletRequest request) {
  46 +// return Result.ok();
  47 +// }
48 48
49 @PostMapping("/notifyAGVTask") 49 @PostMapping("/notifyAGVTask")
50 @ResponseBody 50 @ResponseBody
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/framework/controller/HuahengBaseController.java
@@ -6,6 +6,7 @@ import javax.annotation.Nonnull; @@ -6,6 +6,7 @@ import javax.annotation.Nonnull;
6 6
7 import org.jeecg.common.api.vo.Result; 7 import org.jeecg.common.api.vo.Result;
8 import org.jeecg.common.exception.JeecgBootException; 8 import org.jeecg.common.exception.JeecgBootException;
  9 +import org.jeecg.modules.wms.task.taskHeader.entity.TaskHeader;
9 import org.jeecg.utils.support.RedissonDistributedLocker; 10 import org.jeecg.utils.support.RedissonDistributedLocker;
10 import org.springframework.beans.factory.annotation.Autowired; 11 import org.springframework.beans.factory.annotation.Autowired;
11 12
@@ -59,14 +60,29 @@ public class HuahengBaseController { @@ -59,14 +60,29 @@ public class HuahengBaseController {
59 * @return 60 * @return
60 */ 61 */
61 public Result<?> handleMultiProcess(@Nonnull String taskName, @Nonnull String lockKey, MultiProcessListener multiProcessListener) { 62 public Result<?> handleMultiProcess(@Nonnull String taskName, @Nonnull String lockKey, MultiProcessListener multiProcessListener) {
  63 + return this.handleMultiProcess(taskName, lockKey, WAIT_TIME, LEASE_TIME, multiProcessListener);
  64 + }
  65 +
  66 + /**
  67 + * 获取分布式锁,自定义锁等待,释放时间</br>
  68 + * 注意锁与事务的顺序:获取分布式锁 -> 开启事务 -> 执行业务 -> 提交事务 -> 释放分布式锁
  69 + * @author TanYibin
  70 + * @createDate 2023年2月8日
  71 + * @param taskName
  72 + * @param lockKey
  73 + * @param multiProcessListener
  74 + * @return
  75 + */
  76 + public Result<?> handleMultiProcess(@Nonnull String taskName, @Nonnull String lockKey, @Nonnull Integer waitTime, @Nonnull Integer leaseTime,
  77 + MultiProcessListener multiProcessListener) {
62 Result<?> result = null; 78 Result<?> result = null;
63 final long startTime = SystemClock.now(); 79 final long startTime = SystemClock.now();
64 final String fullLockKey = "RedissonLock_" + taskName + "_" + lockKey; 80 final String fullLockKey = "RedissonLock_" + taskName + "_" + lockKey;
65 - final boolean tryLock = redissonDistributedLocker.tryLock(fullLockKey, TimeUnit.SECONDS, WAIT_TIME, LEASE_TIME); 81 + final boolean tryLock = redissonDistributedLocker.tryLock(fullLockKey, TimeUnit.SECONDS, waitTime, leaseTime);
66 final long endTime = SystemClock.now(); 82 final long endTime = SystemClock.now();
67 if (!tryLock) { 83 if (!tryLock) {
68 log.error("[{}] 获取分布式锁失败 lockKey = {},等待锁耗时:{}ms", taskName, fullLockKey, endTime - startTime); 84 log.error("[{}] 获取分布式锁失败 lockKey = {},等待锁耗时:{}ms", taskName, fullLockKey, endTime - startTime);
69 - throw new RuntimeException(StrUtil.format("[{}] 获取分布式锁失败 lockKey = {},等待时间超出10秒", taskName, fullLockKey)); 85 + throw new RuntimeException(StrUtil.format("[{}] 获取分布式锁失败 lockKey = {},超出设定等待时间:{}s", taskName, fullLockKey, waitTime));
70 } 86 }
71 // 注意:一定是获取锁成功后,才进行try{}finally{释放锁} 87 // 注意:一定是获取锁成功后,才进行try{}finally{释放锁}
72 try { 88 try {
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/framework/service/IHuahengMultiHandlerService.java
1 package org.jeecg.modules.wms.framework.service; 1 package org.jeecg.modules.wms.framework.service;
2 2
  3 +import java.util.List;
  4 +
3 import org.jeecg.common.api.vo.Result; 5 import org.jeecg.common.api.vo.Result;
4 import org.jeecg.modules.wms.api.mobile.entity.CallBoxBean; 6 import org.jeecg.modules.wms.api.mobile.entity.CallBoxBean;
5 import org.jeecg.modules.wms.api.mobile.entity.QuickReceiptBean; 7 import org.jeecg.modules.wms.api.mobile.entity.QuickReceiptBean;
@@ -16,8 +18,6 @@ import org.jeecg.modules.wms.task.taskHeader.entity.TaskHeader; @@ -16,8 +18,6 @@ import org.jeecg.modules.wms.task.taskHeader.entity.TaskHeader;
16 */ 18 */
17 public interface IHuahengMultiHandlerService { 19 public interface IHuahengMultiHandlerService {
18 20
19 - Result sendTaskToWcs(TaskHeader taskHeader);  
20 -  
21 Result createReceiptTask(ReceiptContainerHeader receiptContainerHeader, String warehouseCode); 21 Result createReceiptTask(ReceiptContainerHeader receiptContainerHeader, String warehouseCode);
22 22
23 Result combination(CombinationModel combinationModel); 23 Result combination(CombinationModel combinationModel);
@@ -45,4 +45,9 @@ public interface IHuahengMultiHandlerService { @@ -45,4 +45,9 @@ public interface IHuahengMultiHandlerService {
45 Result backReceipt(ReceiptHeader receiptHeader); 45 Result backReceipt(ReceiptHeader receiptHeader);
46 46
47 Result backShipment(ShipmentHeader shipmentHeader); 47 Result backShipment(ShipmentHeader shipmentHeader);
  48 +
  49 + Result sendTaskToWcs(TaskHeader taskHeader, String zoneCode);
  50 +
  51 + void sendTaskToWcs(List<TaskHeader> taskHeaders, String warehouseCode, String zoneCode);
  52 +
48 } 53 }
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/framework/service/impl/HuahengMultiHandlerServiceImpl.java
1 package org.jeecg.modules.wms.framework.service.impl; 1 package org.jeecg.modules.wms.framework.service.impl;
2 2
3 import java.math.BigDecimal; 3 import java.math.BigDecimal;
  4 +import java.util.List;
4 5
5 import javax.annotation.Resource; 6 import javax.annotation.Resource;
6 7
@@ -26,11 +27,15 @@ import org.jeecg.modules.wms.shipment.shipmentHeader.entity.ShipmentHeader; @@ -26,11 +27,15 @@ import org.jeecg.modules.wms.shipment.shipmentHeader.entity.ShipmentHeader;
26 import org.jeecg.modules.wms.shipment.shipmentHeader.service.IShipmentDetailService; 27 import org.jeecg.modules.wms.shipment.shipmentHeader.service.IShipmentDetailService;
27 import org.jeecg.modules.wms.task.taskHeader.entity.TaskHeader; 28 import org.jeecg.modules.wms.task.taskHeader.entity.TaskHeader;
28 import org.jeecg.modules.wms.task.taskHeader.service.ITaskHeaderService; 29 import org.jeecg.modules.wms.task.taskHeader.service.ITaskHeaderService;
  30 +import org.springframework.scheduling.annotation.Async;
29 import org.springframework.stereotype.Service; 31 import org.springframework.stereotype.Service;
30 32
  33 +import lombok.extern.slf4j.Slf4j;
  34 +
31 /** 35 /**
32 * @author 游杰 36 * @author 游杰
33 */ 37 */
  38 +@Slf4j
34 @Service 39 @Service
35 public class HuahengMultiHandlerServiceImpl extends HuahengBaseController implements IHuahengMultiHandlerService { 40 public class HuahengMultiHandlerServiceImpl extends HuahengBaseController implements IHuahengMultiHandlerService {
36 41
@@ -59,22 +64,42 @@ public class HuahengMultiHandlerServiceImpl extends HuahengBaseController implem @@ -59,22 +64,42 @@ public class HuahengMultiHandlerServiceImpl extends HuahengBaseController implem
59 private IErpService erpService; 64 private IErpService erpService;
60 65
61 @Override 66 @Override
62 - public Result sendTaskToWcs(TaskHeader taskHeader) { 67 + public Result sendTaskToWcs(TaskHeader taskHeader, String zoneCode) {
63 if (taskHeader == null) { 68 if (taskHeader == null) {
64 return Result.error("任务信息为空"); 69 return Result.error("任务信息为空");
65 } 70 }
66 - String lockKey = taskHeader.getWarehouseCode();  
67 - Result result = handleMultiProcess("sendTaskToWcs", lockKey, new MultiProcessListener() { 71 + String lockKey = taskHeader.getWarehouseCode() + "_" + zoneCode;
  72 + Result result = handleMultiProcess("sendTaskToWcs", lockKey, 10, 300, new MultiProcessListener() {
  73 +
68 @Override 74 @Override
69 public Result<?> doProcess() { 75 public Result<?> doProcess() {
70 - Result result = taskHeaderService.sendTaskToWcs(taskHeader.getId());  
71 - return result; 76 + return taskHeaderService.sendTaskToWcs(taskHeader.getId());
72 } 77 }
73 }); 78 });
74 return result; 79 return result;
75 } 80 }
76 81
77 @Override 82 @Override
  83 + @Async("asyncPoolTaskExecutor")
  84 + public void sendTaskToWcs(List<TaskHeader> taskHeaders, String warehouseCode, String zoneCode) {
  85 + String lockKey = warehouseCode + "_" + zoneCode;
  86 + handleMultiProcess("sendTaskToWcs", lockKey, 10, 300, new MultiProcessListener() {
  87 +
  88 + @Override
  89 + public Result<?> doProcess() {
  90 + for (TaskHeader taskHeader : taskHeaders) {
  91 + try {
  92 + taskHeaderService.sendTaskToWcs(taskHeader.getId());
  93 + } catch (Exception e) {
  94 + log.error("sendTaskToWcs 执行异常,errorMessage: {}", e.getMessage(), e);
  95 + }
  96 + }
  97 + return Result.OK();
  98 + }
  99 + });
  100 + }
  101 +
  102 + @Override
78 public Result createReceiptTask(ReceiptContainerHeader receiptContainerHeader, String warehouseCode) { 103 public Result createReceiptTask(ReceiptContainerHeader receiptContainerHeader, String warehouseCode) {
79 Result result = handleMultiProcess("createReceiptTask", warehouseCode, new MultiProcessListener() { 104 Result result = handleMultiProcess("createReceiptTask", warehouseCode, new MultiProcessListener() {
80 @Override 105 @Override
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/monitor/job/WcsTask.java
1 package org.jeecg.modules.wms.monitor.job; 1 package org.jeecg.modules.wms.monitor.job;
2 2
3 -import java.util.HashMap; 3 +import java.util.Date;
4 import java.util.List; 4 import java.util.List;
5 import java.util.Map; 5 import java.util.Map;
  6 +import java.util.stream.Collectors;
6 7
7 import javax.annotation.Resource; 8 import javax.annotation.Resource;
8 9
9 -import org.apache.commons.collections.MapUtils;  
10 import org.jeecg.common.util.DateUtils; 10 import org.jeecg.common.util.DateUtils;
  11 +import org.jeecg.modules.wms.config.container.entity.Container;
  12 +import org.jeecg.modules.wms.config.container.service.IContainerService;
11 import org.jeecg.modules.wms.framework.service.IHuahengMultiHandlerService; 13 import org.jeecg.modules.wms.framework.service.IHuahengMultiHandlerService;
12 import org.jeecg.modules.wms.task.taskHeader.entity.TaskHeader; 14 import org.jeecg.modules.wms.task.taskHeader.entity.TaskHeader;
13 import org.jeecg.modules.wms.task.taskHeader.service.ITaskHeaderService; 15 import org.jeecg.modules.wms.task.taskHeader.service.ITaskHeaderService;
@@ -17,10 +19,13 @@ import org.quartz.Job; @@ -17,10 +19,13 @@ import org.quartz.Job;
17 import org.quartz.JobExecutionContext; 19 import org.quartz.JobExecutionContext;
18 import org.quartz.JobExecutionException; 20 import org.quartz.JobExecutionException;
19 import org.quartz.PersistJobDataAfterExecution; 21 import org.quartz.PersistJobDataAfterExecution;
  22 +import org.springframework.util.CollectionUtils;
  23 +import org.springframework.util.StringUtils;
20 24
21 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 25 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
22 import com.baomidou.mybatisplus.core.toolkit.Wrappers; 26 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
23 27
  28 +import cn.hutool.core.date.DateUtil;
24 import lombok.extern.slf4j.Slf4j; 29 import lombok.extern.slf4j.Slf4j;
25 30
26 /** 31 /**
@@ -39,18 +44,29 @@ public class WcsTask implements Job { @@ -39,18 +44,29 @@ public class WcsTask implements Job {
39 @Resource 44 @Resource
40 private IHuahengMultiHandlerService huahengMultiHandlerService; 45 private IHuahengMultiHandlerService huahengMultiHandlerService;
41 46
  47 + @Resource
  48 + private IContainerService containerService;
  49 +
42 @Override 50 @Override
43 public void execute(JobExecutionContext context) throws JobExecutionException { 51 public void execute(JobExecutionContext context) throws JobExecutionException {
44 log.info(String.format(" WcsTask 执行任务! 时间:" + DateUtils.getTimestamp())); 52 log.info(String.format(" WcsTask 执行任务! 时间:" + DateUtils.getTimestamp()));
45 LambdaQueryWrapper<TaskHeader> taskHeaderLambdaQueryWrapper = Wrappers.lambdaQuery(); 53 LambdaQueryWrapper<TaskHeader> taskHeaderLambdaQueryWrapper = Wrappers.lambdaQuery();
46 - taskHeaderLambdaQueryWrapper.eq(TaskHeader::getStatus, QuantityConstant.TASK_STATUS_BUILD).eq(TaskHeader::getAgvTaskId, 0); 54 + taskHeaderLambdaQueryWrapper.eq(TaskHeader::getStatus, QuantityConstant.TASK_STATUS_BUILD).eq(TaskHeader::getAgvTaskId, 0)
  55 + .ge(TaskHeader::getCreateTime, DateUtil.offsetDay(new Date(), -180)).orderByAsc(TaskHeader::getCreateTime);
47 List<TaskHeader> taskHeaderList = taskHeaderService.list(taskHeaderLambdaQueryWrapper); 56 List<TaskHeader> taskHeaderList = taskHeaderService.list(taskHeaderLambdaQueryWrapper);
48 - for (TaskHeader taskHeader : taskHeaderList) {  
49 - try {  
50 - huahengMultiHandlerService.sendTaskToWcs(taskHeader);  
51 - } catch (Exception e) {  
52 - e.printStackTrace();  
53 - } 57 + if (CollectionUtils.isEmpty(taskHeaderList)) {
  58 + return;
54 } 59 }
  60 + LambdaQueryWrapper<Container> containerLambdaQueryWrapper = Wrappers.lambdaQuery();
  61 + containerLambdaQueryWrapper.in(Container::getCode, taskHeaderList.stream().map(TaskHeader::getContainerCode).collect(Collectors.toList()));
  62 + List<Container> containerList = containerService.list(containerLambdaQueryWrapper);
  63 + Map<String, String> containerZoneCodeMap = containerList.stream().collect(Collectors.toMap(Container::getCode, Container::getZoneCode));
  64 + Map<String, List<TaskHeader>> groupeTaskHeaders =
  65 + taskHeaderList.stream().collect(Collectors.groupingBy(taskHeader -> StringUtils.isEmpty(containerZoneCodeMap.get(taskHeader.getContainerCode()))
  66 + ? QuantityConstant.DEFAULT_ZONE_CODE : containerZoneCodeMap.get(taskHeader.getContainerCode())));
  67 + // 循环 groupedTaskHeaders 中的每个键值对
  68 + groupeTaskHeaders.forEach((zoneCode, taskHeaders) -> {
  69 + huahengMultiHandlerService.sendTaskToWcs(taskHeaders, taskHeaders.get(0).getWarehouseCode(), zoneCode);
  70 + });
55 } 71 }
56 } 72 }
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/receipt/receiving/service/impl/ReceiveServiceImpl.java
@@ -226,6 +226,9 @@ public class ReceiveServiceImpl extends ServiceImpl&lt;ReceiveMapper, Receive&gt; impl @@ -226,6 +226,9 @@ public class ReceiveServiceImpl extends ServiceImpl&lt;ReceiveMapper, Receive&gt; impl
226 receiptDetail1.setId(receiptDetail.getId()); 226 receiptDetail1.setId(receiptDetail.getId());
227 receiptDetail1.setTaskQty(receiptTaskQty); 227 receiptDetail1.setTaskQty(receiptTaskQty);
228 receiptDetail1.setStatus(QuantityConstant.RECEIPT_HEADER_RECEIVING); 228 receiptDetail1.setStatus(QuantityConstant.RECEIPT_HEADER_RECEIVING);
  229 + if (receiptTaskQty.equals(receiptQty)) {
  230 + receiptDetail1.setStatus(QuantityConstant.RECEIPT_HEADER_WAIT_SHELF);
  231 + }
229 receiptDetailList.add(receiptDetail1); 232 receiptDetailList.add(receiptDetail1);
230 233
231 LambdaQueryWrapper<ReceiptContainerDetail> receiptContainerDetailLambdaQueryWrapper = Wrappers.lambdaQuery(); 234 LambdaQueryWrapper<ReceiptContainerDetail> receiptContainerDetailLambdaQueryWrapper = Wrappers.lambdaQuery();
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/shipment/shipmentCombination/service/impl/ShipmentCombinationServiceImpl.java
@@ -87,8 +87,6 @@ public class ShipmentCombinationServiceImpl implements IShipmentCombinationServi @@ -87,8 +87,6 @@ public class ShipmentCombinationServiceImpl implements IShipmentCombinationServi
87 private ITaskDetailService taskDetailService; 87 private ITaskDetailService taskDetailService;
88 @Autowired 88 @Autowired
89 private IInventoryHeaderService inventoryHeaderService; 89 private IInventoryHeaderService inventoryHeaderService;
90 - @Resource  
91 - private IHuahengMultiHandlerService huahengMultiHandlerService;  
92 90
93 /** 91 /**
94 * 根据出库单详情,匹配到可用出库的库存详情 92 * 根据出库单详情,匹配到可用出库的库存详情
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/shipment/shipmentHeader/controller/ShipmentHeaderController.java
@@ -77,10 +77,13 @@ public class ShipmentHeaderController extends JeecgController&lt;ShipmentHeader, IS @@ -77,10 +77,13 @@ public class ShipmentHeaderController extends JeecgController&lt;ShipmentHeader, IS
77 77
78 @Autowired 78 @Autowired
79 private IShipmentDetailService shipmentDetailService; 79 private IShipmentDetailService shipmentDetailService;
  80 +
80 @Resource 81 @Resource
81 private IErpService erpService; 82 private IErpService erpService;
  83 +
82 @Resource 84 @Resource
83 private IInventoryDetailService inventoryDetailService; 85 private IInventoryDetailService inventoryDetailService;
  86 +
84 @Resource 87 @Resource
85 private IHuahengMultiHandlerService huahengMultiHandlerService; 88 private IHuahengMultiHandlerService huahengMultiHandlerService;
86 89
@@ -120,6 +123,14 @@ public class ShipmentHeaderController extends JeecgController&lt;ShipmentHeader, IS @@ -120,6 +123,14 @@ public class ShipmentHeaderController extends JeecgController&lt;ShipmentHeader, IS
120 return shipmentHeaderService.saveShipmentHeader(shipmentHeader); 123 return shipmentHeaderService.saveShipmentHeader(shipmentHeader);
121 } 124 }
122 125
  126 + @AutoLog(value = "出库单-单据合并")
  127 + @ApiOperation(value = "出库单-单据合并", notes = "出库单-单据合并")
  128 + @PostMapping(value = "/mergeShipment")
  129 + @RequiresPermissions("shipmentHeader:mergeShipment")
  130 + public Result<?> mergeShipment(@RequestBody List<ShipmentHeader> shipmentHeaderList, HttpServletRequest req) {
  131 + return shipmentHeaderService.mergeShipment(shipmentHeaderList);
  132 + }
  133 +
123 /** 134 /**
124 * 编辑 135 * 编辑
125 * @param shipmentHeader 136 * @param shipmentHeader
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/shipment/shipmentHeader/entity/ShipmentDetail.java
@@ -40,6 +40,10 @@ public class ShipmentDetail implements Serializable { @@ -40,6 +40,10 @@ public class ShipmentDetail implements Serializable {
40 @Excel(name = "出库单编码", width = 15) 40 @Excel(name = "出库单编码", width = 15)
41 @ApiModelProperty(value = "出库单编码") 41 @ApiModelProperty(value = "出库单编码")
42 private String shipmentCode; 42 private String shipmentCode;
  43 + /** 合并出库单编码 */
  44 + @Excel(name = "合并出库单编码", width = 15)
  45 + @ApiModelProperty(value = "合并出库单编码")
  46 + private String mergeShipmentCode;
43 /** 仓库编码 */ 47 /** 仓库编码 */
44 @Excel(name = "仓库编码", width = 15) 48 @Excel(name = "仓库编码", width = 15)
45 @ApiModelProperty(value = "仓库编码") 49 @ApiModelProperty(value = "仓库编码")
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/shipment/shipmentHeader/entity/ShipmentHeader.java
@@ -34,6 +34,10 @@ public class ShipmentHeader implements Serializable { @@ -34,6 +34,10 @@ public class ShipmentHeader implements Serializable {
34 @Excel(name = "出库单编码", width = 15) 34 @Excel(name = "出库单编码", width = 15)
35 @ApiModelProperty(value = "出库单编码") 35 @ApiModelProperty(value = "出库单编码")
36 private String code; 36 private String code;
  37 + /** 合并出库单编码 */
  38 + @Excel(name = "合并出库单编码", width = 15)
  39 + @ApiModelProperty(value = "合并出库单编码")
  40 + private String mergeShipmentCode;
37 /** 仓库编码 */ 41 /** 仓库编码 */
38 @Excel(name = "仓库编码", width = 15) 42 @Excel(name = "仓库编码", width = 15)
39 @ApiModelProperty(value = "仓库编码") 43 @ApiModelProperty(value = "仓库编码")
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/shipment/shipmentHeader/service/IShipmentHeaderService.java
@@ -2,6 +2,7 @@ package org.jeecg.modules.wms.shipment.shipmentHeader.service; @@ -2,6 +2,7 @@ package org.jeecg.modules.wms.shipment.shipmentHeader.service;
2 2
3 import java.io.Serializable; 3 import java.io.Serializable;
4 import java.util.Collection; 4 import java.util.Collection;
  5 +import java.util.List;
5 6
6 import org.jeecg.common.api.vo.Result; 7 import org.jeecg.common.api.vo.Result;
7 import org.jeecg.modules.wms.shipment.shipmentHeader.entity.ShipmentHeader; 8 import org.jeecg.modules.wms.shipment.shipmentHeader.entity.ShipmentHeader;
@@ -39,4 +40,6 @@ public interface IShipmentHeaderService extends IService&lt;ShipmentHeader&gt; { @@ -39,4 +40,6 @@ public interface IShipmentHeaderService extends IService&lt;ShipmentHeader&gt; {
39 public ShipmentHeader getShipmentHeaderByReferCode(String referCode, String warehouseCode); 40 public ShipmentHeader getShipmentHeaderByReferCode(String referCode, String warehouseCode);
40 41
41 boolean updateFirstStatusAndLastStatusById(Integer firstStatus, Integer lastStatus, int id); 42 boolean updateFirstStatusAndLastStatusById(Integer firstStatus, Integer lastStatus, int id);
  43 +
  44 + public Result<Object> mergeShipment(List<ShipmentHeader> shipmentHeaderList);
42 } 45 }
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/shipment/shipmentHeader/service/impl/ShipmentHeaderServiceImpl.java
@@ -6,6 +6,7 @@ import java.text.SimpleDateFormat; @@ -6,6 +6,7 @@ import java.text.SimpleDateFormat;
6 import java.util.Collection; 6 import java.util.Collection;
7 import java.util.Date; 7 import java.util.Date;
8 import java.util.List; 8 import java.util.List;
  9 +import java.util.stream.Collectors;
9 10
10 import javax.annotation.Resource; 11 import javax.annotation.Resource;
11 12
@@ -31,8 +32,10 @@ import org.jeecg.utils.constant.QuantityConstant; @@ -31,8 +32,10 @@ import org.jeecg.utils.constant.QuantityConstant;
31 import org.springframework.beans.factory.annotation.Autowired; 32 import org.springframework.beans.factory.annotation.Autowired;
32 import org.springframework.stereotype.Service; 33 import org.springframework.stereotype.Service;
33 import org.springframework.transaction.annotation.Transactional; 34 import org.springframework.transaction.annotation.Transactional;
  35 +import org.springframework.util.CollectionUtils;
34 36
35 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 37 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  38 +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
36 import com.baomidou.mybatisplus.core.toolkit.Wrappers; 39 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
37 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 40 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
38 41
@@ -50,26 +53,37 @@ public class ShipmentHeaderServiceImpl extends ServiceImpl&lt;ShipmentHeaderMapper, @@ -50,26 +53,37 @@ public class ShipmentHeaderServiceImpl extends ServiceImpl&lt;ShipmentHeaderMapper,
50 53
51 @Autowired 54 @Autowired
52 private ShipmentHeaderMapper shipmentHeaderMapper; 55 private ShipmentHeaderMapper shipmentHeaderMapper;
  56 +
53 @Autowired 57 @Autowired
54 private ShipmentDetailMapper shipmentDetailMapper; 58 private ShipmentDetailMapper shipmentDetailMapper;
  59 +
55 @Resource 60 @Resource
56 private IShipmentTypeService shipmentTypeService; 61 private IShipmentTypeService shipmentTypeService;
  62 +
57 @Resource 63 @Resource
58 private IShipmentHeaderService shipmentHeaderService; 64 private IShipmentHeaderService shipmentHeaderService;
  65 +
59 @Resource 66 @Resource
60 private IShipmentDetailService shipmentDetailService; 67 private IShipmentDetailService shipmentDetailService;
  68 +
61 @Resource 69 @Resource
62 private IShipmentContainerDetailService shipmentContainerDetailService; 70 private IShipmentContainerDetailService shipmentContainerDetailService;
  71 +
63 @Resource 72 @Resource
64 private ILocationService locationService; 73 private ILocationService locationService;
  74 +
65 @Resource 75 @Resource
66 private IContainerService containerService; 76 private IContainerService containerService;
  77 +
67 @Resource 78 @Resource
68 private ITaskHeaderService taskHeaderService; 79 private ITaskHeaderService taskHeaderService;
  80 +
69 @Resource 81 @Resource
70 private IInventoryDetailService inventoryDetailService; 82 private IInventoryDetailService inventoryDetailService;
  83 +
71 @Resource 84 @Resource
72 private IParameterConfigurationService parameterConfigurationService; 85 private IParameterConfigurationService parameterConfigurationService;
  86 +
73 @Resource 87 @Resource
74 private IShipmentHeaderHistoryService shipmentHeaderHistoryService; 88 private IShipmentHeaderHistoryService shipmentHeaderHistoryService;
75 89
@@ -114,12 +128,12 @@ public class ShipmentHeaderServiceImpl extends ServiceImpl&lt;ShipmentHeaderMapper, @@ -114,12 +128,12 @@ public class ShipmentHeaderServiceImpl extends ServiceImpl&lt;ShipmentHeaderMapper,
114 if (StringUtils.isNotEmpty(referCode)) { 128 if (StringUtils.isNotEmpty(referCode)) {
115 ShipmentHeader referShipmentHeader = getShipmentHeaderByReferCode(referCode, warehouseCode); 129 ShipmentHeader referShipmentHeader = getShipmentHeaderByReferCode(referCode, warehouseCode);
116 if (referShipmentHeader != null) { 130 if (referShipmentHeader != null) {
117 - return Result.error("上游单号" + referCode + ",已经存在"); 131 + return Result.error("上游单号:" + referCode + ",已经存在");
118 } 132 }
119 } 133 }
120 String code = createCode(shipmentHeader.getType()); 134 String code = createCode(shipmentHeader.getType());
121 if (StringUtils.isEmpty(code)) { 135 if (StringUtils.isEmpty(code)) {
122 - throw new JeecgBootException("根据出库单类型" + shipmentHeader.getType() + "生成单号失败"); 136 + throw new JeecgBootException("根据出库单类型:" + shipmentHeader.getType() + ",生成单号失败");
123 } 137 }
124 shipmentHeader.setCode(code); 138 shipmentHeader.setCode(code);
125 shipmentHeader.setFirstStatus(QuantityConstant.RECEIPT_HEADER_BUILD); 139 shipmentHeader.setFirstStatus(QuantityConstant.RECEIPT_HEADER_BUILD);
@@ -138,8 +152,8 @@ public class ShipmentHeaderServiceImpl extends ServiceImpl&lt;ShipmentHeaderMapper, @@ -138,8 +152,8 @@ public class ShipmentHeaderServiceImpl extends ServiceImpl&lt;ShipmentHeaderMapper,
138 Date now = new Date(); 152 Date now = new Date();
139 SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd"); 153 SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd");
140 LambdaQueryWrapper<ShipmentHeader> shipmentHeaderLambdaQueryWrapper = Wrappers.lambdaQuery(); 154 LambdaQueryWrapper<ShipmentHeader> shipmentHeaderLambdaQueryWrapper = Wrappers.lambdaQuery();
141 - shipmentHeaderLambdaQueryWrapper.eq(ShipmentHeader::getType, shipmentType).select(ShipmentHeader::getCode).orderByDesc(ShipmentHeader::getId)  
142 - .last("Limit 1"); 155 + shipmentHeaderLambdaQueryWrapper.eq(ShipmentHeader::getType, shipmentType).likeRight(ShipmentHeader::getCode, shipmentType).select(ShipmentHeader::getCode)
  156 + .orderByDesc(ShipmentHeader::getId).last("Limit 1");
143 String maxCode = null; 157 String maxCode = null;
144 ShipmentHeader shipmentHeader = this.getOne(shipmentHeaderLambdaQueryWrapper); 158 ShipmentHeader shipmentHeader = this.getOne(shipmentHeaderLambdaQueryWrapper);
145 if (shipmentHeader != null) { 159 if (shipmentHeader != null) {
@@ -245,4 +259,78 @@ public class ShipmentHeaderServiceImpl extends ServiceImpl&lt;ShipmentHeaderMapper, @@ -245,4 +259,78 @@ public class ShipmentHeaderServiceImpl extends ServiceImpl&lt;ShipmentHeaderMapper,
245 return success; 259 return success;
246 } 260 }
247 261
  262 + @Override
  263 + @Transactional
  264 + public Result<Object> mergeShipment(List<ShipmentHeader> shipmentHeaderList) {
  265 + if (CollectionUtils.isEmpty(shipmentHeaderList)) {
  266 + return Result.error("至少选择两条记录!");
  267 + }
  268 + // 查询出库单头信息
  269 + LambdaQueryWrapper<ShipmentHeader> shipmentHeaderLambdaQueryWrapper = Wrappers.lambdaQuery();
  270 + shipmentHeaderLambdaQueryWrapper.in(ShipmentHeader::getCode, shipmentHeaderList.stream().map(ShipmentHeader::getCode).collect(Collectors.toList()));
  271 + List<ShipmentHeader> mergeShipmentHeaderList = shipmentHeaderService.list(shipmentHeaderLambdaQueryWrapper);
  272 + if (shipmentHeaderList.size() != mergeShipmentHeaderList.size()) {
  273 + return Result.error("未知错误!");
  274 + }
  275 + if (mergeShipmentHeaderList.size() < 2) {
  276 + return Result.error("至少选择两条有效记录!");
  277 + }
  278 + if (mergeShipmentHeaderList.stream().map(ShipmentHeader::getWarehouseCode).distinct().count() > 1) {
  279 + return Result.error("仓库信息不一致!");
  280 + }
  281 + if (mergeShipmentHeaderList.stream().map(ShipmentHeader::getCompanyCode).distinct().count() > 1) {
  282 + return Result.error("货主信息不一致!");
  283 + }
  284 + if (mergeShipmentHeaderList.stream().map(ShipmentHeader::getType).distinct().count() > 1) {
  285 + return Result.error("出库单类型信息不一致!");
  286 + }
  287 + if (mergeShipmentHeaderList.stream().map(ShipmentHeader::getCustomerCode).distinct().count() > 1) {
  288 + return Result.error("客户信息不一致!");
  289 + }
  290 + // 查询出库单详情
  291 + LambdaQueryWrapper<ShipmentDetail> shipmentDetailLambdaQueryWrapper = Wrappers.lambdaQuery();
  292 + shipmentDetailLambdaQueryWrapper.in(ShipmentDetail::getShipmentCode, shipmentHeaderList.stream().map(ShipmentHeader::getCode).collect(Collectors.toList()));
  293 + List<ShipmentDetail> mergeshipmentDetailList = shipmentDetailService.list(shipmentDetailLambdaQueryWrapper);
  294 +
  295 + ShipmentHeader mergeShipmentHeader = new ShipmentHeader();
  296 + mergeShipmentHeader.setCode(this.createCode(mergeShipmentHeaderList.get(0).getType()));
  297 + mergeShipmentHeader.setWarehouseCode(mergeShipmentHeaderList.get(0).getWarehouseCode());
  298 + mergeShipmentHeader.setType(mergeShipmentHeaderList.get(0).getType());
  299 + mergeShipmentHeader.setCompanyCode(mergeShipmentHeaderList.get(0).getCompanyCode());
  300 + mergeShipmentHeader.setCustomerCode(mergeShipmentHeaderList.get(0).getCustomerCode());
  301 + mergeShipmentHeader.setFirstStatus(QuantityConstant.SHIPMENT_HEADER_BUILD);
  302 + mergeShipmentHeader.setLastStatus(QuantityConstant.SHIPMENT_HEADER_BUILD);
  303 + mergeShipmentHeader.setTotalQty(mergeshipmentDetailList.stream().map(ShipmentDetail::getQty).reduce(BigDecimal.ZERO, BigDecimal::add));
  304 + mergeShipmentHeader.setTotalLines(mergeshipmentDetailList.size());
  305 + mergeShipmentHeader.setRemark("合并单据");
  306 + if (!save(mergeShipmentHeader)) {
  307 + throw new JeecgBootException("新增合并出库单主表失败");
  308 + }
  309 + mergeshipmentDetailList.stream().forEach(t -> {
  310 + t.setId(null);
  311 + t.setShipmentId(mergeShipmentHeader.getId());
  312 + t.setShipmentCode(mergeShipmentHeader.getCode());
  313 + });
  314 + if (!shipmentDetailService.saveBatch(mergeshipmentDetailList)) {
  315 + throw new JeecgBootException("新增合并出库单详情失败");
  316 + }
  317 + // 更新原单据头信息为已合并,关联合并出库单号
  318 + LambdaUpdateWrapper<ShipmentHeader> shipmentHeaderLambdaUpdateWrapper = Wrappers.lambdaUpdate();
  319 + shipmentHeaderLambdaUpdateWrapper.in(ShipmentHeader::getCode, shipmentHeaderList.stream().map(ShipmentHeader::getCode).collect(Collectors.toList()));
  320 + shipmentHeaderLambdaUpdateWrapper.set(ShipmentHeader::getFirstStatus, QuantityConstant.SHIPMENT_HEADER_MERGED)
  321 + .set(ShipmentHeader::getLastStatus, QuantityConstant.SHIPMENT_HEADER_MERGED).set(ShipmentHeader::getMergeShipmentCode, mergeShipmentHeader.getCode());
  322 + if (!shipmentHeaderService.update(shipmentHeaderLambdaUpdateWrapper)) {
  323 + throw new JeecgBootException("更新出库单主表失败");
  324 + }
  325 +
  326 + // 更新原单据详情信息为已合并,关联合并出库单号
  327 + LambdaUpdateWrapper<ShipmentDetail> shipmentDetailLambdaUpdateWrapper = Wrappers.lambdaUpdate();
  328 + shipmentDetailLambdaUpdateWrapper.in(ShipmentDetail::getShipmentCode, shipmentHeaderList.stream().map(ShipmentHeader::getCode).collect(Collectors.toList()));
  329 + shipmentDetailLambdaUpdateWrapper.set(ShipmentDetail::getStatus, QuantityConstant.SHIPMENT_HEADER_MERGED).set(ShipmentDetail::getMergeShipmentCode,
  330 + mergeShipmentHeader.getCode());
  331 + if (!shipmentDetailService.update(shipmentDetailLambdaUpdateWrapper)) {
  332 + throw new JeecgBootException("更新出库单主表失败");
  333 + }
  334 + return Result.OK("合并成功");
  335 + }
248 } 336 }
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/task/taskHeader/controller/TaskHeaderController.java
@@ -387,8 +387,8 @@ public class TaskHeaderController extends HuahengBaseController { @@ -387,8 +387,8 @@ public class TaskHeaderController extends HuahengBaseController {
387 if (taskHeader == null) { 387 if (taskHeader == null) {
388 return Result.error("taskHeader不能为空"); 388 return Result.error("taskHeader不能为空");
389 } 389 }
390 - Result result = huahengMultiHandlerService.sendTaskToWcs(taskHeader);  
391 - return result; 390 + Container container = containerService.getContainerByCode(taskHeader.getContainerCode(), taskHeader.getWarehouseCode());
  391 + return huahengMultiHandlerService.sendTaskToWcs(taskHeader, container == null ? QuantityConstant.DEFAULT_ZONE_CODE : container.getZoneCode());
392 } 392 }
393 393
394 /** 394 /**
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/task/taskHeader/service/impl/TaskHeaderServiceImpl.java
@@ -844,7 +844,7 @@ public class TaskHeaderServiceImpl extends ServiceImpl&lt;TaskHeaderMapper, TaskHea @@ -844,7 +844,7 @@ public class TaskHeaderServiceImpl extends ServiceImpl&lt;TaskHeaderMapper, TaskHea
844 return Result.error("取消任务失败,有前置任务" + preTaskHeader.getId()); 844 return Result.error("取消任务失败,有前置任务" + preTaskHeader.getId());
845 } 845 }
846 if (!taskHeaderService.removeById(taskId)) { 846 if (!taskHeaderService.removeById(taskId)) {
847 - throw new JeecgBootException("取消任务失败, 删除任务失败"); 847 + throw new JeecgBootException("取消任务失败 删除任务失败");
848 } 848 }
849 List<TaskDetail> taskDetailList = taskDetailService.getTaskDetailListByTaskId(taskId); 849 List<TaskDetail> taskDetailList = taskDetailService.getTaskDetailListByTaskId(taskId);
850 if (taskDetailList.size() > 0) { 850 if (taskDetailList.size() > 0) {
@@ -872,6 +872,9 @@ public class TaskHeaderServiceImpl extends ServiceImpl&lt;TaskHeaderMapper, TaskHea @@ -872,6 +872,9 @@ public class TaskHeaderServiceImpl extends ServiceImpl&lt;TaskHeaderMapper, TaskHea
872 throw new JeecgBootException(result.getMessage()); 872 throw new JeecgBootException(result.getMessage());
873 } 873 }
874 } 874 }
  875 + if (!inventoryHeaderService.updateInventoryContainerStatusByContainerCode(taskHeader.getContainerCode(), taskHeader.getWarehouseCode())) {
  876 + throw new JeecgBootException("取消任务失败, 更新库存明细失败");
  877 + }
875 log.info("完成取消任务" + taskHeader.getId()); 878 log.info("完成取消任务" + taskHeader.getId());
876 return result; 879 return result;
877 } 880 }
huaheng-wms-core/src/main/java/org/jeecg/utils/constant/QuantityConstant.java
@@ -108,6 +108,9 @@ public class QuantityConstant { @@ -108,6 +108,9 @@ public class QuantityConstant {
108 108
109 // 过账 109 // 过账
110 public static final Integer SHIPMENT_HEADER_COMPLETED = 800; 110 public static final Integer SHIPMENT_HEADER_COMPLETED = 800;
  111 +
  112 + // 已合并
  113 + public static final Integer SHIPMENT_HEADER_MERGED = 810;
111 114
112 // 回传失败 115 // 回传失败
113 public static final Integer SHIPMENT_HEADER_RETURN_ERROR = 850; 116 public static final Integer SHIPMENT_HEADER_RETURN_ERROR = 850;
@@ -616,4 +619,7 @@ public class QuantityConstant { @@ -616,4 +619,7 @@ public class QuantityConstant {
616 * 受控,受控的库存详情不能出库 619 * 受控,受控的库存详情不能出库
617 */ 620 */
618 public static final int CONTROLLER_ENABLE = 1; 621 public static final int CONTROLLER_ENABLE = 1;
  622 +
  623 + /** 默认库区编码 */
  624 + public static final String DEFAULT_ZONE_CODE = "Default";
619 } 625 }
huaheng-wms-core/src/main/resources/logback-spring.xml
@@ -58,11 +58,11 @@ @@ -58,11 +58,11 @@
58 <appender-ref ref="STDOUT" /> 58 <appender-ref ref="STDOUT" />
59 <appender-ref ref="FILE" /> 59 <appender-ref ref="FILE" />
60 </logger> 60 </logger>
61 - <logger name="jdbc.sqlonly" additivity="false" level="info"> 61 + <logger name="jdbc.sqlonly" additivity="false" level="off">
62 <appender-ref ref="STDOUT" /> 62 <appender-ref ref="STDOUT" />
63 <appender-ref ref="FILE" /> 63 <appender-ref ref="FILE" />
64 </logger> 64 </logger>
65 - <logger name="jdbc.sqltiming" additivity="false" level="off"> 65 + <logger name="jdbc.sqltiming" additivity="false" level="info">
66 <appender-ref ref="STDOUT" /> 66 <appender-ref ref="STDOUT" />
67 <appender-ref ref="FILE" /> 67 <appender-ref ref="FILE" />
68 </logger> 68 </logger>