From a5f66f55b2c176e8504b8a077e00acfe2dfb4b00 Mon Sep 17 00:00:00 2001
From: liu <2021943741@qq.com>
Date: 星期五, 18 九月 2026 18:09:56 +0800
Subject: [PATCH] feat(生产报工): 报工完成按四类区分计数零件并分流质检入库
---
src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java | 227 ++++++++++++++++++++++++++++++++++++++------------------
1 files changed, 153 insertions(+), 74 deletions(-)
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
index 872d52f..ce9eee2 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
@@ -22,7 +22,6 @@
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.procurementrecord.utils.StockUtils;
-import com.ruoyi.production.bean.dto.ProductStructureDto;
import com.ruoyi.production.bean.dto.ProductionProductMainDto;
import com.ruoyi.production.enums.ProductOrderStatusEnum;
import com.ruoyi.production.mapper.*;
@@ -50,6 +49,7 @@
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
@@ -63,6 +63,16 @@
@AllArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class ProductionProductMainServiceImpl extends ServiceImpl<ProductionProductMainMapper, ProductionProductMain> implements ProductionProductMainService {
+
+ /**
+ * 鐢熶骇鎶ュ伐澶х被锛氬彧鍖哄垎灏忔彁鐞�/澶ф彁鐞�/璐濇柉锛屼笉鍐嶅尯鍒嗛浂浠躲��
+ * key涓哄叆搴撹鑼冨�硷紝value涓轰骇鍝佸悕绉板尮閰嶅埆鍚嶏紙鐜板満鏁版嵁璐濇柉鍐欎綔鈥滆礉鍙糕�濓級銆�
+ */
+ private static final Map<String, List<String>> MAJOR_CATEGORY_PATTERNS = new LinkedHashMap<>() {{
+ put("灏忔彁鐞�", List.of("灏忔彁鐞�"));
+ put("澶ф彁鐞�", List.of("澶ф彁鐞�"));
+ put("璐濇柉", List.of("璐濇柉", "璐濆徃"));
+ }};
private final ProductionProductMainMapper productionProductMainMapper;
private final SysUserMapper userMapper;
@@ -78,8 +88,6 @@
private final ProductionAccountMapper productionAccountMapper;
private final ProductionOperationTaskMapper productionOperationTaskMapper;
private final ProductionOrderMapper productionOrderMapper;
- private final ProductionOrderBomMapper productionOrderBomMapper;
- private final ProductionBomStructureMapper productionBomStructureMapper;
private final ProductionOrderRoutingOperationMapper productionOrderRoutingOperationMapper;
private final ProductionOrderRoutingOperationParamMapper productionOrderRoutingOperationParamMapper;
private final TechnologyRoutingOperationMapper technologyRoutingOperationMapper;
@@ -279,13 +287,31 @@
throw new ServiceException("浜у搧瑙勬牸涓嶅瓨鍦�");
}
+ // 鎶ュ伐瀹屾垚鏃跺璁℃暟鐨勯浂浠跺仛鍖哄垎锛氬悎鏍�/杞诲井杩斿伐/涓ラ噸杩斿伐/鎶ュ簾鍥涚被鏁伴噺銆�
+ BigDecimal qualifiedQty = defaultDecimal(dto.getQuantity());
+ BigDecimal reworkMinorQty = defaultDecimal(dto.getReworkMinorQty());
+ BigDecimal reworkMajorQty = defaultDecimal(dto.getReworkMajorQty());
+ BigDecimal scrapQtyInput = defaultDecimal(dto.getScrapQty());
+ if (qualifiedQty.compareTo(BigDecimal.ZERO) < 0
+ || reworkMinorQty.compareTo(BigDecimal.ZERO) < 0
+ || reworkMajorQty.compareTo(BigDecimal.ZERO) < 0
+ || scrapQtyInput.compareTo(BigDecimal.ZERO) < 0) {
+ throw new ServiceException("鎶ュ伐鏁伴噺涓嶈兘涓鸿礋鏁�");
+ }
+ if (qualifiedQty.add(reworkMinorQty).add(reworkMajorQty).add(scrapQtyInput).compareTo(BigDecimal.ZERO) <= 0) {
+ throw new ServiceException("璇锋寜鍚堟牸/杞诲井杩斿伐/涓ラ噸杩斿伐/鎶ュ簾鍒嗙被濉啓闆朵欢鏁伴噺");
+ }
+
ProductionProductMain productionProductMain = new ProductionProductMain();
productionProductMain.setProductNo(generateProductNo());
+ productionProductMain.setMajorCategory(resolveMajorCategory(productModel));
productionProductMain.setUserId(user == null ? dto.getUserId() : user.getUserId());
productionProductMain.setUserName(user == null ? dto.getUserName() : user.getNickName());
productionProductMain.setProductionOperationTaskId(taskId);
productionProductMain.setStatus(0);
- productionProductMain.setReportType(dto.getReportType() == null ? 0 : dto.getReportType());
+ productionProductMain.setReportType(dto.getReportType() != null
+ ? dto.getReportType()
+ : deriveReportType(qualifiedQty, reworkMinorQty, reworkMajorQty, scrapQtyInput));
productionProductMain.setAuditStatus(dto.getAuditStatus() == null ? 0 : dto.getAuditStatus());
productionProductMain.setAuditRemark(dto.getAuditRemark());
productionProductMain.setWorkHour(dto.getWorkHour());
@@ -293,30 +319,21 @@
syncOperationParamInputValue(dto, routingOperation.getId(), productionProductMain.getId());
createReportApprovalInstance(productionProductMain);
- List<ProductStructureDto> productStructureDtos = resolveInputStructures(
- productionOrder.getId(), routingOperation, productModel.getId());
- // 濡傛灉娌℃湁bom瀛愯妭鐐逛簡锛岄偅涔堟姇鍏ュ氨鏄粬鏈韩
- if (productStructureDtos.isEmpty()) {
- ProductStructureDto fallbackInput = new ProductStructureDto();
- fallbackInput.setProductModelId(productModel.getId());
- fallbackInput.setUnitQuantity(BigDecimal.ONE);
- productStructureDtos.add(fallbackInput);
- }
- for (ProductStructureDto item : productStructureDtos) {
- // 褰撳墠瀹炵幇鎸夊伐搴忔垚鍝佺洿鎺ヤ綔涓烘姇鍏ワ紝鍚庣画鑻ユ帴鍏ラ鏂欒褰曞彲鍦ㄨ繖閲屾浛鎹㈡潵婧愩��
- ProductionProductInput productionProductInput = new ProductionProductInput();
- productionProductInput.setProductionProductMainId(productionProductMain.getId());
- productionProductInput.setProductModelId(item.getProductModelId());
- productionProductInput.setInputQuantity(item.getUnitQuantity().multiply(defaultDecimal(dto.getQuantity())));
- productionProductInput.setQuantity(productionProductInput.getInputQuantity());
- productionProductInputMapper.insert(productionProductInput);
- }
+ // 闇�姹傚彉鏇达細鐢熶骇鎶ュ伐涓嶅啀鎸夐浂浠讹紙BOM缁撴瀯锛夋媶鍒嗘姇鍏ワ紝鎶曞叆鍗虫湰娆℃姤宸ョ殑浜у搧鏈韩锛屾寜澶х被缁熻銆�
+ ProductionProductInput productionProductInput = new ProductionProductInput();
+ productionProductInput.setProductionProductMainId(productionProductMain.getId());
+ productionProductInput.setProductModelId(productModel.getId());
+ productionProductInput.setInputQuantity(qualifiedQty);
+ productionProductInput.setQuantity(qualifiedQty);
+ productionProductInputMapper.insert(productionProductInput);
ProductionProductOutput productionProductOutput = new ProductionProductOutput();
productionProductOutput.setProductionProductMainId(productionProductMain.getId());
productionProductOutput.setProductModelId(productModel.getId());
productionProductOutput.setQuantity(defaultDecimal(dto.getQuantity()));
productionProductOutput.setScrapQty(defaultDecimal(dto.getScrapQty()));
+ productionProductOutput.setReworkMinorQty(reworkMinorQty);
+ productionProductOutput.setReworkMajorQty(reworkMajorQty);
productionProductOutputMapper.insert(productionProductOutput);
BigDecimal reportQty = defaultDecimal(productionProductOutput.getQuantity());
BigDecimal scrapQty = defaultDecimal(productionProductOutput.getScrapQty());
@@ -360,7 +377,8 @@
qualityInspectParamMapper.insert(param);
});
}
- } else {
+ } else if(isLastOperation){
+ //(鏈�鍚庝竴閬撳伐搴忔墠鍏ュ簱)
StockInventoryDto stockInventoryDto = new StockInventoryDto();
stockInventoryDto.setRecordId(productionProductMain.getId());
stockInventoryDto.setRecordType(String.valueOf(StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode()));
@@ -427,7 +445,69 @@
productionProductMain.getId(),
qualifiedBatchNo);
}
+ // 鍖哄垎鍑虹殑杩斿伐闆朵欢鐢熸垚涓嶅悎鏍煎搧寰呭鐞嗗崟锛岃繘鍏ヤ笉鍚堟牸鍝佺鐞嗙殑鎶ュ伐澶勭悊闂幆銆�
+ createReworkUnqualifiedRecords(productionProductMain, productModel, reworkMinorQty, reworkMajorQty);
return true;
+ }
+
+ private Integer deriveReportType(BigDecimal qualifiedQty, BigDecimal reworkMinorQty,
+ BigDecimal reworkMajorQty, BigDecimal scrapQty) {
+ if (qualifiedQty.compareTo(BigDecimal.ZERO) > 0) {
+ return 0;
+ }
+ if (reworkMinorQty.compareTo(BigDecimal.ZERO) > 0) {
+ return 1;
+ }
+ if (reworkMajorQty.compareTo(BigDecimal.ZERO) > 0) {
+ return 2;
+ }
+ if (scrapQty.compareTo(BigDecimal.ZERO) > 0) {
+ return 3;
+ }
+ return 0;
+ }
+
+ private void createReworkUnqualifiedRecords(ProductionProductMain productionProductMain,
+ ProductModel productModel,
+ BigDecimal reworkMinorQty,
+ BigDecimal reworkMajorQty) {
+ if (reworkMinorQty.compareTo(BigDecimal.ZERO) <= 0 && reworkMajorQty.compareTo(BigDecimal.ZERO) <= 0) {
+ return;
+ }
+ Product product = productMapper.selectById(productModel.getProductId());
+ if (product == null) {
+ throw new ServiceException("浜у搧涓嶅瓨鍦紝鏃犳硶鐢熸垚鎶ュ伐杩斿伐寰呭鐞嗗崟");
+ }
+ if (reworkMinorQty.compareTo(BigDecimal.ZERO) > 0) {
+ insertReworkUnqualified(productionProductMain, product, productModel, reworkMinorQty, 0);
+ }
+ if (reworkMajorQty.compareTo(BigDecimal.ZERO) > 0) {
+ insertReworkUnqualified(productionProductMain, product, productModel, reworkMajorQty, 1);
+ }
+ }
+
+ private void insertReworkUnqualified(ProductionProductMain productionProductMain,
+ Product product,
+ ProductModel productModel,
+ BigDecimal quantity,
+ int dealType) {
+ QualityUnqualified qualityUnqualified = new QualityUnqualified();
+ qualityUnqualified.setInspectType(1);
+ qualityUnqualified.setInspectState(0);
+ qualityUnqualified.setCheckTime(new Date());
+ qualityUnqualified.setCheckName(productionProductMain.getUserName());
+ qualityUnqualified.setProductId(product.getId());
+ qualityUnqualified.setProductName(product.getProductName());
+ qualityUnqualified.setModel(productModel.getModel());
+ qualityUnqualified.setUnit(productModel.getUnit());
+ qualityUnqualified.setQuantity(quantity);
+ qualityUnqualified.setProductModelId(productModel.getId());
+ qualityUnqualified.setProductMainId(productionProductMain.getId());
+ qualityUnqualified.setDefectivePhenomena("鐢熶骇鎶ュ伐銆�" + productionProductMain.getProductNo()
+ + "銆戣鏁板尯鍒�-" + (dealType == 0 ? "杞诲井杩斿伐" : "涓ラ噸杩斿伐"));
+ qualityUnqualified.setDealType(dealType);
+ qualityUnqualified.setDealResult("鎶ュ伐");
+ qualityUnqualifiedMapper.insert(qualityUnqualified);
}
private void createReportApprovalInstance(ProductionProductMain productionProductMain) {
@@ -467,6 +547,8 @@
BigDecimal schedulingNum = task == null ? BigDecimal.ZERO : defaultDecimal(task.getPlanQuantity());
BigDecimal finishedNum = output == null ? BigDecimal.ZERO : defaultDecimal(output.getQuantity());
BigDecimal scrapQty = output == null ? BigDecimal.ZERO : defaultDecimal(output.getScrapQty());
+ BigDecimal reworkMinorNum = output == null ? BigDecimal.ZERO : defaultDecimal(output.getReworkMinorQty());
+ BigDecimal reworkMajorNum = output == null ? BigDecimal.ZERO : defaultDecimal(output.getReworkMajorQty());
BigDecimal pendingNum = schedulingNum.subtract(finishedNum);
if (pendingNum.compareTo(BigDecimal.ZERO) < 0) {
pendingNum = BigDecimal.ZERO;
@@ -479,7 +561,9 @@
fields.add(buildReportField("workOrderNo", "宸ュ崟缂栧彿", "text", resolveWorkOrderNo(productionProductMain.getProductionOperationTaskId())));
fields.add(buildReportField("schedulingNum", "鎺掍骇鏁伴噺", "number", schedulingNum));
fields.add(buildReportField("pendingNum", "寰呯敓浜ф暟閲�", "number", pendingNum));
- fields.add(buildReportField("finishedNum", "鐢熶骇鍚堟牸鏁伴噺", "number", finishedNum));
+ fields.add(buildReportField("finishedNum", "鍚堟牸鏁伴噺", "number", finishedNum));
+ fields.add(buildReportField("reworkMinorQty", "杞诲井杩斿伐鏁伴噺", "number", reworkMinorNum));
+ fields.add(buildReportField("reworkMajorQty", "涓ラ噸杩斿伐鏁伴噺", "number", reworkMajorNum));
fields.add(buildReportField("scrapQty", "鎶ュ簾鏁伴噺", "number", scrapQty));
fields.add(buildReportField("reportType", "鎶ュ伐缁撴灉", "select", resolveReportTypeLabel(productionProductMain.getReportType())));
fields.add(buildReportField("workHour", "宸ユ椂", "number", productionProductMain.getWorkHour()));
@@ -496,6 +580,8 @@
formPayload.put("pendingNum", pendingNum);
formPayload.put("finishedNum", finishedNum);
formPayload.put("scrapQty", scrapQty);
+ formPayload.put("reworkMinorQty", reworkMinorNum);
+ formPayload.put("reworkMajorQty", reworkMajorNum);
formPayload.put("reportType", resolveReportTypeLabel(productionProductMain.getReportType()));
formPayload.put("workHour", productionProductMain.getWorkHour());
formPayload.put("auditStatus", resolveAuditStatusLabel(productionProductMain.getAuditStatus()));
@@ -654,62 +740,46 @@
return target;
}
- private List<ProductStructureDto> resolveInputStructures(Long productionOrderId,
- ProductionOrderRoutingOperation routingOperation,
- Long outputProductModelId) {
- if (productionOrderId == null || routingOperation == null || routingOperation.getTechnologyOperationId() == null) {
- return new ArrayList<>();
+ /**
+ * 闇�姹傦細鐢熶骇鎶ュ伐鍙尯鍒嗕骇鍝佸ぇ绫伙紙灏忔彁鐞�/澶ф彁鐞�/璐濇柉锛夛紝涓嶅啀鍖哄垎闆朵欢銆�
+ * 浠庝骇鍑轰骇鍝佽嚜韬悕绉板紑濮嬫部浜у搧鏍戝悜涓婂仛鍏抽敭瀛楀尮閰嶏紝鍛戒腑鍗冲彇瀵瑰簲瑙勮寖澶х被锛涙湭鍛戒腑杩斿洖 null銆�
+ * 浜у搧鏍戦《灞備负鈥滄垚鍝�/鍗婃垚鍝�/鍘熸枡鈥濈瓑搴撳瓨鍒嗙被锛屼笉鑳界洿鎺ュ綋浣滃ぇ绫伙紝鍥犳蹇呴』鑷簳鍚戜笂鍙栫涓�涓懡涓殑灞傜骇銆�
+ */
+ private String resolveMajorCategory(ProductModel productModel) {
+ if (productModel == null || productModel.getProductId() == null) {
+ return null;
}
- ProductionOrderBom orderBom = productionOrderBomMapper.selectOne(
- Wrappers.<ProductionOrderBom>lambdaQuery()
- .eq(ProductionOrderBom::getProductionOrderId, productionOrderId)
- .orderByDesc(ProductionOrderBom::getId)
- .last("limit 1"));
- if (orderBom == null || orderBom.getId() == null) {
- return new ArrayList<>();
- }
-
- List<ProductionBomStructure> bomNodeList = productionBomStructureMapper.selectList(
- Wrappers.<ProductionBomStructure>lambdaQuery()
- .eq(ProductionBomStructure::getProductionOrderBomId, orderBom.getId())
- .orderByAsc(ProductionBomStructure::getId));
- if (bomNodeList.isEmpty()) {
- return new ArrayList<>();
- }
-
- Map<Long, ProductionBomStructure> nodeMap = bomNodeList.stream()
- .filter(item -> item != null && item.getId() != null)
- .collect(Collectors.toMap(ProductionBomStructure::getId, item -> item, (left, right) -> left));
- Long currentOutputModelId = routingOperation.getProductModelId() != null
- ? routingOperation.getProductModelId()
- : outputProductModelId;
-
- Map<Long, BigDecimal> unitQtyByProductModel = new LinkedHashMap<>();
- for (ProductionBomStructure node : bomNodeList) {
- if (node == null || node.getParentId() == null || node.getProductModelId() == null) {
- continue;
+ Product product = productMapper.selectById(productModel.getProductId());
+ Set<Long> visited = new LinkedHashSet<>();
+ while (product != null && visited.add(product.getId())) {
+ String category = matchMajorCategory(product.getProductName());
+ if (category != null) {
+ return category;
}
- if (!Objects.equals(node.getTechnologyOperationId(), routingOperation.getTechnologyOperationId())) {
- continue;
+ if (product.getParentId() == null || product.getParentId() == 0L) {
+ break;
}
- ProductionBomStructure parent = nodeMap.get(node.getParentId());
- if (parent == null || !Objects.equals(parent.getProductModelId(), currentOutputModelId)) {
- continue;
- }
- unitQtyByProductModel.merge(node.getProductModelId(), defaultDecimal(node.getUnitQuantity()), BigDecimal::add);
+ product = productMapper.selectById(product.getParentId());
}
+ return null;
+ }
- List<ProductStructureDto> result = new ArrayList<>();
- for (Map.Entry<Long, BigDecimal> entry : unitQtyByProductModel.entrySet()) {
- if (entry.getValue().compareTo(BigDecimal.ZERO) <= 0) {
- continue;
- }
- ProductStructureDto item = new ProductStructureDto();
- item.setProductModelId(entry.getKey());
- item.setUnitQuantity(entry.getValue());
- result.add(item);
+ static String matchMajorCategory(String productName) {
+ if (productName == null || productName.isEmpty()) {
+ return null;
}
- return result;
+ // 鐞寸洅/鐞村绛夐厤浠跺悕绉板彲鑳藉甫鈥滆礉鍙糕�濈瓑瀛楁牱锛堝 SA璐濆徃濂楋級锛屾帓闄ゅ悗閬垮厤璇綊澶х被銆�
+ if (productName.contains("鐞寸洅") || productName.contains("鐞村") || productName.contains("寮撶洅")) {
+ return null;
+ }
+ for (Map.Entry<String, List<String>> entry : MAJOR_CATEGORY_PATTERNS.entrySet()) {
+ for (String alias : entry.getValue()) {
+ if (productName.contains(alias)) {
+ return entry.getKey();
+ }
+ }
+ }
+ return null;
}
private Boolean removeProductMainByProductionTask(ProductionProductMain productionProductMain) {
@@ -725,6 +795,13 @@
if (qualityUnqualifieds.size() > 0 && qualityUnqualifieds.get(0).getInspectState() == 1) {
throw new ServiceException("璇ユ潯鎶ュ伐宸茬粡涓嶅悎鏍煎鐞嗕簡锛屼笉鍏佽鍒犻櫎");
}
+ }
+ // 鎶ュ伐璁℃暟鍖哄垎鐩存帴浜х敓鐨勮繑宸ュ緟澶勭悊鍗曪細宸插鐞嗙殑涓嶅厑璁稿垹闄ゆ姤宸ワ紝鏈鐞嗙殑闅忔姤宸ヤ竴骞跺垹闄ゃ��
+ List<QualityUnqualified> reworkUnqualifieds = qualityUnqualifiedMapper.selectList(
+ Wrappers.<QualityUnqualified>lambdaQuery()
+ .eq(QualityUnqualified::getProductMainId, productionProductMain.getId()));
+ if (reworkUnqualifieds.stream().anyMatch(q -> Integer.valueOf(1).equals(q.getInspectState()))) {
+ throw new ServiceException("璇ユ潯鎶ュ伐鐨勮繑宸ラ浂浠跺凡鍋氫笉鍚堟牸澶勭悊锛屼笉鍏佽鍒犻櫎");
}
ProductionProductOutput productionProductOutput = productionProductOutputMapper.selectList(
Wrappers.<ProductionProductOutput>lambdaQuery()
@@ -772,6 +849,8 @@
}
}
+ qualityUnqualifiedMapper.delete(new LambdaQueryWrapper<QualityUnqualified>()
+ .eq(QualityUnqualified::getProductMainId, productionProductMain.getId()));
qualityInspectMapper.selectList(new LambdaQueryWrapper<QualityInspect>()
.eq(QualityInspect::getProductMainId, productionProductMain.getId())).forEach(q -> {
qualityInspectParamMapper.delete(new LambdaQueryWrapper<QualityInspectParam>()
--
Gitblit v1.9.3