1
10 小时以前 6c3cc6842009f3897c3fb18bef8a6634fe653818
rsf-server/src/main/java/com/vincent/rsf/server/manager/utils/LocManageUtil.java
@@ -1,34 +1,88 @@
package com.vincent.rsf.server.manager.utils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.framework.common.SpringUtils;
import com.vincent.rsf.server.manager.entity.DeviceSite;
import com.vincent.rsf.server.manager.entity.Loc;
import com.vincent.rsf.server.manager.service.DeviceSiteService;
import com.vincent.rsf.server.manager.service.LocService;
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.api.utils.LocUtils;
import com.vincent.rsf.server.manager.controller.dto.ExistDto;
import com.vincent.rsf.server.manager.controller.dto.OrderOutItemDto;
import com.vincent.rsf.server.manager.controller.params.WaveToLocParams;
import com.vincent.rsf.server.manager.entity.*;
import com.vincent.rsf.server.manager.enums.TaskType;
import com.vincent.rsf.server.manager.enums.WaveRuleType;
import com.vincent.rsf.server.manager.service.*;
import com.vincent.rsf.server.manager.enums.LocStsType;
import org.apache.commons.lang3.StringUtils;
import java.util.Objects;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
public class LocManageUtil {
    /**
     * @author Ryan
     * @description  获取目标库位, 包含库位获取策略
     * @param
     * @return
     * @author Ryan
     * @description 获取目标库位, 包含库位获取策略
     * @time 2025/3/31 08:50
     */
    public static String getTargetLoc(Long areaId) {
        //TODO 库位策略后续排期
        LocService locService = SpringUtils.getBean(LocService.class);
        return getTargetLoc(areaId, null);
    }
    public static String getTargetLoc(Long areaId, Long containerType,List<Integer> rowList) {
        Long locType = containerType;
        //TODO 库位策略后续排期
        LocService locService = SpringUtils.getBean(LocService.class);
        Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>()
                .eq(!Objects.isNull(locType), Loc::getType, locType)
                .eq(Loc::getAreaId, areaId)
                .eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_O.type)
                .in(Objects.nonNull(rowList) && !rowList.isEmpty(), Loc::getRow, rowList)
                .orderByAsc(Loc::getLev)
                .orderByAsc(Loc::getCol)
                .orderByAsc(Loc::getRow)
                .eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_O.type), false
                .last("LIMIT 1")
        );
        return !Objects.isNull(loc) ? loc.getCode() : null;
    }
    public static String getTargetLoc(Long areaId, Long containerType) {
        Long locType = containerType;
//        if (!Objects.isNull(containerType)) {
//            LocTypeService locService = SpringUtils.getBean(LocTypeService.class);
//            if (containerType.equals(ContainerType.CONTAINER_TYPE_NORMAL.val)) {
//                LocType low = locService.getOne(new LambdaQueryWrapper<LocType>()
//                        .eq(LocType::getCode, "L"));
//                if (Objects.isNull(low)) {
//                    throw new CoolException("庫位類型不存在!!");
//                }
//                locType = low.getId();
//            } else {
//                LocType low = locService.getOne(new LambdaQueryWrapper<LocType>()
//                        .eq(LocType::getCode, "H"));
//                if (Objects.isNull(low)) {
//                    throw new CoolException("庫位類型不存在!!");
//                }
//                locType = low.getId();
//            }
//        }
        //TODO 库位策略后续排期
        LocService locService = SpringUtils.getBean(LocService.class);
        Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>()
                .eq(!Objects.isNull(locType), Loc::getType, locType)
                .eq(Loc::getAreaId, areaId)
                .eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_O.type)
                .orderByAsc(Loc::getLev)
                .orderByAsc(Loc::getCol)
                .orderByAsc(Loc::getRow)
                .last("LIMIT 1")
        );
        return !Objects.isNull(loc) ? loc.getCode() : null;
