Browse Source

July 20: [ADD] Initial commit 'odoo_website_helpdesk'

pull/331/head
RisvanaCybro 9 months ago
parent
commit
afe0d38587
  1. 44
      odoo_website_helpdesk/README.rst
  2. 23
      odoo_website_helpdesk/__init__.py
  3. 76
      odoo_website_helpdesk/__manifest__.py
  4. 27
      odoo_website_helpdesk/controllers/__init__.py
  5. 162
      odoo_website_helpdesk/controllers/odoo_website_helpdesk.py
  6. 111
      odoo_website_helpdesk/controllers/portal.py
  7. 80
      odoo_website_helpdesk/controllers/ticket_group_by.py
  8. 45
      odoo_website_helpdesk/controllers/ticket_search.py
  9. 151
      odoo_website_helpdesk/controllers/website_form.py
  10. 71
      odoo_website_helpdesk/controllers/website_ticket.py
  11. 13
      odoo_website_helpdesk/data/helpdesk_category_data.xml
  12. 55
      odoo_website_helpdesk/data/helpdesk_replay_template_data.xml
  13. 21
      odoo_website_helpdesk/data/helpdesk_type_data.xml
  14. 16
      odoo_website_helpdesk/data/ir_cron_data.xml
  15. 23
      odoo_website_helpdesk/data/ir_sequence_data.xml
  16. 213
      odoo_website_helpdesk/data/mail_template_data.xml
  17. 39
      odoo_website_helpdesk/data/ticket_stage_data.xml
  18. 7
      odoo_website_helpdesk/doc/RELEASE_NOTES.md
  19. 34
      odoo_website_helpdesk/models/__init__.py
  20. 30
      odoo_website_helpdesk/models/account_move.py
  21. 32
      odoo_website_helpdesk/models/helpdesk_category.py
  22. 30
      odoo_website_helpdesk/models/helpdesk_tag.py
  23. 30
      odoo_website_helpdesk/models/helpdesk_type.py
  24. 42
      odoo_website_helpdesk/models/mail_compose_message.py
  25. 111
      odoo_website_helpdesk/models/merge_ticket.py
  26. 32
      odoo_website_helpdesk/models/project_task.py
  27. 94
      odoo_website_helpdesk/models/res_config_settings.py
  28. 40
      odoo_website_helpdesk/models/support_ticket.py
  29. 59
      odoo_website_helpdesk/models/team_helpdesk.py
  30. 391
      odoo_website_helpdesk/models/ticket_helpdesk.py
  31. 66
      odoo_website_helpdesk/models/ticket_stage.py
  32. 39
      odoo_website_helpdesk/models/website_menu.py
  33. 114
      odoo_website_helpdesk/report/helpdesk_ticket_report_template.xml
  34. 24
      odoo_website_helpdesk/security/ir.model.access.csv
  35. 38
      odoo_website_helpdesk/security/odoo_website_helpdesk_groups.xml
  36. 85
      odoo_website_helpdesk/security/odoo_website_helpdesk_security.xml
  37. 1
      odoo_website_helpdesk/static/description/1608951_ticket_icon.svg
  38. BIN
      odoo_website_helpdesk/static/description/assets/icons/check.png
  39. BIN
      odoo_website_helpdesk/static/description/assets/icons/chevron.png
  40. BIN
      odoo_website_helpdesk/static/description/assets/icons/cogs.png
  41. BIN
      odoo_website_helpdesk/static/description/assets/icons/consultation.png
  42. BIN
      odoo_website_helpdesk/static/description/assets/icons/ecom-black.png
  43. BIN
      odoo_website_helpdesk/static/description/assets/icons/education-black.png
  44. BIN
      odoo_website_helpdesk/static/description/assets/icons/hotel-black.png
  45. BIN
      odoo_website_helpdesk/static/description/assets/icons/license.png
  46. BIN
      odoo_website_helpdesk/static/description/assets/icons/lifebuoy.png
  47. BIN
      odoo_website_helpdesk/static/description/assets/icons/logo.png
  48. BIN
      odoo_website_helpdesk/static/description/assets/icons/manufacturing-black.png
  49. BIN
      odoo_website_helpdesk/static/description/assets/icons/pos-black.png
  50. BIN
      odoo_website_helpdesk/static/description/assets/icons/puzzle.png
  51. BIN
      odoo_website_helpdesk/static/description/assets/icons/restaurant-black.png
  52. BIN
      odoo_website_helpdesk/static/description/assets/icons/service-black.png
  53. BIN
      odoo_website_helpdesk/static/description/assets/icons/trading-black.png
  54. BIN
      odoo_website_helpdesk/static/description/assets/icons/training.png
  55. BIN
      odoo_website_helpdesk/static/description/assets/icons/update.png
  56. BIN
      odoo_website_helpdesk/static/description/assets/icons/user.png
  57. BIN
      odoo_website_helpdesk/static/description/assets/icons/wrench.png
  58. BIN
      odoo_website_helpdesk/static/description/assets/misc/Cybrosys R.png
  59. BIN
      odoo_website_helpdesk/static/description/assets/misc/categories.png
  60. BIN
      odoo_website_helpdesk/static/description/assets/misc/check-box.png
  61. BIN
      odoo_website_helpdesk/static/description/assets/misc/compass.png
  62. BIN
      odoo_website_helpdesk/static/description/assets/misc/corporate.png
  63. BIN
      odoo_website_helpdesk/static/description/assets/misc/customer-support.png
  64. BIN
      odoo_website_helpdesk/static/description/assets/misc/cybrosys-logo.png
  65. BIN
      odoo_website_helpdesk/static/description/assets/misc/features.png
  66. BIN
      odoo_website_helpdesk/static/description/assets/misc/logo.png
  67. BIN
      odoo_website_helpdesk/static/description/assets/misc/pictures.png
  68. BIN
      odoo_website_helpdesk/static/description/assets/misc/pie-chart.png
  69. BIN
      odoo_website_helpdesk/static/description/assets/misc/right-arrow.png
  70. BIN
      odoo_website_helpdesk/static/description/assets/misc/star.png
  71. BIN
      odoo_website_helpdesk/static/description/assets/misc/support.png
  72. BIN
      odoo_website_helpdesk/static/description/assets/misc/whatsapp.png
  73. BIN
      odoo_website_helpdesk/static/description/assets/modules/1.png
  74. BIN
      odoo_website_helpdesk/static/description/assets/modules/2.jpg
  75. BIN
      odoo_website_helpdesk/static/description/assets/modules/3.jpg
  76. BIN
      odoo_website_helpdesk/static/description/assets/modules/4.jpg
  77. BIN
      odoo_website_helpdesk/static/description/assets/modules/5.jpg
  78. BIN
      odoo_website_helpdesk/static/description/assets/modules/6.png
  79. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/1.png
  80. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/10.png
  81. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/11.png
  82. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/12.png
  83. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/13.png
  84. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/14.png
  85. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/15.png
  86. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/16.png
  87. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/17.png
  88. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/18.png
  89. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/19.png
  90. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/2.png
  91. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/20.png
  92. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/21.png
  93. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/22.png
  94. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/23.png
  95. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/24.png
  96. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/25.png
  97. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/26.png
  98. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/27.png
  99. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/28.png
  100. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/29.png

44
odoo_website_helpdesk/README.rst

