Compare commits
4 Commits
9ed3774820
...
923a4f16c4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
923a4f16c4 | ||
|
|
b58fb77f3a | ||
|
|
6b8906325e | ||
|
|
1bfe51109e |
92
helpdesk_user_default_ticket_team/README.md
Normal file
92
helpdesk_user_default_ticket_team/README.md
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
# helpdesk_user_default_ticket_team
|
||||||
|
|
||||||
|
Automate ticket team attribution when a ticket is created by a portal user.
|
||||||
|
|
||||||
|
This module extends the `helpdesk_mgmt` module by allowing to configure a
|
||||||
|
default helpdesk team per user. It provides:
|
||||||
|
|
||||||
|
- A new `default_helpdesk_ticket_team_id` field on the user form, located in
|
||||||
|
the Preferences tab.
|
||||||
|
- Automatic team assignment when a ticket is created:
|
||||||
|
- If the ticket has no team assigned and has a linked partner.
|
||||||
|
- The module looks up the user associated with the partner. A partner with
|
||||||
|
no linked user (e.g. a plain contact) is handled gracefully and left
|
||||||
|
untouched.
|
||||||
|
- If the user has a default helpdesk team configured, it is automatically
|
||||||
|
assigned to the ticket.
|
||||||
|
- If the assigned team has a default project, the ticket is also linked to
|
||||||
|
that project.
|
||||||
|
- Automatic user assignment when a team is selected:
|
||||||
|
- When a team is set or changed on a ticket, if the current assigned user
|
||||||
|
is not a member of that team, the team leader (`team_id.user_id`) is
|
||||||
|
automatically assigned instead.
|
||||||
|
- If the team has no leader configured, the assigned user is left unchanged
|
||||||
|
(to avoid creating unassigned tickets).
|
||||||
|
|
||||||
|
This is particularly useful for multi-company or multi-team environments where
|
||||||
|
portal users should always have their tickets routed to a specific team.
|
||||||
|
|
||||||
|
# Installation
|
||||||
|
|
||||||
|
Use Odoo normal module installation procedure to install
|
||||||
|
`helpdesk_user_default_ticket_team`.
|
||||||
|
|
||||||
|
This module depends on:
|
||||||
|
|
||||||
|
- `helpdesk_mgmt`: provides the base helpdesk ticket functionality.
|
||||||
|
- `helpdesk_mgmt_project`: provides the link between tickets and projects.
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
|
||||||
|
1. Open a user form (Settings > Users & Companies > Users).
|
||||||
|
2. In the **Preferences** tab, set the **Default Helpdesk Team** field.
|
||||||
|
3. When that user (through its linked partner) creates a ticket without an
|
||||||
|
explicit team, the ticket is automatically routed to the configured team,
|
||||||
|
its default project, and the team leader.
|
||||||
|
|
||||||
|
# Testing
|
||||||
|
|
||||||
|
Automated tests live in `tests/test_helpdesk_ticket.py` and cover:
|
||||||
|
|
||||||
|
- The `_define_user_id` decision logic (no team, no current user, user not in
|
||||||
|
team, user in team, team without leader).
|
||||||
|
- The `create` auto-assignment (with/without partner, with/without default
|
||||||
|
team, explicit team not overridden, partner without linked user, batch
|
||||||
|
creation).
|
||||||
|
- The `_compute_user_id` recomputation when the team changes.
|
||||||
|
- The full portal creation flow (team + project + user) and the presence of
|
||||||
|
the `default_helpdesk_ticket_team_id` field on `res.users`.
|
||||||
|
|
||||||
|
Run them with:
|
||||||
|
|
||||||
|
```
|
||||||
|
odoo-bin -d <db> --test-enable --stop-after-init \
|
||||||
|
-i helpdesk_user_default_ticket_team
|
||||||
|
```
|
||||||
|
|
||||||
|
# Known issues / Roadmap
|
||||||
|
|
||||||
|
None yet.
|
||||||
|
|
||||||
|
# Bug Tracker
|
||||||
|
|
||||||
|
Bugs are tracked on [our issues website](https://git.elabore.coop/Elabore/helpdesk-tools/issues).
|
||||||
|
In case of trouble, please check there if your issue has already been
|
||||||
|
reported. If you spotted it first, help us smashing it by providing a
|
||||||
|
detailed and welcomed feedback.
|
||||||
|
|
||||||
|
# Credits
|
||||||
|
|
||||||
|
## Contributors
|
||||||
|
|
||||||
|
- Stéphan Sainléger - [Email](mailto:stephan.sainleger@elabore.coop)
|
||||||
|
|
||||||
|
## Funders
|
||||||
|
|
||||||
|
The development of this module has been financially supported by:
|
||||||
|
|
||||||
|
- Elabore (https://elabore.coop)
|
||||||
|
|
||||||
|
## Maintainer
|
||||||
|
|
||||||
|
This module is maintained by Elabore.
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
=================================
|
|
||||||
helpdesk_user_default_ticket_team
|
|
||||||
=================================
|
|
||||||
|
|
||||||
Automate ticket team attribution when ticket created by portal user.
|
|
||||||
|
|
||||||
This module extends the ``helpdesk_mgmt`` module by allowing to configure a
|
|
||||||
default helpdesk team per user. It provides:
|
|
||||||
|
|
||||||
* A new ``default_helpdesk_ticket_team_id`` field on the user form, located in
|
|
||||||
the Preferences tab.
|
|
||||||
* Automatic team assignment when a ticket is created:
|
|
||||||
|
|
||||||
* If the ticket has no team assigned and has a linked partner.
|
|
||||||
* The module looks up the portal user associated with the partner.
|
|
||||||
* If the user has a default helpdesk team configured, it is automatically
|
|
||||||
assigned to the ticket.
|
|
||||||
* If the assigned team has a default project, the ticket is also linked to
|
|
||||||
that project.
|
|
||||||
|
|
||||||
* Automatic user assignment when a team is selected:
|
|
||||||
|
|
||||||
* When a team is set or changed on a ticket, if the current assigned user
|
|
||||||
is not a member of that team, the team leader (``team_id.user_id``) is
|
|
||||||
automatically assigned instead.
|
|
||||||
* If the team has no leader configured, the assigned user is left unchanged
|
|
||||||
(to avoid creating unassigned tickets).
|
|
||||||
|
|
||||||
This is particularly useful for multi-company or multi-team environments where
|
|
||||||
portal users should always have their tickets routed to a specific team.
|
|
||||||
|
|
||||||
Installation
|
|
||||||
============
|
|
||||||
|
|
||||||
Use Odoo normal module installation procedure to install
|
|
||||||
``helpdesk_user_default_ticket_team``.
|
|
||||||
|
|
||||||
This module depends on:
|
|
||||||
|
|
||||||
* ``helpdesk_mgmt``: provides the base helpdesk ticket functionality.
|
|
||||||
* ``helpdesk_mgmt_project``: provides the link between tickets and projects.
|
|
||||||
|
|
||||||
Known issues / Roadmap
|
|
||||||
======================
|
|
||||||
|
|
||||||
None yet.
|
|
||||||
|
|
||||||
Bug Tracker
|
|
||||||
===========
|
|
||||||
|
|
||||||
Bugs are tracked on `our issues website <https://git.elabore.coop/Elabore/helpdesk-tools/issues>`_. In case of
|
|
||||||
trouble, please check there if your issue has already been
|
|
||||||
reported. If you spotted it first, help us smashing it by providing a
|
|
||||||
detailed and welcomed feedback.
|
|
||||||
|
|
||||||
Credits
|
|
||||||
=======
|
|
||||||
|
|
||||||
Contributors
|
|
||||||
------------
|
|
||||||
|
|
||||||
* Stéphan Sainléger - `Email <mailto:stephan.sainleger@elabore.coop>`_
|
|
||||||
|
|
||||||
Funders
|
|
||||||
-------
|
|
||||||
|
|
||||||
The development of this module has been financially supported by:
|
|
||||||
|
|
||||||
* Elabore (https://elabore.coop)
|
|
||||||
|
|
||||||
|
|
||||||
Maintainer
|
|
||||||
----------
|
|
||||||
|
|
||||||
This module is maintained by Elabore.
|
|
||||||
@@ -6,21 +6,41 @@ class HelpdeskTicket(models.Model):
|
|||||||
|
|
||||||
@api.depends("team_id")
|
@api.depends("team_id")
|
||||||
def _compute_user_id(self):
|
def _compute_user_id(self):
|
||||||
|
"""Recompute the assigned user whenever the team changes.
|
||||||
|
|
||||||
|
Delegates to :meth:`_define_user_id` so that, when a team is set or
|
||||||
|
changed, the assigned user is realigned with that team (replaced by
|
||||||
|
the team leader if the current user does not belong to the team).
|
||||||
|
"""
|
||||||
for ticket in self:
|
for ticket in self:
|
||||||
if ticket.team_id:
|
ticket.user_id = self._define_user_id(
|
||||||
if ticket.user_id not in ticket.team_id.user_ids:
|
ticket.team_id,
|
||||||
if ticket.team_id.user_id:
|
ticket.user_id,
|
||||||
ticket.user_id = ticket.team_id.user_id
|
)
|
||||||
|
|
||||||
@api.model_create_multi
|
@api.model_create_multi
|
||||||
def create(self, vals_list):
|
def create(self, vals_list):
|
||||||
|
"""Auto-assign team, project and user for portal-created tickets.
|
||||||
|
|
||||||
|
When a ticket is created without an explicit team but with a partner,
|
||||||
|
the partner's linked user is looked up and, if that user has a default
|
||||||
|
helpdesk team configured, the ticket is routed accordingly:
|
||||||
|
|
||||||
|
* ``team_id`` is set to the user's default helpdesk team.
|
||||||
|
* ``project_id`` is set to the team's default project, if any.
|
||||||
|
* ``user_id`` is set to the team leader (via :meth:`_define_user_id`).
|
||||||
|
|
||||||
|
Tickets that already have a team, that have no partner, or whose
|
||||||
|
partner has no linked user / no default team are left untouched.
|
||||||
|
"""
|
||||||
for vals in vals_list:
|
for vals in vals_list:
|
||||||
if not vals.get("team_id") and vals.get("partner_id"):
|
if not vals.get("team_id") and vals.get("partner_id"):
|
||||||
# Find the user who creates the ticket
|
# Find the user who creates the ticket
|
||||||
partner = self.env["res.partner"].browse(vals.get("partner_id"))
|
partner = self.env["res.partner"].browse(vals.get("partner_id"))
|
||||||
if not partner:
|
if not partner:
|
||||||
continue
|
continue
|
||||||
user = self.env["res.users"].browse(partner.user_ids[0].id)
|
# A partner may have no linked user (e.g. a plain contact)
|
||||||
|
user = partner.user_ids[:1]
|
||||||
if not user:
|
if not user:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@@ -35,4 +55,42 @@ class HelpdeskTicket(models.Model):
|
|||||||
if team.default_project_id:
|
if team.default_project_id:
|
||||||
vals["project_id"] = team.default_project_id.id
|
vals["project_id"] = team.default_project_id.id
|
||||||
|
|
||||||
|
# Set the user_id to which the ticket is assigned
|
||||||
|
user_id = self._define_user_id(team, None)
|
||||||
|
if user_id:
|
||||||
|
vals["user_id"] = user_id.id
|
||||||
return super().create(vals_list)
|
return super().create(vals_list)
|
||||||
|
|
||||||
|
def _define_user_id(self, team_id=None, ticket_user_id=None):
|
||||||
|
"""Determine which user should be assigned to a ticket for a team.
|
||||||
|
|
||||||
|
Decides whether the current ticket user must be kept or replaced by
|
||||||
|
the helpdesk team leader (``team_id.user_id``), according to the
|
||||||
|
following rules:
|
||||||
|
|
||||||
|
* No team -> keep ``ticket_user_id`` unchanged.
|
||||||
|
* No current user -> use the team leader.
|
||||||
|
* User not in team -> replace with the team leader.
|
||||||
|
* User is a team member-> keep ``ticket_user_id`` unchanged.
|
||||||
|
|
||||||
|
:param team_id: the ``helpdesk.ticket.team`` record (or falsy).
|
||||||
|
:param ticket_user_id: the currently assigned ``res.users`` (or falsy).
|
||||||
|
:return: the ``res.users`` record that should be assigned (possibly an
|
||||||
|
empty recordset when the team has no leader and the current user
|
||||||
|
is not a member of the team).
|
||||||
|
"""
|
||||||
|
if not team_id:
|
||||||
|
# If no team, return the current ticket_user_id
|
||||||
|
return ticket_user_id
|
||||||
|
|
||||||
|
if not ticket_user_id:
|
||||||
|
# If no current user, fall back to the team leader (may be empty).
|
||||||
|
return team_id.user_id
|
||||||
|
|
||||||
|
if ticket_user_id not in team_id.user_ids:
|
||||||
|
# If the current user is not a team member, replace it with the
|
||||||
|
# team leader (may be empty).
|
||||||
|
return team_id.user_id
|
||||||
|
|
||||||
|
# Otherwise the current user is a valid team member: keep it unchanged.
|
||||||
|
return ticket_user_id
|
||||||
|
|||||||
1
helpdesk_user_default_ticket_team/tests/__init__.py
Normal file
1
helpdesk_user_default_ticket_team/tests/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
from . import test_helpdesk_ticket
|
||||||
399
helpdesk_user_default_ticket_team/tests/test_helpdesk_ticket.py
Normal file
399
helpdesk_user_default_ticket_team/tests/test_helpdesk_ticket.py
Normal file
@@ -0,0 +1,399 @@
|
|||||||
|
# Copyright 2025 Stéphan Sainléger (Elabore)
|
||||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
|
from odoo.tests.common import TransactionCase
|
||||||
|
|
||||||
|
|
||||||
|
class TestHelpdeskUserDefaultTicketTeam(TransactionCase):
|
||||||
|
"""Tests for helpdesk_user_default_ticket_team module."""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
super().setUpClass()
|
||||||
|
cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
# Create users
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
cls.team_leader = cls.env["res.users"].create(
|
||||||
|
{
|
||||||
|
"name": "Team Leader",
|
||||||
|
"login": "team_leader",
|
||||||
|
"email": "leader@test.com",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
cls.team_member = cls.env["res.users"].create(
|
||||||
|
{
|
||||||
|
"name": "Team Member",
|
||||||
|
"login": "team_member",
|
||||||
|
"email": "member@test.com",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
cls.portal_user = cls.env["res.users"].create(
|
||||||
|
{
|
||||||
|
"name": "Portal User",
|
||||||
|
"login": "portal_user",
|
||||||
|
"email": "portal@test.com",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
cls.user_no_team = cls.env["res.users"].create(
|
||||||
|
{
|
||||||
|
"name": "No Team User",
|
||||||
|
"login": "no_team_user",
|
||||||
|
"email": "noteam@test.com",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
# Create a project (needed by helpdesk_mgmt_project)
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
cls.project = cls.env["project.project"].create(
|
||||||
|
{"name": "Test Project"}
|
||||||
|
)
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
# Create helpdesk teams
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
cls.team_with_leader = cls.env["helpdesk.ticket.team"].create(
|
||||||
|
{
|
||||||
|
"name": "Team With Leader",
|
||||||
|
"user_id": cls.team_leader.id,
|
||||||
|
"user_ids": [
|
||||||
|
(6, 0, [cls.team_leader.id, cls.team_member.id])
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
cls.team_no_leader = cls.env["helpdesk.ticket.team"].create(
|
||||||
|
{
|
||||||
|
"name": "Team No Leader",
|
||||||
|
"user_ids": [(6, 0, [cls.team_member.id])],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
cls.team_with_project = cls.env["helpdesk.ticket.team"].create(
|
||||||
|
{
|
||||||
|
"name": "Team With Project",
|
||||||
|
"user_id": cls.team_leader.id,
|
||||||
|
"user_ids": [(6, 0, [cls.team_leader.id])],
|
||||||
|
"default_project_id": cls.project.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
cls.empty_team = cls.env["helpdesk.ticket.team"].create(
|
||||||
|
{"name": "Empty Team"}
|
||||||
|
)
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
# Assign default teams to users
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
cls.portal_user.write(
|
||||||
|
{"default_helpdesk_ticket_team_id": cls.team_with_leader.id}
|
||||||
|
)
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
# Create a partner linked to the portal user
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
cls.portal_partner = cls.env["res.partner"].create(
|
||||||
|
{
|
||||||
|
"name": "Portal Partner",
|
||||||
|
"email": "portal@test.com",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
cls.portal_user.write({"partner_id": cls.portal_partner.id})
|
||||||
|
|
||||||
|
# Partner for user without default team
|
||||||
|
cls.no_team_partner = cls.env["res.partner"].create(
|
||||||
|
{
|
||||||
|
"name": "No Team Partner",
|
||||||
|
"email": "noteam@test.com",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
cls.user_no_team.write({"partner_id": cls.no_team_partner.id})
|
||||||
|
|
||||||
|
# Partner without any linked user
|
||||||
|
cls.orphan_partner = cls.env["res.partner"].create(
|
||||||
|
{"name": "Orphan Partner", "email": "orphan@test.com"}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Convenience models
|
||||||
|
cls.HelpdeskTicket = cls.env["helpdesk.ticket"]
|
||||||
|
cls.HelpdeskTeam = cls.env["helpdesk.ticket.team"]
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
# _define_user_id tests
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
|
||||||
|
def test_define_user_id_no_team(self):
|
||||||
|
"""Without a team, _define_user_id returns the current user_id unchanged."""
|
||||||
|
ticket = self.HelpdeskTicket.create(
|
||||||
|
{"name": "No team ticket", "description": "test"}
|
||||||
|
)
|
||||||
|
result = ticket._define_user_id(team_id=None, ticket_user_id=self.team_member)
|
||||||
|
self.assertEqual(result, self.team_member)
|
||||||
|
|
||||||
|
def test_define_user_id_no_ticket_user(self):
|
||||||
|
"""With a team but no current user, returns the team leader."""
|
||||||
|
ticket = self.HelpdeskTicket.create(
|
||||||
|
{"name": "Test ticket", "description": "test"}
|
||||||
|
)
|
||||||
|
result = ticket._define_user_id(
|
||||||
|
team_id=self.team_with_leader, ticket_user_id=None
|
||||||
|
)
|
||||||
|
self.assertEqual(result, self.team_leader)
|
||||||
|
|
||||||
|
def test_define_user_id_user_not_in_team(self):
|
||||||
|
"""When the current user is not in the team, returns the team leader."""
|
||||||
|
ticket = self.HelpdeskTicket.create(
|
||||||
|
{"name": "Test ticket", "description": "test"}
|
||||||
|
)
|
||||||
|
# team_with_leader has team_leader and team_member; user_no_team is not in it
|
||||||
|
result = ticket._define_user_id(
|
||||||
|
team_id=self.team_with_leader, ticket_user_id=self.user_no_team
|
||||||
|
)
|
||||||
|
self.assertEqual(result, self.team_leader)
|
||||||
|
|
||||||
|
def test_define_user_id_user_in_team(self):
|
||||||
|
"""When the current user is a team member, they are kept unchanged."""
|
||||||
|
ticket = self.HelpdeskTicket.create(
|
||||||
|
{"name": "Test ticket", "description": "test"}
|
||||||
|
)
|
||||||
|
result = ticket._define_user_id(
|
||||||
|
team_id=self.team_with_leader, ticket_user_id=self.team_member
|
||||||
|
)
|
||||||
|
self.assertEqual(result, self.team_member)
|
||||||
|
|
||||||
|
def test_define_user_id_team_no_leader(self):
|
||||||
|
"""When the team has no leader, the current user_id is returned unchanged."""
|
||||||
|
ticket = self.HelpdeskTicket.create(
|
||||||
|
{"name": "Test ticket", "description": "test"}
|
||||||
|
)
|
||||||
|
# team_no_leader has no user_id (team leader)
|
||||||
|
result = ticket._define_user_id(
|
||||||
|
team_id=self.team_no_leader, ticket_user_id=self.team_member
|
||||||
|
)
|
||||||
|
self.assertEqual(result, self.team_member)
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
# create() auto-assignment tests
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
|
||||||
|
def test_create_with_partner_default_team(self):
|
||||||
|
"""Creating a ticket with a partner whose user has a default team
|
||||||
|
automatically sets the team_id."""
|
||||||
|
ticket = self.HelpdeskTicket.create(
|
||||||
|
{
|
||||||
|
"name": "Auto team ticket",
|
||||||
|
"description": "test",
|
||||||
|
"partner_id": self.portal_partner.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
ticket.team_id,
|
||||||
|
self.team_with_leader,
|
||||||
|
"Team should be auto-assigned from the portal user's default team",
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_create_with_partner_default_team_and_project(self):
|
||||||
|
"""When the default team has a default_project_id, the ticket gets it."""
|
||||||
|
# Give portal_user a default team that has a project
|
||||||
|
self.portal_user.write(
|
||||||
|
{"default_helpdesk_ticket_team_id": self.team_with_project.id}
|
||||||
|
)
|
||||||
|
ticket = self.HelpdeskTicket.create(
|
||||||
|
{
|
||||||
|
"name": "Auto team+project ticket",
|
||||||
|
"description": "test",
|
||||||
|
"partner_id": self.portal_partner.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self.assertEqual(ticket.team_id, self.team_with_project)
|
||||||
|
self.assertEqual(
|
||||||
|
ticket.project_id,
|
||||||
|
self.project,
|
||||||
|
"Project should be auto-assigned from the team's default project",
|
||||||
|
)
|
||||||
|
# Reset portal_user default team for other tests
|
||||||
|
self.portal_user.write(
|
||||||
|
{"default_helpdesk_ticket_team_id": self.team_with_leader.id}
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_create_with_partner_no_default_team(self):
|
||||||
|
"""Creating a ticket with a partner whose user has no default team
|
||||||
|
does not set a team."""
|
||||||
|
ticket = self.HelpdeskTicket.create(
|
||||||
|
{
|
||||||
|
"name": "No default team ticket",
|
||||||
|
"description": "test",
|
||||||
|
"partner_id": self.no_team_partner.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self.assertFalse(
|
||||||
|
ticket.team_id,
|
||||||
|
"Team should not be set if the user has no default team",
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_create_with_explicit_team(self):
|
||||||
|
"""When a team_id is explicitly provided, it is not overridden."""
|
||||||
|
ticket = self.HelpdeskTicket.create(
|
||||||
|
{
|
||||||
|
"name": "Explicit team ticket",
|
||||||
|
"description": "test",
|
||||||
|
"partner_id": self.portal_partner.id,
|
||||||
|
"team_id": self.team_no_leader.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
ticket.team_id,
|
||||||
|
self.team_no_leader,
|
||||||
|
"Explicitly provided team should not be overridden",
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_create_without_partner(self):
|
||||||
|
"""Creating a ticket without a partner does not trigger auto-assignment."""
|
||||||
|
ticket = self.HelpdeskTicket.create(
|
||||||
|
{"name": "No partner ticket", "description": "test"}
|
||||||
|
)
|
||||||
|
self.assertFalse(
|
||||||
|
ticket.team_id,
|
||||||
|
"Team should not be auto-assigned when there is no partner",
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_create_partner_without_user(self):
|
||||||
|
"""Creating a ticket with a partner that has no linked user
|
||||||
|
does not crash and does not set a team."""
|
||||||
|
ticket = self.HelpdeskTicket.create(
|
||||||
|
{
|
||||||
|
"name": "Orphan partner ticket",
|
||||||
|
"description": "test",
|
||||||
|
"partner_id": self.orphan_partner.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self.assertFalse(
|
||||||
|
ticket.team_id,
|
||||||
|
"Team should not be set when partner has no linked user",
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_create_multi_vals_list(self):
|
||||||
|
"""create() with a vals_list processes each ticket independently."""
|
||||||
|
tickets = self.HelpdeskTicket.create(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "Batch ticket 1",
|
||||||
|
"description": "test",
|
||||||
|
"partner_id": self.portal_partner.id,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Batch ticket 2",
|
||||||
|
"description": "test",
|
||||||
|
"partner_id": self.no_team_partner.id,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Batch ticket 3",
|
||||||
|
"description": "test",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
)
|
||||||
|
self.assertEqual(len(tickets), 3)
|
||||||
|
# First ticket: portal user with default team
|
||||||
|
self.assertEqual(
|
||||||
|
tickets[0].team_id,
|
||||||
|
self.team_with_leader,
|
||||||
|
"First batch ticket should get the default team",
|
||||||
|
)
|
||||||
|
# Second ticket: user without default team
|
||||||
|
self.assertFalse(
|
||||||
|
tickets[1].team_id,
|
||||||
|
"Second batch ticket should have no team",
|
||||||
|
)
|
||||||
|
# Third ticket: no partner at all
|
||||||
|
self.assertFalse(
|
||||||
|
tickets[2].team_id,
|
||||||
|
"Third batch ticket should have no team",
|
||||||
|
)
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
# _compute_user_id tests (depends on team_id)
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
|
||||||
|
def test_compute_user_id_team_change_replaces(self):
|
||||||
|
"""When team_id changes to a team where the current user is not a member,
|
||||||
|
user_id is replaced by the new team's leader."""
|
||||||
|
ticket = self.HelpdeskTicket.create(
|
||||||
|
{
|
||||||
|
"name": "Team change ticket",
|
||||||
|
"description": "test",
|
||||||
|
"user_id": self.user_no_team.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
# user_no_team is not in team_with_leader members
|
||||||
|
ticket.team_id = self.team_with_leader
|
||||||
|
ticket._compute_user_id()
|
||||||
|
self.assertEqual(
|
||||||
|
ticket.user_id,
|
||||||
|
self.team_leader,
|
||||||
|
"User should be replaced by the new team's leader",
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_compute_user_id_team_change_kept(self):
|
||||||
|
"""When team_id changes to a team where the current user is a member,
|
||||||
|
user_id is kept unchanged."""
|
||||||
|
ticket = self.HelpdeskTicket.create(
|
||||||
|
{
|
||||||
|
"name": "Team kept ticket",
|
||||||
|
"description": "test",
|
||||||
|
"user_id": self.team_member.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
# team_member is in team_with_leader members
|
||||||
|
ticket.team_id = self.team_with_leader
|
||||||
|
ticket._compute_user_id()
|
||||||
|
self.assertEqual(
|
||||||
|
ticket.user_id,
|
||||||
|
self.team_member,
|
||||||
|
"User should stay unchanged when they belong to the new team",
|
||||||
|
)
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
# Integration test
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
|
||||||
|
def test_full_creation_flow(self):
|
||||||
|
"""Full flow: portal user creates a ticket → default team + project + user
|
||||||
|
are all set correctly."""
|
||||||
|
self.portal_user.write(
|
||||||
|
{"default_helpdesk_ticket_team_id": self.team_with_project.id}
|
||||||
|
)
|
||||||
|
ticket = self.HelpdeskTicket.create(
|
||||||
|
{
|
||||||
|
"name": "Full flow ticket",
|
||||||
|
"description": "test",
|
||||||
|
"partner_id": self.portal_partner.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
# Team auto-assigned from portal user's default
|
||||||
|
self.assertEqual(ticket.team_id, self.team_with_project)
|
||||||
|
# Project auto-assigned from team's default project
|
||||||
|
self.assertEqual(ticket.project_id, self.project)
|
||||||
|
# User auto-assigned to team leader (since no user was provided)
|
||||||
|
self.assertEqual(ticket.user_id, self.team_leader)
|
||||||
|
# Reset
|
||||||
|
self.portal_user.write(
|
||||||
|
{"default_helpdesk_ticket_team_id": self.team_with_leader.id}
|
||||||
|
)
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
# res.users field test
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
|
||||||
|
def test_user_default_team_field(self):
|
||||||
|
"""The default_helpdesk_ticket_team_id field exists on res.users."""
|
||||||
|
self.assertIn(
|
||||||
|
"default_helpdesk_ticket_team_id",
|
||||||
|
self.env["res.users"]._fields,
|
||||||
|
"Field default_helpdesk_ticket_team_id must exist on res.users",
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
self.portal_user.default_helpdesk_ticket_team_id,
|
||||||
|
self.team_with_leader,
|
||||||
|
)
|
||||||
|
self.assertFalse(
|
||||||
|
self.user_no_team.default_helpdesk_ticket_team_id,
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user