Commit f97dee9338324bb5fd3d7f9f9007d3d4a45643cd

Authored by 肖超群
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 &quot;@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&lt;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&lt;InventoryDetail&gt; {
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&lt;InventoryHeader&gt; {
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&lt;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&lt;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&lt;TaskHeader&gt; {
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&lt;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&lt;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&lt;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&lt;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&lt;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)) {
... ...