LocationAllocationServiceImpl.java 8.5 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.constant.QuantityConstant;
import com.huaheng.common.exception.service.ServiceException;
import com.huaheng.common.utils.StringUtils;
import com.huaheng.framework.web.service.ConfigService;
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.zone.domain.Zone;
import com.huaheng.pc.config.zone.service.ZoneService;
import com.huaheng.pc.task.taskHeader.domain.TaskHeader;
import com.huaheng.pc.task.taskHeader.service.TaskHeaderService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;

@Service
public class LocationAllocationServiceImpl implements LocationAllocationService {

    @Resource
    private LocationService locationService;
    @Resource
    private LocationTypeService locationTypeService;
    @Resource
    private ContainerService containerService;
    @Resource
    private ContainerTypeService containerTypeService;
    @Resource
    private TaskHeaderService taskHeaderService;
    @Resource
    private ZoneService zoneService;
    @Resource
    private ConfigService configService;

    @Override
    public String allocation(int locationRule, List<String> locationTypeCodeList,
                             int high, String area, List<String> roadWays, String warehouseCode,
                             String containerCode, String materialAreaCode) {
        // 查询容器信息
        Container container = containerService.getOne(Wrappers.<Container>lambdaQuery()
                .eq(Container::getCode, containerCode)
                .eq(Container::getWarehouseCode, warehouseCode));

        // 获取容器类型
        ContainerType containerType = containerTypeService.getOne(Wrappers.<ContainerType>lambdaQuery()
                .eq(ContainerType::getCode, container.getContainerType())
                .eq(ContainerType::getWarehouseCode, warehouseCode));

        List<LocationType> locationTypeList = new ArrayList<>();
        if (containerType != null) {
            // 获取容器适用的库位类型列表
            String[] locationTypes = containerType.getLocationType().split(",");
            for (String typeCode : locationTypes) {
                LocationType locationType = locationTypeService.getOne(Wrappers.<LocationType>lambdaQuery()
                        .eq(LocationType::getWarehouseCode, warehouseCode)
                        .eq(LocationType::getCode, typeCode));
                locationTypeList.add(locationType);
            }
        } else {
            // 如果没有容器类型信息,按库区获取默认的库位类型
            Zone zone = zoneService.getOne(Wrappers.<Zone>lambdaQuery()
                    .eq(Zone::getWarehouseCode, warehouseCode)
                    .eq(Zone::getArea, area));
            if (zone != null) {
                locationTypeList = locationTypeService.list(Wrappers.<LocationType>lambdaQuery()
                        .eq(LocationType::getWarehouseCode, warehouseCode)
                        .eq(LocationType::getZoneCode, zone.getCode()));
            }
        }

        // 获取库位类型代码列表
        List<String> locationTypeCodes = locationTypeList.stream()
                .map(LocationType::getCode)
                .collect(Collectors.toList());

        // 合并库位类型代码
        List<String> mergedLocationTypeCodeList = locationTypeCodeList.stream()
                .filter(locationTypeCodes::contains)
                .collect(Collectors.toList());

        // 根据入库规则分配库位
        switch (locationRule) {
            case QuantityConstant.DOUBLE_FORK:
                return doubleRk(area, roadWays, high, warehouseCode, mergedLocationTypeCodeList, materialAreaCode);
            case QuantityConstant.SINGLE_FORK:
                return singleRk(area, roadWays, high, warehouseCode, mergedLocationTypeCodeList, materialAreaCode);
            default:
                return null;
        }
    }

    /**
     * 双伸位库位入库分配
     */
    private String doubleRk(String area, List<String> roadWays, int high, String warehouseCode,
                            List<String> locationTypeCodeList, String materialAreaCode) {
        // 查询符合条件的空置外侧库位
        List<Location> locationList = locationService.list(Wrappers.<Location>lambdaQuery()
                .eq(Location::getArea, area)
                .eq(Location::getWarehouseCode, warehouseCode)
                .in(StringUtils.isNotEmpty(roadWays), Location::getRoadway, roadWays)
                .eq(Location::getStatus, QuantityConstant.STATUS_LOCATION_EMPTY)
                .eq(Location::getHigh, high)
                .eq(StringUtils.isNotEmpty(materialAreaCode), Location::getMaterialAreaCode, materialAreaCode)
                .eq(Location::getRowFlag, QuantityConstant.ROW_OUT)
                .in(Location::getLocationType, locationTypeCodeList)
                .eq(Location::getContainerCode, ""));

        // 如果没有空置外侧库位,查询内侧库位
        if (locationList.isEmpty()) {
            locationList = locationService.list(Wrappers.<Location>lambdaQuery()
                    .eq(Location::getArea, area)
                    .eq(Location::getWarehouseCode, warehouseCode)
                    .in(StringUtils.isNotEmpty(roadWays), Location::getRoadway, roadWays)
                    .eq(Location::getStatus, QuantityConstant.STATUS_LOCATION_EMPTY)
                    .eq(Location::getHigh, high)
                    .eq(StringUtils.isNotEmpty(materialAreaCode), Location::getMaterialAreaCode, materialAreaCode)
                    .eq(Location::getRowFlag, QuantityConstant.ROW_IN)
                    .in(Location::getLocationType, locationTypeCodeList)
                    .eq(Location::getContainerCode, ""));

            // 排除有未完成任务的库位
            locationList.removeIf(location -> taskHeaderService.getUncompleteTaskInNear(location) > 0);
        }
        return locationList.stream().findFirst().map(Location::getCode).orElse(null);
    }

    /**
     * 单伸位库位入库分配
     */
    private String singleRk(String area, List<String> roadWays, int high, String warehouseCode,
                            List<String> locationTypeCodeList, String materialAreaCode) {
        // 根据物料分区调整参数
        if (materialAreaCode != null) {
            if ((Integer.valueOf(area) == 1 || Integer.valueOf(area) == 2)
                    && materialAreaCode.equals(QuantityConstant.STATUS_CONTAINER_MANY)) {
                materialAreaCode = "C";
            }
        }
        if (Integer.valueOf(area) == 3 && high == 3) {
            high = 1;
            materialAreaCode = "A";
        }

        // 查询符合条件的库位
        List<Location> locationList = locationService.list(Wrappers.<Location>lambdaQuery()
                .eq(Location::getArea, area)
                .eq(Location::getWarehouseCode, warehouseCode)
                .in(StringUtils.isNotEmpty(roadWays), Location::getRoadway, roadWays)
                .eq(Location::getStatus, QuantityConstant.STATUS_LOCATION_EMPTY)
                .eq(Location::getHigh, high)
                .eq(StringUtils.isNotEmpty(materialAreaCode), Location::getMaterialAreaCode, materialAreaCode)
                .in(Location::getLocationType, locationTypeCodeList)
                .eq(Location::getContainerCode, ""));

        // 通过配置调整库位顺序
        String cs = configService.getKey(QuantityConstant.Reverse_Engine_Sequence);
        if ("1".equals(cs) && "1".equals(area)) {
            Collections.reverse(locationList);
        }

        // 返回第一个符合条件的库位编码
        return locationList.stream().findFirst().map(Location::getCode).orElseThrow(() ->
                new ServiceException("未找到合适的库位,可能是库位已满"));
    }

}