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.basic.mapper.ProductMapper;
|
import com.ruoyi.basic.mapper.ProductModelMapper;
|
import com.ruoyi.basic.pojo.Product;
|
import com.ruoyi.basic.pojo.ProductModel;
|
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;
|
private final ProductMapper productMapper;
|
private final ProductModelMapper productModelMapper;
|
|
public FinishedProductStockDimensionResolver(ProductionProductMainMapper productionProductMainMapper,
|
ProductionProductOutputMapper productionProductOutputMapper,
|
ProductProcessRouteItemMapper productProcessRouteItemMapper,
|
ProductProcessMapper productProcessMapper,
|
ProductMapper productMapper,
|
ProductModelMapper productModelMapper) {
|
this.productionProductMainMapper = productionProductMainMapper;
|
this.productionProductOutputMapper = productionProductOutputMapper;
|
this.productProcessRouteItemMapper = productProcessRouteItemMapper;
|
this.productProcessMapper = productProcessMapper;
|
this.productMapper = productMapper;
|
this.productModelMapper = productModelMapper;
|
}
|
|
/**
|
* 解析成品入库类别。
|
* 当工序为印铜时返回铜极,当工序为印银时返回银极。
|
*/
|
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<ProductionProductOutput> outputs = loadOutputs(productMainId);
|
|
Long productModelId = outputs.stream()
|
.map(ProductionProductOutput::getProductModelId)
|
.filter(id -> id != null)
|
.findFirst()
|
.orElse(null);
|
|
boolean isFinishedProduct = isFinishedProduct(productModelId);
|
|
for (ProductionProductOutput output : outputs) {
|
String voltage = resolveVoltageValue(output.getOtherData());
|
if (StringUtils.isNotBlank(voltage)) {
|
return voltage;
|
}
|
}
|
|
if (isFinishedProduct) {
|
throw new ServiceException("请配置参数电压");
|
}
|
|
return null;
|
}
|
|
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<ProductionProductOutput> loadOutputs(Long productMainId) {
|
List<ProductionProductOutput> outputs = productionProductOutputMapper.selectList(
|
new LambdaQueryWrapper<ProductionProductOutput>()
|
.eq(ProductionProductOutput::getProductMainId, productMainId)
|
);
|
if (CollectionUtils.isEmpty(outputs)) {
|
throw new ServiceException("报工输出记录不存在,无法确定成品库存维度");
|
}
|
return outputs;
|
}
|
|
private String resolveProcessCategoryByRouteId(Long productRouteId) {
|
List<ProductProcessRouteItem> routeItems = productProcessRouteItemMapper.selectList(
|
new LambdaQueryWrapper<ProductProcessRouteItem>()
|
.eq(ProductProcessRouteItem::getProductRouteId, productRouteId)
|
);
|
if (CollectionUtils.isEmpty(routeItems)) {
|
throw new ServiceException("订单工艺路线未配置工序,无法确定成品类别");
|
}
|
|
Long productModelId = routeItems.stream()
|
.map(ProductProcessRouteItem::getProductModelId)
|
.filter(id -> id != null)
|
.findFirst()
|
.orElse(null);
|
|
boolean isFinishedProduct = isFinishedProduct(productModelId);
|
|
Set<Long> processIds = routeItems.stream()
|
.map(ProductProcessRouteItem::getProcessId)
|
.filter(id -> id != null)
|
.collect(Collectors.toSet());
|
if (processIds.isEmpty()) {
|
throw new ServiceException("订单工艺路线未配置工序,无法确定成品类别");
|
}
|
List<ProductProcess> processes = productProcessMapper.selectBatchIds(processIds);
|
Set<String> matchedCategories = processes.stream()
|
.map(ProductProcess::getName)
|
.filter(name -> PROCESS_COPPER.equals(name) || PROCESS_SILVER.equals(name))
|
.collect(Collectors.toCollection(LinkedHashSet::new));
|
|
if (matchedCategories.isEmpty() && isFinishedProduct) {
|
throw new ServiceException("订单工艺路线未配置印铜/印银工序,无法确定成品类别");
|
}
|
|
if (matchedCategories.size() > 1) {
|
throw new ServiceException("订单工艺路线同时配置了印铜和印银,无法确定成品类别");
|
}
|
|
if (matchedCategories.isEmpty()) {
|
return null;
|
}
|
|
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;
|
}
|
|
private boolean isFinishedProduct(Long productModelId) {
|
if (productModelId == null) {
|
return false;
|
}
|
|
ProductModel productModel = productModelMapper.selectById(productModelId);
|
if (productModel == null || productModel.getProductId() == null) {
|
return false;
|
}
|
|
return isFinishedProductRecursive(productModel.getProductId());
|
}
|
|
private boolean isFinishedProductRecursive(Long productId) {
|
if (productId == null) {
|
return false;
|
}
|
|
Product product = productMapper.selectById(productId);
|
if (product == null) {
|
return false;
|
}
|
|
if ("成品".equals(product.getProductName())) {
|
return true;
|
}
|
|
if (product.getParentId() == null) {
|
return false;
|
}
|
|
return isFinishedProductRecursive(product.getParentId());
|
}
|
}
|