Commit f97dee9338324bb5fd3d7f9f9007d3d4a45643cd
1 parent
2693f41e
悬架库出库
Showing
15 changed files
with
477 additions
and
25 deletions
ant-design-vue-jeecg/src/api/api.js
... | ... | @@ -281,6 +281,8 @@ export const quickReceipt = (params) => postAction('/task/taskHeader/quickReceip |
281 | 281 | export const shipmentInventoryHeader = (params) => postAction('/inventory/inventoryHeader/shipmentInventoryHeader', params) |
282 | 282 | //快速出库,批量快速出库存详情 |
283 | 283 | export const shipmentInventoryDetail = (params) => postAction('/inventory/inventoryHeader/shipmentInventoryDetail', params) |
284 | +//悬臂库快速出库,批量快速出库存详情 | |
285 | +export const cantaleverShipmentInventoryDetail = (params) => postAction('/inventory/inventoryHeader/cantaleverShipmentInventoryDetail', params) | |
284 | 286 | //平库快速出库,通过库存ID |
285 | 287 | export const flatQuickShipment = (params) => postAction('/shipment/shipmentCombination/flatQuickShipment', params) |
286 | 288 | //呼叫入库托盘 |
... | ... |
ant-design-vue-jeecg/src/views/system/inventory/SimpleInventoryDetailList.vue
... | ... | @@ -157,6 +157,7 @@ |
157 | 157 | <a-button v-has="'inventoryHeader:flatReceipt'" @click="expressStorage()" type="primary">平库入库</a-button> |
158 | 158 | <a-button v-has="'inventoryHeader:flatShipment'" @click="expressDelivery()" type="primary">平库出库</a-button> |
159 | 159 | <a-button v-has="'taskHeader:transfer'" @click="createTransferTaskCantalever()" type="primary">悬臂库移库</a-button> |
160 | + <a-button v-has="'inventoryHeader:quickShipmentInventoryHeader'" @click='cantaleverQuickShipment()' type='primary'>悬臂库出库</a-button> | |
160 | 161 | <!-- 高级查询区域 --> |
161 | 162 | <j-super-query :fieldList="superFieldList" v-has="'inventoryDetail:superQuery'" |
162 | 163 | @handleSuperQuery="handleSuperQuery"/> |
... | ... | @@ -263,6 +264,7 @@ |
263 | 264 | |
264 | 265 | <simple-inventory-detail-modal ref="modalForm" @ok="modalFormOk"></simple-inventory-detail-modal> |
265 | 266 | <quick-shipment-detail-modal ref='quickShipmentDetailModal' @ok="modalFormOk"></quick-shipment-detail-modal> |
267 | + <CantaleverShipmentDetailModal ref="cantaleverShipmentDetailModal" @ok="modalFormOk"></CantaleverShipmentDetailModal> | |
266 | 268 | <quality-inventory-detail-modal ref="qualityInventoryDetailModal" @ok="modalFormOk"></quality-inventory-detail-modal> |
267 | 269 | <ExpressStorageModal ref="ExpressStorageModal" @ok="modalFormOk"></ExpressStorageModal> |
268 | 270 | <ExpressDeliveryModal ref="ExpressDeliveryModal" @ok="modalFormOk"></ExpressDeliveryModal> |
... | ... | @@ -289,11 +291,13 @@ import TransferTaskCantaleverModal from "@views/system/task/modules/TransferTask |
289 | 291 | import Vue from "vue"; |
290 | 292 | import {ACCESS_TOKEN} from "@/store/mutation-types"; |
291 | 293 | import store from "@/store"; |
294 | +import CantaleverShipmentDetailModal from "@views/system/shipment/modules/CantaleverShipmentDetailModal.vue"; | |
292 | 295 | |
293 | 296 | export default { |
294 | 297 | name: 'SimpleInventoryDetailList', |
295 | 298 | mixins: [JeecgListMixin, mixinDevice], |
296 | 299 | components: { |
300 | + CantaleverShipmentDetailModal, | |
297 | 301 | ExpressStorageModal, |
298 | 302 | ExpressDeliveryModal, |
299 | 303 | QualityInventoryDetailModal, |
... | ... | @@ -789,6 +793,28 @@ export default { |
789 | 793 | this.selectedRowKeys = selectedRowKeys; |
790 | 794 | this.selectRecord = selectionRows; |
791 | 795 | }, |
796 | + cantaleverQuickShipment() { | |
797 | + if (this.selectedRowKeys.length <= 0) { | |
798 | + this.$message.warning('请选择一条记录!'); | |
799 | + } else { | |
800 | + let zoneCodes = this.selectRecord.map(row => row.zoneCode); | |
801 | + if (new Set(zoneCodes).size !== 1) { | |
802 | + this.$message.warning('所选数据非同库区'); | |
803 | + return; | |
804 | + } | |
805 | + const isInList = this.selectRecord.some(row => { | |
806 | + if (row.zoneType != "L") { | |
807 | + return true | |
808 | + } | |
809 | + }) | |
810 | + if(isInList) { | |
811 | + this.$message.warning('所选数据非立库区类型'); | |
812 | + return; | |
813 | + } | |
814 | + this.$refs.cantaleverShipmentDetailModal.edit(this.selectRecord); | |
815 | + this.$refs.cantaleverShipmentDetailModal.title = '悬臂库出库'; | |
816 | + } | |
817 | + }, | |
792 | 818 | quickShipment() { |
793 | 819 | if (this.selectedRowKeys.length <= 0) { |
794 | 820 | this.$message.warning('请选择一条记录!'); |
... | ... |
ant-design-vue-jeecg/src/views/system/shipment/modules/CantaleverShipmentDetailModal.vue
0 → 100644
1 | +<template> | |
2 | + <j-modal | |
3 | + :title="title" | |
4 | + :width="width" | |
5 | + :visible="visible" | |
6 | + :confirmLoading="confirmLoading" | |
7 | + switchFullscreen | |
8 | + @ok="handleOk" | |
9 | + @cancel="handleCancel" | |
10 | + cancelText="关闭" | |
11 | + > | |
12 | + <a-spin :spinning="confirmLoading"> | |
13 | + <a-form-model ref="form" :model="model" :rules="validatorRules"> | |
14 | + <a-row> | |
15 | + <a-col :span="24"> | |
16 | + <a-form-model-item label="出库口" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="outPortCode"> | |
17 | + <a-select | |
18 | + show-search | |
19 | + placeholder="请选择出库口" | |
20 | + option-filter-prop="children" | |
21 | + v-model="model.outPortCode" | |
22 | + > | |
23 | + <a-select-option v-for="item in portList" :key="item.name" :value="item.code"> | |
24 | + {{ item.name }} | |
25 | + </a-select-option> | |
26 | + </a-select> | |
27 | + </a-form-model-item> | |
28 | + </a-col> | |
29 | + </a-row> | |
30 | + </a-form-model> | |
31 | + </a-spin> | |
32 | + <a-table ref="table" rowKey="id" size="middle" :columns="columns" :dataSource="dataSource" :pagination="false"> | |
33 | + <span slot="action" slot-scope="text, record"> | |
34 | + <a-input-number placeholder="" v-model="record.shipmentQty" :value="text" /> | |
35 | + </span> | |
36 | + | |
37 | + | |
38 | +<!-- <span slot="inventoryStatus" slot-scope="inventoryStatus">--> | |
39 | +<!-- <a-tag :key="inventoryStatus" color="blue" :color="getStatusColor(inventoryStatus)">--> | |
40 | +<!-- {{ solutionInvStatus(inventoryStatus) }}--> | |
41 | +<!-- </a-tag>--> | |
42 | +<!-- </span>--> | |
43 | + | |
44 | + </a-table> | |
45 | + </j-modal> | |
46 | +</template> | |
47 | + | |
48 | +<script> | |
49 | +import { | |
50 | + cantaleverShipmentInventoryDetail, | |
51 | + getZoneList, | |
52 | + selectOutPort, | |
53 | + selectPickPort, | |
54 | + shipmentInventoryDetail | |
55 | +} from '@/api/api' | |
56 | +import {getAction} from "@api/manage"; | |
57 | + | |
58 | +export default { | |
59 | + name: 'CantaleverShipmentDetailModal', | |
60 | + components: {}, | |
61 | + data() { | |
62 | + return { | |
63 | + title: '操作', | |
64 | + width: 800, | |
65 | + portList: [], | |
66 | + inventoryDetailList: [], | |
67 | + dataSource: [], | |
68 | + querySource: {}, | |
69 | + visible: false, | |
70 | + model: {}, | |
71 | + labelCol: { | |
72 | + xs: { span: 24 }, | |
73 | + sm: { span: 5 } | |
74 | + }, | |
75 | + wrapperCol: { | |
76 | + xs: { span: 24 }, | |
77 | + sm: { span: 16 } | |
78 | + }, | |
79 | + columns: [ | |
80 | + { | |
81 | + title: '容器编码', | |
82 | + dataIndex: 'containerCode', | |
83 | + align: 'center', | |
84 | + }, | |
85 | + { | |
86 | + title: '物料编码', | |
87 | + dataIndex: 'materialCode', | |
88 | + align: 'center', | |
89 | + width: 124 | |
90 | + }, | |
91 | + { | |
92 | + title: '物料名称', | |
93 | + dataIndex: 'materialName', | |
94 | + align: 'center', | |
95 | + width: 96 | |
96 | + }, | |
97 | + // { | |
98 | + // title: '库存状态', | |
99 | + // align: 'center', | |
100 | + // dataIndex: 'inventoryStatus_dictText', | |
101 | + // scopedSlots: {customRender: 'inventoryStatus_dictText'} | |
102 | + // }, | |
103 | + { | |
104 | + title: '批次', | |
105 | + dataIndex: 'batch', | |
106 | + align: 'center' | |
107 | + }, | |
108 | + { | |
109 | + title: '位置', | |
110 | + dataIndex: 'position', | |
111 | + align: 'center' | |
112 | + }, | |
113 | + { | |
114 | + title: '库存数量', | |
115 | + dataIndex: 'qty', | |
116 | + align: 'center', | |
117 | + width: 80 | |
118 | + }, | |
119 | + { | |
120 | + title: '出库数量', | |
121 | + dataIndex: 'shipmentQty', | |
122 | + align: 'center', | |
123 | + key: 'action', | |
124 | + scopedSlots: { customRender: 'action' } | |
125 | + }, | |
126 | + ], | |
127 | + url: { | |
128 | + pageByMainIds: "/inventory/inventoryDetail/pageByMainIds", | |
129 | + }, | |
130 | + // 选择用户查询条件配置 | |
131 | + selectUserQueryConfig: [], | |
132 | + confirmLoading: false, | |
133 | + validatorRules: { | |
134 | + outPortCode: [{ required: true, message: '请选择出库口!' }] | |
135 | + } | |
136 | + } | |
137 | + }, | |
138 | + created() { | |
139 | + //备份model原始值 | |
140 | + this.modelDefault = JSON.parse(JSON.stringify(this.model)) | |
141 | + }, | |
142 | + methods: { | |
143 | + add() { | |
144 | + this.edit(this.modelDefault) | |
145 | + }, | |
146 | + edit(record) { | |
147 | + this.visible = true | |
148 | + this.model.containerCode = record[0].containerCode | |
149 | + this.inventoryDetailList = record | |
150 | + this.getPortList() | |
151 | + this.searchInventoryDetailList(); | |
152 | + }, | |
153 | + close() { | |
154 | + this.$emit('close') | |
155 | + this.visible = false | |
156 | + this.$refs.form.clearValidate() | |
157 | + }, | |
158 | + getPortList() { | |
159 | + this.querySource.containerCode = this.model.containerCode | |
160 | + selectOutPort(this.querySource).then(res => { | |
161 | + if (res.success) { | |
162 | + this.portList = res.result | |
163 | + this.visible = true | |
164 | + if (this.portList.length == 1) { | |
165 | + this.model.outPortCode = this.portList[0].code; | |
166 | + } | |
167 | + } | |
168 | + }) | |
169 | + }, | |
170 | + searchInventoryDetailList() { | |
171 | + let params = { | |
172 | + inventoryHeaderIds:"" | |
173 | + }; | |
174 | + this.inventoryDetailList.forEach(x=>{ | |
175 | + params.inventoryHeaderIds+= + x.inventoryHeaderId + "," | |
176 | + }) | |
177 | + getAction(this.url.pageByMainIds, params).then((res) => { | |
178 | + this.dataSource = res.result.records | |
179 | + this.inventoryDetailList = res.result.records | |
180 | + }) | |
181 | + }, | |
182 | + handleOk() { | |
183 | + if (this.model.outPortCode === '') { | |
184 | + this.$message.warning('请选择出库口') | |
185 | + } | |
186 | + this.inventoryDetailList.forEach(x => { | |
187 | + x['toPortCode'] = this.model.outPortCode | |
188 | + }) | |
189 | + cantaleverShipmentInventoryDetail(this.inventoryDetailList).then(res => { | |
190 | + if (res.success) { | |
191 | + this.$message.success(res.message) | |
192 | + this.$emit('ok') | |
193 | + } else { | |
194 | + this.$message.error(res.message) | |
195 | + } | |
196 | + }) | |
197 | + this.$emit('ok', this.model.outPortCode) | |
198 | + this.close() | |
199 | + }, | |
200 | + handleCancel() { | |
201 | + this.close() | |
202 | + } | |
203 | + } | |
204 | +} | |
205 | +</script> | |
0 | 206 | \ No newline at end of file |
... | ... |
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/api/wcs/service/LocationAllocationService.java
... | ... | @@ -26,7 +26,7 @@ public interface LocationAllocationService { |
26 | 26 | * 单伸位库位分配 |
27 | 27 | */ |
28 | 28 | String singleRkCantalever(String zoneCode, List<Integer> roadWays, int high, String warehouseCode, List<String> locationTypeCodeList, String materialAreaCode, |
29 | - String materialCode); | |
29 | + List<String> materialCodeList); | |
30 | 30 | |
31 | 31 | /** |
32 | 32 | * 获取可用巷道 |
... | ... |
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/api/wcs/service/LocationAllocationServiceImpl.java
... | ... | @@ -105,7 +105,9 @@ public class LocationAllocationServiceImpl implements LocationAllocationService |
105 | 105 | bypass); |
106 | 106 | case QuantityConstant.SINGLE_FORK: |
107 | 107 | if (zoneCode.equals(QuantityConstant.ZONE_B)) { |
108 | - return locationAllocationService.singleRkCantalever(zoneCode, raodWays, high, warehouseCode, mergelocationTypeCodeList, materialAreaCode, materialCode); | |
108 | + List<String> materialCodeList = new ArrayList<>(); | |
109 | + materialCodeList.add(materialCode); | |
110 | + return locationAllocationService.singleRkCantalever(zoneCode, raodWays, high, warehouseCode, mergelocationTypeCodeList, materialAreaCode, materialCodeList); | |
109 | 111 | } else { |
110 | 112 | return locationAllocationService.singleRk(zoneCode, raodWays, high, warehouseCode, mergelocationTypeCodeList, materialAreaCode, materialCode); |
111 | 113 | } |
... | ... | @@ -282,21 +284,26 @@ public class LocationAllocationServiceImpl implements LocationAllocationService |
282 | 284 | |
283 | 285 | @Override |
284 | 286 | @Transactional(rollbackFor = Exception.class) |
285 | - public String singleRkCantalever(String zoneCode, List<Integer> roadWays, int high, String warehouseCode, List<String> locationTypeCodeList, String materialAreaCode, String materialCode) { | |
287 | + public String singleRkCantalever(String zoneCode, List<Integer> roadWays, int high, String warehouseCode, List<String> locationTypeCodeList, String materialAreaCode, List<String> materialCodeList) { | |
286 | 288 | if (CollectionUtils.isEmpty(roadWays)) { |
287 | 289 | roadWays = locationService.getRoadWayByZoneCode(zoneCode, warehouseCode); |
288 | 290 | } |
289 | 291 | List<Integer> removeRoadWays = new ArrayList<>(); |
290 | - if (StringUtils.isEmpty(materialCode)) { | |
292 | + if (materialCodeList == null) { | |
291 | 293 | throw new JeecgBootException("分配库位时, 入库物料信息为空"); |
292 | 294 | } |
293 | - Material material = materialService.getMaterialByCode(materialCode); | |
294 | - if (material == null) { | |
295 | - throw new JeecgBootException("分配库位时, 没有找到入库物料信息" + materialCode); | |
295 | + int thickness = 0; | |
296 | + String materialCode = null; | |
297 | + for (int i=0; i < materialCodeList.size(); i++) { | |
298 | + materialCode = materialCodeList.get(i); | |
299 | + Material material = materialService.getMaterialByCode(materialCode); | |
300 | + if (material == null) { | |
301 | + throw new JeecgBootException("分配库位时, 没有找到入库物料信息" + materialCode); | |
302 | + } | |
303 | + int materialThickness = material.getThickness(); | |
304 | + int materialGap = material.getGap(); | |
305 | + thickness = thickness + materialThickness + materialGap; | |
296 | 306 | } |
297 | - int materialThickness = material.getThickness(); | |
298 | - int materialGap = material.getGap(); | |
299 | - int thickness = materialThickness + materialGap; | |
300 | 307 | // 寻找可用巷道,空闲的空库位低于设定值,那么这个巷道就不能用来分配库位 |
301 | 308 | for (Integer roadWay : roadWays) { |
302 | 309 | LambdaQueryWrapper<Location> locationLambdaQueryWrapper = Wrappers.lambdaQuery(); |
... | ... |
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/api/wcs/service/WcsServiceImpl.java
... | ... | @@ -57,6 +57,7 @@ import javax.annotation.Resource; |
57 | 57 | import java.math.BigDecimal; |
58 | 58 | import java.net.SocketException; |
59 | 59 | import java.util.ArrayList; |
60 | +import java.util.Collections; | |
60 | 61 | import java.util.Date; |
61 | 62 | import java.util.List; |
62 | 63 | import java.util.stream.Collectors; |
... | ... | @@ -475,7 +476,7 @@ public class WcsServiceImpl implements WcsService { |
475 | 476 | if (!direction) { |
476 | 477 | // 出库性质的任务圆库位不能为空 |
477 | 478 | if (StringUtils.isEmpty(fromLocationCode)) { |
478 | - return Result.error("任务下发 ,起始库位为空"); | |
479 | + return Result.error("任务下发, 起始库位为空"); | |
479 | 480 | } |
480 | 481 | int rowFlag = fromLocation.getRowFlag(); |
481 | 482 | if (rowFlag == QuantityConstant.ROW_OUT) { |
... | ... | @@ -529,6 +530,50 @@ public class WcsServiceImpl implements WcsService { |
529 | 530 | } |
530 | 531 | } |
531 | 532 | |
533 | + if (!direction) { | |
534 | + String fromZoneCode = fromLocation.getZoneCode(); | |
535 | + if (fromZoneCode.equals(QuantityConstant.ZONE_B)) { | |
536 | + List<TaskDetail> taskDetailList = taskDetailService.getTaskDetailListByTaskId(taskHeader.getId()); | |
537 | + if (CollectionUtils.isNotEmpty(taskDetailList)) { | |
538 | + List<Integer> positionList = taskDetailList.stream().map(TaskDetail::getPosition).collect(Collectors.toList()); | |
539 | + Integer minTaskPosition = Collections.min(positionList); | |
540 | + List<InventoryDetail> inventoryDetailList = inventoryDetailService.getInventoryDetailListByLocationCodeAndNotPosition(fromLocationCode, positionList, warehouseCode); | |
541 | + List<Integer> inventoryPositionList = inventoryDetailList.stream().map(InventoryDetail::getPosition).collect(Collectors.toList()); | |
542 | + Integer minInventoryPosition = Collections.min(inventoryPositionList); | |
543 | + if (minTaskPosition < minInventoryPosition) { | |
544 | + TaskHeader unCompleteTaskHeader = taskHeaderService.getUnCompleteTransferTaskByFromLocationCode(fromLocationCode, warehouseCode); | |
545 | + if (unCompleteTaskHeader != null) { | |
546 | + preTaskNo = unCompleteTaskHeader.getId(); | |
547 | + boolean success = taskHeaderService.updatePreTaskNoById(preTaskNo, taskHeader.getId()); | |
548 | + if (!success) { | |
549 | + throw new JeecgBootException("任务下发, 更新任务前置任务号失败"); | |
550 | + } | |
551 | + } else { | |
552 | + List<String> locationTypeCodeList = new ArrayList<>(); | |
553 | + locationTypeCodeList.add(fromLocation.getLocationTypeCode()); | |
554 | + List<Integer> roadWays = new ArrayList<>(); | |
555 | + roadWays.add(fromLocation.getRoadWay()); | |
556 | + List<String> materialCodeList = inventoryDetailList.stream().map(InventoryDetail::getMaterialCode).collect(Collectors.toList()); | |
557 | + String locationCode = locationAllocationService.singleRkCantalever( fromZoneCode, roadWays, 0, warehouseCode, | |
558 | + locationTypeCodeList, null, materialCodeList); | |
559 | + Result<TaskHeader> result = taskHeaderService.createTransferTaskCantalever(inventoryDetailList, locationCode, warehouseCode); | |
560 | + if (!result.isSuccess()) { | |
561 | + throw new JeecgBootException("任务下发 " + result.getMessage()); | |
562 | + } | |
563 | + preTaskNo = result.getResult().getId(); | |
564 | + taskHeader.setPreTaskNo(preTaskNo); | |
565 | + boolean success = taskHeaderService.updatePreTaskNoById(preTaskNo, taskHeader.getId()); | |
566 | + if (!success) { | |
567 | + throw new JeecgBootException("任务下发, 更新任务状态失败"); | |
568 | + } | |
569 | + return Result.error("任务下发, 先执行移库任务"); | |
570 | + } | |
571 | + | |
572 | + } | |
573 | + } | |
574 | + } | |
575 | + } | |
576 | + | |
532 | 577 | // 下发任务 |
533 | 578 | WcsTask wcsTask = new WcsTask(); |
534 | 579 | wcsTask.setTaskNo(taskHeader.getId().toString()); |
... | ... |
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/inventory/inventoryHeader/controller/InventoryHeaderController.java
... | ... | @@ -420,6 +420,19 @@ public class InventoryHeaderController extends JeecgController<InventoryHeader, |
420 | 420 | return inventoryHeaderService.shipmentInventoryDetail(inventoryDetailList, warehouseCode); |
421 | 421 | } |
422 | 422 | |
423 | + @AutoLog(value = "库存头-批量出库存详情", operateType = 4) | |
424 | + @ApiOperation(value = "批量出库存详情", notes = "批量出库存详情") | |
425 | + @ApiLogger(apiName = "批量出库存详情") | |
426 | + @PostMapping("/cantaleverShipmentInventoryDetail") | |
427 | + public Result cantaleverShipmentInventoryDetail(@RequestBody List<InventoryDetail> inventoryDetailList, HttpServletRequest req) { | |
428 | + if (StringUtils.isEmpty(inventoryDetailList)) { | |
429 | + return Result.error("库存明细为空"); | |
430 | + } | |
431 | + String warehouseCode = HuahengJwtUtil.getWarehouseCodeByToken(req); | |
432 | + return inventoryHeaderService.cantaleverShipmentInventoryDetail(inventoryDetailList, warehouseCode); | |
433 | + } | |
434 | + | |
435 | + | |
423 | 436 | @AutoLog(value = "批量出库存详情", operateType = 4) |
424 | 437 | @ApiOperation(value = "批量出库存详情", notes = "批量出库存详情") |
425 | 438 | @PostMapping("/decuceInventoryDetail") |
... | ... |
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/inventory/inventoryHeader/service/IInventoryDetailService.java
... | ... | @@ -35,6 +35,8 @@ public interface IInventoryDetailService extends IService<InventoryDetail> { |
35 | 35 | |
36 | 36 | List<InventoryDetail> getInventoryDetailListByLocationCode(String locationCode, String warehouseCode); |
37 | 37 | |
38 | + List<InventoryDetail> getInventoryDetailListByLocationCodeAndNotPosition(String locationCode, List<Integer> positionList,String warehouseCode); | |
39 | + | |
38 | 40 | List<InventoryDetail> getInventoryDetailListByMaterialCode(String materialCode, String warehouseCode); |
39 | 41 | |
40 | 42 | List<InventoryDetail> getInventoryDetailListByMaterialCodeAndZoneCode(String materialCode, String zoneCode, String warehouseCode); |
... | ... |
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/inventory/inventoryHeader/service/IInventoryHeaderService.java
... | ... | @@ -50,6 +50,8 @@ public interface IInventoryHeaderService extends IService<InventoryHeader> { |
50 | 50 | |
51 | 51 | Result shipmentInventoryDetail(List<InventoryDetail> inventoryDetailList, String warehouseCode); |
52 | 52 | |
53 | + Result cantaleverShipmentInventoryDetail(List<InventoryDetail> inventoryDetailList, String warehouseCode); | |
54 | + | |
53 | 55 | Result decuceInventoryDetail(List<InventoryDetail> inventoryDetailList, String warehouseCode); |
54 | 56 | |
55 | 57 | boolean updateInventory(String containerCode, String locationCode, String warehouseCode); |
... | ... |
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/inventory/inventoryHeader/service/impl/InventoryDetailServiceImpl.java
... | ... | @@ -166,6 +166,16 @@ public class InventoryDetailServiceImpl extends ServiceImpl<InventoryDetailMappe |
166 | 166 | } |
167 | 167 | |
168 | 168 | @Override |
169 | + public List<InventoryDetail> getInventoryDetailListByLocationCodeAndNotPosition(String locationCode, List<Integer> positionList, String warehouseCode) { | |
170 | + LambdaQueryWrapper<InventoryDetail> inventoryDetailLambdaQueryWrapper = Wrappers.lambdaQuery(); | |
171 | + inventoryDetailLambdaQueryWrapper.eq(InventoryDetail::getLocationCode, locationCode).eq(InventoryDetail::getWarehouseCode, warehouseCode) | |
172 | + .notIn(InventoryDetail::getPosition, positionList) | |
173 | + .eq(InventoryDetail::getEnable, QuantityConstant.INVENTORY_DETAIL_STATUS_ENABLE); | |
174 | + List<InventoryDetail> inventoryDetailList = list(inventoryDetailLambdaQueryWrapper); | |
175 | + return inventoryDetailList; | |
176 | + } | |
177 | + | |
178 | + @Override | |
169 | 179 | public List<InventoryDetail> getInventoryDetailListByMaterialCode(String materialCode, String warehouseCode) { |
170 | 180 | LambdaQueryWrapper<InventoryDetail> inventoryDetailLambdaQueryWrapper = Wrappers.lambdaQuery(); |
171 | 181 | inventoryDetailLambdaQueryWrapper.eq(InventoryDetail::getMaterialCode, materialCode).eq(InventoryDetail::getWarehouseCode, warehouseCode); |
... | ... |
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/inventory/inventoryHeader/service/impl/InventoryHeaderServiceImpl.java
... | ... | @@ -411,6 +411,108 @@ public class InventoryHeaderServiceImpl extends ServiceImpl<InventoryHeaderMappe |
411 | 411 | return Result.OK("批量快速出库成功"); |
412 | 412 | } |
413 | 413 | |
414 | + @Override | |
415 | + @Transactional(rollbackFor = Exception.class) | |
416 | + public Result cantaleverShipmentInventoryDetail(List<InventoryDetail> inventoryDetailList, String warehouseCode) { | |
417 | + if (StringUtils.isEmpty(inventoryDetailList)) { | |
418 | + return Result.error("批量快速出库,所选库存详情为空"); | |
419 | + } | |
420 | + String toPortCode = inventoryDetailList.get(0).getToPortCode(); | |
421 | + if (StringUtils.isEmpty(toPortCode)) { | |
422 | + return Result.error("批量快速出库,出库站台编码为空"); | |
423 | + } | |
424 | + String zoneCode = inventoryDetailList.get(0).getZoneCode(); | |
425 | + inventoryDetailList = | |
426 | + inventoryDetailList.stream().filter((item) -> item.getContainerStatus().equals(QuantityConstant.STATUS_CONTAINER_EMPTY)).collect(Collectors.toList()); | |
427 | + inventoryDetailList = inventoryDetailList.stream().filter((item) -> item.getShipmentQty() != null).collect(Collectors.toList()); | |
428 | + if (StringUtils.isEmpty(inventoryDetailList)) { | |
429 | + return Result.error("批量快速出库, 排除锁定库存后没有可出库存详情"); | |
430 | + } | |
431 | + if (inventoryDetailList.size() != 1) { | |
432 | + return Result.error("批量快速出库, 可出库存详情数量只能为1"); | |
433 | + } | |
434 | + String zoneType = null; | |
435 | + if (StringUtils.isNotEmpty(zoneCode)) { | |
436 | + Zone zone = zoneService.getZoneByCode(zoneCode, warehouseCode); | |
437 | + if (zone == null) { | |
438 | + return Result.error("出库单下发, 没有找到库区"); | |
439 | + } | |
440 | + zoneType = zone.getType(); | |
441 | + } | |
442 | + String companyCode = inventoryDetailList.get(0).getCompanyCode(); | |
443 | + ShipmentHeader shipmentHeader = new ShipmentHeader(); | |
444 | + shipmentHeader.setWarehouseCode(warehouseCode); | |
445 | + shipmentHeader.setCompanyCode(companyCode); | |
446 | + shipmentHeader.setZoneCode(zoneCode); | |
447 | + shipmentHeader.setZoneType(zoneType); | |
448 | + shipmentHeader.setType(QuantityConstant.SHIPMENT_BILL_TYPE_QTC); | |
449 | + shipmentHeader.setRemark("快速出库"); | |
450 | + Result result = shipmentHeaderService.saveShipmentHeader(shipmentHeader); | |
451 | + if (!result.isSuccess()) { | |
452 | + throw new JeecgBootException("批量快速出库,创建出库单失败:".concat(result.getMessage())); | |
453 | + } | |
454 | + | |
455 | + List<ShipmentDetail> shipmentDetailList = new ArrayList<>(); | |
456 | + for (InventoryDetail inventoryDetail : inventoryDetailList) { | |
457 | + ShipmentDetail shipmentDetail = new ShipmentDetail(); | |
458 | + shipmentDetail.setShipmentId(shipmentHeader.getId()); | |
459 | + shipmentDetail.setMaterialCode(inventoryDetail.getMaterialCode()); | |
460 | + shipmentDetail.setInventoryStatus(inventoryDetail.getInventoryStatus()); | |
461 | + shipmentDetail.setZoneCode(inventoryDetail.getZoneCode()); | |
462 | + shipmentDetail.setQty(inventoryDetail.getShipmentQty()); | |
463 | + shipmentDetail.setBatch(inventoryDetail.getBatch()); | |
464 | + result = shipmentDetailService.saveShipmentDetail(shipmentDetail); | |
465 | + if (!result.isSuccess()) { | |
466 | + throw new JeecgBootException("批量快速出库,创建出库详情失败:".concat(result.getMessage())); | |
467 | + } | |
468 | + shipmentDetail = shipmentDetailService.getById(shipmentDetail.getId()); | |
469 | + shipmentDetailList.add(shipmentDetail); | |
470 | + } | |
471 | + | |
472 | + for (int i = 0; i < inventoryDetailList.size(); i++) { | |
473 | + InventoryDetail inventoryDetail = inventoryDetailList.get(i); | |
474 | + ShipmentDetail shipmentDetail = shipmentDetailList.get(i); | |
475 | + CombinationModel combinationModel = new CombinationModel(); | |
476 | + combinationModel.setInventoryDetail(inventoryDetail); | |
477 | + combinationModel.setShipmentDetail(shipmentDetail); | |
478 | + combinationModel.setShipQty(inventoryDetail.getShipmentQty()); | |
479 | + result = shipmentCombinationService.combination(combinationModel); | |
480 | + if (!result.isSuccess()) { | |
481 | + throw new JeecgBootException("批量快速出库,配盘失败:".concat(result.getMessage())); | |
482 | + } | |
483 | + } | |
484 | + | |
485 | + List<ShipmentContainerDetail> shipmentContainerDetailList = | |
486 | + shipmentContainerDetailService.getShipmentContainerDetailListByShipmentCode(shipmentHeader.getCode()); | |
487 | + if (StringUtils.isEmpty(shipmentContainerDetailList)) { | |
488 | + throw new JeecgBootException("批量快速出库,根据出库单没有找到配盘详情"); | |
489 | + } | |
490 | + | |
491 | + List<Integer> shipmentContainerHeaderIdList = | |
492 | + shipmentContainerDetailList.stream().map(ShipmentContainerDetail::getShipmentContainerId).distinct().collect(Collectors.toList()); | |
493 | + long shipmentOrder = System.currentTimeMillis(); | |
494 | + int sequenceNumber = shipmentContainerHeaderIdList.size(); | |
495 | + int sequence = 0; | |
496 | + for (int shipmentContainerId : shipmentContainerHeaderIdList) { | |
497 | + sequence++; | |
498 | + ShipmentContainerHeader shipmentContainerHeader = shipmentContainerHeaderService.getById(shipmentContainerId); | |
499 | + if (shipmentContainerHeader == null) { | |
500 | + throw new JeecgBootException("批量快速出库,没有找到出库表头:" + shipmentContainerId); | |
501 | + } | |
502 | + shipmentContainerHeader.setToPort(toPortCode); | |
503 | + boolean success = shipmentContainerHeaderService.updateById(shipmentContainerHeader); | |
504 | + if (!success) { | |
505 | + throw new JeecgBootException("批量快速出库,更新出库组盘头失败"); | |
506 | + } | |
507 | + result = shipmentCombinationService.createShipmentTask(shipmentContainerHeader, QuantityConstant.TASK_TYPE_WHOLESHIPMENT, warehouseCode, shipmentOrder, sequence, sequenceNumber); | |
508 | + if (!result.isSuccess()) { | |
509 | + throw new JeecgBootException(result.getMessage()); | |
510 | + } | |
511 | + } | |
512 | + | |
513 | + return Result.OK("批量快速出库成功"); | |
514 | + } | |
515 | + | |
414 | 516 | /** |
415 | 517 | * 批量出库存详情 |
416 | 518 | * @param inventoryDetailList |
... | ... |
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/shipment/shipmentCombination/service/impl/ShipmentCombinationServiceImpl.java
... | ... | @@ -914,6 +914,7 @@ public class ShipmentCombinationServiceImpl implements IShipmentCombinationServi |
914 | 914 | shipmentContainerDetail.setMaterialName(shipmentDetail.getMaterialName()); |
915 | 915 | shipmentContainerDetail.setMaterialSpec(shipmentDetail.getMaterialSpec()); |
916 | 916 | shipmentContainerDetail.setMaterialUnit(shipmentDetail.getMaterialUnit()); |
917 | + shipmentContainerDetail.setPosition(inventoryDetail.getPosition()); | |
917 | 918 | shipmentContainerDetail.setQty(shipmentQty); |
918 | 919 | shipmentContainerDetail.setBatch(shipmentDetail.getBatch()); |
919 | 920 | shipmentContainerDetail.setLot(shipmentDetail.getLot()); |
... | ... | @@ -1616,6 +1617,7 @@ public class ShipmentCombinationServiceImpl implements IShipmentCombinationServi |
1616 | 1617 | taskDetail.setMaterialSpec(shipmentContainerDetail.getMaterialSpec()); |
1617 | 1618 | taskDetail.setMaterialName(shipmentContainerDetail.getMaterialName()); |
1618 | 1619 | taskDetail.setMaterialUnit(shipmentContainerDetail.getMaterialUnit()); |
1620 | + taskDetail.setPosition(shipmentContainerDetail.getPosition()); | |
1619 | 1621 | taskDetail.setQty(shipmentContainerDetail.getQty()); |
1620 | 1622 | taskDetailList.add(taskDetail); |
1621 | 1623 | } |
... | ... |
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/shipment/shipmentContainerHeader/entity/ShipmentContainerDetail.java
... | ... | @@ -112,6 +112,10 @@ public class ShipmentContainerDetail implements Serializable { |
112 | 112 | @Excel(name = "序列号", width = 15) |
113 | 113 | @ApiModelProperty(value = "序列号") |
114 | 114 | private String sn; |
115 | + /** 位置 */ | |
116 | + @Excel(name = "位置", width = 15) | |
117 | + @ApiModelProperty(value = "位置") | |
118 | + private Integer position; | |
115 | 119 | /** 备用字段1 */ |
116 | 120 | @Excel(name = "备用字段1", width = 15) |
117 | 121 | @ApiModelProperty(value = "备用字段1") |
... | ... |
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/task/taskHeader/service/ITaskHeaderService.java
... | ... | @@ -65,6 +65,14 @@ public interface ITaskHeaderService extends IService<TaskHeader> { |
65 | 65 | TaskHeader getUnCompleteTaskByToLocationCode(String toLocationCode, String warehouseCode); |
66 | 66 | |
67 | 67 | /** |
68 | + * 通过目标库位编码,获取任务信息 | |
69 | + * @param toLocationCode | |
70 | + * @param warehouseCode | |
71 | + * @return | |
72 | + */ | |
73 | + TaskHeader getUnCompleteTransferTaskByFromLocationCode(String toLocationCode, String warehouseCode); | |
74 | + | |
75 | + /** | |
68 | 76 | * 通过库位编码,获取任务信息 |
69 | 77 | * @param locationCode |
70 | 78 | * @param warehouseCode |
... | ... |
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/task/taskHeader/service/impl/TaskHeaderServiceImpl.java
... | ... | @@ -1015,6 +1015,16 @@ public class TaskHeaderServiceImpl extends ServiceImpl<TaskHeaderMapper, TaskHea |
1015 | 1015 | } |
1016 | 1016 | |
1017 | 1017 | @Override |
1018 | + public TaskHeader getUnCompleteTransferTaskByFromLocationCode(String fromLocationCode, String warehouseCode) { | |
1019 | + LambdaQueryWrapper<TaskHeader> taskHeaderLambdaQueryWrapper = Wrappers.lambdaQuery(); | |
1020 | + taskHeaderLambdaQueryWrapper.eq(TaskHeader::getFromLocationCode, fromLocationCode).eq(TaskHeader::getTaskType, QuantityConstant.TASK_TYPE_TRANSFER). | |
1021 | + eq(TaskHeader::getWarehouseCode, warehouseCode).lt(TaskHeader::getStatus, | |
1022 | + QuantityConstant.TASK_STATUS_COMPLETED); | |
1023 | + TaskHeader taskHeader = taskHeaderService.getOne(taskHeaderLambdaQueryWrapper); | |
1024 | + return taskHeader; | |
1025 | + } | |
1026 | + | |
1027 | + @Override | |
1018 | 1028 | public TaskHeader getUnCompleteTaskByLocationCode(String locationCode, String warehouseCode) { |
1019 | 1029 | TaskHeader taskHeader = getUnCompleteTaskByFromLocationCode(locationCode, warehouseCode); |
1020 | 1030 | if (taskHeader == null) { |
... | ... | @@ -1556,7 +1566,11 @@ public class TaskHeaderServiceImpl extends ServiceImpl<TaskHeaderMapper, TaskHea |
1556 | 1566 | return Result.error("创建移库任务失败,起始库位:" + fromLocationCode + "和目标库位:" + toLocationCode + "是同一个"); |
1557 | 1567 | } |
1558 | 1568 | String containerCode = fromLocation.getContainerCode(); |
1559 | - | |
1569 | + TaskHeader unComleteTask = taskHeaderService.getUnCompleteTaskByContainerCode(containerCode, warehouseCode); | |
1570 | + if (unComleteTask != null) { | |
1571 | + Container container = containerService.createLSContainer(warehouseCode); | |
1572 | + containerCode = container.getCode(); | |
1573 | + } | |
1560 | 1574 | List<InventoryDetail> toInventoryDetailList = inventoryDetailService.getInventoryDetailListByLocationCode(toLocationCode, warehouseCode); |
1561 | 1575 | List<InventoryDetail> totalInventoryDetailList = new ArrayList<>(); |
1562 | 1576 | if (CollectionUtils.isNotEmpty(toInventoryDetailList)) { |
... | ... | @@ -1573,9 +1587,9 @@ public class TaskHeaderServiceImpl extends ServiceImpl<TaskHeaderMapper, TaskHea |
1573 | 1587 | return Result.error("创建移库任务时,起始库位:" + fromLocationCode + "存在入库组盘,不能移库"); |
1574 | 1588 | } |
1575 | 1589 | // 校验出库组盘 |
1576 | - if (shipmentContainerHeaderService.havaUnCompleteCombineByLocationCode(fromLocationCode, warehouseCode)) { | |
1577 | - return Result.error("创建移库任务时,起始库位:" + fromLocationCode + "存在出库组盘,不能移库"); | |
1578 | - } | |
1590 | +// if (shipmentContainerHeaderService.havaUnCompleteCombineByLocationCode(fromLocationCode, warehouseCode)) { | |
1591 | +// return Result.error("创建移库任务时,起始库位:" + fromLocationCode + "存在出库组盘,不能移库"); | |
1592 | +// } | |
1579 | 1593 | |
1580 | 1594 | // 校验入库组盘 |
1581 | 1595 | if (receiptContainerHeaderService.havaUnCompleteCombineByLocationCode(toLocationCode, warehouseCode)) { |
... | ... | @@ -2622,23 +2636,29 @@ public class TaskHeaderServiceImpl extends ServiceImpl<TaskHeaderMapper, TaskHea |
2622 | 2636 | if (container == null) { |
2623 | 2637 | return Result.error("创建分拣任务时, 没有找到托盘" + containerCode); |
2624 | 2638 | } |
2625 | - if (!container.getStatus().equals(QuantityConstant.STATUS_CONTAINER_EMPTY)) { | |
2626 | - return Result.error("创建分拣任务时, 托盘状态并非空闲状态"); | |
2627 | - } | |
2628 | - if (StringUtils.isEmpty(container.getLocationCode())) { | |
2629 | - return Result.error("创建分拣任务时, 容器不在库位" + container.getLocationCode() + "上"); | |
2630 | - } | |
2631 | 2639 | Location fromLocation = locationService.getLocationByCode(fromLocationCode, warehouseCode); |
2632 | 2640 | if (fromLocation == null) { |
2633 | 2641 | return Result.error("创建分拣任务时, 起始库位为空"); |
2634 | 2642 | } |
2643 | + zoneCode = fromLocation.getZoneCode(); | |
2644 | + if (!container.getStatus().equals(QuantityConstant.STATUS_CONTAINER_EMPTY)) { | |
2645 | + if (!zoneCode.equals(QuantityConstant.ZONE_B)) { | |
2646 | + return Result.error("创建分拣任务时, 托盘状态并非空闲状态"); | |
2647 | + } | |
2648 | + } | |
2649 | + if (StringUtils.isEmpty(container.getLocationCode())) { | |
2650 | + if (!zoneCode.equals(QuantityConstant.ZONE_B)) { | |
2651 | + return Result.error("创建分拣任务时, 容器不在库位" + container.getLocationCode() + "上"); | |
2652 | + } | |
2653 | + } | |
2635 | 2654 | if (StringUtils.isEmpty(fromLocation.getContainerCode())) { |
2636 | 2655 | return Result.error("创建分拣任务时," + fromLocationCode + "上已存在容器" + fromLocation.getContainerCode()); |
2637 | 2656 | } |
2638 | 2657 | if (!QuantityConstant.STATUS_LOCATION_EMPTY.equals(fromLocation.getStatus())) { |
2639 | - return Result.error("创建分拣任务时, 起始库位非空闲"); | |
2658 | + if (!zoneCode.equals(QuantityConstant.ZONE_B)) { | |
2659 | + return Result.error("创建分拣任务时, 起始库位非空闲"); | |
2660 | + } | |
2640 | 2661 | } |
2641 | - zoneCode = fromLocation.getZoneCode(); | |
2642 | 2662 | taskLockEntity.setZoneCode(zoneCode); |
2643 | 2663 | if (StringUtils.isNotEmpty(toLocationCode) && !fromLocationCode.equals(toLocationCode)) { |
2644 | 2664 | Location toLocation = locationService.getLocationByCode(toLocationCode, warehouseCode); |
... | ... | @@ -2657,11 +2677,15 @@ public class TaskHeaderServiceImpl extends ServiceImpl<TaskHeaderMapper, TaskHea |
2657 | 2677 | } |
2658 | 2678 | success = containerService.updateStatus(containerCode, QuantityConstant.STATUS_CONTAINER_LOCK, warehouseCode); |
2659 | 2679 | if (!success) { |
2660 | - throw new JeecgBootException("创建分拣任务时,更新容器状态失败"); | |
2680 | + if (!zoneCode.equals(QuantityConstant.ZONE_B)) { | |
2681 | + throw new JeecgBootException("创建分拣任务时,更新容器状态失败"); | |
2682 | + } | |
2661 | 2683 | } |
2662 | 2684 | success = locationService.updateStatus(fromLocationCode, QuantityConstant.STATUS_LOCATION_LOCK, warehouseCode); |
2663 | 2685 | if (!success) { |
2664 | - throw new JeecgBootException("创建分拣任务时,更新库位状态失败"); | |
2686 | + if (!zoneCode.equals(QuantityConstant.ZONE_B)) { | |
2687 | + throw new JeecgBootException("创建分拣任务时,更新库位状态失败"); | |
2688 | + } | |
2665 | 2689 | } |
2666 | 2690 | if (StringUtils.isNotEmpty(toLocationCode)) { |
2667 | 2691 | if (!fromLocationCode.equals(toLocationCode)) { |
... | ... |