diff --git a/helpdesk_mgmt_activity/README.rst b/helpdesk_mgmt_activity/README.rst new file mode 100644 index 0000000000..207ec47f98 --- /dev/null +++ b/helpdesk_mgmt_activity/README.rst @@ -0,0 +1,152 @@ +============================ +Helpdesk Management Activity +============================ + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:c77bb124906154be8648020f75af1b6c2dca2c419551445c18e60b86488fe429 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fhelpdesk-lightgray.png?logo=github + :target: https://github.com/OCA/helpdesk/tree/16.0/helpdesk_mgmt_activity + :alt: OCA/helpdesk +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/helpdesk-16-0/helpdesk-16-0-helpdesk_mgmt_activity + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/helpdesk&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +The module adds the following features: + +* Link a ticket to an Odoo model record +* Set the list of available models for a Helpdesk team +* Pre-configure ticket description template based on it's category +* Create an activity for the linked record right from the Ticket +* Change the Ticket's stage based on the activity state + + + +**Table of contents** + +.. contents:: + :local: + +Use Cases / Context +=================== + +To streamline your helpdesk operations you can set activities to the pre-configured odoo modules records right from the Helpdesk. + +The ticket will be moved to the pre-defined stage when the activity is marked as done. + +For instance: + +A customer reaches the support team regarding a delayed shipment.  +- Assign Activity: The helpdesk support team user opens a ticket for the relevant Inventory picking record with specific instructions to check the shipment status and actions that must be taken. +- Warehouse Action: The assigned warehouse user sees the new activity in their Odoo dashboard, follows the prescribed steps to investigate, and updates the activity status accordingly. +- Automated Updates: Once the warehouse user marks the activity as done, the ticket automatically moves to the "Awaiting" stage to be checked by the support team user. + +Configuration +============= + +**To Configure Available Odoo Models** +====================================== + +- Go to Helpdesk-->Configuration-->Settings +- In the Available Models field add models available for a Helpdesk + +.. figure:: https://raw.githubusercontent.com/OCA/helpdesk/16.0/helpdesk_mgmt_activity/static/img/settings.png + :alt: Settings view + :width: 600 px + +To Configure Ticket's Stage on Activity State** +=============================================== + +- Go to Helpdesk-->Configuration-->Teams +- Create a new team or select an existing record +- Enable the "Set Activities" checkbox to enable the feature +- Select the "Done Activity Stage" to move the ticket when the activity is done + +.. figure:: https://raw.githubusercontent.com/OCA/helpdesk/16.0/helpdesk_mgmt_activity/static/img/team.png + :alt: Team view + :width: 600 px + + +Usage +===== + +**Go to Helpdesk module** +========================= + +- Select a Team +- Open a Ticket +- Create a new Ticket +- In the "Assign Activity" group + + - Select a related model and record in the Source field + - Select Activity type and due date + +.. image:: https://raw.githubusercontent.com/OCA/helpdesk/16.0/helpdesk_mgmt_activity/static/img/helpdesk_activity_fields.png + :width: 400 + :alt: Helpdesk Activity Fields + +- Enter the Description +- Click the "Perform Action" button +- Ticket will be moved to the next preset state and activity will be created in the related model +- If an activity is Done, the Ticket moves to the pre-defined stage + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Cetmix OÜ + +Contributors +~~~~~~~~~~~~ + +* `Cetmix OÜ `_: + + * Ivan Sokolov + * Mikhail Lapin + * Dessan Hemrayev + * Maksim Shurupov + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/helpdesk `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/helpdesk_mgmt_activity/__init__.py b/helpdesk_mgmt_activity/__init__.py new file mode 100644 index 0000000000..bf8e144111 --- /dev/null +++ b/helpdesk_mgmt_activity/__init__.py @@ -0,0 +1,4 @@ +# Copyright (C) 2024 Cetmix OÜ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import models diff --git a/helpdesk_mgmt_activity/__manifest__.py b/helpdesk_mgmt_activity/__manifest__.py new file mode 100644 index 0000000000..f61aa4eebf --- /dev/null +++ b/helpdesk_mgmt_activity/__manifest__.py @@ -0,0 +1,19 @@ +# Copyright (C) 2024 Cetmix OÜ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + "name": "Helpdesk Management Activity", + "summary": "Create Activities for Odoo records from the Helpdesk", + "version": "16.0.1.0.0", + "license": "AGPL-3", + "author": "Cetmix OÜ, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/helpdesk", + "depends": ["helpdesk_mgmt"], + "data": [ + "views/res_config_settings_views.xml", + "views/helpdesk_ticket_view.xml", + "views/mail_activity_views.xml", + "views/helpdesk_ticket_team_views.xml", + ], + "application": False, +} diff --git a/helpdesk_mgmt_activity/models/__init__.py b/helpdesk_mgmt_activity/models/__init__.py new file mode 100644 index 0000000000..05003e865c --- /dev/null +++ b/helpdesk_mgmt_activity/models/__init__.py @@ -0,0 +1,7 @@ +# Copyright (C) 2024 Cetmix OÜ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import res_config_settings +from . import helpdesk_ticket +from . import helpdesk_ticket_team +from . import mail_activity diff --git a/helpdesk_mgmt_activity/models/helpdesk_ticket.py b/helpdesk_mgmt_activity/models/helpdesk_ticket.py new file mode 100644 index 0000000000..bc95fa223f --- /dev/null +++ b/helpdesk_mgmt_activity/models/helpdesk_ticket.py @@ -0,0 +1,155 @@ +# Copyright (C) 2024 Cetmix OÜ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import ast + +from odoo import _, api, fields, models + + +class HelpdeskTicket(models.Model): + _inherit = "helpdesk.ticket" + + can_create_activity = fields.Boolean(related="team_id.allow_set_activity") + res_model = fields.Char(string="Source Document Model", index=True) + res_id = fields.Integer(string="Source Document", index=True) + + record_ref = fields.Reference( + selection="_selection_record_ref", + compute="_compute_record_ref", + inverse="_inverse_record_ref", + string="Source Record", + ) + source_activity_type_id = fields.Many2one(comodel_name="mail.activity.type") + date_deadline = fields.Date(string="Due Date", default=fields.Date.today) + next_stage_id = fields.Many2one( + comodel_name="helpdesk.ticket.stage", + compute="_compute_next_stage_id", + store=True, + index=True, + ) + assigned_user_id = fields.Many2one( + comodel_name="res.users", + ) + is_new_stage = fields.Boolean(compute="_compute_is_new_stage") + + @api.model + def _selection_record_ref(self): + """Select target model for source document""" + model_ids_str = ( + self.env["ir.config_parameter"] + .sudo() + .get_param("helpdesk_mgmt_activity.helpdesk_available_model_ids", "[]") + ) + model_ids = ast.literal_eval(model_ids_str) + if not model_ids: + return [] + IrModelAccess = self.env["ir.model.access"].with_user(self.env.user.id) + available_models = self.env["ir.model"].search_read( + [("id", "in", model_ids)], fields=["model", "name"] + ) + return [ + (model.get("model"), model.get("name")) + for model in available_models + if IrModelAccess.check(model.get("model"), "read", False) + ] + + @api.model + def _get_team_stages(self, teams): + """ + Get grouping stages by team id + + :param teams: helpdesk.ticket.team record set + :return: dict {team_id: team stages recordset} + """ + return {team.id: team._get_applicable_stages() for team in teams} + + def _compute_is_new_stage(self): + for ticket in self: + new_stage = ticket.team_id._get_applicable_stages()[:1] + ticket.is_new_stage = ticket.stage_id == new_stage + + @api.depends("stage_id") + def _compute_next_stage_id(self): + """Compute next stage for ticket""" + team_stages = self._get_team_stages(self.team_id) + helpdesk_ticket_stage_obj = self.env["helpdesk.ticket.stage"] + for record in self: + current_stage = record.stage_id + stages = team_stages.get(record.team_id.id, helpdesk_ticket_stage_obj) + next_stage = ( + stages.filtered( + lambda stage, _cur_stage=current_stage: stage.sequence + > current_stage.sequence + )[:1] + or current_stage + ) + record.next_stage_id = next_stage + + @api.depends("res_model", "res_id") + def _compute_record_ref(self): + """Compute Source Document Reference""" + for rec in self: + if not rec.res_model or not rec.res_id: + rec.record_ref = None + continue + try: + self.env[rec.res_model].browse(rec.res_id).check_access_rule("read") + rec.record_ref = "%s,%s" % (rec.res_model, rec.res_id) + except Exception: + rec.record_ref = None + + def _inverse_record_ref(self): + """Set Source Document Reference""" + for record in self: + record_ref = record.record_ref + record.write( + { + "res_id": record_ref and record_ref.id or False, + "res_model": record_ref and record_ref._name or False, + } + ) + + def set_next_stage(self): + """Set next ticket stage""" + for record in self: + record.stage_id = record.next_stage_id + + def _check_activity_values(self): + """Check activity values for helpdesk ticket""" + if not self.can_create_activity: + raise models.UserError(_("You cannot create activity!")) + if not (self.res_id and self.res_model): + raise models.UserError(_("Source Record is not set!")) + if not self.source_activity_type_id: + raise models.UserError(_("Activity Type is not set!")) + if not self.date_deadline: + raise models.UserError(_("Date Deadline is not set!")) + if not self.assigned_user_id: + raise models.UserError(_("Assigned User is not set!")) + + def perform_action(self): + """Perform action for ticket""" + self.ensure_one() + # Check values for create activity + self._check_activity_values() + try: + # Create activity for source record + self.record_ref.activity_schedule( + summary=self.name, + note=self.description, + date_deadline=self.date_deadline, + activity_type_id=self.source_activity_type_id.id, + ticket_id=self.id, + ) + self.set_next_stage() + except Exception as e: + raise models.UserError from e + return { + "type": "ir.actions.client", + "tag": "display_notification", + "params": { + "type": "success", + "message": _("Activity has been created!"), + "next": {"type": "ir.actions.act_window_close"}, + }, + } diff --git a/helpdesk_mgmt_activity/models/helpdesk_ticket_team.py b/helpdesk_mgmt_activity/models/helpdesk_ticket_team.py new file mode 100644 index 0000000000..68ce5f3668 --- /dev/null +++ b/helpdesk_mgmt_activity/models/helpdesk_ticket_team.py @@ -0,0 +1,19 @@ +# Copyright (C) 2024 Cetmix OÜ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class HelpdeskTicketTeam(models.Model): + _inherit = "helpdesk.ticket.team" + + allow_set_activity = fields.Boolean( + string="Set Activities", + help="Available to set activity on source record from ticket", + ) + activity_stage_id = fields.Many2one( + comodel_name="helpdesk.ticket.stage", + string="Done Activity Stage", + domain="['|', ('team_ids', 'in, []'), ('team_ids', 'in', [id])]", + help="Move the ticket when the activity in source record is done", + ) diff --git a/helpdesk_mgmt_activity/models/mail_activity.py b/helpdesk_mgmt_activity/models/mail_activity.py new file mode 100644 index 0000000000..8761dd2bf4 --- /dev/null +++ b/helpdesk_mgmt_activity/models/mail_activity.py @@ -0,0 +1,22 @@ +# Copyright (C) 2024 Cetmix OÜ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class MailActivity(models.Model): + _inherit = "mail.activity" + + ticket_id = fields.Many2one( + comodel_name="helpdesk.ticket", + help="Activity created from helpdesk ticket" + "After closing this activity, ticket is moved to done stage", + ) + + def _action_done(self, feedback=False, attachment_ids=None): + # Get closed stage for ticket + for ticket in self.ticket_id: + if ticket.team_id and ticket.team_id.activity_stage_id: + # Change ticket stage + ticket.stage_id = ticket.team_id.activity_stage_id.id + return super()._action_done(feedback, attachment_ids) diff --git a/helpdesk_mgmt_activity/models/res_config_settings.py b/helpdesk_mgmt_activity/models/res_config_settings.py new file mode 100644 index 0000000000..886cf4caa3 --- /dev/null +++ b/helpdesk_mgmt_activity/models/res_config_settings.py @@ -0,0 +1,41 @@ +# Copyright (C) 2024 Cetmix OÜ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import ast + +from odoo import api, fields, models + + +class ResConfigSettings(models.TransientModel): + _inherit = "res.config.settings" + + helpdesk_available_model_ids = fields.Many2many( + comodel_name="ir.model", + domain="[('transient', '=', False)]", + string="Available Models", + help="Available models for set source record in helpdesk ticket", + ) + + def set_values(self): + super().set_values() + ICPSudo = self.env["ir.config_parameter"].sudo() + ICPSudo.set_param( + "helpdesk_mgmt_activity.helpdesk_available_model_ids", + str(self.helpdesk_available_model_ids.ids), + ) + return + + @api.model + def get_values(self): + res = super().get_values() + ICPSudo = self.env["ir.config_parameter"].sudo() + helpdesk_available_model_ids = ICPSudo.get_param( + "helpdesk_mgmt_activity.helpdesk_available_model_ids", False + ) + if helpdesk_available_model_ids: + res.update( + helpdesk_available_model_ids=ast.literal_eval( + helpdesk_available_model_ids + ) + ) + return res diff --git a/helpdesk_mgmt_activity/readme/CONFIGURE.rst b/helpdesk_mgmt_activity/readme/CONFIGURE.rst new file mode 100644 index 0000000000..7f7caf4fce --- /dev/null +++ b/helpdesk_mgmt_activity/readme/CONFIGURE.rst @@ -0,0 +1,22 @@ +**To Configure Available Odoo Models** +====================================== + +- Go to Helpdesk-->Configuration-->Settings +- In the Available Models field add models available for a Helpdesk + +.. figure:: ../static/img/settings.png + :alt: Settings view + :width: 600 px + +To Configure Ticket's Stage on Activity State** +=============================================== + +- Go to Helpdesk-->Configuration-->Teams +- Create a new team or select an existing record +- Enable the "Set Activities" checkbox to enable the feature +- Select the "Done Activity Stage" to move the ticket when the activity is done + +.. figure:: ../static/img/team.png + :alt: Team view + :width: 600 px + diff --git a/helpdesk_mgmt_activity/readme/CONTEXT.rst b/helpdesk_mgmt_activity/readme/CONTEXT.rst new file mode 100644 index 0000000000..3acc086ef9 --- /dev/null +++ b/helpdesk_mgmt_activity/readme/CONTEXT.rst @@ -0,0 +1,10 @@ +To streamline your helpdesk operations you can set activities to the pre-configured odoo modules records right from the Helpdesk. + +The ticket will be moved to the pre-defined stage when the activity is marked as done. + +For instance: + +A customer reaches the support team regarding a delayed shipment.  +- Assign Activity: The helpdesk support team user opens a ticket for the relevant Inventory picking record with specific instructions to check the shipment status and actions that must be taken. +- Warehouse Action: The assigned warehouse user sees the new activity in their Odoo dashboard, follows the prescribed steps to investigate, and updates the activity status accordingly. +- Automated Updates: Once the warehouse user marks the activity as done, the ticket automatically moves to the "Awaiting" stage to be checked by the support team user. \ No newline at end of file diff --git a/helpdesk_mgmt_activity/readme/CONTRIBUTORS.rst b/helpdesk_mgmt_activity/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000000..f6396e8c34 --- /dev/null +++ b/helpdesk_mgmt_activity/readme/CONTRIBUTORS.rst @@ -0,0 +1,6 @@ +* `Cetmix OÜ `_: + + * Ivan Sokolov + * Mikhail Lapin + * Dessan Hemrayev + * Maksim Shurupov diff --git a/helpdesk_mgmt_activity/readme/DESCRIPTION.rst b/helpdesk_mgmt_activity/readme/DESCRIPTION.rst new file mode 100644 index 0000000000..c7c5af9e5c --- /dev/null +++ b/helpdesk_mgmt_activity/readme/DESCRIPTION.rst @@ -0,0 +1,9 @@ +The module adds the following features: + +* Link a ticket to an Odoo model record +* Set the list of available models for a Helpdesk team +* Pre-configure ticket description template based on it's category +* Create an activity for the linked record right from the Ticket +* Change the Ticket's stage based on the activity state + + diff --git a/helpdesk_mgmt_activity/readme/USAGE.rst b/helpdesk_mgmt_activity/readme/USAGE.rst new file mode 100644 index 0000000000..b10daf3423 --- /dev/null +++ b/helpdesk_mgmt_activity/readme/USAGE.rst @@ -0,0 +1,19 @@ +**Go to Helpdesk module** +========================= + +- Select a Team +- Open a Ticket +- Create a new Ticket +- In the "Assign Activity" group + + - Select a related model and record in the Source field + - Select Activity type and due date + +.. image:: ../static/img/helpdesk_activity_fields.png + :width: 400 + :alt: Helpdesk Activity Fields + +- Enter the Description +- Click the "Perform Action" button +- Ticket will be moved to the next preset state and activity will be created in the related model +- If an activity is Done, the Ticket moves to the pre-defined stage diff --git a/helpdesk_mgmt_activity/static/description/icon.png b/helpdesk_mgmt_activity/static/description/icon.png new file mode 100644 index 0000000000..3a0328b516 Binary files /dev/null and b/helpdesk_mgmt_activity/static/description/icon.png differ diff --git a/helpdesk_mgmt_activity/static/description/index.html b/helpdesk_mgmt_activity/static/description/index.html new file mode 100644 index 0000000000..007460f6c1 --- /dev/null +++ b/helpdesk_mgmt_activity/static/description/index.html @@ -0,0 +1,497 @@ + + + + + +Helpdesk Management Activity + + + +
+

