package com.ruoyi.production;
|
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.ruoyi.basic.mapper.ProductModelMapper;
|
import com.ruoyi.basic.pojo.ProductModel;
|
import com.ruoyi.production.mapper.ProcessRouteItemMapper;
|
import com.ruoyi.production.mapper.ProcessRouteMapper;
|
import com.ruoyi.production.pojo.ProcessRoute;
|
import com.ruoyi.production.pojo.ProcessRouteItem;
|
import org.junit.jupiter.api.Test;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.test.annotation.Rollback;
|
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.util.CollectionUtils;
|
|
import java.util.ArrayList;
|
import java.util.Collections;
|
import java.util.Comparator;
|
import java.util.HashMap;
|
import java.util.LinkedHashMap;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.Objects;
|
import java.util.stream.Collectors;
|
|
/**
|
* 工艺路线项目补齐测试。
|
*/
|
@SpringBootTest
|
public class ProcessRouteItemCopyTest {
|
|
@Autowired
|
private ProductModelMapper productModelMapper;
|
|
@Autowired
|
private ProcessRouteMapper processRouteMapper;
|
|
@Autowired
|
private ProcessRouteItemMapper processRouteItemMapper;
|
|
@Test
|
@Rollback(false)
|
@Transactional(rollbackFor = Exception.class)
|
public void copyAllProcessRouteItemsByProductId() {
|
List<ProductModel> allProductModels = productModelMapper.selectList(
|
Wrappers.<ProductModel>lambdaQuery()
|
.isNotNull(ProductModel::getProductId)
|
.orderByAsc(ProductModel::getProductId)
|
.orderByAsc(ProductModel::getId)
|
);
|
if (CollectionUtils.isEmpty(allProductModels)) {
|
throw new IllegalStateException("未查询到任何产品规格");
|
}
|
|
Map<Long, List<ProductModel>> productModelGroups = allProductModels.stream()
|
.collect(Collectors.groupingBy(ProductModel::getProductId, LinkedHashMap::new, Collectors.toList()));
|
|
List<CopySummary> summaries = new ArrayList<>();
|
for (Map.Entry<Long, List<ProductModel>> entry : productModelGroups.entrySet()) {
|
CopySummary summary = copyProcessRouteItems(entry.getKey(), entry.getValue());
|
summaries.add(summary);
|
printProductSummary(summary);
|
}
|
|
printBatchSummary(summaries);
|
}
|
|
private CopySummary copyProcessRouteItems(Long productId, List<ProductModel> productModels) {
|
if (CollectionUtils.isEmpty(productModels)) {
|
return CopySummary.skipped(productId, 0, 0, "未查询到产品大类对应的规格");
|
}
|
|
Map<Long, ProductModel> productModelMap = productModels.stream()
|
.collect(Collectors.toMap(ProductModel::getId, item -> item, (left, right) -> left, LinkedHashMap::new));
|
List<Long> productModelIds = new ArrayList<>(productModelMap.keySet());
|
|
List<ProcessRoute> routeList = processRouteMapper.selectList(
|
Wrappers.<ProcessRoute>lambdaQuery()
|
.in(ProcessRoute::getProductModelId, productModelIds)
|
.orderByAsc(ProcessRoute::getId)
|
);
|
if (CollectionUtils.isEmpty(routeList)) {
|
return CopySummary.skipped(productId, productModels.size(), 0, "未查询到产品大类对应的工艺路线");
|
}
|
|
Map<Long, List<ProcessRouteItem>> routeItemMap = loadRouteItemMap(routeList);
|
ProcessRoute templateRoute = findTemplateRouteOrNull(routeList, routeItemMap);
|
if (templateRoute == null) {
|
return CopySummary.skipped(productId, productModels.size(), routeList.size(), "当前产品大类下没有可作为模板的完整路线项目");
|
}
|
|
List<ProcessRouteItem> templateItems = routeItemMap.getOrDefault(templateRoute.getId(), Collections.emptyList())
|
.stream()
|
.sorted(Comparator
|
.comparing(ProcessRouteItem::getDragSort, Comparator.nullsLast(Integer::compareTo))
|
.thenComparing(ProcessRouteItem::getId))
|
.collect(Collectors.toList());
|
|
int copiedRouteCount = 0;
|
int skippedRouteCount = 0;
|
int insertedRouteItemCount = 0;
|
|
for (ProcessRoute targetRoute : routeList) {
|
if (Objects.equals(templateRoute.getId(), targetRoute.getId())) {
|
skippedRouteCount++;
|
continue;
|
}
|
|
List<ProcessRouteItem> targetItems = routeItemMap.getOrDefault(targetRoute.getId(), Collections.emptyList());
|
if (!targetItems.isEmpty()) {
|
skippedRouteCount++;
|
continue;
|
}
|
|
int copiedItems = copyTemplateItems(templateItems, targetRoute);
|
copiedRouteCount++;
|
insertedRouteItemCount += copiedItems;
|
}
|
|
return CopySummary.copied(
|
productId,
|
productModels.size(),
|
templateRoute.getId(),
|
templateRoute.getProcessRouteCode(),
|
routeList.size(),
|
copiedRouteCount,
|
skippedRouteCount,
|
insertedRouteItemCount
|
);
|
}
|
|
private Map<Long, List<ProcessRouteItem>> loadRouteItemMap(List<ProcessRoute> routeList) {
|
List<Long> routeIds = routeList.stream()
|
.map(ProcessRoute::getId)
|
.filter(Objects::nonNull)
|
.collect(Collectors.toList());
|
if (routeIds.isEmpty()) {
|
return Collections.emptyMap();
|
}
|
|
List<ProcessRouteItem> routeItems = processRouteItemMapper.selectList(
|
Wrappers.<ProcessRouteItem>lambdaQuery()
|
.in(ProcessRouteItem::getRouteId, routeIds)
|
.orderByAsc(ProcessRouteItem::getRouteId)
|
.orderByAsc(ProcessRouteItem::getDragSort)
|
.orderByAsc(ProcessRouteItem::getId)
|
);
|
|
Map<Long, List<ProcessRouteItem>> routeItemMap = new HashMap<>();
|
for (ProcessRouteItem routeItem : routeItems) {
|
routeItemMap.computeIfAbsent(routeItem.getRouteId(), key -> new ArrayList<>()).add(routeItem);
|
}
|
return routeItemMap;
|
}
|
|
private ProcessRoute findTemplateRouteOrNull(List<ProcessRoute> routeList,
|
Map<Long, List<ProcessRouteItem>> routeItemMap) {
|
return routeList.stream()
|
.filter(item -> routeItemCount(routeItemMap.getOrDefault(item.getId(), Collections.emptyList())) > 0)
|
.max(Comparator.comparingInt(item -> routeItemCount(routeItemMap.getOrDefault(item.getId(), Collections.emptyList()))))
|
.orElse(null);
|
}
|
|
private int routeItemCount(List<ProcessRouteItem> routeItems) {
|
return routeItems == null ? 0 : routeItems.size();
|
}
|
|
private int copyTemplateItems(List<ProcessRouteItem> templateItems, ProcessRoute targetRoute) {
|
int insertedCount = 0;
|
for (int i = 0; i < templateItems.size(); i++) {
|
ProcessRouteItem sourceItem = templateItems.get(i);
|
ProcessRouteItem copiedItem = new ProcessRouteItem();
|
copiedItem.setRouteId(targetRoute.getId());
|
copiedItem.setProductModelId(sourceItem.getProductModelId());
|
copiedItem.setProcessId(sourceItem.getProcessId());
|
copiedItem.setTenantId(firstNotNull(targetRoute.getTenantId(), sourceItem.getTenantId()));
|
copiedItem.setDragSort(sourceItem.getDragSort() == null ? i + 1 : sourceItem.getDragSort());
|
copiedItem.setIsQuality(sourceItem.getIsQuality());
|
|
processRouteItemMapper.insert(copiedItem);
|
insertedCount++;
|
}
|
return insertedCount;
|
}
|
|
private Long firstNotNull(Long first, Long second) {
|
return first != null ? first : second;
|
}
|
|
private void printProductSummary(CopySummary summary) {
|
if (summary.isProductSkipped()) {
|
System.out.printf(
|
"跳过产品分类:productId=%s,规格数=%s,工艺路线总数=%s,原因=%s%n",
|
summary.getProductId(),
|
summary.getProductModelCount(),
|
summary.getTotalRouteCount(),
|
summary.getSkipReason()
|
);
|
return;
|
}
|
|
System.out.printf(
|
"处理产品分类:productId=%s,模板工艺路线=%s(%s),规格数=%s,工艺路线总数=%s,已补齐路线=%s,跳过路线=%s,新增路线项目=%s%n",
|
summary.getProductId(),
|
summary.getTemplateRouteCode(),
|
summary.getTemplateRouteId(),
|
summary.getProductModelCount(),
|
summary.getTotalRouteCount(),
|
summary.getCopiedRouteCount(),
|
summary.getSkippedRouteCount(),
|
summary.getInsertedRouteItemCount()
|
);
|
}
|
|
private void printBatchSummary(List<CopySummary> summaries) {
|
int productCount = summaries.size();
|
int skippedProductCount = 0;
|
int totalRouteCount = 0;
|
int copiedRouteCount = 0;
|
int skippedRouteCount = 0;
|
int insertedRouteItemCount = 0;
|
|
for (CopySummary summary : summaries) {
|
if (summary.isProductSkipped()) {
|
skippedProductCount++;
|
}
|
totalRouteCount += summary.getTotalRouteCount();
|
copiedRouteCount += summary.getCopiedRouteCount();
|
skippedRouteCount += summary.getSkippedRouteCount();
|
insertedRouteItemCount += summary.getInsertedRouteItemCount();
|
}
|
|
System.out.printf(
|
"工艺路线项目批量复制完成:产品分类数=%s,已处理分类=%s,跳过分类=%s,工艺路线总数=%s,已补齐路线=%s,跳过路线=%s,新增路线项目=%s%n",
|
productCount,
|
productCount - skippedProductCount,
|
skippedProductCount,
|
totalRouteCount,
|
copiedRouteCount,
|
skippedRouteCount,
|
insertedRouteItemCount
|
);
|
}
|
|
private static class CopySummary {
|
private final Long productId;
|
private final int productModelCount;
|
private final Long templateRouteId;
|
private final String templateRouteCode;
|
private final int totalRouteCount;
|
private final int copiedRouteCount;
|
private final int skippedRouteCount;
|
private final int insertedRouteItemCount;
|
private final String skipReason;
|
|
private CopySummary(Long productId,
|
int productModelCount,
|
Long templateRouteId,
|
String templateRouteCode,
|
int totalRouteCount,
|
int copiedRouteCount,
|
int skippedRouteCount,
|
int insertedRouteItemCount,
|
String skipReason) {
|
this.productId = productId;
|
this.productModelCount = productModelCount;
|
this.templateRouteId = templateRouteId;
|
this.templateRouteCode = templateRouteCode;
|
this.totalRouteCount = totalRouteCount;
|
this.copiedRouteCount = copiedRouteCount;
|
this.skippedRouteCount = skippedRouteCount;
|
this.insertedRouteItemCount = insertedRouteItemCount;
|
this.skipReason = skipReason;
|
}
|
|
private static CopySummary copied(Long productId,
|
int productModelCount,
|
Long templateRouteId,
|
String templateRouteCode,
|
int totalRouteCount,
|
int copiedRouteCount,
|
int skippedRouteCount,
|
int insertedRouteItemCount) {
|
return new CopySummary(
|
productId,
|
productModelCount,
|
templateRouteId,
|
templateRouteCode,
|
totalRouteCount,
|
copiedRouteCount,
|
skippedRouteCount,
|
insertedRouteItemCount,
|
null
|
);
|
}
|
|
private static CopySummary skipped(Long productId, int productModelCount, int totalRouteCount, String skipReason) {
|
return new CopySummary(
|
productId,
|
productModelCount,
|
null,
|
null,
|
totalRouteCount,
|
0,
|
totalRouteCount,
|
0,
|
skipReason
|
);
|
}
|
|
private Long getProductId() {
|
return productId;
|
}
|
|
private int getProductModelCount() {
|
return productModelCount;
|
}
|
|
private Long getTemplateRouteId() {
|
return templateRouteId;
|
}
|
|
private String getTemplateRouteCode() {
|
return templateRouteCode;
|
}
|
|
private int getTotalRouteCount() {
|
return totalRouteCount;
|
}
|
|
private int getCopiedRouteCount() {
|
return copiedRouteCount;
|
}
|
|
private int getSkippedRouteCount() {
|
return skippedRouteCount;
|
}
|
|
private int getInsertedRouteItemCount() {
|
return insertedRouteItemCount;
|
}
|
|
private String getSkipReason() {
|
return skipReason;
|
}
|
|
private boolean isProductSkipped() {
|
return skipReason != null;
|
}
|
}
|
}
|