Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions spp_farmer_registry_demo/models/farmer_demo_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -901,6 +901,12 @@ def _create_farm(
"farm_size_idle": farm_size_idle,
"experience_years": experience_years,
}
# OP#1120: farm groups default to the FARM group type (a farm stays a
# farm even when it becomes a member of a cooperative — only the
# cooperative container is typed COOPERATIVE, in _create_cooperatives).
farm_group_type_id = self._ensure_farm_group_type()
if farm_group_type_id:
farm_vals["group_type_id"] = farm_group_type_id
if phone:
farm_vals["phone"] = phone
farm = Partner.create(farm_vals)
Expand Down Expand Up @@ -1395,6 +1401,26 @@ def _ensure_cooperative_group_type(self):
_logger.warning("Could not create cooperative group type vocabulary code")
return False

def _ensure_farm_group_type(self):
"""Ensure the 'farm' group type vocabulary code exists (OP#1120).

Farm groups default to this type. Mirrors _ensure_cooperative_group_type
(ADR-016: local codes with is_local=True bypass system protection).

Returns:
int: vocabulary code ID for the farm group type, or False.
"""
try:
code = self.env["spp.vocabulary.code"].get_or_create_local(
"urn:openspp:vocab:group-type",
"farm",
display="Farm",
)
return code.id
except Exception:
_logger.warning("Could not create farm group type vocabulary code")
return False

# ──────────────────────────────────────────────────────────────────────
# GIS Data (Coordinates + Land Records)
# ──────────────────────────────────────────────────────────────────────
Expand Down
25 changes: 25 additions & 0 deletions spp_farmer_registry_demo/models/seeded_farm_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,7 @@ def __init__(self, env, locale="fil_PH", seed=42):
self._vocab_cache = {}
self._species_cache = {}
self._head_type_id = None
self._farm_group_type_id = None # OP#1120

# OP#1114: names already handed out this run, so the ~730 farms drawn
# from an 86-surname pool don't end up with duplicate farm names (and,
Expand Down Expand Up @@ -500,6 +501,10 @@ def generate_all_farms(self, blueprints):
"farm_size_idle": idle,
"experience_years": experience,
}
# OP#1120: seeded farm groups default to the FARM group type.
farm_group_type_id = self._ensure_farm_group_type()
if farm_group_type_id:
gvals["group_type_id"] = farm_group_type_id
if gps:
gvals["coordinates"] = json.dumps({"type": "Point", "coordinates": [gps[0], gps[1]]})
if area_id:
Expand Down Expand Up @@ -1151,6 +1156,26 @@ def _get_vocab_code(self, namespace_uri, code):
self._vocab_cache[cache_key] = vocab.id if vocab else False
return self._vocab_cache[cache_key]

def _ensure_farm_group_type(self):
"""Ensure and return the 'farm' group type vocabulary code ID (OP#1120).

Seeded farm groups default to this type. Created via get_or_create_local
so it exists even if the wizard hasn't already made it, and cached for
the run.
"""
if self._farm_group_type_id is None:
try:
code = self.env["spp.vocabulary.code"].get_or_create_local(
"urn:openspp:vocab:group-type",
"farm",
display="Farm",
)
self._farm_group_type_id = code.id
except Exception:
_logger.warning("Could not create farm group type vocabulary code")
self._farm_group_type_id = False
return self._farm_group_type_id

def _resolve_species(self, species_code):
"""Map a species code string to a vocabulary code ID."""
if species_code in self._species_cache:
Expand Down
20 changes: 20 additions & 0 deletions spp_farmer_registry_demo/tests/test_demo_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,8 @@ def test_create_story_farms_are_groups(self):
for farm in story_farms.values():
self.assertTrue(farm.is_group)
self.assertTrue(farm.is_registrant)
# OP#1120: story farm groups are typed FARM.
self.assertEqual(farm.group_type_id.code, "farm")

def test_create_story_farms_have_members(self):
"""Test story farms have farmer members."""
Expand Down Expand Up @@ -262,6 +264,24 @@ def test_create_farm_helper(self):
self.assertEqual(farm.name, "Test Farm")
self.assertTrue(farm.is_group)
self.assertEqual(farm.farm_total_size, 3.0)
# OP#1120: farm groups default to the FARM group type.
self.assertEqual(farm.group_type_id.code, "farm")

def test_1120_cooperative_container_typed_cooperative(self):
"""OP#1120: the cooperative container is typed COOPERATIVE, while its
member farms stay FARM (a farm is still a farm inside a cooperative)."""
wizard = self.Generator.create({"name": _unique("Coop Type Test")})
story_farms = wizard._create_story_farms()

cooperatives = wizard._create_cooperatives(story_farms)
self.assertTrue(cooperatives, "expected at least one cooperative")

for coop in cooperatives.values():
self.assertEqual(coop.group_type_id.code, "cooperative")
members = self.env["spp.group.membership"].search([("group", "=", coop.id)])
self.assertTrue(members, "cooperative should have member farms")
for membership in members:
self.assertEqual(membership.individual.group_type_id.code, "farm")

def test_maria_santos_profile(self):
"""Test Maria Santos persona - smallholder rice farmer."""
Expand Down
3 changes: 3 additions & 0 deletions spp_farmer_registry_demo/tests/test_seeded_farm_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -964,6 +964,9 @@ def test_generate_all_farms_mixed_farm_type(self):
self.assertTrue(farm.is_group)
self.assertTrue(farm.is_registrant)
self.assertEqual(len(result["members"]), 2)
# OP#1120: seeded farm groups are typed FARM.
self.assertTrue(farm.group_type_id, "farm group must have a group type")
self.assertEqual(farm.group_type_id.code, "farm")

# Verify farm details
details = farm.farm_details_id
Expand Down
Loading