| | |
| | | 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 |
| | | LambdaQueryWrapper<SalesLedger> salesLedgerLambdaQueryWrapper = new LambdaQueryWrapper<>(); |
| | | salesLedgerLambdaQueryWrapper.ge(SalesLedger::getEntryDate, currentMonth.atDay(1).atStartOfDay()) // 大于等于本月第一天 |
| | | .lt(SalesLedger::getEntryDate, currentMonth.plusMonths(1).atDay(1).atStartOfDay()); // 小于下月第一天 |
| | | .lt(SalesLedger::getEntryDate, currentMonth.plusMonths(1).atDay(1).atStartOfDay()) // 小于下月第一天 |
| | | .ne(SalesLedger::getReviewStatus, 2); // 排除反审核数据 |
| | | List<SalesLedger> salesLedgers = salesLedgerMapper.selectList(salesLedgerLambdaQueryWrapper); |
| | | if (!CollectionUtils.isEmpty(salesLedgers)) { |
| | | // 合计合同金额 |
| | |
| | | |
| | | @Override |
| | | public AnalysisCustomerContractAmountsDto analysisCustomerContractAmounts() { |
| | | List<SalesLedger> salesLedgers = salesLedgerMapper.selectList(null); |
| | | List<SalesLedger> salesLedgers = salesLedgerMapper.selectList(new LambdaQueryWrapper<SalesLedger>().ne(SalesLedger::getReviewStatus, 2)); |
| | | // 合计合同金额 |
| | | BigDecimal contractAmount = salesLedgers.stream().map(SalesLedger::getContractAmount) |
| | | .filter(Objects::nonNull) |
| | |
| | | LocalDate endOfWeek = today.with(DayOfWeek.SUNDAY); |
| | | List<SalesLedger> salesLedgers1 = salesLedgerMapper.selectList(new LambdaQueryWrapper<SalesLedger>() |
| | | .ge(SalesLedger::getEntryDate, startOfWeek) // 大于等于本周周一 |
| | | .lt(SalesLedger::getEntryDate, endOfWeek.plusDays(1))); // 修改:使用 lt 并加上一天来包含周日 |
| | | .lt(SalesLedger::getEntryDate, endOfWeek.plusDays(1)) |
| | | .ne(SalesLedger::getReviewStatus, 2)); // 修改:使用 lt 并加上一天来包含周日 |
| | | BigDecimal weekContractAmount = salesLedgers1.stream().map(SalesLedger::getContractAmount) |
| | | .filter(Objects::nonNull) |
| | | .reduce(BigDecimal.ZERO, BigDecimal::add); |
| | |
| | | LocalDate lastYearEndOfWeek = today.minusYears(1).with(DayOfWeek.SUNDAY); |
| | | List<SalesLedger> salesLedgers2 = salesLedgerMapper.selectList(new LambdaQueryWrapper<SalesLedger>() |
| | | .ge(SalesLedger::getEntryDate, lastYearStartOfWeek) // 大于等于去年本周周一 |
| | | .lt(SalesLedger::getEntryDate, lastYearEndOfWeek.plusDays(1))); // 修改:使用 lt 并加上一天来包含周日 |
| | | .lt(SalesLedger::getEntryDate, lastYearEndOfWeek.plusDays(1)) |
| | | .ne(SalesLedger::getReviewStatus, 2)); // 修改:使用 lt 并加上一天来包含周日 |
| | | BigDecimal lastYearWeekContractAmount = salesLedgers2.stream().map(SalesLedger::getContractAmount) |
| | | .filter(Objects::nonNull) |
| | | .reduce(BigDecimal.ZERO, BigDecimal::add); |
| | |
| | | LocalDate plusDays = today.plusDays(1); |
| | | List<SalesLedger> salesLedgers3 = salesLedgerMapper.selectList(new LambdaQueryWrapper<SalesLedger>() |
| | | .ge(SalesLedger::getEntryDate, today) // 大于等于今天 |
| | | .lt(SalesLedger::getEntryDate, plusDays)); // 修改:使用 lt 并加上一天来包含当天 |
| | | .lt(SalesLedger::getEntryDate, plusDays) |
| | | .ne(SalesLedger::getReviewStatus, 2)); // 修改:使用 lt 并加上一天来包含当天 |
| | | BigDecimal todayContractAmount = salesLedgers3.stream().map(SalesLedger::getContractAmount) |
| | | .filter(Objects::nonNull) |
| | | .reduce(BigDecimal.ZERO, BigDecimal::add); |
| | | List<SalesLedger> salesLedgers4 = salesLedgerMapper.selectList(new LambdaQueryWrapper<SalesLedger>() |
| | | .ge(SalesLedger::getEntryDate, yesterday) // 大于等于昨天 |
| | | .lt(SalesLedger::getEntryDate, today)); // 修改:使用 lt 而不是 gt |
| | | .lt(SalesLedger::getEntryDate, today) |
| | | .ne(SalesLedger::getReviewStatus, 2)); // 修改:使用 lt 而不是 gt |
| | | BigDecimal lastYearYesterdayContractAmount = salesLedgers4.stream().map(SalesLedger::getContractAmount) |
| | | .filter(Objects::nonNull) |
| | | .reduce(BigDecimal.ZERO, BigDecimal::add); |
| | |
| | | }); |
| | | analysisCustomerContractAmountsDto.setItem(mapDtos); |
| | | 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 |
| | |
| | | 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); |
| | | } |
| | |
| | | } |
| | | // 应收 |
| | | List<SalesLedger> salesLedgers = salesLedgerMapper.selectList(new LambdaQueryWrapper<SalesLedger>() |
| | | // .ge(SalesLedger::getEntryDate, startDate) |
| | | // .lt(SalesLedger::getEntryDate, endDate) |
| | | .ne(SalesLedger::getReviewStatus, 2) // 排除反审核数据 |
| | | ); |
| | | // BigDecimal receivableMoney = |
| | | // salesLedgers.stream().map(SalesLedger::getContractAmount).reduce(BigDecimal.ZERO, |
| | |
| | | @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) { |
| | |
| | | List<SalesLedger> list = salesLedgerMapper.selectList(new LambdaQueryWrapper<SalesLedger>() |
| | | .eq(SalesLedger::getCustomerId, customerId) |
| | | .ge(SalesLedger::getEntryDate, start) |
| | | .le(SalesLedger::getEntryDate, end)); |
| | | .le(SalesLedger::getEntryDate, end) |
| | | .ne(SalesLedger::getReviewStatus, 2)); |
| | | |
| | | if (groupByMonth) { |
| | | for (int i = 0; i < 3; i++) { |
| | |
| | | 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; |
| | |
| | | |
| | | return productProcessMapper.calculateProductionStatistics(startDateTime, endDateTime, userId, processIds); |
| | | } |
| | | } |
| | | } |