Helpdesk Management Activity

+ + +

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

+

The module adds the following features:

+
    +
  • Link a ticket to an Odoo model record
  • +
  • Set the list of available models for a Helpdesk team
  • +
  • Pre-configure ticket description template based on it’s category
  • +
  • Create an activity for the linked record right from the Ticket
  • +
  • Change the Ticket’s stage based on the activity state
  • +
+

Table of contents

+ +
+

Use Cases / Context

+

To streamline your helpdesk operations you can set activities to the pre-configured odoo modules records right from the Helpdesk.

+

The ticket will be moved to the pre-defined stage when the activity is marked as done.

+

For instance:

+

A customer reaches the support team regarding a delayed shipment. +- Assign Activity: The helpdesk support team user opens a ticket for the relevant Inventory picking record with specific instructions to check the shipment status and actions that must be taken. +- Warehouse Action: The assigned warehouse user sees the new activity in their Odoo dashboard, follows the prescribed steps to investigate, and updates the activity status accordingly. +- Automated Updates: Once the warehouse user marks the activity as done, the ticket automatically moves to the “Awaiting” stage to be checked by the support team user.

+
+ +
+

To Configure Available Odoo Models

+
    +
  • Go to Helpdesk–>Configuration–>Settings
  • +
  • In the Available Models field add models available for a Helpdesk
  • +
