| | |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.ruoyi.account.mapper.AccountExpenseMapper; |
| | | import com.ruoyi.account.mapper.AccountIncomeMapper; |
| | | import com.ruoyi.account.pojo.AccountExpense; |
| | | import com.ruoyi.home.mapper.HomeMapper; |
| | | import com.ruoyi.account.mapper.AccountExpenseMapper; |
| | | import com.ruoyi.approve.mapper.ApproveProcessMapper; |
| | | import com.ruoyi.approve.pojo.ApproveProcess; |
| | | import com.ruoyi.basic.mapper.CustomerMapper; |
| | | import com.ruoyi.basic.mapper.ProductMapper; |
| | | import com.ruoyi.basic.mapper.ProductModelMapper; |
| | | import com.ruoyi.basic.mapper.SupplierManageMapper; |
| | | import com.ruoyi.basic.pojo.Customer; |
| | | import com.ruoyi.basic.pojo.Product; |
| | |
| | | import com.ruoyi.dto.MapDto; |
| | | import com.ruoyi.framework.security.LoginUser; |
| | | import com.ruoyi.home.dto.*; |
| | | import com.ruoyi.home.mapper.HomeMapper; |
| | | import com.ruoyi.home.service.HomeService; |
| | | import com.ruoyi.procurementrecord.mapper.ProcurementRecordMapper; |
| | | import com.ruoyi.procurementrecord.pojo.ProcurementRecordStorage; |
| | | import com.ruoyi.procurementrecord.utils.StockUtils; |
| | | import com.ruoyi.production.dto.ProductOrderDto; |
| | | import com.ruoyi.production.dto.ProductWorkOrderDto; |
| | | import com.ruoyi.production.mapper.ProductOrderMapper; |
| | | import com.ruoyi.production.mapper.ProductProcessMapper; |
| | | import com.ruoyi.production.mapper.ProductWorkOrderMapper; |
| | | import com.ruoyi.production.mapper.ProductionProductInputMapper; |
| | | import com.ruoyi.production.mapper.ProductionProductOutputMapper; |
| | | import com.ruoyi.production.mapper.SalesLedgerProductionAccountingMapper; |
| | | import com.ruoyi.production.pojo.ProductProcess; |
| | | import com.ruoyi.production.mapper.*; |
| | | import com.ruoyi.production.pojo.ProductWorkOrder; |
| | | import com.ruoyi.project.system.domain.SysDept; |
| | | import com.ruoyi.project.system.mapper.SysDeptMapper; |
| | |
| | | |
| | | @Autowired |
| | | private ProductProcessMapper productProcessMapper; |
| | | |
| | | |
| | | @Autowired |
| | | private AccountExpenseMapper accountExpenseMapper; |
| | | |
| | |
| | | LambdaQueryWrapper<PurchaseLedger> queryWrapper = new LambdaQueryWrapper<>(); |
| | | queryWrapper.ge(PurchaseLedger::getEntryDate, currentMonth.atDay(1).atStartOfDay()) // 大于等于本月第一天 |
| | | .lt(PurchaseLedger::getEntryDate, currentMonth.plusMonths(1).atDay(1).atStartOfDay()); // 小于下月第一天 |
| | | // 执行查询并计算总和 |
| | | |
| | | List<PurchaseLedger> purchaseLedgers = purchaseLedgerMapper.selectList(queryWrapper); |
| | | if (!CollectionUtils.isEmpty(purchaseLedgers)) { |
| | | LambdaQueryWrapper<SalesLedgerProduct> salesLedgerProductMapperLambdaQueryWrapperCopy = new LambdaQueryWrapper<SalesLedgerProduct>(); |
| | | salesLedgerProductMapperLambdaQueryWrapperCopy.eq(SalesLedgerProduct::getType, 2) |
| | | LambdaQueryWrapper<SalesLedgerProduct> salesLedgerProductMapperLambdaQueryWrapperCopy = new LambdaQueryWrapper<>(); |
| | | salesLedgerProductMapperLambdaQueryWrapperCopy.eq(SalesLedgerProduct::getType, 2) // 采购类型 |
| | | .in(SalesLedgerProduct::getSalesLedgerId, |
| | | purchaseLedgers.stream().map(PurchaseLedger::getId).collect(Collectors.toList())); |
| | | |
| | | List<SalesLedgerProduct> salesLedgerProductsCopy = salesLedgerProductMapper |
| | | .selectList(salesLedgerProductMapperLambdaQueryWrapperCopy); |
| | | // 合计合同金额 |
| | | |
| | | // 合计合同总金额 |
| | | BigDecimal receiveAmount = purchaseLedgers.stream() |
| | | .map(PurchaseLedger::getContractAmount) |
| | | .filter(Objects::nonNull) |
| | | .reduce(BigDecimal.ZERO, BigDecimal::add); |
| | | // 未开票金额 |
| | | |
| | | // 待付款总金额 |
| | | BigDecimal unReceiptPaymentAmount = salesLedgerProductsCopy.stream() |
| | | .map(SalesLedgerProduct::getNoInvoiceAmount) |
| | | .map(SalesLedgerProduct::getPendingTicketsTotal) |
| | | .filter(Objects::nonNull) |
| | | .reduce(BigDecimal.ZERO, BigDecimal::add); |
| | | |
| | | homeBusinessDto.setMonthPurchaseMoney(receiveAmount.setScale(2, RoundingMode.HALF_UP).toString()); |
| | | homeBusinessDto |
| | | .setMonthPurchaseHaveMoney(unReceiptPaymentAmount.setScale(2, RoundingMode.HALF_UP).toString()); |
| | | homeBusinessDto.setMonthPurchaseHaveMoney(unReceiptPaymentAmount.setScale(2, RoundingMode.HALF_UP).toString()); |
| | | } |
| | | // 统计库存 |
| | | BigDecimal stockQuantityTotal = stockInventoryMapper.selectTotal(); |
| | |
| | | return analysisCustomerContractAmountsDto; |
| | | } |
| | | |
| | | private static BigDecimal nz(BigDecimal v) { |
| | | return v == null ? BigDecimal.ZERO : v; |
| | | } |
| | | |
| | | /** |
| | | * 大屏/报表统计用合格数量:以 qualified_quantity |
| | | */ |
| | | private BigDecimal inspectQualifiedQtyForStat(QualityInspect item) { |
| | | if (item.getQualifiedQuantity() != null) { |
| | | return item.getQualifiedQuantity(); |
| | | } |
| | | BigDecimal qty = nz(item.getQuantity()); |
| | | if ("合格".equals(item.getCheckResult())) { |
| | | return qty; |
| | | } |
| | | return BigDecimal.ZERO; |
| | | } |
| | | |
| | | /** |
| | | * 大屏/报表统计用不合格数量:以 unqualified_quantity |
| | | */ |
| | | private BigDecimal inspectUnqualifiedQtyForStat(QualityInspect item) { |
| | | if (item.getUnqualifiedQuantity() != null) { |
| | | return item.getUnqualifiedQuantity(); |
| | | } |
| | | BigDecimal qty = nz(item.getQuantity()); |
| | | String cr = item.getCheckResult(); |
| | | if ("不合格".equals(cr) || "部分合格".equals(cr)) { |
| | | return qty; |
| | | } |
| | | return BigDecimal.ZERO; |
| | | } |
| | | |
| | | private boolean inspectHasUnqualifiedVolume(QualityInspect item) { |
| | | return inspectUnqualifiedQtyForStat(item).compareTo(BigDecimal.ZERO) > 0; |
| | | } |
| | | |
| | | private static int toStatInt(BigDecimal v) { |
| | | return nz(v).setScale(0, RoundingMode.HALF_UP).intValue(); |
| | | } |
| | | |
| | | @Override |
| | | public QualityStatisticsDto qualityStatistics() { |
| | | // 获取近四个月数据(往前推三个月,共4个完整月份) |
| | |
| | | QualityStatisticsItem item = new QualityStatisticsItem(); |
| | | item.setDate(monthStart.format(monthFormatter)); // 日期显示为“年月”(如 2025-10) |
| | | |
| | | // 1. 供应商检验(类型0)- 合格数量 |
| | | BigDecimal supplierQualified = monthInspects.stream() |
| | | // 1~3:本月「不合格数量」(仅已提交检验),按检验类别拆分——用于图表图例「××不合格数」 |
| | | BigDecimal supplierUnq = monthInspects.stream() |
| | | .filter(inspect -> inspect.getInspectType().equals(0) |
| | | && "合格".equals(inspect.getCheckResult())) |
| | | .map(QualityInspect::getQuantity) |
| | | && Objects.equals(inspect.getInspectState(), 1)) |
| | | .map(this::inspectUnqualifiedQtyForStat) |
| | | .reduce(BigDecimal.ZERO, BigDecimal::add); |
| | | item.setSupplierNum(supplierQualified); |
| | | item.setSupplierNum(supplierUnq); |
| | | |
| | | // 2. 工序检验(类型1)- 合格数量 |
| | | BigDecimal processQualified = monthInspects.stream() |
| | | BigDecimal processUnq = monthInspects.stream() |
| | | .filter(inspect -> inspect.getInspectType().equals(1) |
| | | && "合格".equals(inspect.getCheckResult())) |
| | | .map(QualityInspect::getQuantity) |
| | | && Objects.equals(inspect.getInspectState(), 1)) |
| | | .map(this::inspectUnqualifiedQtyForStat) |
| | | .reduce(BigDecimal.ZERO, BigDecimal::add); |
| | | item.setProcessNum(processQualified); |
| | | item.setProcessNum(processUnq); |
| | | |
| | | // 3. 工厂检验(类型2)- 合格数量 |
| | | BigDecimal factoryQualified = monthInspects.stream() |
| | | BigDecimal factoryUnq = monthInspects.stream() |
| | | .filter(inspect -> inspect.getInspectType().equals(2) |
| | | && "合格".equals(inspect.getCheckResult())) |
| | | .map(QualityInspect::getQuantity) |
| | | && Objects.equals(inspect.getInspectState(), 1)) |
| | | .map(this::inspectUnqualifiedQtyForStat) |
| | | .reduce(BigDecimal.ZERO, BigDecimal::add); |
| | | item.setFactoryNum(factoryQualified); |
| | | item.setFactoryNum(factoryUnq); |
| | | |
| | | qualityStatisticsItems.add(item); |
| | | } |
| | |
| | | @Override |
| | | public HomeSummaryDto summaryStatistics() { |
| | | HomeSummaryDto dto = new HomeSummaryDto(); |
| | | LocalDate now = LocalDate.now(); |
| | | YearMonth currentMonth = YearMonth.from(now); |
| | | YearMonth prevMonth = currentMonth.minusMonths(1); |
| | | |
| | | LocalDateTime currentMonthEnd = currentMonth.atEndOfMonth().atTime(23, 59, 59); |
| | | LocalDateTime prevMonthEnd = prevMonth.atEndOfMonth().atTime(23, 59, 59); |
| | | |
| | | // 总工作人员 |
| | | Long currentStaff = countStaff(currentMonthEnd); |
| | | Long prevStaff = countStaff(prevMonthEnd); |
| | | Long currentStaff = 0L; |
| | | dto.setTotalStaff(currentStaff); |
| | | dto.setStaffGrowthRate(calculateMoM(currentStaff, prevStaff)); |
| | | |
| | | // 总客户数 |
| | | Long currentCustomers = countCustomers(currentMonthEnd); |
| | | Long prevCustomers = countCustomers(prevMonthEnd); |
| | | Long currentCustomers = customerMapper.selectCount(null); |
| | | dto.setTotalCustomer(currentCustomers); |
| | | dto.setCustomerGrowthRate(calculateMoM(currentCustomers, prevCustomers)); |
| | | |
| | | // 总供应商数 |
| | | Long currentSuppliers = countSuppliers(currentMonthEnd); |
| | | Long prevSuppliers = countSuppliers(prevMonthEnd); |
| | | Long currentSuppliers = supplierManageMapper.selectCount(null); |
| | | dto.setTotalSupplier(currentSuppliers); |
| | | dto.setSupplierGrowthRate(calculateMoM(currentSuppliers, prevSuppliers)); |
| | | |
| | | return dto; |
| | | } |
| | | |
| | | private Long countStaff(LocalDateTime dateTime) { |
| | | Long staffCountItem = staffOnJobMapper.selectCount(new LambdaQueryWrapper<StaffOnJob>() |
| | | .isNotNull(StaffOnJob::getStaffState) |
| | | .eq(StaffOnJob::getStaffState, 1) |
| | | .le(StaffOnJob::getCreateTime, dateTime)); |
| | | return staffCountItem; |
| | | } |
| | | |
| | | private Long countCustomers(LocalDateTime dateTime) { |
| | | return customerMapper.selectCount(new LambdaQueryWrapper<Customer>() |
| | | .le(Customer::getMaintenanceTime, dateTime.toLocalDate())); |
| | | } |
| | | |
| | | private Long countSuppliers(LocalDateTime dateTime) { |
| | | return supplierManageMapper.selectCount(new LambdaQueryWrapper<SupplierManage>() |
| | | .le(SupplierManage::getCreateTime, dateTime)); |
| | | } |
| | | |
| | | private String calculateMoM(Number current, Number prev) { |
| | | BigDecimal curVal = new BigDecimal(current.toString()); |
| | | BigDecimal prevVal = new BigDecimal(prev.toString()); |
| | | if (prevVal.compareTo(BigDecimal.ZERO) == 0) { |
| | | return curVal.compareTo(BigDecimal.ZERO) > 0 ? "100.00" : "0.00"; |
| | | } |
| | | return curVal.subtract(prevVal) |
| | | .divide(prevVal, 4, RoundingMode.HALF_UP) |
| | | .multiply(new BigDecimal("100")) |
| | | .setScale(2, RoundingMode.HALF_UP) |
| | | .toString(); |
| | | } |
| | | |
| | | @Override |
| | | public List<SupplierPurchaseRankingDto> supplierPurchaseRanking(Integer type) { |
| | |
| | | BigDecimal unqualifiedCount = BigDecimal.ZERO; |
| | | |
| | | for (QualityInspect item : list) { |
| | | if ("合格".equals(item.getCheckResult())) { |
| | | qualifiedCount = qualifiedCount.add(item.getQuantity()); |
| | | } else { |
| | | unqualifiedCount = unqualifiedCount.add(item.getQuantity()); |
| | | } |
| | | qualifiedCount = qualifiedCount.add(inspectQualifiedQtyForStat(item)); |
| | | unqualifiedCount = unqualifiedCount.add(inspectUnqualifiedQtyForStat(item)); |
| | | } |
| | | |
| | | BigDecimal totalCount = qualifiedCount.add(unqualifiedCount); |
| | | |
| | | dto.setQualifiedCount(qualifiedCount.intValue()); |
| | | dto.setUnqualifiedCount(unqualifiedCount.intValue()); |
| | | dto.setQualifiedCount(toStatInt(qualifiedCount)); |
| | | dto.setUnqualifiedCount(toStatInt(unqualifiedCount)); |
| | | |
| | | if (totalCount.compareTo(BigDecimal.ZERO) == 0) { |
| | | dto.setQualifiedRate(BigDecimal.ZERO.setScale(2)); |
| | |
| | | continue; |
| | | } |
| | | |
| | | BigDecimal quantity = item.getQuantity(); |
| | | |
| | | if ("合格".equals(item.getCheckResult())) { |
| | | dto.setQualifiedCount(dto.getQualifiedCount().add(quantity)); |
| | | } else { |
| | | dto.setUnqualifiedCount(dto.getUnqualifiedCount().add(quantity)); |
| | | } |
| | | dto.setQualifiedCount(dto.getQualifiedCount().add(inspectQualifiedQtyForStat(item))); |
| | | dto.setUnqualifiedCount(dto.getUnqualifiedCount().add(inspectUnqualifiedQtyForStat(item))); |
| | | } |
| | | |
| | | // 计算合格率 |
| | |
| | | BigDecimal unqualifiedCount = BigDecimal.ZERO; |
| | | |
| | | for (QualityInspect item : items) { |
| | | BigDecimal qty = item.getQuantity(); |
| | | BigDecimal qty = nz(item.getQuantity()); |
| | | totalCount = totalCount.add(qty); |
| | | |
| | | if ("合格".equals(item.getCheckResult())) { |
| | | qualifiedCount = qualifiedCount.add(qty); |
| | | } else { |
| | | unqualifiedCount = unqualifiedCount.add(qty); |
| | | } |
| | | qualifiedCount = qualifiedCount.add(inspectQualifiedQtyForStat(item)); |
| | | unqualifiedCount = unqualifiedCount.add(inspectUnqualifiedQtyForStat(item)); |
| | | } |
| | | |
| | | if (totalCount.compareTo(BigDecimal.ZERO) == 0) { |
| | |
| | | dto.setProcessNum(sumQuantity(qualityInspectList, 1)); // 过程 |
| | | dto.setFactoryNum(sumQuantity(qualityInspectList, 2)); // 出厂 |
| | | |
| | | // 假设 qualityInspectList 是一个 List<QualityInspect> 类型的集合 |
| | | Map<String, List<QualityInspect>> groupedByCheckResult = qualityInspectList.stream() |
| | | .collect(Collectors.groupingBy(QualityInspect::getCheckResult)); |
| | | List<QualityInspect> qualityInspects = groupedByCheckResult.get("不合格"); |
| | | // 存在不合格数量的检验单(含按数量拆分的新数据;旧数据仍可用检测结果兜底) |
| | | List<QualityInspect> qualityInspects = qualityInspectList.stream() |
| | | .filter(this::inspectHasUnqualifiedVolume) |
| | | .collect(Collectors.toList()); |
| | | if (ObjectUtils.isNull(qualityInspects) || qualityInspects.size() == 0) { |
| | | return null; |
| | | return dto; |
| | | } |
| | | // 4. 处理图表项 (Item) |
| | | List<QualityStatisticsItem> itemList = new ArrayList<>(); |
| | |
| | | QualityStatisticsItem item = new QualityStatisticsItem(); |
| | | item.setDate(dateLabel); |
| | | |
| | | item.setSupplierNum(list.stream().filter(i -> i.getInspectType() == 0).map(QualityInspect::getQuantity) |
| | | item.setSupplierNum(list.stream().filter(i -> i.getInspectType() == 0).map(this::inspectUnqualifiedQtyForStat) |
| | | .reduce(BigDecimal.ZERO, BigDecimal::add)); |
| | | item.setProcessNum(list.stream().filter(i -> i.getInspectType() == 1).map(QualityInspect::getQuantity) |
| | | item.setProcessNum(list.stream().filter(i -> i.getInspectType() == 1).map(this::inspectUnqualifiedQtyForStat) |
| | | .reduce(BigDecimal.ZERO, BigDecimal::add)); |
| | | item.setFactoryNum(list.stream().filter(i -> i.getInspectType() == 2).map(QualityInspect::getQuantity) |
| | | item.setFactoryNum(list.stream().filter(i -> i.getInspectType() == 2).map(this::inspectUnqualifiedQtyForStat) |
| | | .reduce(BigDecimal.ZERO, BigDecimal::add)); |
| | | |
| | | return item; |