package com.ruoyi.production.service.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 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.enums.AuditEnum; import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum; 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.mapper.*; import com.ruoyi.production.pojo.*; import com.ruoyi.production.service.ProductionProductMainService; import com.ruoyi.production.vo.ProductAuditVo; import com.ruoyi.project.system.domain.SysUser; import com.ruoyi.project.system.mapper.SysUserMapper; import com.ruoyi.quality.mapper.*; import com.ruoyi.quality.pojo.*; import com.ruoyi.quality.service.IQualityInspectService; import com.ruoyi.sales.mapper.SalesLedgerMapper; import lombok.AllArgsConstructor; import org.springframework.aop.framework.AopContext; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.validation.constraints.NotNull; import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.stream.Collectors; import static cn.hutool.core.date.LocalDateTimeUtil.between; @Service @AllArgsConstructor @Transactional(rollbackFor = Exception.class) public class ProductionProductMainServiceImpl extends ServiceImpl implements ProductionProductMainService { private final SalesLedgerMapper salesLedgerMapper; private final ProductionMachineRecordMapper productionMachineRecordMapper; private IQualityInspectService qualityInspectService; private ProductionProductMainMapper productionProductMainMapper; private ProductWorkOrderMapper productWorkOrderMapper; private ProductProcessRouteItemMapper productProcessRouteItemMapper; private SysUserMapper userMapper; private ProductionProductOutputMapper productionProductOutputMapper; private ProductModelMapper productModelMapper; private QualityInspectMapper qualityInspectMapper; private QualityUnqualifiedMapper qualityUnqualifiedMapper; private ProductProcessMapper productProcessMapper; private ProductProcessRouteMapper productProcessRouteMapper; private ProductMapper productMapper; private QualityTestStandardParamMapper qualityTestStandardParamMapper; private QualityTestStandardMapper qualityTestStandardMapper; private QualityInspectParamMapper qualityInspectParamMapper; private ProductStructureMapper productStructureMapper; private ProductionProductInputMapper productionProductInputMapper; private ProductOrderMapper productOrderMapper; private SalesLedgerProductionAccountingMapper salesLedgerProductionAccountingMapper; private ProductionReportPersonMapper productionReportPersonMapper; private StockUtils stockUtils; @Override public IPage listPageProductionProductMainDto(Page page, ProductionProductMainDto productionProductMainDto) { return productionProductMainMapper.listPageProductionProductMainDto(page, productionProductMainDto); } @Override @Transactional(rollbackFor = Exception.class) public Boolean addProductMain(ProductionProductMainDto dto) { LocalDateTime now = LocalDateTime.now(); ProductWorkOrder productWorkOrder = productWorkOrderMapper.selectById(dto.getWorkOrderId()); ProductionProductMain productionProductMain = new ProductionProductMain(); //当前工艺路线对应的工序详情 ProductProcessRouteItem productProcessRouteItem = productProcessRouteItemMapper.selectById(dto.getProductProcessRouteItemId()); if (productProcessRouteItem == null) { throw new RuntimeException("工艺路线项不存在"); } //当前具体工序 ProductProcess productProcess = productProcessMapper.selectById(productProcessRouteItem.getProcessId()); //工艺路线中当前工序对应的产出规格型号 ProductModel productModel = productModelMapper.selectById(productProcessRouteItem.getProductModelId()); //查询该生产订单对应的bom ProductProcessRoute productProcessRoute = Optional.ofNullable(productProcessRouteMapper.selectById(productProcessRouteItem.getProductRouteId())).orElse(new ProductProcessRoute()); /*新增报工主表*/ //查询最大报工编号 String datePrefix = "BG" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyMMdd")); QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.select("MAX(product_no) as maxNo") .likeRight("product_no", datePrefix); List> resultList = productionProductMainMapper.selectMaps(queryWrapper); int sequenceNumber = 1; if (resultList != null && !resultList.isEmpty()) { Map result = resultList.get(0); if (result != null) { Object maxNoObj = result.get("maxNo"); if (maxNoObj != null) { String lastNo = maxNoObj.toString(); System.out.println("lastNo: " + lastNo); if (lastNo.startsWith(datePrefix)) { try { String seqStr = lastNo.substring(datePrefix.length()); sequenceNumber = Integer.parseInt(seqStr) + 1; } catch (NumberFormatException e) { sequenceNumber = 1; } } } } } String productNo = String.format("%s%03d", datePrefix, sequenceNumber); productionProductMain.setProductNo(productNo); // 修改班组信息 以第一人作为原先setUserId setUserName Assert.isTrue(CollUtil.isNotEmpty(dto.getTeamList()), "班组信息不能为空"); productionProductMain.setTeamIds(dto.getTeamList().stream().map(ProductionProductMainDto.Team::getUserId).map(String::valueOf).collect(Collectors.joining(","))); productionProductMain.setTeamNames(dto.getTeamList().stream().map(ProductionProductMainDto.Team::getUserName).collect(Collectors.joining(","))); //报工人 是 谁报工就是是谁 productionProductMain.setUserId(SecurityUtils.getUserId()); productionProductMain.setUserName(SecurityUtils.getLoginUser().getNickName()); productionProductMain.setProductProcessRouteItemId(dto.getProductProcessRouteItemId()); productionProductMain.setWorkOrderId(dto.getWorkOrderId()); // productionProductMain.setAuditUserId(dto.getAuditUserId()); // productionProductMain.setAuditUserName(dto.getAuditUserName()); productionProductMain.setStatus(0); if (ObjectUtils.isNotEmpty(dto.getStartTime()) && ObjectUtils.isNotEmpty(dto.getEndTime())) { productionProductMain.setStartTime(dto.getStartTime()); productionProductMain.setEndTime(dto.getEndTime()); } else { productionProductMain.setStartTime(productWorkOrder.getStartProductTime()); productionProductMain.setEndTime(now); } productionProductMain.setDeviceId(dto.getDeviceId()); productionProductMain.setDeviceName(dto.getDeviceName()); // 审批人为自己 直接通过审批 productionProductMain.setAuditUserName(SecurityUtils.getUsername()); productionProductMain.setAuditUserId(SecurityUtils.getUserId()); productionProductMainMapper.insert(productionProductMain); /*保存报工班组人员产量时长明细*/ List personList = dto.getPersonList(); BigDecimal personSum = BigDecimal.ZERO; if (CollUtil.isNotEmpty(personList)) { for (ProductionProductMainDto.Person person : personList) { BigDecimal personQty = person.getQuantity() == null ? BigDecimal.ZERO : person.getQuantity(); personSum = personSum.add(personQty); ProductionReportPerson reportPerson = new ProductionReportPerson(); reportPerson.setProductMainId(productionProductMain.getId()); reportPerson.setUserId(person.getUserId()); reportPerson.setUserName(person.getUserName()); reportPerson.setQuantity(personQty); reportPerson.setWorkHour(person.getWorkHour() != null ? person.getWorkHour() : 0); productionReportPersonMapper.insert(reportPerson); } } BigDecimal totalQuantity = dto.getQuantity() == null ? BigDecimal.ZERO : dto.getQuantity(); if (CollUtil.isNotEmpty(personList) && personSum.compareTo(totalQuantity) != 0) { throw new ServiceException("各班组产量之和必须等于报工总产量"); } /*新增报工投入表*/ List productStructureDtos = productStructureMapper.listBybomAndProcess(Optional.ofNullable(productProcessRoute.getBomId()).orElse(0), productProcess.getId()); if (productStructureDtos.isEmpty()) { //如果该工序没有产品结构的投入品,那这个投入品和产出品是同一个 ProductStructureDto productStructureDto = new ProductStructureDto(); productStructureDto.setProductModelId(productProcessRouteItem.getProductModelId()); productStructureDto.setUnitQuantity(BigDecimal.ONE); productStructureDtos.add(productStructureDto); } for (ProductStructureDto productStructureDto : productStructureDtos) { 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(), StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode(), productionProductMain.getId()); } /*新增报工产出表*/ ProductionProductOutput productionProductOutput = new ProductionProductOutput(); productionProductOutput.setProductMainId(productionProductMain.getId()); productionProductOutput.setProductModelId(productProcessRouteItem.getProductModelId()); productionProductOutput.setQuantity(dto.getQuantity() != null ? dto.getQuantity() : BigDecimal.ZERO); productionProductOutput.setScrapQty(dto.getScrapQty() != null ? dto.getScrapQty() : BigDecimal.ZERO); productionProductOutput.setReplenishQty(dto.getReplenishQty()); productionProductOutput.setAddQty(dto.getAddQty() != null ? dto.getAddQty() : BigDecimal.ZERO); productionProductOutputMapper.insert(productionProductOutput); //工序流转数量=产出数量+加放数(报废仅做数据记录,不扣减工序流转基数,各工序总产量保持连贯) BigDecimal addQty = productionProductOutput.getAddQty() == null ? BigDecimal.ZERO : productionProductOutput.getAddQty(); BigDecimal productQty = productionProductOutput.getQuantity().add(addQty); //只有工序流转数量>0才能增加相应数据 if (productQty.compareTo(BigDecimal.ZERO) > 0) { List productProcessRouteItems = productProcessRouteItemMapper.selectList(Wrappers.lambdaQuery().eq(ProductProcessRouteItem::getProductRouteId, productProcessRouteItem.getProductRouteId())); /*更新工单和生产订单*/ productWorkOrder.setCompleteQuantity(productWorkOrder.getCompleteQuantity().add(productQty)); // 查询该工单对应的最早上机时间(按上机时间升序,取第一条) List machineRecords = productionMachineRecordMapper.selectList( Wrappers.lambdaQuery() .eq(ProductionMachineRecord::getWorkOrderId, productWorkOrder.getId()) .isNotNull(ProductionMachineRecord::getMachineStartTime) .orderByAsc(ProductionMachineRecord::getMachineStartTime) ); if (!machineRecords.isEmpty()) { productWorkOrder.setActualStartTime(machineRecords.get(0).getMachineStartTime()); } // 仅完成数量达到计划数量时才填充实际结束时间,未完成则清空已填的结束时间(允许继续分批报工) if (productWorkOrder.getCompleteQuantity().compareTo(productWorkOrder.getPlanQuantity()) >= 0) { productWorkOrder.setActualEndTime(now); productWorkOrder.setEndProductTime(now); productWorkOrderMapper.updateById(productWorkOrder); } else { // updateById 默认忽略 null 字段,需用 UpdateWrapper 显式清空(自愈历史脏数据) productWorkOrderMapper.update(null, Wrappers.lambdaUpdate() .eq(ProductWorkOrder::getId, productWorkOrder.getId()) .set(ProductWorkOrder::getActualEndTime, null) .set(ProductWorkOrder::getEndProductTime, null)); } //生产订单 ProductOrder productOrder = productOrderMapper.selectById(productWorkOrder.getProductOrderId()); if (ObjectUtils.isNull(productOrder.getStartTime())) { productOrder.setStartTime(now);//开始时间 } if (productProcessRouteItem.getDragSort() >= productProcessRouteItems.size() -1 ) { //如果是最后一道工序报工之后生产订单完成数量+ productOrder.setCompleteQuantity(productOrder.getCompleteQuantity().add(productQty)); if (productOrder.getCompleteQuantity().compareTo(productOrder.getQuantity()) >= 0) { productOrder.setEndTime(now);//结束时间 } } productOrderMapper.updateById(productOrder); } ProductAuditVo productAuditVo = new ProductAuditVo(); productAuditVo.setId(productionProductMain.getId()); productAuditVo.setAuditStatus(AuditEnum.AUDIT_SUCCESS); productAuditVo.setAuditOpinion(""); ((ProductionProductMainService) AopContext.currentProxy()).auditProductMain(productAuditVo); // nextAddProductMain(productionProductOutput) // 由于需要审核,所以需要拆封下来 return true; } @Override @Transactional(rollbackFor = Exception.class) public void auditProductMain(ProductAuditVo productAuditVo) { ProductionProductMain productionProductMain = productionProductMainMapper.selectById(productAuditVo.getId()); // 当前审批人 要与当前登录人为同一人 if (productionProductMain.getAuditUserId() != -1) { Assert.isTrue(SecurityUtils.getUserId().equals(productionProductMain.getAuditUserId()), "当前登录用户不是当前审批人"); } // 状态必须为待审核状态 if (!Objects.equals(productionProductMain.getAuditStatus(), AuditEnum.NO_AUDIT.getCode())) { throw new ServiceException("当前状态已审核,不能重复审核"); } LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(ProductionProductOutput::getProductMainId, productionProductMain.getId()); queryWrapper.last("limit 1"); ProductionProductOutput productionProductOutput = productionProductOutputMapper.selectOne(queryWrapper); ProductProcessRouteItem productProcessRouteItem = productProcessRouteItemMapper.selectById(productionProductMain.getProductProcessRouteItemId()); switch (productAuditVo.getAuditStatus()) { case NO_AUDIT: throw new ServiceException("修改审核状态失败,不能为未审核状态"); case AUDIT_SUCCESS: Assert.isTrue(productionProductOutput != null, "没有找到对应的报工产出记录"); ((ProductionProductMainService) AopContext.currentProxy()).nextAddProductMain(productionProductOutput); break; case AUDIT_FAIL: // 减少 更新工单和生产订单 ProductWorkOrder productWorkOrder = productWorkOrderMapper.selectById(productionProductMain.getWorkOrderId()); ProductOrder productOrder = productOrderMapper.selectById(productWorkOrder.getProductOrderId()); //工序流转数量=产出数量+加放数(与报工累加口径一致,报废不扣减流转基数) BigDecimal processQty = productionProductOutput.getQuantity().add( productionProductOutput.getAddQty() == null ? BigDecimal.ZERO : productionProductOutput.getAddQty()); productWorkOrder.setCompleteQuantity( productWorkOrder.getCompleteQuantity() .subtract(processQty) .max(BigDecimal.ZERO) ); List productProcessRouteItems = productProcessRouteItemMapper.selectList(Wrappers.lambdaQuery().eq(ProductProcessRouteItem::getProductRouteId, productProcessRouteItem.getProductRouteId())); if (productProcessRouteItem.getDragSort() == productProcessRouteItems.size()) { //如果是最后一道工序报工之后生产订单 需要扣除 productOrder.setCompleteQuantity( productOrder.getCompleteQuantity() .subtract(processQty) .max(BigDecimal.ZERO) ); if (productOrder.getCompleteQuantity().compareTo(processQty) > 0) { productOrder.setEndTime(null); } productOrderMapper.updateById(productOrder); } if (productWorkOrder.getCompleteQuantity().compareTo(processQty) > 0) { productWorkOrder.setActualEndTime(null); } productWorkOrderMapper.updateById(productWorkOrder); break; } // 修改状态 ProductionProductMain updateDate = new ProductionProductMain(); updateDate.setId(productionProductMain.getId()); updateDate.setAuditStatus(productAuditVo.getAuditStatus().getCode()); updateDate.setSureAuditUserId(SecurityUtils.getUserId()); updateDate.setSureAuditUserName(SecurityUtils.getUsername()); updateDate.setAuditTime(LocalDateTime.now()); updateDate.setAuditOpinion(productAuditVo.getAuditOpinion()); productionProductMainMapper.updateById(updateDate); } @Override @Transactional(rollbackFor = Exception.class) public void nextAddProductMain(@NotNull ProductionProductOutput productionProductOutput) { //实际入库数量=产出数量+加放数-报废数量 ProductionProductMain productionProductMain = productionProductMainMapper.selectById(productionProductOutput.getProductMainId()); BigDecimal addQty = productionProductOutput.getAddQty() == null ? BigDecimal.ZERO : productionProductOutput.getAddQty(); BigDecimal productQty = productionProductOutput.getQuantity().add(addQty).subtract(productionProductOutput.getScrapQty()); ProductProcessRouteItem productProcessRouteItem = productProcessRouteItemMapper.selectById(productionProductMain.getProductProcessRouteItemId()); ProductProcess productProcess = productProcessMapper.selectById(productProcessRouteItem.getProcessId()); //工艺路线中当前工序对应的产出规格型号 ProductModel productModel = productModelMapper.selectById(productProcessRouteItem.getProductModelId()); SysUser user = userMapper.selectUserById(SecurityUtils.getUserId()); //只有合格数量>0才能增加相应数据 if (productQty.compareTo(BigDecimal.ZERO) > 0) { /*新增质检*/ List productProcessRouteItems = productProcessRouteItemMapper.selectList(Wrappers.lambdaQuery().eq(ProductProcessRouteItem::getProductRouteId, productProcessRouteItem.getProductRouteId())); if (productProcessRouteItem.getIsQuality()) { //对应的过程检或者出厂检 int inspectType = 1; String process = productProcess.getName();//工序 if (productProcessRouteItem.getDragSort() == (productProcessRouteItems.size()-1)) { //最后一道工序生成出厂检 inspectType = 2; process = null; } // 排产下达时已为该工单预生成质检单(product_main_id IS NULL),报工审核时认领并更新为实际数量 QualityInspect preInspect = qualityInspectMapper.selectOne( Wrappers.lambdaQuery() .eq(QualityInspect::getWorkOrderId, productionProductMain.getWorkOrderId()) .isNull(QualityInspect::getProductMainId) .last("limit 1")); if (preInspect != null) { preInspect.setProductMainId(productionProductMain.getId()); preInspect.setQuantity(productQty); if (preInspect.getInspectState() != null && preInspect.getInspectState() == 1 && preInspect.getInspectType() != null && preInspect.getInspectType() == 2) { // 已提交且为出厂检:删除按计划数量入库的记录,按实际数量重新入库 stockUtils.deleteStockInRecord(preInspect.getId(), StockInQualifiedRecordTypeEnum.QUALITYINSPECT_STOCK_IN.getCode()); stockUtils.addStock(productModel.getId(), productQty, StockInQualifiedRecordTypeEnum.QUALITYINSPECT_STOCK_IN.getCode(), preInspect.getId(), "-", "-", "-"); } qualityInspectMapper.updateById(preInspect); } else { insertQualityInspect(productProcessRouteItem, inspectType, process, productionProductMain.getId(), productionProductMain.getWorkOrderId(), productQty); } } else { //直接入库 if (productProcessRouteItem.getDragSort() == (productProcessRouteItems.size()-1)) { //最后一道工序才会入库 stockUtils.addStock(productProcessRouteItem.getProductModelId(), productQty, StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode(), productionProductMain.getId(), "-", "-", "-"); } } /*添加生产核算 区分工序是计件还是计时*/ BigDecimal workHours = productProcess.getSalaryQuota(); List productionMachineRecords = productionMachineRecordMapper.selectList(Wrappers.lambdaQuery().eq(ProductionMachineRecord::getWorkOrderId, productionProductMain.getWorkOrderId())); // 报工班组人员产量时长明细(有明细则按人生成核算,无明细则回退机台操作员逻辑) List personList = productionReportPersonMapper.selectList(Wrappers.lambdaQuery().eq(ProductionReportPerson::getProductMainId, productionProductMain.getId())); // 设备取报工单设备,未填写时回退取该工单任一台机 Long reportDeviceId = productionProductMain.getDeviceId() != null ? productionProductMain.getDeviceId() : productionMachineRecords.stream().map(ProductionMachineRecord::getMachineId).filter(Objects::nonNull).findFirst().orElse(null); if (CollUtil.isNotEmpty(personList)) { // 每次报工独立按人生成核算(支持分批报工直至完成),不受上机记录报工状态影响 BigDecimal netQty = productQty; BigDecimal rawQuantity = productionProductOutput.getQuantity() == null ? BigDecimal.ZERO : productionProductOutput.getQuantity(); for (ProductionReportPerson person : personList) { BigDecimal personQty = person.getQuantity() == null ? BigDecimal.ZERO : person.getQuantity(); BigDecimal finishedNum; if (netQty.compareTo(rawQuantity) == 0 || rawQuantity.compareTo(BigDecimal.ZERO) == 0) { // 无报废(或毛产量为0)时净值即毛产量,直接取个人产量 finishedNum = personQty; } else { // 有报废时按各人毛产量占比分摊净值,四舍五入保留2位 finishedNum = personQty.multiply(netQty).divide(rawQuantity, 2, BigDecimal.ROUND_HALF_UP); } SalesLedgerProductionAccounting salesLedgerProductionAccounting = SalesLedgerProductionAccounting.builder() .productMainId(productionProductMain.getId()) .schedulingUserId(person.getUserId()) .schedulingUserName(person.getUserName()) .finishedNum(finishedNum) .workHours(workHours) .process(productProcess.getName()) .schedulingDate(LocalDate.now()) .tenantId(productionProductOutput.getTenantId()) .deviceId(reportDeviceId) .workHour(person.getWorkHour() == null ? 0L : person.getWorkHour().longValue()) .build(); salesLedgerProductionAccountingMapper.insert(salesLedgerProductionAccounting); } // 该工单上机记录本次已报工 for (ProductionMachineRecord productionMachineRecord : productionMachineRecords) { if (!productionMachineRecord.getReportStatus()) { productionMachineRecord.setReportStatus(true); productionMachineRecordMapper.updateById(productionMachineRecord); } } } else if (ObjectUtils.isNotEmpty(productionMachineRecords)) { // 兼容旧数据:未传人员明细则回退按未报工的机台上机操作员生成核算 for (ProductionMachineRecord productionMachineRecord : productionMachineRecords) { //说明已经添加过了,不添加了 if (productionMachineRecord.getReportStatus()) { continue; } for (String s : productionMachineRecord.getOperatorId().split(",")) { Long minutes = 0L; if (productionMachineRecord.getMachineStartTime() != null) { minutes = between(productionMachineRecord.getMachineStartTime(), LocalDateTime.now()).toMinutes(); } SalesLedgerProductionAccounting salesLedgerProductionAccounting = SalesLedgerProductionAccounting.builder() .productMainId(productionProductMain.getId()) .schedulingUserId(Long.parseLong(s)) .schedulingUserName(Optional.of(userMapper.selectUserById(Long.parseLong(s))).orElse(new SysUser()).getNickName()) .finishedNum(productQty) .workHours(workHours) .process(productProcess.getName()) .schedulingDate(LocalDate.now()) .tenantId(productionProductOutput.getTenantId()) .deviceId(productionMachineRecord.getMachineId()) .workHour(minutes) .build(); salesLedgerProductionAccountingMapper.insert(salesLedgerProductionAccounting); } productionMachineRecord.setReportStatus(true); productionMachineRecordMapper.updateById(productionMachineRecord); } } } } /** * 生成质检单并回填检测标准/检验参数 */ private void insertQualityInspect(ProductProcessRouteItem routeItem, Integer inspectType, String process, Long productMainId, Long workOrderId, BigDecimal quantity) { ProductModel productModel = productModelMapper.selectById(routeItem.getProductModelId()); 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(quantity); qualityInspect.setProcess(process); qualityInspect.setInspectState(0); qualityInspect.setInspectType(inspectType); qualityInspect.setProductMainId(productMainId); qualityInspect.setWorkOrderId(workOrderId); qualityInspect.setProductModelId(productModel.getId()); qualityInspectMapper.insert(qualityInspect); List qualityTestStandard = qualityTestStandardMapper.getQualityTestStandardByProductId(product.getId(), inspectType, process); if (!qualityTestStandard.isEmpty()) { qualityInspect.setTestStandardId(qualityTestStandard.get(0).getId()); qualityInspectMapper.updateById(qualityInspect); qualityTestStandardParamMapper.selectList(Wrappers.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); }); } } @Override public void preGenerateQualityInspectForOrder(Long productOrderId) { if (productOrderId == null) { return; } ProductProcessRoute productProcessRoute = productProcessRouteMapper.selectOne( Wrappers.lambdaQuery() .eq(ProductProcessRoute::getProductOrderId, productOrderId)); if (productProcessRoute == null) { return; } List items = productProcessRouteItemMapper.selectList( Wrappers.lambdaQuery() .eq(ProductProcessRouteItem::getProductRouteId, productProcessRoute.getId()) .orderByAsc(ProductProcessRouteItem::getDragSort) .orderByAsc(ProductProcessRouteItem::getId)); if (items.isEmpty()) { return; } // 第一道工序需质检才预生成 ProductProcessRouteItem first = items.get(0); if (!Boolean.TRUE.equals(first.getIsQuality())) { return; } ProductWorkOrder workOrder = productWorkOrderMapper.selectOne( Wrappers.lambdaQuery() .eq(ProductWorkOrder::getProductProcessRouteItemId, first.getId())); if (workOrder == null) { return; } // 该工单已存在预生成质检单则不重复生成 Long existCount = qualityInspectMapper.selectCount( Wrappers.lambdaQuery() .eq(QualityInspect::getWorkOrderId, workOrder.getId()) .isNull(QualityInspect::getProductMainId)); if (existCount != null && existCount > 0) { return; } boolean onlyOne = items.size() == 1; int inspectType = onlyOne ? 2 : 1; String process = null; if (!onlyOne) { ProductProcess processEntity = productProcessMapper.selectById(first.getProcessId()); if (processEntity != null) { process = processEntity.getName(); } } insertQualityInspect(first, inspectType, process, null, workOrder.getId(), workOrder.getPlanQuantity()); } @Override public void cleanPreGeneratedQualityInspects(List workOrderIds) { if (CollUtil.isEmpty(workOrderIds)) { return; } List preInspects = qualityInspectMapper.selectList( Wrappers.lambdaQuery() .in(QualityInspect::getWorkOrderId, workOrderIds) .isNull(QualityInspect::getProductMainId)); if (CollUtil.isEmpty(preInspects)) { return; } for (QualityInspect pre : preInspects) { if (pre.getInspectState() != null && pre.getInspectState() == 1) { throw new ServiceException("已提交的检验单不能删除"); } } List inspectIds = preInspects.stream().map(QualityInspect::getId).collect(Collectors.toList()); qualityInspectParamMapper.delete( Wrappers.lambdaQuery().in(QualityInspectParam::getInspectId, inspectIds)); qualityInspectMapper.deleteBatchIds(inspectIds); } @Override public Boolean removeProductMain(Long id) { //判断该条报工是否不合格处理,如果不合格处理了,则不允许删除 List qualityInspects = qualityInspectMapper.selectList(Wrappers.lambdaQuery().eq(QualityInspect::getProductMainId, id)); if (qualityInspects.size() > 0) { List qualityUnqualifieds = qualityUnqualifiedMapper.selectList(Wrappers.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); //该报工对应的工艺路线详情 ProductProcessRouteItem productProcessRouteItem = productProcessRouteItemMapper.selectById(productionProductMain.getProductProcessRouteItemId()); ProductionProductOutput productionProductOutput = productionProductOutputMapper.selectList(Wrappers.lambdaQuery().eq(ProductionProductOutput::getProductMainId, productionProductMain.getId())).get(0); /*删除核算*/ salesLedgerProductionAccountingMapper.delete( new LambdaQueryWrapper() .eq(SalesLedgerProductionAccounting::getProductMainId, productionProductMain.getId()) ); /*删除报工班组人员产量时长明细*/ productionReportPersonMapper.delete( new LambdaQueryWrapper() .eq(ProductionReportPerson::getProductMainId, productionProductMain.getId()) ); /*更新工单和生产订单*/ ProductWorkOrder productWorkOrder = productWorkOrderMapper.selectById(productionProductMain.getWorkOrderId()); if (productWorkOrder != null && productionProductOutput != null) { BigDecimal outputQty = productionProductOutput.getQuantity() == null ? BigDecimal.ZERO : productionProductOutput.getQuantity(); BigDecimal addQty = productionProductOutput.getAddQty() == null ? BigDecimal.ZERO : productionProductOutput.getAddQty(); BigDecimal completeQty = productWorkOrder.getCompleteQuantity() == null ? BigDecimal.ZERO : productWorkOrder.getCompleteQuantity(); // 必须为审核通过的才会减少数量 BigDecimal validQuantity = outputQty.add(addQty); if (productionProductMain.getAuditStatus() != 2) { productWorkOrder.setCompleteQuantity(completeQty.subtract(validQuantity).max(BigDecimal.ZERO)); } productWorkOrder.setActualEndTime(null); productWorkOrderMapper.updateById(productWorkOrder); } else { throw new ServiceException("操作失败:工单信息或产出记录不存在"); } //判断是否是最后一道工序 List productProcessRouteItems = productProcessRouteItemMapper.selectList(Wrappers.lambdaQuery().eq(ProductProcessRouteItem::getProductRouteId, productProcessRouteItem.getProductRouteId())); if (productProcessRouteItem.getDragSort() != null && productProcessRouteItems != null && productProcessRouteItem.getDragSort() == productProcessRouteItems.size()) { ProductOrder productOrder = productOrderMapper.selectById(productWorkOrder.getProductOrderId()); if (productOrder != null) { BigDecimal orderCompleteQty = productOrder.getCompleteQuantity() == null ? BigDecimal.ZERO : productOrder.getCompleteQuantity(); BigDecimal totalQty = productionProductOutput.getQuantity() != null ? productionProductOutput.getQuantity() : BigDecimal.ZERO; BigDecimal addQty = productionProductOutput.getAddQty() != null ? productionProductOutput.getAddQty() : BigDecimal.ZERO; BigDecimal actualQualifiedQty = totalQty.add(addQty); BigDecimal newCompleteQty = orderCompleteQty.subtract(actualQualifiedQty); productOrder.setCompleteQuantity(newCompleteQty.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : newCompleteQty); productOrder.setEndTime(null); productOrderMapper.updateById(productOrder); } else { throw new ServiceException("关联的生产订单不存在"); } } //删除质检 qualityInspectMapper.selectList( new LambdaQueryWrapper() .eq(QualityInspect::getProductMainId, productionProductMain.getId()) ).forEach(q -> { qualityInspectParamMapper.delete( new LambdaQueryWrapper() .eq(QualityInspectParam::getInspectId, q.getId())); qualityInspectMapper.deleteById(q.getId()); stockUtils.deleteStockInRecord(q.getId(), StockInQualifiedRecordTypeEnum.QUALITYINSPECT_STOCK_IN.getCode()); }); // 删除产出记录 productionProductOutputMapper.delete(new LambdaQueryWrapper() .eq(ProductionProductOutput::getProductMainId, productionProductMain.getId())); //删除投入记录 productionProductInputMapper.delete(new LambdaQueryWrapper() .eq(ProductionProductInput::getProductMainId, productionProductMain.getId())); //删除不需要质检的合格入库 stockUtils.deleteStockInRecord(productionProductMain.getId(), StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode()); //删除投入对应的出库记录 // stockUtils.deleteStockOutRecord(productionProductMain.getId(), StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode()); // 删除主表 productionProductMainMapper.deleteById(productionProductMain.getId()); return true; } @Override public ArrayList listMain(List idList) { return productionProductMainMapper.listMain(idList); } }