Skip to content

Commit dcafa51

Browse files
Merge pull request #208 from OpenSPP/fix/assign-program-cross-registrant-conflict
fix(spp_cr_type_assign_program): scope duplicate-assignment conflict to (registrant, program)
2 parents bc0cfe5 + a8edf53 commit dcafa51

3 files changed

Lines changed: 32 additions & 6 deletions

File tree

spp_cr_type_assign_program/__manifest__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "OpenSPP CR Type - Assign to Program",
3-
"version": "19.0.1.0.0",
3+
"version": "19.0.1.0.1",
44
"sequence": 53,
55
"category": "OpenSPP",
66
"summary": "Change request type for assigning a registrant to a program",

spp_cr_type_assign_program/models/change_request.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@
44
class SPPChangeRequest(models.Model):
55
"""Custom conflict-detection hook for the assign-program CR type.
66
7-
The base conflict rule scoped to the same registrant flags every in-flight
8-
`assign_program` CR for that registrant. We narrow the match to those
9-
targeting the same `(registrant, program)` pair so two CRs assigning the
10-
same registrant to *different* programs are allowed to proceed.
7+
The rule uses `scope='custom'`, so the base domain does not pre-filter by
8+
registrant. We narrow the candidate set to those targeting the same
9+
`(registrant, program)` pair: two CRs assigning the same registrant to
10+
*different* programs may proceed, and two CRs assigning *different*
11+
registrants to the same program may also proceed.
1112
"""
1213

1314
_inherit = "spp.change.request"
@@ -44,4 +45,6 @@ def _check_custom_conflicts(self, candidates, rule):
4445
)
4546
.ids
4647
)
47-
return candidates.filtered(lambda c: c.detail_res_id in matching_detail_ids)
48+
return candidates.filtered(
49+
lambda c: c.detail_res_id in matching_detail_ids and c.registrant_id == self.registrant_id
50+
)

spp_cr_type_assign_program/tests/test_assign_program.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,29 @@ def test_f3_two_crs_for_same_registrant_different_programs_allowed(self):
253253
self.assertEqual(cr2.conflict_status, "none")
254254
self.assertFalse(cr2.conflicting_cr_ids)
255255

256+
def test_f5_two_crs_for_different_registrants_same_program_allowed(self):
257+
# Two different registrants assigning to the *same* program must both
258+
# be able to proceed. The rule's intent is "same (registrant, program)
259+
# pair" — different registrants are not in conflict even when the
260+
# program matches.
261+
other_individual = self.Partner.create(
262+
{
263+
"name": "Other Individual",
264+
"given_name": "Other",
265+
"family_name": "Individual",
266+
"is_registrant": True,
267+
"is_group": False,
268+
}
269+
)
270+
271+
_cr1, _d1 = self._make_cr(self.test_individual, self.indiv_program_active)
272+
cr2, _d2 = self._make_cr(other_individual, self.indiv_program_active)
273+
274+
cr2._run_conflict_checks()
275+
276+
self.assertEqual(cr2.conflict_status, "none")
277+
self.assertFalse(cr2.conflicting_cr_ids)
278+
256279
def test_a10_apply_translates_unique_violation_to_user_error(self):
257280
"""Race-path: a concurrent transaction inserts the same
258281
(registrant, program) pair between our validate() and create().

0 commit comments

Comments
 (0)