diff --git a/spp_farmer_registry_demo/README.rst b/spp_farmer_registry_demo/README.rst index 1d41a26df..dc909e81a 100644 --- a/spp_farmer_registry_demo/README.rst +++ b/spp_farmer_registry_demo/README.rst @@ -120,6 +120,14 @@ Dependencies Changelog ========= +19.0.2.1.4 +~~~~~~~~~~ + +- feat(farmer_demo): seed EC1, a 50 ha commercial farm carrying idle + land. Story 9 needs a farm that has the positive Climate Resilience + signal (idle land) but is still rejected for not being a smallholder, + so the targeting rule can be demonstrated turning one down (#1119) + 19.0.2.1.2 ~~~~~~~~~~ diff --git a/spp_farmer_registry_demo/__manifest__.py b/spp_farmer_registry_demo/__manifest__.py index f92f36d6c..1052b881a 100644 --- a/spp_farmer_registry_demo/__manifest__.py +++ b/spp_farmer_registry_demo/__manifest__.py @@ -3,7 +3,7 @@ "name": "OpenSPP Farmer Registry Demo", "summary": "Demo generator for Farmer Registry with fixed stories and volume generation", "category": "OpenSPP", - "version": "19.0.2.1.2", + "version": "19.0.2.1.4", "sequence": 1, "author": "OpenSPP.org", "website": "https://github.com/OpenSPP/OpenSPP2", diff --git a/spp_farmer_registry_demo/docs/USE_CASES.md b/spp_farmer_registry_demo/docs/USE_CASES.md index 111174f72..5f3ae3fef 100644 --- a/spp_farmer_registry_demo/docs/USE_CASES.md +++ b/spp_farmer_registry_demo/docs/USE_CASES.md @@ -965,8 +965,9 @@ across 21 deterministic blueprints. Counts and shapes are seed-stable (`seed=42` | Flood-affected female farmer | 25 | rural | crop | 1.0–2.5 | 5–18 | F | 2 | | Young farmer (< 3 years' experience) | 40 | rural | crop | 0.5–2.0 | 0–3 | any | 1 | | Elderly farmer (20+ years' experience) | 30 | rural | crop | 1.0–3.0 | 20–40 | M | 2 | +| EC1 — Large commercial, idle land | 1 | rural | crop | 50.0 | 20–30 | M | 2 | -**Total blueprints:** 21. **Total farms:** ~730. **Estimated members:** ~1,500. +**Total blueprints:** 22. **Total farms:** ~731. **Estimated members:** ~1,500. --- diff --git a/spp_farmer_registry_demo/models/farmer_blueprints.py b/spp_farmer_registry_demo/models/farmer_blueprints.py index fa43a84b9..02ce93dab 100644 --- a/spp_farmer_registry_demo/models/farmer_blueprints.py +++ b/spp_farmer_registry_demo/models/farmer_blueprints.py @@ -619,6 +619,43 @@ _AQUACULTURE: False, }, }, + # ========================================================================= + # Edge Cases — Targeting Exclusion (1 blueprint, 1 farm) + # OP#1119: EC1 — a large commercial farm (50 ha, well above the 5 ha + # smallholder threshold) that ALSO has idle/fallow land. Scenario 5 + # (Climate Resilience) needs this so the CEL + # `r.is_group == true and is_smallholder and farm_size_idle > 0` can be + # shown rejecting it on is_smallholder even though farm_size_idle > 0. + # All eligibility is False — it is the deliberate rejection example. + # ========================================================================= + { + "id": "bp_22_ec1_large_commercial_idle", + "label": "EC1 — Large commercial farm, 50ha with idle land (targeting exclusion)", + "count": 1, + "zone": "rural", + "farm_type": "crop", + "size_range": (50.0, 50.0), + "idle_pct": 0.1, # 5 ha fallow/idle — the positive Climate signal it can't use (not a smallholder) + "experience_range": (20, 30), + "head_gender": "male", + "members": [ + {"role": "head", "gender": "male", "age_range": (45, 60)}, + {"role": "spouse", "gender": "female", "age_range": (42, 58)}, + ], + "activities": [ + {"type": "crop", "species_code": "rice_irrigated", "area_pct": 0.5}, + {"type": "crop", "species_code": "maize", "area_pct": 0.3}, + ], + "land_tenure": "self", + "land_use": "cultivation", + "eligibility": { + _INPUT_SUBSIDY: False, + _EQUIPMENT_GRANT: False, + _LIVESTOCK: False, + _CLIMATE: False, + _AQUACULTURE: False, + }, + }, ] diff --git a/spp_farmer_registry_demo/readme/HISTORY.md b/spp_farmer_registry_demo/readme/HISTORY.md index 34d7fb547..00a7ebdf0 100644 --- a/spp_farmer_registry_demo/readme/HISTORY.md +++ b/spp_farmer_registry_demo/readme/HISTORY.md @@ -1,3 +1,7 @@ +### 19.0.2.1.4 + +- feat(farmer_demo): seed EC1, a 50 ha commercial farm carrying idle land. Story 9 needs a farm that has the positive Climate Resilience signal (idle land) but is still rejected for not being a smallholder, so the targeting rule can be demonstrated turning one down (#1119) + ### 19.0.2.1.2 - fix(demo): put the Input Subsidy Program on **manual** entitlement approval (`auto_approve_entitlements=False`) so a demo user can walk the full cycle → entitlement approval chain, not just cycle approval. The flag is now per-program (every other demo program stays auto-approve), and historically seeded cycles are unaffected because the generator force-approves their pending entitlements (#1122) diff --git a/spp_farmer_registry_demo/static/description/index.html b/spp_farmer_registry_demo/static/description/index.html index fe080f1fe..1cc52dc6f 100644 --- a/spp_farmer_registry_demo/static/description/index.html +++ b/spp_farmer_registry_demo/static/description/index.html @@ -488,6 +488,15 @@

Changelog

+

19.0.2.1.4

+ +
+

19.0.2.1.2

-
+

19.0.2.1.1

-
+

19.0.2.1.0

  • feat(demo): add GIS + irrigation scenario (FM4) with reservoir + canal @@ -532,7 +541,7 @@

    19.0.2.1.0

    tables and the CR overview
-
+

19.0.2.0.0

  • Initial migration to OpenSPP2
  • diff --git a/spp_farmer_registry_demo/tests/test_seeded_farm_generator.py b/spp_farmer_registry_demo/tests/test_seeded_farm_generator.py index a965a2b1b..5b5b2960c 100644 --- a/spp_farmer_registry_demo/tests/test_seeded_farm_generator.py +++ b/spp_farmer_registry_demo/tests/test_seeded_farm_generator.py @@ -1036,6 +1036,26 @@ def test_generate_all_farms_idle_land(self): self.assertAlmostEqual(details.farm_size_idle, 1.0, places=1) self.assertAlmostEqual(details.farm_size_under_crops, 3.0, places=1) + def test_1119_ec1_large_commercial_not_smallholder_with_idle(self): + """OP#1119: the EC1 blueprint seeds a large commercial farm that is NOT + a smallholder yet has idle land > 0 — the contrast case for Scenario 5, + where the Climate Resilience CEL (is_smallholder AND farm_size_idle > 0) + rejects it on is_smallholder despite the idle land.""" + from odoo.addons.spp_farmer_registry_demo.models.farmer_blueprints import ( + FARMER_BLUEPRINTS, + ) + + ec1 = next((bp for bp in FARMER_BLUEPRINTS if bp["id"] == "bp_22_ec1_large_commercial_idle"), None) + self.assertIsNotNone(ec1, "EC1 large-commercial blueprint must exist") + + gen = self._make_generator() + farm = gen.generate_all_farms([ec1])[0]["group"] + + threshold = float(self.env["ir.config_parameter"].sudo().get_param("spp.farmer.smallholder_threshold", "5.0")) + self.assertGreater(farm.farm_total_size, threshold, "EC1 must be above the smallholder threshold") + self.assertFalse(farm.is_smallholder, "EC1 must not be a smallholder") + self.assertGreater(farm.farm_size_idle, 0.0, "EC1 must have idle/fallow land > 0") + def test_generate_all_farms_assigns_areas(self): """Farms should be assigned to demo areas if any exist.""" gen = self._make_generator()