@@ -36,16 +90,235 @@
    /**
    * @author Ryan
    * @description 获取目标站点
    * @param
    * @return
    * @time 2025/3/31 09:49
    */
     * @param
     * @return
     * @author Ryan
     * @description 获取目标站点
     * @time 2025/3/31 09:49
     */
    public static String getTargetSite() {
        //TODO 站点策略后续排期
        DeviceSiteService deviceSite = SpringUtils.getBean(DeviceSiteService.class);
        DeviceSite loc = deviceSite.getOne(new LambdaQueryWrapper<DeviceSite>().eq(DeviceSite::getStatus, 1), false);
        return !Objects.isNull(loc) ? loc.getSite() : null;
    }
    /**
     * 出库策略:--〈效率优化〉
     *
     * @param matnrCode
     * @param splrBatch
     * @param anfme
     * @return
     */
    public static List<LocItem> getEfficiencyFirstItemList(String matnrCode, String splrBatch, Double anfme) {
        LambdaQueryWrapper<LocItem> locItemQueryWrapper = new LambdaQueryWrapper<>();
        locItemQueryWrapper.eq(LocItem::getMatnrCode, matnrCode);
        locItemQueryWrapper.eq(StringUtils.isNotBlank(splrBatch), LocItem::getBatch, splrBatch);
        String applySql = String.format(
                "EXISTS (SELECT 1 FROM man_loc ml " +
                        "WHERE ml.use_status = '%s'" +
                        "AND ml.id = man_loc_item.loc_id " +
                        ")",
                LocStsType.LOC_STS_TYPE_F.type
        );
        locItemQueryWrapper.apply(applySql);
        LocItemService locItemService = SpringUtils.getBean(LocItemService.class);
        List<LocItem> locItems = locItemService.list(locItemQueryWrapper);
        locItems.sort(Comparator.comparing((LocItem item) -> !LocUtils.isShallowLoc(item.getLocCode())));
        List<LocItem> locsSet = locItems.stream().filter(locItem -> locItem.getAnfme().compareTo(anfme) == 0.0).collect(Collectors.toList());
        if (!locsSet.isEmpty()) {
            return locsSet;
        }
        return locItems;
    }
    /**
     * 出库策略:--<先进先出>
     *
     * @param matnrCode
     * @param splrBatch
     * @param anfme
     * @return
     */
    public static List<LocItem> getFirstInFirstOutItemList(String matnrCode, String splrBatch, Double anfme) {
        LambdaQueryWrapper<LocItem> locItemQueryWrapper = new LambdaQueryWrapper<>();
        locItemQueryWrapper.eq(LocItem::getMatnrCode, matnrCode);
        locItemQueryWrapper.eq(StringUtils.isNotEmpty(splrBatch), LocItem::getBatch, splrBatch);
        //如果批次不为空,按批次先后出库
        if (StringUtils.isNotBlank(splrBatch)) {
            locItemQueryWrapper.orderByAsc(LocItem::getBatch);
        } else {
            locItemQueryWrapper.orderByAsc(LocItem::getCreateTime);
        }
        String applySql = String.format(
                "EXISTS (SELECT 1 FROM man_loc ml " +
                        "WHERE ml.use_status = '%s'" +
                        "AND ml.id = man_loc_item.loc_id " +
                        ")",
                LocStsType.LOC_STS_TYPE_F.type
        );
        locItemQueryWrapper.apply(applySql);
        LocItemService locItemService = SpringUtils.getBean(LocItemService.class);
        List<LocItem> locItems = locItemService.list(locItemQueryWrapper);
        return locItems;
    }
    /**
     * 获取出库库位信息
     *
     * @param params
     * @param waveRule
     * @return
     */
    public static List<OrderOutItemDto> getOutOrderList(List<WaveToLocParams> params, WaveRule waveRule) {
        LocService locService = SpringUtils.getBean(LocService.class);
        LocItemService locItemService = SpringUtils.getBean(LocItemService.class);
        DeviceSiteService deviceSiteService = SpringUtils.getBean(DeviceSiteService.class);
        BasStationAreaService basStationAreaService = SpringUtils.getBean(BasStationAreaService.class);
//        List<BasStationArea> basStationAreas = basStationAreaService.list(new LambdaQueryWrapper<>());//
        List<Loc> locList = new  ArrayList<>();
        List<OrderOutItemDto> list = new ArrayList<>();
        //不让站点重复使用问题
        List<BasStation> stations = new ArrayList<>();
        Set<ExistDto> existDtos = new HashSet<>();
        for (WaveToLocParams item : params) {
            BigDecimal issued = new BigDecimal(item.getAnfme().toString())
                    .subtract(new BigDecimal(item.getWorkQty().toString()));
            if (issued.doubleValue() <= 0) {
                continue;
            }
            List<LocItem> locItems;
            if (Objects.isNull(waveRule)) {
                locItems = LocManageUtil.getFirstInFirstOutItemList(item.getMatnrCode(), item.getBatch(), item.getAnfme());
            } else {
                if (WaveRuleType.Efficiency_First.type.equals(waveRule.getType())) {
                    locItems = LocManageUtil.getEfficiencyFirstItemList(item.getMatnrCode(), item.getBatch(), item.getAnfme());
                } else if (WaveRuleType.First_In_First_Out.type.equals(waveRule.getType())) {
                    locItems = LocManageUtil.getFirstInFirstOutItemList(item.getMatnrCode(), item.getBatch(), item.getAnfme());
                } else {
                    locItems = LocManageUtil.getFirstInFirstOutItemList(item.getMatnrCode(), item.getBatch(), item.getAnfme());
                }
            }
            for (LocItem locItem : locItems) {
                Loc loc = locService.getById(locItem.getLocId());
                List<LocItem> itemList = locItemService.list(new LambdaQueryWrapper<LocItem>().eq(LocItem::getLocId, loc.getId()));
                if (issued.doubleValue() > 0 && locList.contains(loc)) {
                    for (OrderOutItemDto itemDto : list) {
                        if (itemDto.getLoc().equals(loc)) {
                            ExistDto existDto = new ExistDto().setBatch(locItem.getBatch()).setMatnr(locItem.getMatnrCode()).setLocNo(locItem.getLocCode());
                            if (existDtos.add(existDto)) {
                                locItem.setOutQty(issued.doubleValue() >= locItem.getAnfme() ? locItem.getAnfme() : issued.doubleValue());
                                locItem.setBarcode(loc.getBarcode())
                                        .setSourceId(item.getWaveId())//波次ID
                                        .setSource(item.getItemId());//波次明细ID
                                itemDto.getLocItemList().add(locItem);
                                issued = issued.subtract(new BigDecimal(locItem.getAnfme().toString()));
                            }
                            break;
                        }
                    }
                } else if (issued.doubleValue() > 0) {
                    ExistDto existDto = new ExistDto().setBatch(locItem.getBatch()).setMatnr(locItem.getMatnrCode()).setLocNo(locItem.getLocCode());
                    if (existDtos.add(existDto)) {
                        locItem.setOutQty(issued.doubleValue() >= locItem.getAnfme() ? locItem.getAnfme() : issued.doubleValue());
                        locItem.setBarcode(loc.getBarcode())
                                .setSourceId(item.getWaveId())//波次ID
                                .setSource(item.getItemId());//波次明细ID
                        OrderOutItemDto orderOutItemDto = new OrderOutItemDto();
//                        orderOutItemDto.setLocItem(locItem);
                        orderOutItemDto.setLoc(loc);
                        orderOutItemDto.getLocItemList().add(locItem);
                        BasContainer containerType = getContainerType(loc.getBarcode());
                        List<BasStationArea> basStationAreas = basStationAreaService.list(new LambdaQueryWrapper<BasStationArea>()
                                .apply("JSON_CONTAINS(cross_zone_area, '{0}') = 1", loc.getAreaId())//可执行库区区区域id
                                .apply("JSON_CONTAINS(container_type, '{0}') = 1", containerType)//容器类型
//                                .apply("JSON_CONTAINS(station_alias, '\"{0}\"') = 1", null)//区域包含站点集
                                .eq(BasStationArea::getDeleted, 0));// 通常需要加上未删除条件
                        List<String> targSiteAreaList = new ArrayList<>();
                        for (BasStationArea basStationArea : basStationAreas) {
                            targSiteAreaList.add(basStationArea.getStationAreaId());
                        }
                        int count = 0;
                        for (BasStationArea basStationArea : basStationAreas) {
                            count++;
                            if (!basStationArea.getStationAlias().isEmpty()) {
                                List<OrderOutItemDto.staListDto> maps = new ArrayList<>();
                                for (String site : basStationArea.getStationAlias()) {
                                    OrderOutItemDto.staListDto staListDto = new OrderOutItemDto.staListDto();
                                    staListDto.setStaNo(site);
                                    staListDto.setStaName(site);
                                    maps.add(staListDto);
                                }
                                orderOutItemDto.setStaNos(maps);
                                //获取满足条件站点
                                Set<String> stationSet = new HashSet<>(basStationArea.getStationAlias());
//                                Set<String> stationSet = basStationArea.getStationAlias().stream().collect(Collectors.toSet());
//                                Set<String> stationSet = deviceSites.stream().map(DeviceSite::getSite).collect(Collectors.toSet());
                                //已使用站点
                                Set<String> stas = stations.stream().map(BasStation::getStationName).collect(Collectors.toSet());
                                BasStationService basStationService = SpringUtils.getBean(BasStationService.class);
                                BasStation basStation = basStationService.getOne(new LambdaQueryWrapper<BasStation>()
                                        .eq(BasStation::getUseStatus, LocStsType.LOC_STS_TYPE_O.type)
                                        .in(BasStation::getStationName, stationSet)
                                        .notIn(!stas.isEmpty(), BasStation::getStationName, stas)
                                        .last("LIMIT 1"));
                                if (!Objects.isNull(basStation)) {
                                    stations.add(basStation);
                                }
                                if (count == basStationAreas.size()) {
                                    if (!Objects.isNull(basStation)) {
                                        orderOutItemDto.setSiteNo(basStation.getStationName());
//                                        throw new CoolException("站點不存在!!");
                                    }
                                } else {
                                    if (Objects.isNull(basStation)) {
                                        continue;
//                                        throw new CoolException("站點不存在!!");
                                    }
                                    orderOutItemDto.setSiteNo(basStation.getStationName());
                                }
                            }
                            orderOutItemDto.setSource(item.getItemId().toString())
                                    .setTargSiteAreaList(targSiteAreaList)
                                    .setSourceId(item.getWaveId().toString());
                            list.add(orderOutItemDto);
                            locList.add(loc);
                            issued = issued.subtract(new BigDecimal(locItem.getAnfme().toString()));
                            break;
                        }
                    }
                }
            }
        }
        return list;
    }
    //根据条码获取规则
    private static BasContainer getContainerType(String barcode) {
        BasContainerService basContainerService = SpringUtils.getBean(BasContainerService.class);
        if (Cools.isEmpty(barcode)) {
            throw new CoolException("容器码不能为空");
        }
        List<BasContainer> containers = basContainerService.list(new LambdaQueryWrapper<>());
        for (BasContainer container : containers) {
            String codeType = container.getCodeType();  // 获取正则表达式
            if (barcode.matches(codeType)) {  // 判断条码是否符合这个正则
                return container;
            }
        }
        return null;
    }
}