@ -0,0 +1,44 @@
.. image:: https://img.shields.io/badge/license-LGPL--3-green.svg
:target: https://www.gnu.org/licenses/lgpl-3.0-standalone.html
:alt: License: LGPL-3
Website Helpdesk Support Ticket Management
==========================================
- HelpDesk Support for Odoo 17 community edition
Installation
============
- www.odoo.com/documentation/17.0/setup/install.html
- Install our custom addon
License
-------
General Public License, Version 3 (LGPL v3).
(https://www.odoo.com/documentation/user/17.0/legal/licenses/licenses.html)
Company
-------
* `Cybrosys Techno Solutions <https://cybrosys.com/>`__
Credits
-------
* Developer (V17): Dhanya Babu @ cybrosys, odoo@cybrosys.com
Contacts
--------
* Mail Contact : odoo@cybrosys.com
Bug Tracker
-----------
Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported.
Maintainer
==========
.. image:: https://cybrosys.com/images/logo.png
:target: https://cybrosys.com
For support and more information, please visit https://www.cybrosys.com
Further information
===================
HTML Description: `<static/description/index.html>`__

23
odoo_website_helpdesk/__init__.py

@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Dhanya B (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
from . import controllers
from . import models

76
odoo_website_helpdesk/__manifest__.py

@ -0,0 +1,76 @@
# -*- coding: utf-8 -*-
############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Dhanya B (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
############################################################################
{
'name': "Website Helpdesk Support Ticket Management",
'version': '17.0.1.0.0',
'category': 'Website',
'summary': """The website allows for the creation of tickets, which can
then be controlled from the backend. Furthermore, a bill that includes
the service charge can be generated for the ticket for odoo community
Edition version 17.""",
'description': """A ticket can be created from the website and subsequently
managed from the backend. Additionally, a bill can be generated for the
ticket, which includes the service cost.""",
'author': "Cybrosys Techno Solutions",
'company': 'Cybrosys Techno Solutions',
'maintainer': 'Cybrosys Techno Solutions',
'depends': ['website', 'project', 'sale_project', 'hr_timesheet',
'mail', 'contacts'],
'data': [
'security/odoo_website_helpdesk_groups.xml',
'security/odoo_website_helpdesk_security.xml',
'security/ir.model.access.csv',
'data/helpdesk_category_data.xml',
'data/helpdesk_replay_template_data.xml',
'data/helpdesk_type_data.xml',
'data/ir_cron_data.xml',
'data/ir_sequence_data.xml',
'data/mail_template_data.xml',
'data/ticket_stage_data.xml',
'views/helpdesk_category_views.xml',
'views/helpdesk_tag_views.xml',
'views/helpdesk_type_views.xml',
'views/merge_ticket_views.xml',
'views/odoo_website_helpdesk_portal_templates.xml',
'views/portal_templates.xml',
'views/rating_form.xml',
'report/helpdesk_ticket_report_template.xml',
'views/res_config_settings_views.xml',
'views/team_helpdesk_views.xml',
'views/ticket_helpdesk_views.xml',
'views/ticket_stage_views.xml',
'views/website_form.xml',
'views/helpdesk_views.xml',
],
'assets': {
'web.assets_frontend': [
'odoo_website_helpdesk/static/src/js/ticket_details.js',
'/odoo_website_helpdesk/static/src/js/portal_search.js',
'/odoo_website_helpdesk/static/src/js/multiple_product_choose.js',
]
},
'images': ['static/description/banner.jpg'],
'license': 'LGPL-3',
'installable': True,
'auto_install': False,
'application': False,
}

27
odoo_website_helpdesk/controllers/__init__.py

@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Dhanya Babu (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from . import odoo_website_helpdesk
from . import portal
from . import ticket_group_by
from . import ticket_search
from . import website_form
from . import website_ticket

162
odoo_website_helpdesk/controllers/odoo_website_helpdesk.py

@ -0,0 +1,162 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Dhanya Babu (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import datetime as DT
from odoo import http
from odoo.http import request
class HelpDeskDashboard(http.Controller):
"""Controller for handling Help Desk dashboard requests."""
@http.route(['/helpdesk_dashboard'], type='json', auth="public")
def helpdesk_dashboard(self):
"""Retrieves statistics for tickets in different stages.
Returns:dict: Dashboard statistics including counts and IDs for each
stage.
"""
stage_names = ['Inbox', 'Draft', 'In Progress', 'Canceled', 'Done',
'Closed']
stage_ids = {
name: request.env['ticket.stage'].search([('name', '=', name)],
limit=1).id for name in
stage_names}
new_stages = [stage_ids['Inbox'], stage_ids['Draft']]
def get_ticket_data(stage_ids):
tickets = request.env["ticket.helpdesk"].search(
[('stage_id', 'in', stage_ids)])
return len(tickets), [ticket.id for ticket in tickets]
dashboard_values = {
'new': (get_ticket_data(new_stages))[0],
'new_id': (get_ticket_data(new_stages))[1],
'in_progress': (get_ticket_data([stage_ids['In Progress']]))[0],
'in_progress_id': (get_ticket_data([stage_ids['In Progress']]))[1],
'canceled': (get_ticket_data([stage_ids['Canceled']]))[0],
'canceled_id': (get_ticket_data([stage_ids['Canceled']]))[1],
'done': (get_ticket_data([stage_ids['Done']]))[0],
'done_id': (get_ticket_data([stage_ids['Done']]))[1],
'closed': (get_ticket_data([stage_ids['Closed']]))[0],
'closed_id': (get_ticket_data([stage_ids['Closed']]))[1]}
return dashboard_values
def helpdesk_dashboard_week(self):
""" Retrieves statistics for tickets created in the past week.
Returns:
dict: Dashboard statistics including counts and IDs for each stage."""
today = DT.date.today()
week_ago = str(today - DT.timedelta(days=7)) + ' '
stage_names = ['Inbox', 'Draft', 'In Progress', 'Canceled', 'Done',
'Closed']
stages = {
name: request.env['ticket.stage'].search([('name', '=', name)],
limit=1).id for name in
stage_names}
stage_ids = [stages['Inbox'], stages['Draft']]
def get_ticket_data(stage_id):
count = request.env["ticket.helpdesk"].search_count(
[('stage_id', '=', stage_id), ('create_date', '>', week_ago)])
ids = request.env["ticket.helpdesk"].search(
[('stage_id', '=', stage_id),
('create_date', '>', week_ago)]).ids
return count, ids
new_count, new_ids = get_ticket_data(stage_ids)
in_progress_count, in_progress_ids = get_ticket_data(
stages['In Progress'])
canceled_count, canceled_ids = get_ticket_data(stages['Canceled'])
done_count, done_ids = get_ticket_data(stages['Done'])
closed_count, closed_ids = get_ticket_data(stages['Closed'])
dashboard_values = {
'new': new_count,
'in_progress': in_progress_count,
'canceled': canceled_count,
'done': done_count,
'closed': closed_count,
'new_id': new_ids,
'in_progress_id': in_progress_ids,
'canceled_id': canceled_ids,
'done_id': done_ids,
'closed_id': closed_ids,
}
return dashboard_values
@http.route(['/helpdesk_dashboard_month'], type='json', auth="public")
def helpdesk_dashboard_month(self):
"""Retrieves statistics for tickets created in the past month.
Returns:
dict: Dashboard statistics including counts and IDs for each stage."""
today = DT.date.today()
month_ago = today - DT.timedelta(days=30)
week_ago = str(month_ago) + ' '
stages = request.env['ticket.stage'].search([('name', 'in',
['Inbox', 'Draft',
'In Progress',
'Canceled', 'Done',
'Closed'])])
stage_ids = {stage.name: stage.id for stage in stages}
def get_stage_data(stage_names):
stage_ids_list = [stage_ids[name] for name in stage_names]
tickets = request.env["ticket.helpdesk"].search(
[('stage_id', 'in', stage_ids_list),
('create_date', '>', week_ago)])
return len(tickets), [ticket.id for ticket in tickets]
new_count, new_ids = get_stage_data(['Inbox', 'Draft'])
in_progress_count, in_progress_ids = get_stage_data(['In Progress'])
canceled_count, canceled_ids = get_stage_data(['Canceled'])
done_count, done_ids = get_stage_data(['Done'])
closed_count, closed_ids = get_stage_data(['Closed'])
dashboard_values = {
'new': new_count,
'in_progress': in_progress_count,
'canceled': canceled_count,
'done': done_count,
'closed': closed_count,
'new_id': new_ids,
'in_progress_id': in_progress_ids,
'canceled_id': canceled_ids,
'done_id': done_ids,
'closed_id': closed_ids,
}
return dashboard_values
@http.route(['/helpdesk_dashboard_year'], type='json', auth="public")
def helpdesk_dashboard_year(self):
"""Retrieves statistics for tickets created in the past year.
Returns:
dict: Dashboard statistics including counts and IDs for each stage.
"""
today = DT.date.today()
year_ago = today - DT.timedelta(days=360)
stages = ['Inbox', 'Draft', 'In Progress', 'Canceled', 'Done', 'Closed']
stage_ids = {
stage: request.env['ticket.stage'].search([('name', '=', stage)],
limit=1).id for stage in
stages}
def get_ticket_data(stage_name):
stage_id = stage_ids[stage_name]
tickets = request.env["ticket.helpdesk"].search(
[('stage_id', '=', stage_id), ('create_date', '>', year_ago)])
return len(tickets), [ticket.id for ticket in tickets]
dashboard_values = {}
for stage in stages:
count, ids = get_ticket_data(stage)
dashboard_values[stage.lower()] = count
dashboard_values[f'{stage.lower()}_id'] = ids
return dashboard_values

111
odoo_website_helpdesk/controllers/portal.py

@ -0,0 +1,111 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Dhanya Babu (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from odoo import http
from odoo.addons.portal.controllers import portal
from odoo.http import request
class TicketPortal(portal.CustomerPortal):
def _prepare_home_portal_values(self, counters):
"""
Prepare values for the home portal, including ticket count. Args:
counters (dict): A dictionary containing counters for various portal
information. Returns: dict: A dictionary of values for the home portal.
"""
values = super()._prepare_home_portal_values(counters)
if 'ticket_count' in counters:
ticket_count = request.env['ticket.helpdesk'].search_count(
self._get_tickets_domain()) if request.env[
'ticket.helpdesk'].check_access_rights(
'read', raise_exception=False) else 0
values['ticket_count'] = ticket_count
return values
def _get_tickets_domain(self):
"""
Define the domain for searching tickets related to the current customer.
Returns:
list: A list representing the domain for ticket search.
"""
return [('customer_id', '=', request.env.user.partner_id.id)]
@http.route(['/my/tickets'], type='http', auth="user", website=True)
def portal_my_tickets(self):
"""
Route to display the tickets associated with the current customer.
Returns:
http.Response: The HTTP response rendering the tickets page.
"""
domain = self._get_tickets_domain()
tickets = request.env['ticket.helpdesk'].sudo().search(domain)
values = {
'default_url': "/my/tickets",
'tickets': tickets,
'page_name': 'ticket',
}
return request.render("odoo_website_helpdesk.portal_my_tickets",
values)
@http.route(['/my/tickets/<int:id>'], type='http', auth="public",
website=True)
def portal_tickets_details(self, **kwargs):
"""
Route to display the details of a specific ticket.
Args:
ticket_id (int): The ID of the ticket to be displayed.
Returns:
http.Response: The HTTP response rendering the ticket details page.
"""
ticket_id = kwargs.get("id")
details = request.env['ticket.helpdesk'].sudo().browse(ticket_id)
data = {
'page_name': 'ticket',
'ticket': True,
'details': details,
}
return request.render("odoo_website_helpdesk.portal_ticket_details",
data)
@http.route('/my/tickets/download/<id>', auth='public',
type='http',
website=True)
def ticket_download_portal(self, **kwargs):
"""
Route to download a PDF version of a specific ticket.
Args:
ticket (str): The ID of the ticket to be downloaded.
Returns:
http.Response: The HTTP response with the PDF file for download.
"""
ticket_id = int(kwargs.get('id'))
data = {
'help': request.env['ticket.helpdesk'].sudo().browse(ticket_id)}
report = request.env.ref(
'odoo_website_helpdesk.report_ticket')
pdf, _ = report.sudo()._render_qweb_pdf(
report, res_ids=ticket_id, data=data)
pdf_http_headers = [('Content-Type', 'application/pdf'),
('Content-Length', len(pdf)),
('Content-Disposition',
'attachment; filename="Helpdesk Ticket.pdf"')]
return request.make_response(pdf, headers=pdf_http_headers)

80
odoo_website_helpdesk/controllers/ticket_group_by.py

@ -0,0 +1,80 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Dhanya Babu (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from odoo import http
from odoo.http import request
class TicketGroupBy(http.Controller):
"""Controller for handling ticket grouping based on different criteria."""
@http.route(['/ticketgroupby'], type='json', auth="public", website=True)
def ticket_group_by(self, **kwargs):
"""grouping tickets based on user-defined criteria.
Args:
- kwargs (dict): Keyword arguments received from the HTTP request.
Returns:
- http.Response: Rendered HTTP response containing grouped ticket information.
"""
context = []
group_value = kwargs.get("search_value")
if group_value == '0':
context = []
tickets = request.env["ticket.helpdesk"].search(
[('user_id', '=', request.env.user.id)])
if tickets:
context.append({
'name': '',
'data': tickets
})
if group_value == '1':
context = []
stage_ids = request.env['ticket.stage'].search([])
for stage in stage_ids:
ticket_ids = request.env['ticket.helpdesk'].search([
('stage_id', '=', stage.id),
('user_id', '=', request.env.user.id)
])
if ticket_ids:
context.append({
'name': stage.name,
'data': ticket_ids
})
if group_value == '2':
context = []
type_ids = request.env['helpdesk.type'].search([])
for types in type_ids:
ticket_ids_1 = request.env['ticket.helpdesk'].search([
('ticket_type_id', '=', types.id),
('user_id', '=', request.env.user.id)
])
if ticket_ids_1:
context.append({
'name': types.name,
'data': ticket_ids_1
})
values = {
'tickets': context,
}
response = http.Response(
template='odoo_website_helpdesk.ticket_group_by_table',
qcontext=values)
return response.render()

45
odoo_website_helpdesk/controllers/ticket_search.py

@ -0,0 +1,45 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Dhanya Babu (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from odoo import http
from odoo.http import request
class TicketSearch(http.Controller):
@http.route(['/ticketsearch'], type='json', auth="public", website=True)
def ticket_search(self, **kwargs):
"""
Search for tickets based on the provided search value.
:param search_value: The value to search for in the ticket name or subject.
:type search_value: str
:return: A JSON response containing the matching tickets.
:rtype: http.Response
"""
search_value = kwargs.get("search_value")
tickets = request.env["ticket.helpdesk"].search(
['|', ('name', 'ilike', search_value),
('subject', 'ilike', search_value)])
values = {
'tickets': tickets,
}
response = http.Response(template='odoo_website_helpdesk.ticket_table',
qcontext=values)
return response.render()

151
odoo_website_helpdesk/controllers/website_form.py

@ -0,0 +1,151 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Dhanya Babu (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import base64
import json
from psycopg2 import IntegrityError
from odoo import http, _
from odoo.http import request
from odoo.exceptions import ValidationError
from odoo.addons.website.controllers.form import WebsiteForm
class HelpdeskProduct(http.Controller):
""" Controller for handling helpdesk products.
"""
@http.route('/product', auth='public', type='json')
def product(self):
prols = []
acc = request.env['product.template'].sudo().search([])
for i in acc:
dic = {'name': i['name'],
'id': i['id']}
prols.append(dic)
return prols
class WebsiteFormInherit(WebsiteForm):
def _handle_website_form(self, model_name, **kwargs):
"""
Handle the submission of website forms.
:param model_name: The name of the model associated with the form.
:type model_name: str
:param kwargs: Keyword arguments containing form data.
:type kwargs: dict
:return: JSON response indicating the success or failure of form submission.
:rtype: str
"""
customer = request.env.user.partner_id
lowest_stage_id = None
if model_name == 'ticket.helpdesk':
tickets = request.env['ticket.stage'].sudo().search([])
if tickets:
sequence = tickets.mapped('sequence')
lowest_sequence = tickets.filtered(
lambda x: x.sequence == min(sequence))
if lowest_sequence:
lowest_stage_id = lowest_sequence[0]
if lowest_stage_id is None:
return json.dumps(
{'error': "No stage found with the lowest sequence."})
products = kwargs.get('product')
if products:
split_product = products.split(',')
product_list = [int(i) for i in split_product]
rec_val = {
'customer_name': kwargs.get('customer_name'),
'subject': kwargs.get('subject'),
'description': kwargs.get('description'),
'email': kwargs.get('email_from'),
'phone': kwargs.get('phone'),
'priority': kwargs.get('priority'),
'product_ids': product_list,
'stage_id': lowest_stage_id.id,
'customer_id': customer.id,
'ticket_type_id': kwargs.get('ticket_type_id'),
'category_id': kwargs.get('category'),
}
else:
rec_val = {
'customer_name': kwargs.get('customer_name'),
'subject': kwargs.get('subject'),
'description': kwargs.get('description'),
'email': kwargs.get('email_from'),
'phone': kwargs.get('phone'),
'priority': kwargs.get('priority'),
'stage_id': lowest_stage_id.id,
'customer_id': customer.id,
'ticket_type_id': kwargs.get('ticket_type_id'),
'category_id': kwargs.get('category'),
}
ticket_id = request.env['ticket.helpdesk'].sudo().create(rec_val)
request.session['ticket_number'] = ticket_id.name
request.session['ticket_id'] = ticket_id.id
model_record = request.env['ir.model'].sudo().search(
[('model', '=', model_name)])
attachments = []
attachment_index = 0
while f"ticket_attachment[0][{attachment_index}]" in kwargs:
attachment_key = f"ticket_attachment[0][{attachment_index}]"
if attachment_key in kwargs:
attachment = kwargs[attachment_key]
attachments.append(attachment)
attachment_index += 1
for attachment in attachments:
attached_file = attachment.read()
request.env['ir.attachment'].sudo().create({
'name': attachment.filename,
'res_model': 'ticket.helpdesk',
'res_id': ticket_id.id,
'type': 'binary',
'datas': base64.encodebytes(attached_file),
})
request.session['form_builder_model_model'] = model_record.model
request.session['form_builder_model'] = model_record.name
request.session['form_builder_id'] = ticket_id.id
return json.dumps({'id': ticket_id.id})
else:
model_record = request.env['ir.model'].sudo().search(
[('model', '=', model_name)])
if not model_record:
return json.dumps(
{'error': _("The form's specified model does not exist")})
try:
data = self.extract_data(model_record, request.params)
except ValidationError as e:
return json.dumps({'error_fields': e.args[0]})
try:
id_record = self.insert_record(request, model_record,
data['record'], data['custom'],
data.get('meta'))
if id_record:
self.insert_attachment(model_record, id_record,
data['attachments'])
if model_name == 'mail.mail':
request.env[model_name].sudo().browse(id_record).send()
except IntegrityError:
return json.dumps(False)
request.session['form_builder_model_model'] = model_record.model
request.session['form_builder_model'] = model_record.name
request.session['form_builder_id'] = id_record
return json.dumps({'id': id_record})

71
odoo_website_helpdesk/controllers/website_ticket.py

@ -0,0 +1,71 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Dhanya Babu (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from odoo import http
from odoo.http import request
class WebsiteDesk(http.Controller):
@http.route(['/helpdesk_ticket'], type='http', auth="public", website=True,
sitemap=True)
def helpdesk_ticket(self, **kwargs):
"""
Route to display the helpdesk ticket creation form.
Returns:
http.Response: The HTTP response rendering the helpdesk ticket form.
"""
types = request.env['helpdesk.type'].sudo().search([])
categories = request.env['helpdesk.category'].sudo().search([])
product = request.env['product.template'].sudo().search([])
values = {}
values.update({
'types': types,
'categories': categories,
'product_website': product
})
return request.render('odoo_website_helpdesk.ticket_form', values)
@http.route(['/rating/<int:ticket_id>'], type='http', auth="public",
website=True,
sitemap=True)
def rating(self, ticket_id):
"""
Route to display the rating form for a specific ticket. Args:
ticket_id (int): The ID of the ticket for which the rating form is
displayed. Returns: http.Response: The HTTP response rendering the
rating form.
"""
ticket = request.env['ticket.helpdesk'].browse(ticket_id)
data = {
'ticket': ticket.id,
}
return request.render('odoo_website_helpdesk.rating_form', data)
@http.route(['/rating/<int:ticket_id>/submit'], type='http', auth="user",
website=True, csrf=False,
sitemap=True)
def rating_backend(self, ticket_id, **post):
ticket = request.env['ticket.helpdesk'].browse(ticket_id)
ticket.write({
'customer_rating': post['rating'],
'review': post['message'],
})
return request.render('odoo_website_helpdesk.rating_thanks')

13
odoo_website_helpdesk/data/helpdesk_category_data.xml

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<!-- Record for a helpdesk ticket category representing internal tickets.-->
<record id="ticket_categories_1" model="helpdesk.category">
<field name="name">Internal</field>
</record>
<!-- Record for a helpdesk ticket category representing technical tickets.-->
<record id="ticket_categories_2" model="helpdesk.category">
<field name="name">Technical</field>
</record>
</data>
</odoo>

55
odoo_website_helpdesk/data/helpdesk_replay_template_data.xml

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!-- Helpdesk Replay mail template -->
<record id="helpdesk_replay_email_template" model="mail.template">
<field name="name">Helpdesk Reply Email Template</field>
<field name="model_id"
ref="odoo_website_helpdesk.model_ticket_helpdesk"/>
<field name="auto_delete" eval="True"/>
<field name="subject">{{ object.name }} Replay</field>
<field name="body_html" type="html">
<div class="container">
<h4 style="text-align:center">Helpdesk Replay</h4>
<div style="min-height:30vh;">message........</div>
<t t-set="base_url"
t-value="request.env['ir.config_parameter'].sudo().get_param('web.base.url')"/>
<h6>
<a t-attf-href="{{base_url}}/my/tickets/{{object.id}}"
class="btn btn-primary">View Ticket
</a>
</h6>
<table class="table table-light" width="100%">
<tbody>
<tr>
<th>Name</th>
<td>
<t t-if="object.assigned_user_id">
<t t-esc="object.assigned_user_id.name"/>
</t>
<t t-else="">username</t>
<t t-esc="base_url"/>
</td>
</tr>
<tr>
<th>Team name</th>
<td>
<t t-if="object.team_id">
<t t-esc="object.team_id.name"/>
</t>
<t t-else="">Team name</t>
</td>
</tr>
<tr>
<th>Replied On</th>
<td>
<t t-set="date"
t-value="(datetime.date.today())"/>
<t t-esc="date"/>
</td>
</tr>
</tbody>
</table>
</div>
</field>
</record>
</odoo>

21
odoo_website_helpdesk/data/helpdesk_type_data.xml

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<!-- Record for a helpdesk ticket type representing a general question.-->
<record id="ticket_type_1" model="helpdesk.type">
<field name="name">Question</field>
</record>
<!-- Record for a helpdesk ticket type representing an issue.-->
<record id="ticket_type_2" model="helpdesk.type">
<field name="name">Issue</field>
</record>
<!-- Record for a helpdesk ticket type representing a repair request.-->
<record id="ticket_type_3" model="helpdesk.type">
<field name="name">Repair</field>
</record>
<!-- Record for a helpdesk ticket type representing a maintenance request.-->
<record id="ticket_type_4" model="helpdesk.type">
<field name="name">Maintenance</field>
</record>
</data>
</odoo>

16
odoo_website_helpdesk/data/ir_cron_data.xml

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<data noupdate="1">
<!-- Scheduled task (cron job) for automatically closing tickets-->
<record id="auto_close_ticket" model="ir.cron">
<field name="name">Auto Close Ticket</field>
<field name="model_id" ref="odoo_website_helpdesk.model_ticket_helpdesk"/>
<field name="state">code</field>
<field name="code">model.auto_close_ticket()</field>
<field name="user_id" ref="base.user_root"/>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
</record>
</data>
</odoo>

23
odoo_website_helpdesk/data/ir_sequence_data.xml

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<data noupdate="1">
<!-- Define a sequence for help tickets -->
<record id="sequence_help_ticket_seq" model="ir.sequence">
<field name="name">Helpdesk</field>
<field name="code">ticket.helpdesk</field>
<field name="prefix">TKT</field>
<field name="padding">5</field>
<field eval="1" name="number_increment"/>
<field eval="False" name="company_id"/>
</record>
<!-- Define a sequence for help ticket invoices -->
<record id="sequence_help_ticket_inv_seq" model="ir.sequence">
<field name="name">Helpdesk Invoice</field>
<field name="code">ticket.invoice</field>
<field name="prefix">INV/TKT/%(year)s/</field>
<field name="padding">3</field>
<field eval="1" name="number_increment"/>
<field eval="False" name="company_id"/>
</record>
</data>
</odoo>

213
odoo_website_helpdesk/data/mail_template_data.xml

@ -0,0 +1,213 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<data noupdate="1">
<!-- Mail Template for notifying customers about the creation of a ticket.-->
<record id="ticket_created" model="mail.template">
<field name="name">Create Ticket</field>
<field name="model_id" ref="odoo_website_helpdesk.model_ticket_helpdesk"/>
<field name="auto_delete" eval="True"/>
<field name="email_to">{{object.customer_id.email}}</field>
<field name="subject">Ticket Created</field>
<field name="body_html" type="html">
<p>
Dear
<t t-out="object.customer_id.name"/>
<br/>
Your Ticket
<t t-out="object.name"/>
is Created and Assigned. Kindly Wait while we're resolving your Query
<br/>
<br/>
Thanks.
</p>
</field>
</record>
<!-- Mail Template for notifying customers about the closure of a ticket and prompting them for feedback.-->
<record id="helpdesk_rating" model="mail.template">
<field name="name">Close Ticket And Feedback</field>
<field name="model_id"
ref="odoo_website_helpdesk.model_ticket_helpdesk"/>
<field name="auto_delete" eval="True"/>
<field name="email_to">{{object.customer_id.email}}</field>
<field name="subject">Ticket Closed</field>
<field name="body_html" type="html">
<p>
Dear
<t t-out="object.customer_id.name"/>
Your Ticket
<t t-out="object.name"/>
Is Closed
<br/>
<button class="btn btn-info" role="button"
style="border:1px solid black;background-color:purple;padding-x:20px;padding-y:15px;border-radius:10px; width:120px;">
<a t-attf-href="/rating/{{object.id}}"
style="text-decoration:none;color:white;font-weight:bold;font-size:18px;">
Rate Now
</a>
</button>
<br/>
<br/>
Thanks.
</p>
</field>
</record>
<!-- Mail Template for notifying customers about the reopening of a ticket.-->
<record id="ticket_reopened" model="mail.template">
<field name="name">Reopened Ticket</field>
<field name="model_id"
ref="odoo_website_helpdesk.model_ticket_helpdesk"/>
<field name="auto_delete" eval="True"/>
<field name="email_to">{{object.customer_id.email}}</field>
<field name="subject">Ticket Reopened</field>
<field name="body_html" type="html">
<p>
Dear
<t t-out="object.customer_id.name"/>
<br/>
Your Ticket
<t t-out="object.name"/>
is Reopened
<br/>
<br/>
Thanks.
</p>
</field>
</record>
<!-- Mail Template for notifying customers about the approval and resolution of a ticket.-->
<record id="ticket_approved" model="mail.template">
<field name="name">Approve Ticket</field>
<field name="model_id"
ref="odoo_website_helpdesk.model_ticket_helpdesk"/>
<field name="auto_delete" eval="True"/>
<field name="email_to">{{object.customer_id.email}}</field>
<field name="subject">Ticket Solved</field>
<field name="body_html" type="html">
<p>
Dear
<t t-out="object.customer_id.name"/>
<br/>
i think your Problem is Solved.
Your Ticket
<t t-out="object.name"/>
is Done
<br/>
<br/>
Thanks.
</p>
</field>
</record>
<!-- An email template for notifying customers about the cancellation-->
<!-- of a ticket.-->
<record id="ticket_canceled" model="mail.template">
<field name="name">Cancel Ticket</field>
<field name="model_id"
ref="odoo_website_helpdesk.model_ticket_helpdesk"/>
<field name="auto_delete" eval="True"/>
<field name="email_to">{{object.customer_id.email}}</field>
<field name="subject">Ticket Canceled</field>
<field name="body_html" type="html">
<p>
Dear
<t t-out="object.customer_id.name"/>
<br/>
Your Ticket
<t t-out="object.name"/>
is Canceled Due to Some Reasons
<br/>
<br/>
Thanks.
</p>
</field>
</record>
<!-- This XML record defines an email template for notifying the team head about the assignment of a ticket.-->
<!-- The template is associated with the "mail.template" model and is designed to be triggered when a ticket-->
<!-- is assigned to a specific team.-->
<record id="odoo_website_helpdesk_assign"
model="mail.template">
<field name="name">Ticket Assign</field>
<field name="email_from"/>
<field name="email_to"/>
<field name="subject"/>
<field name="model_id"
ref="odoo_website_helpdesk.model_ticket_helpdesk"/>
<field name="body_html" type="html">
<div style="margin: 0px; padding: 0px;">
<p>Dear,
<t t-esc="object.team_head_id.name"/>
</p>
<p>Your team has been given the ticket [<t t-esc="object.name"/>] kindly complete your work
carefully.
</p>
<br/>
<h2>Details</h2>
<p>Subject :
<t t-esc="object.subject"/>
</p>
<p>Customer :
<t t-esc="object.customer_id.name"/>
</p>
<p>Description :
<t t-esc="object.description"/>
</p>
<br/>
<p>Best regards</p>
</div>
</field>
</record>
<!-- An email template for notifying an assigned user about the assignment of a ticket.-->
<record id="odoo_website_helpdesk_assign_user"
model="mail.template">
<field name="name">Ticket Assign to User</field>
<field name="email_from"/>
<field name="email_to"/>
<field name="subject"/>
<field name="model_id"
ref="odoo_website_helpdesk.model_ticket_helpdesk"/>
<field name="body_html" type="html">
<div style="margin: 0px; padding: 0px;">
<p>Dear,
<t t-esc="object.assigned_user_id.name"/>
</p>
<p>Ticket [<t t-esc="object.name"/>] Assign to you , kindly complete your work carefully.
</p>
<br/>
<h2>Details</h2>
<p>Subject :
<t t-esc="object.subject"/>
</p>
<p>Customer :
<t t-esc="object.customer_id.name"/>
</p>
<p>Description :
<t t-esc="object.description"/>
</p>
<br/>
<p>Best regards</p>
</div>
</field>
</record>
<!-- This record defines an email template for notifying a customer about the assignment of a helpdesk ticket to a user.-->
<record id="odoo_website_helpdesk_to_customer"
model="mail.template">
<field name="name">Mail To Customer Assign to User</field>
<field name="email_from"/>
<field name="email_to"/>
<field name="subject"/>
<field name="model_id"
ref="odoo_website_helpdesk.model_ticket_helpdesk"/>
<field name="body_html" type="html">
<div style="margin: 0px; padding: 0px;">
<p>Dear,
<t t-esc="object.customer_id.name"/>
</p>
<p>Ticket [<t t-esc="object.name"/>] successfully assigned to "<t
t-esc="object.assigned_user_id.name"/>".
</p>
<br/>
<p>Best regards</p>
</div>
</field>
</record>
</data>
</odoo>

39
odoo_website_helpdesk/data/ticket_stage_data.xml

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<!-- Project Stages -->
<!-- - stage_inbox: Initial stage where tickets are received.-->
<record id="stage_inbox" model="ticket.stage">
<field name="sequence">10</field>
<field name="name">Inbox</field>
</record>
<!-- - stage_draft: Tickets in the drafting phase.-->
<record id="stage_draft" model="ticket.stage">
<field name="sequence">15</field>
<field name="name">Draft</field>
</record>
<!-- - stage_done: Final stage indicating completion.-->
<record id="stage_done" model="ticket.stage">
<field name="sequence">25</field>
<field name="name">Done</field>
</record>
<!-- - stage_in_progress: Tickets actively being worked on.-->
<record id="stage_in_progress" model="ticket.stage">
<field name="sequence">20</field>
<field name="starting_stage" eval="True"/>
<field name="name">In Progress</field>
</record>
<!-- - stage_closed: Closing stage for resolved tickets.-->
<record id="stage_closed" model="ticket.stage">
<field name="sequence">30</field>
<field name="closing_stage">True</field>
<field name="name">Closed</field>
</record>
<!-- - stage_canceled: Stage for canceled or invalidated tickets.-->
<record id="stage_canceled" model="ticket.stage">
<field name="sequence">35</field>
<field name="cancel_stage">True</field>
<field name="name">Canceled</field>
</record>
</data>
</odoo>

7
odoo_website_helpdesk/doc/RELEASE_NOTES.md

@ -0,0 +1,7 @@
## Module <odoo_website_helpdesk>
#### 18.07.2024
#### Version 17.0.1.0.0
#### ADD
- Initial commit for Website Helpdesk Support Ticket Management

34
odoo_website_helpdesk/models/__init__.py

@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Dhanya Babu (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from . import account_move
from . import helpdesk_category
from . import helpdesk_tag
from . import helpdesk_type
from . import mail_compose_message
from . import merge_ticket
from . import project_task
from . import res_config_settings
from . import support_ticket
from . import team_helpdesk
from . import ticket_helpdesk
from . import ticket_stage
from . import website_menu

30
odoo_website_helpdesk/models/account_move.py

@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Dhanya Babu (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from odoo import fields, models
class AccountMove(models.Model):
"""Inheriting the account.move model"""
_inherit = 'account.move'
ticket_id = fields.Many2one('ticket.helpdesk',
string='Ticket', help='ID of the ticket.')

32
odoo_website_helpdesk/models/helpdesk_category.py

@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Dhanya B (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
#############################################################################
from odoo import fields, models
class HelpdeskCategory(models.Model):
"""Category Model"""
_name = 'helpdesk.category'
_description = 'Categories'
name = fields.Char('Name', help='Category name of the helpdesk')
sequence = fields.Integer('Sequence', default=0,
help='Sequence of the helpdesk category')

30
odoo_website_helpdesk/models/helpdesk_tag.py

@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Dhanya Babu (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from odoo import fields, models
class HelpdeskTag(models.Model):
"""Helpdesk tags"""
_name = 'helpdesk.tag'
_description = 'Helpdesk Tags'
name = fields.Char(string='Tag', help='Tag name of the helpdesk.')

30
odoo_website_helpdesk/models/helpdesk_type.py

@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Dhanya Babu (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from odoo import fields, models
class HelpdeskType(models.Model):
"""Helpdesk type """
_name = 'helpdesk.type'
_description = 'Helpdesk Type'
name = fields.Char(string='Type', help='Types of help desk.')

42
odoo_website_helpdesk/models/mail_compose_message.py

@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Dhanya Babu (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from odoo import fields, models
class MailComposeMessage(models.TransientModel):
"""Inheriting the Mail compose message"""
_inherit = 'mail.compose.message'
def _action_send_mail(self, auto_commit=False):
"""Send mail function"""
if self.model == 'ticket.helpdesk':
try:
res_ids_list = eval(self.res_ids)
if not isinstance(res_ids_list, list):
raise ValueError("Invalid format for res_ids")
except Exception as e:
raise ValueError(
"Error converting res_ids to list: {}".format(e))
ticket_ids = self.env['ticket.helpdesk'].browse(res_ids_list)
ticket_ids.replied_date = fields.Date.today()
return super(MailComposeMessage, self)._action_send_mail(
auto_commit=auto_commit)

111
odoo_website_helpdesk/models/merge_ticket.py

@ -0,0 +1,111 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Dhanya Babu (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from odoo import api, fields, models
class MergeTicket(models.Model):
"""Tickets merging class"""
_name = 'merge.ticket'
_description = 'Merging the selected tickets'
_rec_name = 'support_ticket_id'
user_id = fields.Many2one('res.partner',
string='Responsible User',
help='User name of responsible person.',
default=lambda self: self.env.user.partner_id.id)
support_team_id = fields.Many2one('team.helpdesk',
string='Support Team',
help='Name of the support team.')
customer_id = fields.Many2one('res.partner', string='Customer',
help='Name of the Customer ')
support_ticket_id = fields.Many2one('ticket.helpdesk',
string='Support Ticket',
help="Name of the support ticket")
new_ticket = fields.Boolean(string='Create New Ticket ?',
help='Creating new tickets or not.',
default=False)
subject = fields.Char(string='Subject', help='Enter the New Ticket Subject')
merge_reason = fields.Char(string='Merge Reason',
help='Reason for Merging the tickets. ')
support_ticket_ids = fields.One2many('support.ticket',
'support_ticket_id',
string='Support Tickets',
help='Merged tickets')
active = fields.Boolean(string='Disable Record', help='Disable Record',
default=True)
def default_get(self, fields_list):
"""Override the default_get method to provide default values for fields
when creating a new record."""
defaults = super(MergeTicket, self).default_get(fields_list)
active_ids = self._context.get('active_ids', [])
selected_tickets = self.env['ticket.helpdesk'].browse(active_ids)
customer_ids = selected_tickets.mapped('customer_id')
subjects = selected_tickets.mapped('subject')
display_names = selected_tickets.mapped('display_name')
helpdesk_team = selected_tickets.mapped('team_id')
descriptions = selected_tickets.mapped('description')
if len(customer_ids):
defaults.update({
'customer_id': customer_ids[0].id,
'support_team_id': helpdesk_team,
'support_ticket_ids': [(0, 0, {
'subject': subject,
'display_name': display_name,
'description': description,
}) for subject, display_name, description in
zip(subjects, display_names,
descriptions)]
})
return defaults
def action_merge_ticket(self):
"""Merging the tickets or creating new tickets"""
if self.new_ticket:
description = "\n\n".join(
f"{ticket.subject}\n{'-' * len(ticket.subject)}\n{ticket.description}"
for ticket in self.support_ticket_ids
)
self.env['ticket.helpdesk'].create({
'subject': self.subject,
'description': description,
'customer_id': self.customer_id.id,
'team_id': self.support_team_id.id,
})
else:
if len(self.support_ticket_ids):
description = "\n\n".join(
f"{ticket.subject}\n{'-' * len(ticket.subject)}\n{ticket.description}"
for ticket in self.support_ticket_ids
)
self.support_ticket_id.write({
'description': description,
'merge_ticket_invisible': True,
'merge_count': len(self.support_ticket_ids),
})
@api.onchange('support_ticket_id')
def _onchange_support_ticket_id(self):
"""Onchange function to add the support ticket id."""
self.support_ticket_ids.write({
'merged_ticket': self.support_ticket_id
})

32
odoo_website_helpdesk/models/project_task.py

@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Dhanya Babu (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from odoo import fields, models
class ProjectTask(models.Model):
"""Inheriting the project task"""
_inherit = 'project.task'
ticket_id = fields.Many2one('ticket.helpdesk', string='Ticket',
help='ID of the ticket .')
ticket_billed = fields.Boolean('Billed', default=False,
help='Billed Tickets')

94
odoo_website_helpdesk/models/res_config_settings.py

@ -0,0 +1,94 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Dhanya Babu (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from odoo import api, fields, models
class ResConfigSettings(models.TransientModel):
"""Inheriting the res config settings model"""
_inherit = 'res.config.settings'
show_create_task = fields.Boolean(string="Create Tasks",
config_parameter='odoo_website_helpdesk.show_create_task',
help='Enable this option to allow users'
'to create tasks directly from the '
'helpdesk module. When activated, users '
'will have the ability to generate and '
'assign tasks as part of their workflow '
'within the helpdesk interface.')
show_category = fields.Boolean(string="Category",
config_parameter='odoo_website_helpdesk.show_category',
help='Enable this option to display the '
'category field in the helpdesk tickets. '
'This can be useful for organizing and '
'filtering tickets based on their category.',
implied_group='odoo_website_helpdesk.group_show_category')
product_website = fields.Boolean(string="Product On Website",
config_parameter='odoo_website_helpdesk.product_website',
help='Product on website')
auto_close_ticket = fields.Boolean(string="Auto Close Ticket",
config_parameter='odoo_website_helpdesk.auto_close_ticket',
help='Auto Close ticket')
no_of_days = fields.Integer(string="No Of Days",
config_parameter='odoo_website_helpdesk.no_of_days',
help='No of Days')
closed_stage_id = fields.Many2one(
'ticket.stage', string='Closing stage',
help='Closing Stage of the ticket.',
config_parameter='odoo_website_helpdesk.closed_stage_id')
reply_template_id = fields.Many2one('mail.template',
domain="[('model', '=', 'ticket.helpdesk')]",
config_parameter='odoo_website_helpdesk.reply_template_id',
help='Reply Template of the helpdesk'
' ticket.')
helpdesk_menu_show = fields.Boolean('Helpdesk Menu',
config_parameter=
'odoo_website_helpdesk.helpdesk_menu_show',
help='Helpdesk menu')
@api.onchange('closed_stage_id')
def _onchange_closed_stage_id(self):
"""Closing stage function"""
if self.closed_stage_id:
stage = self.closed_stage_id.id
in_stage = self.env['ticket.stage'].search([('id', '=', stage)])
not_in_stage = self.env['ticket.stage'].search(
[('id', '!=', stage)])
in_stage.closing_stage = True
for each in not_in_stage:
each.closing_stage = False
@api.constrains('show_category')
def _constrains_show_category_subcategory(self):
"""Show category and the sub category"""
if self.show_category:
group_cat = self.env.ref(
'odoo_website_helpdesk.group_show_category')
group_cat.write({
'users': [(4, self.env.user.id)]
})
else:
group_cat = self.env.ref(
'odoo_website_helpdesk.group_show_category')
group_cat.write({
'users': [(5, False)]
})

40
odoo_website_helpdesk/models/support_ticket.py

@ -0,0 +1,40 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Dhanya Babu (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from odoo import fields, models
class SupportTicket(models.Model):
"""Creating onetoMany model"""
_name = 'support.ticket'
_description = 'Support Tickets'
subject = fields.Char(string='Subject', help='Subject of the merged '
'tickets.')
display_name = fields.Char(string='Display Name',
help='Display name of the merged tickets.')
description = fields.Char(string='Description',
help='Description of the tickets.')
support_ticket_id = fields.Many2one('merge.ticket',
string='Support Tickets',
help='Support tickets')
merged_ticket = fields.Integer(string='Merged Ticket ID',
help='Storing merged ticket id')

59
odoo_website_helpdesk/models/team_helpdesk.py

@ -0,0 +1,59 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Dhanya Babu (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from odoo import api, fields, models
class TeamHelpDesk(models.Model):
"""Helpdesk team"""
_name = 'team.helpdesk'
_description = 'Helpdesk Team'
name = fields.Char('Name', help='Helpdesk Team Name')
team_lead_id = fields.Many2one('res.users', string='Team Leader',
help='Team Leader Name',
domain=lambda self: [
('groups_id', 'in', self.env.ref(
'odoo_website_helpdesk.helpdesk_team_leader').id)])
member_ids = fields.Many2many('res.users', string='Members',
help='Team Members',
domain=lambda self: [
('groups_id', 'in', self.env.ref(
'odoo_website_helpdesk.helpdesk_user').id)])
email = fields.Char('Email', help='Email of the team member.')
project_id = fields.Many2one('project.project',
string='Project',
help='Projects related helpdesk team.')
create_task = fields.Boolean(string="Create Task",
help="Task created or not")
@api.onchange('team_lead_id')
def _onchange_team_lead_id(self):
"""Members selection function"""
fetch_members = self.env['res.users'].search([])
filtered_members = fetch_members.filtered(
lambda x: x.id != self.team_lead_id.id)
return {'domain': {'member_ids':
[('id', '=', filtered_members.ids), (
'groups_id', 'in',
self.env.ref('base.group_user').id),
('groups_id', 'not in', self.env.ref(
'odoo_website_helpdesk.helpdesk_team_leader').id)]}}

391
odoo_website_helpdesk/models/ticket_helpdesk.py

@ -0,0 +1,391 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Dhanya B (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import logging
from odoo import api, fields, models, _
from odoo.exceptions import UserError
from odoo.exceptions import ValidationError
_logger = logging.getLogger(__name__)
PRIORITIES = [
('0', 'Very Low'),
('1', 'Low'),
('2', 'Normal'),
('3', 'High'),
('4', 'Very High'),
]
RATING = [
('0', 'Very Low'),
('1', 'Low'),
('2', 'Normal'),
('3', 'High'),
('4', 'Very High'),
('5', 'Extreme High')
]
class TicketHelpDesk(models.Model):
"""Help_ticket model"""
_name = 'ticket.helpdesk'
_description = 'Helpdesk Ticket'
_inherit = ['mail.thread', 'mail.activity.mixin']
def _default_show_create_task(self):
"""Task creation"""
return self.env['ir.config_parameter'].sudo().get_param(
'odoo_website_helpdesk.show_create_task')
def _default_show_category(self):
"""Show category default"""
return self.env['ir.config_parameter'].sudo().get_param(
'odoo_website_helpdesk.show_category')
name = fields.Char('Name', default=lambda self: self.env['ir.sequence'].
next_by_code('ticket.helpdesk') or _('New'),
help='Ticket Name')
customer_id = fields.Many2one('res.partner',
string='Customer Name',
help='Customer Name')
customer_name = fields.Char('Customer Name', help='Customer Name')
subject = fields.Text('Subject', required=True,
help='Subject of the Ticket')
description = fields.Text('Description', required=True,
help='Description')
email = fields.Char('Email', help='Email')
phone = fields.Char('Phone', help='Contact Number')
team_id = fields.Many2one('team.helpdesk', string='Helpdesk Team',
help='Helpdesk Team Name')
product_ids = fields.Many2many('product.template',
string='Product',
help='Product Name')
project_id = fields.Many2one('project.project',
string='Project',
readonly=False,
related='team_id.project_id',
store=True,
help='Project Name')
priority = fields.Selection(PRIORITIES, default='1', help='Priority of the'
' Ticket')
stage_id = fields.Many2one('ticket.stage', string='Stage',
default=lambda self: self.env[
'ticket.stage'].search(
[('name', '=', 'Draft')], limit=1).id,
tracking=True,
group_expand='_read_group_stage_ids',
help='Stages')
user_id = fields.Many2one('res.users',
default=lambda self: self.env.user,
check_company=True,
index=True, tracking=True,
help='Login User', string='User')
cost = fields.Float('Cost per hour', help='Cost Per Unit')
service_product_id = fields.Many2one('product.product',
string='Service Product',
help='Service Product',
domain=[
('detailed_type', '=', 'service')])
create_date = fields.Datetime('Creation Date', help='Created date')
start_date = fields.Datetime('Start Date', help='Start Date')
end_date = fields.Datetime('End Date', help='End Date')
public_ticket = fields.Boolean(string="Public Ticket",
help='Public Ticket')
invoice_ids = fields.Many2many('account.move',
string='Invoices',
help='Invoicing id'
)
task_ids = fields.Many2many('project.task',
string='Tasks',
help='Task id')
color = fields.Integer(string="Color", help='Color')
replied_date = fields.Datetime('Replied date', help='Replied Date')
last_update_date = fields.Datetime('Last Update Date',
help='Last Update Date')
ticket_type_id = fields.Many2one('helpdesk.type',
string='Ticket Type', help='Ticket Type')
team_head_id = fields.Many2one('res.users', string='Team Leader',
compute='_compute_team_head_id',
help='Team Leader Name')
assigned_user_id = fields.Many2one('res.users', string='Assigned User',
domain=lambda self: [('groups_id', 'in',
self.env.ref(
'odoo_website_helpdesk.helpdesk_user').id)],
help='Assigned User Name')
category_id = fields.Many2one('helpdesk.category', string='Category',
help='Category')
tags_ids = fields.Many2many('helpdesk.tag', help='Tags', string='Tags')
assign_user = fields.Boolean(default=False, help='Assign User',
string='Assign User')
attachment_ids = fields.One2many('ir.attachment', 'res_id',
help='Attachment Line',
string='Attachments')
merge_ticket_invisible = fields.Boolean(string='Merge Ticket',
help='Merge Ticket Invisible or '
'Not', default=False)
merge_count = fields.Integer(string='Merge Count', help='Merged Tickets '
'Count')
active = fields.Boolean(default=True, help='Active', string='Active')
show_create_task = fields.Boolean(string="Show Create Task",
help='Show created task or not',
default=_default_show_create_task,
compute='_compute_show_create_task')
create_task = fields.Boolean(string="Create Task", readonly=False,
help='Create task or not',
related='team_id.create_task', store=True)
billable = fields.Boolean(string="Billable", default=False,
help='Is billable or not', )
show_category = fields.Boolean(default=_default_show_category,
string="Show Category",
help='Show category or not',
compute='_compute_show_category')
customer_rating = fields.Selection(RATING, default='0', readonly=True)
review = fields.Char('Review', readonly=True, help='Ticket review')
kanban_state = fields.Selection([
('normal', 'Ready'),
('done', 'In Progress'),
('blocked', 'Blocked'), ], default='normal')
@api.onchange('team_id', 'team_head_id')
def _onchange_team_id(self):
"""Changing the team leader when selecting the team"""
li = self.team_id.member_ids.mapped(id)
return {'domain': {'assigned_user_id': [('id', 'in', li)]}}
@api.depends('team_id')
def _compute_team_head_id(self):
"""Compute the team head function"""
self.team_head_id = self.team_id.team_lead_id.id
@api.onchange('stage_id')
def _onchange_stage_id(self):
"""Sending mail to the user function"""
rec_id = self._origin.id
data = self.env['ticket.helpdesk'].search([('id', '=', rec_id)])
data.last_update_date = fields.Datetime.now()
if self.stage_id.starting_stage:
data.start_date = fields.Datetime.now()
if self.stage_id.closing_stage or self.stage_id.cancel_stage:
data.end_date = fields.Datetime.now()
if self.stage_id.template_id:
mail_template = self.stage_id.template_id
mail_template.send_mail(self._origin.id, force_send=True)
def assign_to_teamleader(self):
"""Assigning team leader function"""
if self.team_id:
self.team_head_id = self.team_id.team_lead_id.id
mail_template = self.env.ref(
'odoo_website_helpdesk.odoo_website_helpdesk_assign')
mail_template.sudo().write({
'email_to': self.team_head_id.email,
'subject': self.name
})
mail_template.sudo().send_mail(self.id, force_send=True)
else:
raise ValidationError("Please choose a Helpdesk Team")
def _compute_show_category(self):
"""Compute show category"""
show_category = self._default_show_category()
for rec in self:
rec.show_category = show_category
def _compute_show_create_task(self):
"""Compute the created task"""
show_create_task = self._default_show_create_task()
for record in self:
record.show_create_task = show_create_task
def auto_close_ticket(self):
"""Automatically closing the ticket"""
auto_close = self.env['ir.config_parameter'].sudo().get_param(
'odoo_website_helpdesk.auto_close_ticket')
if auto_close:
no_of_days = self.env['ir.config_parameter'].sudo().get_param(
'odoo_website_helpdesk.no_of_days')
records = self.env['ticket.helpdesk'].search([])
for rec in records:
days = (fields.Datetime.today() - rec.create_date).days
if days >= int(no_of_days):
close_stage_id = self.env['ticket.stage'].search(
[('closing_stage', '=', True)])
if close_stage_id:
rec.stage_id = close_stage_id
def default_stage_id(self):
"""Method to return the default stage"""
return self.env['ticket.stage'].search(
[('name', '=', 'Draft')], limit=1).id
@api.model
def _read_group_stage_ids(self, stages, domain, order):
"""
return the stages to stage_ids
"""
stage_ids = self.env['ticket.stage'].search([])
return stage_ids
@api.model_create_multi
def create(self, vals_list):
"""Create function"""
for vals in vals_list:
if vals.get('name', _('New')) == _('New'):
vals['name'] = self.env['ir.sequence'].next_by_code(
'ticket.helpdesk')
return super(TicketHelpDesk, self).create(vals_list)
def write(self, vals):
"""Write function"""
result = super(TicketHelpDesk, self).write(vals)
return result
def action_create_invoice(self):
"""Create Invoice based on the ticket"""
tasks = self.env['project.task'].search(
[('project_id', '=', self.project_id.id),
('ticket_id', '=', self.id)]).filtered(
lambda line: not line.ticket_billed)
if not tasks:
raise UserError('No Tasks to Bill')
total = sum(x.effective_hours for x in tasks if
x.effective_hours > 0 and not x.some_flag)
invoice_no = self.env['ir.sequence'].next_by_code(
'ticket.invoice')
self.env['account.move'].create([
{
'name': invoice_no,
'move_type': 'out_invoice',
'partner_id': self.customer_id.id,
'ticket_id': self.id,
'date': fields.Date.today(),
'invoice_date': fields.Date.today(),
'invoice_line_ids': [(0, 0,
{
'product_id': self.service_product_id.id,
'name': self.service_product_id.name,
'quantity': total,
'product_uom_id': self.service_product_id.uom_id.id,
'price_unit': self.cost,
'account_id': self.service_product_id.categ_id.property_account_income_categ_id.id,
})],
}, ])
for task in tasks:
task.ticket_billed = True
return {
'effect': {
'fadeout': 'medium',
'message': 'Billed Successfully!',
'type': 'rainbow_man',
}
}
def action_create_tasks(self):
"""Task creation"""
task_id = self.env['project.task'].create({
'name': self.name + '-' + self.subject,
'project_id': self.project_id.id,
'company_id': self.env.company.id,
'ticket_id': self.id,
})
self.write({
'task_ids': [(4, task_id.id)]
})
return {
'name': 'Tasks',
'res_model': 'project.task',
'view_id': False,
'res_id': task_id.id,
'view_mode': 'form',
'type': 'ir.actions.act_window',
'target': 'new',
}
def action_open_tasks(self):
"""View the Created task """
return {
'name': 'Tasks',
'domain': [('ticket_id', '=', self.id)],
'res_model': 'project.task',
'view_id': False,
'view_mode': 'tree,form',
'type': 'ir.actions.act_window',
}
def action_open_invoices(self):
"""View the Created invoice"""
return {
'name': 'Invoice',
'domain': [('ticket_id', '=', self.id)],
'res_model': 'account.move',
'view_id': False,
'view_mode': 'tree,form',
'type': 'ir.actions.act_window',
}
def action_open_merged_tickets(self):
"""Open the merged tickets tree view"""
ticket_ids = self.env['support.ticket'].search(
[('merged_ticket', '=', self.id)])
helpdesk_ticket_ids = ticket_ids.mapped('display_name')
help_ticket_records = self.env['ticket.helpdesk'].search(
[('name', 'in', helpdesk_ticket_ids)])
return {
'type': 'ir.actions.act_window',
'name': 'Helpdesk Ticket',
'view_mode': 'tree,form',
'res_model': 'ticket.helpdesk',
'domain': [('id', 'in', help_ticket_records.ids)],
'context': self.env.context,
}
def action_send_reply(self):
"""Action to sent reply button"""
template_id = self.env['ir.config_parameter'].sudo().get_param(
'odoo_website_helpdesk.reply_template_id'
)
template_id = self.env['mail.template'].browse(int(template_id))
if template_id:
return {
'type': 'ir.actions.act_window',
'name': 'mail',
'res_model': 'mail.compose.message',
'view_mode': 'form',
'target': 'new',
'views': [[False, 'form']],
'context': {
'default_model': 'ticket.helpdesk',
'default_res_ids': self.ids,
'default_template_id': template_id.id
}
}
return {
'type': 'ir.actions.act_window',
'name': 'mail',
'res_model': 'mail.compose.message',
'view_mode': 'form',
'target': 'new',
'views': [[False, 'form']],
'context': {
'default_model': 'ticket.helpdesk',
'default_res_ids': self.ids,
}
}

66
odoo_website_helpdesk/models/ticket_stage.py

@ -0,0 +1,66 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Dhanya B (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from odoo import fields, models, _
from odoo.exceptions import UserError
class TicketStage(models.Model):
"""Stage Ticket model """
_name = 'ticket.stage'
_description = 'Ticket Stage'
_order = 'sequence, id'
_fold_name = 'fold'
name = fields.Char('Name', help='Name of the ticket stage')
active = fields.Boolean(string='Active', default=True, help='Active option'
'for ticket '
'stage.')
sequence = fields.Integer(string='Sequence', default=50,
help='Sequence number of the ticket stage.')
closing_stage = fields.Boolean('Closing Stage', default=False,
help='Closing stage of the ticket.')
cancel_stage = fields.Boolean('Cancel Stage', default=False,
help='Cancel stage of the ticket.')
starting_stage = fields.Boolean('Start Stage', default=False,
help='Starting Stage of the ticket.')
folded = fields.Boolean('Folded in Kanban', default=False,
help='Folded Stage of the ticket.')
template_id = fields.Many2one('mail.template',
help='Templates', string='Template',
domain="[('model', '=', 'ticket.helpdesk')]")
group_ids = fields.Many2many('res.groups', help='Group', string='Groups')
fold = fields.Boolean(string='Fold', help='Folded option in ticket.')
def unlink(self):
"""Unlinking Function to unlink the stage"""
for rec in self:
tickets = rec.search([])
sequence = tickets.mapped('sequence')
lowest_sequence = tickets.filtered(
lambda x: x.sequence == min(sequence))
if self.name == "Draft":
raise UserError(_("Cannot Delete This Stage"))
if rec == lowest_sequence:
raise UserError(_("Cannot Delete '%s'" % (rec.name)))
else:
res = super().unlink()
return res

39
odoo_website_helpdesk/models/website_menu.py

@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Dhanya B (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
from odoo import models
class WebsiteMenu(models.Model):
"""Inheriting the website menu"""
_inherit = "website.menu"
def _compute_visible(self):
"""Compute function for to visible the menu based on the boolean
field visibility"""
super()._compute_visible()
show_menu_header = self.env['ir.config_parameter'].sudo().get_param(
'odoo_website_helpdesk.helpdesk_menu_show')
for menu in self:
if menu.name == 'Helpdesk' and not show_menu_header:
menu.is_visible = False
if menu.name == 'Helpdesk' and show_menu_header:
menu.is_visible = True

114
odoo_website_helpdesk/report/helpdesk_ticket_report_template.xml

@ -0,0 +1,114 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!-- Define a Qweb template for the support ticket report -->
<template id="report_helpdesk_ticket">
<t t-call="web.html_container">
<t t-foreach="docs" t-as="o">
<t t-call="web.external_layout">
<div class="page">
<div style="margin-bottom: 10px;">
<div class="text-center"
style="font-weight: 400 !important; font-size: 2rem !important;">
<t t-esc="o.name"/>
-
<t t-esc="o.subject"/>
</div>
<br/>
<table class="table table-bordered mt32">
<thead>
<tr>
<th class="text-center">
<span>Customer</span>
</th>
<th class="text-center">
<span>Description </span>
</th>
<th class="text-center">
<span>Priority </span>
</th>
<th class="text-center">
<span>Products</span>
</th>
</tr>
</thead>
<tbody>
<tr class="text-center">
<td>
<span t-field="o.customer_id"
t-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": True}'/>
</td>
<td>
<span t-field="o.description"/>
</td>
<td>
<span t-field="o.priority"/>
</td>
<td>
<span t-field="o.product_ids"/>
</td>
</tr>
</tbody>
</table>
</div>
<t t-set="tasks"
t-value="request.env['project.task'].search([('ticket_id', '=', o.id)])"/>
<t t-if="tasks">
<div>
<h3 class="text-center">
<strong>Tasks</strong>
</h3>
</div>
<table class="table table-bordered mt32">
<thead>
<tr>
<th class="text-center">
<span>Task Name</span>
</th>
<th class="text-center">
<span>Analytic Account</span>
</th>
<th class="text-center">
<span>Assigned to</span>
</th>
<th class="text-center">
<span>Total Hours Spend</span>
</th>
</tr>
</thead>
<t t-foreach="tasks" t-as="task">
<tbody>
<tr class="text-center">
<td>
<span t-field="task.name"/>
</td>
<td>
<span t-field="task.analytic_account_id"/>
</td>
<td>
<span t-esc="', '.join(map(lambda x: (x.name), task.user_ids))"/>
</td>
<td>
<span t-field="task.effective_hours"/>
</td>
</tr>
</tbody>
</t>
</table>
</t>
</div>
</t>
</t>
</t>
</template>
<!-- Define an action for the Support Ticket report -->
<record id="report_ticket" model="ir.actions.report">
<field name="name">Support Ticket</field>
<field name="model">ticket.helpdesk</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">odoo_website_helpdesk.report_helpdesk_ticket</field>
<field name="report_file">odoo_website_helpdesk.report_helpdesk_ticket</field>
<field name="binding_model_id" ref="model_ticket_helpdesk"/>
<field name="binding_view_types"/>
<field name="binding_type">report</field>
</record>
</odoo>

24
odoo_website_helpdesk/security/ir.model.access.csv

@ -0,0 +1,24 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_help_ticket,access.ticket.helpdesk,model_ticket_helpdesk,,1,1,1,1
access_help_ticket_teams_user,access.team.helpdesk,model_team_helpdesk,odoo_website_helpdesk.helpdesk_user,1,0,0,0
access_help_ticket_teams_leader,access.team.helpdesk,model_team_helpdesk,odoo_website_helpdesk.helpdesk_team_leader,1,0,0,0
access_help_ticket_teams_manager,access.team.helpdesk,model_team_helpdesk,odoo_website_helpdesk.helpdesk_manager,1,1,1,1
access_helpdesk_tag_user,access.helpdesk.tag,model_helpdesk_tag,odoo_website_helpdesk.helpdesk_user,1,0,0,0
access_helpdesk_tag_leader,access.helpdesk.tag,model_helpdesk_tag,odoo_website_helpdesk.helpdesk_team_leader,1,1,1,1
access_helpdesk_tag_manager,access.helpdesk.tag,model_helpdesk_tag,odoo_website_helpdesk.helpdesk_manager,1,1,1,1
access_help_ticket_stage_user,access.ticket.stage,model_ticket_stage,odoo_website_helpdesk.helpdesk_user,1,1,1,1
access_helpdesk_type_user,access.helpdesk.type,model_helpdesk_type,odoo_website_helpdesk.helpdesk_user,1,0,0,0
access_helpdesk_type_leader,access.helpdesk.type,model_helpdesk_type,odoo_website_helpdesk.helpdesk_team_leader,1,1,1,1
access_helpdesk_type_manager,access.helpdesk.type,model_helpdesk_type,odoo_website_helpdesk.helpdesk_manager,1,1,1,1
access_helpdesk_category_user,access_helpdesk_category,model_helpdesk_category,odoo_website_helpdesk.helpdesk_user,1,0,0,0
access_helpdesk_category_leader,access_helpdesk_category,model_helpdesk_category,odoo_website_helpdesk.helpdesk_team_leader,1,1,1,1
access_helpdesk_category_manager,access_helpdesk_category,model_helpdesk_category,odoo_website_helpdesk.helpdesk_manager,1,1,1,1
merge_tickets,merge.ticket,model_merge_ticket,odoo_website_helpdesk.helpdesk_manager,1,1,1,1
support_tickets,support.ticket,model_support_ticket,odoo_website_helpdesk.helpdesk_manager,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_help_ticket access.ticket.helpdesk model_ticket_helpdesk 1 1 1 1
3 access_help_ticket_teams_user access.team.helpdesk model_team_helpdesk odoo_website_helpdesk.helpdesk_user 1 0 0 0
4 access_help_ticket_teams_leader access.team.helpdesk model_team_helpdesk odoo_website_helpdesk.helpdesk_team_leader 1 0 0 0
5 access_help_ticket_teams_manager access.team.helpdesk model_team_helpdesk odoo_website_helpdesk.helpdesk_manager 1 1 1 1
6 access_helpdesk_tag_user access.helpdesk.tag model_helpdesk_tag odoo_website_helpdesk.helpdesk_user 1 0 0 0
7 access_helpdesk_tag_leader access.helpdesk.tag model_helpdesk_tag odoo_website_helpdesk.helpdesk_team_leader 1 1 1 1
8 access_helpdesk_tag_manager access.helpdesk.tag model_helpdesk_tag odoo_website_helpdesk.helpdesk_manager 1 1 1 1
9 access_help_ticket_stage_user access.ticket.stage model_ticket_stage odoo_website_helpdesk.helpdesk_user 1 1 1 1
10 access_helpdesk_type_user access.helpdesk.type model_helpdesk_type odoo_website_helpdesk.helpdesk_user 1 0 0 0
11 access_helpdesk_type_leader access.helpdesk.type model_helpdesk_type odoo_website_helpdesk.helpdesk_team_leader 1 1 1 1
12 access_helpdesk_type_manager access.helpdesk.type model_helpdesk_type odoo_website_helpdesk.helpdesk_manager 1 1 1 1
13 access_helpdesk_category_user access_helpdesk_category model_helpdesk_category odoo_website_helpdesk.helpdesk_user 1 0 0 0
14 access_helpdesk_category_leader access_helpdesk_category model_helpdesk_category odoo_website_helpdesk.helpdesk_team_leader 1 1 1 1
15 access_helpdesk_category_manager access_helpdesk_category model_helpdesk_category odoo_website_helpdesk.helpdesk_manager 1 1 1 1
16 merge_tickets merge.ticket model_merge_ticket odoo_website_helpdesk.helpdesk_manager 1 1 1 1
17 support_tickets support.ticket model_support_ticket odoo_website_helpdesk.helpdesk_manager 1 1 1 1

38
odoo_website_helpdesk/security/odoo_website_helpdesk_groups.xml

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Helpdesk Access Groups Category -->
<record id="module_category_helpdesk" model="ir.module.category">
<field name="name">Helpdesk</field>
<field name="description">Helpdesk Access Groups</field>
<field name="sequence">20</field>
</record>
<!-- Helpdesk User Group -->
<record id="helpdesk_user" model="res.groups">
<field name="name">User</field>
<field name="category_id" ref="odoo_website_helpdesk.module_category_helpdesk"/>
</record>
<!-- Helpdesk Team Leader Group -->
<record id="helpdesk_team_leader" model="res.groups">
<field name="name">Team Leader</field>
<field name="category_id" ref="odoo_website_helpdesk.module_category_helpdesk"/>
<field name="implied_ids" eval="[(4, ref('odoo_website_helpdesk.helpdesk_user'))]"/>
</record>
<!-- Helpdesk Manager Group -->
<record id="helpdesk_manager" model="res.groups">
<field name="name">Manager</field>
<field name="category_id" ref="odoo_website_helpdesk.module_category_helpdesk"/>
<field name="implied_ids" eval="[(4, ref('odoo_website_helpdesk.helpdesk_team_leader'))]"/>
</record>
<!-- Group Show Category -->
<record id="group_show_category" model="res.groups">
<field name="name">group_show_category</field>
</record>
<!-- Group Show Subcategory -->
<record id="group_show_subcategory" model="res.groups">
<field name="name">group_show_subcategory</field>
</record>
<!-- Default User with Helpdesk Manager Group -->
<record id="base.default_user" model="res.users">
<field name="groups_id" eval="[(4,ref('odoo_website_helpdesk.helpdesk_manager'))]"/>
</record>
</odoo>

85
odoo_website_helpdesk/security/odoo_website_helpdesk_security.xml

@ -0,0 +1,85 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Record rule for team leader -->
<record id="help_desk_dashboard_team_leader"
model="ir.rule">
<field name="name">Record Rule for team leader</field>
<field name="model_id" ref="model_ticket_helpdesk"/>
<field name="groups"
eval="[(4, ref('odoo_website_helpdesk.helpdesk_team_leader'))]"/>
<field name="domain_force">['&amp;', ('team_head_id.id', '=', user.id), ('stage_id.group_ids.users', 'in',
user.id)]
</field>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
<field name="perm_unlink" eval="True"/>
</record>
<!-- Record rule for manager -->
<record id="help_desk_dashboard_manager"
model="ir.rule">
<field name="name">Record Rule for manager</field>
<field name="model_id" ref="model_ticket_helpdesk"/>
<field name="groups"
eval="[(4, ref('odoo_website_helpdesk.helpdesk_manager'))]"/>
<field name="domain_force">[(1, '=', 1)]</field>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
<field name="perm_unlink" eval="True"/>
</record>
<!-- Record rule for user -->
<record id="help_desk_dashboard_user"
model="ir.rule">
<field name="name">Record Rule for user</field>
<field ref="model_ticket_helpdesk" name="model_id"/>
<field name="groups"
eval="[(4, ref('odoo_website_helpdesk.helpdesk_user'))]"/>
<field name="domain_force">['&amp;', ('assigned_user_id', '=', user.id), ('stage_id.group_ids.users', 'in',
user.id)]
</field>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
<field name="perm_unlink" eval="True"/>
</record>
<!-- Record rule for stages leader -->
<record id="help_desk_stage_rule_leader"
model="ir.rule">
<field name="name">Record Rule stages leader</field>
<field ref="model_ticket_stage" name="model_id"/>
<field name="groups"
eval="[(4, ref('odoo_website_helpdesk.helpdesk_team_leader'))]"/>
<field name="domain_force">[('group_ids.users', 'in', user.id)]</field>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
<field name="perm_unlink" eval="True"/>
</record>
<!-- Record rule for stages manager -->
<record id="help_desk_stage_rule_manager"
model="ir.rule">
<field name="name">Record Rule stages manager</field>
<field ref="model_ticket_stage" name="model_id"/>
<field name="groups"
eval="[(4, ref('odoo_website_helpdesk.helpdesk_manager'))]"/>
<field name="domain_force">[(1, '=', 1)]</field>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
<field name="perm_unlink" eval="True"/>
</record>
<!-- Record rule for stages user -->
<record id="help_desk_stage_rule_user"
model="ir.rule">
<field name="name">Record Rule stages user</field>
<field ref="model_ticket_stage" name="model_id"/>
<field name="groups"
eval="[(4, ref('odoo_website_helpdesk.helpdesk_user'))]"/>
<field name="domain_force">[('group_ids.users', 'in', user.id)]</field>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
<field name="perm_unlink" eval="True"/>
</record>
</odoo>

1
odoo_website_helpdesk/static/description/1608951_ticket_icon.svg

@ -0,0 +1 @@
<?xml version="1.0" ?><svg height="1792" viewBox="0 0 1792 1792" width="1792" xmlns="http://www.w3.org/2000/svg"><path d="M1024 452l316 316-572 572-316-316zm-211 979l618-618q19-19 19-45t-19-45l-362-362q-18-18-45-18t-45 18l-618 618q-19 19-19 45t19 45l362 362q18 18 45 18t45-18zm889-637l-907 908q-37 37-90.5 37t-90.5-37l-126-126q56-56 56-136t-56-136-136-56-136 56l-125-126q-37-37-37-90.5t37-90.5l907-906q37-37 90.5-37t90.5 37l125 125q-56 56-56 136t56 136 136 56 136-56l126 125q37 37 37 90.5t-37 90.5z"/></svg>

After

Width:  |  Height:  |  Size: 507 B

BIN
odoo_website_helpdesk/static/description/assets/icons/check.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
odoo_website_helpdesk/static/description/assets/icons/chevron.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 B

BIN
odoo_website_helpdesk/static/description/assets/icons/cogs.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
odoo_website_helpdesk/static/description/assets/icons/consultation.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
odoo_website_helpdesk/static/description/assets/icons/ecom-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 576 B

BIN
odoo_website_helpdesk/static/description/assets/icons/education-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 733 B

BIN
odoo_website_helpdesk/static/description/assets/icons/hotel-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 911 B

BIN
odoo_website_helpdesk/static/description/assets/icons/license.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
odoo_website_helpdesk/static/description/assets/icons/lifebuoy.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
odoo_website_helpdesk/static/description/assets/icons/logo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
odoo_website_helpdesk/static/description/assets/icons/manufacturing-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 B

BIN
odoo_website_helpdesk/static/description/assets/icons/pos-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 878 B

BIN
odoo_website_helpdesk/static/description/assets/icons/puzzle.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 653 B

BIN
odoo_website_helpdesk/static/description/assets/icons/restaurant-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 905 B

BIN
odoo_website_helpdesk/static/description/assets/icons/service-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 839 B

BIN
odoo_website_helpdesk/static/description/assets/icons/trading-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 427 B

BIN
odoo_website_helpdesk/static/description/assets/icons/training.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 627 B

BIN
odoo_website_helpdesk/static/description/assets/icons/update.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
odoo_website_helpdesk/static/description/assets/icons/user.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 988 B

BIN
odoo_website_helpdesk/static/description/assets/icons/wrench.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
odoo_website_helpdesk/static/description/assets/misc/Cybrosys R.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

BIN
odoo_website_helpdesk/static/description/assets/misc/categories.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
odoo_website_helpdesk/static/description/assets/misc/check-box.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
odoo_website_helpdesk/static/description/assets/misc/compass.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
odoo_website_helpdesk/static/description/assets/misc/corporate.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
odoo_website_helpdesk/static/description/assets/misc/customer-support.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
odoo_website_helpdesk/static/description/assets/misc/cybrosys-logo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
odoo_website_helpdesk/static/description/assets/misc/features.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 589 B

BIN
odoo_website_helpdesk/static/description/assets/misc/logo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
odoo_website_helpdesk/static/description/assets/misc/pictures.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
odoo_website_helpdesk/static/description/assets/misc/pie-chart.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
odoo_website_helpdesk/static/description/assets/misc/right-arrow.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 967 B

BIN
odoo_website_helpdesk/static/description/assets/misc/star.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
odoo_website_helpdesk/static/description/assets/misc/support.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
odoo_website_helpdesk/static/description/assets/misc/whatsapp.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

BIN
odoo_website_helpdesk/static/description/assets/modules/1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

BIN
odoo_website_helpdesk/static/description/assets/modules/2.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

BIN
odoo_website_helpdesk/static/description/assets/modules/3.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

BIN
odoo_website_helpdesk/static/description/assets/modules/4.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

BIN
odoo_website_helpdesk/static/description/assets/modules/5.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

BIN
odoo_website_helpdesk/static/description/assets/modules/6.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

BIN
odoo_website_helpdesk/static/description/assets/screenshots/1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

BIN
odoo_website_helpdesk/static/description/assets/screenshots/10.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
odoo_website_helpdesk/static/description/assets/screenshots/11.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
odoo_website_helpdesk/static/description/assets/screenshots/12.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

BIN
odoo_website_helpdesk/static/description/assets/screenshots/13.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

BIN
odoo_website_helpdesk/static/description/assets/screenshots/14.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

BIN
odoo_website_helpdesk/static/description/assets/screenshots/15.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

BIN
odoo_website_helpdesk/static/description/assets/screenshots/16.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

BIN
odoo_website_helpdesk/static/description/assets/screenshots/17.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
odoo_website_helpdesk/static/description/assets/screenshots/18.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

BIN
odoo_website_helpdesk/static/description/assets/screenshots/19.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

BIN
odoo_website_helpdesk/static/description/assets/screenshots/2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

BIN
odoo_website_helpdesk/static/description/assets/screenshots/20.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

BIN
odoo_website_helpdesk/static/description/assets/screenshots/21.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

BIN
odoo_website_helpdesk/static/description/assets/screenshots/22.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

BIN
odoo_website_helpdesk/static/description/assets/screenshots/23.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

BIN
odoo_website_helpdesk/static/description/assets/screenshots/24.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

BIN
odoo_website_helpdesk/static/description/assets/screenshots/25.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
odoo_website_helpdesk/static/description/assets/screenshots/26.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
odoo_website_helpdesk/static/description/assets/screenshots/27.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

BIN
odoo_website_helpdesk/static/description/assets/screenshots/28.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

BIN
odoo_website_helpdesk/static/description/assets/screenshots/29.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save