| | |
| | | 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.CollectionUtils; |
| | | import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | |
| | | import com.ruoyi.basic.pojo.Product; |
| | | import com.ruoyi.basic.pojo.ProductModel; |
| | | import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum; |
| | | import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum; |
| | | import com.ruoyi.common.enums.StockInUnQualifiedRecordTypeEnum; |
| | | import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum; |
| | | 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 lombok.AllArgsConstructor; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import com.ruoyi.production.mapper.ProductionProductMainMapper; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | |
| | | import java.time.LocalDateTime; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.*; |
| | | import java.util.function.Function; |
| | | import java.util.stream.Collectors; |
| | | |
| | | @Service |
| | |
| | | if (productProcessRouteItem == null) { |
| | | throw new RuntimeException("工艺路线项不存在"); |
| | | } |
| | | // 是否能报工: 1. 第一个工序能报工 2. 上一个工序已报工 3. 之前的工序未被隔离 |
| | | //检查上一个工序是否已报工 |
| | | Integer currentDragSort = productProcessRouteItem.getDragSort(); |
| | | if (currentDragSort != null && currentDragSort > 1) { |
| | | ProductProcessRouteItem previousItem = productProcessRouteItemMapper.selectOne( |
| | | boolean isPreviousReported = productionProductMainMapper.checkPreviousProcessReported( |
| | | productProcessRouteItem.getProductRouteId(), |
| | | currentDragSort |
| | | ); |
| | | if (!isPreviousReported) { |
| | | throw new RuntimeException("上一个工序尚未报工,不能进行当前工序报工"); |
| | | } |
| | | |
| | | // 查询所有之前的工序(排序号小于当前工序) |
| | | List<ProductProcessRouteItem> previousItems = productProcessRouteItemMapper.selectList( |
| | | Wrappers.<ProductProcessRouteItem>lambdaQuery() |
| | | .eq(ProductProcessRouteItem::getProductRouteId, productProcessRouteItem.getProductRouteId()) |
| | | .eq(ProductProcessRouteItem::getDragSort, currentDragSort - 1) |
| | | .lt(ProductProcessRouteItem::getDragSort, currentDragSort) |
| | | ); |
| | | if (CollectionUtils.isNotEmpty(previousItems)) { |
| | | // 提取之前工序的名称列表 |
| | | List<String> previousProcessNames = new ArrayList<>(); |
| | | for (ProductProcessRouteItem item : previousItems) { |
| | | ProductProcess process = productProcessMapper.selectById(item.getProcessId()); |
| | | if (process != null) { |
| | | previousProcessNames.add(process.getName()); |
| | | } |
| | | } |
| | | |
| | | if (previousItem != null) { |
| | | //检查上一个工序是否有报工记录 |
| | | Long count = productionProductMainMapper.selectCount( |
| | | Wrappers.<ProductionProductMain>lambdaQuery() |
| | | .eq(ProductionProductMain::getProductProcessRouteItemId, previousItem.getId()) |
| | | ); |
| | | |
| | | if (count == 0) { |
| | | throw new RuntimeException("上一个工序尚未报工,不能进行当前工序报工"); |
| | | // 检查之前的工序是否有被隔离的不合格记录 |
| | | List<QualityUnqualified> unqualifiedList = qualityUnqualifiedMapper.selectUnqualifiedByProcessNames(previousProcessNames); |
| | | if (CollectionUtils.isNotEmpty(unqualifiedList)) { |
| | | throw new RuntimeException("之前的工序已被隔离,不能进行当前工序报工"); |
| | | } |
| | | } |
| | | } |
| | |
| | | } |
| | | String productNo = String.format("%s%03d", datePrefix, sequenceNumber); |
| | | productionProductMain.setProductNo(productNo); |
| | | productionProductMain.setUserId(dto.getUserId()); |
| | | productionProductMain.setUserName(dto.getUserName()); |
| | | Long userId = dto.getUserId(); |
| | | String userName = dto.getUserName(); |
| | | if (userId == null) { |
| | | userId = SecurityUtils.getLoginUser().getUserId(); |
| | | userName = SecurityUtils.getLoginUser().getNickName(); |
| | | } |
| | | productionProductMain.setUserId(userId); |
| | | productionProductMain.setUserName(userName); |
| | | productionProductMain.setProductProcessRouteItemId(dto.getProductProcessRouteItemId()); |
| | | productionProductMain.setWorkOrderId(dto.getWorkOrderId()); |
| | | productionProductMain.setStatus(0); |
| | | productionProductMainMapper.insert(productionProductMain); |
| | | /*新增报工投入表*/ |
| | | List<ProductStructureDto> productStructureDtos = productStructureMapper.listBybomAndProcess(productProcessRoute.getBomId(), productProcess.getId()); |
| | | if (productStructureDtos.size() == 0) { |
| | | if (productStructureDtos.isEmpty()) { |
| | | //如果该工序没有产品结构的投入品,那这个投入品和产出品是同一个 |
| | | ProductStructureDto productStructureDto = new ProductStructureDto(); |
| | | productStructureDto.setProductModelId(productProcessRouteItem.getProductModelId()); |
| | | productStructureDto.setUnitQuantity(BigDecimal.ONE); |
| | | productStructureDtos.add(productStructureDto); |
| | | } |
| | | Set<Long> parentIds = productStructureDtos.stream() |
| | | .map(ProductStructureDto::getParentId) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toSet()); |
| | | Map<Long, ProductStructureDto> parentMap = new HashMap<>(); |
| | | if (!parentIds.isEmpty()) { |
| | | parentMap = productStructureMapper.selectByIds(parentIds) |
| | | .stream() |
| | | .collect(Collectors.toMap( |
| | | ProductStructureDto::getId, |
| | | Function.identity() |
| | | )); |
| | | } |
| | | for (ProductStructureDto productStructureDto : productStructureDtos) { |
| | | |
| | | ProductionProductInput productionProductInput = new ProductionProductInput(); |
| | | productionProductInput.setProductModelId(productStructureDto.getProductModelId()); |
| | | productionProductInput.setQuantity(productStructureDto.getUnitQuantity().multiply(dto.getQuantity())); |
| | | // productionProductInput.setQuantity(productStructureDto.getUnitQuantity().multiply(dto.getQuantity())); |
| | | BigDecimal childQty = productStructureDto.getUnitQuantity(); |
| | | BigDecimal parentQty = BigDecimal.ONE; |
| | | if (productStructureDto.getParentId() != null) { |
| | | ProductStructureDto parent = parentMap.get(productStructureDto.getParentId()); |
| | | if (parent != null) { |
| | | parentQty = parent.getUnitQuantity(); |
| | | } |
| | | } |
| | | |
| | | // 核心计算 |
| | | BigDecimal needQty = childQty.divide(parentQty, 6, RoundingMode.HALF_UP).multiply(dto.getQuantity()); |
| | | |
| | | |
| | | productionProductInput.setQuantity(needQty); |
| | | |
| | | productionProductInput.setProductMainId(productionProductMain.getId()); |
| | | productionProductInputMapper.insert(productionProductInput); |
| | | stockUtils.substractStock(productStructureDto.getProductModelId(), productionProductInput.getQuantity(), StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode(), productionProductMain.getId()); |
| | | |
| | | stockUtils.substractStock(productStructureDto.getProductModelId(), productionProductInput.getQuantity(), StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode(), productionProductMain.getId(), null); |
| | | } |
| | | /*新增报工产出表*/ |
| | | ProductionProductOutput productionProductOutput = new ProductionProductOutput(); |
| | |
| | | |
| | | //合格数量=报工数量-报废数量 |
| | | BigDecimal productQty = productionProductOutput.getQuantity().subtract(productionProductOutput.getScrapQty()); |
| | | // 合格率=合格数量/报工数量 |
| | | BigDecimal productQtyRate = productQty.divide(productionProductOutput.getQuantity(), 2, RoundingMode.HALF_UP) |
| | | .multiply(new BigDecimal("100")); |
| | | // 该工序的合格率 < 合格率 |
| | | if (productQtyRate.compareTo(productProcess.getQualifiedRate()) < 0) { |
| | | // 发送通知给管理员 |
| | | sysNoticeService.simpleNoticeByUser("报工提示", |
| | | String.format("%s生产订单,%s工序合格率%.2f%%低于标准%.2f%%", productOrder.getNpsNo(), productProcess.getName(), productQtyRate, productProcess.getQualifiedRate()), |
| | | Arrays.asList(Long.valueOf(1L)), |
| | | "/productionManagement/productionReporting"); |
| | | } |
| | | |
| | | List<ProductProcessRouteItem> productProcessRouteItems = productProcessRouteItemMapper.selectList(Wrappers.<ProductProcessRouteItem>lambdaQuery().eq(ProductProcessRouteItem::getProductRouteId, productProcessRouteItem.getProductRouteId())); |
| | | //只有合格数量>0才能增加相应数据 |
| | | if (productQty.compareTo(BigDecimal.ZERO) > 0) { |
| | |
| | | qualityInspect.setProcess(process); |
| | | qualityInspect.setInspectState(0); |
| | | qualityInspect.setInspectType(inspectType); |
| | | qualityInspect.setDefectiveQuantity(productionProductOutput.getScrapQty()); |
| | | qualityInspect.setDefectiveQuantity(BigDecimal.ZERO); |
| | | qualityInspect.setProductMainId(productionProductMain.getId()); |
| | | qualityInspect.setProductModelId(productModel.getId()); |
| | | qualityInspectMapper.insert(qualityInspect); |
| | |
| | | /*添加生产核算*/ |
| | | SalesLedgerProductionAccounting salesLedgerProductionAccounting = SalesLedgerProductionAccounting.builder() |
| | | .productMainId(productionProductMain.getId()) |
| | | .schedulingUserId(user.getUserId()) |
| | | .schedulingUserName(user.getNickName()) |
| | | .schedulingUserId(userId) |
| | | .schedulingUserName(userName) |
| | | .finishedNum(productQty) |
| | | .workHours(productProcess.getSalaryQuota()) |
| | | .process(productProcess.getName()) |
| | |
| | | productionProductMainDtos.forEach(p -> { |
| | | QualityInspect qualityInspect = productMainIdToInspectMap.get(p.getId()); |
| | | if (qualityInspect != null) { |
| | | // 不良数量 |
| | | p.setDefectiveQuantity( qualityInspect.getDefectiveQuantity()); |
| | | // 合格数量 = 报工数量-报废数量-不良数量 |
| | | p.setQualifiedQty(p.getQuantity().subtract(p.getScrapQty()).subtract(p.getDefectiveQuantity())); |
| | | QualityUnqualified qualityUnqualified = inspectIdToUnqualifiedMap.get(qualityInspect.getId()); |
| | | if (qualityUnqualified != null) { |
| | | p.setDealResult(qualityUnqualified.getDealResult() == null ? "" : qualityUnqualified.getDealResult()); |