cost: don't leave copied cost items in the copied schedule (#8851)

copy_cost_item appends the copy to the inverse relationships of the
original cost item, which for a root cost item includes the source
schedule's IfcRelAssignsToControl. copy_cost_schedule then assigned that
same cost item to the new schedule as well, so the copies showed up in
both schedules and deleting them from one removed them from the other.

Unassign the copy from the source schedule before assigning it to the
new one.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
carlopav
2026-07-23 14:57:58 +02:00
committed by Massimo Fabbro
parent 98a25eca96
commit 305f8c6003
2 changed files with 4 additions and 0 deletions
@@ -45,5 +45,6 @@ def copy_cost_schedule(
if isinstance(duplicated_cost_item, list):
# All other nested items are not connected to the cost schedule explicitly.
duplicated_cost_item = duplicated_cost_item[0]
ifcopenshell.api.control.unassign_control(file, cost_schedule, [duplicated_cost_item])
ifcopenshell.api.control.assign_control(file, new_schedule, [duplicated_cost_item])
return new_schedule
@@ -40,6 +40,9 @@ class TestCopyCostSchedule(test.bootstrap.IFC4):
assert len(new_cost_items) == 2
assert len(new_cost_items.intersection(old_cost_items)) == 0
# The copies should be removed from the original schedule.
assert set(ifcopenshell.util.cost.get_schedule_cost_items(schedule)) == old_cost_items
class TestCopyCostScheduleIFC2X3(test.bootstrap.IFC2X3, TestCopyCostSchedule):
pass