CORE Pipeline Quality Report


Form: 990combined Tax year: 2012 Generated: 2026-05-15 11:03:14

✅ PASSED — Strict mode: FALSE

Executive Summary

Metric Value
Row count 510,116
Column count 151
Vintage-aware completeness 100.00%
Raw completeness (all cols / all rows) 40.67%
Unique EINs 508,576
Duplicate EINs (amendments) 1,540
Missing columns vs schema 0
Extra columns vs schema 91
YoY row-count delta vs prior run no_baseline

Identity-Field Checks

Code
ein  <- r$critical_field_issues$ein
tp   <- r$critical_field_issues$tax_period
sub  <- r$critical_field_issues$subsection
typ  <- r$critical_field_issues$types

ident <- data.table(
  Check = c("EIN format (XX-XXXXXXX)", "EIN null count", "EIN duplicates (soft)",
            "tax_period format (YYYYMM)", "tax_period out-of-range",
            "subsection_cd whitelist", "Column types"),
  Result = c(
    if (is.null(ein))  "✅ all valid" else sprintf("❌ %d malformed", ein$malformed),
    if (is.null(ein) && r$summary_stats$duplicate_eins >= 0) "✅ no nulls" else sprintf("❌ %d nulls", ein$null_count),
    sprintf("ℹ %d (soft, not a failure)", r$summary_stats$duplicate_eins),
    if (is.null(tp))   "✅ all valid"  else sprintf("❌ %d malformed", tp$malformed_count),
    if (is.null(tp))   "✅ all in range" else sprintf("❌ %d out of range", tp$out_of_range_count),
    if (is.null(sub))  "✅ all in IRM whitelist" else sprintf("❌ %d unknown codes", sub$unknown_count),
    if (is.null(typ))  "✅ all types correct" else sprintf("❌ %s", paste(typ$issues, collapse = "; "))
  )
)
kable(ident)
Check Result
EIN format (XX-XXXXXXX) ✅ all valid
EIN null count ✅ no nulls
EIN duplicates (soft) ℹ 1540 (soft, not a failure)
tax_period format (YYYYMM) ✅ all valid
tax_period out-of-range ✅ all in range
subsection_cd whitelist ✅ all in IRM whitelist
Column types ✅ all types correct

Subsection Code Distribution

(IRC 501(c) / 501(d) / 501(e) / 501(f) / 501(k) / 501(n) / 521 / 527 / 529 / 4947 / 1381 subsection codes per IRM 25.7.1. See data/lookups/subsection_codes.csv.)

Code
sd <- r$summary_stats$subsection_distribution
if (length(sd$top_values) == 0L) {
  cat("(no subsection data)")
} else {
  tab <- rbindlist(lapply(sd$top_values, as.data.table))
  setnames(tab, c("code", "count", "pct"))
  tab[, pct := paste0(pct, "%")]
  tab[, count := format(count, big.mark = ",")]
  kable(tab)
}
code count pct
3 373,395 73.2%
6 34,691 6.8%
4 26,522 5.2%
5 19,350 3.79%
7 18,631 3.65%
8 8,337 1.63%
19 7,820 1.53%
9 6,157 1.21%
12 3,646 0.71%
13 2,909 0.57%

Financial Summary

Code
fin <- r$summary_stats$financial
if (length(fin) == 0L) {
  cat("(no financial summary)")
} else {
  tab <- data.table(
    metric = c("total_revenue", "total_expenses", "total_assets_eoy"),
    sum = c(fmt_money(fin$revenue$total),  fmt_money(fin$expenses$total),  fmt_money(fin$assets$total)),
    median = c(fmt_money(fin$revenue$median), fmt_money(fin$expenses$median), fmt_money(fin$assets$median))
  )
  kable(tab)
}
metric sum median
total_revenue $2,110,442,026,162 $123,894
total_expenses
total_assets_eoy $4,319,028,448,747 $149,248

Tax Period Year Coverage

Code
d <- r$summary_stats$tax_period_year_distribution
if (length(d) == 0L) {
  cat("(no coverage data)")
} else {
  tab <- data.table(tax_year = names(d), n = as.integer(unlist(d)))
  setorder(tab, tax_year)
  tab[, pct := sprintf("%.2f%%", 100 * n / sum(n))]
  tab[, n := format(n, big.mark = ",")]
  kable(tab)
}
tax_year n pct
2012 510,116 100.00%

