WarecellAllocationServiceImpl.java 18.9 KB
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.common.exception.service.ServiceException;
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.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 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;
    /**
     * 立库仓位分配
     * 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());
        List<LocationType> locationTypeList = locationTypeService.list(lambdaQueryWrapper);
        List<String> codeList = new ArrayList<>();
        for (LocationType locationType: locationTypeList) {
            codeList.add(locationType.getCode());
        }

        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("任务已经完成,不能再分库位");
        }

        /* 循环查询入库组盘明细*/
        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) {
            ReceiptContainerHeader receiptContainerHeader = receiptContainerHeaderService.getById(receiptContainerDetail.getReceiptContainerId());

            String locatingRule = this.taskPositioning(receiptContainerDetail);

            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("cut");

            //根据定位规则查询库位编码
            LambdaQueryWrapper<Location> locationLambda = Wrappers.lambdaQuery();
            locationLambda.last(locatingRules[0]);
            locationLambda.eq(Location::getRoadway, wcsTask.getDestination());
            List<Location> locationList = locationService.list(locationLambda);
            if(locationList == null || locationList.size() == 0) {
                locationLambda.last(locatingRules[1]);
                locationList = locationService.list(locationLambda);
            };
            locationCode = filter(locationList, locationTypeList, wcsTask.getDestination());
            if (StringUtils.isEmpty(locationCode)){
                throw new ServiceException("没有库位可分配");
            }

            if (StringUtils.isNotEmpty(locationCode)){
                locationService.updateStatus(locationCode, "lock");
                if (StringUtils.isNotEmpty(taskHeader.getToLocation()) && !locationCode.equals(taskHeader.getToLocation())){
                    locationService.updateStatus(taskHeader.getToLocation(), "empty");
                }
            } else {
                throw new ServiceException("定位失败,请检查定位规则是否正确");
            }

            //更新库位编码到组盘头表
            receiptContainerHeader.setToLocation(locationCode);
            if (!receiptContainerHeaderService.updateById(receiptContainerHeader)){
                throw new ServiceException("更新库位失败");
            }

            //把库位编码赋到该入库组盘头表下的所有明细
            LambdaQueryWrapper<ReceiptContainerDetail> lambda = Wrappers.lambdaQuery();
            lambda.eq(ReceiptContainerDetail::getReceiptContainerId, receiptContainerHeader.getId())
                    .eq(ReceiptContainerDetail::getWarehouseCode, ShiroUtils.getWarehouseCode());
            List<ReceiptContainerDetail> receiptContainerDetails = receiptContainerDetailService.list(lambda);
            for (ReceiptContainerDetail receiptContainerDetail2: receiptContainerDetails) {
                receiptContainerDetail2.setLocationCode(locationCode);
                if (!receiptContainerDetailService.updateById(receiptContainerDetail2)){throw new ServiceException("更新库位编码到入库组盘明细");}
            }
        }

        if (StringUtils.isNotEmpty(locationCode)){
            //修改任务明细目标库位
            for (TaskDetail taskDetail : taskDetailList) {
                taskDetail.setToLocation(locationCode);
                if (!taskDetailService.updateById(taskDetail)){ throw new ServiceException("更新任务明细目标库位失败");}
            }


            taskHeader.setToLocation(locationCode);
            if (!taskHeaderService.updateById(taskHeader)){throw new ServiceException("更新任务头表目标库位失败");}

            LambdaQueryWrapper<Location> locationLambdaQueryWrapper = Wrappers.lambdaQuery();
            locationLambdaQueryWrapper.eq(Location::getCode, locationCode);
            Location location = locationService.getOne(locationLambdaQueryWrapper);
            int rowFlag = location.getRowFlag().intValue();
            //如果是外侧库位,那么就要判断该库位对应的内侧库位是不是有托盘
            if(rowFlag == 1) {
                Location insideLocation = locationService.getInsideNear(location);
                if(StringUtils.isNotEmpty(insideLocation.getContainerCode())) {
                    Location destinationLocation = locationService.getEmptyInsideLocation(insideLocation);
                    AjaxResult ajaxResult = transferTaskService.createTransferTask(insideLocation.getCode(), destinationLocation.getCode());
                    if(ajaxResult.hasErr()) {
                        throw new ServiceException("创建移库任务失败");
                    }
                }
            }
            return AjaxResult.success(locationCode);
        }

        return AjaxResult.error("错误");
    }

    /**
     * 库位筛选
     * @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();
        }
    }

    /**
     * 定位
     * @param receiptContainerDetail
     * @return
     */
    @Override
    public String taskPositioning(ReceiptContainerDetail receiptContainerDetail){
        ReceiptContainerHeader receiptContainerHeader = receiptContainerHeaderService.getById(receiptContainerDetail.getReceiptContainerId());
        String locatingRule = receiptContainerHeader.getLocatingRule(); //定位规则
        if (StringUtils.isEmpty(locatingRule)){
            locatingRule = receiptDetailService.getById(receiptContainerDetail.getReceiptDetailId()).getLocatingRule();
            //入库单明细定位规则不为空时执行
            if (StringUtils.isEmpty(locatingRule)){
                //入库单明细为空时,查询物料表中是否含有定位规则
                LambdaQueryWrapper<Material> materialLambda = Wrappers.lambdaQuery();
                materialLambda.eq(Material::getCode, receiptContainerDetail.getMaterialCode());
                Material material = materialService.getOne(materialLambda);
                locatingRule = material.getLocatingRule();

                if (StringUtils.isEmpty(locatingRule)){
                    //物料表中定位规则为空时,查询物料类别
                    LambdaQueryWrapper<MaterialType> materialTypeLambda = Wrappers.lambdaQuery();
                    materialTypeLambda.eq(MaterialType::getCode, material.getType());
                    MaterialType materialType = materialTypeService.getOne(materialTypeLambda);
                    locatingRule = materialType.getLocatingRule();
                    if (StringUtils.isEmpty(locatingRule)){
                        //物料类别中定位规则为空时,查询入库首选项
                        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);
                        locatingRule = receiptPreferenceService.getOne(receiptPreferenceLambda).getLocationRule();
                    }
                }
            }
        }
        //通过定位规则查找自定义sql
        if (StringUtils.isEmpty(locatingRule)){
            throw new ServiceException("未绑定定位规则");
        }

        return locatingRule;
    }


    /**
     *  去向分配
     */
    @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(receiptContainerDetail);

            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);
    }
}