+
+Settings view +
+
+
+

To Configure Ticket’s Stage on Activity State**

+
    +
  • Go to Helpdesk–>Configuration–>Teams
  • +
  • Create a new team or select an existing record
  • +
  • Enable the “Set Activities” checkbox to enable the feature
  • +
  • Select the “Done Activity Stage” to move the ticket when the activity is done
  • +
+
+Team view +
+
+
+

Usage

+
+
+

Go to Helpdesk module

+
    +
  • Select a Team
  • +
  • Open a Ticket
  • +
  • Create a new Ticket
  • +
  • In the “Assign Activity” group
      +
    • Select a related model and record in the Source field
    • +
    • Select Activity type and due date
    • +
    +
  • +
+Helpdesk Activity Fields +
    +
  • Enter the Description
  • +
  • Click the “Perform Action” button
  • +
  • Ticket will be moved to the next preset state and activity will be created in the related model
  • +
  • If an activity is Done, the Ticket moves to the pre-defined stage
  • +
+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Cetmix OÜ
  • +
+
+
+

Contributors

+
    +
  • Cetmix OÜ:
      +
    • Ivan Sokolov
    • +
    • Mikhail Lapin
    • +
    • Dessan Hemrayev
    • +
    • Maksim Shurupov
    • +
    +
  • +
