Skip to content

[Econ] Port bedding cost preprocessing to a special-case handler - #3219

Open
matthew7838 wants to merge 2 commits into
refactor_preprocessfrom
bedding-mapping-refactor
Open

[Econ] Port bedding cost preprocessing to a special-case handler#3219
matthew7838 wants to merge 2 commits into
refactor_preprocessfrom
bedding-mapping-refactor

Conversation

@matthew7838

Copy link
Copy Markdown
Collaborator

Context

Issue(s) closed by this pull request: closes #3088
Ports the implementation from #3117 (bedding-mapping) onto the refactor_preprocess special-case architecture; #3117 remains the reference for the review history.

What

Implements the Bedding requirements line item as a special-case handler (RUFAS/EEE/economics/special_cases/bedding_requirements.py, registered as BeddingRequirementsHandler) on top of the preprocessing refactor, replacing the dedicated_processor dispatch used on the bedding-mapping branch. Also fixes the base branch's dangling SeedCostHandler import (special_cases/seed_costs.py does not exist on refactor_preprocess, so the package did not import).

Why

The generic pipeline computed bedding cost as one blended average head count times one blended price, and the pen bedding_name (a user config name such as calf_straw) never matched the price-file keys (straw), so every pen fell back to a $1/head placeholder. On the example freestall farm this produced ~$42.50/yr instead of the correct value. The refactor branch introduces the special-case handler architecture, and this line item belongs there.

How

  • BeddingRequirementsHandler.process() resolves each pen bedding_name -> bedding_configs.bedding_type -> price file (matching pens by their id field, not list position), then bills (average head present that year) x (that year's dollar-per-head price) per calendar year, summed across pens and years.
  • Only pens whose animal combination is in the mapping's billable_pen_combinations (["LAC_COW"]) are billed - the SME-confirmed price basis is per lactating cow. Pens with bedding_type "none" incur no cost.
  • bedding_type_to_file_key in mapping.py is the complete registry of billable bedding types (identity entries deliberate); lookups are strict.
  • Missing price years fall back to the nearest available year with a warning (the bedding CSVs currently carry only a 2021 column); missing FIPS rows, unloadable price files, malformed bedding configs, and non-numeric output values all warn instead of failing silently.
  • biophysical_aggregate reports the billed quantity (head-years) so quantity x price_aggregate reconciles with the line-item total; headline results are also emitted as econ_bedding_total_cost, econ_bedding_billed_head_years, and econ_bedding_avg_price_per_head_year for lightweight report filters.
  • The handler reads its configuration from the Bedding requirements entry in ECONOMIC_MAP, keeping the mapping the single declarative registry.

Test plan

  • 27 tests pass in tests/test_EEE/test_economics_preprocessing.py (14 ported bedding tests covering per-pen pairing, name-to-type resolution, compound-type normalization, none-skip, leap/partial-year units, multi-year per-year pricing, out-of-order pen ids, missing price file, missing FIPS, quantity-x-price reconciliation, and the framework breakdown flow).
  • Full 7-year freestall example run end-to-end on this branch: bedding line item is 623.02 head-years x $53.22 = $33,156.91, an exact match with the bedding-mapping branch output; quantity x price reconciles to the cent.
  • Black-clean; mypy reports no issues in the new handler module.

Input Changes

  • input/data/EEE/economics_map.json - Bedding requirements block updated to mirror mapping.py (reference file, not loaded at runtime). No user-facing input schema change; animal.bedding_configs and animal.pen_information already exist.

Output Changes

  • BeddingRequirementsHandler.process.econ_bedding_total_cost: total bedding cost in dollars.
  • BeddingRequirementsHandler.process.econ_bedding_billed_head_years: billed quantity in head-years.
  • BeddingRequirementsHandler.process.econ_bedding_avg_price_per_head_year: average dollar-per-head-per-year price used.
  • The bedding line item within econ_preprocessed_economic_inputs / econ_economic_line_item_breakdown now reflects correct per-pen annual cost (values change materially vs the base branch).

Filter

{
    "name": "Bedding cost (issue #3088)",
    "filters": [
        "econ_bedding_total_cost$",
        "econ_bedding_billed_head_years$",
        "econ_bedding_avg_price_per_head_year$"
    ]
}

Moves the issue #3088 bedding implementation from the dedicated_processor
branch in EconomicPreprocessor onto the refactor_preprocess special-case
architecture as BeddingRequirementsHandler. Behavior is unchanged: per-pen
pairing of animal counts with each pen's own bedding price, name-to-type
resolution through animal.bedding_configs, annual dollar-per-head billing by
calendar year, LAC_COW-only billing per the SME-confirmed price basis, and
the emitted econ_bedding_* reporting scalars. Verified identical output on
the 7-year freestall example (623.02 head-years x $53.22 = $33,156.91).

Also replaces the dangling SeedCostHandler import (seed_costs.py does not
exist on the base branch) with the new handler registration.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant