yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProductServiceImpl.java
@@ -2,6 +2,10 @@
import cn.hutool.core.util.ObjUtil;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import cn.iocoder.yudao.module.mes.dal.mysql.pro.route.MesProRouteMapper;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteDO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.product.MesProRouteProductSaveReqVO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProductDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
@@ -10,6 +14,7 @@
import cn.iocoder.yudao.module.mes.enums.md.MesMdItemTypeEnum;
import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemTypeService;
import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
@@ -32,6 +37,8 @@
    @Resource
    private MesProRouteProductMapper routeProductMapper;
    @Resource
    private MesProRouteMapper routeMapper;
    @Resource
    @Lazy
@@ -43,6 +50,29 @@
    private MesMdItemService itemService;
    @Resource
    private MesMdItemTypeService itemTypeService;
    @Resource
    private MesWmWarehouseAreaService warehouseAreaService;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void setTemplateReference(Long id) {
        MesProRouteProductDO initial = routeProductMapper.selectById(id);
        validateRouteProductExists(initial);
        MesProRouteDO route = routeMapper.selectOne(new LambdaQueryWrapperX<MesProRouteDO>()
                .eq(MesProRouteDO::getId, initial.getRouteId()).last("FOR UPDATE"));
        if (route == null) throw exception(PRO_ROUTE_NOT_EXISTS);
        MesProRouteProductDO current = routeProductMapper.selectById(id);
        validateRouteProductExists(current);
        if (!java.util.Objects.equals(current.getRouteId(), route.getId())) throw exception(PRO_ROUTE_PRODUCT_NOT_EXISTS);
        if (!isFinishedProduct(current.getItemId())) throw exception(PRO_ROUTE_TEMPLATE_REFERENCE_NOT_FINISHED);
        routeProductMapper.update(null, new LambdaUpdateWrapper<MesProRouteProductDO>()
                .eq(MesProRouteProductDO::getRouteId, route.getId())
                .eq(MesProRouteProductDO::getTemplateReference, true)
                .set(MesProRouteProductDO::getTemplateReference, false));
        if (routeProductMapper.updateById(new MesProRouteProductDO().setId(id).setTemplateReference(true)) != 1) {
            throw exception(PRO_ROUTE_PRODUCT_NOT_EXISTS);
        }
    }
    @Override
    public Long createRouteProduct(MesProRouteProductSaveReqVO createReqVO) {
@@ -52,6 +82,8 @@
        validateProductItem(createReqVO.getItemId());
        // 1.2 校验产品唯一性(一个产品只能关联一条工艺路线)
        validateItemUnique(null, createReqVO.getItemId());
        warehouseAreaService.validateWarehouseAreaExists(createReqVO.getWarehouseId(),
                createReqVO.getLocationId(), createReqVO.getAreaId());
        // 2. 插入
        MesProRouteProductDO routeProduct = BeanUtils.toBean(createReqVO, MesProRouteProductDO.class);
@@ -69,6 +101,8 @@
        validateProductItem(updateReqVO.getItemId());
        // 1.3 校验产品唯一性
        validateItemUnique(updateReqVO.getId(), updateReqVO.getItemId());
        warehouseAreaService.validateWarehouseAreaExists(updateReqVO.getWarehouseId(),
                updateReqVO.getLocationId(), updateReqVO.getAreaId());
        // 2. 更新
        MesProRouteProductDO updateObj = BeanUtils.toBean(updateReqVO, MesProRouteProductDO.class);
@@ -102,6 +136,18 @@
        }
    }
    private boolean isFinishedProduct(Long itemId) {
        MesMdItemDO item = itemService.validateItemExists(itemId);
        MesMdItemTypeDO type = itemTypeService.getItemType(item.getItemTypeId());
        java.util.Set<Long> seen = new java.util.HashSet<>();
        while (type != null && seen.add(type.getId())) {
            if ("FG".equals(type.getCode())) return true;
            if (type.getParentId() == null || MesMdItemTypeDO.PARENT_ID_ROOT.equals(type.getParentId())) break;
            type = itemTypeService.getItemType(type.getParentId());
        }
        return false;
    }
    private void validateProductItem(Long itemId) {
        MesMdItemDO item = itemService.validateItemExistsAndEnable(itemId);
        MesMdItemTypeDO itemType = itemTypeService.getItemType(item.getItemTypeId());