From 0be02df3d287f802c76e5738916301a877dfaa0e Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期一, 27 四月 2026 16:56:12 +0800
Subject: [PATCH] feat: 生产报工与报工台账功能更改完成

---
 src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java |  604 ++++++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 472 insertions(+), 132 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 8be62c1..b21c4fd 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
@@ -11,12 +11,19 @@
 import com.ruoyi.basic.mapper.ProductModelMapper;
 import com.ruoyi.basic.pojo.Product;
 import com.ruoyi.basic.pojo.ProductModel;
-import com.ruoyi.common.enums.StockQualifiedRecordTypeEnum;
-import com.ruoyi.common.enums.StockUnQualifiedRecordTypeEnum;
+import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
+import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
+import com.ruoyi.common.enums.StockInUnQualifiedRecordTypeEnum;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.bean.BeanUtils;
 import com.ruoyi.procurementrecord.utils.StockUtils;
-import com.ruoyi.production.dto.ProductStructureDto;
 import com.ruoyi.production.dto.ProductionProductMainDto;
+import com.ruoyi.production.dto.ProductionReportDailySummaryDto;
+import com.ruoyi.production.dto.ProductionReportStateDto;
+import com.ruoyi.production.enums.ProductProcessEnum;
+import com.ruoyi.production.mapper.ProductionProductReportDailyMapper;
+import com.ruoyi.production.pojo.ProductionProductReportDaily;
 import com.ruoyi.production.mapper.*;
 import com.ruoyi.production.pojo.*;
 import com.ruoyi.production.service.ProductionProductMainService;
@@ -30,11 +37,15 @@
 import com.ruoyi.production.mapper.ProductionProductMainMapper;
 
 import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.time.Duration;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 @Service
 @AllArgsConstructor
