From 2ebac456f7790ffc27ec651088696c1d276fe5d7 Mon Sep 17 00:00:00 2001 From: Anthony Volk <14987227+anth-volk@users.noreply.github.com> Date: Tue, 20 Oct 2026 20:51:20 +0400 Subject: [PATCH] Include each variable's quantity type in the country metadata (#3986) GET /{country_id}/metadata now describes each variable's quantity type as quantityType: "stock" for a balance or value at one point in time, "flow" for an amount over a period. The value is core's Variable.quantity_type, which a model sets or core defaults. The app's household builder needs it to leave the "Annually" label off money stocks such as rental property value. Co-Authored-By: Claude Opus 5.5 --- .../metadata-variable-quantity-type.added.md | 1 + policyengine_api/country.py | 3 ++ tests/unit/test_country.py | 33 +++++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 changelog.d/metadata-variable-quantity-type.added.md diff --git a/changelog.d/metadata-variable-quantity-type.added.md b/changelog.d/metadata-variable-quantity-type.added.md new file mode 100644 index 000000000..21def9340 --- /dev/null +++ b/changelog.d/metadata-variable-quantity-type.added.md @@ -0,0 +1 @@ +Include each variable's quantity type ("stock" or "flow") in the `/{country_id}/metadata` variable descriptions as `quantityType`. diff --git a/policyengine_api/country.py b/policyengine_api/country.py index da57c41a9..268c4b155 100644 --- a/policyengine_api/country.py +++ b/policyengine_api/country.py @@ -350,6 +350,9 @@ def build_variables(self) -> dict: "entity": variable.entity.key, "valueType": variable.value_type.__name__, "definitionPeriod": variable.definition_period, + # "stock" for a balance or value at one point in time, "flow" + # for an amount over a period. + "quantityType": variable.quantity_type, "name": variable_name, "label": variable.label, "category": variable.category, diff --git a/tests/unit/test_country.py b/tests/unit/test_country.py index ea2c753fe..301c7ced1 100644 --- a/tests/unit/test_country.py +++ b/tests/unit/test_country.py @@ -195,6 +195,39 @@ def get_population(self, entity_plural): ) +class TestVariableQuantityType: + """Each variable's metadata says whether it is a stock or a flow.""" + + @pytest.mark.parametrize( + ("country_id", "variable_name", "quantity_type"), + [ + # Money over a period: core's default for a float variable. + ("us", "employment_income", "flow"), + ("uk", "employment_income", "flow"), + # A value at one point in time, declared in the model. + ("us", "household_vehicles_value", "stock"), + ("uk", "mortgage_debt", "stock"), + # Core's default for a yes-or-no variable. + ("us", "is_blind", "stock"), + ], + ) + def test__variable_metadata_includes_the_models_quantity_type( + self, country_id, variable_name, quantity_type + ): + variable_metadata = COUNTRIES[country_id].metadata["variables"][variable_name] + + assert variable_metadata["quantityType"] == quantity_type + + def test__every_variable_has_a_stock_or_flow_quantity_type(self): + for country_id, country in COUNTRIES.items(): + quantity_types = { + variable_metadata["quantityType"] + for variable_metadata in country.metadata["variables"].values() + } + + assert quantity_types <= {"stock", "flow"}, country_id + + class TestUKCountryMetadata: """Tests for UK country metadata, specifically local authority loading."""