package com.ruoyi.stock.support; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.production.mapper.ProductProcessMapper; import com.ruoyi.production.mapper.ProductProcessRouteItemMapper; import com.ruoyi.production.mapper.ProductionProductMainMapper; import com.ruoyi.production.mapper.ProductionProductOutputMapper; import com.ruoyi.production.pojo.ProductProcess; import com.ruoyi.production.pojo.ProductProcessRouteItem; import com.ruoyi.production.pojo.ProductionProductMain; import com.ruoyi.production.pojo.ProductionProductOutput; import org.springframework.stereotype.Component; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @Component public class FinishedProductStockDimensionResolver { private static final String PROCESS_COPPER = "印铜"; private static final String PROCESS_SILVER = "印银"; private static final String PROCESS_CATEGORY_COPPER = "铜极"; private static final String PROCESS_CATEGORY_SILVER = "银极"; private static final String VOLTAGE_PARAMETER = "电压"; private final ProductionProductMainMapper productionProductMainMapper; private final ProductionProductOutputMapper productionProductOutputMapper; private final ProductProcessRouteItemMapper productProcessRouteItemMapper; private final ProductProcessMapper productProcessMapper; public FinishedProductStockDimensionResolver(ProductionProductMainMapper productionProductMainMapper, ProductionProductOutputMapper productionProductOutputMapper, ProductProcessRouteItemMapper productProcessRouteItemMapper, ProductProcessMapper productProcessMapper) { this.productionProductMainMapper = productionProductMainMapper; this.productionProductOutputMapper = productionProductOutputMapper; this.productProcessRouteItemMapper = productProcessRouteItemMapper; this.productProcessMapper = productProcessMapper; } /** * 解析成品入库类别。 * 当工序为印铜时返回铜极,当工序为印银时返回银极。 */ public String resolveProcessCategory(Long productMainId) { ProductionProductMain productionProductMain = loadProductionMain(productMainId); ProductProcessRouteItem routeItem = loadRouteItem(productionProductMain); if (routeItem.getProductRouteId() == null) { throw new ServiceException("工艺路线未绑定工艺明细,无法确定成品类别"); } return resolveProcessCategoryByRouteId(routeItem.getProductRouteId()); } /** * 解析成品入库电压,来源于报工 otherData 中的“电压”参数。 */ public String resolveVoltage(Long productMainId) { List outputs = loadOutputs(productMainId); for (ProductionProductOutput output : outputs) { String voltage = resolveVoltageValue(output.getOtherData()); if (StringUtils.isNotBlank(voltage)) { return voltage; } } throw new ServiceException("请配置参数电压"); } private ProductionProductMain loadProductionMain(Long productMainId) { if (productMainId == null) { throw new ServiceException("报工ID不能为空"); } ProductionProductMain productionProductMain = productionProductMainMapper.selectById(productMainId); if (productionProductMain == null) { throw new ServiceException("报工记录不存在,无法确定成品库存维度"); } return productionProductMain; } private ProductProcessRouteItem loadRouteItem(ProductionProductMain productionProductMain) { if (productionProductMain.getProductProcessRouteItemId() == null) { throw new ServiceException("报工未关联工艺路线明细,无法确定成品库存维度"); } ProductProcessRouteItem routeItem = productProcessRouteItemMapper.selectById(productionProductMain.getProductProcessRouteItemId()); if (routeItem == null) { throw new ServiceException("工艺路线明细不存在,无法确定成品库存维度"); } return routeItem; } private List loadOutputs(Long productMainId) { List outputs = productionProductOutputMapper.selectList( new LambdaQueryWrapper() .eq(ProductionProductOutput::getProductMainId, productMainId) ); if (CollectionUtils.isEmpty(outputs)) { throw new ServiceException("报工输出记录不存在,无法确定成品库存维度"); } return outputs; } private String resolveProcessCategoryByRouteId(Long productRouteId) { List routeItems = productProcessRouteItemMapper.selectList( new LambdaQueryWrapper() .eq(ProductProcessRouteItem::getProductRouteId, productRouteId) ); if (CollectionUtils.isEmpty(routeItems)) { throw new ServiceException("订单工艺路线未配置工序,无法确定成品类别"); } Set processIds = routeItems.stream() .map(ProductProcessRouteItem::getProcessId) .filter(id -> id != null) .collect(Collectors.toSet()); if (processIds.isEmpty()) { throw new ServiceException("订单工艺路线未配置工序,无法确定成品类别"); } List processes = productProcessMapper.selectBatchIds(processIds); Set matchedCategories = processes.stream() .map(ProductProcess::getName) .filter(name -> PROCESS_COPPER.equals(name) || PROCESS_SILVER.equals(name)) .collect(Collectors.toCollection(LinkedHashSet::new)); if (matchedCategories.isEmpty()) { throw new ServiceException("订单工艺路线未配置印铜/印银工序,无法确定成品类别"); } if (matchedCategories.size() > 1) { throw new ServiceException("订单工艺路线同时配置了印铜和印银,无法确定成品类别"); } String matchedProcess = matchedCategories.iterator().next(); if (PROCESS_COPPER.equals(matchedProcess)) { return PROCESS_CATEGORY_COPPER; } return PROCESS_CATEGORY_SILVER; } private String resolveVoltageValue(String otherData) { if (StringUtils.isBlank(otherData)) { return null; } Object parsed; try { parsed = JSON.parse(otherData); } catch (Exception ex) { throw new ServiceException("报工参数格式错误,无法解析电压"); } String voltage = StringUtils.trim(findVoltageValue(parsed)); return StringUtils.isBlank(voltage) ? null : voltage; } private String findVoltageValue(Object node) { if (node instanceof JSONArray) { JSONArray array = (JSONArray) node; for (Object item : array) { String voltage = findVoltageValue(item); if (StringUtils.isNotBlank(voltage)) { return voltage; } } return null; } if (node instanceof JSONObject) { JSONObject object = (JSONObject) node; if (VOLTAGE_PARAMETER.equals(StringUtils.trim(object.getString("parameterItem")))) { String value = StringUtils.trim(object.getString("value")); if (StringUtils.isNotBlank(value)) { return value; } } for (Object value : object.values()) { String voltage = findVoltageValue(value); if (StringUtils.isNotBlank(voltage)) { return voltage; } } } return null; } }