package com.huaheng.api.wcs.service.warecellAllocation; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.huaheng.api.wcs.domain.WCSInfo; import com.huaheng.common.exception.service.ServiceException; import com.huaheng.common.support.Convert; import com.huaheng.common.utils.StringUtils; import com.huaheng.common.utils.security.ShiroUtils; import com.huaheng.framework.web.domain.AjaxResult; import com.huaheng.pc.config.FilterConfigDetail.domain.FilterConfigDetail; import com.huaheng.pc.config.FilterConfigDetail.service.FilterConfigDetailService; import com.huaheng.pc.config.configValue.domain.ConfigValue; import com.huaheng.pc.config.configValue.service.ConfigValueService; import com.huaheng.pc.config.container.domain.Container; import com.huaheng.pc.config.container.service.ContainerService; import com.huaheng.pc.config.containerType.domain.ContainerType; import com.huaheng.pc.config.containerType.service.ContainerTypeService; import com.huaheng.pc.config.location.domain.Location; import com.huaheng.pc.config.location.service.LocationService; import com.huaheng.pc.config.locationType.domain.LocationType; import com.huaheng.pc.config.locationType.service.LocationTypeService; import com.huaheng.pc.config.material.domain.Material; import com.huaheng.pc.config.material.service.MaterialService; import com.huaheng.pc.config.materialType.domain.MaterialType; import com.huaheng.pc.config.materialType.service.MaterialTypeService; import com.huaheng.pc.config.receiptPreference.domain.ReceiptPreference; import com.huaheng.pc.config.receiptPreference.service.ReceiptPreferenceService; import com.huaheng.pc.receipt.receiptContainerDetail.domain.ReceiptContainerDetail; import com.huaheng.pc.receipt.receiptContainerDetail.service.ReceiptContainerDetailService; import com.huaheng.pc.receipt.receiptContainerHeader.domain.ReceiptContainerHeader; import com.huaheng.pc.receipt.receiptContainerHeader.service.ReceiptContainerHeaderService; import com.huaheng.pc.receipt.receiptDetail.service.ReceiptDetailService; import com.huaheng.pc.task.taskDetail.domain.TaskDetail; import com.huaheng.pc.task.taskDetail.service.TaskDetailService; import com.huaheng.pc.task.taskHeader.domain.TaskHeader; import com.huaheng.pc.task.taskHeader.service.TaskHeaderService; import com.huaheng.pc.task.taskHeader.service.TransferTaskService; import com.huaheng.pc.task.taskHeader.service.WorkTaskService; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.huaheng.api.wcs.domain.WcsTask; import javax.annotation.Resource; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @Service public class WarecellAllocationServiceImpl implements WarecellAllocationService { @Resource private LocationTypeService locationTypeService; @Resource private LocationService locationService; @Resource private ContainerService containerService; @Resource private ContainerTypeService containerTypeService; @Resource private ConfigValueService configValueService; @Resource private ReceiptPreferenceService receiptPreferenceService; @Resource private FilterConfigDetailService filterConfigDetailService; @Resource private TaskDetailService taskDetailService; @Resource private TaskHeaderService taskHeaderService; @Resource private ReceiptContainerDetailService receiptContainerDetailService; @Resource private ReceiptContainerHeaderService receiptContainerHeaderService; @Resource private ReceiptDetailService receiptDetailService; @Resource private MaterialService materialService; @Resource private MaterialTypeService materialTypeService; @Resource private WorkTaskService workTaskService; @Resource private TransferTaskService transferTaskService; @Resource private LocationAllocationService locationAllocationService; /** * 立库仓位分配 * 1、判断非空字段 * 2、实体转换 * 3、查询满足条件的库位类型 * * @param wcsTask * @return */ @Override @Transactional(rollbackFor = Exception.class) public AjaxResult warecellAllocation(WcsTask wcsTask) { //1、判断非空字段 if (StringUtils.isEmpty(wcsTask.getTaskNo())) { return AjaxResult.error("任务号为空"); } if (StringUtils.isEmpty(wcsTask.getDestination())) { return AjaxResult.error("目的为空"); } if (StringUtils.isNull(wcsTask.getLength())) { return AjaxResult.error("长为空"); } if (StringUtils.isNull(wcsTask.getWidth())) { return AjaxResult.error("宽为空"); } if (StringUtils.isNull(wcsTask.getHeight())) { return AjaxResult.error("高为空"); } if (StringUtils.isNull(wcsTask.getWeight())) { return AjaxResult.error("重为空"); } String locationType = null; if (StringUtils.isNull(wcsTask.getLocationType())) { locationType = "L"; } else { locationType = wcsTask.getLocationType(); } if (locationType.equals("L")) { return verticalWarehouseAllocation(wcsTask); } return AjaxResult.error("库位类型错误"); } public AjaxResult verticalWarehouseAllocation(WcsTask wcsTask) { //查询满足条件的库位类型 LambdaQueryWrapper<LocationType> lambdaQueryWrapper = Wrappers.lambdaQuery(); lambdaQueryWrapper.gt(LocationType::getLength, wcsTask.getLength()) .gt(LocationType::getWidth, wcsTask.getWidth()) .gt(LocationType::getHeight, wcsTask.getHeight()) .gt(LocationType::getMaxWeight, wcsTask.getWidth()) .eq(LocationType::getWarehouseCode, wcsTask.getWarehouseCode()); List<LocationType> locationTypeList = locationTypeService.list(lambdaQueryWrapper); String locationCode = null; //查询任务明细 LambdaQueryWrapper<TaskDetail> taskDetailLambda = Wrappers.lambdaQuery(); taskDetailLambda.eq(TaskDetail::getTaskId, wcsTask.getTaskNo()); List<TaskDetail> taskDetailList = taskDetailService.list(taskDetailLambda); TaskHeader taskHeader = taskHeaderService.getById(wcsTask.getTaskNo()); if (taskHeader.getStatus() == 100) { return AjaxResult.error("任务已经完成,不能再分库位"); } String containerCode = taskHeader.getContainerCode(); /* 循环查询入库组盘明细*/ List<ReceiptContainerDetail> receiptContainerDetailList = new ArrayList<>(); for (TaskDetail taskDetail : taskDetailList) { receiptContainerDetailList.add(receiptContainerDetailService.getById(taskDetail.getAllocationId())); } //去重 receiptContainerDetailList = receiptContainerDetailList.stream().distinct().collect(Collectors.toList()); String locatingRule = null; ReceiptContainerHeader receiptContainerHeader = null; if (StringUtils.isEmpty(locatingRule)) { //物料类别中定位规则为空时,查询入库首选项 LambdaQueryWrapper<ConfigValue> configValueLambda = Wrappers.lambdaQuery(); configValueLambda.eq(ConfigValue::getWarehouseCode, wcsTask.getWarehouseCode()) .eq(ConfigValue::getModuleType, "receipt") .eq(ConfigValue::getRecordType, "入库首选项"); ConfigValue configValue = configValueService.getOne(configValueLambda); LambdaQueryWrapper<ReceiptPreference> receiptPreferenceLambda = Wrappers.lambdaQuery(); receiptPreferenceLambda.eq(ReceiptPreference::getCode, configValue.getValue()) .eq(ReceiptPreference::getWarehouseCode, wcsTask.getWarehouseCode()); ReceiptPreference receiptPreference = receiptPreferenceService.getOne(receiptPreferenceLambda); locatingRule = receiptPreference.getLocationRule(); } if (StringUtils.isEmpty(locatingRule)){ throw new ServiceException("未绑定定位规则"); } locationCode = locationAllocationService.allocation(locatingRule, wcsTask.getDestination(), wcsTask.getWarehouseCode(), containerCode); if (StringUtils.isEmpty(locationCode)) { throw new ServiceException("没有库位可分配"); } if (StringUtils.isNotEmpty(locationCode)) { locationService.updateStatus(locationCode, "lock", wcsTask.getWarehouseCode()); if (StringUtils.isNotEmpty(taskHeader.getToLocation()) && !locationCode.equals(taskHeader.getToLocation())) { locationService.updateStatus(taskHeader.getToLocation(), "empty", wcsTask.getWarehouseCode()); } } else { throw new ServiceException("定位失败,请检查定位规则是否正确"); } if (receiptContainerDetailList != null && receiptContainerDetailList.size() > 0) { //更新库位编码到组盘头表 ReceiptContainerDetail receiptContainerDetail = receiptContainerDetailList.get(0); if (receiptContainerDetail != null) { receiptContainerHeader = receiptContainerHeaderService.getById(receiptContainerDetail.getReceiptContainerId()); receiptContainerHeader.setToLocation(locationCode); if (!receiptContainerHeaderService.updateById(receiptContainerHeader)) { throw new ServiceException("更新库位失败"); } //把库位编码赋到该入库组盘头表下的所有明细 LambdaQueryWrapper<ReceiptContainerDetail> lambda = Wrappers.lambdaQuery(); lambda.eq(ReceiptContainerDetail::getReceiptContainerId, receiptContainerHeader.getId()) .eq(ReceiptContainerDetail::getWarehouseCode, wcsTask.getWarehouseCode()); List<ReceiptContainerDetail> receiptContainerDetails = receiptContainerDetailService.list(lambda); for (ReceiptContainerDetail receiptContainerDetail2 : receiptContainerDetails) { receiptContainerDetail2.setLocationCode(locationCode); if (!receiptContainerDetailService.updateById(receiptContainerDetail2)) { throw new ServiceException("更新库位编码到入库组盘明细"); } } } } for (TaskDetail taskDetail : taskDetailList) { taskDetail.setToLocation(locationCode); if (!taskDetailService.updateById(taskDetail)) { throw new ServiceException("更新任务明细目标库位失败"); } } //修改任务明细目标库位 LambdaQueryWrapper<Location> locationLambdaQueryWrapper = Wrappers.lambdaQuery(); locationLambdaQueryWrapper.eq(Location::getCode, locationCode) .eq(Location::getWarehouseCode, wcsTask.getWarehouseCode()); Location location = locationService.getOne(locationLambdaQueryWrapper); int rowFlag = location.getRowFlag().intValue(); Integer preTaskNo = 0; //如果是外侧库位,那么就要判断该库位对应的内侧库位是不是有托盘 if (rowFlag == 1) { Location insideLocation = locationService.getInsideNear(location); if (StringUtils.isNotEmpty(insideLocation.getContainerCode())) { Location destinationLocation = locationService.getEmptyLocation(insideLocation); AjaxResult ajaxResult = transferTaskService.createTransferTask(insideLocation.getCode(), destinationLocation.getCode()); preTaskNo = (Integer) ajaxResult.getData(); if (ajaxResult.hasErr()) { throw new ServiceException("创建移库任务失败"); } taskHeaderService.sendTaskToWcs(Convert.toIntArray(String.valueOf(preTaskNo))); } } taskHeader.setPreTaskNo(preTaskNo); taskHeader.setToLocation(locationCode); if (!taskHeaderService.updateById(taskHeader)) { throw new ServiceException("更新任务头表目标库位失败"); } WCSInfo wcsInfo = new WCSInfo(); wcsInfo.setLocationCode(locationCode); wcsInfo.setPreTask(String.valueOf(preTaskNo)); return AjaxResult.success().setData(wcsInfo); } /** * 库位筛选 * * @param locationList 库位列表 * @param locationTypeList 库位类型列表 * @param roadway 巷道 * @return */ public String filter(List<Location> locationList, List<LocationType> locationTypeList, String roadway) { List<String> codeList = locationTypeList.stream().map(t -> t.getCode()).collect(Collectors.toList()); List<Location> newLocation = locationList.stream().filter(t -> codeList.contains(t.getLocationType()) && t.getRoadway().equals(roadway)).collect(Collectors.toList()); if (newLocation.isEmpty()) { return null; } else { return newLocation.get(0).getCode(); } } /** * 定位规则 * @return */ @Override public String taskPositioning() { //物料类别中定位规则为空时,查询入库首选项 LambdaQueryWrapper<ConfigValue> configValueLambda = Wrappers.lambdaQuery(); configValueLambda.eq(ConfigValue::getWarehouseCode, ShiroUtils.getWarehouseCode()) .eq(ConfigValue::getModuleType, "receipt") .eq(ConfigValue::getRecordType, "入库首选项"); ConfigValue configValue = configValueService.getOne(configValueLambda); LambdaQueryWrapper<ReceiptPreference> receiptPreferenceLambda = Wrappers.lambdaQuery(); receiptPreferenceLambda.eq(ReceiptPreference::getCode, configValue.getValue()) .eq(ReceiptPreference::getWarehouseCode, ShiroUtils.getWarehouseCode()); ReceiptPreference receiptPreference = receiptPreferenceService.getOne(receiptPreferenceLambda); String locatingRule = receiptPreference.getLocationRule(); //通过定位规则查找自定义sql if (StringUtils.isEmpty(locatingRule)) { throw new ServiceException("未绑定定位规则"); } LambdaQueryWrapper<FilterConfigDetail> lambdaQueryWrapper = Wrappers.lambdaQuery(); lambdaQueryWrapper.eq(FilterConfigDetail::getCode, locatingRule) .eq(FilterConfigDetail::getWarehouseCode,ShiroUtils.getWarehouseCode()); FilterConfigDetail filterConfigDetail = filterConfigDetailService.getOne(lambdaQueryWrapper); return filterConfigDetail.getStatement(); } /** * 去向分配 */ @Override public AjaxResult destinationAllocation(WcsTask wcsTask) { //1、判断非空字段 if (StringUtils.isEmpty(wcsTask.getTaskNo())) { return AjaxResult.error("任务号为空"); } if (StringUtils.isNull(wcsTask.getLength())) { return AjaxResult.error("长为空"); } if (StringUtils.isNull(wcsTask.getWidth())) { return AjaxResult.error("宽为空"); } if (StringUtils.isNull(wcsTask.getHeight())) { return AjaxResult.error("高为空"); } if (StringUtils.isNull(wcsTask.getWeight())) { return AjaxResult.error("重为空"); } //查询满足条件的库位类型 LambdaQueryWrapper<LocationType> lambdaQueryWrapper = Wrappers.lambdaQuery(); lambdaQueryWrapper.gt(LocationType::getLength, wcsTask.getLength()) .gt(LocationType::getWidth, wcsTask.getWidth()) .gt(LocationType::getHeight, wcsTask.getHeight()) .gt(LocationType::getMaxWeight, wcsTask.getWidth()); List<LocationType> locationTypeList = locationTypeService.list(lambdaQueryWrapper); if (locationTypeList.isEmpty()) { return AjaxResult.error("没有区域可分配"); } List<String> codeList = new ArrayList<>(); for (LocationType locationType : locationTypeList) { codeList.add(locationType.getCode()); } //定位库位List List<String> positioningLocationCodeList = null; //查询任务明细 LambdaQueryWrapper<TaskDetail> taskDetailLambda = Wrappers.lambdaQuery(); taskDetailLambda.eq(TaskDetail::getTaskId, wcsTask.getTaskNo()); List<TaskDetail> taskDetailList = taskDetailService.list(taskDetailLambda); /* 循环查询入库组盘明细*/ List<ReceiptContainerDetail> receiptContainerDetailList = new ArrayList<>(); for (TaskDetail taskDetail : taskDetailList) { receiptContainerDetailList.add(receiptContainerDetailService.getById(taskDetail.getAllocationId())); } //去重 receiptContainerDetailList = receiptContainerDetailList.stream().distinct().collect(Collectors.toList()); for (ReceiptContainerDetail receiptContainerDetail : receiptContainerDetailList) { String locatingRule = this.taskPositioning(); LambdaQueryWrapper<FilterConfigDetail> filterConfigDetailLambda = Wrappers.lambdaQuery(); filterConfigDetailLambda.eq(FilterConfigDetail::getCode, locatingRule) .eq(FilterConfigDetail::getWarehouseCode, ShiroUtils.getWarehouseCode()); FilterConfigDetail filterConfigDetail = filterConfigDetailService.getOne(filterConfigDetailLambda); String[] locatingRules = filterConfigDetail.getStatement().split("limit"); //根据定位规则查询库位编码 LambdaQueryWrapper<Location> locationLambda = Wrappers.lambdaQuery(); locationLambda.last(locatingRules[0]); List<Location> locationList = locationService.list(locationLambda); List<String> locationCodeList = locationTypeList.stream().map(t -> t.getCode()).collect(Collectors.toList()); List<Location> newLocation = locationList.stream().filter(t -> locationCodeList.contains(t.getLocationType())).collect(Collectors.toList()); if (!newLocation.isEmpty()) { positioningLocationCodeList.add(newLocation.get(0).getCode()); } if (StringUtils.isEmpty(positioningLocationCodeList)) { throw new ServiceException("没有区域可分配"); } } LambdaQueryWrapper<Location> locationLambdaQueryWrapper = Wrappers.lambdaQuery(); locationLambdaQueryWrapper.eq(Location::getCode, positioningLocationCodeList.get(0)); Location location = locationService.getOne(locationLambdaQueryWrapper); String destinationArea = location.getRoadway(); return AjaxResult.success(destinationArea); } }