| | |
| | | .eq(InvestmentSystem::getReportPeriod, reportPeriod))) { |
| | | sysMap.computeIfAbsent(normInvestName(s.getProjectName()), k -> new ArrayList<>()).add(s); |
| | | } |
| | | // 同报表期投资系统基准整期缺失时,不做"项目缺失核实"(缺失=基准未导入,不等于项目不存在),避免整表误报 |
| | | boolean benchmarkMissing = sysMap.isEmpty(); |
| | | |
| | | // 幂等:只清除 INVEST 规则的旧审核结果 |
| | | List<Long> ruleIds = new ArrayList<>(); |
| | |
| | | String projectName = project == null ? "未知项目" : project.getProjectName(); |
| | | InvestmentSystem sys = findInvestSystem(sysMap, projectName); |
| | | for (AuditRule rule : rules) { |
| | | if (benchmarkMissing && "EXISTENCE_SYS".equals(rule.getCompareType())) continue; |
| | | AuditResult result = checkInvestRule(rule, monthly, projectName, sys); |
| | | if (result != null) { |
| | | result.setRuleName(rule.getRuleName()); |
| | |
| | | case "RULE_I001": |
| | | case "RULE_I002": |
| | | case "RULE_I003": |
| | | case "RULE_I004": |
| | | return investSystemMapper.selectCount(new LambdaQueryWrapper<InvestmentSystem>() |
| | | .eq(InvestmentSystem::getReportPeriod, period)) == 0; |
| | | default: |
| | |
| | | return null; |
| | | } |
| | | |
| | | /** 数值范围检查(如 整车吨位 4≤且≤40) */ |
| | | /** 数值范围检查;整车吨位按“平均吨位=整车吨位/整车数”口径判定 4~40 */ |
| | | private AuditResult checkOutRange(AuditRule rule, H2032EnterpriseMonthly report) { |
| | | String[] bounds = rule.getThreshold().split(","); |
| | | if (bounds.length < 2) return null; |
| | | double value = getH2032FieldValue(report, rule.getCheckField()); |
| | | String field = rule.getCheckField(); |
| | | String label = h2032FieldLabel(field); |
| | | double value; |
| | | if ("tonsWhole".equals(field)) { |
| | | double vehicles = report.getVehicleWhole() == null ? 0.0 : report.getVehicleWhole().doubleValue(); |
| | | double tons = nvl(report.getTonsWhole()); |
| | | if (vehicles > 0) { |
| | | value = tons / vehicles; |
| | | label = "整车平均吨位(整车吨位/整车数)"; |
| | | } else { |
| | | value = tons; // 无整车数但有吨位时仍按原吨位判定 |
| | | } |
| | | } else { |
| | | value = getH2032FieldValue(report, field); |
| | | } |
| | | double low = Double.parseDouble(bounds[0].trim()); |
| | | double high = Double.parseDouble(bounds[1].trim()); |
| | | if (value > 0 && (value < low || value > high)) { |
| | | return buildResult(rule, report, h2032FieldLabel(rule.getCheckField()) + "=" + fmt(value), |
| | | return buildResult(rule, report, label + "=" + fmt(value), |
| | | "范围 " + fmt(low) + "~" + fmt(high), "超出范围"); |
| | | } |
| | | return null; |
| | |
| | | } |
| | | |
| | | private String fmt(double v) { |
| | | if (v == Math.floor(v) && !Double.isInfinite(v)) { |
| | | if (v == Math.floor(v) && !Double.isInfinite(v) && Math.abs(v) < 1e15) { |
| | | return String.valueOf((long) v); |
| | | } |
| | | return String.valueOf(Math.round(v * 100.0) / 100.0); |
| | | return java.math.BigDecimal.valueOf(v).setScale(2, java.math.RoundingMode.HALF_UP) |
| | | .stripTrailingZeros().toPlainString(); |
| | | } |
| | | |
| | | /** 占比/小数值:保留 4 位小数 */ |
| | | private String fmt4(double v) { |
| | | if (v == Math.floor(v) && !Double.isInfinite(v)) { |
| | | if (v == Math.floor(v) && !Double.isInfinite(v) && Math.abs(v) < 1e15) { |
| | | return String.valueOf((long) v); |
| | | } |
| | | return String.valueOf(Math.round(v * 10000.0) / 10000.0); |
| | | return java.math.BigDecimal.valueOf(v).setScale(4, java.math.RoundingMode.HALF_UP) |
| | | .stripTrailingZeros().toPlainString(); |
| | | } |
| | | |
| | | // ========== H2031 旅客审核 ========== |
| | |
| | | result.setStatus("PENDING"); |
| | | return result; |
| | | } |
| | | } |
| | | } |