Skip to content
Draft
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
35 changes: 27 additions & 8 deletions dashboard/framework/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,16 +168,35 @@ def save(self, *args, **kwargs):
ProjectObjectiveCondition,
) # avoids circular import

super().save(*args, **kwargs)
# Check if the objective is being changed for an existing condition
old_objective_id = None
if self.pk:
try:
old_objective_id = Condition.objects.values_list(
"objective_id", flat=True
).get(pk=self.pk)
except Condition.DoesNotExist:
pass

projectobjectives = ProjectObjective.objects.filter(objective=self.objective)
super().save(*args, **kwargs)

for projectobjective in projectobjectives:
ProjectObjectiveCondition.objects.get_or_create(
project=projectobjective.project,
objective=projectobjective.objective,
condition=self,
)
if old_objective_id is not None and old_objective_id != self.objective_id:
# Condition moved to a new objective: update existing POCs to the new
# objective instead of creating new ones, so that status is preserved
ProjectObjectiveCondition.objects.filter(
condition=self, objective_id=old_objective_id
).update(objective=self.objective)
else:
# New condition or objective unchanged: propagate to all existing
# ProjectObjectives
projectobjectives = ProjectObjective.objects.filter(objective=self.objective)

for projectobjective in projectobjectives:
ProjectObjectiveCondition.objects.get_or_create(
project=projectobjective.project,
objective=projectobjective.objective,
condition=self,
)

class Meta:
ordering = ["objective__name", "level__value"]
41 changes: 41 additions & 0 deletions dashboard/framework/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,44 @@ def test_new_objective_means_new_commitments(

assert project.commitment_set.count() == 2
assert work_cycle.commitment_set.count() == 2


@pytest.mark.django_db
def test_moving_condition_updates_poc_not_creates_duplicate(
project, objective, objective_group, level
):
"""Moving a condition to a different objective should update the existing POC,
preserving the status, rather than creating a duplicate POC."""

objective_b = Objective.objects.create(
name="test_objective_b", group=objective_group, weight=1
)

condition = Condition.objects.create(
name="test_condition", level=level, objective=objective
)

# Set the POC's status to "DO" before moving
poc = ProjectObjectiveCondition.objects.get(
project=project, objective=objective, condition=condition
)
poc.status = "DO"
poc.save()

# Move the condition to objective_b
condition.objective = objective_b
condition.save()

# There should be exactly one POC for this condition across all projects
all_pocs = ProjectObjectiveCondition.objects.filter(condition=condition)
assert all_pocs.count() == 1, (
f"Expected 1 POC but got {all_pocs.count()}. "
"Moving a condition should update the existing POC, not create a duplicate."
)

# The POC should point to objective_b
updated_poc = all_pocs.first()
assert updated_poc.objective == objective_b

# The POC should retain its completion status
assert updated_poc.status == "DO"