+
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/helpdesk project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/helpdesk_mgmt_activity/static/img/helpdesk_activity_fields.png b/helpdesk_mgmt_activity/static/img/helpdesk_activity_fields.png new file mode 100644 index 0000000000..ea1b2faa14 Binary files /dev/null and b/helpdesk_mgmt_activity/static/img/helpdesk_activity_fields.png differ diff --git a/helpdesk_mgmt_activity/static/img/settings.png b/helpdesk_mgmt_activity/static/img/settings.png new file mode 100755 index 0000000000..91b0ecc11a Binary files /dev/null and b/helpdesk_mgmt_activity/static/img/settings.png differ diff --git a/helpdesk_mgmt_activity/static/img/team.png b/helpdesk_mgmt_activity/static/img/team.png new file mode 100755 index 0000000000..031e7028f4 Binary files /dev/null and b/helpdesk_mgmt_activity/static/img/team.png differ diff --git a/helpdesk_mgmt_activity/tests/__init__.py b/helpdesk_mgmt_activity/tests/__init__.py new file mode 100644 index 0000000000..c49ed31723 --- /dev/null +++ b/helpdesk_mgmt_activity/tests/__init__.py @@ -0,0 +1,4 @@ +# Copyright (C) 2024 Cetmix OÜ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import test_helpdesk_ticket diff --git a/helpdesk_mgmt_activity/tests/test_helpdesk_ticket.py b/helpdesk_mgmt_activity/tests/test_helpdesk_ticket.py new file mode 100644 index 0000000000..9b4abe3718 --- /dev/null +++ b/helpdesk_mgmt_activity/tests/test_helpdesk_ticket.py @@ -0,0 +1,258 @@ +# Copyright (C) 2024 Cetmix OÜ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo.exceptions import UserError +from odoo.fields import Date +from odoo.tests import Form + +from odoo.addons.helpdesk_mgmt.tests.common import TestHelpdeskTicketBase + + +class TestHelpdeskTicket(TestHelpdeskTicketBase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.partner_model = cls.env["ir.model"]._get("res.partner") + cls.test_partner = cls.env["res.partner"].create({"name": "Test Partner"}) + cls.activity_type_meeting = cls.env.ref("mail.mail_activity_data_meeting") + cls.env["ir.config_parameter"].sudo().set_param( + "helpdesk_mgmt_activity.helpdesk_available_model_ids", cls.partner_model.ids + ) + + # Stages + cls.progress_stage = cls.env.ref( + "helpdesk_mgmt.helpdesk_ticket_stage_in_progress" + ) + cls.awaiting_stage = cls.env.ref("helpdesk_mgmt.helpdesk_ticket_stage_awaiting") + + def create_ticket_and_activity(self): + """Create ticket and activity for record""" + ticket = self._create_ticket(self.team_a, self.user) + ticket.write( + { + "record_ref": f"res.partner,{self.test_partner.id}", + "source_activity_type_id": self.activity_type_meeting.id, + "date_deadline": Date.today(), + "assigned_user_id": self.env.user.id, + } + ) + ticket.perform_action() + activity = ticket.record_ref.activity_ids + return ticket, activity + + def test_ticket_next_stage(self): + """Test flow check stage for ticket""" + # Set team config + self.team_a.write( + { + "allow_set_activity": True, + "activity_stage_id": self.stage_closed.id, + } + ) + # Create ticket + ticket = self._create_ticket(self.team_a, self.user) + + self.assertEqual(ticket.stage_id, self.new_stage, "Stage must be new") + self.assertEqual( + ticket.next_stage_id, self.progress_stage, "Next stage must be progress" + ) + + # Set activity configuration for ticket + ticket.write( + { + "record_ref": f"res.partner,{self.test_partner.id}", + "source_activity_type_id": self.activity_type_meeting.id, + "date_deadline": Date.today(), + "assigned_user_id": self.env.user.id, + } + ) + + # Create activity for source record + ticket.perform_action() + activity = ticket.record_ref.activity_ids + + self.assertEqual( + ticket.stage_id, self.progress_stage, "Ticket stage must be progress" + ) + + # Activity set done + activity.action_done() + + self.assertEqual( + ticket.stage_id, self.stage_closed, "Ticket stage must be closed" + ) + + def test_ticket_available_model_ids(self): + """Test flow when available model for ticket is updated""" + settings = self.env["res.config.settings"].create({}) + with Form(settings) as form: + form.helpdesk_available_model_ids.add(self.partner_model) + values = settings.get_values() + self.assertEqual( + values.get("helpdesk_available_model_ids"), self.partner_model.ids + ) + self.env["ir.config_parameter"].sudo().set_param( + "helpdesk_mgmt_activity.helpdesk_available_model_ids", False + ) + values = settings.get_values() + self.assertFalse( + values.get("helpdesk_available_model_ids"), "Available models must be False" + ) + + def test_ticket_record_ref(self): + """Test flow when change source record""" + ticket = self._create_ticket(self.team_a, self.user) + self.assertFalse(ticket.record_ref, "Reference record must be False") + self.assertFalse(ticket.res_model, "Res Model must be False") + self.assertFalse(ticket.res_id, "Res ID must be False") + + ticket.record_ref = f"res.partner,{self.test_partner.id}" + self.assertEqual( + ticket.record_ref, + self.test_partner, + f"Reference record must be equal to {self.test_partner}", + ) + self.assertEqual( + ticket.res_id, + self.test_partner.id, + f"Res ID must be equal to {self.test_partner.id}", + ) + self.assertEqual( + ticket.res_model, "res.partner", "Res Model must be equal to 'res.partner'" + ) + + ticket.record_ref = False + self.assertFalse(ticket.res_id, "Res ID must be False") + self.assertFalse(ticket.res_model, "Res Model must be False") + + def test_perform_action(self): + """Test flow when create action in record reference""" + ticket = self._create_ticket(self.team_a, self.user) + + with self.assertRaises(UserError) as error: + ticket.perform_action() + self.assertEqual( + error.exception.args[0], + "You cannot create activity!", + "Errors must be the same", + ) + + ticket.team_id.allow_set_activity = True + + with self.assertRaises(UserError) as error: + ticket.perform_action() + self.assertEqual( + error.exception.args[0], + "Source Record is not set!", + "Errors must be the same", + ) + + ticket.record_ref = f"res.partner,{self.test_partner.id}" + + with self.assertRaises(UserError) as error: + ticket.perform_action() + self.assertEqual( + error.exception.args[0], + "Activity Type is not set!", + "Errors must be the same", + ) + + ticket.source_activity_type_id = self.activity_type_meeting + ticket.date_deadline = False + + with self.assertRaises(UserError) as error: + ticket.perform_action() + self.assertEqual( + error.exception.args[0], + "Date Deadline is not set!", + "Errors must be the same", + ) + + ticket.date_deadline = Date.today() + + with self.assertRaises(UserError) as error: + ticket.perform_action() + self.assertEqual( + error.exception.args[0], + "Assigned User is not set!", + "Errors must be the same", + ) + + ticket.assigned_user_id = self.env.user + + action = ticket.perform_action() + + self.assertDictEqual( + action, + { + "type": "ir.actions.client", + "tag": "display_notification", + "params": { + "type": "success", + "message": "Activity has been created!", + "next": {"type": "ir.actions.act_window_close"}, + }, + }, + ) + + activity = self.test_partner.activity_ids + self.assertEqual(len(activity), 1, "Activity count must be equal to 1") + self.assertRecordValues( + activity, + [ + { + "summary": ticket.name, + "note": ticket.description, + "date_deadline": ticket.date_deadline, + "activity_type_id": ticket.source_activity_type_id.id, + "ticket_id": ticket.id, + "user_id": self.env.user.id, + } + ], + ) + + def test_helpdesk_activity_with_team_stage(self): + """ + Test flow when create activity from helpdesk ticket + and done it. Ticket is moved to cancel stage + """ + self.team_a.write( + { + "allow_set_activity": True, + "activity_stage_id": self.stage_closed.id, + } + ) + ticket, activity = self.create_ticket_and_activity() + self.assertEqual( + activity.res_model_id.id, self.partner_model.id, "Model id's must be equal" + ) + self.assertEqual( + activity.res_id, + self.test_partner.id, + "Res ID must be equal to test partner ID", + ) + + activity.action_done() + self.assertEqual( + ticket.stage_id.id, self.stage_closed.id, "Stage ID must be equal" + ) + + def test_helpdesk_activity_without_team_stage(self): + """ + Test flow when create activity from helpdesk ticket + and done it without activity_stage_id field value from ticket team + """ + self.team_a.allow_set_activity = True + ticket, activity = self.create_ticket_and_activity() + ticket_stage_id = ticket.stage_id.id + self.assertEqual( + activity.res_model_id.id, self.partner_model.id, "Model id's must be equal" + ) + self.assertEqual( + activity.res_id, + self.test_partner.id, + "Res ID must be equal to test partner ID", + ) + + activity.action_done() + self.assertEqual(ticket_stage_id, ticket.stage_id.id, "Stage ID must be equal") diff --git a/helpdesk_mgmt_activity/views/helpdesk_ticket_team_views.xml b/helpdesk_mgmt_activity/views/helpdesk_ticket_team_views.xml new file mode 100644 index 0000000000..d795f984c5 --- /dev/null +++ b/helpdesk_mgmt_activity/views/helpdesk_ticket_team_views.xml @@ -0,0 +1,19 @@ + + + + view.helpdesk_team.form + helpdesk.ticket.team + + 99 + + + + + + + + diff --git a/helpdesk_mgmt_activity/views/helpdesk_ticket_view.xml b/helpdesk_mgmt_activity/views/helpdesk_ticket_view.xml new file mode 100644 index 0000000000..2b49982f28 --- /dev/null +++ b/helpdesk_mgmt_activity/views/helpdesk_ticket_view.xml @@ -0,0 +1,42 @@ + + + + helpdesk.ticket.view.form + helpdesk.ticket + + 99 + +
+ + +
+ + + + + + + + + + +
+
+
diff --git a/helpdesk_mgmt_activity/views/mail_activity_views.xml b/helpdesk_mgmt_activity/views/mail_activity_views.xml new file mode 100644 index 0000000000..8437d3e063 --- /dev/null +++ b/helpdesk_mgmt_activity/views/mail_activity_views.xml @@ -0,0 +1,15 @@ + + + + + mail.activity.view.form.popup.helpdesk.inherit + mail.activity + + + + + + + + + diff --git a/helpdesk_mgmt_activity/views/res_config_settings_views.xml b/helpdesk_mgmt_activity/views/res_config_settings_views.xml new file mode 100644 index 0000000000..0e8155d9ef --- /dev/null +++ b/helpdesk_mgmt_activity/views/res_config_settings_views.xml @@ -0,0 +1,31 @@ + + + + res.config.settings.form.view + res.config.settings + + + +
+
+
+
+
+
+
+ + + + diff --git a/setup/helpdesk_mgmt_activity/odoo/addons/helpdesk_mgmt_activity b/setup/helpdesk_mgmt_activity/odoo/addons/helpdesk_mgmt_activity new file mode 120000 index 0000000000..407eab2985 --- /dev/null +++ b/setup/helpdesk_mgmt_activity/odoo/addons/helpdesk_mgmt_activity @@ -0,0 +1 @@ +../../../../helpdesk_mgmt_activity \ No newline at end of file diff --git a/setup/helpdesk_mgmt_activity/setup.py b/setup/helpdesk_mgmt_activity/setup.py new file mode 100644 index 0000000000..28c57bb640 --- /dev/null +++ b/setup/helpdesk_mgmt_activity/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)