Summary
ConflictDetectionMixin._get_group_member_ids (spp_change_request_v2/models/conflict_mixin.py, lines 282/289/292 on 19.0 @ 0341801) traverses spp.group.membership records via individual_id and group_id:
registrant.group_membership_ids.filtered(lambda m: not m.ended_date).mapped("individual_id.id") # L282
group = membership.group_id # L289
group.group_membership_ids.filtered(lambda m: not m.ended_date).mapped("individual_id.id") # L292
But spp.group.membership names these many2ones individual and group (spp_registry/models/group_membership.py:16,22) — the _id suffix convention was not followed by this model. No module adds alias fields (the only other inheritor is spp_registry_group_hierarchy), confirmed against a live DB with spp_change_request_v2 installed.
Impact
Any change request whose type has an active conflict rule with scope = "group":
- Group registrant: crashes unconditionally with
KeyError: 'individual_id' — even for a group with zero members, since mapped() resolves the field name via records._fields[name] before iterating (odoo/orm/models.py __getitem__).
- Individual registrant: crashes with the first non-ended membership (
membership.group_id → AttributeError), i.e. exactly when the group-scope rule is supposed to do its job. An individual with no memberships happens to work, which is why the existing test passes.
Group-scope conflict rules are therefore unusable: enabling one makes CR creation/conflict detection raise for every registrant that actually belongs to a group.
Why tests don't catch it
test_conflict_detection_extended.py::test_group_scope_same_household_members calls _get_group_member_ids directly on an individual with zero memberships, so the loop body and both mapped() calls never execute. (The test's own comment notes membership creation was left "implementation-dependent".)
Fix
Rename the three accesses to the actual field names (individual, group) and extend the test to cover a group registrant with members and an individual with a membership.
Found while reviewing #418 (out of scope there — pre-existing on 19.0).
Summary
ConflictDetectionMixin._get_group_member_ids(spp_change_request_v2/models/conflict_mixin.py, lines 282/289/292 on19.0@ 0341801) traversesspp.group.membershiprecords viaindividual_idandgroup_id:But
spp.group.membershipnames these many2onesindividualandgroup(spp_registry/models/group_membership.py:16,22) — the_idsuffix convention was not followed by this model. No module adds alias fields (the only other inheritor isspp_registry_group_hierarchy), confirmed against a live DB withspp_change_request_v2installed.Impact
Any change request whose type has an active conflict rule with
scope = "group":KeyError: 'individual_id'— even for a group with zero members, sincemapped()resolves the field name viarecords._fields[name]before iterating (odoo/orm/models.py__getitem__).membership.group_id→AttributeError), i.e. exactly when the group-scope rule is supposed to do its job. An individual with no memberships happens to work, which is why the existing test passes.Group-scope conflict rules are therefore unusable: enabling one makes CR creation/conflict detection raise for every registrant that actually belongs to a group.
Why tests don't catch it
test_conflict_detection_extended.py::test_group_scope_same_household_memberscalls_get_group_member_idsdirectly on an individual with zero memberships, so the loop body and bothmapped()calls never execute. (The test's own comment notes membership creation was left "implementation-dependent".)Fix
Rename the three accesses to the actual field names (
individual,group) and extend the test to cover a group registrant with members and an individual with a membership.Found while reviewing #418 (out of scope there — pre-existing on
19.0).