@@ -42,6 +53,7 @@
 public class ProductionProductMainServiceImpl extends ServiceImpl<ProductionProductMainMapper, ProductionProductMain> implements ProductionProductMainService {
 
     private ProductionProductMainMapper productionProductMainMapper;
+    private ProductionProductReportDailyMapper productionProductReportDailyMapper;
 
 
     private ProductWorkOrderMapper productWorkOrderMapper;
@@ -50,24 +62,16 @@
     private SysUserMapper userMapper;
 
     private ProductionProductOutputMapper productionProductOutputMapper;
-
-
     private ProductModelMapper productModelMapper;
+    private ProductMapper productMapper;
+    private ProductProcessMapper productProcessMapper;
 
     private QualityInspectMapper qualityInspectMapper;
-
-    private ProductProcessMapper productProcessMapper;
-    private ProductProcessRouteMapper productProcessRouteMapper;
-
-    private ProductMapper productMapper;
-
-
-    private QualityTestStandardParamMapper qualityTestStandardParamMapper;
-    private QualityTestStandardMapper qualityTestStandardMapper;
+    private QualityUnqualifiedMapper qualityUnqualifiedMapper;
 
     private QualityInspectParamMapper qualityInspectParamMapper;
-
-    private ProductStructureMapper productStructureMapper;
+    private QualityTestStandardParamMapper qualityTestStandardParamMapper;
+    private QualityTestStandardMapper qualityTestStandardMapper;
 
     private ProductionProductInputMapper productionProductInputMapper;
 
@@ -79,27 +83,162 @@
 
 
     @Override
-    public IPage<ProductionProductMainDto> listPageProductionProductMainDto(Page page, ProductionProductMainDto productionProductMainDto) {
-        return productionProductMainMapper.listPageProductionProductMainDto(page, productionProductMainDto);
+    public IPage<ProductionProductMainDto> listPageProductionProductMainDto(Page<ProductionProductMainDto> page, ProductionProductMainDto productionProductMainDto) {
+        if (productionProductMainDto == null) {
+            productionProductMainDto = new ProductionProductMainDto();
+        }
+//        productionProductMainDto.setUserId(SecurityUtils.getUserId());
+        IPage<ProductionProductMainDto> result = productionProductMainMapper.listPageProductionProductMainDto(page, productionProductMainDto);
+        fillHourDefaults(result.getRecords());
+        return result;
+    }
+
+    @Override
+    public IPage<ProductionProductMainDto> listPageProductionProductMainDetailDto(Page<ProductionProductMainDto> page, ProductionProductMainDto productionProductMainDto) {
+        if (productionProductMainDto == null) {
+            productionProductMainDto = new ProductionProductMainDto();
+        }
+        IPage<ProductionProductMainDto> result = productionProductMainMapper.listPageProductionProductMainDetailDto(page, productionProductMainDto);
+        fillHourDefaults(result.getRecords());
+        return result;
+    }
+
+    @Override
+    public IPage<ProductionProductMainDto> listPageProductionProductMainDailyDto(Page<ProductionProductMainDto> page, ProductionProductMainDto productionProductMainDto) {
+        if (productionProductMainDto == null) {
+            productionProductMainDto = new ProductionProductMainDto();
+        }
+        IPage<ProductionProductMainDto> result = productionProductMainMapper.listPageProductionProductMainDailyDto(page, productionProductMainDto);
+        fillHourDefaults(result.getRecords());
+        return result;
+    }
+
+    private void fillHourDefaults(List<ProductionProductMainDto> records) {
+        if (records == null || records.isEmpty()) {
+            return;
+        }
+        records.forEach(item -> {
+            if (item.getProjectTotalHours() == null) {
+                item.setProjectTotalHours(BigDecimal.ZERO);
+            }
+            if (item.getProcessStandardHours() == null) {
+                item.setProcessStandardHours(BigDecimal.ZERO);
+            }
+            if (item.getActualReportHours() == null) {
+                item.setActualReportHours(BigDecimal.ZERO);
+            }
+            if (item.getDailyPersonHours() == null) {
+                item.setDailyPersonHours(BigDecimal.ZERO);
+            }
+        });
     }
 
     @Override
     public Boolean addProductMain(ProductionProductMainDto dto) {
-        SysUser user = userMapper.selectUserById(dto.getUserId());
-        ProductionProductMain productionProductMain = new ProductionProductMain();
-        //褰撳墠宸ヨ壓璺嚎瀵瑰簲鐨勫伐搴忚鎯�
-        ProductProcessRouteItem productProcessRouteItem = productProcessRouteItemMapper.selectById(dto.getProductProcessRouteItemId());
-        if (productProcessRouteItem == null) {
-            throw new RuntimeException("宸ヨ壓璺嚎椤逛笉瀛樺湪");
+        if (dto.getActionType() == null) {
+            if (dto.getId() != null) {
+                if (dto.getQuantity() == null || dto.getQuantity().compareTo(BigDecimal.ZERO) <= 0) {
+                    throw new ServiceException("缁撴潫鎶ュ伐澶辫触: 鏈鐢熶骇鏁伴噺蹇呴』澶т簬0");
+                }
+                return finishReport(dto);
+            }
+
+            Long workOrderId = dto.getWorkOrderId();
+            Long itemId = dto.getProductProcessRouteItemId();
+            if (workOrderId == null || itemId == null) {
+                throw new ServiceException("宸ュ崟ID鍜屽伐鑹鸿矾绾块」鐩甀D涓嶈兘涓虹┖");
+            }
+            ProductionProductMain running = getRunning(workOrderId, itemId);
+            if (running != null) {
+                if (dto.getQuantity() == null || dto.getQuantity().compareTo(BigDecimal.ZERO) <= 0) {
+                    throw new ServiceException("缁撴潫鎶ュ伐澶辫触: 鏈鐢熶骇鏁伴噺蹇呴』澶т簬0");
+                }
+                dto.setId(running.getId());
+                return finishReport(dto);
+            }
+            return startReport(dto);
         }
-        //褰撳墠鍏蜂綋宸ュ簭
-        ProductProcess productProcess = productProcessMapper.selectById(productProcessRouteItem.getProcessId());
-        //宸ヨ壓璺嚎涓綋鍓嶅伐搴忓搴旂殑浜у嚭瑙勬牸鍨嬪彿
-        ProductModel productModel = productModelMapper.selectById(productProcessRouteItem.getProductModelId());
-        //鏌ヨ璇ョ敓浜ц鍗曞搴旂殑bom
-        ProductProcessRoute productProcessRoute = productProcessRouteMapper.selectById(productProcessRouteItem.getProductRouteId());
-        /*鏂板鎶ュ伐涓昏〃*/
-        //鏌ヨ鏈�澶ф姤宸ョ紪鍙�
+
+        if (dto.getActionType() == 1) {
+            return startReport(dto);
+        }
+        if (dto.getActionType() == 2) {
+            return finishReport(dto);
+        }
+        throw new ServiceException("鏃犳晥鎶ュ伐鍔ㄤ綔: " + dto.getActionType());
+    }
+
+    @Override
+    public ProductionProductMain getRunning(Long workOrderId, Long productProcessRouteItemId) {
+        if (workOrderId == null || productProcessRouteItemId == null) {
+            throw new ServiceException("宸ュ崟ID鍜屽伐鑹鸿矾绾块」鐩甀D涓嶈兘涓虹┖");
+        }
+        Long currentUserId = SecurityUtils.getUserId();
+        return productionProductMainMapper.selectOne(
+                Wrappers.<ProductionProductMain>lambdaQuery()
+                        .eq(ProductionProductMain::getWorkOrderId, workOrderId)
+                        .eq(ProductionProductMain::getProductProcessRouteItemId, productProcessRouteItemId)
+                        .eq(ProductionProductMain::getUserId, currentUserId)
+                        .eq(ProductionProductMain::getStatus, 0)
+                        .orderByDesc(ProductionProductMain::getReportStartTime)
+                        .last("limit 1")
+        );
+    }
+
+    @Override
+    public List<ProductionReportDailySummaryDto> dailyDuration(Long workOrderId, Long productProcessRouteItemId, LocalDate startDate, LocalDate endDate) {
+        Long userId = SecurityUtils.getUserId();
+        return productionProductReportDailyMapper.listDailySummary(
+                workOrderId,
+                productProcessRouteItemId,
+                userId,
+                startDate,
+                endDate
+        );
+    }
+
+    @Override
+    public ProductionReportStateDto reportState(Long workOrderId, Long productProcessRouteItemId) {
+        ProductionProductMain running = getRunning(workOrderId, productProcessRouteItemId);
+        ProductionReportStateDto dto = new ProductionReportStateDto();
+        if (running == null) {
+            dto.setState(1);
+            return dto;
+        }
+        dto.setState(2);
+        dto.setRunningId(running.getId());
+        dto.setStartTime(running.getReportStartTime());
+        return dto;
+    }
+
+    private Boolean startReport(ProductionProductMainDto dto) {
+        if (dto.getWorkOrderId() == null || dto.getProductProcessRouteItemId() == null) {
+            throw new ServiceException("寮�濮嬫姤宸ュけ璐�: 宸ュ崟ID鍜屽伐鑹鸿矾绾块」鐩甀D涓嶈兘涓虹┖");
+        }
+        if (dto.getUserId() == null) {
+            dto.setUserId(SecurityUtils.getUserId());
+        }
+        if (dto.getUserId() == null) {
+            throw new ServiceException("寮�濮嬫姤宸ュけ璐�: 鏃犳硶鑾峰彇褰撳墠鐧诲綍浜�");
+        }
+
+        QueryWrapper<ProductionProductMain> runningWrapper = new QueryWrapper<>();
+        runningWrapper.eq("work_order_id", dto.getWorkOrderId())
+                .eq("product_process_route_item_id", dto.getProductProcessRouteItemId())
+                .eq("user_id", dto.getUserId())
+                .eq("status", 0);
+        Long runningCount = productionProductMainMapper.selectCount(runningWrapper);
+        if (runningCount != null && runningCount > 0) {
+            // 宸叉湁杩涜涓殑鎶ュ伐鏃讹紝涓嶅啀鏂板缓锛岀户缁部鐢ㄥ埌缁撴潫鎶ュ伐
+            return true;
+        }
+
+        SysUser user = userMapper.selectUserById(dto.getUserId());
+        if (user == null) {
+            throw new ServiceException("鎶ュ伐浜轰笉瀛樺湪");
+        }
+
+        ProductionProductMain productionProductMain = new ProductionProductMain();
         String datePrefix = "BG" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyMMdd"));
         QueryWrapper<ProductionProductMain> queryWrapper = new QueryWrapper<>();
         queryWrapper.select("MAX(product_no) as maxNo")
@@ -127,149 +266,341 @@
         String productNo = String.format("%s%03d", datePrefix, sequenceNumber);
         productionProductMain.setProductNo(productNo);
         productionProductMain.setUserId(dto.getUserId());
-        productionProductMain.setUserName(dto.getUserName());
+        productionProductMain.setUserName(user.getNickName());
         productionProductMain.setProductProcessRouteItemId(dto.getProductProcessRouteItemId());
         productionProductMain.setWorkOrderId(dto.getWorkOrderId());
         productionProductMain.setStatus(0);
+        productionProductMain.setReportStartTime(LocalDateTime.now());
         productionProductMainMapper.insert(productionProductMain);
-        /*鏂板鎶ュ伐鎶曞叆琛�*/
-        List<ProductStructureDto> productStructureDtos = productStructureMapper.listBybomAndProcess(productProcessRoute.getBomId(), productProcess.getId());
-        if (productStructureDtos.size() == 0) {
-            //濡傛灉璇ュ伐搴忔病鏈変骇鍝佺粨鏋勭殑鎶曞叆鍝�,閭h繖涓姇鍏ュ搧鍜屼骇鍑哄搧鏄悓涓�涓�
-            ProductStructureDto productStructureDto = new ProductStructureDto();
-            productStructureDto.setProductModelId(productProcessRouteItem.getProductModelId());
-            productStructureDto.setUnitQuantity(BigDecimal.ONE);
-            productStructureDtos.add(productStructureDto);
-        }
-        for (ProductStructureDto productStructureDto : productStructureDtos) {
+        return true;
+    }
 
-            ProductionProductInput productionProductInput = new ProductionProductInput();
-            productionProductInput.setProductModelId(productStructureDto.getProductModelId());
-            productionProductInput.setQuantity(productStructureDto.getUnitQuantity().multiply(dto.getQuantity()));
-            productionProductInput.setProductMainId(productionProductMain.getId());
-            productionProductInputMapper.insert(productionProductInput);
-            stockUtils.substractStock(productStructureDto.getProductModelId(), productionProductInput.getQuantity(), StockQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode(), productionProductMain.getId());
-
+    private Boolean finishReport(ProductionProductMainDto dto) {
+        if (dto.getId() == null) {
+            throw new ServiceException("缁撴潫鎶ュ伐澶辫触: 鎶ュ伐ID涓嶈兘涓虹┖");
         }
+        if (dto.getQuantity() == null || dto.getQuantity().compareTo(BigDecimal.ZERO) <= 0) {
+            throw new ServiceException("缁撴潫鎶ュ伐澶辫触: 鏈鐢熶骇鏁伴噺蹇呴』澶т簬0");
+        }
+        ProductionProductMain productionProductMain = productionProductMainMapper.selectById(dto.getId());
+        if (productionProductMain == null) {
+            throw new ServiceException("缁撴潫鎶ュ伐澶辫触: 鎶ュ伐璁板綍涓嶅瓨鍦�");
+        }
+        if (productionProductMain.getStatus() != null && productionProductMain.getStatus() == 1) {
+            throw new ServiceException("璇ユ姤宸ュ凡缁撴潫锛岃鍕块噸澶嶆彁浜�");
+        }
+        if (productionProductMain.getReportStartTime() == null) {
+            throw new ServiceException("璇ユ姤宸ョ己灏戝紑濮嬫椂闂达紝鏃犳硶缁撴潫");
+        }
+
+        LocalDateTime endTime = LocalDateTime.now();
+        long durationSeconds = Duration.between(productionProductMain.getReportStartTime(), endTime).getSeconds();
+        BigDecimal durationMinutes = secondsToMinutesExact(durationSeconds);
+        int finishRows = productionProductMainMapper.update(
+                null,
+                Wrappers.<ProductionProductMain>lambdaUpdate()
+                        .set(ProductionProductMain::getReportEndTime, endTime)
+                        .set(ProductionProductMain::getReportDurationMinutes, durationMinutes)
+                        .set(ProductionProductMain::getStatus, 1)
+                        .eq(ProductionProductMain::getId, productionProductMain.getId())
+                        .eq(ProductionProductMain::getStatus, 0)
+        );
+        if (finishRows <= 0) {
+            throw new ServiceException("璇ユ姤宸ュ凡缁撴潫锛岃鍕块噸澶嶆彁浜�");
+        }
+        productionProductMain.setReportEndTime(endTime);
+        productionProductMain.setReportDurationMinutes(durationMinutes);
+        productionProductMain.setStatus(1);
+
+        // 鍐欏叆鈥滄瘡鏃ユ椂闀挎槑缁嗏�濓紝璺ㄥぉ鑷姩鎷嗗垎
+        saveDailyDurations(productionProductMain, productionProductMain.getReportStartTime(), endTime);
+
+        dto.setWorkOrderId(productionProductMain.getWorkOrderId());
+        dto.setProductProcessRouteItemId(productionProductMain.getProductProcessRouteItemId());
+        if (dto.getUserId() == null) {
+            dto.setUserId(productionProductMain.getUserId());
+        }
+        if (dto.getUserName() == null) {
+            dto.setUserName(productionProductMain.getUserName());
+        }
+        if (dto.getScrapQty() == null) {
+            dto.setScrapQty(BigDecimal.ZERO);
+        }
+
+        SysUser user = userMapper.selectUserById(dto.getUserId());
+        if (user == null) {
+            throw new ServiceException("鎶ュ伐浜轰笉瀛樺湪");
+        }
+
+        //  浣跨敤宸ュ崟鍏宠仈鐨勭敓浜ц鍗曚骇鍝佸瀷鍙�
+        ProductWorkOrder productWorkOrder = productWorkOrderMapper.selectById(dto.getWorkOrderId());
+        if (productWorkOrder == null) {
+            throw new ServiceException("缁撴潫鎶ュ伐澶辫触: 宸ュ崟涓嶅瓨鍦�");
+        }
+        ProductOrder productOrder = productOrderMapper.selectById(productWorkOrder.getProductOrderId());
+        if (productOrder == null) {
+            throw new ServiceException("缁撴潫鎶ュ伐澶辫触: 鍏宠仈鐢熶骇璁㈠崟涓嶅瓨鍦�");
+        }
+        Long outputProductModelId = productOrder.getProductModelId();
+        if (outputProductModelId == null) {
+            throw new ServiceException("缁撴潫鎶ュ伐澶辫触: 鐢熶骇璁㈠崟鏈厤缃骇鍝佸瀷鍙�");
+        }
+
+        /*鏂板鎶ュ伐鎶曞叆琛�(鏃燘OM鍦烘櫙: 鎶曞叆=浜у嚭鍨嬪彿, 鏁伴噺鎸夋湰娆℃姤宸ユ暟閲�)*/
+        ProductionProductInput productionProductInput = new ProductionProductInput();
+        productionProductInput.setProductModelId(outputProductModelId);
+        productionProductInput.setQuantity(dto.getQuantity());
+        productionProductInput.setProductMainId(productionProductMain.getId());
+        productionProductInputMapper.insert(productionProductInput);
+        stockUtils.substractStock(outputProductModelId, dto.getQuantity(), StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode(), productionProductMain.getId());
+
         /*鏂板鎶ュ伐浜у嚭琛�*/
         ProductionProductOutput productionProductOutput = new ProductionProductOutput();
         productionProductOutput.setProductMainId(productionProductMain.getId());
-        productionProductOutput.setProductModelId(productProcessRouteItem.getProductModelId());
+        productionProductOutput.setProductModelId(outputProductModelId);
         productionProductOutput.setQuantity(dto.getQuantity() != null ? dto.getQuantity() : BigDecimal.ZERO);
         productionProductOutput.setScrapQty(dto.getScrapQty() != null ? dto.getScrapQty() : BigDecimal.ZERO);
         productionProductOutputMapper.insert(productionProductOutput);
         //鍚堟牸鏁伴噺=鎶ュ伐鏁伴噺-鎶ュ簾鏁伴噺
         BigDecimal productQty = productionProductOutput.getQuantity().subtract(productionProductOutput.getScrapQty());
+        // 鏄惁闇�瑕佽川妫�锛氭寜 product_process.is_quality 鍒ゆ柇锛�1-闇�瑕侊紝0-涓嶉渶瑕侊級
+        boolean needQuality = isNeedQualityByWorkOrder(productWorkOrder);
+
         //鍙湁鍚堟牸鏁伴噺>0鎵嶈兘澧炲姞鐩稿簲鏁版嵁
-        if (productQty.compareTo(BigDecimal.ZERO)>0) {
-            /*鏂板璐ㄦ*/
-            //瀵瑰簲鐨勮繃绋嬫鎴栬�呭嚭鍘傛
-            List<ProductProcessRouteItem> productProcessRouteItems = productProcessRouteItemMapper.selectList(Wrappers.<ProductProcessRouteItem>lambdaQuery().eq(ProductProcessRouteItem::getProductRouteId, productProcessRouteItem.getProductRouteId()));
-            int inspectType = 1;
-            String process = productProcess.getName();//宸ュ簭
-            if (productProcessRouteItem.getDragSort() == productProcessRouteItems.size()) {
-                //鏈�鍚庝竴閬撳伐搴忕敓鎴愬嚭鍘傛
-                inspectType = 2;
-                process = null;
+        if (productQty.compareTo(BigDecimal.ZERO) > 0) {
+            // 闇�瑕佽川妫�鏃舵墠鏂板杩囩▼妫�/鍑哄巶妫�
+            if (needQuality) {
+                createQualityInspect(productionProductMain.getId(), outputProductModelId, productQty, 1, "鐢熶骇鎶ュ伐");
             }
-            Product product = productMapper.selectById(productModel.getProductId());
-            QualityInspect qualityInspect = new QualityInspect();
-            qualityInspect.setProductId(product.getId());
-            qualityInspect.setProductName(product.getProductName());
-            qualityInspect.setModel(productModel.getModel());
-            qualityInspect.setUnit(productModel.getUnit());
-            qualityInspect.setQuantity(productQty);
-            qualityInspect.setProcess(process);
-            qualityInspect.setInspectState(0);
-            qualityInspect.setInspectType(inspectType);
-            qualityInspect.setProductMainId(productionProductMain.getId());
-            qualityInspect.setProductModelId(productModel.getId());
-            qualityInspectMapper.insert(qualityInspect);
-            List<QualityTestStandard> qualityTestStandard = qualityTestStandardMapper.getQualityTestStandardByProductId(product.getId(), inspectType, process);
-            if (qualityTestStandard.size() > 0) {
-                qualityInspect.setTestStandardId(qualityTestStandard.get(0).getId());
-                qualityInspectMapper.updateById(qualityInspect);
-                qualityTestStandardParamMapper.selectList(Wrappers.<QualityTestStandardParam>lambdaQuery()
-                        .eq(QualityTestStandardParam::getTestStandardId, qualityTestStandard.get(0).getId()))//榛樿鑾峰彇鏈�鏂扮殑
-                        .forEach(qualityTestStandardParam -> {
-                            QualityInspectParam param = new QualityInspectParam();
-                            BeanUtils.copyProperties(qualityTestStandardParam, param);
-                            param.setId(null);
-                            param.setInspectId(qualityInspect.getId());
-                            qualityInspectParamMapper.insert(param);
-                        });
-            }
+            stockUtils.addStock(outputProductModelId, productQty, StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode(), productionProductMain.getId());
             /*鏇存柊宸ュ崟鍜岀敓浜ц鍗�*/
-            ProductWorkOrder productWorkOrder = productWorkOrderMapper.selectById(dto.getWorkOrderId());
-            productWorkOrder.setCompleteQuantity(productWorkOrder.getCompleteQuantity().add(productQty));
-            if (ObjectUtils.isNull(productWorkOrder.getActualStartTime())) {
-                productWorkOrder.setActualStartTime(LocalDate.now());//瀹為檯寮�濮嬫椂闂�
+            int woRows = productWorkOrderMapper.addCompleteQtyIfNotExceed(dto.getWorkOrderId(), productQty);
+            if (woRows <= 0) {
+                ProductWorkOrder current = productWorkOrderMapper.selectById(dto.getWorkOrderId());
+                throw new ServiceException("鏈鐢熶骇鏁伴噺涓嶈兘澶т簬鍓╀綑鏁伴噺锛屽墿浣欐暟閲�: "
+                        + (current == null ? "0" : current.getPlanQuantity().subtract(current.getCompleteQuantity())));
             }
-            if (productWorkOrder.getCompleteQuantity().compareTo(productWorkOrder.getPlanQuantity()) == 0) {
-                productWorkOrder.setActualEndTime(LocalDate.now());//瀹為檯缁撴潫鏃堕棿
+
+            // 鏃犲伐鑹鸿矾绾垮満鏅細鎶ュ伐鍗宠鍏ョ敓浜ц鍗曞畬鎴愭暟閲�
+            int poRows = productOrderMapper.addCompleteQtyIfNotExceed(productOrder.getId(), productQty);
+            if (poRows <= 0) {
+                ProductOrder currentOrder = productOrderMapper.selectById(productOrder.getId());
+                throw new ServiceException("鏈鐢熶骇鏁伴噺涓嶈兘澶т簬璁㈠崟鍓╀綑鏁伴噺锛屽墿浣欐暟閲�: "
+                        + (currentOrder == null ? "0" : currentOrder.getQuantity().subtract(currentOrder.getCompleteQuantity())));
             }
-            productWorkOrderMapper.updateById(productWorkOrder);
-            //鐢熶骇璁㈠崟
-            ProductOrder productOrder = productOrderMapper.selectById(productWorkOrder.getProductOrderId());
-            if (ObjectUtils.isNull(productOrder.getStartTime())) {
-                productOrder.setStartTime(LocalDateTime.now());//寮�濮嬫椂闂�
+            ProductOrder latestOrder = productOrderMapper.selectById(productOrder.getId());
+            if (needQuality
+                    && latestOrder != null
+                    && latestOrder.getCompleteQuantity() != null
+                    && latestOrder.getQuantity() != null
+                    && latestOrder.getCompleteQuantity().compareTo(latestOrder.getQuantity()) >= 0) {
+                // 璁㈠崟瀹屾垚鏃舵柊澧炲嚭鍘傛
+                createQualityInspect(productionProductMain.getId(), outputProductModelId, productQty, 2, null);
             }
-            if (productProcessRouteItem.getDragSort() == productProcessRouteItems.size()) {
-                //濡傛灉鏄渶鍚庝竴閬撳伐搴忔姤宸ヤ箣鍚庣敓浜ц鍗曞畬鎴愭暟閲�+
-                productOrder.setCompleteQuantity(productOrder.getCompleteQuantity().add(productQty));
-                if (productOrder.getCompleteQuantity().compareTo(productOrder.getQuantity()) == 0) {
-                    productOrder.setEndTime(LocalDateTime.now());//缁撴潫鏃堕棿
-                }
-            }
-            productOrderMapper.updateById(productOrder);
-            /*娣诲姞鐢熶骇鏍哥畻*/
+            /*娣诲姞鐢熶骇鏍哥畻        鍖哄垎宸ュ簭鏄浠惰繕鏄鏃�*/
+            BigDecimal workHours = durationMinutes.divide(BigDecimal.valueOf(60), 2, RoundingMode.HALF_UP);
+
             SalesLedgerProductionAccounting salesLedgerProductionAccounting = SalesLedgerProductionAccounting.builder()
-                    .salesLedgerWorkId(productionProductMain.getId())
-                    .salesLedgerSchedulingId(0L)
-                    .salesLedgerId(productOrder.getSalesLedgerId())
-                    .salesLedgerProductId(productOrder.getProductModelId())
+                    .productMainId(productionProductMain.getId())
                     .schedulingUserId(user.getUserId())
                     .schedulingUserName(user.getNickName())
                     .finishedNum(productQty)
-                    .workHours(productProcess.getSalaryQuota())
-                    .process(productProcess.getName())
+                    .workHours(workHours)
+                    .process(resolveProcessTypeName(productWorkOrder))
                     .schedulingDate(LocalDate.now())
                     .tenantId(dto.getTenantId())
                     .build();
             salesLedgerProductionAccountingMapper.insert(salesLedgerProductionAccounting);
         }
         //濡傛灉鎶ュ簾鏁伴噺>0,闇�瑕佽繘鍏ユ姤搴熺殑搴撳瓨
-        if (dto.getScrapQty().compareTo(BigDecimal.ZERO) > 0) {
-            stockUtils.addUnStock(productModel.getId(), dto.getScrapQty(), StockUnQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode(), productionProductMain.getId());
+        if (ObjectUtils.isNotEmpty(dto.getScrapQty())) {
+            if (dto.getScrapQty().compareTo(BigDecimal.ZERO) > 0) {
+                stockUtils.addUnStock(outputProductModelId, dto.getScrapQty(), StockInUnQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode(), productionProductMain.getId());
+            }
         }
         return true;
     }
 
+    /**
+     * 鍒涘缓璐ㄦ鍙婅川妫�鍙傛暟
+     */
+    private void createQualityInspect(Long productMainId, Long productModelId, BigDecimal qty, Integer inspectType, String process) {
+        ProductModel productModel = productModelMapper.selectById(productModelId);
+        if (productModel == null) {
+            return;
+        }
+        Product product = productMapper.selectById(productModel.getProductId());
+        if (product == null) {
+            return;
+        }
+        QualityInspect qualityInspect = new QualityInspect();
+        qualityInspect.setProductId(product.getId());
+        qualityInspect.setProductName(product.getProductName());
+        qualityInspect.setModel(productModel.getModel());
+        qualityInspect.setUnit(productModel.getUnit());
+        qualityInspect.setQuantity(qty);
+        qualityInspect.setProcess(process);
+        qualityInspect.setInspectState(0);
+        qualityInspect.setInspectType(inspectType);
+        qualityInspect.setProductMainId(productMainId);
+        qualityInspect.setProductModelId(productModelId);
+        qualityInspectMapper.insert(qualityInspect);
+
+        List<QualityTestStandard> qualityTestStandard = qualityTestStandardMapper.getQualityTestStandardByProductId(product.getId(), inspectType, process);
+        if (qualityTestStandard.isEmpty()) {
+            return;
+        }
+        qualityInspect.setTestStandardId(qualityTestStandard.get(0).getId());
+        qualityInspectMapper.updateById(qualityInspect);
+        qualityTestStandardParamMapper.selectList(Wrappers.<QualityTestStandardParam>lambdaQuery()
+                        .eq(QualityTestStandardParam::getTestStandardId, qualityTestStandard.get(0).getId()))
+                .forEach(qualityTestStandardParam -> {
+                    QualityInspectParam param = new QualityInspectParam();
+                    BeanUtils.copyProperties(qualityTestStandardParam, param);
+                    param.setId(null);
+                    param.setInspectId(qualityInspect.getId());
+                    qualityInspectParamMapper.insert(param);
+                });
+    }
+
+    /**
+     * 鏄惁闇�瑕佽川妫�锛氫緷鎹伐搴忚〃 is_quality锛�1-闇�瑕侊紝0-涓嶉渶瑕侊級
+     */
+    private boolean isNeedQualityByWorkOrder(ProductWorkOrder workOrder) {
+        if (workOrder == null || workOrder.getProductProcessRouteItemId() == null) {
+            return true;
+        }
+        ProductProcessRouteItem routeItem = productProcessRouteItemMapper.selectById(workOrder.getProductProcessRouteItemId());
+        if (routeItem == null || routeItem.getProcessId() == null) {
+            return true;
+        }
+        ProductProcess process = productProcessMapper.selectById(routeItem.getProcessId());
+        if (process == null || process.getIsQuality() == null) {
+            return true;
+        }
+        return process.getIsQuality();
+    }
+
+    /**
+     * 鑾峰彇宸ュ簭瀵瑰簲鐨勨�滈儴浠剁被鍨嬧�濇枃妗�
+     */
+    private String resolveProcessTypeName(ProductWorkOrder workOrder) {
+        if (workOrder == null || workOrder.getProductProcessRouteItemId() == null) {
+            return "鍏朵粬";
+        }
+        ProductProcessRouteItem routeItem = productProcessRouteItemMapper.selectById(workOrder.getProductProcessRouteItemId());
+        if (routeItem == null || routeItem.getProcessId() == null) {
+            return "鍏朵粬";
+        }
+        ProductProcess process = productProcessMapper.selectById(routeItem.getProcessId());
+        if (process == null || process.getType() == null) {
+            return "鍏朵粬";
+        }
+        for (ProductProcessEnum value : ProductProcessEnum.values()) {
+            if (value.getCode().equals(process.getType())) {
+                return value.getInfo();
+            }
+        }
+        return "鍏朵粬";
+    }
+
+    private void saveDailyDurations(ProductionProductMain main, LocalDateTime start, LocalDateTime end) {
+        if (main == null || start == null || end == null) {
+            return;
+        }
+        if (end.isBefore(start)) {
+            return;
+        }
+
+        // 闃叉閲嶅鍐欙紙渚嬪璇噸澶嶇粨鏉熸椂锛夛紝鍏堝垹鍐嶆彃
+        productionProductReportDailyMapper.delete(
+                Wrappers.<ProductionProductReportDaily>lambdaQuery()
+                        .eq(ProductionProductReportDaily::getProductMainId, main.getId())
+        );
+
+        LocalDateTime cursor = start;
+        while (cursor.isBefore(end)) {
+            LocalDate date = cursor.toLocalDate();
+            LocalDateTime nextDayStart = date.plusDays(1).atStartOfDay();
+            LocalDateTime sliceEnd = end.isBefore(nextDayStart) ? end : nextDayStart;
+
+            long seconds = Duration.between(cursor, sliceEnd).getSeconds();
+            BigDecimal minutes = secondsToMinutesExact(seconds);
+            if (minutes.compareTo(BigDecimal.ZERO) > 0) {
+                ProductionProductReportDaily daily = new ProductionProductReportDaily();
+                daily.setProductMainId(main.getId());
+                daily.setWorkOrderId(main.getWorkOrderId());
+                daily.setProductProcessRouteItemId(main.getProductProcessRouteItemId());
+                daily.setUserId(main.getUserId());
+                daily.setReportDate(date);
+                daily.setStartTime(cursor);
+                daily.setEndTime(sliceEnd);
+                daily.setDurationMinutes(minutes);
+                productionProductReportDailyMapper.insert(daily);
+            }
+            cursor = sliceEnd;
+        }
+    }
+
+    /**
+     * 绉掕浆鍒嗛挓锛氬寘鍚垎绉掑苟鍚戜笂鍙栨暣鍒板垎閽�
+     */
+    private BigDecimal secondsToMinutesExact(long seconds) {
+        if (seconds <= 0L) {
+            return BigDecimal.ZERO;
+        }
+        return BigDecimal.valueOf(seconds).divide(BigDecimal.valueOf(60), 2, RoundingMode.HALF_UP);
+    }
+
     @Override
-    public Boolean removeProductMain(ProductionProductMainDto dto) {
-        ProductionProductMain productionProductMain = productionProductMainMapper.selectById(dto.getId());
-        //璇ユ姤宸ュ搴旂殑宸ヨ壓璺嚎璇︽儏
-        ProductProcessRouteItem productProcessRouteItem = productProcessRouteItemMapper.selectById(productionProductMain.getProductProcessRouteItemId());
-        ProductionProductOutput productionProductOutput = productionProductOutputMapper.selectList(Wrappers.<ProductionProductOutput>lambdaQuery().eq(ProductionProductOutput::getProductMainId, productionProductMain.getId())).get(0);
+    public Boolean removeProductMain(Long id) {
+        //鍒ゆ柇璇ユ潯鎶ュ伐鏄惁涓嶅悎鏍煎鐞�,濡傛灉涓嶅悎鏍煎鐞嗕簡锛屽垯涓嶅厑璁稿垹闄�
+        List<QualityInspect> qualityInspects = qualityInspectMapper.selectList(Wrappers.<QualityInspect>lambdaQuery().eq(QualityInspect::getProductMainId, id));
+        if (qualityInspects.size() > 0) {
+            List<QualityUnqualified> qualityUnqualifieds = qualityUnqualifiedMapper.selectList(Wrappers.<QualityUnqualified>lambdaQuery()
+                    .in(QualityUnqualified::getInspectId, qualityInspects.stream().map(QualityInspect::getId).collect(Collectors.toList())));
+            if (qualityUnqualifieds.size() > 0 && qualityUnqualifieds.get(0).getInspectState() == 1) {
+                throw new ServiceException("璇ユ潯鎶ュ伐宸茬粡涓嶅悎鏍煎鐞嗕簡锛屼笉鍏佽鍒犻櫎");
+            }
+        }
+        ProductionProductMain productionProductMain = productionProductMainMapper.selectById(id);
+        List<ProductionProductOutput> outputList = productionProductOutputMapper.selectList(
+                Wrappers.<ProductionProductOutput>lambdaQuery().eq(ProductionProductOutput::getProductMainId, productionProductMain.getId())
+        );
+        ProductionProductOutput productionProductOutput = outputList.isEmpty() ? null : outputList.get(0);
         /*鍒犻櫎鏍哥畻*/
         salesLedgerProductionAccountingMapper.delete(
                 new LambdaQueryWrapper<SalesLedgerProductionAccounting>()
-                        .eq(SalesLedgerProductionAccounting::getSalesLedgerWorkId, productionProductMain.getId())
+                        .eq(SalesLedgerProductionAccounting::getProductMainId, productionProductMain.getId())
         );
         /*鏇存柊宸ュ崟鍜岀敓浜ц鍗�*/
         ProductWorkOrder productWorkOrder = productWorkOrderMapper.selectById(productionProductMain.getWorkOrderId());
-        productWorkOrder.setCompleteQuantity(productWorkOrder.getCompleteQuantity().subtract(productionProductOutput.getQuantity()));
-        productWorkOrder.setActualEndTime(null);
-        productWorkOrderMapper.updateById(productWorkOrder);
-        //鍒ゆ柇鏄惁鏄渶鍚庝竴閬撳伐搴�
-        List<ProductProcessRouteItem> productProcessRouteItems = productProcessRouteItemMapper.selectList(Wrappers.<ProductProcessRouteItem>lambdaQuery().eq(ProductProcessRouteItem::getProductRouteId, productProcessRouteItem.getProductRouteId()));
-        if (productProcessRouteItem.getDragSort() == productProcessRouteItems.size()){
+        BigDecimal validQuantity = BigDecimal.ZERO;
+        if (productWorkOrder != null && productionProductOutput != null) {
+            BigDecimal outputQty = productionProductOutput.getQuantity() == null ? BigDecimal.ZERO : productionProductOutput.getQuantity();
+            BigDecimal scrapQty = productionProductOutput.getScrapQty() == null ? BigDecimal.ZERO : productionProductOutput.getScrapQty();
+            BigDecimal completeQty = productWorkOrder.getCompleteQuantity() == null ? BigDecimal.ZERO : productWorkOrder.getCompleteQuantity();
+
+            validQuantity = outputQty.subtract(scrapQty);
+
+            productWorkOrder.setCompleteQuantity(completeQty.subtract(validQuantity));
+            productWorkOrder.setActualEndTime(null);
+            productWorkOrderMapper.updateById(productWorkOrder);
+        } else if (productWorkOrder == null) {
+            throw new ServiceException("鎿嶄綔澶辫触锛氬伐鍗曚俊鎭垨浜у嚭璁板綍涓嶅瓨鍦�");
+        }
+        // 鏃犲伐鑹鸿矾绾垮満鏅細鍒犻櫎鎶ュ伐鏃跺彧瑕佹湁鏈夋晥浜у嚭灏辨墸鍑忕敓浜ц鍗曞畬鎴愭暟閲�
+        if (productionProductOutput != null && validQuantity.compareTo(BigDecimal.ZERO) > 0) {
             ProductOrder productOrder = productOrderMapper.selectById(productWorkOrder.getProductOrderId());
-            productOrder.setCompleteQuantity(productOrder.getCompleteQuantity().subtract(productionProductOutput.getQuantity()));
+            if (productOrder == null) {
+                throw new ServiceException("鍏宠仈鐨勭敓浜ц鍗曚笉瀛樺湪");
+            }
+            BigDecimal orderCompleteQty = productOrder.getCompleteQuantity() == null ? BigDecimal.ZERO : productOrder.getCompleteQuantity();
+            BigDecimal newCompleteQty = orderCompleteQty.subtract(validQuantity);
+            productOrder.setCompleteQuantity(newCompleteQty.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : newCompleteQty);
             productOrder.setEndTime(null);
             productOrderMapper.updateById(productOrder);
         }
-        /*鍒犻櫎浜у嚭*/
         //鍒犻櫎璐ㄦ
         qualityInspectMapper.selectList(
                 new LambdaQueryWrapper<QualityInspect>()
@@ -279,7 +610,9 @@
                     new LambdaQueryWrapper<QualityInspectParam>()
                             .eq(QualityInspectParam::getInspectId, q.getId()));
             qualityInspectMapper.deleteById(q.getId());
+            stockUtils.deleteStockInRecord(q.getId(), StockInQualifiedRecordTypeEnum.QUALITYINSPECT_STOCK_IN.getCode());
         });
+
         // 鍒犻櫎浜у嚭璁板綍
         productionProductOutputMapper.delete(new LambdaQueryWrapper<ProductionProductOutput>()
                 .eq(ProductionProductOutput::getProductMainId, productionProductMain.getId()));
@@ -287,11 +620,18 @@
         productionProductInputMapper.delete(new LambdaQueryWrapper<ProductionProductInput>()
                 .eq(ProductionProductInput::getProductMainId, productionProductMain.getId()));
         //鍒犻櫎鎶ュ簾鐨勫叆搴撹褰�
-        stockUtils.deleteStockRecord(productionProductMain.getId(), StockUnQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode());
+        stockUtils.deleteStockInRecord(productionProductMain.getId(), StockInUnQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode());
+        //鍒犻櫎涓嶉渶瑕佽川妫�鐨勫悎鏍煎叆搴�
+        stockUtils.deleteStockInRecord(productionProductMain.getId(), StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode());
         //鍒犻櫎鎶曞叆瀵瑰簲鐨勫嚭搴撹褰�
-        stockUtils.deleteStockRecord(productionProductMain.getId(), StockQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode());
+        stockUtils.deleteStockOutRecord(productionProductMain.getId(), StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode());
         // 鍒犻櫎涓昏〃
         productionProductMainMapper.deleteById(productionProductMain.getId());
         return true;
     }
+
+    @Override
+    public ArrayList<Long> listMain(List<Long> idList) {
+        return productionProductMainMapper.listMain(idList);
+    }
 }

--
Gitblit v1.9.3