Field Completeness by Category

Columns are grouped by Form section parsed from the crosswalk’s location field.

Code
cats <- r$category_reports
if (length(cats) == 0L) {
  cat("(no category breakdown)")
} else {
  tab <- rbindlist(lapply(cats, function(c) data.table(
    category         = c$category_name,
    n_cols           = c$column_count,
    cols_present     = c$columns_present,
    avg_completeness = sprintf("%.2f%%", c$avg_completeness)
  )))
  setorder(tab, -n_cols)
  kable(tab)
}
category n_cols cols_present avg_completeness
sched_a 32 32 91.49%
part_viii 27 27 35.90%
part_x 15 15 22.12%
part_v 8 8 60.63%
part_ix 7 7 6.73%
part_iv 4 4 21.15%
header 3 3 100.00%
other 1 1 1.98%

Completeness by Vintage Cohort

When a single tax-year file blends rows from multiple extract_year × source_form cohorts, the per-cohort completeness reveals whether any vintage is dragging the overall metric down. A clean run produces 100% for every cohort.

Code
pc <- r$completeness_by_cohort
if (length(pc) == 0L) {
  cat("(single cohort)")
} else {
  tab <- rbindlist(lapply(pc, function(c) data.table(
    extract_year     = c$extract_year,
    source_form      = c$source_form,
    rows             = format(c$n_rows, big.mark = ","),
    expected_cols    = c$n_expected_cols,
    completeness_pct = sprintf("%.2f%%", c$completeness_pct)
  )))
  kable(tab)
}
extract_year source_form rows expected_cols completeness_pct
2012 990 40,768 35 100.00%
2012 990ez 37,829 35 100.00%
2013 990ez 158,433 58 100.00%
2013 990 229,004 58 100.00%
2014 990 15,617 58 100.00%
2016 990 511 59 100.00%
2017 990 199 59 100.00%
2014 990ez 18,282 58 100.00%
2015 990ez 4,215 59 100.00%
2017 990ez 677 59 100.00%
2024 990ez 53 59 96.61%
2016 990ez 1,715 59 100.00%
2015 990 1,495 59 100.00%
2021 990ez 114 59 99.05%
2019 990ez 264 59 99.17%
2023 990 16 59 98.94%
2020 990 22 59 99.38%
2018 990ez 432 59 100.00%
2019 990 50 59 99.29%
2021 990 26 59 99.61%
2023 990ez 81 59 99.27%
2022 990ez 78 59 99.13%
2018 990 142 59 100.00%
2024 990 13 59 99.22%
2020 990ez 62 59 97.35%
2022 990 16 59 97.25%

Data Issues

Code
issues <- character(0)
if (length(r$missing_columns)) issues <- c(issues, sprintf("Missing %d columns: %s",
  length(r$missing_columns), paste(head(r$missing_columns, 10), collapse = ", ")))
if (length(r$extra_columns)) issues <- c(issues, sprintf("Extra %d columns: %s",
  length(r$extra_columns), paste(head(r$extra_columns, 10), collapse = ", ")))
if (length(r$critical_field_issues)) {
  for (k in names(r$critical_field_issues)) {
    issues <- c(issues, sprintf("%s: %s", k, paste(unlist(r$critical_field_issues[[k]]), collapse = " | ")))
  }
}

if (length(issues) == 0L) {
  cat("✅ No hard-check issues detected.\n")
} else {
  for (i in issues) cat("- ", i, "\n", sep = "")
}
- Extra 91 columns: membership_dues_assessments_sec170, gross_sales_securities, cost_basis_securities, fundraising_events_direct_expenses, gross_profit_inventory_sales, gross_receipts_total, total_functional_expenses, compensation_current_officers, professional_fundraising_fees, total_assets_boy

Generated from /mnt/c/Users/tpoongundranar/Documents/Urban/NCCS/nccs-data-core/data/logs/merged/quality_990combined_2012.rds. See R/quality/post_checks.R for the validator implementation and docs/05-quality-gates.qmd for the gate definitions.