| | |
| | | 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 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.Objects; |
| | | 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<ProductionProductMainMapper, ProductionProductMain> implements ProductionProductMainService { |
| | | |
| | | private final SalesLedgerMapper salesLedgerMapper; |
| | | private final ProductionMachineRecordMapper productionMachineRecordMapper; |
| | | private IQualityInspectService qualityInspectService; |
| | | private ProductionProductMainMapper productionProductMainMapper; |
| | | |
| | |
| | | |
| | | private SalesLedgerProductionAccountingMapper salesLedgerProductionAccountingMapper; |
| | | |
| | | private ProductionReportPersonMapper productionReportPersonMapper; |
| | | |
| | | private StockUtils stockUtils; |
| | | |
| | | |
| | |
| | | LocalDateTime now = LocalDateTime.now(); |
| | | ProductWorkOrder productWorkOrder = productWorkOrderMapper.selectById(dto.getWorkOrderId()); |
| | | |
| | | SysUser user = userMapper.selectUserById(dto.getUserId()); |
| | | ProductionProductMain productionProductMain = new ProductionProductMain(); |
| | | //当前工艺路线对应的工序详情 |
| | | ProductProcessRouteItem productProcessRouteItem = productProcessRouteItemMapper.selectById(dto.getProductProcessRouteItemId()); |
| | |
| | | //工艺路线中当前工序对应的产出规格型号 |
| | | ProductModel productModel = productModelMapper.selectById(productProcessRouteItem.getProductModelId()); |
| | | //查询该生产订单对应的bom |
| | | ProductProcessRoute productProcessRoute = productProcessRouteMapper.selectById(productProcessRouteItem.getProductRouteId()); |
| | | ProductProcessRoute productProcessRoute = Optional.ofNullable(productProcessRouteMapper.selectById(productProcessRouteItem.getProductRouteId())).orElse(new ProductProcessRoute()); |
| | | /*新增报工主表*/ |
| | | //查询最大报工编号 |
| | | String datePrefix = "BG" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyMMdd")); |
| | |
| | | productionProductMain.setProductNo(productNo); |
| | | |
| | | // 修改班组信息 以第一人作为原先setUserId setUserName |
| | | Assert.isTrue(CollUtil.isNotEmpty(dto.getTeamList()),"班组信息不能为空"); |
| | | 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(dto.getTeamList().get(0).getUserId()); |
| | | productionProductMain.setUserName(dto.getTeamList().get(0).getUserName()); |
| | | |
| | | //报工人 是 谁报工就是是谁 |
| | | 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.setAuditUserId(dto.getAuditUserId()); |
| | | // productionProductMain.setAuditUserName(dto.getAuditUserName()); |
| | | productionProductMain.setStatus(0); |
| | | if (ObjectUtils.isNotEmpty(dto.getStartTime())&&ObjectUtils.isNotEmpty(dto.getEndTime())) { |
| | | if (ObjectUtils.isNotEmpty(dto.getStartTime()) && ObjectUtils.isNotEmpty(dto.getEndTime())) { |
| | | productionProductMain.setStartTime(dto.getStartTime()); |
| | | productionProductMain.setEndTime(dto.getEndTime()); |
| | | }else { |
| | | } 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<ProductionProductMainDto.Person> 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<ProductStructureDto> productStructureDtos = productStructureMapper.listBybomAndProcess(productProcessRoute.getBomId(), productProcess.getId()); |
| | | List<ProductStructureDto> productStructureDtos = productStructureMapper.listBybomAndProcess(Optional.ofNullable(productProcessRoute.getBomId()).orElse(0), productProcess.getId()); |
| | | if (productStructureDtos.isEmpty()) { |
| | | //如果该工序没有产品结构的投入品,那这个投入品和产出品是同一个 |
| | | ProductStructureDto productStructureDto = new ProductStructureDto(); |
| | |
| | | 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.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 productQty = productionProductOutput.getQuantity().subtract(productionProductOutput.getScrapQty()); |
| | | //只有合格数量>0才能增加相应数据 |
| | | //工序流转数量=产出数量+加放数(报废仅做数据记录,不扣减工序流转基数,各工序总产量保持连贯) |
| | | BigDecimal addQty = productionProductOutput.getAddQty() == null ? BigDecimal.ZERO : productionProductOutput.getAddQty(); |
| | | BigDecimal productQty = productionProductOutput.getQuantity().add(addQty); |
| | | //只有工序流转数量>0才能增加相应数据 |
| | | if (productQty.compareTo(BigDecimal.ZERO) > 0) { |
| | | List<ProductProcessRouteItem> productProcessRouteItems = productProcessRouteItemMapper.selectList(Wrappers.<ProductProcessRouteItem>lambdaQuery().eq(ProductProcessRouteItem::getProductRouteId, productProcessRouteItem.getProductRouteId())); |
| | | /*更新工单和生产订单*/ |
| | | productWorkOrder.setCompleteQuantity(productWorkOrder.getCompleteQuantity().add(productQty)); |
| | | if (ObjectUtils.isNull(productWorkOrder.getActualStartTime())) { |
| | | productWorkOrder.setActualStartTime(LocalDate.now());//实际开始时间 |
| | | // 查询该工单对应的最早上机时间(按上机时间升序,取第一条) |
| | | List<ProductionMachineRecord> machineRecords = productionMachineRecordMapper.selectList( |
| | | Wrappers.<ProductionMachineRecord>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(LocalDate.now());//实际结束时间 |
| | | // 仅完成数量达到计划数量时才填充实际结束时间,未完成则清空已填的结束时间(允许继续分批报工) |
| | | if (productWorkOrder.getCompleteQuantity().compareTo(productWorkOrder.getPlanQuantity()) >= 0) { |
| | | productWorkOrder.setActualEndTime(now); |
| | | productWorkOrder.setEndProductTime(now); |
| | | productWorkOrderMapper.updateById(productWorkOrder); |
| | | } else { |
| | | // updateById 默认忽略 null 字段,需用 UpdateWrapper 显式清空(自愈历史脏数据) |
| | | productWorkOrderMapper.update(null, Wrappers.<ProductWorkOrder>lambdaUpdate() |
| | | .eq(ProductWorkOrder::getId, productWorkOrder.getId()) |
| | | .set(ProductWorkOrder::getActualEndTime, null) |
| | | .set(ProductWorkOrder::getEndProductTime, null)); |
| | | } |
| | | productWorkOrder.setEndProductTime(now); |
| | | productWorkOrderMapper.updateById(productWorkOrder); |
| | | //生产订单 |
| | | ProductOrder productOrder = productOrderMapper.selectById(productWorkOrder.getProductOrderId()); |
| | | if (ObjectUtils.isNull(productOrder.getStartTime())) { |
| | | productOrder.setStartTime(now);//开始时间 |
| | | } |
| | | if (productProcessRouteItem.getDragSort() == productProcessRouteItems.size()) { |
| | | if (productProcessRouteItem.getDragSort() >= productProcessRouteItems.size() -1 ) { |
| | | //如果是最后一道工序报工之后生产订单完成数量+ |
| | | productOrder.setCompleteQuantity(productOrder.getCompleteQuantity().add(productQty)); |
| | | if (productOrder.getCompleteQuantity().compareTo(productOrder.getQuantity()) == 0) { |
| | | if (productOrder.getCompleteQuantity().compareTo(productOrder.getQuantity()) >= 0) { |
| | | productOrder.setEndTime(now);//结束时间 |
| | | } |
| | | } |
| | | productOrderMapper.updateById(productOrder); |
| | | } |
| | | |
| | | //nextAddProductMain(productionProductOutput) // 由于需要审核,所以需要拆封下来 |
| | | ProductAuditVo productAuditVo = new ProductAuditVo(); |
| | | productAuditVo.setId(productionProductMain.getId()); |
| | | productAuditVo.setAuditStatus(AuditEnum.AUDIT_SUCCESS); |
| | | productAuditVo.setAuditOpinion(""); |
| | | ((ProductionProductMainService) AopContext.currentProxy()).auditProductMain(productAuditVo); |
| | | // nextAddProductMain(productionProductOutput) // 由于需要审核,所以需要拆封下来 |
| | | return true; |
| | | } |
| | | |
| | |
| | | ProductionProductMain productionProductMain = productionProductMainMapper.selectById(productAuditVo.getId()); |
| | | |
| | | // 当前审批人 要与当前登录人为同一人 |
| | | if(productionProductMain.getAuditUserId() != -1){ |
| | | if (productionProductMain.getAuditUserId() != -1) { |
| | | Assert.isTrue(SecurityUtils.getUserId().equals(productionProductMain.getAuditUserId()), "当前登录用户不是当前审批人"); |
| | | } |
| | | |
| | |
| | | // 减少 更新工单和生产订单 |
| | | 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(productionProductOutput.getQuantity()) |
| | | .subtract(processQty) |
| | | .max(BigDecimal.ZERO) |
| | | ); |
| | | List<ProductProcessRouteItem> productProcessRouteItems = productProcessRouteItemMapper.selectList(Wrappers.<ProductProcessRouteItem>lambdaQuery().eq(ProductProcessRouteItem::getProductRouteId, productProcessRouteItem.getProductRouteId())); |
| | |
| | | //如果是最后一道工序报工之后生产订单 需要扣除 |
| | | productOrder.setCompleteQuantity( |
| | | productOrder.getCompleteQuantity() |
| | | .subtract(productionProductOutput.getQuantity()) |
| | | .subtract(processQty) |
| | | .max(BigDecimal.ZERO) |
| | | ); |
| | | if (productOrder.getCompleteQuantity().compareTo(productionProductOutput.getQuantity()) > 0) { |
| | | if (productOrder.getCompleteQuantity().compareTo(processQty) > 0) { |
| | | productOrder.setEndTime(null); |
| | | } |
| | | productOrderMapper.updateById(productOrder); |
| | | } |
| | | |
| | | if (productWorkOrder.getCompleteQuantity().compareTo(productionProductOutput.getQuantity()) > 0) { |
| | | if (productWorkOrder.getCompleteQuantity().compareTo(processQty) > 0) { |
| | | productWorkOrder.setActualEndTime(null); |
| | | } |
| | | |
| | |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void nextAddProductMain(@NotNull ProductionProductOutput productionProductOutput){ |
| | | //合格数量=报工数量-报废数量 |
| | | public void nextAddProductMain(@NotNull ProductionProductOutput productionProductOutput) { |
| | | //实际入库数量=产出数量+加放数-报废数量 |
| | | ProductionProductMain productionProductMain = productionProductMainMapper.selectById(productionProductOutput.getProductMainId()); |
| | | BigDecimal productQty = productionProductOutput.getQuantity().subtract(productionProductOutput.getScrapQty()); |
| | | 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()); |
| | | //工艺路线中当前工序对应的产出规格型号 |
| | |
| | | //对应的过程检或者出厂检 |
| | | int inspectType = 1; |
| | | String process = productProcess.getName();//工序 |
| | | if (productProcessRouteItem.getDragSort() == productProcessRouteItems.size()) { |
| | | if (productProcessRouteItem.getDragSort() == (productProcessRouteItems.size()-1)) { |
| | | //最后一道工序生成出厂检 |
| | | inspectType = 2; |
| | | process = null; |
| | | } |
| | | 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.isEmpty()) { |
| | | 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); |
| | | }); |
| | | // 排产下达时已为该工单预生成质检单(product_main_id IS NULL),报工审核时认领并更新为实际数量 |
| | | QualityInspect preInspect = qualityInspectMapper.selectOne( |
| | | Wrappers.<QualityInspect>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 { |
| | | } else { |
| | | //直接入库 |
| | | stockUtils.addStock(productProcessRouteItem.getProductModelId(), productQty, StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode(), productionProductMain.getId(),"-","-","-"); |
| | | if (productProcessRouteItem.getDragSort() == (productProcessRouteItems.size()-1)) { |
| | | //最后一道工序才会入库 |
| | | stockUtils.addStock(productProcessRouteItem.getProductModelId(), productQty, StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode(), productionProductMain.getId(), "-", "-", "-"); |
| | | } |
| | | } |
| | | |
| | | /*添加生产核算 区分工序是计件还是计时*/ |
| | | BigDecimal workHours = productProcess.getSalaryQuota(); |
| | | |
| | | SalesLedgerProductionAccounting salesLedgerProductionAccounting = SalesLedgerProductionAccounting.builder() |
| | | .productMainId(productionProductMain.getId()) |
| | | .schedulingUserId(productionProductMain.getUserId()) |
| | | .schedulingUserName(userMapper.selectUserById(productionProductMain.getUserId()).getNickName()) |
| | | .finishedNum(productQty) |
| | | .workHours(workHours) |
| | | .process(productProcess.getName()) |
| | | .schedulingDate(LocalDate.now()) |
| | | .tenantId(productionProductOutput.getTenantId()) |
| | | .build(); |
| | | salesLedgerProductionAccountingMapper.insert(salesLedgerProductionAccounting); |
| | | } |
| | | |
| | | //如果报废数量>0,需要进入报废的库存 |
| | | if (ObjectUtils.isNotEmpty(productionProductOutput.getScrapQty())) { |
| | | if (productionProductOutput.getScrapQty().compareTo(BigDecimal.ZERO) > 0) { |
| | | stockUtils.addUnStock(productModel.getId(), productionProductOutput.getScrapQty(), StockInUnQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode(), productionProductMain.getId(),"-","-","-"); |
| | | List<ProductionMachineRecord> productionMachineRecords = productionMachineRecordMapper.selectList(Wrappers.<ProductionMachineRecord>lambdaQuery().eq(ProductionMachineRecord::getWorkOrderId, productionProductMain.getWorkOrderId())); |
| | | // 报工班组人员产量时长明细(有明细则按人生成核算,无明细则回退机台操作员逻辑) |
| | | List<ProductionReportPerson> personList = productionReportPersonMapper.selectList(Wrappers.<ProductionReportPerson>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> qualityTestStandard = qualityTestStandardMapper.getQualityTestStandardByProductId(product.getId(), inspectType, process); |
| | | if (!qualityTestStandard.isEmpty()) { |
| | | 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); |
| | | }); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void preGenerateQualityInspectForOrder(Long productOrderId) { |
| | | if (productOrderId == null) { |
| | | return; |
| | | } |
| | | ProductProcessRoute productProcessRoute = productProcessRouteMapper.selectOne( |
| | | Wrappers.<ProductProcessRoute>lambdaQuery() |
| | | .eq(ProductProcessRoute::getProductOrderId, productOrderId)); |
| | | if (productProcessRoute == null) { |
| | | return; |
| | | } |
| | | List<ProductProcessRouteItem> items = productProcessRouteItemMapper.selectList( |
| | | Wrappers.<ProductProcessRouteItem>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.<ProductWorkOrder>lambdaQuery() |
| | | .eq(ProductWorkOrder::getProductProcessRouteItemId, first.getId())); |
| | | if (workOrder == null) { |
| | | return; |
| | | } |
| | | // 该工单已存在预生成质检单则不重复生成 |
| | | Long existCount = qualityInspectMapper.selectCount( |
| | | Wrappers.<QualityInspect>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<Long> workOrderIds) { |
| | | if (CollUtil.isEmpty(workOrderIds)) { |
| | | return; |
| | | } |
| | | List<QualityInspect> preInspects = qualityInspectMapper.selectList( |
| | | Wrappers.<QualityInspect>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<Long> inspectIds = preInspects.stream().map(QualityInspect::getId).collect(Collectors.toList()); |
| | | qualityInspectParamMapper.delete( |
| | | Wrappers.<QualityInspectParam>lambdaQuery().in(QualityInspectParam::getInspectId, inspectIds)); |
| | | qualityInspectMapper.deleteBatchIds(inspectIds); |
| | | } |
| | | |
| | | @Override |
| | | public Boolean removeProductMain(Long id) { |
| | | //判断该条报工是否不合格处理,如果不合格处理了,则不允许删除 |
| | | List<QualityInspect> qualityInspects = qualityInspectMapper.selectList(Wrappers.<QualityInspect>lambdaQuery().eq(QualityInspect::getProductMainId, id)); |
| | | if (qualityInspects.size() > 0){ |
| | | 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) { |
| | | if (qualityUnqualifieds.size() > 0 && qualityUnqualifieds.get(0).getInspectState() == 1) { |
| | | throw new ServiceException("该条报工已经不合格处理了,不允许删除"); |
| | | } |
| | | } |
| | |
| | | new LambdaQueryWrapper<SalesLedgerProductionAccounting>() |
| | | .eq(SalesLedgerProductionAccounting::getProductMainId, productionProductMain.getId()) |
| | | ); |
| | | /*删除报工班组人员产量时长明细*/ |
| | | productionReportPersonMapper.delete( |
| | | new LambdaQueryWrapper<ProductionReportPerson>() |
| | | .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 scrapQty = productionProductOutput.getScrapQty() == null ? BigDecimal.ZERO : productionProductOutput.getScrapQty(); |
| | | BigDecimal addQty = productionProductOutput.getAddQty() == null ? BigDecimal.ZERO : productionProductOutput.getAddQty(); |
| | | BigDecimal completeQty = productWorkOrder.getCompleteQuantity() == null ? BigDecimal.ZERO : productWorkOrder.getCompleteQuantity(); |
| | | |
| | | // 必须为审核通过的才会减少数量 |
| | | |
| | | |
| | | BigDecimal validQuantity = outputQty.subtract(scrapQty); |
| | | if(productionProductMain.getAuditStatus() != 2){ |
| | | BigDecimal validQuantity = outputQty.add(addQty); |
| | | if (productionProductMain.getAuditStatus() != 2) { |
| | | productWorkOrder.setCompleteQuantity(completeQty.subtract(validQuantity).max(BigDecimal.ZERO)); |
| | | } |
| | | productWorkOrder.setActualEndTime(null); |
| | |
| | | if (productOrder != null) { |
| | | BigDecimal orderCompleteQty = productOrder.getCompleteQuantity() == null ? BigDecimal.ZERO : productOrder.getCompleteQuantity(); |
| | | BigDecimal totalQty = productionProductOutput.getQuantity() != null ? productionProductOutput.getQuantity() : BigDecimal.ZERO; |
| | | BigDecimal scrapQty = productionProductOutput.getScrapQty() != null ? productionProductOutput.getScrapQty() : BigDecimal.ZERO; |
| | | BigDecimal actualQualifiedQty = totalQty.subtract(scrapQty); |
| | | 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); |
| | |
| | | new LambdaQueryWrapper<QualityInspectParam>() |
| | | .eq(QualityInspectParam::getInspectId, q.getId())); |
| | | qualityInspectMapper.deleteById(q.getId()); |
| | | stockUtils.deleteStockInRecord(q.getId(), StockInQualifiedRecordTypeEnum.QUALITYINSPECT_STOCK_IN.getCode()); |
| | | stockUtils.deleteStockInRecord(q.getId(), StockInQualifiedRecordTypeEnum.QUALITYINSPECT_STOCK_IN.getCode()); |
| | | }); |
| | | |
| | | // 删除产出记录 |
| | |
| | | //删除投入记录 |
| | | productionProductInputMapper.delete(new LambdaQueryWrapper<ProductionProductInput>() |
| | | .eq(ProductionProductInput::getProductMainId, productionProductMain.getId())); |
| | | //删除报废的入库记录 |
| | | stockUtils.deleteStockInRecord(productionProductMain.getId(), StockInUnQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode()); |
| | | //删除不需要质检的合格入库 |
| | | stockUtils.deleteStockInRecord(productionProductMain.getId(), StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode()); |
| | | //删除投入对应的出库记录 |
| | |
| | | public ArrayList<Long> listMain(List<Long> idList) { |
| | | return productionProductMainMapper.listMain(idList); |
| | | } |
| | | } |
| | | } |