diff --git a/src/blenderbim/blenderbim/bim/handler.py b/src/blenderbim/blenderbim/bim/handler.py index 7fa721521d..3aaf842117 100644 --- a/src/blenderbim/blenderbim/bim/handler.py +++ b/src/blenderbim/blenderbim/bim/handler.py @@ -20,6 +20,8 @@ import bpy import json import addon_utils import ifcopenshell.api.owner.settings +import blenderbim.tool as tool +import blenderbim.core.owner as core_owner from blenderbim.bim.module.drawing.prop import RasterStyleProperty from bpy.app.handlers import persistent from blenderbim.bim.ifc import IfcStore @@ -228,16 +230,7 @@ def setDefaultProperties(scene): bpy.msgbus.subscribe_rna( key=active_object_key, owner=global_subscription_owner, args=(), notify=active_object_callback ) - ifcopenshell.api.owner.settings.get_person = ( - lambda ifc: ifc.by_id(int(bpy.context.scene.BIMOwnerProperties.user_person)) - if get_user_person(None, None) and bpy.context.scene.BIMOwnerProperties.user_person - else None - ) - ifcopenshell.api.owner.settings.get_organisation = ( - lambda ifc: ifc.by_id(int(bpy.context.scene.BIMOwnerProperties.user_organisation)) - if get_user_organisation(None, None) and bpy.context.scene.BIMOwnerProperties.user_organisation - else None - ) + ifcopenshell.api.owner.settings.get_user = lambda ifc: core_owner.get_user(tool.Owner) ifcopenshell.api.owner.settings.get_application = get_application if len(bpy.context.scene.DocProperties.drawing_styles) == 0: drawing_style = bpy.context.scene.DocProperties.drawing_styles.add() diff --git a/src/blenderbim/blenderbim/bim/module/owner/__init__.py b/src/blenderbim/blenderbim/bim/module/owner/__init__.py index aff8435c80..94effc9326 100644 --- a/src/blenderbim/blenderbim/bim/module/owner/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/owner/__init__.py @@ -24,6 +24,7 @@ classes = ( operator.AddAddressAttribute, operator.AddOrganisation, operator.AddPerson, + operator.AddPersonAndOrganisation, operator.AddPersonAttribute, operator.AddRole, operator.DisableEditingAddress, @@ -42,8 +43,10 @@ classes = ( operator.RemoveAddressAttribute, operator.RemoveOrganisation, operator.RemovePerson, + operator.RemovePersonAndOrganisation, operator.RemovePersonAttribute, operator.RemoveRole, + operator.SetUser, prop.BIMOwnerProperties, ui.BIM_PT_people, ui.BIM_PT_organisations, diff --git a/src/blenderbim/blenderbim/bim/module/owner/data.py b/src/blenderbim/blenderbim/bim/module/owner/data.py index 5719716da0..c74762c856 100644 --- a/src/blenderbim/blenderbim/bim/module/owner/data.py +++ b/src/blenderbim/blenderbim/bim/module/owner/data.py @@ -164,7 +164,12 @@ class OwnerData: @classmethod def load(cls): - cls.data = {"user_person": cls.get_user_person(), "user_organisation": cls.get_user_organisation()} + cls.data = { + "user_person": cls.get_user_person(), + "user_organisation": cls.get_user_organisation(), + "can_add_user": cls.can_add_user(), + "users": cls.get_users(), + } cls.is_loaded = True @classmethod @@ -174,3 +179,18 @@ class OwnerData: @classmethod def get_user_organisation(cls): return [(str(p.id()), p[0] or "Unnamed", "") for p in tool.Ifc.get().by_type("IfcOrganization")] + + @classmethod + def can_add_user(cls): + return tool.Ifc.get().by_type("IfcPerson") and tool.Ifc.get().by_type("IfcOrganization") + + @classmethod + def get_users(cls): + results = [] + for user in tool.Ifc.get().by_type("IfcPersonAndOrganization"): + results.append({ + "id": user.id(), + "label": "{} ({})".format(user.ThePerson[0] or "Unnamed", user.TheOrganization[0] or "Unnamed"), + "is_active": bpy.context.scene.BIMOwnerProperties.active_user_id == user.id(), + }) + return results diff --git a/src/blenderbim/blenderbim/bim/module/owner/operator.py b/src/blenderbim/blenderbim/bim/module/owner/operator.py index eeaf9be4a1..127b492b8a 100644 --- a/src/blenderbim/blenderbim/bim/module/owner/operator.py +++ b/src/blenderbim/blenderbim/bim/module/owner/operator.py @@ -264,3 +264,38 @@ class RemoveOrganisation(bpy.types.Operator, Operator): def _execute(self, context): core.remove_organisation(tool.Ifc, tool.Ifc.get().by_id(self.organisation)) + + +class AddPersonAndOrganisation(bpy.types.Operator, Operator): + bl_idname = "bim.add_person_and_organisation" + bl_label = "Add Person And Organisation" + bl_options = {"REGISTER", "UNDO"} + person: bpy.props.IntProperty() + organisation: bpy.props.IntProperty() + + def _execute(self, context): + core.add_person_and_organisation( + tool.Ifc, person=tool.Ifc.get().by_id(self.person), organisation=tool.Ifc.get().by_id(self.organisation) + ) + + +class RemovePersonAndOrganisation(bpy.types.Operator, Operator): + bl_idname = "bim.remove_person_and_organisation" + bl_label = "Remove Person And Organisation" + bl_options = {"REGISTER", "UNDO"} + person_and_organisation: bpy.props.IntProperty() + + def _execute(self, context): + core.remove_person_and_organisation( + tool.Ifc, tool.Owner, person_and_organisation=tool.Ifc.get().by_id(self.person_and_organisation) + ) + + +class SetUser(bpy.types.Operator, Operator): + bl_idname = "bim.set_user" + bl_label = "set_user" + bl_options = {"REGISTER", "UNDO"} + user: bpy.props.IntProperty() + + def _execute(self, context): + core.set_user(tool.Owner, user=tool.Ifc.get().by_id(self.user)) diff --git a/src/blenderbim/blenderbim/bim/module/owner/prop.py b/src/blenderbim/blenderbim/bim/module/owner/prop.py index 1cbd3c466c..23a2e8d413 100644 --- a/src/blenderbim/blenderbim/bim/module/owner/prop.py +++ b/src/blenderbim/blenderbim/bim/module/owner/prop.py @@ -63,3 +63,4 @@ class BIMOwnerProperties(PropertyGroup): messaging_ids: CollectionProperty(type=StrProperty, name="IMs") user_person: EnumProperty(items=get_user_person, name="Person") user_organisation: EnumProperty(items=get_user_organisation, name="Organisation") + active_user_id: IntProperty(name="Active User Id") diff --git a/src/blenderbim/blenderbim/bim/module/owner/ui.py b/src/blenderbim/blenderbim/bim/module/owner/ui.py index 7f5d472dfb..bd61add10e 100644 --- a/src/blenderbim/blenderbim/bim/module/owner/ui.py +++ b/src/blenderbim/blenderbim/bim/module/owner/ui.py @@ -207,3 +207,19 @@ class BIM_PT_owner(bpy.types.Panel): else: row = self.layout.row() row.prop(props, "user_organisation") + + if OwnerData.data["can_add_user"]: + row = self.layout.row() + op = row.operator("bim.add_person_and_organisation", icon="ADD") + op.person = int(props.user_person) + op.organisation = int(props.user_organisation) + + for user in OwnerData.data["users"]: + row = self.layout.row(align=True) + if user["is_active"]: + row.label(text=user["label"], icon="USER") + else: + row.label(text=user["label"]) + row.operator("bim.set_user", icon="KEYFRAME_HLT", text="").user = user["id"] + op = row.operator("bim.remove_person_and_organisation", icon="X", text="") + op.person_and_organisation = user["id"] diff --git a/src/blenderbim/blenderbim/bim/module/project/operator.py b/src/blenderbim/blenderbim/bim/module/project/operator.py index 604f277871..ca7ed6250c 100644 --- a/src/blenderbim/blenderbim/bim/module/project/operator.py +++ b/src/blenderbim/blenderbim/bim/module/project/operator.py @@ -27,7 +27,8 @@ import ifcopenshell.util.selector import ifcopenshell.util.representation import blenderbim.bim.handler import blenderbim.tool as tool -import blenderbim.core.context as context_core +import blenderbim.core.context as core_context +import blenderbim.core.owner as core_owner from blenderbim.bim.ifc import IfcStore from blenderbim.bim import import_ifc @@ -57,8 +58,10 @@ class CreateProject(bpy.types.Operator): ) self.file = IfcStore.get_file() - bpy.ops.bim.add_person() - bpy.ops.bim.add_organisation() + person = core_owner.add_person(tool.Ifc) + organisation = core_owner.add_organisation(tool.Ifc) + user = core_owner.add_person_and_organisation(tool.Ifc, person=person, organisation=organisation) + core_owner.set_user(tool.Owner, user=user) project = bpy.data.objects.new(self.get_name("IfcProject", "My Project"), None) site = bpy.data.objects.new(self.get_name("IfcSite", "My Site"), None) @@ -68,18 +71,17 @@ class CreateProject(bpy.types.Operator): bpy.ops.bim.assign_class(obj=project.name, ifc_class="IfcProject") bpy.ops.bim.assign_unit() - # TODO: refactor - model = context_core.add_context( + model = core_context.add_context( tool.Ifc, context_type="Model", context_identifier="", target_view="", parent=0 ) - context_core.add_context( + core_context.add_context( tool.Ifc, context_type="Model", context_identifier="Body", target_view="MODEL_VIEW", parent=model ) - context_core.add_context( + core_context.add_context( tool.Ifc, context_type="Model", context_identifier="Box", target_view="MODEL_VIEW", parent=model ) - plan = context_core.add_context(tool.Ifc, context_type="Plan", context_identifier="", target_view="", parent=0) - context_core.add_context( + plan = core_context.add_context(tool.Ifc, context_type="Plan", context_identifier="", target_view="", parent=0) + core_context.add_context( tool.Ifc, context_type="Plan", context_identifier="Annotation", target_view="PLAN_VIEW", parent=plan ) diff --git a/src/blenderbim/blenderbim/core/owner.py b/src/blenderbim/blenderbim/core/owner.py index 4c89c2dcc4..0c31a7cad6 100644 --- a/src/blenderbim/blenderbim/core/owner.py +++ b/src/blenderbim/blenderbim/core/owner.py @@ -121,3 +121,21 @@ def edit_organisation(ifc, organisation_editor): organisation = organisation_editor.get_organisation() ifc.run("owner.edit_organisation", organisation=organisation, attributes=organisation_editor.export_attributes()) organisation_editor.clear_organisation() + + +def add_person_and_organisation(ifc, person=None, organisation=None): + return ifc.run("owner.add_person_and_organisation", person=person, organisation=organisation) + + +def remove_person_and_organisation(ifc, owner, person_and_organisation): + if owner.get_user() == person_and_organisation: + owner.clear_user() + ifc.run("owner.remove_person_and_organisation", person_and_organisation=person_and_organisation) + + +def set_user(owner, user=None): + owner.set_user(user) + + +def get_user(owner): + return owner.get_user() diff --git a/src/blenderbim/blenderbim/core/tool/__init__.py b/src/blenderbim/blenderbim/core/tool/__init__.py index c98548be52..33eb9d7515 100644 --- a/src/blenderbim/blenderbim/core/tool/__init__.py +++ b/src/blenderbim/blenderbim/core/tool/__init__.py @@ -23,3 +23,4 @@ from blenderbim.core.tool.role_editor import RoleEditor from blenderbim.core.tool.address_editor import AddressEditor from blenderbim.core.tool.organisation_editor import OrganisationEditor from blenderbim.core.tool.context_editor import ContextEditor +from blenderbim.core.tool.owner import Owner diff --git a/src/blenderbim/blenderbim/core/tool/owner.py b/src/blenderbim/blenderbim/core/tool/owner.py new file mode 100644 index 0000000000..9a6f421fb4 --- /dev/null +++ b/src/blenderbim/blenderbim/core/tool/owner.py @@ -0,0 +1,18 @@ +import abc + + +class Owner(abc.ABC): + @classmethod + @abc.abstractmethod + def set_user(cls, user): + pass + + @classmethod + @abc.abstractmethod + def get_user(cls): + pass + + @classmethod + @abc.abstractmethod + def clear_user(cls): + pass diff --git a/src/blenderbim/blenderbim/tool/__init__.py b/src/blenderbim/blenderbim/tool/__init__.py index 6c6127a108..f39d65c33d 100644 --- a/src/blenderbim/blenderbim/tool/__init__.py +++ b/src/blenderbim/blenderbim/tool/__init__.py @@ -23,3 +23,4 @@ from blenderbim.tool.role_editor import RoleEditor from blenderbim.tool.address_editor import AddressEditor from blenderbim.tool.organisation_editor import OrganisationEditor from blenderbim.tool.context_editor import ContextEditor +from blenderbim.tool.owner import Owner diff --git a/src/blenderbim/blenderbim/tool/owner.py b/src/blenderbim/blenderbim/tool/owner.py new file mode 100644 index 0000000000..898f291c29 --- /dev/null +++ b/src/blenderbim/blenderbim/tool/owner.py @@ -0,0 +1,17 @@ +import bpy +import blenderbim.core.tool +import blenderbim.tool as tool + +class Owner(blenderbim.core.tool.owner.Owner): + @classmethod + def set_user(cls, user): + bpy.context.scene.BIMOwnerProperties.active_user_id = user.id() + + @classmethod + def get_user(cls): + if bpy.context.scene.BIMOwnerProperties.active_user_id: + return tool.Ifc.get().by_id(bpy.context.scene.BIMOwnerProperties.active_user_id) + + @classmethod + def clear_user(cls): + bpy.context.scene.BIMOwnerProperties.active_user_id = 0 diff --git a/src/blenderbim/test/bim/bootstrap.py b/src/blenderbim/test/bim/bootstrap.py index 146033b89a..f531cef13c 100644 --- a/src/blenderbim/test/bim/bootstrap.py +++ b/src/blenderbim/test/bim/bootstrap.py @@ -44,6 +44,7 @@ class NewFile: while bpy.data.objects: bpy.data.objects.remove(bpy.data.objects[0]) bpy.ops.outliner.orphans_purge(do_local_ids=True, do_linked_ids=True, do_recursive=True) + blenderbim.bim.handler.setDefaultProperties(None) class NewIfc: @@ -54,6 +55,7 @@ class NewIfc: while bpy.data.objects: bpy.data.objects.remove(bpy.data.objects[0]) bpy.ops.outliner.orphans_purge(do_local_ids=True, do_linked_ids=True, do_recursive=True) + blenderbim.bim.handler.setDefaultProperties(None) bpy.ops.bim.create_project() diff --git a/src/blenderbim/test/bim/feature/owner.feature b/src/blenderbim/test/bim/feature/owner.feature index d64d8ab59e..fe1a7f3197 100644 --- a/src/blenderbim/test/bim/feature/owner.feature +++ b/src/blenderbim/test/bim/feature/owner.feature @@ -10,7 +10,7 @@ Scenario: Add person Scenario: Remove person Given an empty IFC project When I press "bim.add_person" - And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" + And the variable "person" is "{ifc}.by_type('IfcPerson')[-1].id()" And I press "bim.remove_person(person={person})" Then nothing happens @@ -198,6 +198,38 @@ Scenario: Edit organisation Scenario: Remove organisation Given an empty IFC project When I press "bim.add_organisation" - And the variable "organisation" is "{ifc}.by_type('IfcOrganization')[0].id()" + And the variable "organisation" is "{ifc}.by_type('IfcOrganization')[-1].id()" And I press "bim.remove_organisation(organisation={organisation})" Then nothing happens + +Scenario: Add person and organisation + Given an empty IFC project + When I press "bim.add_person" + And I press "bim.add_organisation" + And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" + And the variable "organisation" is "{ifc}.by_type('IfcOrganization')[0].id()" + And I press "bim.add_person_and_organisation(person={person}, organisation={organisation})" + Then nothing happens + +Scenario: Remove person and organisation + Given an empty IFC project + When I press "bim.add_person" + And I press "bim.add_organisation" + And the variable "person" is "{ifc}.by_type('IfcPerson')[-1].id()" + And the variable "organisation" is "{ifc}.by_type('IfcOrganization')[-1].id()" + And I press "bim.add_person_and_organisation(person={person}, organisation={organisation})" + # Note: these are set to -1 temporarily to prevent crashing due to bug #1747 + And the variable "pno" is "{ifc}.by_type('IfcPersonAndOrganization')[-1].id()" + And I press "bim.remove_person_and_organisation(person_and_organisation={pno})" + Then nothing happens + +Scenario: Set user + Given an empty IFC project + When I press "bim.add_person" + And I press "bim.add_organisation" + And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()" + And the variable "organisation" is "{ifc}.by_type('IfcOrganization')[0].id()" + And I press "bim.add_person_and_organisation(person={person}, organisation={organisation})" + And the variable "user" is "{ifc}.by_type('IfcPersonAndOrganization')[0].id()" + And I press "bim.set_user(user={user})" + Then nothing happens diff --git a/src/blenderbim/test/core/bootstrap.py b/src/blenderbim/test/core/bootstrap.py index 13f0613b4d..86a13dad43 100644 --- a/src/blenderbim/test/core/bootstrap.py +++ b/src/blenderbim/test/core/bootstrap.py @@ -70,6 +70,13 @@ def context_editor(): prophet.verify() +@pytest.fixture +def owner(): + prophet = Prophecy(blenderbim.core.tool.Owner) + yield prophet + prophet.verify() + + class Prophecy: def __init__(self, cls): self.subject = cls diff --git a/src/blenderbim/test/core/test_owner.py b/src/blenderbim/test/core/test_owner.py index bc4cca86e5..53c05719bf 100644 --- a/src/blenderbim/test/core/test_owner.py +++ b/src/blenderbim/test/core/test_owner.py @@ -18,7 +18,7 @@ import blenderbim.core.owner as subject -from test.core.bootstrap import ifc, blender, person_editor, role_editor, address_editor, organisation_editor +from test.core.bootstrap import ifc, blender, person_editor, role_editor, address_editor, organisation_editor, owner class TestAddPerson: @@ -181,3 +181,41 @@ class TestEditOrganisation: ifc.run("owner.edit_organisation", organisation="organisation", attributes="attributes").should_be_called() organisation_editor.clear_organisation().should_be_called() subject.edit_organisation(ifc, organisation_editor) + + +class TestAddPersonAndOrganisation: + def test_run(self, ifc): + ifc.run( + "owner.add_person_and_organisation", person="person", organisation="organisation" + ).should_be_called().will_return("person_and_organisation") + assert ( + subject.add_person_and_organisation(ifc, person="person", organisation="organisation") + == "person_and_organisation" + ) + + +class TestRemovePersonAndOrganisation: + def test_run(self, ifc, owner): + owner.get_user().should_be_called().will_return("user") + ifc.run( + "owner.remove_person_and_organisation", person_and_organisation="person_and_organisation" + ).should_be_called() + subject.remove_person_and_organisation(ifc, owner, person_and_organisation="person_and_organisation") + + def test_clearing_the_active_user_if_you_remove_it(self, ifc, owner): + owner.get_user().should_be_called().will_return("user") + owner.clear_user().should_be_called() + ifc.run("owner.remove_person_and_organisation", person_and_organisation="user").should_be_called() + subject.remove_person_and_organisation(ifc, owner, person_and_organisation="user") + + +class TestSetUser: + def test_run(self, owner): + owner.set_user("person_and_organisation").should_be_called() + subject.set_user(owner, user="person_and_organisation") + + +class TestGetUser: + def test_run(self, owner): + owner.get_user().should_be_called().will_return("person_and_organisation") + assert subject.get_user(owner) == "person_and_organisation" diff --git a/src/blenderbim/test/tool/test_owner.py b/src/blenderbim/test/tool/test_owner.py new file mode 100644 index 0000000000..21377cf8e5 --- /dev/null +++ b/src/blenderbim/test/tool/test_owner.py @@ -0,0 +1,35 @@ +import bpy +import ifcopenshell +import test.bim.bootstrap +import blenderbim.core.tool +import blenderbim.tool as tool +from blenderbim.tool.owner import Owner as subject + + +class TestImplementsTool(test.bim.bootstrap.NewFile): + def test_run(self): + assert isinstance(subject(), blenderbim.core.tool.owner.Owner) + + +class TestSetUser(test.bim.bootstrap.NewFile): + def test_run(self): + ifc = ifcopenshell.file() + tool.Ifc.set(ifc) + user = ifc.createIfcPersonAndOrganization() + subject.set_user(user) + assert bpy.context.scene.BIMOwnerProperties.active_user_id == user.id() + + +class TestGetUser(test.bim.bootstrap.NewFile): + def test_run(self): + assert subject.get_user() is None + TestSetUser().test_run() + user = tool.Ifc.get().by_type("IfcPersonAndOrganization")[0] + assert subject.get_user() == user + + +class TestClearUser(test.bim.bootstrap.NewFile): + def test_run(self): + TestSetUser().test_run() + subject.clear_user() + assert bpy.context.scene.BIMOwnerProperties.active_user_id == 0 diff --git a/src/ifcopenshell-python/ifcopenshell/api/owner/remove_actor.py b/src/ifcopenshell-python/ifcopenshell/api/owner/add_person_and_organisation.py similarity index 51% rename from src/ifcopenshell-python/ifcopenshell/api/owner/remove_actor.py rename to src/ifcopenshell-python/ifcopenshell/api/owner/add_person_and_organisation.py index 9dc134ef0c..443e1411d0 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/owner/remove_actor.py +++ b/src/ifcopenshell-python/ifcopenshell/api/owner/add_person_and_organisation.py @@ -1,9 +1,9 @@ class Usecase: def __init__(self, file, **settings): self.file = file - self.settings = {"actor": None} + self.settings = {"person": None, "organisation": None} for key, value in settings.items(): self.settings[key] = value def execute(self): - self.file.remove(self.settings["actor"]) + return self.file.createIfcPersonAndOrganization(self.settings["person"], self.settings["organisation"]) diff --git a/src/ifcopenshell-python/ifcopenshell/api/owner/remove_organisation.py b/src/ifcopenshell-python/ifcopenshell/api/owner/remove_organisation.py index 217aa5fe76..93c482a890 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/owner/remove_organisation.py +++ b/src/ifcopenshell-python/ifcopenshell/api/owner/remove_organisation.py @@ -27,7 +27,7 @@ class Usecase: elif inverse.is_a("IfcPersonAndOrganization"): ifcopenshell.api.run("owner.remove_person_and_organisation", self.file, person_and_organisation=inverse) elif inverse.is_a("IfcActor"): - ifcopenshell.api.run("owner.remove_actor", self.file, actor=inverse) + ifcopenshell.api.run("root.remove_product", self.file, product=inverse) elif inverse.is_a("IfcResourceLevelRelationship") and not inverse.is_a("IfcOrganizationRelationship"): if inverse.RelatedResourceObjects == (self.settings["organisation"],): self.file.remove(inverse) diff --git a/src/ifcopenshell-python/ifcopenshell/api/owner/remove_person.py b/src/ifcopenshell-python/ifcopenshell/api/owner/remove_person.py index 8a5fb6d245..be40cd17f6 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/owner/remove_person.py +++ b/src/ifcopenshell-python/ifcopenshell/api/owner/remove_person.py @@ -28,7 +28,7 @@ class Usecase: elif inverse.is_a("IfcPersonAndOrganization"): ifcopenshell.api.run("owner.remove_person_and_organisation", self.file, person_and_organisation=inverse) elif inverse.is_a("IfcActor"): - ifcopenshell.api.run("owner.remove_actor", self.file, actor=inverse) + ifcopenshell.api.run("root.remove_product", self.file, product=inverse) elif inverse.is_a("IfcResourceLevelRelationship"): if inverse.RelatedResourceObjects == (self.settings["person"],): self.file.remove(inverse) diff --git a/src/ifcopenshell-python/ifcopenshell/api/owner/remove_person_and_organisation.py b/src/ifcopenshell-python/ifcopenshell/api/owner/remove_person_and_organisation.py index b2b86b24d7..9f951144e1 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/owner/remove_person_and_organisation.py +++ b/src/ifcopenshell-python/ifcopenshell/api/owner/remove_person_and_organisation.py @@ -1,3 +1,6 @@ +import ifcopenshell.api + + class Usecase: def __init__(self, file, **settings): self.file = file @@ -6,4 +9,15 @@ class Usecase: self.settings[key] = value def execute(self): + for inverse in self.file.get_inverse(self.settings["person_and_organisation"]): + if inverse.is_a("IfcDocumentInformation"): + if inverse.Editors == (self.settings["person_and_organisation"],): + inverse.Editors = None + elif inverse.is_a("IfcActor"): + ifcopenshell.api.run("root.remove_product", self.file, product=inverse) + elif inverse.is_a("IfcResourceLevelRelationship"): + if inverse.RelatedResourceObjects == (self.settings["person_and_organisation"],): + self.file.remove(inverse) + elif inverse.is_a("IfcOwnerHistory"): + self.file.remove(inverse) self.file.remove(self.settings["person_and_organisation"]) diff --git a/src/ifcopenshell-python/test/api/owner/test_add_person_and_organisation.py b/src/ifcopenshell-python/test/api/owner/test_add_person_and_organisation.py new file mode 100644 index 0000000000..d21716075e --- /dev/null +++ b/src/ifcopenshell-python/test/api/owner/test_add_person_and_organisation.py @@ -0,0 +1,11 @@ +import test.bootstrap +import ifcopenshell.api + + +class TestAddPersonAndOrganisation(test.bootstrap.IFC4): + def test_adding(self): + person = self.file.createIfcPerson() + organisation = self.file.createIfcOrganization() + person_and_organisation = ifcopenshell.api.run( + "owner.add_person_and_organisation", self.file, person=person, organisation=organisation + ) diff --git a/src/ifcopenshell-python/test/api/owner/test_remove_person_and_organisation.py b/src/ifcopenshell-python/test/api/owner/test_remove_person_and_organisation.py new file mode 100644 index 0000000000..c3a4894387 --- /dev/null +++ b/src/ifcopenshell-python/test/api/owner/test_remove_person_and_organisation.py @@ -0,0 +1,45 @@ +import test.bootstrap +import ifcopenshell.api + + +class TestRemovePersonAndOrganisation(test.bootstrap.IFC4): + def test_removing(self): + user = self.file.createIfcPersonAndOrganization() + ifcopenshell.api.run("owner.remove_person_and_organisation", self.file, person_and_organisation=user) + assert len(self.file.by_type("IfcPersonAndOrganization")) == 0 + + def test_deleting_actors(self): + user = self.file.createIfcPersonAndOrganization() + self.file.createIfcActor(GlobalId=ifcopenshell.guid.new(), TheActor=user) + ifcopenshell.api.run("owner.remove_person_and_organisation", self.file, person_and_organisation=user) + assert len(self.file.by_type("IfcActor")) == 0 + + def test_ensuring_document_information_should_not_be_left_in_an_invalid_set_cardinality(self): + user = self.file.createIfcPersonAndOrganization() + document_information = self.file.createIfcDocumentInformation(Editors=[user]) + ifcopenshell.api.run("owner.remove_person_and_organisation", self.file, person_and_organisation=user) + assert document_information.Editors is None + + def test_deleting_resource_approval_relationships(self): + user = self.file.createIfcPersonAndOrganization() + self.file.createIfcResourceApprovalRelationship(RelatedResourceObjects=[user]) + ifcopenshell.api.run("owner.remove_person_and_organisation", self.file, person_and_organisation=user) + assert len(self.file.by_type("IfcResourceApprovalRelationship")) == 0 + + def test_deleting_resource_constraint_relationships(self): + user = self.file.createIfcPersonAndOrganization() + self.file.createIfcResourceConstraintRelationship(RelatedResourceObjects=[user]) + ifcopenshell.api.run("owner.remove_person_and_organisation", self.file, person_and_organisation=user) + assert len(self.file.by_type("IfcResourceConstraintRelationship")) == 0 + + def test_deleting_external_reference_relationships(self): + user = self.file.createIfcPersonAndOrganization() + self.file.createIfcExternalReferenceRelationship(RelatedResourceObjects=[user]) + ifcopenshell.api.run("owner.remove_person_and_organisation", self.file, person_and_organisation=user) + assert len(self.file.by_type("IfcExternalReferenceRelationship")) == 0 + + def test_deleting_owner_history(self): + user = self.file.createIfcPersonAndOrganization() + self.file.createIfcOwnerHistory(OwningUser=user) + ifcopenshell.api.run("owner.remove_person_and_organisation", self.file, person_and_organisation=user) + assert len(self.file.by_type("IfcOwnerHistory")) == 0