Closes the last blocked test in the suite. Owner ruled both halves of the open question yes on 2026-07-30. `cog_revenue()` gains `revenue_concept`, mirroring `expenditure_concept`, with Census's two published concepts defined as crosswalk `revenue_subtype` sets rather than item-code prefixes: general = own_source + federal + state + local_aid (the default) total = general + utility + liquor_store + insurance_trust The manual defines the first by subtracting the other three from the second (4.3), so both are computable only once all four families are named -- which cog_pipeline#79 does. Insurance trust now includes the employee-retirement X codes (X01/X02/X05/X08) alongside the Y codes. - inst/sql: revenue_long / revenue_long_harmonized carry EVERY revenue subtype; the concept narrows in R via the existing subtype_scope machinery, exactly as expenditure_concept narrows spending_long. - cog_explain() now prints each verb's OWN concept. It previously printed `expenditure_concept` unconditionally, so a cog_revenue() caller was told "Concept: primary" -- a spending concept their result has nothing to do with. - Fixture regenerated at pipeline_commit aadb46b (330 crosswalk rows). Corrected two stale expectations in the blocked test while un-skipping it. It asserted X01+X04+X05+X08 and omitted X02, which applies to state governments and is nonzero for Wisconsin; X04 is an exhibit code for an INTRAgovernmental transfer that Census's own "Total Emp Ret Rev" excludes. Verified against that Census field: the right set is X01+X02+X05+X08 = $2,283,883k, exactly. And its expected `total` of $33,377,093k predated the Y codes being classified -- complete Total Revenue for WI FY2012 is $34,881,961k (general 31,338,293 + Y 1,259,785 + X 2,283,883). Behaviour change worth knowing: `general` is now STRICT Census General Revenue, so utility and liquor store revenue leave the default. Measured on the fixture that is 15.9% of what cog_revenue() returned for cities, vs 1.2% for states and 1.7% for counties. Suite: 716 pass / 0 fail / 0 skip -- the first time this package has had no skipped tests. Closes #12
147 lines
5.0 KiB
R
147 lines
5.0 KiB
R
# R/provenance.R
|
|
# Shared provenance construction. Matches inst/schemas/provenance-v1.json.
|
|
|
|
#' @noRd
|
|
.build_provenance <- function(verb, call, govid, years, category,
|
|
per_capita, adjust_to_year, result, sql,
|
|
subtype_col, basis = NA_character_,
|
|
basis_note = NA_character_,
|
|
expenditure_concept = "primary",
|
|
expenditure_concept_note = NA_character_,
|
|
expenditure_concept_direct_suppressed = FALSE,
|
|
revenue_concept = "general",
|
|
harmonization = NULL, recipe = NULL,
|
|
suggestions = list(),
|
|
completion = NULL) {
|
|
manifest <- .uscogdata_env$manifest
|
|
|
|
codes <- result[["codes_included"]]
|
|
codes_observed <- if (length(codes) == 0L) {
|
|
character(0)
|
|
} else {
|
|
sorted <- sort(unique(unlist(strsplit(codes, ",", fixed = TRUE))))
|
|
sorted[nzchar(sorted)]
|
|
}
|
|
|
|
agg_flag <- result[["aggregate_fallback"]]
|
|
agg_applied <- isTRUE(any(agg_flag, na.rm = TRUE))
|
|
agg_years <- if (agg_applied) {
|
|
unique(as.integer(result$year[which(agg_flag)]))
|
|
} else {
|
|
integer(0)
|
|
}
|
|
|
|
gov_names <- if (nrow(result) == 0L) {
|
|
character(0)
|
|
} else {
|
|
unique(result$gov_name)
|
|
}
|
|
|
|
schema_version <- suppressWarnings(as.integer(manifest$schema_version %||% 0L))
|
|
con <- .uscogdata_env$con
|
|
have_con <- !is.null(con) && DBI::dbIsValid(con)
|
|
break_refs <- if (have_con) {
|
|
.build_series_break_refs(con, codes_observed, years, schema_version)
|
|
} else {
|
|
character(0)
|
|
}
|
|
# Corpus-wide caveats travel separately: they qualify the whole result
|
|
# rather than one series, and they do not depend on codes_observed (see
|
|
# .build_corpus_break_refs()).
|
|
corpus_refs <- if (have_con) {
|
|
.build_corpus_break_refs(con, years, schema_version)
|
|
} else {
|
|
character(0)
|
|
}
|
|
|
|
list(
|
|
verb = verb,
|
|
call = paste(deparse(call), collapse = " "),
|
|
target = list(
|
|
canonical_govid = as.character(govid),
|
|
gov_name = gov_names
|
|
),
|
|
years = as.integer(years),
|
|
category = category,
|
|
basis = basis,
|
|
basis_note = basis_note,
|
|
expenditure_concept = expenditure_concept,
|
|
expenditure_concept_note = expenditure_concept_note,
|
|
expenditure_concept_direct_suppressed = isTRUE(expenditure_concept_direct_suppressed),
|
|
revenue_concept = revenue_concept,
|
|
harmonization = harmonization %||% list(
|
|
applied = FALSE, na_rows_excluded = 0L, na_amount_excluded = 0,
|
|
note = NA_character_
|
|
),
|
|
recipe = recipe,
|
|
suggestions = suggestions,
|
|
scope = list(
|
|
gov_types_included = as.integer(unlist(manifest$scope$gov_types_included)),
|
|
gov_types_excluded = as.integer(unlist(manifest$scope$gov_types_excluded)),
|
|
scope_note = manifest$scope$scope_note %||% ""
|
|
),
|
|
codes_summed = list(
|
|
observed = codes_observed,
|
|
subtype_column = subtype_col
|
|
),
|
|
aggregate_fallback = list(
|
|
applied = agg_applied,
|
|
years = agg_years
|
|
),
|
|
transformations = list(
|
|
units_conversion = list(
|
|
applied = TRUE,
|
|
source_unit = "$1,000s (raw Census)",
|
|
target_unit = "$USD",
|
|
multiplier = 1000L
|
|
),
|
|
per_capita = list(
|
|
applied = isTRUE(per_capita),
|
|
denominator_source = if (isTRUE(per_capita)) {
|
|
"Census F-33 population (per-year, from long.population)"
|
|
} else {
|
|
NA_character_
|
|
},
|
|
popyear_range = if (isTRUE(per_capita)) {
|
|
attr(result, ".popyear_range") %||% integer(0)
|
|
} else {
|
|
integer(0)
|
|
},
|
|
pop_source_counts = if (isTRUE(per_capita)) {
|
|
ps <- result[["pop_source"]]
|
|
if (is.null(ps) || length(ps) == 0L) {
|
|
list(census_f33 = 0L, unavailable = 0L)
|
|
} else {
|
|
list(
|
|
census_f33 = sum(ps == "census_f33", na.rm = TRUE),
|
|
unavailable = sum(ps == "unavailable", na.rm = TRUE)
|
|
)
|
|
}
|
|
} else {
|
|
NULL
|
|
}
|
|
),
|
|
inflation = list(
|
|
applied = !is.null(adjust_to_year),
|
|
base_year = if (is.null(adjust_to_year)) NA_integer_ else as.integer(adjust_to_year),
|
|
index = if (is.null(adjust_to_year)) NA_character_ else "CPI-U (BLS CPIAUCSL annual average, bundled)"
|
|
)
|
|
),
|
|
series_break_refs = break_refs,
|
|
corpus_break_refs = corpus_refs,
|
|
# What `complete = TRUE` filled, and the rule it filled by. Always
|
|
# present so a consumer can read `completion$applied` without testing
|
|
# for the key -- an absent block and applied = FALSE would otherwise be
|
|
# indistinguishable from an older reader version.
|
|
completion = completion %||% list(
|
|
applied = FALSE, rows_filled = 0L, absence_means = list()
|
|
),
|
|
manifest = list(
|
|
schema_version = as.integer(manifest$schema_version),
|
|
pipeline_commit = manifest$pipeline_commit %||% NA_character_,
|
|
built_at = manifest$built_at %||% NA_character_
|
|
),
|
|
sql_query = sql
|
|
)
|
|
}
|