Browse Source

Jan 23 [UPDT] : Updated 'odoo_website_helpdesk'

pull/302/head
AjmalCybro 1 year ago
parent
commit
ce82c7f0d5
  1. 40
      odoo_website_helpdesk/README.rst
  2. 2
      odoo_website_helpdesk/__init__.py
  3. 58
      odoo_website_helpdesk/__manifest__.py
  4. 25
      odoo_website_helpdesk/controller/__init__.py
  5. 172
      odoo_website_helpdesk/controller/helpdesk_website.py
  6. 32
      odoo_website_helpdesk/controller/portal.py
  7. 34
      odoo_website_helpdesk/controller/ticket_group_by.py
  8. 26
      odoo_website_helpdesk/controller/ticket_search.py
  9. 56
      odoo_website_helpdesk/controller/website.py
  10. 22
      odoo_website_helpdesk/data/helpdesk_types_data.xml
  11. 17
      odoo_website_helpdesk/data/ir_cron_data.xml
  12. 8
      odoo_website_helpdesk/data/ir_sequence_data.xml
  13. 211
      odoo_website_helpdesk/data/mail_template_data.xml
  14. 121
      odoo_website_helpdesk/data/rating_template.xml
  15. 79
      odoo_website_helpdesk/data/ticket_auto_close.xml
  16. 36
      odoo_website_helpdesk/data/ticket_stage_data.xml
  17. 21
      odoo_website_helpdesk/data/ticket_type.xml
  18. 11
      odoo_website_helpdesk/doc/RELEASE_NOTES.md
  19. 19
      odoo_website_helpdesk/models/__init__.py
  20. 16
      odoo_website_helpdesk/models/account_move.py
  21. 59
      odoo_website_helpdesk/models/heldesk_team.py
  22. 65
      odoo_website_helpdesk/models/help_team.py
  23. 342
      odoo_website_helpdesk/models/help_ticket.py
  24. 34
      odoo_website_helpdesk/models/helpdesk_categories.py
  25. 13
      odoo_website_helpdesk/models/helpdesk_tag.py
  26. 30
      odoo_website_helpdesk/models/helpdesk_types.py
  27. 13
      odoo_website_helpdesk/models/mail_compose_message.py
  28. 38
      odoo_website_helpdesk/models/merge_tickets.py
  29. 42
      odoo_website_helpdesk/models/project_task.py
  30. 100
      odoo_website_helpdesk/models/res_config.py
  31. 100
      odoo_website_helpdesk/models/res_config_settings.py
  32. 4
      odoo_website_helpdesk/models/support_tickets.py
  33. 98
      odoo_website_helpdesk/models/ticket_stage.py
  34. 61
      odoo_website_helpdesk/models/website_menu.py
  35. 4
      odoo_website_helpdesk/report/help_ticket_templates.xml
  36. 39
      odoo_website_helpdesk/security/ir.model.access.csv
  37. 22
      odoo_website_helpdesk/security/odoo_website_helpdesk_security.xml
  38. BIN
      odoo_website_helpdesk/static/description/assets/modules/1.jpg
  39. BIN
      odoo_website_helpdesk/static/description/assets/modules/2.jpg
  40. BIN
      odoo_website_helpdesk/static/description/assets/modules/3.png
  41. BIN
      odoo_website_helpdesk/static/description/assets/modules/4.png
  42. BIN
      odoo_website_helpdesk/static/description/assets/modules/5.jpg
  43. BIN
      odoo_website_helpdesk/static/description/assets/modules/7.jpg
  44. BIN
      odoo_website_helpdesk/static/description/assets/modules/budget_image.png
  45. BIN
      odoo_website_helpdesk/static/description/assets/modules/credit_image.png
  46. BIN
      odoo_website_helpdesk/static/description/assets/modules/employee_image.png
  47. BIN
      odoo_website_helpdesk/static/description/assets/modules/export_image.png
  48. BIN
      odoo_website_helpdesk/static/description/assets/modules/gantt_image.png
  49. BIN
      odoo_website_helpdesk/static/description/assets/modules/quotation_image.png
  50. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/Screenshot10.png
  51. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/Screenshot11.png
  52. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/Screenshot12.png
  53. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/Screenshot13.png
  54. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/Screenshot14.png
  55. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/Screenshot15.png
  56. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/Screenshot16.png
  57. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/Screenshot5.png
  58. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/Screenshot6.png
  59. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/Screenshot7.png
  60. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/Screenshot8.png
  61. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/Screenshot9.png
  62. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/billed.png
  63. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/catagory.png
  64. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/create-new-ticket.png
  65. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/enable_billing.png
  66. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/enable_helpdesk.png
  67. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/enable_settings_task.png
  68. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/enable_task.png
  69. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/hero.gif
  70. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/invoice.png
  71. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/kanban_view.png
  72. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/merge-action.png
  73. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/model.png
  74. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/open-new-ticket.png
  75. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/printing.png
  76. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/report.png
  77. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/stages.png
  78. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/tags.png
  79. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/task_creation.png
  80. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/teams.png
  81. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/ticket.png
  82. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/types.png
  83. BIN
      odoo_website_helpdesk/static/description/assets/screenshots/v16-hero.gif
  84. 253
      odoo_website_helpdesk/static/description/index.html
  85. 120
      odoo_website_helpdesk/static/src/js/helpdesk_dashboard_action.js
  86. 29
      odoo_website_helpdesk/static/src/js/multiple_product_choose.js
  87. 16
      odoo_website_helpdesk/static/src/js/portal_groupby.js
  88. 33
      odoo_website_helpdesk/static/src/js/portal_groupby_and_search.js
  89. 16
      odoo_website_helpdesk/static/src/js/portal_search.js
  90. 4
      odoo_website_helpdesk/static/src/js/ticket_details.js
  91. 272
      odoo_website_helpdesk/static/src/xml/help_ticket_templates.xml
  92. 287
      odoo_website_helpdesk/static/src/xml/helpdesk_dashboard.xml
  93. 58
      odoo_website_helpdesk/templates/helpdesk_replay_template.xml
  94. 13
      odoo_website_helpdesk/views/categories.xml
  95. 16
      odoo_website_helpdesk/views/help_team_views.xml
  96. 143
      odoo_website_helpdesk/views/help_ticket_views.xml
  97. 20
      odoo_website_helpdesk/views/helpdesk_categories_views.xml
  98. 61
      odoo_website_helpdesk/views/helpdesk_replay_template.xml
  99. 24
      odoo_website_helpdesk/views/helpdesk_tag_views.xml
  100. 24
      odoo_website_helpdesk/views/helpdesk_types_views.xml

40
odoo_website_helpdesk/README.rst

