diff --git a/README.md b/README.md index 3506f0594e..da3d17f862 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ addon | version | maintainers | summary [fieldservice_sale_recurring](fieldservice_sale_recurring/) | 17.0.1.0.0 | [![wolfhall](https://github.com/wolfhall.png?size=30px)](https://github.com/wolfhall) [![max3903](https://github.com/max3903.png?size=30px)](https://github.com/max3903) [![brian10048](https://github.com/brian10048.png?size=30px)](https://github.com/brian10048) | Sell recurring field services. [fieldservice_sale_stock](fieldservice_sale_stock/) | 17.0.1.0.0 | [![wolfhall](https://github.com/wolfhall.png?size=30px)](https://github.com/wolfhall) [![max3903](https://github.com/max3903.png?size=30px)](https://github.com/max3903) [![brian10048](https://github.com/brian10048.png?size=30px)](https://github.com/brian10048) | Sell stockable items linked to field service orders. [fieldservice_size](fieldservice_size/) | 17.0.1.0.0 | [![brian10048](https://github.com/brian10048.png?size=30px)](https://github.com/brian10048) | Manage Sizes for Field Service Locations and Orders -[fieldservice_stage_server_action](fieldservice_stage_server_action/) | 17.0.1.2.0 | [![wolfhall](https://github.com/wolfhall.png?size=30px)](https://github.com/wolfhall) [![max3903](https://github.com/max3903.png?size=30px)](https://github.com/max3903) [![osi-scampbell](https://github.com/osi-scampbell.png?size=30px)](https://github.com/osi-scampbell) | Execute server actions when reaching a Field Service stage +[fieldservice_stage_server_action](fieldservice_stage_server_action/) | 17.0.1.3.0 | [![wolfhall](https://github.com/wolfhall.png?size=30px)](https://github.com/wolfhall) [![max3903](https://github.com/max3903.png?size=30px)](https://github.com/max3903) [![osi-scampbell](https://github.com/osi-scampbell.png?size=30px)](https://github.com/osi-scampbell) | Execute server actions when reaching a Field Service stage [fieldservice_stage_validation](fieldservice_stage_validation/) | 17.0.1.0.0 | [![brian10048](https://github.com/brian10048.png?size=30px)](https://github.com/brian10048) [![max3903](https://github.com/max3903.png?size=30px)](https://github.com/max3903) | Validate input data when reaching a Field Service stage [fieldservice_stock](fieldservice_stock/) | 17.0.1.0.0 | [![brian10048](https://github.com/brian10048.png?size=30px)](https://github.com/brian10048) [![wolfhall](https://github.com/wolfhall.png?size=30px)](https://github.com/wolfhall) [![max3903](https://github.com/max3903.png?size=30px)](https://github.com/max3903) [![smangukiya](https://github.com/smangukiya.png?size=30px)](https://github.com/smangukiya) | Integrate the logistics operations with Field Service [fieldservice_stock_request](fieldservice_stock_request/) | 17.0.1.0.0 | [![brian10048](https://github.com/brian10048.png?size=30px)](https://github.com/brian10048) [![wolfhall](https://github.com/wolfhall.png?size=30px)](https://github.com/wolfhall) [![max3903](https://github.com/max3903.png?size=30px)](https://github.com/max3903) [![smangukiya](https://github.com/smangukiya.png?size=30px)](https://github.com/smangukiya) | Integrate Stock Requests with Field Service Orders diff --git a/fieldservice_stage_server_action/README.rst b/fieldservice_stage_server_action/README.rst index 1aae88f1a5..ed813032f3 100644 --- a/fieldservice_stage_server_action/README.rst +++ b/fieldservice_stage_server_action/README.rst @@ -7,7 +7,7 @@ Field Service - Stage Server Action !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:692853f7ec0c8b792133260b679740fe08a9b1421f649d86b1dbfb7092098cf1 + !! source digest: sha256:8f82be57132b1954908f048a909057dede2e15ca164db60ca95f1d11eff92bec !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png diff --git a/fieldservice_stage_server_action/__manifest__.py b/fieldservice_stage_server_action/__manifest__.py index 00bf1f197f..2cbd637e57 100644 --- a/fieldservice_stage_server_action/__manifest__.py +++ b/fieldservice_stage_server_action/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Field Service - Stage Server Action", "summary": "Execute server actions when reaching a Field Service stage", - "version": "17.0.1.2.0", + "version": "17.0.1.3.0", "category": "Field Service", "author": "Open Source Integrators, Odoo Community Association (OCA)", "website": "https://github.com/OCA/field-service", diff --git a/fieldservice_stage_server_action/models/fsm_stage_server_action_mixin.py b/fieldservice_stage_server_action/models/fsm_stage_server_action_mixin.py index 4b2812d732..5e431e6824 100644 --- a/fieldservice_stage_server_action/models/fsm_stage_server_action_mixin.py +++ b/fieldservice_stage_server_action/models/fsm_stage_server_action_mixin.py @@ -11,22 +11,30 @@ class FsmStageServerActionMixin(models.AbstractModel): @api.model_create_multi def create(self, vals_list): records = super().create(vals_list) - records._run_stage_server_action() - return records - - def write(self, vals): - res = super().write(vals) - if "stage_id" in vals: - self._run_stage_server_action() - return res - - def _run_stage_server_action(self): - for record in self: - action_id = record.stage_id.action_id - if not action_id: + for record in records: + action = record.stage_id.action_id + if not action: continue - ctx = { + context = { "active_model": self._name, "active_id": record.id, } - action_id.with_context(**ctx).run() + action.with_context(**context).run() + return records + + def write(self, vals): + records = "stage_id" in vals and self.filtered( + lambda ticket: ticket.stage_id.id != vals.get("stage_id") + ) + if records: + res = super().write(vals) + action = self.env["fsm.stage"].browse(vals["stage_id"]).action_id + if action: + context = { + "active_model": self._name, + "active_ids": records.ids, + } + action.with_context(**context).run() + else: + res = super().write(vals) + return res diff --git a/fieldservice_stage_server_action/static/description/index.html b/fieldservice_stage_server_action/static/description/index.html index dc2f8ad9c7..ee68f1ec36 100644 --- a/fieldservice_stage_server_action/static/description/index.html +++ b/fieldservice_stage_server_action/static/description/index.html @@ -367,7 +367,7 @@

Field Service - Stage Server Action

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:692853f7ec0c8b792133260b679740fe08a9b1421f649d86b1dbfb7092098cf1 +!! source digest: sha256:8f82be57132b1954908f048a909057dede2e15ca164db60ca95f1d11eff92bec !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Beta License: AGPL-3 OCA/field-service Translate me on Weblate Try me on Runboat

This module allows you to execute server actions when a FSM orders diff --git a/fieldservice_stage_server_action/tests/test_fsm_order_run_action.py b/fieldservice_stage_server_action/tests/test_fsm_order_run_action.py index 5dfce0dc90..96d3039a1d 100644 --- a/fieldservice_stage_server_action/tests/test_fsm_order_run_action.py +++ b/fieldservice_stage_server_action/tests/test_fsm_order_run_action.py @@ -8,33 +8,206 @@ class TestFSMOrderRunAction(TransactionCase): @classmethod def setUpClass(cls): super().setUpClass() - cls.Order = cls.env["fsm.order"] - cls.Tag = cls.env["fsm.tag"] - cls.test_location = cls.env.ref("fieldservice.test_location") - cls.stage1 = cls.env.ref("fieldservice.fsm_stage_completed") - cls.stage2 = cls.env.ref("fieldservice.fsm_stage_cancelled") - cls.location_1 = cls.env.ref("fieldservice.location_1") - cls.create_action = cls.env["ir.actions.server"].create( - { - "model_id": cls.env["ir.model"]._get_id("fsm.tag"), - "crud_model_id": cls.env["ir.model"]._get_id("fsm.tag"), + cls.FSMEquipment = cls.env["fsm.equipment"] + cls.FSMLocation = cls.env["fsm.location"] + cls.FSMOrders = cls.env["fsm.order"] + cls.FSMPerson = cls.env["fsm.person"] + cls.FSMStage = cls.env["fsm.stage"] + cls.FSMTag = cls.env["fsm.tag"] + cls.ServerAction = cls.env["ir.actions.server"] + # Mail Activity Type + cls.activity_type = cls.env["mail.activity.type"].create({"name": "To Do"}) + # Phone Number + cls.phone = "070-070-070" + # Equipment + cls.server_action_equipment = cls.ServerAction.create( + { + "name": "Equipment Server Action", + "model_id": cls.env.ref("fieldservice.model_fsm_equipment").id, + "state": "next_activity", + "activity_user_field_name": "user_id", + "activity_type_id": cls.activity_type.id, + "activity_user_type": "generic", + } + ) + cls.stage_equipment_1 = cls.FSMStage.create( + { + "name": "Equipment Stage 1", + "stage_type": "equipment", + "action_id": cls.server_action_equipment.id, + "sequence": 10, + } + ) + cls.stage_equipment_2 = cls.FSMStage.create( + { + "name": "Equipment Stage 2", + "stage_type": "equipment", + "action_id": cls.server_action_equipment.id, + "sequence": 11, + } + ) + # Location + cls.server_action_location = cls.ServerAction.create( + { + "name": "Location Server Action", + "model_id": cls.env.ref("fieldservice.model_fsm_location").id, + "state": "next_activity", + "activity_user_field_name": "user_id", + "activity_type_id": cls.activity_type.id, + "activity_user_type": "generic", + } + ) + cls.stage_location_1 = cls.FSMStage.create( + { + "name": "Location Stage 1", + "stage_type": "location", + "action_id": cls.server_action_location.id, + "sequence": 12, + } + ) + cls.stage_location_2 = cls.FSMStage.create( + { + "name": "Location Stage 2", + "stage_type": "location", + "action_id": cls.server_action_location.id, + "sequence": 13, + } + ) + # Order + cls.server_action_order = cls.ServerAction.create( + { + "name": "Order Server Action", + "model_id": cls.env.ref("fieldservice.model_fsm_order").id, + "state": "next_activity", + "activity_user_field_name": "user_id", + "activity_type_id": cls.activity_type.id, + "activity_user_type": "generic", + } + ) + cls.stage_order_1 = cls.FSMStage.create( + { + "name": "Order Stage 1", + "stage_type": "order", + "action_id": cls.server_action_order.id, + "sequence": 14, + } + ) + cls.stage_order_2 = cls.FSMStage.create( + { + "name": "Order Stage 2", + "stage_type": "order", + "action_id": cls.server_action_order.id, + "sequence": 15, + } + ) + # Worker + cls.field = cls.env["ir.model.fields"]._get(cls.FSMPerson._name, "phone") + cls.server_action_worker = cls.ServerAction.create( + { + "name": "Worker Server Action", + "model_id": cls.env["ir.model"]._get_id("fsm.person"), + "crud_model_id": cls.env["ir.model"]._get_id("fsm.person"), + "value": cls.phone, + "update_path": "phone", + "update_field_id": cls.env["ir.model.fields"]._get_ids("fsm.person")[ + "phone" + ], + "evaluation_type": "value", + "state": "object_write", + } + ) + cls.stage_worker_1 = cls.FSMStage.create( + { + "name": "Worker Stage 1", + "stage_type": "worker", + "action_id": cls.server_action_worker.id, + "sequence": 16, + } + ) + cls.stage_worker_2 = cls.FSMStage.create( + { + "name": "Worker Stage 2", + "stage_type": "worker", + "action_id": cls.server_action_worker.id, + "sequence": 17, + } + ) + + def test_fsm_equipment(self): + # Create + self.equipment = self.FSMEquipment.create( + {"name": "Equipment", "stage_id": self.stage_equipment_1.id} + ) + self.assertEqual(len(self.equipment.activity_ids), 1) + # Write + self.equipment.write({"stage_id": self.stage_equipment_2.id}) + self.assertEqual(len(self.equipment.activity_ids), 2) + + def test_fsm_location(self): + # Create + self.worker = self.FSMPerson.create({"name": "Worker"}) + self.location = self.FSMLocation.create( + { + "name": "Location", + "stage_id": self.stage_location_1.id, + "owner_id": self.worker.id, + } + ) + self.assertEqual(len(self.location.activity_ids), 1) + # Write + self.location.write({"stage_id": self.stage_location_2.id}) + self.assertEqual(len(self.location.activity_ids), 2) + + def test_fsm_order(self): + # Create + self.worker = self.FSMPerson.create({"name": "Worker"}) + self.location = self.FSMLocation.create( + {"name": "Location", "owner_id": self.worker.id} + ) + self.order = self.FSMOrders.create( + { + "name": "Order", + "stage_id": self.stage_order_1.id, + "location_id": self.location.id, + } + ) + self.assertEqual(len(self.order.activity_ids), 1) + # Write + self.order.write({"stage_id": self.stage_order_2.id}) + self.assertEqual(len(self.order.activity_ids), 2) + + def test_fsm_worker(self): + self.worker = self.FSMPerson.create( + {"name": "Worker", "stage_id": self.stage_worker_1.id} + ) + self.assertEqual(self.worker.phone, self.phone) + self.worker.write({"phone": False}) + self.worker.write({"stage_id": self.stage_worker_2.id}) + self.assertEqual(self.worker.phone, self.phone) + + def test_fsm_order_run_action(self): + test_location = self.env.ref("fieldservice.test_location") + stage1 = self.env.ref("fieldservice.fsm_stage_completed") + stage2 = self.env.ref("fieldservice.fsm_stage_cancelled") + create_action = self.env["ir.actions.server"].create( + { + "model_id": self.env["ir.model"]._get_id("fsm.tag"), + "crud_model_id": self.env["ir.model"]._get_id("fsm.tag"), "name": "Create new tag", "value": "New test tag", "state": "object_create", } ) - cls.stage2.action_id = cls.create_action - - def test_fsm_order_run_action(self): - order = self.Order.create( + stage2.action_id = create_action + order = self.FSMOrders.create( { - "location_id": self.test_location.id, - "stage_id": self.stage1.id, + "location_id": test_location.id, + "stage_id": stage1.id, } ) - self.assertFalse(self.Tag.search([("name", "=", "New test tag")]).exists()) - with RecordCapturer(self.Tag, []) as capture: - order.write({"stage_id": self.stage2.id}) + self.assertFalse(self.FSMTag.search([("name", "=", "New test tag")]).exists()) + with RecordCapturer(self.FSMTag, []) as capture: + order.write({"stage_id": stage2.id}) tag = capture.records self.assertEqual(1, len(tag)) self.assertEqual("New test tag", tag.name)