@ -1,30 +1,36 @@
HelpDesk Support .. image:: https://img.shields.io/badge/license-LGPL--3-green.svg
========================= :target: https://www.gnu.org/licenses/lgpl-3.0-standalone.html
* HelpDesk Support for Odoo 16 community editions :alt: License: LGPL-3
Installation Website Helpdesk Support Ticket Management
============ ==========================================
- www.odoo.com/documentation/16.0/setup/install.html
- Install our custom addon
License The module is a comprehensive solution designed to streamline and enhance
------- support ticket management within your Odoo instance. This module extends the
General Public License, Version 3 (LGPL v3). capabilities of Odoo's helpdesk functionality, providing a user-friendly
(https://www.odoo.com/documentation/user/15.0/legal/licenses/licenses.html) interface for customers to submit, track, and manage support tickets efficiently.
Configuration
=============
* No additional configurations needed
Company Company
------- -------
* 'Cybrosys Techno Solutions <https://cybrosys.com/>`__ * `Cybrosys Techno Solutions <https://cybrosys.com/>`__
Credits License
------- -------
* Developer: General Public License, Version 3 (LGPL v3).
(v16) Robin @ Cybrosys (https://www.gnu.org/licenses/lgpl-3.0-standalone.html)
Credits
-------
* Developer:(v16) Junaidul Ansar M , Contacts : odoo@cybrosys.com
Contacts Contacts
-------- --------
* Mail Contact : odoo@cybrosys.com * Mail Contact : odoo@cybrosys.com
* Website : https://cybrosys.com
Bug Tracker Bug Tracker
----------- -----------
@ -32,6 +38,9 @@ Bugs are tracked on GitHub Issues. In case of trouble, please check there if you
Maintainer Maintainer
========== ==========
.. image:: https://cybrosys.com/images/logo.png
:target: https://cybrosys.com
This module is maintained by Cybrosys Technologies. This module is maintained by Cybrosys Technologies.
For support and more information, please visit https://www.cybrosys.com For support and more information, please visit https://www.cybrosys.com
@ -39,4 +48,3 @@ For support and more information, please visit https://www.cybrosys.com
Further information Further information
=================== ===================
HTML Description: `<static/description/index.html>`__ HTML Description: `<static/description/index.html>`__

2
odoo_website_helpdesk/__init__.py

@ -3,7 +3,7 @@
# #
# Cybrosys Technologies Pvt. Ltd. # Cybrosys Technologies Pvt. Ltd.
# #
# Copyright (C) 2022-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) # Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) # Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
# #
# You can modify it under the terms of the GNU LESSER # You can modify it under the terms of the GNU LESSER

58
odoo_website_helpdesk/__manifest__.py

@ -3,7 +3,7 @@
# #
# Cybrosys Technologies Pvt. Ltd. # Cybrosys Technologies Pvt. Ltd.
# #
# Copyright (C) 2022-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) # Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) # Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
# #
# You can modify it under the terms of the GNU LESSER # You can modify it under the terms of the GNU LESSER
@ -19,52 +19,52 @@
# If not, see <http://www.gnu.org/licenses/>. # If not, see <http://www.gnu.org/licenses/>.
# #
############################################################################# #############################################################################
{ {
'name': "Website Helpdesk Support Ticket Management", 'name': "Website Helpdesk Support Ticket Management",
'version': '16.0.4.0.1', 'version': '16.0.3.0.0',
'category': 'Website',
'summary': """Helpdesk Module for community""", 'summary': """Helpdesk Module for community""",
'description': """Can create ticket from website also and can manage it from backend. 'description': 'Can create ticket from website also and can manage it from'
Bill can be created for ticket with service cost""", ' backend.Bill can be created for ticket with service cost',
'author': "Cybrosys Techno Solutions", 'author': "Cybrosys Techno Solutions",
'company': 'Cybrosys Techno Solutions', 'company': 'Cybrosys Techno Solutions',
'maintainer': 'Cybrosys Techno Solutions', 'maintainer': 'Cybrosys Techno Solutions',
'category': 'Website', 'website': 'https://www.cybrosys.com',
'depends': ['base', 'website', 'project', 'sale_project', 'hr_timesheet', 'depends': ['base', 'website', 'project', 'sale_project',
'mail', 'contacts'], 'hr_timesheet', 'mail', 'contacts'],
'data': [ 'data': [
'security/security_groups.xml', 'security/odoo_website_helpdesk_security.xml',
'security/ir.model.access.csv', 'security/ir.model.access.csv',
'data/ticket_sequence.xml', 'data/ir_sequence_data.xml',
'data/ticket_stage_data.xml', 'data/ticket_stage_data.xml',
'data/ticket_type.xml', 'data/helpdesk_types_data.xml',
'data/ticket_auto_close.xml', 'data/ir_cron_data.xml',
'data/rating_template.xml', 'data/mail_template_data.xml',
'views/team.xml', 'views/help_team_views.xml',
'views/portal_search.xml', 'views/portal_search_templates.xml',
'views/res_config_settings.xml', 'views/res_config_settings_views.xml',
'views/website_form.xml', 'views/website_form.xml',
'views/report.xml', 'views/report_templates.xml',
'views/helpdesk.xml', 'views/help_ticket_views.xml',
'views/helpdesk_views.xml', 'views/portal_views_templates.xml',
'views/portal.xml', 'views/helpdesk_categories_views.xml',
'views/categories.xml', 'views/rating_form_templates.xml',
'views/rating_form.xml',
'views/merge_tickets_views.xml', 'views/merge_tickets_views.xml',
'templates/helpdesk_replay_template.xml', 'views/helpdesk_tag_views.xml',
'report/helpdesk_ticket_report_template.xml', 'views/helpdesk_types_views.xml',
'views/ticket_stage_views.xml',
'views/helpdesk_replay_template.xml',
'views/odoo_website_helpdesk_menus.xml',
'report/help_ticket_templates.xml',
], ],
'assets': { 'assets': {
# 'web.assets_frontend': [
# ],
'web.assets_backend': [ 'web.assets_backend': [
'odoo_website_helpdesk/static/src/xml/helpdesk_dashboard.xml', 'odoo_website_helpdesk/static/src/xml/help_ticket_templates.xml',
'odoo_website_helpdesk/static/src/js/helpdesk_dashboard_action.js', 'odoo_website_helpdesk/static/src/js/helpdesk_dashboard_action.js',
], ],
'web.assets_frontend': [ 'web.assets_frontend': [
'odoo_website_helpdesk/static/src/js/ticket_details.js', 'odoo_website_helpdesk/static/src/js/ticket_details.js',
'/odoo_website_helpdesk/static/src/js/portal_search.js', '/odoo_website_helpdesk/static/src/js/portal_groupby_and_search.js',
'/odoo_website_helpdesk/static/src/js/portal_groupby.js',
'/odoo_website_helpdesk/static/src/js/multiple_product_choose.js', '/odoo_website_helpdesk/static/src/js/multiple_product_choose.js',
'/odoo_website_helpdesk/static/src/cdn/jquery.sumoselect.min.js', '/odoo_website_helpdesk/static/src/cdn/jquery.sumoselect.min.js',
'/odoo_website_helpdesk/static/src/cdn/sumoselect.min.css', '/odoo_website_helpdesk/static/src/cdn/sumoselect.min.css',

25
odoo_website_helpdesk/controller/__init__.py

@ -1,5 +1,26 @@
from . import website_form # -*- coding: utf-8 -*-
from . import portal #############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.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 helpdesk_website from . import helpdesk_website
from . import portal
from . import ticket_search from . import ticket_search
from . import ticket_group_by from . import ticket_group_by
from . import website

172
odoo_website_helpdesk/controller/helpdesk_website.py

@ -1,12 +1,35 @@
# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.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 import http
from odoo.http import request from odoo.http import request
import datetime as DT
class HelpDeskDashboard(http.Controller): class HelpDeskDashboard(http.Controller):
"""Website helpdesk dashboard"""
@http.route(['/helpdesk_dashboard'], type='json', auth="public") @http.route(['/helpdesk_dashboard'], type='json', auth="public")
def helpdesk_dashboard(self): def helpdesk_dashboard(self):
"""Helpdesk dashboard controller"""
stage_new = request.env['ticket.stage'].search( stage_new = request.env['ticket.stage'].search(
[('name', '=', 'Inbox')], limit=1).id [('name', '=', 'Inbox')], limit=1).id
stage_draft = request.env['ticket.stage'].search( stage_draft = request.env['ticket.stage'].search(
@ -19,41 +42,40 @@ class HelpDeskDashboard(http.Controller):
[('name', '=', 'Done')], limit=1).id [('name', '=', 'Done')], limit=1).id
stage_closed = request.env['ticket.stage'].search( stage_closed = request.env['ticket.stage'].search(
[('name', '=', 'Closed')], limit=1).id [('name', '=', 'Closed')], limit=1).id
stage_ids = [stage_new,stage_draft] stage_ids = [stage_new, stage_draft]
new = request.env["help.ticket"].search_count([('stage_id', 'in', stage_ids)]) new = request.env["help.ticket"].search_count(
new_id = request.env["help.ticket"].search([('stage_id', 'in', stage_ids)]) [('stage_id', 'in', stage_ids)])
new_id_ls = [] new_id = request.env["help.ticket"].search(
for data in new_id: [('stage_id', 'in', stage_ids)])
new_id_ls.append(data.id) new_id_ls = [data.id for data in new_id]
in_progress = request.env["help.ticket"].search_count([('stage_id', '=', stage_inprogress)]) in_progress = request.env["help.ticket"].search_count(
in_progress_id = request.env["help.ticket"].search([('stage_id', '=', stage_inprogress)]) [('stage_id', '=', stage_inprogress)])
in_progress_ls = [] in_progress_id = request.env["help.ticket"].search(
for data in in_progress_id: [('stage_id', '=', stage_inprogress)])
in_progress_ls.append(data.id) in_progress_ls = [data.id for data in in_progress_id]
canceled = request.env["help.ticket"].search_count([('stage_id', '=', stage_canceled)]) canceled = request.env["help.ticket"].search_count(
canceled_id = request.env["help.ticket"].search([('stage_id', '=', stage_canceled)]) [('stage_id', '=', stage_canceled)])
canceled_id_ls = [] canceled_id = request.env["help.ticket"].search(
for data in canceled_id: [('stage_id', '=', stage_canceled)])
canceled_id_ls.append(data.id) canceled_id_ls = [data.id for data in canceled_id]
done = request.env["help.ticket"].search_count([('stage_id', '=', stage_done)]) done = request.env["help.ticket"].search_count(
done_id = request.env["help.ticket"].search([('stage_id', '=', stage_done)]) [('stage_id', '=', stage_done)])
done_id_ls = [] done_id = request.env["help.ticket"].search(
for data in done_id: [('stage_id', '=', stage_done)])
done_id_ls.append(data.id) done_id_ls = [data.id for data in done_id]
closed = request.env["help.ticket"].search_count([('stage_id', '=', stage_closed)]) closed = request.env["help.ticket"].search_count(
closed_id = request.env["help.ticket"].search([('stage_id', '=', stage_closed)]) [('stage_id', '=', stage_closed)])
closed_id_ls = [] closed_id = request.env["help.ticket"].search(
for data in closed_id: [('stage_id', '=', stage_closed)])
closed_id_ls.append(data.id) closed_id_ls = [data.id for data in closed_id]
dashboard_values = { dashboard_values = {
'new':new, 'new': new,
'in_progress':in_progress, 'in_progress': in_progress,
'canceled':canceled, 'canceled': canceled,
'done':done, 'done': done,
'closed':closed, 'closed': closed,
'new_id':new_id_ls, 'new_id': new_id_ls,
'in_progress_id':in_progress_ls, 'in_progress_id': in_progress_ls,
'canceled_id': canceled_id_ls, 'canceled_id': canceled_id_ls,
'done_id': done_id_ls, 'done_id': done_id_ls,
'closed_id': closed_id_ls, 'closed_id': closed_id_ls,
@ -62,6 +84,7 @@ class HelpDeskDashboard(http.Controller):
@http.route(['/helpdesk_dashboard_week'], type='json', auth="public") @http.route(['/helpdesk_dashboard_week'], type='json', auth="public")
def helpdesk_dashboard_week(self): def helpdesk_dashboard_week(self):
"""Week based sorting controller"""
today = DT.date.today() today = DT.date.today()
stage_new = request.env['ticket.stage'].search( stage_new = request.env['ticket.stage'].search(
[('name', '=', 'Inbox')], limit=1).id [('name', '=', 'Inbox')], limit=1).id
@ -81,38 +104,31 @@ class HelpDeskDashboard(http.Controller):
[('stage_id', 'in', stage_ids), ('create_date', '>', week_ago)]) [('stage_id', 'in', stage_ids), ('create_date', '>', week_ago)])
new_id = request.env["help.ticket"].search( new_id = request.env["help.ticket"].search(
[('stage_id', 'in', stage_ids), ('create_date', '>', week_ago)]) [('stage_id', 'in', stage_ids), ('create_date', '>', week_ago)])
new_id_ls = [] new_id_ls = [data.id for data in new_id]
for data in new_id:
new_id_ls.append(data.id)
in_progress = request.env["help.ticket"].search_count( in_progress = request.env["help.ticket"].search_count(
[('stage_id', '=', stage_inprogress), ('create_date', '>', week_ago)]) [('stage_id', '=', stage_inprogress),
('create_date', '>', week_ago)])
in_progress_id = request.env["help.ticket"].search( in_progress_id = request.env["help.ticket"].search(
[('stage_id', '=', stage_inprogress), ('create_date', '>', week_ago)]) [('stage_id', '=', stage_inprogress),
in_progress_ls = [] ('create_date', '>', week_ago)])
for data in in_progress_id: in_progress_ls = [data.id for data in in_progress_id]
in_progress_ls.append(data.id)
canceled = request.env["help.ticket"].search_count( canceled = request.env["help.ticket"].search_count(
[('stage_id', '=', stage_canceled), ('create_date', '>', week_ago)]) [('stage_id', '=', stage_canceled),
('create_date', '>', week_ago)])
canceled_id = request.env["help.ticket"].search( canceled_id = request.env["help.ticket"].search(
[('stage_id', '=', stage_canceled), ('create_date', '>', week_ago)]) [('stage_id', '=', stage_canceled),
canceled_id_ls = [] ('create_date', '>', week_ago)])
for data in canceled_id: canceled_id_ls = [data.id for data in canceled_id]
canceled_id_ls.append(data.id)
done = request.env["help.ticket"].search_count( done = request.env["help.ticket"].search_count(
[('stage_id', '=', stage_done), ('create_date', '>', week_ago)]) [('stage_id', '=', stage_done), ('create_date', '>', week_ago)])
done_id = request.env["help.ticket"].search( done_id = request.env["help.ticket"].search(
[('stage_id', '=', stage_done), ('create_date', '>', week_ago)]) [('stage_id', '=', stage_done), ('create_date', '>', week_ago)])
done_id_ls = [] done_id_ls = [data.id for data in done_id]
for data in done_id:
done_id_ls.append(data.id)
closed = request.env["help.ticket"].search_count( closed = request.env["help.ticket"].search_count(
[('stage_id', '=', stage_closed), ('create_date', '>', week_ago)]) [('stage_id', '=', stage_closed), ('create_date', '>', week_ago)])
closed_id = request.env["help.ticket"].search( closed_id = request.env["help.ticket"].search(
[('stage_id', '=', stage_closed), ('create_date', '>', week_ago)]) [('stage_id', '=', stage_closed), ('create_date', '>', week_ago)])
closed_id_ls = [] closed_id_ls = [data.id for data in closed_id]
for data in closed_id:
closed_id_ls.append(data.id)
dashboard_values = { dashboard_values = {
'new': new, 'new': new,
'in_progress': in_progress, 'in_progress': in_progress,
@ -129,6 +145,7 @@ class HelpDeskDashboard(http.Controller):
@http.route(['/helpdesk_dashboard_month'], type='json', auth="public") @http.route(['/helpdesk_dashboard_month'], type='json', auth="public")
def helpdesk_dashboard_month(self): def helpdesk_dashboard_month(self):
"""Month based sorting controller"""
today = DT.date.today() today = DT.date.today()
stage_new = request.env['ticket.stage'].search( stage_new = request.env['ticket.stage'].search(
[('name', '=', 'Inbox')], limit=1).id [('name', '=', 'Inbox')], limit=1).id
@ -148,42 +165,31 @@ class HelpDeskDashboard(http.Controller):
[('stage_id', 'in', stage_ids), ('create_date', '>', week_ago)]) [('stage_id', 'in', stage_ids), ('create_date', '>', week_ago)])
new_id = request.env["help.ticket"].search( new_id = request.env["help.ticket"].search(
[('stage_id', 'in', stage_ids), ('create_date', '>', week_ago)]) [('stage_id', 'in', stage_ids), ('create_date', '>', week_ago)])
new_id_ls = [] new_id_ls = [data.id for data in new_id]
for data in new_id:
new_id_ls.append(data.id)
in_progress = request.env["help.ticket"].search_count( in_progress = request.env["help.ticket"].search_count(
[('stage_id', '=', stage_inprogress), [('stage_id', '=', stage_inprogress),
('create_date', '>', week_ago)]) ('create_date', '>', week_ago)])
in_progress_id = request.env["help.ticket"].search( in_progress_id = request.env["help.ticket"].search(
[('stage_id', '=', stage_inprogress), [('stage_id', '=', stage_inprogress),
('create_date', '>', week_ago)]) ('create_date', '>', week_ago)])
in_progress_ls = [] in_progress_ls = [data.id for data in in_progress_id]
for data in in_progress_id:
in_progress_ls.append(data.id)
canceled = request.env["help.ticket"].search_count( canceled = request.env["help.ticket"].search_count(
[('stage_id', '=', stage_canceled), [('stage_id', '=', stage_canceled),
('create_date', '>', week_ago)]) ('create_date', '>', week_ago)])
canceled_id = request.env["help.ticket"].search( canceled_id = request.env["help.ticket"].search(
[('stage_id', '=', stage_canceled), [('stage_id', '=', stage_canceled),
('create_date', '>', week_ago)]) ('create_date', '>', week_ago)])
canceled_id_ls = [] canceled_id_ls = [data.id for data in canceled_id]
for data in canceled_id:
canceled_id_ls.append(data.id)
done = request.env["help.ticket"].search_count( done = request.env["help.ticket"].search_count(
[('stage_id', '=', stage_done), ('create_date', '>', week_ago)]) [('stage_id', '=', stage_done), ('create_date', '>', week_ago)])
done_id = request.env["help.ticket"].search( done_id = request.env["help.ticket"].search(
[('stage_id', '=', stage_done), ('create_date', '>', week_ago)]) [('stage_id', '=', stage_done), ('create_date', '>', week_ago)])
done_id_ls = [] done_id_ls = [data.id for data in done_id]
for data in done_id:
done_id_ls.append(data.id)
closed = request.env["help.ticket"].search_count( closed = request.env["help.ticket"].search_count(
[('stage_id', '=', stage_closed), ('create_date', '>', week_ago)]) [('stage_id', '=', stage_closed), ('create_date', '>', week_ago)])
closed_id = request.env["help.ticket"].search( closed_id = request.env["help.ticket"].search(
[('stage_id', '=', stage_closed), ('create_date', '>', week_ago)]) [('stage_id', '=', stage_closed), ('create_date', '>', week_ago)])
closed_id_ls = [] closed_id_ls = [data.id for data in closed_id]
for data in closed_id:
closed_id_ls.append(data.id)
dashboard_values = { dashboard_values = {
'new': new, 'new': new,
'in_progress': in_progress, 'in_progress': in_progress,
@ -200,6 +206,7 @@ class HelpDeskDashboard(http.Controller):
@http.route(['/helpdesk_dashboard_year'], type='json', auth="public") @http.route(['/helpdesk_dashboard_year'], type='json', auth="public")
def helpdesk_dashboard_year(self): def helpdesk_dashboard_year(self):
"""Year based sorting"""
today = DT.date.today() today = DT.date.today()
stage_new = request.env['ticket.stage'].search( stage_new = request.env['ticket.stage'].search(
[('name', '=', 'Inbox')], limit=1).id [('name', '=', 'Inbox')], limit=1).id
@ -219,42 +226,31 @@ class HelpDeskDashboard(http.Controller):
[('stage_id', 'in', stage_ids), ('create_date', '>', week_ago)]) [('stage_id', 'in', stage_ids), ('create_date', '>', week_ago)])
new_id = request.env["help.ticket"].search( new_id = request.env["help.ticket"].search(
[('stage_id', 'in', stage_ids), ('create_date', '>', week_ago)]) [('stage_id', 'in', stage_ids), ('create_date', '>', week_ago)])
new_id_ls = [] new_id_ls = [data.id for data in new_id]
for data in new_id:
new_id_ls.append(data.id)
in_progress = request.env["help.ticket"].search_count( in_progress = request.env["help.ticket"].search_count(
[('stage_id', '=', stage_inprogress), [('stage_id', '=', stage_inprogress),
('create_date', '>', week_ago)]) ('create_date', '>', week_ago)])
in_progress_id = request.env["help.ticket"].search( in_progress_id = request.env["help.ticket"].search(
[('stage_id', '=', stage_inprogress), [('stage_id', '=', stage_inprogress),
('create_date', '>', week_ago)]) ('create_date', '>', week_ago)])
in_progress_ls = [] in_progress_ls = [data.id for data in in_progress_id]
for data in in_progress_id:
in_progress_ls.append(data.id)
canceled = request.env["help.ticket"].search_count( canceled = request.env["help.ticket"].search_count(
[('stage_id', '=', stage_canceled), [('stage_id', '=', stage_canceled),
('create_date', '>', week_ago)]) ('create_date', '>', week_ago)])
canceled_id = request.env["help.ticket"].search( canceled_id = request.env["help.ticket"].search(
[('stage_id', '=', stage_canceled), [('stage_id', '=', stage_canceled),
('create_date', '>', week_ago)]) ('create_date', '>', week_ago)])
canceled_id_ls = [] canceled_id_ls = [data.id for data in canceled_id]
for data in canceled_id:
canceled_id_ls.append(data.id)
done = request.env["help.ticket"].search_count( done = request.env["help.ticket"].search_count(
[('stage_id', '=', stage_done), ('create_date', '>', week_ago)]) [('stage_id', '=', stage_done), ('create_date', '>', week_ago)])
done_id = request.env["help.ticket"].search( done_id = request.env["help.ticket"].search(
[('stage_id', '=', stage_done), ('create_date', '>', week_ago)]) [('stage_id', '=', stage_done), ('create_date', '>', week_ago)])
done_id_ls = [] done_id_ls = [data.id for data in done_id]
for data in done_id:
done_id_ls.append(data.id)
closed = request.env["help.ticket"].search_count( closed = request.env["help.ticket"].search_count(
[('stage_id', '=', stage_closed), ('create_date', '>', week_ago)]) [('stage_id', '=', stage_closed), ('create_date', '>', week_ago)])
closed_id = request.env["help.ticket"].search( closed_id = request.env["help.ticket"].search(
[('stage_id', '=', stage_closed), ('create_date', '>', week_ago)]) [('stage_id', '=', stage_closed), ('create_date', '>', week_ago)])
closed_id_ls = [] closed_id_ls = [data.id for data in closed_id]
for data in closed_id:
closed_id_ls.append(data.id)
dashboard_values = { dashboard_values = {
'new': new, 'new': new,
'in_progress': in_progress, 'in_progress': in_progress,
@ -267,4 +263,4 @@ class HelpDeskDashboard(http.Controller):
'done_id': done_id_ls, 'done_id': done_id_ls,
'closed_id': closed_id_ls, 'closed_id': closed_id_ls,
} }
return dashboard_values return dashboard_values

32
odoo_website_helpdesk/controller/portal.py

@ -3,7 +3,7 @@
# #
# Cybrosys Technologies Pvt. Ltd. # Cybrosys Technologies Pvt. Ltd.
# #
# Copyright (C) 2022-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) # Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) # Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
# #
# You can modify it under the terms of the GNU LESSER # You can modify it under the terms of the GNU LESSER
@ -19,15 +19,18 @@
# If not, see <http://www.gnu.org/licenses/>. # If not, see <http://www.gnu.org/licenses/>.
# #
############################################################################# #############################################################################
from odoo import http from odoo import http
from odoo.addons.portal.controllers import portal from odoo.addons.portal.controllers import portal
from odoo.http import request from odoo.http import request
class TicketPortal(portal.CustomerPortal): class TicketPortal(portal.CustomerPortal):
""" Controller for handling customer portal related actions related to
helpdesk tickets.
"""
def _prepare_home_portal_values(self, counters): def _prepare_home_portal_values(self, counters):
"""Prepares a dictionary of values to be used in the home portal view
and get their count."""
values = super()._prepare_home_portal_values(counters) values = super()._prepare_home_portal_values(counters)
if 'ticket_count' in counters: if 'ticket_count' in counters:
ticket_count = request.env['help.ticket'].search_count( ticket_count = request.env['help.ticket'].search_count(
@ -37,14 +40,16 @@ class TicketPortal(portal.CustomerPortal):
values['ticket_count'] = ticket_count values['ticket_count'] = ticket_count
return values return values
# checking domain:
def _get_tickets_domain(self): def _get_tickets_domain(self):
"""Checking the domain"""
return [('customer_id', '=', request.env.user.partner_id.id)] return [('customer_id', '=', request.env.user.partner_id.id)]
@http.route(['/my/tickets'], type='http', auth="user", website=True) @http.route(['/my/tickets'], type='http', auth="user", website=True)
def portal_my_tickets(self): def portal_my_tickets(self):
"""Displays a list of tickets for the current user in the user's
portal."""
domain = self._get_tickets_domain() domain = self._get_tickets_domain()
tickets = request.env['help.ticket'].sudo().search(domain) tickets = request.env['help.ticket'].search(domain)
values = { values = {
'default_url': "/my/tickets", 'default_url': "/my/tickets",
'tickets': tickets, 'tickets': tickets,
@ -56,6 +61,8 @@ class TicketPortal(portal.CustomerPortal):
@http.route(['/my/tickets/<int:id>'], type='http', auth="public", @http.route(['/my/tickets/<int:id>'], type='http', auth="public",
website=True) website=True)
def portal_tickets_details(self, id): def portal_tickets_details(self, id):
"""Displays a list of tickets for the current user in the user's
portal."""
details = request.env['help.ticket'].sudo().search([('id', '=', id)]) details = request.env['help.ticket'].sudo().search([('id', '=', id)])
data = { data = {
'page_name': 'ticket', 'page_name': 'ticket',
@ -69,6 +76,8 @@ class TicketPortal(portal.CustomerPortal):
type='http', type='http',
website=True) website=True)
def ticket_download_portal(self, id): def ticket_download_portal(self, id):
"""Download the ticket information in a pdf formate of the current
event ticket."""
data = { data = {
'help': request.env['help.ticket'].sudo().browse(int(id))} 'help': request.env['help.ticket'].sudo().browse(int(id))}
report = request.env.ref( report = request.env.ref(
@ -84,9 +93,11 @@ class TicketPortal(portal.CustomerPortal):
class WebsiteDesk(http.Controller): class WebsiteDesk(http.Controller):
@http.route(['/helpdesk_ticket'], type='http', auth="public", website=True, """Control for handling the helpdesk tickets form and its submission."""
sitemap=True) @http.route(['/helpdesk_ticket'], type='http', auth="public",
def helpdesk_ticket(self, **kwargs): website=True, sitemap=True)
def helpdesk_ticket(self):
"""Render the helpdesk ticket form."""
types = request.env['helpdesk.types'].sudo().search([]) types = request.env['helpdesk.types'].sudo().search([])
categories = request.env['helpdesk.categories'].sudo().search([]) categories = request.env['helpdesk.categories'].sudo().search([])
product = request.env['product.template'].sudo().search([]) product = request.env['product.template'].sudo().search([])
@ -102,16 +113,19 @@ class WebsiteDesk(http.Controller):
website=True, website=True,
sitemap=True) sitemap=True)
def rating(self, ticket_id): def rating(self, ticket_id):
"""Render the helpdesk ticket rating form."""
ticket = request.env['help.ticket'].browse(ticket_id) ticket = request.env['help.ticket'].browse(ticket_id)
data = { data = {
'ticket': ticket.id, 'ticket': ticket.id,
} }
return request.render('odoo_website_helpdesk.rating_form', data) return request.render('odoo_website_helpdesk.rating_form', data)
@http.route(['/rating/<int:ticket_id>/submit'], type='http', auth="user", @http.route(['/rating/<int:ticket_id>/submit'], type='http',
auth="user",
website=True, csrf=False, website=True, csrf=False,
sitemap=True) sitemap=True)
def rating_backend(self, ticket_id, **post): def rating_backend(self, ticket_id, **post):
"""Render the thanks page after rating the helpdesk ticket."""
ticket = request.env['help.ticket'].browse(ticket_id) ticket = request.env['help.ticket'].browse(ticket_id)
ticket.write({ ticket.write({
'customer_rating': post['rating'], 'customer_rating': post['rating'],

34
odoo_website_helpdesk/controller/ticket_group_by.py

@ -1,24 +1,46 @@
# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.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 import http
from odoo.http import request from odoo.http import request
class TicketGroupBy(http.Controller): class TicketGroupBy(http.Controller):
"""Control for handle the customer portal groupBy
filtering by the tickets."""
@http.route(['/ticketgroupby'], type='json', auth="public", website=True) @http.route(['/ticketgroupby'], type='json', auth="public", website=True)
def ticket_group_by(self, **kwargs): def ticket_group_by(self, **kwargs):
"""Display the list of tickets based on the groupBy filtering"""
context = [] context = []
group_value = kwargs.get("search_value") group_value = kwargs.get("search_value")
if group_value == '0': if group_value == '0':
context = [] context = []
tickets = request.env["help.ticket"].search( tickets = request.env["help.ticket"].search([])
[('user_id', '=', request.env.user.id)])
context.append(tickets) context.append(tickets)
if group_value == '1': if group_value == '1':
context = [] context = []
stage_ids = request.env['ticket.stage'].search([]) stage_ids = request.env['ticket.stage'].search([])
for stage in stage_ids: for stage in stage_ids:
ticket_ids = request.env['help.ticket'].search([ ticket_ids = request.env['help.ticket'].search([
('stage_id', '=', stage.id), ('stage_id', '=', stage.id)
('user_id', '=', request.env.user.id)
]) ])
if ticket_ids: if ticket_ids:
context.append({ context.append({
@ -30,15 +52,13 @@ class TicketGroupBy(http.Controller):
type_ids = request.env['helpdesk.types'].search([]) type_ids = request.env['helpdesk.types'].search([])
for types in type_ids: for types in type_ids:
ticket_ids_1 = request.env['help.ticket'].search([ ticket_ids_1 = request.env['help.ticket'].search([
('ticket_type', '=', types.id), ('ticket_type', '=', types.id)
('user_id', '=', request.env.user.id)
]) ])
if ticket_ids_1: if ticket_ids_1:
context.append({ context.append({
'name': types.name, 'name': types.name,
'data': ticket_ids_1 'data': ticket_ids_1
}) })
values = { values = {
'tickets': context, 'tickets': context,
} }

26
odoo_website_helpdesk/controller/ticket_search.py

@ -1,15 +1,39 @@
# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.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 import http
from odoo.http import request from odoo.http import request
class TicketSearch(http.Controller): class TicketSearch(http.Controller):
"""Control for handle the customer portal search
filtering by the tickets."""
@http.route(['/ticketsearch'], type='json', auth="public", website=True) @http.route(['/ticketsearch'], type='json', auth="public", website=True)
def ticket_search(self, **kwargs): def ticket_search(self, **kwargs):
""" Display the list of tickets satisfying the searching condition.
Searching the ticket based on name or subject"""
search_value = kwargs.get("search_value") search_value = kwargs.get("search_value")
tickets = request.env["help.ticket"].search( tickets = request.env["help.ticket"].search(
['|', ('name', 'ilike', search_value), ['|', ('name', 'ilike', search_value),
('subject', 'ilike', search_value)]) ('subject', 'ilike', search_value)])
values = { values = {
'tickets': tickets, 'tickets': tickets,
} }

56
odoo_website_helpdesk/controller/website_form.py → odoo_website_helpdesk/controller/website.py

@ -3,7 +3,7 @@
# #
# Cybrosys Technologies Pvt. Ltd. # Cybrosys Technologies Pvt. Ltd.
# #
# Copyright (C) 2022-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) # Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) # Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
# #
# You can modify it under the terms of the GNU LESSER # You can modify it under the terms of the GNU LESSER
@ -21,34 +21,35 @@
############################################################################# #############################################################################
import base64 import base64
import json import json
from psycopg2 import IntegrityError
from odoo import _, http from odoo import _, http
from odoo.addons.website.controllers.form import WebsiteForm from psycopg2 import IntegrityError
from odoo.exceptions import ValidationError
from odoo.http import request from odoo.http import request
from odoo.exceptions import ValidationError
from odoo.addons.website.controllers.form import WebsiteForm
class helpdesk_product(http.Controller): class HelpdeskProduct(http.Controller):
"""It controls the website products and return the product."""
@http.route('/product', auth='public', type='json') @http.route('/product', auth='public', type='json')
def product(self): def product(self):
prols = [] """Product control function"""
acc = request.env['product.template'].sudo().search([]) products = request.env['product.template'].sudo().search_read([],
for i in acc: ['name',
dic = {'name': i['name'], 'id'])
'id': i['id']} return products
prols.append(dic)
return prols
class WebsiteFormInherit(WebsiteForm): class WebsiteFormInherit(WebsiteForm):
"""This module extends the functionality of the website form controller
to handle the creation of new help desk tickets. It provides a new
controller to display a list of tickets for the current user in their
portal, and overrides the website form controller's method for handling
form submissions to create a new help desk ticket instead."""
def _handle_website_form(self, model_name, **kwargs): def _handle_website_form(self, model_name, **kwargs):
"""Website Help Desk Form"""
customer = request.env.user.partner_id customer = request.env.user.partner_id
if model_name == 'help.ticket': if model_name == 'help.ticket':
tickets = request.env['ticket.stage'].sudo().search( tickets = request.env['ticket.stage'].search([])
[])
for rec in tickets: for rec in tickets:
sequence = tickets.mapped('sequence') sequence = tickets.mapped('sequence')
lowest_sequence = tickets.filtered( lowest_sequence = tickets.filtered(
@ -66,7 +67,7 @@ class WebsiteFormInherit(WebsiteForm):
'email': kwargs.get('email_from'), 'email': kwargs.get('email_from'),
'phone': kwargs.get('phone'), 'phone': kwargs.get('phone'),
'priority': kwargs.get('priority'), 'priority': kwargs.get('priority'),
'product_id': product_list, 'product_ids': product_list,
'stage_id': lowest_stage_id.id, 'stage_id': lowest_stage_id.id,
'customer_id': customer.id, 'customer_id': customer.id,
'ticket_type': kwargs.get('ticket_type'), 'ticket_type': kwargs.get('ticket_type'),
@ -78,8 +79,9 @@ class WebsiteFormInherit(WebsiteForm):
model_record = request.env['ir.model'].sudo().search( model_record = request.env['ir.model'].sudo().search(
[('model', '=', model_name)]) [('model', '=', model_name)])
data = self.extract_data(model_record, request.params) data = self.extract_data(model_record, request.params)
if 'ticket_attachment' in request.params or request.httprequest.files or data.get( if ('ticket_attachment' in request.params or
'attachments'): request.httprequest.files or data.get(
'attachments')):
attached_files = data.get('attachments') attached_files = data.get('attachments')
for attachment in attached_files: for attachment in attached_files:
attached_file = attachment.read() attached_file = attachment.read()
@ -96,9 +98,6 @@ class WebsiteFormInherit(WebsiteForm):
request.session['form_builder_id'] = ticket_id.id request.session['form_builder_id'] = ticket_id.id
return json.dumps({'id': ticket_id.id}) return json.dumps({'id': ticket_id.id})
else: else:
lowest_sequence = tickets.filtered(
lambda x: x.sequence == min(sequence))
lowest_stage_id = lowest_sequence
rec_val = { rec_val = {
'customer_name': kwargs.get('customer_name'), 'customer_name': kwargs.get('customer_name'),
'subject': kwargs.get('subject'), 'subject': kwargs.get('subject'),
@ -117,8 +116,9 @@ class WebsiteFormInherit(WebsiteForm):
model_record = request.env['ir.model'].sudo().search( model_record = request.env['ir.model'].sudo().search(
[('model', '=', model_name)]) [('model', '=', model_name)])
data = self.extract_data(model_record, request.params) data = self.extract_data(model_record, request.params)
if 'ticket_attachment' in request.params or request.httprequest.files or data.get( if ('ticket_attachment' in request.params or
'attachments'): request.httprequest.files or data.get(
'attachments')):
attached_files = data.get('attachments') attached_files = data.get('attachments')
for attachment in attached_files: for attachment in attached_files:
attached_file = attachment.read() attached_file = attachment.read()
@ -152,8 +152,8 @@ class WebsiteFormInherit(WebsiteForm):
if id_record: if id_record:
self.insert_attachment(model_record, id_record, self.insert_attachment(model_record, id_record,
data['attachments']) data['attachments'])
# in case of an email, we want to send it immediately instead of waiting # In case of an email, we want to send it immediately instead of waiting
# for the email queue to process # For the email queue to process
if model_name == 'mail.mail': if model_name == 'mail.mail':
request.env[model_name].sudo().browse(id_record).send() request.env[model_name].sudo().browse(id_record).send()
@ -162,9 +162,7 @@ class WebsiteFormInherit(WebsiteForm):
# TODO: How to get the name of the erroneous field ? # TODO: How to get the name of the erroneous field ?
except IntegrityError: except IntegrityError:
return json.dumps(False) return json.dumps(False)
request.session['form_builder_model_model'] = model_record.model request.session['form_builder_model_model'] = model_record.model
request.session['form_builder_model'] = model_record.name request.session['form_builder_model'] = model_record.name
request.session['form_builder_id'] = id_record request.session['form_builder_id'] = id_record
return json.dumps({'id': id_record}) return json.dumps({'id': id_record})

22
odoo_website_helpdesk/data/helpdesk_types_data.xml

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Ticket types-->
<record id="helpdesk_types_question" model="helpdesk.types">
<field name="name">Question</field>
</record>
<record id="helpdesk_types_issue" model="helpdesk.types">
<field name="name">Issue</field>
</record>
<record id="helpdesk_types_repair" model="helpdesk.types">
<field name="name">Repair</field>
</record>
<record id="helpdesk_types_maintenance" model="helpdesk.types">
<field name="name">Maintenance</field>
</record>
<record id="helpdesk_categories_internal" model="helpdesk.categories">
<field name="name">Internal</field>
</record>
<record id="helpdesk_categories_technical" model="helpdesk.categories">
<field name="name">Technical</field>
</record>
</odoo>

17
odoo_website_helpdesk/data/ir_cron_data.xml

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<data noupdate="1">
<!-- Auto close ticket-->
<record id="ir_cron_auto_close_ticket" model="ir.cron">
<field name="name">Auto Close Ticket</field>
<field name="model_id"
ref="odoo_website_helpdesk.model_help_ticket"/>
<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>

8
odoo_website_helpdesk/data/ticket_sequence.xml → odoo_website_helpdesk/data/ir_sequence_data.xml

@ -1,13 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo> <odoo>
<!-- Sequence of ticket-->
<record id="sequence_help_ticket_seq" model="ir.sequence"> <record id="sequence_help_ticket_seq" model="ir.sequence">
<field name="name">Helpdesk</field> <field name="name">Helpdesk</field>
<field name="code">help.ticket</field> <field name="code">help.ticket</field>
<field name="prefix">TKT</field> <field name="prefix">TKT</field>
<field name="padding">5</field> <field name="padding">5</field>
<field eval="1" name="number_increment"/> <field name="number_increment">1</field>
<field eval="False" name="company_id"/>
</record> </record>
<!-- Sequence of invoiced ticket -->
<record id="sequence_help_ticket_inv_seq" model="ir.sequence"> <record id="sequence_help_ticket_inv_seq" model="ir.sequence">
<field name="name">Helpdesk Invoice</field> <field name="name">Helpdesk Invoice</field>
<field name="code">ticket.invoice</field> <field name="code">ticket.invoice</field>
@ -17,4 +18,3 @@
<field eval="False" name="company_id"/> <field eval="False" name="company_id"/>
</record> </record>
</odoo> </odoo>

211
odoo_website_helpdesk/data/mail_template_data.xml

@ -0,0 +1,211 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!--Ticket mail template-->
<record id="mail_template_create_ticket" model="mail.template">
<field name="name">Create Ticket</field>
<field name="model_id"
ref="odoo_website_helpdesk.model_help_ticket"/>
<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>
<!-- Helpdesk ticket Rating template-->
<record id="mail_template_ticket_rating" model="mail.template">
<field name="name">Close Ticket And Feedback</field>
<field name="model_id"
ref="odoo_website_helpdesk.model_help_ticket"/>
<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>
<!-- Ticket response sending formate-->
<record id="mail_template_ticket_reopened" model="mail.template">
<field name="name">Reopened Ticket</field>
<field name="model_id"
ref="odoo_website_helpdesk.model_help_ticket"/>
<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>
<!-- Ticket approved sending formate-->
<record id="mail_template_ticket_approved" model="mail.template">
<field name="name">Approve Ticket</field>
<field name="model_id"
ref="odoo_website_helpdesk.model_help_ticket"/>
<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>
<!-- Cancelled tickets formate-->
<record id="mail_template_ticket_canceled" model="mail.template">
<field name="name">Cancel Ticket</field>
<field name="model_id"
ref="odoo_website_helpdesk.model_help_ticket"/>
<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>
<!-- Mail formate to inform the Team to assign a task-->
<record id="mail_template_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_help_ticket"/>
<field name="body_html" type="html">
<div style="margin: 0px; padding: 0px;">
<p>Dear,
<t t-esc="object.team_head.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>
<!-- Mail sending formate to inform the user to assign the task-->
<record id="mail_template_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_help_ticket"/>
<field name="body_html" type="html">
<div style="margin: 0px; padding: 0px;">
<p>Dear,
<t t-esc="object.assigned_user.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>
<!-- Mail sending to the customer for informing the assigned user-->
<record id="mail_template_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_help_ticket"/>
<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.name"/>".
</p>
<br/>
<p>Best regards</p>
</div>
</field>
</record>
</odoo>

121
odoo_website_helpdesk/data/rating_template.xml

@ -1,121 +0,0 @@
<odoo>
<data>
<record id="ticket_created" model="mail.template">
<field name="name">Create Ticket</field>
<field name="model_id" ref="odoo_website_helpdesk.model_help_ticket"/>
<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>
<record id="helpdesk_rating" model="mail.template">
<field name="name">Close Ticket And Feedback</field>
<field name="model_id"
ref="odoo_website_helpdesk.model_help_ticket"/>
<field name="auto_delete" eval="True"/>
<!-- <field name="email_from">{{object.customer_id.email}}</field>-->
<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>
<record id="ticket_reopened" model="mail.template">
<field name="name">Reopened Ticket</field>
<field name="model_id"
ref="odoo_website_helpdesk.model_help_ticket"/>
<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>
<record id="ticket_approved" model="mail.template">
<field name="name">Approve Ticket</field>
<field name="model_id"
ref="odoo_website_helpdesk.model_help_ticket"/>
<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>
<record id="ticket_canceled" model="mail.template">
<field name="name">Cancel Ticket</field>
<field name="model_id"
ref="odoo_website_helpdesk.model_help_ticket"/>
<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>
</data>
</odoo>

79
odoo_website_helpdesk/data/ticket_auto_close.xml

@ -1,79 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<data noupdate="1">
<record id="auto_close_ticket" model="ir.cron">
<field name="name">Auto Close Ticket</field>
<field name="model_id" ref="odoo_website_helpdesk.model_help_ticket"/>
<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>
<record id="odoo_website_helpdesk_assign"
model="mail.template">
<field name="name">Ticket Assign</field>
<field name="email_from"></field>
<field name="email_to"></field>
<field name="subject"></field>
<field name="model_id"
ref="odoo_website_helpdesk.model_help_ticket"/>
<field name="body_html" type="html">
<div style="margin: 0px; padding: 0px;">
<p>Dear,<t t-esc="object.team_head.name"/></p>
<p> Your team has been given the ticket [<t t-esc="object.name"/>] kindly complete your work carefully.
</p>
<br></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></br>
<p>Best regards</p>
</div>
</field>
</record>
<record id="odoo_website_helpdesk_assign_user"
model="mail.template">
<field name="name">Ticket Assign to User</field>
<field name="email_from"></field>
<field name="email_to"></field>
<field name="subject"></field>
<field name="model_id"
ref="odoo_website_helpdesk.model_help_ticket"/>
<field name="body_html" type="html">
<div style="margin: 0px; padding: 0px;">
<p>Dear,<t t-esc="object.assigned_user.name"/></p>
<p> Ticket [<t t-esc="object.name"/>] Assign to you , kindly complete your work carefully.
</p>
<br></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></br>
<p>Best regards</p>
</div>
</field>
</record>
<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>
<field name="email_to"></field>
<field name="subject"></field>
<field name="model_id"
ref="odoo_website_helpdesk.model_help_ticket"/>
<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.name"/>".
</p>
<br></br>
<p>Best regards</p>
</div>
</field>
</record>
</data>
</odoo>

36
odoo_website_helpdesk/data/ticket_stage_data.xml

@ -1,31 +1,39 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<odoo> <odoo>
<!-- Project Stages --> <!-- Project Stages -->
<record id="stage_inbox" model="ticket.stage"> <record id="ticket_stage_inbox" model="ticket.stage">
<field name="sequence">10</field> <field name="sequence">10</field>
<field name="name">Inbox</field> <field name="name">Inbox</field>
</record> </record>
<record id="stage_draft" model="ticket.stage"> <!-- Draft-->
<record id="ticket_stage_draft" model="ticket.stage">
<field name="sequence">15</field> <field name="sequence">15</field>
<field name="name">Draft</field> <field name="name">Draft</field>
</record> </record>
<record id="stage_done" model="ticket.stage"> <!--In progress-->
<field name="sequence">25</field> <record id="ticket_stage_in_progress" model="ticket.stage">
<field name="name">Done</field>
</record>
<record id="stage_in_progress" model="ticket.stage">
<field name="sequence">20</field> <field name="sequence">20</field>
<field name="starting_stage" eval="True"/> <field name="starting_stage" eval="True"/>
<field name="name">In Progress</field> <field name="name">In Progress</field>
</record> </record>
<record id="stage_closed" model="ticket.stage"> <!--Done-->
<field name="sequence">30</field> <record id="ticket_stage_done" model="ticket.stage">
<field name="closing_stage">True</field> <field name="sequence">25</field>
<field name="name">Closed</field> <field name="name">Done</field>
<field name="folded" eval="True"/>
</record> </record>
<record id="stage_canceled" model="ticket.stage"> <!--Cancelled-->
<field name="sequence">35</field> <record id="ticket_stage_cancel" model="ticket.stage">
<field name="cancel_stage">True</field> <field name="sequence">30</field>
<field name="name">Canceled</field> <field name="name">Canceled</field>
<field name="cancel_stage" eval="True"/>
<field name="folded" eval="True"/>
</record>
<!-- Closed-->
<record id="ticket_stage_closed" model="ticket.stage">
<field name="sequence">29</field>
<field name="name">Closed</field>
<field name="closing_stage" eval="True"/>
<field name="folded" eval="True"/>
</record> </record>
</odoo> </odoo>

21
odoo_website_helpdesk/data/ticket_type.xml

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="ticket_type_1" model="helpdesk.types">
<field name="name">Question</field>
</record>
<record id="ticket_type_2" model="helpdesk.types">
<field name="name">Issue</field>
</record>
<record id="ticket_type_3" model="helpdesk.types">
<field name="name">Repair</field>
</record>
<record id="ticket_type_4" model="helpdesk.types">
<field name="name">Maintenance</field>
</record>
<record id="ticket_categories_1" model="helpdesk.categories">
<field name="name">Internal</field>
</record>
<record id="ticket_categories_2" model="helpdesk.categories">
<field name="name">Technical</field>
</record>
</odoo>

11
odoo_website_helpdesk/doc/RELEASE_NOTES.md

@ -1,13 +1,6 @@
## Module <odoo_website_helpdesk> ## Module <odoo_website_helpdesk>
#### 01.09.2023 #### 04.12.2023
#### Version 16.0.1.0.0 #### Version 16.0.1.0.0
#### ADD #### ADD
- Initial commit for Website Helpdesk Support Ticket Management
- Initial commit for Website Helpdesk Support Ticket
#### 28.11.2023
#### Version 16.0.1.0.1
#### FIX
- Updated the End date when changed the stage to Closed

19
odoo_website_helpdesk/models/__init__.py

@ -3,7 +3,7 @@
# #
# Cybrosys Technologies Pvt. Ltd. # Cybrosys Technologies Pvt. Ltd.
# #
# Copyright (C) 2022-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) # Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) # Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
# #
# You can modify it under the terms of the GNU LESSER # You can modify it under the terms of the GNU LESSER
@ -19,11 +19,16 @@
# If not, see <http://www.gnu.org/licenses/>. # If not, see <http://www.gnu.org/licenses/>.
# #
############################################################################# #############################################################################
from . import helpdesk from . import account_move
from . import task from . import help_team
from . import res_config from . import help_ticket
from . import categories from . import helpdesk_categories
from . import heldesk_team from . import helpdesk_tag
from . import mail_compose from . import helpdesk_types
from . import mail_compose_message
from . import merge_tickets from . import merge_tickets
from . import project_task
from . import res_config_settings
from . import support_tickets from . import support_tickets
from . import ticket_stage
from . import website_menu

16
odoo_website_helpdesk/models/task.py → odoo_website_helpdesk/models/account_move.py

@ -3,7 +3,7 @@
# #
# Cybrosys Technologies Pvt. Ltd. # Cybrosys Technologies Pvt. Ltd.
# #
# Copyright (C) 2022-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) # Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) # Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
# #
# You can modify it under the terms of the GNU LESSER # You can modify it under the terms of the GNU LESSER
@ -22,16 +22,10 @@
from odoo import fields, models from odoo import fields, models
class Task(models.Model):
"""Inheriting the project task"""
_inherit = 'project.task'
ticket_id = fields.Many2one('help.ticket', string='Ticket',
help='Ticket')
class AccountMove(models.Model): class AccountMove(models.Model):
"""Inheriting the account.move model""" """ This class extends the functionality of the 'account.move' model to
include a reference to a help ticket through the 'ticket_id' field."""
_inherit = 'account.move' _inherit = 'account.move'
ticket_id = fields.Many2one('help.ticket', string='Ticket') ticket_id = fields.Many2one('help.ticket', string='Ticket',
help='Choose the tickets')

59
odoo_website_helpdesk/models/heldesk_team.py

@ -1,59 +0,0 @@
# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2022-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.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 HelpDeskTeam(models.Model):
"""Helpdesk team"""
_name = 'help.team'
_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')
project_id = fields.Many2one('project.project',
string='Project',
help='Projects')
create_task = fields.Boolean(string="Create Task",
help="Task created or not")
@api.onchange('team_lead_id')
def members_choose(self):
"""Members selection function"""
fetch_memebers = self.env['res.users'].search([])
filterd_members = fetch_memebers.filtered(
lambda x: x.id != self.team_lead_id.id)
return {'domain': {'member_ids':
[('id', '=', filterd_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)]}}

65
odoo_website_helpdesk/models/help_team.py

@ -0,0 +1,65 @@
# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.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 HelpTeam(models.Model):
""" This class represents a Helpdesk Team in the system, providing
information about the team members, leader, and related project."""
_name = 'help.team'
_description = 'Helpdesk Team'
name = fields.Char(string='Name', help='Name of the Helpdesk Team. It '
'identify the helpdesk team')
team_lead_id = fields.Many2one(
'res.users',
string='Team Leader',
help='Name of the Helpdesk Team Leader.',
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='Users who belong to that Helpdesk Team',
domain=lambda self: [('groups_id', 'in', self.env.ref(
'odoo_website_helpdesk.helpdesk_user').id)])
email = fields.Char(string='Email', help='Email')
project_id = fields.Many2one('project.project',
string='Project',
help='The Project they are currently in')
create_task = fields.Boolean(string="Create Task",
help="Enable for allowing team to "
"create tasks from tickets")
@api.onchange('team_lead_id')
def members_choose(self):
""" This method is triggered when the Team Leader is changed. It
updates the available team members based on the selected leader and
filters out the leader from the list of potential members."""
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)]}}

342
odoo_website_helpdesk/models/helpdesk.py → odoo_website_helpdesk/models/help_ticket.py

@ -3,7 +3,7 @@
# #
# Cybrosys Technologies Pvt. Ltd. # Cybrosys Technologies Pvt. Ltd.
# #
# Copyright (C) 2022-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) # Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) # Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
# #
# You can modify it under the terms of the GNU LESSER # You can modify it under the terms of the GNU LESSER
@ -20,7 +20,7 @@
# #
############################################################################# #############################################################################
import logging import logging
from odoo import models, fields, api, _ from odoo import api, fields, models, _
from odoo.exceptions import UserError from odoo.exceptions import UserError
from odoo.exceptions import ValidationError from odoo.exceptions import ValidationError
@ -43,111 +43,155 @@ RATING = [
] ]
class HelpDeskTicket(models.Model): class HelpTicket(models.Model):
"""Help_ticket model""" """This model represents the Helpdesk Ticket, which allows users to raise
tickets related to products, services or any other issues. Each ticket has a
name, customer information, description, team responsible for handling
requests, associated project, priority level, stage, cost per hour, service
product, start and end dates, and related tasks and invoices."""
_name = 'help.ticket' _name = 'help.ticket'
_description = 'Helpdesk Ticket' _description = 'Help Ticket'
_inherit = ['mail.thread', 'mail.activity.mixin'] _inherit = ['mail.thread', 'mail.activity.mixin']
name = fields.Char('Name', default=lambda self: self.env['ir.sequence']. name = fields.Char(string='Name', default=lambda self: _('New'),
next_by_code('help.ticket') or _('New')) help='The name of the help ticket. By default, a new '
'unique sequence number is assigned to each '
'help ticket, unless a name is provided.',
readonly=True)
active = fields.Boolean(default=True, help='Active', string='Active')
customer_id = fields.Many2one('res.partner', customer_id = fields.Many2one('res.partner',
string='Customer Name', string='Customer Name',
help='Customer Name') help='Select the Customer Name')
customer_name = fields.Char('Customer Name', help='Customer Name') customer_name = fields.Char(string='Customer Name',
subject = fields.Text('Subject', required=True, help='Add the Customer Name')
subject = fields.Text(string='Subject', required=True,
help='Subject of the Ticket') help='Subject of the Ticket')
description = fields.Text('Description', required=True, description = fields.Text(string='Description', required=True,
help='Description') help='Issue Description')
email = fields.Char('Email', help='Email') email = fields.Char(string='Email', help='Email of the User.')
phone = fields.Char('Phone', help='Contact Number') phone = fields.Char(string='Phone', help='Phone Number of the user')
team_id = fields.Many2one('help.team', string='Helpdesk Team', team_id = fields.Many2one('help.team', string='Helpdesk Team',
help='Helpdesk Team Name') help='The helpdesk team responsible for '
product_id = fields.Many2many('product.template', 'handling requests related to this '
string='Product', 'record')
help='Product Name') product_ids = fields.Many2many('product.template',
string='Product',
help='The product associated with this '
'record.This field allows you to select'
'an existing product from the product '
'catalog.')
project_id = fields.Many2one('project.project', project_id = fields.Many2one('project.project',
string='Project', string='Project',
readonly=False, readonly=False,
related='team_id.project_id', related='team_id.project_id',
store=True, store=True,
help='Project Name') help='The project associated with this team.'
'This field is automatically filled '
priority = fields.Selection(PRIORITIES, default='1', help='Priority of the' 'based on the project assigned to '
' Ticket') 'the team.')
priority = fields.Selection(PRIORITIES,
default='1',
help='Set the priority level',
string='Priority')
stage_id = fields.Many2one('ticket.stage', string='Stage', stage_id = fields.Many2one('ticket.stage', string='Stage',
default=lambda self: self.env[ default=lambda self: self.env[
'ticket.stage'].search( 'ticket.stage'].search(
[('name', '=', 'Draft')], limit=1).id, [('name', '=', 'Draft')], limit=1).id,
tracking=True, tracking=True,
group_expand='_read_group_stage_ids', group_expand='_read_group_stage_ids',
help='Stages') help='Stages of the ticket.')
user_id = fields.Many2one('res.users', user_id = fields.Many2one('res.users',
default=lambda self: self.env.user, default=lambda self: self.env.user,
check_company=True, check_company=True,
index=True, tracking=True, index=True, tracking=True,
help='Login User') help='Login User')
cost = fields.Float('Cost per hour', help='Cost Per Unit') cost = fields.Float(string='Cost per hour',
help='The cost per hour for this record. This field '
'specifies the hourly cost associated with the'
'record, which can be used in various '
'calculations or reports.')
service_product_id = fields.Many2one('product.product', service_product_id = fields.Many2one('product.product',
string='Service Product', string='Service Product',
help='Service Product', help='The product associated with this'
'service. Only service products '
'are available for selection.',
domain=[ domain=[
('detailed_type', '=', 'service')]) ('detailed_type', '=', 'service')])
create_date = fields.Datetime('Creation Date', help='Created date') create_date = fields.Datetime(string='Creation Date', help='Created date of'
start_date = fields.Datetime('Start Date', help='Start Date') 'the Ticket')
end_date = fields.Datetime('End Date', help='End Date') start_date = fields.Datetime(string='Start Date', help='Start Date of the '
'Ticket')
end_date = fields.Datetime(string='End Date', help='End Date of the Ticket')
public_ticket = fields.Boolean(string="Public Ticket", help='Public Ticket') public_ticket = fields.Boolean(string="Public Ticket", help='Public Ticket')
invoice_ids = fields.Many2many('account.move', invoice_ids = fields.Many2many('account.move',
string='Invoices', string='Invoices',
help='Invoicing id' help='To Generate Invoice based on hours '
'spent on the ticket'
) )
task_ids = fields.Many2many('project.task', task_ids = fields.Many2many('project.task',
string='Tasks', string='Tasks',
help='Task id') help='Related Task of the Ticket')
color = fields.Integer(string="Color", help='Color') color = fields.Integer(string="Color", help='Color')
replied_date = fields.Datetime('Replied date', help='Replied Date') replied_date = fields.Datetime(string='Replied date',
last_update_date = fields.Datetime('Last Update Date', help='Replied Date of the Ticket')
help='Last Update Date') last_update_date = fields.Datetime(string='Last Update Date',
help='Last Update Date of Ticket')
ticket_type = fields.Many2one('helpdesk.types', ticket_type = fields.Many2one('helpdesk.types',
string='Ticket Type', help='Ticket Type') string='Ticket Type', help='Ticket Type')
team_head = fields.Many2one('res.users', string='Team Leader', team_head = fields.Many2one('res.users', string='Team Leader',
compute='_compute_team_head', compute='_compute_team_head',
help='Team Leader Name') help='Team Leader Name')
assigned_user = fields.Many2one('res.users', assigned_user = fields.Many2one(
domain=lambda self: [ 'res.users',
('groups_id', 'in', self.env.ref( string='Assigned User',
'odoo_website_helpdesk.helpdesk_user').id)], domain=lambda self: [('groups_id', 'in', self.env.ref(
help='Assigned User Name') 'odoo_website_helpdesk.helpdesk_user').id)],
help='Choose the Assigned User Name')
category_id = fields.Many2one('helpdesk.categories', category_id = fields.Many2one('helpdesk.categories',
help='Category') help='Choose the Category', string='Category')
tags = fields.Many2many('helpdesk.tag', help='Tags') tags = fields.Many2many('helpdesk.tag', help='Choose the Tags',
assign_user = fields.Boolean(default=False, help='Assign User') string='Tag')
attachment_ids = fields.One2many('ir.attachment', 'res_id', assign_user = fields.Boolean(string='Assigned User', help='Assign User')
help='Attachment Line') attachment_ids = fields.One2many('ir.attachment',
'res_id',
help='Attachment Line',
string='Attachment')
merge_ticket_invisible = fields.Boolean(string='Merge Ticket', merge_ticket_invisible = fields.Boolean(string='Merge Ticket',
help='Merge Ticket Invisible or ' help='Merge Ticket Invisible or '
'Not', default=False) 'Not')
merge_count = fields.Integer(string='Merge Count', help='Merged Tickets ' merge_count = fields.Integer(string='Merge Count', help='Merged Tickets '
'Count') 'Count')
active = fields.Boolean(default=True, help='Active', string='Active')
@api.onchange('team_id', 'team_head') @api.onchange('team_id', 'team_head')
def team_leader_domain(self): def team_leader_domain(self):
"""Changing the team leader when selecting the team""" """Update the domain for the assigned user based on the selected team.
li = []
This onchange method is triggered when the helpdesk team or team leader
is changed. It updates the domain for the assigned user field to include
only the members of the selected team."""
teams = []
for rec in self.team_id.member_ids: for rec in self.team_id.member_ids:
li.append(rec.id) teams.append(rec.id)
return {'domain': {'assigned_user': [('id', 'in', li)]}} return {'domain': {'assigned_user': [('id', 'in', teams)]}}
@api.depends('team_id') @api.depends('team_id')
def _compute_team_head(self): def _compute_team_head(self):
"""Compute the team head function""" """Compute the team head based on the selected team.
This method is triggered when the helpdesk team is changed. It computes
and updates the team head field based on the team's lead.
"""
self.team_head = self.team_id.team_lead_id.id self.team_head = self.team_id.team_lead_id.id
@api.onchange('stage_id') @api.onchange('stage_id')
def mail_snd(self): def mail_snd(self):
"""Sending mail to the user function""" """Send an email when the stage of the ticket is changed.
This onchange method is triggered when the stage of the ticket is
changed. It updates the last update date, start date, and end date
fields accordingly. If a template is associated with the stage, it
sends an email using that template."""
rec_id = self._origin.id rec_id = self._origin.id
data = self.env['help.ticket'].search([('id', '=', rec_id)]) data = self.env['help.ticket'].search([('id', '=', rec_id)])
data.last_update_date = fields.Datetime.now() data.last_update_date = fields.Datetime.now()
@ -160,11 +204,16 @@ class HelpDeskTicket(models.Model):
mail_template.send_mail(self._origin.id, force_send=True) mail_template.send_mail(self._origin.id, force_send=True)
def assign_to_teamleader(self): def assign_to_teamleader(self):
"""Assigning team leader function""" """Assign the ticket to the team leader and send a notification.
This function checks if a helpdesk team is selected and assigns the
team leader to the ticket. It then sends a notification email to the
team leader."""
if self.team_id: if self.team_id:
self.team_head = self.team_id.team_lead_id.id self.team_head = self.team_id.team_lead_id.id
mail_template = self.env.ref( mail_template = self.env.ref(
'odoo_website_helpdesk.odoo_website_helpdesk_assign') 'odoo_website_helpdesk.'
'mail_template_odoo_website_helpdesk_assign')
mail_template.sudo().write({ mail_template.sudo().write({
'email_to': self.team_head.email, 'email_to': self.team_head.email,
'subject': self.name 'subject': self.name
@ -174,27 +223,42 @@ class HelpDeskTicket(models.Model):
raise ValidationError("Please choose a Helpdesk Team") raise ValidationError("Please choose a Helpdesk Team")
def _default_show_create_task(self): def _default_show_create_task(self):
"""Task creation""" """Get the default value for the 'show_create_task' field.
This method retrieves the default value for the 'show_create_task'
field from the configuration settings."""
return self.env['ir.config_parameter'].sudo().get_param( return self.env['ir.config_parameter'].sudo().get_param(
'odoo_website_helpdesk.show_create_task') 'odoo_website_helpdesk.show_create_task')
show_create_task = fields.Boolean(string="Create Task", show_create_task = fields.Boolean(string="Create Task",
default=_default_show_create_task, default=_default_show_create_task,
compute='_compute_show_create_task') compute='_compute_show_create_task',
help='Determines whether the Create Task'
' button should be shown for this '
'ticket.')
create_task = fields.Boolean(string="Create Task", readonly=False, create_task = fields.Boolean(string="Create Task", readonly=False,
related='team_id.create_task', store=True) related='team_id.create_task',
billable = fields.Boolean(string="Billable", default=False) store=True,
help='Defines if a task should be created when'
' this ticket is created.')
billable = fields.Boolean(string="Billable", help='Indicates whether the '
'ticket is billable or '
'not.')
def _default_show_category(self): def _default_show_category(self):
"""Show category default""" """Its display the default category"""
return self.env['ir.config_parameter'].sudo().get_param( return self.env['ir.config_parameter'].sudo().get_param(
'odoo_website_helpdesk.show_category') 'odoo_website_helpdesk.show_category')
show_category = fields.Boolean(default=_default_show_category, show_category = fields.Boolean(default=_default_show_category,
compute='_compute_show_category') compute='_compute_show_category',
customer_rating = fields.Selection(RATING, default='0', readonly=True) help='Display the default category')
customer_rating = fields.Selection(RATING, default='0', readonly=True,
review = fields.Char('Review', readonly=True) string='Customer Rating',
help='Display the customer rating.')
review = fields.Char(string='Review', readonly=True,
help='Customer review of the ticket.')
kanban_state = fields.Selection([ kanban_state = fields.Selection([
('normal', 'Ready'), ('normal', 'Ready'),
('done', 'In Progress'), ('done', 'In Progress'),
@ -207,13 +271,14 @@ class HelpDeskTicket(models.Model):
rec.show_category = show_category rec.show_category = show_category
def _compute_show_create_task(self): def _compute_show_create_task(self):
"""Compute the created task""" """Compute the value of the 'show_create_task' field for each record in
the current recordset."""
show_create_task = self._default_show_create_task() show_create_task = self._default_show_create_task()
for record in self: for record in self:
record.show_create_task = show_create_task record.show_create_task = show_create_task
def auto_close_ticket(self): def auto_close_ticket(self):
"""Automatically closing the ticket""" """Automatically closing the ticket based on the closing date."""
auto_close = self.env['ir.config_parameter'].sudo().get_param( auto_close = self.env['ir.config_parameter'].sudo().get_param(
'odoo_website_helpdesk.auto_close_ticket') 'odoo_website_helpdesk.auto_close_ticket')
if auto_close: if auto_close:
@ -229,39 +294,46 @@ class HelpDeskTicket(models.Model):
rec.stage_id = close_stage_id rec.stage_id = close_stage_id
def default_stage_id(self): def default_stage_id(self):
# Search your stage """Search your stage"""
return self.env['ticket.stage'].search( return self.env['ticket.stage'].search(
[('name', '=', 'Draft')], limit=1).id [('name', '=', 'Draft')], limit=1).id
@api.model @api.model
def _read_group_stage_ids(self, stages, domain, order): def _read_group_stage_ids(self, stages, domain, order):
""" """
return the stages to stage_ids Return the available stages for grouping.
This static method is used to provide the available stages for
grouping when displaying records in a grouped view.
""" """
stage_ids = self.env['ticket.stage'].search([]) stage_ids = self.env['ticket.stage'].search([])
return stage_ids return stage_ids
@api.model_create_multi @api.model
def create(self, vals_list): def create(self, vals_list):
"""Create function""" """Create a new helpdesk ticket.
return super(HelpDeskTicket, self).create(vals_list) This method is called when creating a new helpdesk ticket. It
generates a unique name for the ticket using a sequence if no
def write(self, vals): name is provided.
"""Write function""" """
result = super(HelpDeskTicket, self).write(vals) if vals_list.get('name', _('New')) == _('New'):
return result vals_list['name'] = self.env['ir.sequence'].next_by_code(
'help.ticket') or _('New')
def create_invoice(self): return super().create(vals_list)
"""Create Invoice based on the ticket"""
def action_create_invoice(self):
"""Create Invoice for Help Desk Ticket.
This function creates an invoice for the help desk ticket based on
the associated tasks with billed hours.
"""
tasks = self.env['project.task'].search( tasks = self.env['project.task'].search(
[('project_id', '=', self.project_id.id), [('project_id', '=', self.project_id.id),
('ticket_id', '=', self.id)]).filtered( ('ticket_id', '=', self.id)]).filtered(
lambda line: line.ticket_billed == False) lambda line: line.ticket_billed == True)
if not tasks: if not tasks:
raise UserError('No Tasks to Bill') raise UserError('No Tasks to Bill')
total = sum(x.effective_hours for x in tasks if x.effective_hours > 0) total = sum(x.effective_hours for x in tasks if x.effective_hours > 0)
invoice_no = self.env['ir.sequence'].next_by_code( invoice_no = self.env['ir.sequence'].next_by_code(
'ticket.invoice') 'ticket.invoice')
self.env['account.move'].create([ self.env['account.move'].create([
@ -272,14 +344,15 @@ class HelpDeskTicket(models.Model):
'ticket_id': self.id, 'ticket_id': self.id,
'date': fields.Date.today(), 'date': fields.Date.today(),
'invoice_date': fields.Date.today(), 'invoice_date': fields.Date.today(),
'invoice_line_ids': [(0, 0, 'invoice_line_ids':
{'product_id': self.service_product_id.id, [(0, 0, {'product_id': self.service_product_id.id,
'name': self.service_product_id.name, 'name': self.service_product_id.name,
'quantity': total, 'quantity': total,
'product_uom_id': self.service_product_id.uom_id.id, 'product_uom_id': self.service_product_id.uom_id.id,
'price_unit': self.cost, 'price_unit': self.cost,
'account_id': self.service_product_id.categ_id.property_account_income_categ_id.id, 'account_id':
})], self.service_product_id.categ_id.property_account_income_categ_id.id,
})],
}, ]) }, ])
for task in tasks: for task in tasks:
task.ticket_billed = True task.ticket_billed = True
@ -291,8 +364,11 @@ class HelpDeskTicket(models.Model):
} }
} }
def create_tasks(self): def action_create_tasks(self):
"""Task creation""" """Create Task for HelpDesk Ticket
This function creates a task associated with the helpdesk ticket
and updates the task_ids field.
"""
task_id = self.env['project.task'].create({ task_id = self.env['project.task'].create({
'name': self.name + '-' + self.subject, 'name': self.name + '-' + self.subject,
'project_id': self.project_id.id, 'project_id': self.project_id.id,
@ -302,7 +378,6 @@ class HelpDeskTicket(models.Model):
self.write({ self.write({
'task_ids': [(4, task_id.id)] 'task_ids': [(4, task_id.id)]
}) })
return { return {
'name': 'Tasks', 'name': 'Tasks',
'res_model': 'project.task', 'res_model': 'project.task',
@ -313,8 +388,8 @@ class HelpDeskTicket(models.Model):
'target': 'new', 'target': 'new',
} }
def open_tasks(self): def action_open_tasks(self):
"""View the Created task """ """Smart Button of Task to view the Tasks of HelpDesk Ticket"""
return { return {
'name': 'Tasks', 'name': 'Tasks',
'domain': [('ticket_id', '=', self.id)], 'domain': [('ticket_id', '=', self.id)],
@ -324,8 +399,8 @@ class HelpDeskTicket(models.Model):
'type': 'ir.actions.act_window', 'type': 'ir.actions.act_window',
} }
def open_invoices(self): def action_open_invoices(self):
"""View the Created invoice""" """Smart Button of Invoice to view the Invoices for HelpDesk Ticket"""
return { return {
'name': 'Invoice', 'name': 'Invoice',
'domain': [('ticket_id', '=', self.id)], 'domain': [('ticket_id', '=', self.id)],
@ -335,8 +410,8 @@ class HelpDeskTicket(models.Model):
'type': 'ir.actions.act_window', 'type': 'ir.actions.act_window',
} }
def open_merged_tickets(self): def action_open_merged_tickets(self):
"""Open the merged tickets tree view""" """ Smart button of the merged tickets"""
ticket_ids = self.env['support.tickets'].search( ticket_ids = self.env['support.tickets'].search(
[('merged_ticket', '=', self.id)]) [('merged_ticket', '=', self.id)])
# Get the display_name matching records from the support.tickets # Get the display_name matching records from the support.tickets
@ -354,7 +429,10 @@ class HelpDeskTicket(models.Model):
} }
def action_send_reply(self): def action_send_reply(self):
"""Action to sent reply button""" """Compose and send a reply to the customer.
This function opens a window for composing and sending a reply to
the customer. It uses the configured email template for replies.
"""
template_id = self.env['ir.config_parameter'].sudo().get_param( template_id = self.env['ir.config_parameter'].sudo().get_param(
'odoo_website_helpdesk.reply_template_id' 'odoo_website_helpdesk.reply_template_id'
) )
@ -385,67 +463,3 @@ class HelpDeskTicket(models.Model):
'default_res_id': self.id, 'default_res_id': self.id,
} }
} }
class StageTicket(models.Model):
"""Stage Ticket class"""
_name = 'ticket.stage'
_description = 'Ticket Stage'
_order = 'sequence, id'
_fold_name = 'fold'
name = fields.Char('Name', help='Name')
active = fields.Boolean(default=True, help='Active', string='Active')
sequence = fields.Integer(default=50, help='Sequence', string='Sequence')
closing_stage = fields.Boolean('Closing Stage', default=False,
help='Closing stage')
cancel_stage = fields.Boolean('Cancel Stage', default=False,
help='Cancel stage')
starting_stage = fields.Boolean('Start Stage', default=False,
help='Starting Stage')
folded = fields.Boolean('Folded in Kanban', default=False,
help='Folded Stage')
template_id = fields.Many2one('mail.template',
help='Templates',
domain="[('model', '=', 'help.ticket')]")
group_ids = fields.Many2many('res.groups', help='Group ID')
fold = fields.Boolean(string='Fold', help='Folded')
def unlink(self):
"""Unlinking Function"""
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
class HelpdeskTypes(models.Model):
"""Helpdesk types """
_name = 'helpdesk.types'
_description = 'Helpdesk Types'
name = fields.Char(string='Type', help='Types')
class Tasks(models.Model):
"""Inheriting the task"""
_inherit = 'project.task'
ticket_billed = fields.Boolean('Billed', default=False,
help='Billed Tickets')
class HelpdeskTags(models.Model):
"""Helpdesk tags"""
_name = 'helpdesk.tag'
_description = 'Helpdesk Tags'
name = fields.Char(string='Tag', help='Tag Name')

34
odoo_website_helpdesk/models/helpdesk_categories.py

@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.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 HelpdeskCategories(models.Model):
"""This class represents the Helpdesk Categories, providing information
about different categories that can be assigned to helpdesk items.
"""
_name = 'helpdesk.categories'
_description = 'Helpdesk Categories'
name = fields.Char(string='Name', help='Category Name')
sequence = fields.Integer(string='Sequence', default=0,
help='Sequence of a Category')

13
odoo_website_helpdesk/models/categories.py → odoo_website_helpdesk/models/helpdesk_tag.py

@ -3,7 +3,7 @@
# #
# Cybrosys Technologies Pvt. Ltd. # Cybrosys Technologies Pvt. Ltd.
# #
# Copyright (C) 2022-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) # Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) # Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
# #
# You can modify it under the terms of the GNU LESSER # You can modify it under the terms of the GNU LESSER
@ -22,10 +22,9 @@
from odoo import fields, models from odoo import fields, models
class HelpdeskCategories(models.Model): class HelpdeskTag(models.Model):
"""Category Model""" """ Its handle to control the helpdesk ticket tags"""
_name = 'helpdesk.categories' _name = 'helpdesk.tag'
_description = 'Categories' _description = 'Helpdesk Tag'
name = fields.Char('Name', help='Category Name') name = fields.Char(string='Tag', help='Choose the tags')
sequence = fields.Integer('Sequence', default=0, help='Sequence')

30
odoo_website_helpdesk/models/helpdesk_types.py

@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.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 HelpdeskTypes(models.Model):
"""Its handle to control helpdesk ticket types """
_name = 'helpdesk.types'
_description = 'Helpdesk Types'
name = fields.Char(string='Type', help='Types helpdesk tickets')

13
odoo_website_helpdesk/models/mail_compose.py → odoo_website_helpdesk/models/mail_compose_message.py

@ -3,7 +3,7 @@
# #
# Cybrosys Technologies Pvt. Ltd. # Cybrosys Technologies Pvt. Ltd.
# #
# Copyright (C) 2022-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) # Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) # Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
# #
# You can modify it under the terms of the GNU LESSER # You can modify it under the terms of the GNU LESSER
@ -23,11 +23,18 @@ from odoo import fields, models
class MailComposeMessage(models.TransientModel): class MailComposeMessage(models.TransientModel):
"""Inheriting the Mail compose message""" """ This class extends the functionality of the 'mail.compose.message'
model to include custom behavior for sending emails related to help tickets.
"""
_inherit = 'mail.compose.message' _inherit = 'mail.compose.message'
def _action_send_mail(self, auto_commit=False): def _action_send_mail(self, auto_commit=False):
"""Send mail function""" """Override of the base '_action_send_mail' method to include additional
logic when sending emails related to help tickets.
If the model associated with the mail is 'help.ticket', update the
'replied_date' field of the associated help ticket to the current date.
"""
if self.model == 'help.ticket': if self.model == 'help.ticket':
ticket_id = self.env['help.ticket'].browse(self.res_id) ticket_id = self.env['help.ticket'].browse(self.res_id)
ticket_id.replied_date = fields.Date.today() ticket_id.replied_date = fields.Date.today()

38
odoo_website_helpdesk/models/merge_tickets.py

@ -3,7 +3,7 @@
# #
# Cybrosys Technologies Pvt. Ltd. # Cybrosys Technologies Pvt. Ltd.
# #
# Copyright (C) 2022-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) # Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) # Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
# #
# You can modify it under the terms of the GNU LESSER # You can modify it under the terms of the GNU LESSER
@ -22,37 +22,42 @@
from odoo import api, fields, models from odoo import api, fields, models
class MergeTicket(models.Model): class MergeTickets(models.Model):
"""Tickets merging class""" """Tickets merging class
This class allows users to merge support tickets or create new ones.
It provides functionality to consolidate information from multiple tickets.
"""
_name = 'merge.tickets' _name = 'merge.tickets'
_description = 'Merging the selected tickets' _description = 'Merge Tickets'
_rec_name = 'support_ticket_id' _rec_name = 'support_ticket_id'
user_id = fields.Many2one('res.partner', user_id = fields.Many2one('res.partner',
string='Responsible User', string='Responsible User',
help='Responsible user name', help='Responsible user name',
default=lambda self: self.env.user.partner_id.id) default=lambda self: self.env.user.partner_id.id)
support_team_id = fields.Many2one('help.team', string='Support Team', support_team_id = fields.Many2one('help.team',
string='Support Team',
help='Support Team Name') help='Support Team Name')
customer_id = fields.Many2one('res.partner', string='Customer', customer_id = fields.Many2one('res.partner',
string='Customer',
help='Customer Name' help='Customer Name'
) )
support_ticket_id = fields.Many2one('help.ticket', support_ticket_id = fields.Many2one('help.ticket',
string='Support Ticket') string='Support Ticket')
new_ticket = fields.Boolean(string='Create New Ticket ?', new_ticket = fields.Boolean(string='Create New Ticket ?',
help='Creating new tickets or not.', help='Creating new tickets or not.',
default=False) )
subject = fields.Char(string='Subject', help='Enter the New Ticket Subject') subject = fields.Char(string='Subject', help='Enter the New Ticket Subject')
merge_reason = fields.Char(string='Merge Reason', help='Merging Reason') merge_reason = fields.Char(string='Merge Reason', help='Merging Reason')
support_ticket_ids = fields.One2many('support.tickets', support_ticket_ids = fields.One2many('support.tickets',
'support_ticket_id', 'support_ticket_id',
string='Support Tickets', string='Support Tickets',
helps='Merged tickets') helps='Merged tickets')
active = fields.Boolean(string='Disable Record', help='Disable Record', active = fields.Boolean(string='Disable Record', help='Disable Record')
default=True)
def default_get(self, fields_list): def default_get(self, fields_list):
defaults = super(MergeTicket, self).default_get(fields_list) """It handles to get the default pre-filled the values """
defaults = super().default_get(fields_list)
active_ids = self._context.get('active_ids', []) active_ids = self._context.get('active_ids', [])
selected_tickets = self.env['help.ticket'].browse(active_ids) selected_tickets = self.env['help.ticket'].browse(active_ids)
customer_ids = selected_tickets.mapped('customer_id') customer_ids = selected_tickets.mapped('customer_id')
@ -60,7 +65,8 @@ class MergeTicket(models.Model):
display_names = selected_tickets.mapped('display_name') display_names = selected_tickets.mapped('display_name')
helpdesk_team = selected_tickets.mapped('team_id') helpdesk_team = selected_tickets.mapped('team_id')
descriptions = selected_tickets.mapped('description') descriptions = selected_tickets.mapped('description')
if len(customer_ids): # Ensure both selected records have the same customer # Ensure both selected records have the same customer
if len(customer_ids):
defaults.update({ defaults.update({
'customer_id': customer_ids[0].id, 'customer_id': customer_ids[0].id,
'support_team_id': helpdesk_team, 'support_team_id': helpdesk_team,
@ -80,10 +86,10 @@ class MergeTicket(models.Model):
"""Merging the tickets or creating new tickets""" """Merging the tickets or creating new tickets"""
if self.new_ticket: if self.new_ticket:
description = "\n\n".join( description = "\n\n".join(
f"{ticket.subject}\n{'-' * len(ticket.subject)}\n{ticket.description}" f"{ticket.subject}\n{'-' * len(ticket.subject)}\n"
f"{ticket.description}"
for ticket in self.support_ticket_ids for ticket in self.support_ticket_ids
) )
self.env['help.ticket'].create({ self.env['help.ticket'].create({
'subject': self.subject, 'subject': self.subject,
'description': description, 'description': description,
@ -93,10 +99,12 @@ class MergeTicket(models.Model):
else: else:
if len(self.support_ticket_ids): if len(self.support_ticket_ids):
description = "\n\n".join( description = "\n\n".join(
f"{ticket.subject}\n{'-' * len(ticket.subject)}\n{ticket.description}" f"{ticket.subject}\n{'-' * len(ticket.subject)}\n"
f"{ticket.description}"
for ticket in self.support_ticket_ids for ticket in self.support_ticket_ids
) )
# Update the existing support_ticket with the combined information # Update the existing support_ticket with the combined
# Information
self.support_ticket_id.write({ self.support_ticket_id.write({
'description': description, 'description': description,
'merge_ticket_invisible': True, 'merge_ticket_invisible': True,

42
odoo_website_helpdesk/models/project_task.py

@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.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):
"""
This class extends the 'project.task' model in Odoo to add a custom field
called 'ticket_billed' and 'ticket_id'.
ticket_billed: A boolean field indicating whether the ticket has
been billed or not.
ticket_id : A many2One field to link the task
with a help ticket
"""
_inherit = 'project.task'
ticket_billed = fields.Boolean(string='Billed',
help='Whether the Ticket has been Invoiced'
'or Not')
ticket_id = fields.Many2one('help.ticket', string='Ticket',
help='The help ticket associated with this '
'recordThis field allows you to link '
'this record to an existing help ticket.')

100
odoo_website_helpdesk/models/res_config.py

@ -1,100 +0,0 @@
# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2022-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.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 Menu(models.Model):
"""Inheriting the website menu"""
_inherit = "website.menu"
def _compute_visible(self):
"""Compute visible"""
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 show_menu_header == False:
menu.is_visible = False
if menu.name == 'Helpdesk' and show_menu_header == True:
menu.is_visible = True
class Helpdesk(models.TransientModel):
"""Inheriting the res config"""
_inherit = 'res.config.settings'
show_create_task = fields.Boolean(string="Create Tasks",
config_parameter='odoo_website_helpdesk.show_create_task',
help='Create Task')
show_category = fields.Boolean(string="Category",
config_parameter='odoo_website_helpdesk.show_category',
help='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 = fields.Many2one(
'ticket.stage', string='Closing stage',
help='Closing Stage',
config_parameter='odoo_website_helpdesk.closed_stage')
reply_template_id = fields.Many2one('mail.template',
domain="[('model', '=', 'help.ticket')]",
config_parameter='odoo_website_helpdesk.reply_template_id',
help='Reply Template')
helpdesk_menu_show = fields.Boolean('Helpdesk Menu',
config_parameter=
'odoo_website_helpdesk.helpdesk_menu_show',
help='Helpdesk menu')
@api.onchange('closed_stage')
def closed_stage_a(self):
"""Closing stage function"""
if self.closed_stage:
stage = self.closed_stage.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 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)]
})

100
odoo_website_helpdesk/models/res_config_settings.py

@ -0,0 +1,100 @@
# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.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):
"""This class extends the functionality of the 'res.config.settings' model
to provide configuration options for various settings related to the
helpdesk module.
"""
_inherit = 'res.config.settings'
show_create_task = fields.Boolean(
string="Create Tasks",
config_parameter='odoo_website_helpdesk.show_create_task',
help='When enabling this field yu can create a task under the ticket')
show_category = fields.Boolean(
string="Category",
config_parameter='odoo_website_helpdesk.show_category',
help='When enabling this its show the category of ticket',
implied_group='odoo_website_helpdesk.group_show_category')
product_website = fields.Boolean(
string="Product On Website",
config_parameter='odoo_website_helpdesk.product_website',
help='When enabling this feature you can mention the product on website'
' at time of creating the ticketProduct on website')
auto_close_ticket = fields.Boolean(
string="Auto Close Ticket",
config_parameter='odoo_website_helpdesk.auto_close_ticket',
help='Automatically Close ticket if the condition is satisfied')
no_of_days = fields.Integer(
string="No Of Days",
config_parameter='odoo_website_helpdesk.no_of_days',
help='After this date the ticket will closing automatically ')
closed_stage = fields.Many2one(
'ticket.stage', string='Closing stage',
help='Closing Stage',
config_parameter='odoo_website_helpdesk.closed_stage')
reply_template_id = fields.Many2one(
'mail.template',
string='Relaid ID',
domain="[('model', '=', 'help.ticket')]",
config_parameter='odoo_website_helpdesk.reply_template_id',
help='Reply Template')
helpdesk_menu_show = fields.Boolean(
string='Helpdesk Menu',
config_parameter='odoo_website_helpdesk.helpdesk_menu_show',
help='When enabling this option to visible Helpdesk menu in website')
@api.onchange('closed_stage')
def closed_stage_a(self):
"""This method is triggered when the 'closed_stage' field is changed.
It updates the 'closing_stage' attribute of the selected stage and
clears it for other stages.
"""
stage = self.closed_stage.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 show_category_subcategory(self):
""" This constraint method is triggered when the 'show_category' field
is changed. It updates the users in the 'group_show_category' based on
the 'show_category' value.
"""
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)]
})

4
odoo_website_helpdesk/models/support_tickets.py

@ -3,7 +3,7 @@
# #
# Cybrosys Technologies Pvt. Ltd. # Cybrosys Technologies Pvt. Ltd.
# #
# Copyright (C) 2022-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) # Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) # Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
# #
# You can modify it under the terms of the GNU LESSER # You can modify it under the terms of the GNU LESSER
@ -23,7 +23,7 @@ from odoo import fields, models
class SupportTickets(models.Model): class SupportTickets(models.Model):
"""Creating onetoMany model""" """Creating onetoMany model to handle the merging ticket"""
_name = 'support.tickets' _name = 'support.tickets'
_description = 'Support Tickets' _description = 'Support Tickets'

98
odoo_website_helpdesk/models/ticket_stage.py

@ -0,0 +1,98 @@
# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.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):
"""This model represents the stages of a helpdesk ticket. A stage is used to
indicate the current state of a ticket, such as 'New', 'In Progress',
'Resolved', or 'Closed'. Stages are used to organize and track the
progress of tickets throughout their lifecycle."""
_name = 'ticket.stage'
_description = 'Ticket Stage'
_order = 'sequence, id'
_fold_name = 'fold'
name = fields.Char(string='Name', help='The name of the stage. This field'
' is used to identify the stage and'
' is displayed in various views '
'and reports.')
active = fields.Boolean(default=True,
string='Active',
help='Whether the stage is active or not. If this '
'field is set to False,the stage will not be '
'displayed in various views and reports.')
sequence = fields.Integer(string='Sequence',
default=50,
help='The sequence number of the stage. This '
'field is used to specify the order in which'
' the stages are displayed in various views '
'and reports.', )
closing_stage = fields.Boolean(string='Closing Stage',
help='Whether the stage is a closing stage '
'or not. A closing stage is a stage '
'that indicates that the helpdesk '
'ticket has been resolved or closed.'
' This field is used to identify the '
'closing stage and is used in various '
'calculations and reports.')
cancel_stage = fields.Boolean(string='Cancel Stage',
help='Whether the stage is a cancel stage '
'or not. A cancel stage is a stage that'
'indicate the helpdesk tickets has been '
'cancelled or removed')
starting_stage = fields.Boolean(string='Start Stage',
help='Starting ticket Stage')
folded = fields.Boolean(string='Folded in Kanban',
help='Whether the stage is folded in the Kanban '
'view or not. If this field is set to True,'
' the stage will be displayed in a collapsed '
'state in the Kanban view, which can be '
'expanded by clicking on it.This field is '
'used to control the behavior of the '
'Kanban view.')
template_id = fields.Many2one('mail.template',
string='Template',
help='Choose the template',
domain="[('model', '=', 'help.ticket')]")
group_ids = fields.Many2many('res.groups',
string='Group',
help='Choose the group ID')
fold = fields.Boolean(string='Fold', help='When enabling this the ticket '
'stage will folded on the view')
def unlink(self):
"""Deleting the helpdesk tickets from various 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

61
odoo_website_helpdesk/models/website_menu.py

@ -0,0 +1,61 @@
# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.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.
This class inherits from the 'website.menu' model and extends its
functionality to compute the visibility of the menu
item based on the value of the 'odoo_website_helpdesk.helpdesk_menu_show'
configuration parameter.
Attributes:
_inherit (str): The name of the model being inherited.
"""
_inherit = "website.menu"
def _compute_visible(self):
"""
Compute the visibility of the menu item.
This method is used to determine whether the menu item should be
visible or hidden based on the value of the
'odoo_website_helpdesk.helpdesk_menu_show' configuration parameter.
Returns:
None
Side Effects:
Sets the 'is_visible' field of the menu item record to True or
False accordingly.
"""
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 show_menu_header is False:
menu.is_visible = False
if menu.name == 'Helpdesk' and show_menu_header is True:
menu.is_visible = True

4
odoo_website_helpdesk/report/helpdesk_ticket_report_template.xml → odoo_website_helpdesk/report/help_ticket_templates.xml

@ -1,4 +1,5 @@
<odoo> <odoo>
<!-- Pdf report template-->
<template id="report_helpdesk_ticket"> <template id="report_helpdesk_ticket">
<t t-call="web.html_container"> <t t-call="web.html_container">
<t t-foreach="help" t-as="o"> <t t-foreach="help" t-as="o">
@ -40,7 +41,7 @@
<h3 t-field="o.priority"/> <h3 t-field="o.priority"/>
</td> </td>
<td> <td>
<h3 t-field="o.product_id"/> <h3 t-field="o.product_ids"/>
</td> </td>
</tr> </tr>
</tbody> </tbody>
@ -97,6 +98,7 @@
</t> </t>
</t> </t>
</template> </template>
<!-- Pdf report action-->
<record id="action_report_helpdesk_ticket" model="ir.actions.report"> <record id="action_report_helpdesk_ticket" model="ir.actions.report">
<field name="name">Helpdesk Ticket Report</field> <field name="name">Helpdesk Ticket Report</field>
<field name="model">help.ticket</field> <field name="model">help.ticket</field>

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

@ -1,24 +1,17 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_help_ticket_user,access.help.ticket.user,model_help_ticket,base.group_user,1,1,1,1
access_help_ticket,access.help.ticket,model_help_ticket,,1,1,1,1 access_help_ticket_teams_user,access.help.team.user,model_help_team,odoo_website_helpdesk.helpdesk_user,1,0,0,0
access_help_ticket_teams_leader,access.help.team.leader,model_help_team,odoo_website_helpdesk.helpdesk_team_leader,1,0,0,0
access_help_ticket_teams_user,access.help.team,model_help_team,odoo_website_helpdesk.helpdesk_user,1,0,0,0 access_help_ticket_teams_manager,access.help.team.manager,model_help_team,odoo_website_helpdesk.helpdesk_manager,1,1,1,1
access_help_ticket_teams_leader,access.help.team,model_help_team,odoo_website_helpdesk.helpdesk_team_leader,1,0,0,0 access_helpdesk_tag_user,access.helpdesk.tag.user,model_helpdesk_tag,odoo_website_helpdesk.helpdesk_user,1,0,0,0
access_help_ticket_teams_manager,access.help.team,model_help_team,odoo_website_helpdesk.helpdesk_manager,1,1,1,1 access_helpdesk_tag_leader,access.helpdesk.tag.leader,model_helpdesk_tag,odoo_website_helpdesk.helpdesk_team_leader,1,1,1,1
access_helpdesk_tag_manager,access.helpdesk.tag.manager,model_helpdesk_tag,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_types_user,access.helpdesk.types.user,model_helpdesk_types,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_types_leader,access.helpdesk.types.leader,model_helpdesk_types,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_helpdesk_types_manager,access.helpdesk.types.manager,model_helpdesk_types,odoo_website_helpdesk.helpdesk_manager,1,1,1,1
access_helpdesk_categories_user,access.helpdesk.categories.user,model_helpdesk_categories,odoo_website_helpdesk.helpdesk_user,1,0,0,0
access_help_ticket_stage_user,access.ticket.stage,model_ticket_stage,odoo_website_helpdesk.helpdesk_user,1,1,1,1 access_helpdesk_categories_leader,access.helpdesk.categories.leader,model_helpdesk_categories,odoo_website_helpdesk.helpdesk_team_leader,1,1,1,1
access_helpdesk_categories_manager,access.helpdesk.categories.manager,model_helpdesk_categories,odoo_website_helpdesk.helpdesk_manager,1,1,1,1
access_helpdesk_types_user,access.helpdesk.types,model_helpdesk_types,odoo_website_helpdesk.helpdesk_user,1,0,0,0 merge_tickets_manager,merge.tickets.manager,model_merge_tickets,odoo_website_helpdesk.helpdesk_manager,1,1,1,1
access_helpdesk_types_leader,access.helpdesk.types,model_helpdesk_types,odoo_website_helpdesk.helpdesk_team_leader,1,1,1,1 support_tickets_manager,support.tickets.manager,model_support_tickets,odoo_website_helpdesk.helpdesk_manager,1,1,1,1
access_helpdesk_types_manager,access.helpdesk.types,model_helpdesk_types,odoo_website_helpdesk.helpdesk_manager,1,1,1,1 access_help_ticket_stage_user,access.ticket.stage.user,model_ticket_stage,base.group_user,1,1,1,1
access_helpdesk_categories_user,access_helpdesk_categories,model_helpdesk_categories,odoo_website_helpdesk.helpdesk_user,1,0,0,0
access_helpdesk_categories_leader,access_helpdesk_categories,model_helpdesk_categories,odoo_website_helpdesk.helpdesk_team_leader,1,1,1,1
access_helpdesk_categories_manager,access_helpdesk_categories,model_helpdesk_categories,odoo_website_helpdesk.helpdesk_manager,1,1,1,1
merge_tickets,merge.tickets,model_merge_tickets,odoo_website_helpdesk.helpdesk_manager,1,1,1,1
support_tickets,support.tickets,model_support_tickets,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_help_ticket_user access.help.ticket access.help.ticket.user model_help_ticket base.group_user 1 1 1 1
3 access_help_ticket_teams_user access.help.team access.help.team.user model_help_team odoo_website_helpdesk.helpdesk_user 1 0 0 0
4 access_help_ticket_teams_leader access.help.team access.help.team.leader model_help_team odoo_website_helpdesk.helpdesk_team_leader 1 0 0 0
5 access_help_ticket_teams_manager access.help.team access.help.team.manager model_help_team odoo_website_helpdesk.helpdesk_manager 1 1 1 1
6 access_helpdesk_tag_user access.helpdesk.tag access.helpdesk.tag.user model_helpdesk_tag odoo_website_helpdesk.helpdesk_user 1 0 0 0
7 access_helpdesk_tag_leader access.helpdesk.tag access.helpdesk.tag.leader model_helpdesk_tag odoo_website_helpdesk.helpdesk_team_leader 1 1 1 1
8 access_helpdesk_tag_manager access.helpdesk.tag access.helpdesk.tag.manager model_helpdesk_tag odoo_website_helpdesk.helpdesk_manager 1 1 1 1
9 access_help_ticket_stage_user access_helpdesk_types_user access.ticket.stage access.helpdesk.types.user model_ticket_stage model_helpdesk_types odoo_website_helpdesk.helpdesk_user 1 1 0 1 0 1 0
10 access_helpdesk_types_user access_helpdesk_types_leader access.helpdesk.types access.helpdesk.types.leader model_helpdesk_types odoo_website_helpdesk.helpdesk_user odoo_website_helpdesk.helpdesk_team_leader 1 0 1 0 1 0 1
11 access_helpdesk_types_leader access_helpdesk_types_manager access.helpdesk.types access.helpdesk.types.manager model_helpdesk_types odoo_website_helpdesk.helpdesk_team_leader odoo_website_helpdesk.helpdesk_manager 1 1 1 1
12 access_helpdesk_types_manager access_helpdesk_categories_user access.helpdesk.types access.helpdesk.categories.user model_helpdesk_types model_helpdesk_categories odoo_website_helpdesk.helpdesk_manager odoo_website_helpdesk.helpdesk_user 1 1 0 1 0 1 0
13 access_helpdesk_categories_user access_helpdesk_categories_leader access_helpdesk_categories access.helpdesk.categories.leader model_helpdesk_categories odoo_website_helpdesk.helpdesk_user odoo_website_helpdesk.helpdesk_team_leader 1 0 1 0 1 0 1
14 access_helpdesk_categories_leader access_helpdesk_categories_manager access_helpdesk_categories access.helpdesk.categories.manager model_helpdesk_categories odoo_website_helpdesk.helpdesk_team_leader odoo_website_helpdesk.helpdesk_manager 1 1 1 1
15 access_helpdesk_categories_manager merge_tickets_manager access_helpdesk_categories merge.tickets.manager model_helpdesk_categories model_merge_tickets odoo_website_helpdesk.helpdesk_manager 1 1 1 1
16 merge_tickets support_tickets_manager merge.tickets support.tickets.manager model_merge_tickets model_support_tickets odoo_website_helpdesk.helpdesk_manager 1 1 1 1
17 support_tickets access_help_ticket_stage_user support.tickets access.ticket.stage.user model_support_tickets model_ticket_stage odoo_website_helpdesk.helpdesk_manager base.group_user 1 1 1 1

22
odoo_website_helpdesk/security/security_groups.xml → odoo_website_helpdesk/security/odoo_website_helpdesk_security.xml

@ -1,36 +1,34 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo> <odoo>
<record model="ir.module.category" id="module_category_helpdesk"> <record model="ir.module.category" id="module_category_helpdesk">
<field name="name">Helpdesk</field> <field name="name">Helpdesk</field>
<field name="description">Helpdesk Access Groups</field> <field name="description">Helpdesk Access Groups</field>
<field name="sequence">20</field> <field name="sequence">20</field>
</record> </record>
<!-- Helpdesk user access-->
<record id="helpdesk_user" model="res.groups"> <record id="helpdesk_user" model="res.groups">
<field name="name">User</field> <field name="name">User</field>
<field name="category_id" ref="odoo_website_helpdesk.module_category_helpdesk"/> <field name="category_id" ref="odoo_website_helpdesk.module_category_helpdesk"/>
</record> </record>
<!-- Helpdesk leader access-->
<record id="helpdesk_team_leader" model="res.groups"> <record id="helpdesk_team_leader" model="res.groups">
<field name="name">Team Leader</field> <field name="name">Team Leader</field>
<field name="category_id" ref="odoo_website_helpdesk.module_category_helpdesk"/> <field name="category_id" ref="odoo_website_helpdesk.module_category_helpdesk"/>
<field name="implied_ids" eval="[(4, ref('odoo_website_helpdesk.helpdesk_user'))]"/> <field name="implied_ids" eval="[(4, ref('odoo_website_helpdesk.helpdesk_user'))]"/>
</record> </record>
<!-- Helpdesk manager access-->
<record id="helpdesk_manager" model="res.groups"> <record id="helpdesk_manager" model="res.groups">
<field name="name">Manager</field> <field name="name">Manager</field>
<field name="category_id" ref="odoo_website_helpdesk.module_category_helpdesk"/> <field name="category_id" ref="odoo_website_helpdesk.module_category_helpdesk"/>
<field name="implied_ids" eval="[(4, ref('odoo_website_helpdesk.helpdesk_team_leader'))]"/> <field name="implied_ids" eval="[(4, ref('odoo_website_helpdesk.helpdesk_team_leader'))]"/>
</record> </record>
<record id="group_show_category" model="res.groups"> <record id="group_show_category" model="res.groups">
<field name="name">group_show_category</field> <field name="name">group_show_category</field>
</record> </record>
<record id="group_show_subcategory" model="res.groups"> <record id="group_show_subcategory" model="res.groups">
<field name="name">group_show_subcategory</field> <field name="name">group_show_subcategory</field>
</record> </record>
<!--Record Rule for team leader-->
<record id="help_desk_dashboard_team_leader" <record id="help_desk_dashboard_team_leader"
model="ir.rule"> model="ir.rule">
<field name="name">Record Rule for team leader</field> <field name="name">Record Rule for team leader</field>
@ -43,7 +41,7 @@
<field name="perm_create" eval="True"/> <field name="perm_create" eval="True"/>
<field name="perm_unlink" eval="True"/> <field name="perm_unlink" eval="True"/>
</record> </record>
<!--Record Rule for manage-->
<record id="help_desk_dashboard_manager" <record id="help_desk_dashboard_manager"
model="ir.rule"> model="ir.rule">
<field name="name">Record Rule for manager</field> <field name="name">Record Rule for manager</field>
@ -56,7 +54,7 @@
<field name="perm_create" eval="True"/> <field name="perm_create" eval="True"/>
<field name="perm_unlink" eval="True"/> <field name="perm_unlink" eval="True"/>
</record> </record>
<!--Record Rule for use-->
<record id="help_desk_dashboard_user" <record id="help_desk_dashboard_user"
model="ir.rule"> model="ir.rule">
<field name="name">Record Rule for user</field> <field name="name">Record Rule for user</field>
@ -69,7 +67,7 @@
<field name="perm_create" eval="True"/> <field name="perm_create" eval="True"/>
<field name="perm_unlink" eval="True"/> <field name="perm_unlink" eval="True"/>
</record> </record>
<!--Record Rule stages leader-->
<record id="help_desk_stage_rule_leader" <record id="help_desk_stage_rule_leader"
model="ir.rule"> model="ir.rule">
<field name="name">Record Rule stages leader</field> <field name="name">Record Rule stages leader</field>
@ -82,7 +80,7 @@
<field name="perm_create" eval="True"/> <field name="perm_create" eval="True"/>
<field name="perm_unlink" eval="True"/> <field name="perm_unlink" eval="True"/>
</record> </record>
<!-- Record Rule stages manager-->
<record id="help_desk_stage_rule_manager" <record id="help_desk_stage_rule_manager"
model="ir.rule"> model="ir.rule">
<field name="name">Record Rule stages manager</field> <field name="name">Record Rule stages manager</field>
@ -95,7 +93,7 @@
<field name="perm_create" eval="True"/> <field name="perm_create" eval="True"/>
<field name="perm_unlink" eval="True"/> <field name="perm_unlink" eval="True"/>
</record> </record>
<!--Record Rule stages user-->
<record id="help_desk_stage_rule_user" <record id="help_desk_stage_rule_user"
model="ir.rule"> model="ir.rule">
<field name="name">Record Rule stages user</field> <field name="name">Record Rule stages user</field>

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 KiB

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 174 KiB

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 178 KiB

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 218 KiB

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 174 KiB

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 224 KiB

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 172 KiB

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 175 KiB

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 182 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

BIN
odoo_website_helpdesk/static/description/assets/screenshots/create-new-ticket.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 KiB

After

Width:  |  Height:  |  Size: 109 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

BIN
odoo_website_helpdesk/static/description/assets/screenshots/hero.gif

Binary file not shown.

Before

Width:  |  Height:  |  Size: 154 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

BIN
odoo_website_helpdesk/static/description/assets/screenshots/merge-action.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 164 KiB

After

Width:  |  Height:  |  Size: 104 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

BIN
odoo_website_helpdesk/static/description/assets/screenshots/open-new-ticket.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 125 KiB

After

Width:  |  Height:  |  Size: 106 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
odoo_website_helpdesk/static/description/assets/screenshots/v16-hero.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 446 KiB

253
odoo_website_helpdesk/static/description/index.html

@ -9,10 +9,6 @@
class="mr-2"> class="mr-2">
<i class="fa fa-check mr-1"></i>Community <i class="fa fa-check mr-1"></i>Community
</div> </div>
<div style="color: #875A7B; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;"
class="mr-2">
<i class="fa fa-check mr-1"></i>Enterprise
</div>
<div style="color: #017E84; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;" <div style="color: #017E84; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;"
class="mr-2"> class="mr-2">
<i class="fa fa-check mr-1"></i>Odoo.sh <i class="fa fa-check mr-1"></i>Odoo.sh
@ -20,7 +16,6 @@
</div> </div>
</div> </div>
<!-- END OF TITLE BAR --> <!-- END OF TITLE BAR -->
<!-- APP HERO --> <!-- APP HERO -->
<h1 style="color: #FFFFFF; font-weight: bolder; font-size: 50px; text-align: center; margin-top: 50px;"> <h1 style="color: #FFFFFF; font-weight: bolder; font-size: 50px; text-align: center; margin-top: 50px;">
Website Helpdesk Support Ticket Management Website Helpdesk Support Ticket Management
@ -29,7 +24,7 @@
A Module For Managing Support Tickets A Module For Managing Support Tickets
</p> </p>
<!-- END OF APP HERO --> <!-- END OF APP HERO -->
<img src="assets/screenshots/hero.gif" <img src="assets/screenshots/v16-hero.gif"
style="width: 75%; height: auto; position: absolute; margin-left: auto; margin-right: auto; top: 45%; left: 12%; right: auto;"/> style="width: 75%; height: auto; position: absolute; margin-left: auto; margin-right: auto; top: 45%; left: 12%; right: auto;"/>
</div> </div>
<!-- NAVIGATION SECTION --> <!-- NAVIGATION SECTION -->
@ -56,7 +51,8 @@
more about this more about this
module</span> module</span>
</div> </div>
<img src="./assets/misc/right-arrow.png" width="36" height="36"/> <img src="./assets/misc/right-arrow.png" width="36"
height="36"/>
</div> </div>
</a> </a>
</div> </div>
@ -71,7 +67,8 @@
features of this features of this
module</span> module</span>
</div> </div>
<img src="./assets/misc/right-arrow.png" width="36" height="36"/> <img src="./assets/misc/right-arrow.png" width="36"
height="36"/>
</div> </div>
</a> </a>
</div> </div>
@ -86,7 +83,8 @@
screenshots for this screenshots for this
module</span> module</span>
</div> </div>
<img src="./assets/misc/right-arrow.png" width="36" height="36"/> <img src="./assets/misc/right-arrow.png" width="36"
height="36"/>
</div> </div>
</a> </a>
</div> </div>
@ -108,9 +106,11 @@
<div class="row" <div class="row"
style="font-family: 'Montserrat', sans-serif; font-weight: 400; font-size: 14px; line-height: 200%;"> style="font-family: 'Montserrat', sans-serif; font-weight: 400; font-size: 14px; line-height: 200%;">
<div class="col-sm-12 py-4"> <div class="col-sm-12 py-4">
In the Helpdesk Support App, one can Create Ticket trough website portal and can view their tickets.</p> <p> In the Helpdesk Support App, one can Create Ticket trough website
The Internal user can assign th ticket to any team and link to any project if needed and can invoice based on the portal and can view their tickets.
timesheet The Internal user can assign th ticket to any team and link to any
project if needed and can invoice based on the
timesheet</p>
</div> </div>
</div> </div>
<!-- END OF OVERVIEW SECTION --> <!-- END OF OVERVIEW SECTION -->
@ -144,7 +144,7 @@
<img src="./assets/misc/check-box.png" class="mr-2"/> <img src="./assets/misc/check-box.png" class="mr-2"/>
<div> <div>
<span style="display: block; font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> <span style="display: block; font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
View created tickets from portal View Created Tickets from Portal
</span> </span>
</div> </div>
</div> </div>
@ -153,7 +153,7 @@
<img src="./assets/misc/check-box.png" class="mr-2"/> <img src="./assets/misc/check-box.png" class="mr-2"/>
<div> <div>
<span style="display: block; font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> <span style="display: block; font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Create Tasks for the project linked to the Ticket </span> Create Tasks for the Project Linked to the Ticket </span>
</div> </div>
</div> </div>
<div class="d-flex align-items-start" <div class="d-flex align-items-start"
@ -161,7 +161,7 @@ Create Tasks for the project linked to the Ticket </span>
<img src="./assets/misc/check-box.png" class="mr-2"/> <img src="./assets/misc/check-box.png" class="mr-2"/>
<div> <div>
<span style="display: block; font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> <span style="display: block; font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Link a project to the Ticket and invoice based on the tasks timesheet Link a Project to the Ticket and Invoice based on the Tasks Timesheet
</span> </span>
</div> </div>
</div> </div>
@ -170,7 +170,7 @@ Create Tasks for the project linked to the Ticket </span>
<img src="./assets/misc/check-box.png" class="mr-2"/> <img src="./assets/misc/check-box.png" class="mr-2"/>
<div> <div>
<span style="display: block; font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> <span style="display: block; font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Tickets can be viewed and managed from backend Tickets can be Viewed and Managed from Backend
</span> </span>
</div> </div>
</div> </div>
@ -179,11 +179,11 @@ Create Tasks for the project linked to the Ticket </span>
<img src="./assets/misc/check-box.png" class="mr-2"/> <img src="./assets/misc/check-box.png" class="mr-2"/>
<div> <div>
<span style="display: block; font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> <span style="display: block; font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Customise stages or use predefined stages for seeing the status of ticket Customise Stages or Use Predefined Stages for Seeing the Status of Ticket
</span> </span>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<!-- END OF FEATURES SECTION --> <!-- END OF FEATURES SECTION -->
@ -203,111 +203,134 @@ Create Tasks for the project linked to the Ticket </span>
</div> </div>
<div class="row"> <div class="row">
<div class="col-sm-12"> <div class="col-sm-12">
<div style="display: block; margin: 30px auto;"> <div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Create Tickets From website, Enable the Helpdesk Menu on the Website.
</h3>
<img src="./assets/screenshots/enable_helpdesk.png"
class="img-thumbnail"><br/>
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Create Tickets From Website
</h3> </h3>
<img src="./assets/screenshots/Screenshot1.png" <img src="./assets/screenshots/Screenshot1.png"
class="img-thumbnail"><br/> <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> class="img-thumbnail"><br/>
Get Confirmation/Success message for ticket creation <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Get Confirmation/Success Message for Ticket Creation
</h3><br/> </h3><br/>
<img src="./assets/screenshots/Screenshot2.png" <img src="./assets/screenshots/Screenshot2.png"
class="img-thumbnail"> class="img-thumbnail">
</div> </div>
<div style="display: block; margin: 30px auto;"> <div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
View created tickets from portal View Created Tickets from Portal
</h3> </h3>
<img src="./assets/screenshots/Screenshot4.png" <img src="./assets/screenshots/Screenshot4.png"
class="img-thumbnail"> class="img-thumbnail">
</div> </div>
<div style="display: block; margin: 30px auto;"> <div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
View the details of each ticket by hovering over them. View the Details of each Ticket by Hovering Over Them.
</h3> </h3>
<img src="./assets/screenshots/Screenshot3.png" <img src="./assets/screenshots/Screenshot3.png"
class="img-thumbnail"> class="img-thumbnail">
</div> </div>
<div style="display: block; margin: 30px auto;"> <div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Configure stages for tickets View All Tickets According to Stages in Kanban View.
</h3> </h3>
<img src="./assets/screenshots/Screenshot5.png" <img src="./assets/screenshots/kanban_view.png"
class="img-thumbnail"> class="img-thumbnail">
</div> </div>
</div>
<div class="col-sm-12">
<div style="display: block; margin: 30px auto;"> <div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
View tickets according to stages in kanban view. Create / Configure Helpdesk Teams
</h3> </h3>
<img src="./assets/screenshots/Screenshot6.png" <img src="./assets/screenshots/teams.png"
class="img-thumbnail"> class="img-thumbnail"><br/>
</div> </div>
</div>
<div class="col-sm-12">
<div style="display: block; margin: 30px auto;"> <div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Create / configure helpdesk teams Create / Configure Categories
</h3> </h3>
<img src="./assets/screenshots/Screenshot7.png" <img src="./assets/screenshots/catagory.png"
class="img-thumbnail"><br/>
</div>
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Create / Configure Helpdesk Types
</h3>
<img src="./assets/screenshots/types.png"
class="img-thumbnail"><br/>
</div>
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Configure Stages for Tickets
</h3>
<img src="./assets/screenshots/stages.png"
class="img-thumbnail"><br/> class="img-thumbnail"><br/>
<img src="./assets/screenshots/Screenshot8.png"
class="img-thumbnail">
</div> </div>
<div style="display: block; margin: 30px auto;"> <div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Create Tickets from backend normally Create Tickets from Backend Normally
</h3> </h3>
<img src="./assets/screenshots/Screenshot9.png" <img src="./assets/screenshots/ticket.png"
class="img-thumbnail"> class="img-thumbnail">
</div> </div>
<div style="display: block; margin: 30px auto;"> <div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Enable 'Create Tasks' from configuration settings to create tasks for the project linked to the Ticket Enable 'Create Tasks' from Configuration Settings to create
Tasks for the Project Linked to the Ticket
</h3> </h3>
<img src="./assets/screenshots/Screenshot10.png" <img src="./assets/screenshots/enable_settings_task.png"
class="img-thumbnail"> class="img-thumbnail">
</div> </div>
<div style="display: block; margin: 30px auto;"> <div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Turn on 'create task' toggle inside the ticket form to link a project to the Ticket Turn on 'Create Task' Toggle Inside the Ticket form to Link a
Project to the Ticket
</h3> </h3>
<img src="./assets/screenshots/Screenshot11.png" <img src="./assets/screenshots/enable_task.png"
class="img-thumbnail"><br/><h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> class="img-thumbnail"><br/>
Create Tasks: <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
CREATE TASK:
</h3><br/> </h3><br/>
<img src="./assets/screenshots/Screenshot13.png" <img src="./assets/screenshots/task_creation.png"
class="img-thumbnail"> class="img-thumbnail">
</div> </div>
<div style="display: block; margin: 30px auto;"> <div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Turn on 'Billable' toggle inside the ticket form to create invoice based on the tasks timesheet Turn on 'Billable' toggle inside the ticket form to 'CREATE
INVOICE' based on the tasks timesheet
</h3> </h3>
<img src="./assets/screenshots/Screenshot12.png" <img src="./assets/screenshots/enable_billing.png"
class="img-thumbnail"><br/><h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> class="img-thumbnail"><br/>
Create invoice: <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
CREATE INVOICE:
</h3><br/>
<img src="./assets/screenshots/billed.png"
class="img-thumbnail">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
CONFIRM INVOICE:
</h3><br/> </h3><br/>
<img src="./assets/screenshots/Screenshot14.png" <img src="./assets/screenshots/invoice.png"
class="img-thumbnail"> class="img-thumbnail">
</div> </div>
<div style="display: block; margin: 30px auto;"> <div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Print PDF Report of the Ticket from backend Print PDF Report of the Ticket from backend
</h3> </h3>
<img src="./assets/screenshots/Screenshot15.png" <img src="./assets/screenshots/printing.png"
class="img-thumbnail"> class="img-thumbnail">
</div> </div>
</div> </div>
<div class="col-sm-12"> <div class="col-sm-12">
<div style="display: block; margin: 30px auto;"> <div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Ticket (pdf): Ticket (pdf):
</h3> </h3>
<img src="./assets/screenshots/Screenshot16.png" <img src="./assets/screenshots/report.png"
class="img-thumbnail"> class="img-thumbnail">
</div> </div>
</div> </div>
@ -338,7 +361,7 @@ Create Tasks for the project linked to the Ticket </span>
class="img-thumbnail"> class="img-thumbnail">
</div> </div>
</div> </div>
<div class="col-sm-12"> <div class="col-sm-12">
<div style="display: block; margin: 30px auto;"> <div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
New Ticket. New Ticket.
@ -351,109 +374,76 @@ Create Tasks for the project linked to the Ticket </span>
<!-- END OF SCREENSHOTS SECTION --> <!-- END OF SCREENSHOTS SECTION -->
<!-- RELATED PRODUCTS --> <!-- RELATED PRODUCTS -->
<div class="d-flex align-items-center" <div class="d-flex align-items-center" style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
style="border-bottom: 2px solid #714B67; padding: 15px 0px;"> <div class="d-flex justify-content-center align-items-center mr-2" style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<div class="d-flex justify-content-center align-items-center mr-2" <img src="assets/misc/categories.png" />
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="./assets/misc/categories.png"/>
</div> </div>
<h2 class="mt-2" <h2 class="mt-2" style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">Related Products</h2>
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Related
Products
</h2>
</div> </div>
<div class="row"> <div class="row">
<div class="col-sm-12"> <div class="col-sm-12">
<div id="demo1" class="row carousel slide" data-ride="carousel"> <div id="demo1" class="row carousel slide" data-ride="carousel">
<!-- The slideshow --> <!-- The slideshow -->
<div class="carousel-inner" style="padding: 30px;"> <div class="carousel-inner" style="padding: 30px;">
<div class="carousel-item" style="min-height: 198.656px;"> <div class="carousel-item" style="min-height: 198.656px;">
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left">
style="float:left"> <a href="https://apps.odoo.com/apps/modules/16.0/website_hide_button/" target="_blank">
<a href="https://apps.odoo.com/apps/modules/15.0/export_stockinfo_xls/" target="_blank">
<div style="border-radius:10px"> <div style="border-radius:10px">
<img class="img img-responsive center-block" <img class="img img-responsive center-block" style="border-radius: 0px;" src="assets/modules/1.jpg">
style="border-radius: 0px;"
src="./assets/modules/export_image.png">
</div> </div>
</a> </a>
</div> </div>
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left">
style="float:left"> <a href="https://apps.odoo.com/apps/modules/16.0/website_portal_events/#" target="_blank">
<a href="https://apps.odoo.com/apps/modules/15.0/custom_gantt_view/"
target="_blank">
<div style="border-radius:10px"> <div style="border-radius:10px">
<img class="img img-responsive center-block" <img class="img img-responsive center-block" style="border-radius: 0px;" src="assets/modules/2.jpg">
style="border-radius: 0px;"
src="./assets/modules/gantt_image.png">
</div> </div>
</a> </a>
</div> </div>
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left">
style="float:left"> <a href="https://apps.odoo.com/apps/modules/16.0/website_seo_kit/" target="_blank">
<a href="https://apps.odoo.com/apps/modules/15.0/sales_credit_limit/" target="_blank">
<div style="border-radius:10px"> <div style="border-radius:10px">
<img class="img img-responsive center-block" <img class="img img-responsive center-block" style="border-radius: 0px;" src="assets/modules/3.png">
style="border-radius: 0px;"
src="./assets/modules/credit_image.png">
</div> </div>
</a> </a>
</div> </div>
</div> </div>
<div class="carousel-item active" <div class="carousel-item active" style="min-height: 198.656px;">
style="min-height: 198.656px;"> <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left">
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" <a href="https://apps.odoo.com/apps/modules/16.0/call_for_price_website/" target="_blank">
style="float:left">
<a href="https://apps.odoo.com/apps/modules/15.0/base_account_budget/" target="_blank">
<div style="border-radius:10px"> <div style="border-radius:10px">
<img class="img img-responsive center-block" <img class="img img-responsive center-block" style="border-radius: 0px;" src="assets/modules/4.png">
style="border-radius: 0px;"
src="./assets/modules/budget_image.png">
</div> </div>
</a> </a>
</div> </div>
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left">
style="float:left"> <a href="https://apps.odoo.com/apps/modules/16.0/special_product_snippet/" target="_blank">
<a href="https://apps.odoo.com/apps/modules/15.0/product_to_quotation/" target="_blank">
<div style="border-radius:10px"> <div style="border-radius:10px">
<img class="img img-responsive center-block" <img class="img img-responsive center-block" style="border-radius: 0px;" src="assets/modules/5.jpg">
style="border-radius: 0px;"
src="./assets/modules/quotation_image.png">
</div> </div>
</a> </a>
</div> </div>
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left">
style="float:left"> <a href="https://apps.odoo.com/apps/modules/16.0/website_favourites_grid/" target="_blank">
<a href="https://apps.odoo.com/apps/modules/15.0/employee_documents_expiry/" target="_blank">
<div style="border-radius:10px"> <div style="border-radius:10px">
<img class="img img-responsive center-block" <img class="img img-responsive center-block" style="border-radius: 0px;" src="assets/modules/7.jpg">
style="border-radius: 0px;"
src="./assets/modules/employee_image.png">
</div> </div>
</a> </a>
</div> </div>
</div> </div>
</div> </div>
<!-- Left and right controls --> <!-- Left and right controls -->
<a class="carousel-control-prev" href="#demo1" data-slide="prev" <a class="carousel-control-prev" href="#demo1" data-slide="prev" style="width:35px; color:#000"> <span
style="width:35px; color:#000"> <span class="carousel-control-prev-icon"><i class="fa fa-chevron-left" style="font-size:24px"></i></span>
class="carousel-control-prev-icon"><i </a> <a class="carousel-control-next" href="#demo1" data-slide="next" style="width:35px; color:#000">
class="fa fa-chevron-left" <span class="carousel-control-next-icon"><i class="fa fa-chevron-right" style="font-size:24px"></i></span></a>
style="font-size:24px"></i></span>
</a> <a class="carousel-control-next" href="#demo1"
data-slide="next" style="width:35px; color:#000">
<span class="carousel-control-next-icon"><i
class="fa fa-chevron-right"
style="font-size:24px"></i></span>
</a>
</div> </div>
</div> </div>
</div> </div>
<!-- END OF RELATED PRODUCTS --> <!-- END OF RELATED PRODUCTS -->
<!-- OUR SERVICES --> <!-- OUR SERVICES -->
<div class="d-flex align-items-center" <div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;"> style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
<div class="d-flex justify-content-center align-items-center mr-2" <div class="d-flex justify-content-center align-items-center mr-2"
@ -465,7 +455,6 @@ Create Tasks for the project linked to the Ticket </span>
Our Services Our Services
</h2> </h2>
</div> </div>
<div class="container my-5"> <div class="container my-5">
<div class="row"> <div class="row">
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
@ -566,7 +555,6 @@ Create Tasks for the project linked to the Ticket </span>
Odoo Odoo
Implementation</h6> Implementation</h6>
</div> </div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3" <div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #e6be26 !important; border-radius: 15px !important; height: 80px; width: 80px;"> style="background-color: #e6be26 !important; border-radius: 15px !important; height: 80px; width: 80px;">
@ -581,16 +569,13 @@ Create Tasks for the project linked to the Ticket </span>
</div> </div>
</div> </div>
<!-- END OF OUR SERVICES -->
<!-- END OF END OF OUR SERVICES -->
<!-- OUR INDUSTRIES --> <!-- OUR INDUSTRIES -->
<div class="d-flex align-items-center" <div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;"> style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
<div class="d-flex justify-content-center align-items-center mr-2" <div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="./assets/misc/corporate.png"/> <img src="assets/misc/corporate.png"/>
</div> </div>
<h2 class="mt-2" <h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
@ -604,7 +589,7 @@ Create Tasks for the project linked to the Ticket </span>
<div class="col-lg-3"> <div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center" <div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="../assets/icons/trading-black.png" <img src="assets/icons/trading-black.png"
class="img-responsive mb-3" height="48px" width="48px"> class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> <h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
Trading Trading
@ -619,7 +604,7 @@ Create Tasks for the project linked to the Ticket </span>
<div class="col-lg-3"> <div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center" <div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="../assets/icons/pos-black.png" <img src="assets/icons/pos-black.png"
class="img-responsive mb-3" height="48px" width="48px"> class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> <h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
POS POS
@ -634,7 +619,7 @@ Create Tasks for the project linked to the Ticket </span>
<div class="col-lg-3"> <div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center" <div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="../assets/icons/education-black.png" <img src="assets/icons/education-black.png"
class="img-responsive mb-3" height="48px" width="48px"> class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> <h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
Education Education
@ -648,7 +633,7 @@ Create Tasks for the project linked to the Ticket </span>
<div class="col-lg-3"> <div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center" <div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="../assets/icons/manufacturing-black.png" <img src="assets/icons/manufacturing-black.png"
class="img-responsive mb-3" height="48px" class="img-responsive mb-3" height="48px"
width="48px"> width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> <h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
@ -663,7 +648,7 @@ Create Tasks for the project linked to the Ticket </span>
<div class="col-lg-3"> <div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center" <div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="../assets/icons/ecom-black.png" <img src="assets/icons/ecom-black.png"
class="img-responsive mb-3" height="48px" width="48px"> class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> <h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
E-commerce &amp; Website E-commerce &amp; Website
@ -678,7 +663,7 @@ Create Tasks for the project linked to the Ticket </span>
<div class="col-lg-3"> <div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center" <div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="../assets/icons/service-black.png" <img src="assets/icons/service-black.png"
class="img-responsive mb-3" height="48px" width="48px"> class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> <h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
Service Management Service Management
@ -692,7 +677,7 @@ Create Tasks for the project linked to the Ticket </span>
<div class="col-lg-3"> <div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center" <div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="../assets/icons/restaurant-black.png" <img src="assets/icons/restaurant-black.png"
class="img-responsive mb-3" height="48px" width="48px"> class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> <h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
Restaurant Restaurant
@ -706,7 +691,7 @@ Create Tasks for the project linked to the Ticket </span>
<div class="col-lg-3"> <div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center" <div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="../assets/icons/hotel-black.png" <img src="assets/icons/hotel-black.png"
class="img-responsive mb-3" height="48px" width="48px"> class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> <h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
Hotel Management Hotel Management
@ -720,7 +705,7 @@ Create Tasks for the project linked to the Ticket </span>
</div> </div>
</div> </div>
<!-- END OF END OF OUR INDUSTRIES --> <!-- END OF OUR INDUSTRIES -->
<!-- SUPPORT --> <!-- SUPPORT -->
<div class="d-flex align-items-center" <div class="d-flex align-items-center"

120
odoo_website_helpdesk/static/src/js/helpdesk_dashboard_action.js

@ -1,9 +1,7 @@
odoo.define('odoo_website_helpdesk.helpdesk_dashboard_action', function (require){ odoo.define('odoo_website_helpdesk.helpdesk_dashboard_action', function (require){
"use strict"; "use strict";
var AbstractAction = require('web.AbstractAction'); var AbstractAction = require('web.AbstractAction');
var ControlPanel = require('web.ControlPanel');
var core = require('web.core'); var core = require('web.core');
var QWeb = core.qweb;
var rpc = require('web.rpc'); var rpc = require('web.rpc');
var ajax = require('web.ajax'); var ajax = require('web.ajax');
var CustomDashBoard = AbstractAction.extend({ var CustomDashBoard = AbstractAction.extend({
@ -12,12 +10,13 @@ var CustomDashBoard = AbstractAction.extend({
start: function() { start: function() {
var self = this; var self = this;
ajax.rpc('/helpdesk_dashboard').then(function (res) { ajax.rpc('/helpdesk_dashboard').then(function (res) {
$("#new_state_value").text(res.new) self.$el.find("#new_state_value").text(res.new)
$("#inprogress_value").text(res.in_progress) self.$el.find("#inprogress_value").text(res.in_progress)
$("#canceled_value").text(res.canceled) self.$el.find("#canceled_value").text(res.canceled)
$("#done_value").text(res.done) self.$el.find("#done_value").text(res.done)
$("#closed_value").text(res.closed) self.$el.find("#closed_value").text(res.closed)
$("#new_state").click(function(){ // Update the dashboard new state value
self.$el.find("#new_state").click(function(){
self.do_action({ self.do_action({
name:'New Tickets', name:'New Tickets',
type: 'ir.actions.act_window', type: 'ir.actions.act_window',
@ -27,7 +26,8 @@ var CustomDashBoard = AbstractAction.extend({
domain: [['id', '=', res.new_id]], domain: [['id', '=', res.new_id]],
}) })
}) })
$("#in_progress_state").click(function(){ // Update the dashboard in progress state value
self.$el.find("#in_progress_state").click(function(){
self.do_action({ self.do_action({
name:'In progress Tickets', name:'In progress Tickets',
type: 'ir.actions.act_window', type: 'ir.actions.act_window',
@ -37,7 +37,8 @@ var CustomDashBoard = AbstractAction.extend({
domain: [['id', '=', res.in_progress_id]], domain: [['id', '=', res.in_progress_id]],
}) })
}) })
$("#cancelled_state").click(function(){ // Update the dashboard cancel state value
self.$el.find("#cancelled_state").click(function(){
self.do_action({ self.do_action({
name:'Canceled Tickets', name:'Canceled Tickets',
type: 'ir.actions.act_window', type: 'ir.actions.act_window',
@ -47,7 +48,8 @@ var CustomDashBoard = AbstractAction.extend({
domain: [['id', '=', res.canceled_id]], domain: [['id', '=', res.canceled_id]],
}) })
}) })
$("#done_state").click(function(){ // Update the dashboard done state value
self.$el.find("#done_state").click(function(){
self.do_action({ self.do_action({
name:'Done Tickets', name:'Done Tickets',
type: 'ir.actions.act_window', type: 'ir.actions.act_window',
@ -57,7 +59,8 @@ var CustomDashBoard = AbstractAction.extend({
domain: [['id', '=', res.done_id]], domain: [['id', '=', res.done_id]],
}) })
}) })
$("#closed_state").click(function(){ // Update the dashboard closed state value
self.$el.find("#closed_state").click(function(){
self.do_action({ self.do_action({
name:'Closed Tickets', name:'Closed Tickets',
type: 'ir.actions.act_window', type: 'ir.actions.act_window',
@ -67,19 +70,19 @@ var CustomDashBoard = AbstractAction.extend({
domain: [['id', '=', res.closed_id]], domain: [['id', '=', res.closed_id]],
}) })
}) })
// week function start // week function start
$("#filter_selection").change(function(e){ self.$el.find("#filter_selection").change(function(e){
var target = $(e.target) var target = $(e.target)
var value = target.val() var value = target.val()
if (value == "this_week") { if (value == "this_week") {
ajax.rpc('/helpdesk_dashboard_week').then(function (res) { ajax.rpc('/helpdesk_dashboard_week').then(function (res) {
$("#new_state_value").text(res.new) self.$el.find("#new_state_value").text(res.new)
$("#inprogress_value").text(res.in_progress) self.$el.find("#inprogress_value").text(res.in_progress)
$("#canceled_value").text(res.canceled) self.$el.find("#canceled_value").text(res.canceled)
$("#done_value").text(res.done) self.$el.find("#done_value").text(res.done)
$("#closed_value").text(res.closed) self.$el.find("#closed_value").text(res.closed)
$("#new_state").click(function(){ // Week function new state updation
self.$el.find("#new_state").click(function(){
self.do_action({ self.do_action({
name:'New Tickets', name:'New Tickets',
type: 'ir.actions.act_window', type: 'ir.actions.act_window',
@ -89,7 +92,8 @@ var CustomDashBoard = AbstractAction.extend({
domain: [['id', '=', res.new_id]], domain: [['id', '=', res.new_id]],
}) })
}) })
$("#in_progress_state").click(function(){ // Week function in progress state update
self.$el.find("#in_progress_state").click(function(){
self.do_action({ self.do_action({
name:'In progress Tickets', name:'In progress Tickets',
type: 'ir.actions.act_window', type: 'ir.actions.act_window',
@ -99,7 +103,8 @@ var CustomDashBoard = AbstractAction.extend({
domain: [['id', '=', res.in_progress_id]], domain: [['id', '=', res.in_progress_id]],
}) })
}) })
$("#cancelled_state").click(function(){ // Week function in cancel state update
self.$el.find("#cancelled_state").click(function(){
self.do_action({ self.do_action({
name:'Canceled Tickets', name:'Canceled Tickets',
type: 'ir.actions.act_window', type: 'ir.actions.act_window',
@ -109,7 +114,8 @@ var CustomDashBoard = AbstractAction.extend({
domain: [['id', '=', res.canceled_id]], domain: [['id', '=', res.canceled_id]],
}) })
}) })
$("#done_state").click(function(){ // Week function in done state update
self.$el.find("#done_state").click(function(){
self.do_action({ self.do_action({
name:'Done Tickets', name:'Done Tickets',
type: 'ir.actions.act_window', type: 'ir.actions.act_window',
@ -119,7 +125,8 @@ var CustomDashBoard = AbstractAction.extend({
domain: [['id', '=', res.done_id]], domain: [['id', '=', res.done_id]],
}) })
}) })
$("#closed_state").click(function(){ // Week function in closed state update
self.$el.find("#closed_state").click(function(){
self.do_action({ self.do_action({
name:'Closed Tickets', name:'Closed Tickets',
type: 'ir.actions.act_window', type: 'ir.actions.act_window',
@ -130,14 +137,17 @@ var CustomDashBoard = AbstractAction.extend({
}) })
}) })
}) })
}else if (value == "this_month") { }
// Month function start
else if (value == "this_month") {
ajax.rpc('/helpdesk_dashboard_month').then(function (res) { ajax.rpc('/helpdesk_dashboard_month').then(function (res) {
$("#new_state_value").text(res.new) self.$el.find("#new_state_value").text(res.new)
$("#inprogress_value").text(res.in_progress) self.$el.find("#inprogress_value").text(res.in_progress)
$("#canceled_value").text(res.canceled) self.$el.find("#canceled_value").text(res.canceled)
$("#done_value").text(res.done) self.$el.find("#done_value").text(res.done)
$("#closed_value").text(res.closed) self.$el.find("#closed_value").text(res.closed)
$("#new_state").click(function(){ // Month searching new state update
self.$el.find("#new_state").click(function(){
self.do_action({ self.do_action({
name:'New Tickets', name:'New Tickets',
type: 'ir.actions.act_window', type: 'ir.actions.act_window',
@ -147,7 +157,8 @@ var CustomDashBoard = AbstractAction.extend({
domain: [['id', '=', res.new_id]], domain: [['id', '=', res.new_id]],
}) })
}) })
$("#in_progress_state").click(function(){ // Month searching in progress state update
self.$el.find("#in_progress_state").click(function(){
self.do_action({ self.do_action({
name:'In progress Tickets', name:'In progress Tickets',
type: 'ir.actions.act_window', type: 'ir.actions.act_window',
@ -157,7 +168,8 @@ var CustomDashBoard = AbstractAction.extend({
domain: [['id', '=', res.in_progress_id]], domain: [['id', '=', res.in_progress_id]],
}) })
}) })
$("#cancelled_state").click(function(){ // Month searching cancel state update
self.$el.find("#cancelled_state").click(function(){
self.do_action({ self.do_action({
name:'Canceled Tickets', name:'Canceled Tickets',
type: 'ir.actions.act_window', type: 'ir.actions.act_window',
@ -167,7 +179,8 @@ var CustomDashBoard = AbstractAction.extend({
domain: [['id', '=', res.canceled_id]], domain: [['id', '=', res.canceled_id]],
}) })
}) })
$("#done_state").click(function(){ // Month searching done state update
self.$el.find("#done_state").click(function(){
self.do_action({ self.do_action({
name:'Done Tickets', name:'Done Tickets',
type: 'ir.actions.act_window', type: 'ir.actions.act_window',
@ -177,7 +190,8 @@ var CustomDashBoard = AbstractAction.extend({
domain: [['id', '=', res.done_id]], domain: [['id', '=', res.done_id]],
}) })
}) })
$("#closed_state").click(function(){ // Month searching closed state update
self.$el.find("#closed_state").click(function(){
self.do_action({ self.do_action({
name:'Closed Tickets', name:'Closed Tickets',
type: 'ir.actions.act_window', type: 'ir.actions.act_window',
@ -188,14 +202,17 @@ var CustomDashBoard = AbstractAction.extend({
}) })
}) })
}) })
}else if (value == "this_year") { }
// Year filtering start
else if (value == "this_year") {
ajax.rpc('/helpdesk_dashboard_year').then(function (res) { ajax.rpc('/helpdesk_dashboard_year').then(function (res) {
$("#new_state_value").text(res.new) self.$el.find("#new_state_value").text(res.new)
$("#inprogress_value").text(res.in_progress) self.$el.find("#inprogress_value").text(res.in_progress)
$("#canceled_value").text(res.canceled) self.$el.find("#canceled_value").text(res.canceled)
$("#done_value").text(res.done) self.$el.find("#done_value").text(res.done)
$("#closed_value").text(res.closed) self.$el.find("#closed_value").text(res.closed)
$("#new_state").click(function(){ // Year filtering new state update
self.$el.find("#new_state").click(function(){
self.do_action({ self.do_action({
name:'New Tickets', name:'New Tickets',
type: 'ir.actions.act_window', type: 'ir.actions.act_window',
@ -205,7 +222,8 @@ var CustomDashBoard = AbstractAction.extend({
domain: [['id', '=', res.new_id]], domain: [['id', '=', res.new_id]],
}) })
}) })
$("#in_progress_state").click(function(){ // Year filtering in progress state update
self.$el.find("#in_progress_state").click(function(){
self.do_action({ self.do_action({
name:'In progress Tickets', name:'In progress Tickets',
type: 'ir.actions.act_window', type: 'ir.actions.act_window',
@ -215,7 +233,8 @@ var CustomDashBoard = AbstractAction.extend({
domain: [['id', '=', res.in_progress_id]], domain: [['id', '=', res.in_progress_id]],
}) })
}) })
$("#cancelled_state").click(function(){ // Year filtering cancel state update
self.$el.find("#cancelled_state").click(function(){
self.do_action({ self.do_action({
name:'Canceled Tickets', name:'Canceled Tickets',
type: 'ir.actions.act_window', type: 'ir.actions.act_window',
@ -225,7 +244,8 @@ var CustomDashBoard = AbstractAction.extend({
domain: [['id', '=', res.canceled_id]], domain: [['id', '=', res.canceled_id]],
}) })
}) })
$("#done_state").click(function(){ // Year filtering done state update
self.$el.find("#done_state").click(function(){
self.do_action({ self.do_action({
name:'Done Tickets', name:'Done Tickets',
type: 'ir.actions.act_window', type: 'ir.actions.act_window',
@ -235,7 +255,8 @@ var CustomDashBoard = AbstractAction.extend({
domain: [['id', '=', res.done_id]], domain: [['id', '=', res.done_id]],
}) })
}) })
$("#closed_state").click(function(){ // Year filtering closed state update
self.$el.find("#closed_state").click(function(){
self.do_action({ self.do_action({
name:'Closed Tickets', name:'Closed Tickets',
type: 'ir.actions.act_window', type: 'ir.actions.act_window',
@ -251,11 +272,6 @@ var CustomDashBoard = AbstractAction.extend({
}) })
}, },
}) })
core.action_registry.add('helpdesk_dashboard_tag', CustomDashBoard); core.action_registry.add('helpdesk_dashboard_tag', CustomDashBoard);
return CustomDashBoard return CustomDashBoard
}) })

29
odoo_website_helpdesk/static/src/js/multiple_product_choose.js

@ -1,14 +1,23 @@
odoo.define('odoo_website_helpdesk.multiple_product_choose', function(require) { odoo.define('odoo_website_helpdesk.multiple_product_choose', function(require) {
"use strict"; "use strict";
var ajax = require('web.ajax'); var rpc = require('web.rpc');
$(document).ready(function() { var publicWidget = require('web.public.widget');
ajax.rpc('/product').then(function (res) { publicWidget.registry.SelectProduct = publicWidget.Widget.extend({
var ar = res selector: '.website_ticket',
$('#product').empty() start: function () {
$(ar).each(function(i){ var self = this;
$('#product').append("<option value=" + ar[i].id + ">" + ar[i].name + "</option>"); rpc.query({
route: '/product'
}).then(function (res) {
var ar = res;
self.$el.find('#product').empty();
ar.forEach(function (item) {
self.$el.find('#product').append("<option value='" + item.id + "'>" + item.name + "</option>");
});
self.$el.find('#product').SumoSelect({ clearAll: true });
}); });
$('#product').SumoSelect({ clearAll: true }); return this._super.apply(this, arguments);
},
}); });
}); return publicWidget.registry.SelectProduct;
}); });

16
odoo_website_helpdesk/static/src/js/portal_groupby.js

@ -1,16 +0,0 @@
odoo.define("odoo_website_helpdesk.portal_group_by", function (require) {
"use strict";
var ajax = require('web.ajax');
var core = require('web.core');
var QWeb = core.qweb;
$("#group_select").on('change', function () {
var search_value = $("#group_select").val();
ajax.jsonRpc('/ticketgroupby', 'call', {
'search_value': search_value,
}).then(function(result) {
$('.search_ticket').html(result);
});
})
})

33
odoo_website_helpdesk/static/src/js/portal_groupby_and_search.js

@ -0,0 +1,33 @@
odoo.define("odoo_website_helpdesk.portal_group_by_and_search", function (require) {
"use strict";
var ajax = require('web.ajax');
var publicWidget = require('web.public.widget');
publicWidget.registry.portalSearchGroup = publicWidget.Widget.extend({
selector: '.portal_group_by',
events: {
'change #group_select': '_onGroupSelectChange',
'click #search_ticket': '_searchTickets',
},
// GroupBy filtering the portal tickets
_onGroupSelectChange: function (ev) {
var self = this;
var searchValue = this.$el.find('#group_select').val();
ajax.jsonRpc('/ticketgroupby', 'call', {
'search_value': searchValue,
}).then(function (result) {
$('.search_ticket').html(result);
});
},
// Searching the portal tickets
_searchTickets: function (ev) {
var self = this;
var search_value = this.$el.find("#search_box").val();
ajax.jsonRpc('/ticketsearch', 'call', {
'search_value': search_value,
}).then(function(result) {
var self = this;
$('.search_ticket').html(result);
});
}
});
})

16
odoo_website_helpdesk/static/src/js/portal_search.js

@ -1,16 +0,0 @@
odoo.define("odoo_website_helpdesk.portal_search", function (require) {
"use strict";
var ajax = require('web.ajax');
var core = require('web.core');
var QWeb = core.qweb;
$("#search_ticket").on('click', function () {
var search_value = $("#search_box").val();
ajax.jsonRpc('/ticketsearch', 'call', {
'search_value': search_value,
}).then(function(result) {
$('.search_ticket').html(result);
});
})
})

4
odoo_website_helpdesk/static/src/js/ticket_details.js

@ -4,6 +4,7 @@ odoo.define("odoo_website_helpdesk.ticket_details", function (require) {
$(document).on("mouseover", "#popover", function (event) { $(document).on("mouseover", "#popover", function (event) {
var self = this; var self = this;
var item_text = ""; var item_text = "";
var element = $(this);
if (self.parentElement.parentElement.children[3]) { if (self.parentElement.parentElement.children[3]) {
item_text = item_text =
"Ticket : " + "Ticket : " +
@ -22,8 +23,7 @@ odoo.define("odoo_website_helpdesk.ticket_details", function (require) {
self.parentElement.parentElement.children[3].outerText + self.parentElement.parentElement.children[3].outerText +
"<br/>"; "<br/>";
} }
element.popover({
$(this).popover({
html: true, html: true,
placement: "right", placement: "right",
trigger: "hover", trigger: "hover",

272
odoo_website_helpdesk/static/src/xml/help_ticket_templates.xml

@ -0,0 +1,272 @@
<?xml version="1.0" encoding="utf-8" ?>
<templates>
<t t-name="HelpdeskDashBoard">
<section class="dashboard_main_section" id="main_section_manager">
<div class="row">
<style>
.c-dashboardInfo {
margin-bottom: 15px;
width: 20%;
}
.c-dashboardInfo .wrap {
background: #ffffff;
box-shadow: 2px 10px 20px rgba(0, 0, 0, 0.1);
border-radius: 7px;
text-align: center;
position: relative;
overflow: hidden;
padding: 40px 25px 20px;
height: 100%;
}
.c-dashboardInfo__title,
.c-dashboardInfo__subInfo {
color: #6c6c6c;
font-size: 1.18em;
}
.c-dashboardInfo span {
display: block;
}
.c-dashboardInfo__count {
font-weight: 600;
font-size: 2.5em;
line-height: 64px;
color: #323c43;
}
.c-dashboardInfo .wrap:after {
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 10px;
content: "";
}
.c-dashboardInfo:nth-child(1) .wrap:after {
background: linear-gradient(82.59deg, #00c48c 0%, #00a173
100%);
}
.wrap:hover{
-webkit-transform: scale(1.2);
-ms-transform: scale(1.2);
transform: scale(1.2);
transition: 1s ease;
}
.c-dashboardInfo:nth-child(2) .wrap:after {
background: linear-gradient(81.67deg, #0084f4 0%, #1a4da2
100%);
}
.c-dashboardInfo:nth-child(3) .wrap:after {
background: linear-gradient(69.83deg, #0084f4 0%, #00c48c
100%);
}
.c-dashboardInfo:nth-child(4) .wrap:after {
background: linear-gradient(81.67deg, #ff647c 0%, #1f5dc5
100%);
}
.c-dashboardInfo:nth-child(5) .wrap:after {
background: linear-gradient(82.59deg, #00c48c 0%, #00a173
100%);
}
.c-dashboardInfo:nth-child(6) .wrap:after {
background: linear-gradient(81.67deg, #ff647c 0%, #1f5dc5
100%);
}
.c-dashboardInfo__title svg {
color: #d7d7d7;
margin-left: 5px;
}
.MuiSvgIcon-root-19 {
fill: currentColor;
width: 1em;
height: 1em;
display: inline-block;
font-size: 24px;
transition: fill 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
user-select: none;
flex-shrink: 0;
}
.dropbtn {
background-color: #04AA6D;
color: white;
padding: 16px;
font-size: 16px;
border: none;
width: 16px;
}
.dropdown {
position: relative;
display: inline-block;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f1f1f1;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.dropdown-content a:hover {background-color: #ddd;}
.dropdown:hover .dropdown-content {display: block;}
.dropdown:hover .dropbtn {background-color: #3e8e41;}
</style>
<div class="col-sm-12 mb-4">
<div class="row">
<div class="col"
style="margin-top: 28px;margin-left: 88px;height: 48px;">
<h2 class="section-header" style="color:#4a5c9a;">
Helpdesk Dashboard
</h2>
</div>
<div class="col-md-4 d-flex justify-content-end bg-light"
style="margin-top: 20px;margin-right: 20px; padding-bottom: 40px">
<b style="white-space: nowrap;padding-right: 8px;padding-top: 8px;">
Filter by:
</b>
<select id="filter_selection"
style="width: 50%;padding:10px;border-radius:10px; background:white;">
<option id="this_year" value="this_year"
selected="">This Year
</option>
<option id="this_month"
value="this_month">This Month
</option>
<option id="this_week" value="this_week">This
Week
</option>
</select>
</div>
<hr/>
</div>
</div>
<div id="root">
<div class="container pt-5">
<div class="row align-items-stretch">
<div class="c-dashboardInfo"
id="new_state">
<div class="wrap">
<h4 class="heading heading5 hind-font medium-font-weight c-dashboardInfo__title">
New
<svg
class="MuiSvgIcon-root-19"
focusable="false"
viewBox="0 0 24 24"
aria-hidden="true"
role="presentation">
<path fill="none"
d="M0 0h24v24H0z"/>
<path
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z">
</path>
</svg>
</h4>
<span class="hind-font caption-12 c-dashboardInfo__count"
id="new_state_value">
</span>
</div>
</div>
<div class="c-dashboardInfo"
id="in_progress_state">
<div class="wrap">
<h4 class="heading heading5 hind-font medium-font-weight c-dashboardInfo__title">
In Progress
<svg
class="MuiSvgIcon-root-19"
focusable="false"
viewBox="0 0 24 24"
aria-hidden="true"
role="presentation">
<path fill="none"
d="M0 0h24v24H0z"/>
<path
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z">
</path>
</svg>
</h4>
<span class="hind-font caption-12 c-dashboardInfo__count"
id="inprogress_value">
</span>
</div>
</div>
<div class="c-dashboardInfo"
id="cancelled_state">
<div class="wrap">
<h4 class="heading heading5 hind-font medium-font-weight c-dashboardInfo__title">
Cancelled
<svg
class="MuiSvgIcon-root-19"
focusable="false"
viewBox="0 0 24 24"
aria-hidden="true"
role="presentation">
<path fill="none"
d="M0 0h24v24H0z"/>
<path
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z">
</path>
</svg>
</h4>
<span class="hind-font caption-12 c-dashboardInfo__count"
id="canceled_value">
</span>
</div>
</div>
<div class="c-dashboardInfo"
id="done_state">
<div class="wrap">
<h4 class="heading heading5 hind-font medium-font-weight c-dashboardInfo__title">
Done
<svg
class="MuiSvgIcon-root-19"
focusable="false"
viewBox="0 0 24 24"
aria-hidden="true"
role="presentation">
<path fill="none"
d="M0 0h24v24H0z"/>
<path
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z">
</path>
</svg>
</h4>
<span class="hind-font caption-12 c-dashboardInfo__count"
id="done_value">
</span>
</div>
</div>
<div class="c-dashboardInfo"
id="closed_state">
<div class="wrap">
<h4 class="heading heading5 hind-font medium-font-weight c-dashboardInfo__title">
Closed
<svg
class="MuiSvgIcon-root-19"
focusable="false"
viewBox="0 0 24 24"
aria-hidden="true"
role="presentation">
<path fill="none"
d="M0 0h24v24H0z"/>
<path
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z">
</path>
</svg>
</h4>
<span class="hind-font caption-12 c-dashboardInfo__count"
id="closed_value">
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</t>
</templates>

287
odoo_website_helpdesk/static/src/xml/helpdesk_dashboard.xml

@ -1,287 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<template>
<t t-name="HelpdeskDashBoard">
<section class="dashboard_main_section" id="main_section_manager">
<div class="row">
<style>
.c-dashboardInfo {
margin-bottom: 15px;
width: 20%;
}
.c-dashboardInfo .wrap {
background: #ffffff;
box-shadow: 2px 10px 20px rgba(0, 0, 0, 0.1);
border-radius: 7px;
text-align: center;
position: relative;
overflow: hidden;
padding: 40px 25px 20px;
height: 100%;
}
.c-dashboardInfo__title,
.c-dashboardInfo__subInfo {
color: #6c6c6c;
font-size: 1.18em;
}
.c-dashboardInfo span {
display: block;
}
.c-dashboardInfo__count {
font-weight: 600;
font-size: 2.5em;
line-height: 64px;
color: #323c43;
}
.c-dashboardInfo .wrap:after {
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 10px;
content: "";
}
.c-dashboardInfo:nth-child(1) .wrap:after {
background: linear-gradient(82.59deg, #00c48c 0%, #00a173
100%);
}
.wrap:hover{
-webkit-transform: scale(1.2);
-ms-transform: scale(1.2);
transform: scale(1.2);
transition: 1s ease;
}
.c-dashboardInfo:nth-child(2) .wrap:after {
background: linear-gradient(81.67deg, #0084f4 0%, #1a4da2
100%);
}
.c-dashboardInfo:nth-child(3) .wrap:after {
background: linear-gradient(69.83deg, #0084f4 0%, #00c48c
100%);
}
.c-dashboardInfo:nth-child(4) .wrap:after {
background: linear-gradient(81.67deg, #ff647c 0%, #1f5dc5
100%);
}
.c-dashboardInfo:nth-child(5) .wrap:after {
background: linear-gradient(82.59deg, #00c48c 0%, #00a173
100%);
}
.c-dashboardInfo:nth-child(6) .wrap:after {
background: linear-gradient(81.67deg, #ff647c 0%, #1f5dc5
100%);
}
.c-dashboardInfo__title svg {
color: #d7d7d7;
margin-left: 5px;
}
.MuiSvgIcon-root-19 {
fill: currentColor;
width: 1em;
height: 1em;
display: inline-block;
font-size: 24px;
transition: fill 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
user-select: none;
flex-shrink: 0;
}
.dropbtn {
background-color: #04AA6D;
color: white;
padding: 16px;
font-size: 16px;
border: none;
width: 16px;
}
.dropdown {
position: relative;
display: inline-block;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f1f1f1;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.dropdown-content a:hover {background-color: #ddd;}
.dropdown:hover .dropdown-content {display: block;}
.dropdown:hover .dropbtn {background-color: #3e8e41;}
</style>
<div class="col-sm-12 mb-4">
<div class="row">
<div class="col"
style="margin-top: 28px;margin-left: 88px;height: 48px;">
<h2 class="section-header" style="color:#4a5c9a;">
Helpdesk Dashboard
</h2>
</div>
<div class="col-md-4 d-flex justify-content-end bg-light"
style="margin-top: 20px;margin-right: 20px; padding-bottom: 40px">
<b style="white-space: nowrap;padding-right: 8px;padding-top: 8px;">Filter by:</b>
<select id="filter_selection" style="width: 50%;padding:10px;border-radius:10px; background:white;">
<option id="this_year" value="this_year"
selected="">This Year
</option>
<option id="this_month"
value="this_month">This Month
</option>
<option id="this_week" value="this_week">This Week
</option>
</select>
</div>
<hr/>
</div>
</div>
<div id="root">
<div class="container pt-5">
<div class="row align-items-stretch">
<div class="c-dashboardInfo"
id="new_state">
<div class="wrap">
<h4 class="heading heading5 hind-font medium-font-weight c-dashboardInfo__title">
New
<svg
class="MuiSvgIcon-root-19"
focusable="false"
viewBox="0 0 24 24"
aria-hidden="true"
role="presentation">
<path fill="none"
d="M0 0h24v24H0z"></path>
<path
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z">
</path>
</svg>
</h4>
<span class="hind-font caption-12 c-dashboardInfo__count"
id="new_state_value">
</span>
</div>
</div>
<div class="c-dashboardInfo"
id="in_progress_state">
<div class="wrap">
<h4 class="heading heading5 hind-font medium-font-weight c-dashboardInfo__title">
In Progress
<svg
class="MuiSvgIcon-root-19"
focusable="false"
viewBox="0 0 24 24"
aria-hidden="true"
role="presentation">
<path fill="none"
d="M0 0h24v24H0z"></path>
<path
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z">
</path>
</svg>
</h4>
<span class="hind-font caption-12 c-dashboardInfo__count"
id="inprogress_value">
</span>
</div>
</div>
<div class="c-dashboardInfo"
id="cancelled_state">
<div class="wrap">
<h4 class="heading heading5 hind-font medium-font-weight c-dashboardInfo__title">
Cancelled
<svg
class="MuiSvgIcon-root-19"
focusable="false"
viewBox="0 0 24 24"
aria-hidden="true"
role="presentation">
<path fill="none"
d="M0 0h24v24H0z"></path>
<path
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z">
</path>
</svg>
</h4>
<span class="hind-font caption-12 c-dashboardInfo__count"
id="canceled_value">
</span>
</div>
</div>
<div class="c-dashboardInfo"
id="done_state">
<div class="wrap">
<h4 class="heading heading5 hind-font medium-font-weight c-dashboardInfo__title">
Done
<svg
class="MuiSvgIcon-root-19"
focusable="false"
viewBox="0 0 24 24"
aria-hidden="true"
role="presentation">
<path fill="none"
d="M0 0h24v24H0z"></path>
<path
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z">
</path>
</svg>
</h4>
<span class="hind-font caption-12 c-dashboardInfo__count"
id="done_value">
</span>
<!-- <span-->
<!-- class="hind-font caption-12 c-dashboardInfo__subInfo">-->
<!-- Last month: €30-->
<!-- </span>-->
</div>
</div>
<div class="c-dashboardInfo"
id="closed_state">
<div class="wrap">
<h4 class="heading heading5 hind-font medium-font-weight c-dashboardInfo__title">
Closed
<svg
class="MuiSvgIcon-root-19"
focusable="false"
viewBox="0 0 24 24"
aria-hidden="true"
role="presentation">
<path fill="none"
d="M0 0h24v24H0z"></path>
<path
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z">
</path>
</svg>
</h4>
<span class="hind-font caption-12 c-dashboardInfo__count"
id="closed_value">
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</t>
</template>

58
odoo_website_helpdesk/templates/helpdesk_replay_template.xml

@ -1,58 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<data>
<!-- 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_help_ticket"/>
<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>
<h6><a t-attf-href="http://cybrosys:8050/@/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">
<t t-esc="object.assigned_user.name"/>
</t>
<t t-else="">
username
</t>
</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>
</data>
</odoo>

13
odoo_website_helpdesk/views/categories.xml

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="view_helpdesk_categories_tree" model="ir.ui.view">
<field name="name">categories.tree</field>
<field name="model">helpdesk.categories</field>
<field name="arch" type="xml">
<tree string="Categories" editable="bottom">
<field name="sequence" widget="handle"/>
<field name="name"/>
</tree>
</field>
</record>
</odoo>

16
odoo_website_helpdesk/views/team.xml → odoo_website_helpdesk/views/help_team_views.xml

@ -1,7 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<odoo> <odoo>
<record id="view_helpdesk_team_form" model="ir.ui.view"> <!-- Helpdesk ticket team view action-->
<field name="name">help.team.form</field> <record id="help_team_action" model="ir.actions.act_window">
<field name="name">Helpdesk</field>
<field name="res_model">help.team</field>
<field name="view_mode">tree,form</field>
</record>
<!-- Help_team form view-->
<record id="help_team_view_form" model="ir.ui.view">
<field name="name">help.team.view.form</field>
<field name="model">help.team</field> <field name="model">help.team</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<form> <form>
@ -45,8 +52,9 @@
</form> </form>
</field> </field>
</record> </record>
<record id="view_helpdesk_team_tree" model="ir.ui.view"> <!-- Help_team tree view-->
<field name="name">help.team.tree</field> <record id="help_team_view_tree" model="ir.ui.view">
<field name="name">help.team.view.tree</field>
<field name="model">help.team</field> <field name="model">help.team</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree> <tree>

143
odoo_website_helpdesk/views/helpdesk.xml → odoo_website_helpdesk/views/help_ticket_views.xml

@ -1,18 +1,37 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<odoo> <odoo>
<!-- Form view--> <!-- Ticket view action-->
<record id="view_helpdesk_form" model="ir.ui.view"> <record id="help_ticket_action" model="ir.actions.act_window">
<field name="name">help.ticket.form</field> <field name="name">Helpdesk</field>
<field name="res_model">help.ticket</field>
<field name="view_mode">kanban,tree,form,calendar,activity,pivot,graph</field>
</record>
<!-- My ticket view action-->
<record id="help_ticket_my_ticket_action" model="ir.actions.act_window">
<field name="name">My Helpdesk</field>
<field name="res_model">help.ticket</field>
<field name="domain">[('assigned_user','=',uid), ('team_head','=', uid)]</field>
<field name="view_mode">kanban,tree,form,calendar,activity,pivot,graph</field>
</record>
<!-- Ticket report action-->
<record id="help_ticket_report_action" model="ir.actions.act_window">
<field name="name">Report Help Desk</field>
<field name="res_model">help.ticket</field>
<field name="view_mode">graph,search</field>
</record>
<!-- Ticket form view-->
<record id="help_ticket_view_form" model="ir.ui.view">
<field name="name">help.ticket.view.form</field>
<field name="model">help.ticket</field> <field name="model">help.ticket</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<form> <form string="Ticket" class="o_event_form_view">
<header> <header>
<button name="action_send_reply" string="Reply" <button name="action_send_reply" string="Reply"
type="object" class="btn-primary"/> type="object" class="btn-primary"/>
<button name="create_tasks" string="Create Task" <button name="action_create_tasks" string="Create Task"
type="object" class="btn-primary" type="object" class="btn-primary"
attrs="{'invisible':[('create_task','=',False)]}"/> attrs="{'invisible':[('create_task','=',False)]}"/>
<button name="create_invoice" string="Create Invoice" <button name="action_create_invoice" string="Create Invoice"
type="object" class="btn-primary" type="object" class="btn-primary"
attrs="{'invisible':[('billable','=',False)]}"/> attrs="{'invisible':[('billable','=',False)]}"/>
<field name="stage_id" widget="statusbar" <field name="stage_id" widget="statusbar"
@ -20,12 +39,12 @@
</header> </header>
<sheet> <sheet>
<div class="oe_button_box" name="button_box"> <div class="oe_button_box" name="button_box">
<button class="oe_stat_button" name="open_tasks" <button class="oe_stat_button" name="action_open_tasks"
string="Tasks" type="object" icon="fa-tasks" string="Tasks" type="object" icon="fa-tasks"
attrs="{'invisible':[('create_task','=',False)]}"> attrs="{'invisible':[('create_task','=',False)]}">
</button> </button>
<button class="oe_stat_button" <button class="oe_stat_button"
name="open_merged_tickets" name="action_open_merged_tickets"
string="Merged Tickets" type="object" string="Merged Tickets" type="object"
icon="fa-list" icon="fa-list"
attrs="{'invisible':[('merge_ticket_invisible','=',False)]}"> attrs="{'invisible':[('merge_ticket_invisible','=',False)]}">
@ -34,8 +53,7 @@
<span class="o_stat_text">Merged Tickets</span> <span class="o_stat_text">Merged Tickets</span>
</div> </div>
</button> </button>
<button class="oe_stat_button" name="action_open_invoices"
<button class="oe_stat_button" name="open_invoices"
string="Invoices" type="object" icon="fa-tasks" string="Invoices" type="object" icon="fa-tasks"
attrs="{'invisible':[('billable','=',False)]}"> attrs="{'invisible':[('billable','=',False)]}">
</button> </button>
@ -65,7 +83,7 @@
<field name="create_date"/> <field name="create_date"/>
<field name="start_date"/> <field name="start_date"/>
<field name="end_date"/> <field name="end_date"/>
<field name="product_id" widget="many2many_tags"/> <field name="product_ids" widget="many2many_tags"/>
<field name="show_category" invisible="1"/> <field name="show_category" invisible="1"/>
<field name="merge_count" invisible="1"/> <field name="merge_count" invisible="1"/>
<field name="merge_ticket_invisible" invisible="1"/> <field name="merge_ticket_invisible" invisible="1"/>
@ -136,12 +154,12 @@
</form> </form>
</field> </field>
</record> </record>
<!--Tree view--> <!--Ticket tree view-->
<record id="view_helpdesk_tree" model="ir.ui.view"> <record id="help_ticket_view_tree" model="ir.ui.view">
<field name="name">help.ticket.tree</field> <field name="name">help.ticket.view.tree</field>
<field name="model">help.ticket</field> <field name="model">help.ticket</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree> <tree default_order="name desc">
<field name="name"/> <field name="name"/>
<field name="customer_id"/> <field name="customer_id"/>
<field name="customer_name"/> <field name="customer_name"/>
@ -150,8 +168,9 @@
</tree> </tree>
</field> </field>
</record> </record>
<record id="view_helpdesk_quick_create_form" model="ir.ui.view"> <!-- Ticket quick create form view-->
<field name="name">help.ticket.quick.form</field> <record id="help_ticket_view_form_quick_create" model="ir.ui.view">
<field name="name">help.ticket.view.form.quick.create</field>
<field name="model">help.ticket</field> <field name="model">help.ticket</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<form> <form>
@ -163,14 +182,14 @@
</form> </form>
</field> </field>
</record> </record>
<!-- Kanban view--> <!-- Ticket kanban view-->
<record id="view_helpdesk_kanban" model="ir.ui.view"> <record id="help_ticket_view_kanban" model="ir.ui.view">
<field name="name">help.ticket.kanban</field> <field name="name">help.ticket.view.kanban</field>
<field name="model">help.ticket</field> <field name="model">help.ticket</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<kanban default_group_by="stage_id" class="o_kanban_small_column" <kanban default_group_by="stage_id" class="o_kanban_small_column"
quick_create="true" quick_create="true"
quick_create_view="odoo_website_helpdesk.view_helpdesk_quick_create_form" quick_create_view="odoo_website_helpdesk.help_ticket_view_form_quick_create"
on_create="quick_create"> on_create="quick_create">
<field name="color"/> <field name="color"/>
<field name="name"/> <field name="name"/>
@ -244,9 +263,9 @@
</kanban> </kanban>
</field> </field>
</record> </record>
<!-- Activity view--> <!-- Ticket activity view-->
<record id="helpdesk_view_activity" model="ir.ui.view"> <record id="help_ticket_view_activity" model="ir.ui.view">
<field name="name">help.ticket.activity</field> <field name="name">help.ticket.view.activity</field>
<field name="model">help.ticket</field> <field name="model">help.ticket</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<activity string="Tickets"> <activity string="Tickets">
@ -262,9 +281,9 @@
</activity> </activity>
</field> </field>
</record> </record>
<!--Calendar view--> <!--Ticket Calendar view-->
<record id="help_ticket_view_calendar" model="ir.ui.view"> <record id="help_ticket_view_calendar" model="ir.ui.view">
<field name="name">help.ticket.calendar</field> <field name="name">help.ticket.view.calendar</field>
<field name="model">help.ticket</field> <field name="model">help.ticket</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<calendar string="Helpdesk Ticket" date_start="create_date" <calendar string="Helpdesk Ticket" date_start="create_date"
@ -276,67 +295,9 @@
</calendar> </calendar>
</field> </field>
</record> </record>
<!-- Stage form view--> <!--Ticket pivot view-->
<record id="view_helpdesk_stage_form" model="ir.ui.view">
<field name="name">ticket.stage.form</field>
<field name="model">ticket.stage</field>
<field name="arch" type="xml">
<form>
<sheet>
<group>
<group>
<field name="name"/>
<field name="template_id"/>
<field name="starting_stage"/>
<field name="cancel_stage"/>
</group>
<group>
<field name="fold"/>
<field name="sequence"/>
<field name="closing_stage"/>
<field name="group_ids" widget="many2many_tags"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<!--Stage tree view-->
<record id="view_helpdesk_stage_tree" model="ir.ui.view">
<field name="name">ticket.stage.tree</field>
<field name="model">ticket.stage</field>
<field name="arch" type="xml">
<tree>
<field name="name"/>
<field name="sequence"/>
<field name="closing_stage"/>
<field name="fold"/>
</tree>
</field>
</record>
<!--Type tree view-->
<record id="view_helpdesk_types_tree" model="ir.ui.view">
<field name="name">helpdesk.types.tree</field>
<field name="model">helpdesk.types</field>
<field name="arch" type="xml">
<tree editable="bottom">
<field name="name"/>
</tree>
</field>
</record>
<!--tag tree-->
<record id="view_helpdesk_tag_tree" model="ir.ui.view">
<field name="name">helpdesk.tag.tree</field>
<field name="model">helpdesk.tag</field>
<field name="arch" type="xml">
<tree editable="bottom">
<field name="name"/>
</tree>
</field>
</record>
<!--Pivot view-->
<record id="help_ticket_view_pivot" model="ir.ui.view"> <record id="help_ticket_view_pivot" model="ir.ui.view">
<field name="name">help.ticket.pivot</field> <field name="name">help.ticket.view.pivot</field>
<field name="model">help.ticket</field> <field name="model">help.ticket</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<pivot> <pivot>
@ -352,9 +313,9 @@
</pivot> </pivot>
</field> </field>
</record> </record>
<!--Graph view--> <!--Ticket graph view-->
<record id="help_ticket_view_graph" model="ir.ui.view"> <record id="help_ticket_view_graph" model="ir.ui.view">
<field name="name">help.ticket.graph</field> <field name="name">help.ticket.view.graph</field>
<field name="model">help.ticket</field> <field name="model">help.ticket</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<graph> <graph>
@ -370,9 +331,9 @@
</graph> </graph>
</field> </field>
</record> </record>
<!--Search view--> <!--Ticket search view-->
<record id="help_ticket_search" model="ir.ui.view"> <record id="help_ticket_view_search" model="ir.ui.view">
<field name="name">help.ticket.search</field> <field name="name">help.ticket.view.search</field>
<field name="model">help.ticket</field> <field name="model">help.ticket</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<search string="Ticket Search"> <search string="Ticket Search">

20
odoo_website_helpdesk/views/helpdesk_categories_views.xml

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!-- Helpdesk categories view action-->
<record id="helpdesk_categories_action" model="ir.actions.act_window">
<field name="name">Categories</field>
<field name="res_model">helpdesk.categories</field>
<field name="view_mode">tree</field>
</record>
<!-- Helpdesk category tree view-->
<record id="helpdesk_categories_view_tree" model="ir.ui.view">
<field name="name">helpdesk.categories.view.tree</field>
<field name="model">helpdesk.categories</field>
<field name="arch" type="xml">
<tree string="Categories" editable="bottom">
<field name="sequence" widget="handle"/>
<field name="name"/>
</tree>
</field>
</record>
</odoo>

61
odoo_website_helpdesk/views/helpdesk_replay_template.xml

@ -0,0 +1,61 @@
<?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_help_ticket"/>
<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">
<t t-esc="object.assigned_user.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>

24
odoo_website_helpdesk/views/helpdesk_tag_views.xml

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!-- Helpdesk tag view action-->
<record id="helpdesk_tag_action" model="ir.actions.act_window">
<field name="name">Tags</field>
<field name="res_model">helpdesk.tag</field>
<field name="view_mode">tree</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a new record!
</p>
</field>
</record>
<!--Helpdesk tag tree view-->
<record id="helpdesk_tag_view_tree" model="ir.ui.view">
<field name="name">helpdesk.tag.view.tree</field>
<field name="model">helpdesk.tag</field>
<field name="arch" type="xml">
<tree editable="bottom">
<field name="name"/>
</tree>
</field>
</record>
</odoo>

24
odoo_website_helpdesk/views/helpdesk_types_views.xml

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!-- Helpdesk types view action-->
<record id="helpdesk_types_action" model="ir.actions.act_window">
<field name="name">Types</field>
<field name="res_model">helpdesk.types</field>
<field name="view_mode">tree</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a new record!
</p>
</field>
</record>
<!-- Helpdesk type tree view-->
<record id="helpdesk_types_view_tree" model="ir.ui.view">
<field name="name">helpdesk.types.view.tree</field>
<field name="model">helpdesk.types</field>
<field name="arch" type="xml">
<tree editable="bottom">
<field name="name"/>
</tree>
</field>
</record>
</odoo>

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

Loading…
Cancel
Save