diff --git a/odoo_website_helpdesk/README.rst b/odoo_website_helpdesk/README.rst index fa956625c..425c5fc25 100644 --- a/odoo_website_helpdesk/README.rst +++ b/odoo_website_helpdesk/README.rst @@ -4,33 +4,30 @@ Website Helpdesk Support Ticket Management ========================================== +- HelpDesk Support for Odoo 18 community edition -The module is a comprehensive solution designed to streamline and enhance -support ticket management within your Odoo instance. This module extends the -capabilities of Odoo's helpdesk functionality, providing a user-friendly -interface for customers to submit, track, and manage support tickets efficiently. +Installation +============ +- www.odoo.com/documentation/18.0/setup/install.html +- Install our custom addon -Configuration -============= -* No additional configurations needed +License +------- +General Public License, Version 3 (LGPL v3). +(https://www.odoo.com/documentation/user/18.0/legal/licenses/licenses.html) Company ------- * `Cybrosys Techno Solutions `__ -License -------- -General Public License, Version 3 (LGPL v3). -(https://www.gnu.org/licenses/lgpl-3.0-standalone.html) - Credits ------- -* Developer:(v16) Junaidul Ansar M , Contacts : odoo@cybrosys.com +* Developers: (V18) Bhagyadev KP, +* Contact: odoo@cybrosys.com Contacts -------- * Mail Contact : odoo@cybrosys.com -* Website : https://cybrosys.com Bug Tracker ----------- @@ -41,8 +38,6 @@ Maintainer .. image:: https://cybrosys.com/images/logo.png :target: https://cybrosys.com -This module is maintained by Cybrosys Technologies. - For support and more information, please visit https://www.cybrosys.com Further information diff --git a/odoo_website_helpdesk/__init__.py b/odoo_website_helpdesk/__init__.py index 0fd044ce3..91b93f2f6 100644 --- a/odoo_website_helpdesk/__init__.py +++ b/odoo_website_helpdesk/__init__.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- -############################################################################# +################################################################################ # # Cybrosys Technologies Pvt. Ltd. # -# Copyright (C) 2023-TODAY Cybrosys Technologies() -# Author: Cybrosys Techno Solutions() +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Bhagyadev KP () # # You can modify it under the terms of the GNU LESSER # GENERAL PUBLIC LICENSE (LGPL v3), Version 3. @@ -18,6 +18,6 @@ # (LGPL v3) along with this program. # If not, see . # -############################################################################# +################################################################################ from . import controller from . import models diff --git a/odoo_website_helpdesk/__manifest__.py b/odoo_website_helpdesk/__manifest__.py index e0bf26fbc..d8af91749 100644 --- a/odoo_website_helpdesk/__manifest__.py +++ b/odoo_website_helpdesk/__manifest__.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- -############################################################################# +################################################################################ # # Cybrosys Technologies Pvt. Ltd. # -# Copyright (C) 2023-TODAY Cybrosys Technologies() -# Author: Cybrosys Techno Solutions() +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Bhagyadev KP () # # You can modify it under the terms of the GNU LESSER # GENERAL PUBLIC LICENSE (LGPL v3), Version 3. @@ -18,59 +18,54 @@ # (LGPL v3) along with this program. # If not, see . # -############################################################################# +################################################################################ { - 'name': "Website Helpdesk Support Ticket Management", - 'version': '16.0.3.0.1', + 'name': "Website Helpdesk Management", + 'version': '18.0.1.0.2', 'category': 'Website', - 'summary': """Helpdesk Module for community""", - 'description': 'Can create ticket from website also and can manage it from' - ' backend.Bill can be created for ticket with service cost', + 'summary': """The website allows for the creation of tickets, which can + then be controlled from the backend.""", + 'description': """Website Helpdesk, Odoo Helpdesk, Helpdesk, Helpdesk Management, Helpdesk Ticket, Odoo18 Helpdesk, Website Ticket, Support Ticket, Odoo18""", 'author': "Cybrosys Techno Solutions", 'company': 'Cybrosys Techno Solutions', 'maintainer': 'Cybrosys Techno Solutions', - 'website': 'https://www.cybrosys.com', - 'depends': ['base', 'website', 'project', 'sale_project', - 'hr_timesheet', 'mail', 'contacts'], + 'website': "http://www.cybrosys.com", + 'depends': ['website', 'project', 'sale_project', 'hr_timesheet', + 'mail', 'contacts'], 'data': [ + 'security/odoo_website_helpdesk_groups.xml', 'security/odoo_website_helpdesk_security.xml', 'security/ir.model.access.csv', - 'data/ir_sequence_data.xml', - 'data/ticket_stage_data.xml', - 'data/helpdesk_types_data.xml', + 'data/helpdesk_category_data.xml', + 'data/helpdesk_replay_template_data.xml', + 'data/helpdesk_type_data.xml', 'data/ir_cron_data.xml', + 'data/ir_sequence_data.xml', 'data/mail_template_data.xml', - 'views/help_team_views.xml', - 'views/portal_search_templates.xml', - 'views/res_config_settings_views.xml', - 'views/website_form.xml', - 'views/report_templates.xml', - 'views/help_ticket_views.xml', - 'views/portal_views_templates.xml', - 'views/helpdesk_categories_views.xml', - 'views/rating_form_templates.xml', - 'views/merge_tickets_views.xml', + 'data/ticket_stage_data.xml', + 'views/helpdesk_category_views.xml', 'views/helpdesk_tag_views.xml', - 'views/helpdesk_types_views.xml', + 'views/helpdesk_type_views.xml', + 'views/merge_ticket_views.xml', + 'views/odoo_website_helpdesk_portal_templates.xml', + 'views/portal_templates.xml', + 'views/rating_form.xml', + 'report/helpdesk_ticket_report_template.xml', + 'views/res_config_settings_views.xml', + 'views/team_helpdesk_views.xml', + 'views/ticket_helpdesk_views.xml', 'views/ticket_stage_views.xml', - 'views/helpdesk_replay_template.xml', - 'views/odoo_website_helpdesk_menus.xml', - 'report/help_ticket_templates.xml', + 'views/website_form.xml', + 'views/helpdesk_menu_views.xml', ], 'assets': { - 'web.assets_backend': [ - 'odoo_website_helpdesk/static/src/xml/help_ticket_templates.xml', - 'odoo_website_helpdesk/static/src/js/helpdesk_dashboard_action.js', - ], 'web.assets_frontend': [ - 'odoo_website_helpdesk/static/src/js/ticket_details.js', - '/odoo_website_helpdesk/static/src/js/portal_groupby_and_search.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/multiple_product_choose.js', - '/odoo_website_helpdesk/static/src/cdn/jquery.sumoselect.min.js', - '/odoo_website_helpdesk/static/src/cdn/sumoselect.min.css', ] }, - 'images': ['static/description/banner.png'], + 'images': ['static/description/banner.jpg'], 'license': 'LGPL-3', 'installable': True, 'auto_install': False, diff --git a/odoo_website_helpdesk/controller/__init__.py b/odoo_website_helpdesk/controller/__init__.py index f5133fcde..a45781185 100644 --- a/odoo_website_helpdesk/controller/__init__.py +++ b/odoo_website_helpdesk/controller/__init__.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- -############################################################################# +################################################################################ # # Cybrosys Technologies Pvt. Ltd. # -# Copyright (C) 2023-TODAY Cybrosys Technologies() -# Author: Cybrosys Techno Solutions() +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Bhagyadev KP () # # You can modify it under the terms of the GNU LESSER # GENERAL PUBLIC LICENSE (LGPL v3), Version 3. @@ -18,9 +18,10 @@ # (LGPL v3) along with this program. # If not, see . # -############################################################################# -from . import helpdesk_website +################################################################################ +from . import odoo_website_helpdesk from . import portal -from . import ticket_search from . import ticket_group_by -from . import website +from . import ticket_search +from . import website_form +from . import website_ticket diff --git a/odoo_website_helpdesk/controller/helpdesk_website.py b/odoo_website_helpdesk/controller/helpdesk_website.py deleted file mode 100644 index 75c3cd96c..000000000 --- a/odoo_website_helpdesk/controller/helpdesk_website.py +++ /dev/null @@ -1,266 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################# -# -# Cybrosys Technologies Pvt. Ltd. -# -# Copyright (C) 2023-TODAY Cybrosys Technologies() -# Author: Cybrosys Techno Solutions() -# -# 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 . -# -############################################################################# -import datetime as DT -from odoo import http -from odoo.http import request - - -class HelpDeskDashboard(http.Controller): - """Website helpdesk dashboard""" - - @http.route(['/helpdesk_dashboard'], type='json', auth="public") - def helpdesk_dashboard(self): - """Helpdesk dashboard controller""" - stage_new = request.env['ticket.stage'].search( - [('name', '=', 'Inbox')], limit=1).id - stage_draft = request.env['ticket.stage'].search( - [('name', '=', 'Draft')], limit=1).id - stage_inprogress = request.env['ticket.stage'].search( - [('name', '=', 'In Progress')], limit=1).id - stage_canceled = request.env['ticket.stage'].search( - [('name', '=', 'Canceled')], limit=1).id - stage_done = request.env['ticket.stage'].search( - [('name', '=', 'Done')], limit=1).id - stage_closed = request.env['ticket.stage'].search( - [('name', '=', 'Closed')], limit=1).id - stage_ids = [stage_new, stage_draft] - new = request.env["help.ticket"].search_count( - [('stage_id', 'in', stage_ids)]) - new_id = request.env["help.ticket"].search( - [('stage_id', 'in', stage_ids)]) - new_id_ls = [data.id for data in new_id] - in_progress = request.env["help.ticket"].search_count( - [('stage_id', '=', stage_inprogress)]) - in_progress_id = request.env["help.ticket"].search( - [('stage_id', '=', stage_inprogress)]) - in_progress_ls = [data.id for data in in_progress_id] - canceled = request.env["help.ticket"].search_count( - [('stage_id', '=', stage_canceled)]) - canceled_id = request.env["help.ticket"].search( - [('stage_id', '=', stage_canceled)]) - canceled_id_ls = [data.id for data in canceled_id] - done = request.env["help.ticket"].search_count( - [('stage_id', '=', stage_done)]) - done_id = request.env["help.ticket"].search( - [('stage_id', '=', stage_done)]) - done_id_ls = [data.id for data in done_id] - closed = request.env["help.ticket"].search_count( - [('stage_id', '=', stage_closed)]) - closed_id = request.env["help.ticket"].search( - [('stage_id', '=', stage_closed)]) - closed_id_ls = [data.id for data in closed_id] - dashboard_values = { - 'new': new, - 'in_progress': in_progress, - 'canceled': canceled, - 'done': done, - 'closed': closed, - 'new_id': new_id_ls, - 'in_progress_id': in_progress_ls, - 'canceled_id': canceled_id_ls, - 'done_id': done_id_ls, - 'closed_id': closed_id_ls, - } - return dashboard_values - - @http.route(['/helpdesk_dashboard_week'], type='json', auth="public") - def helpdesk_dashboard_week(self): - """Week based sorting controller""" - today = DT.date.today() - stage_new = request.env['ticket.stage'].search( - [('name', '=', 'Inbox')], limit=1).id - stage_draft = request.env['ticket.stage'].search( - [('name', '=', 'Draft')], limit=1).id - stage_inprogress = request.env['ticket.stage'].search( - [('name', '=', 'In Progress')], limit=1).id - stage_canceled = request.env['ticket.stage'].search( - [('name', '=', 'Canceled')], limit=1).id - stage_done = request.env['ticket.stage'].search( - [('name', '=', 'Done')], limit=1).id - stage_closed = request.env['ticket.stage'].search( - [('name', '=', 'Closed')], limit=1).id - stage_ids = [stage_new, stage_draft] - week_ago = str(today - DT.timedelta(days=7)) + ' ' - new = request.env["help.ticket"].search_count( - [('stage_id', 'in', stage_ids), ('create_date', '>', week_ago)]) - new_id = request.env["help.ticket"].search( - [('stage_id', 'in', stage_ids), ('create_date', '>', week_ago)]) - new_id_ls = [data.id for data in new_id] - in_progress = request.env["help.ticket"].search_count( - [('stage_id', '=', stage_inprogress), - ('create_date', '>', week_ago)]) - in_progress_id = request.env["help.ticket"].search( - [('stage_id', '=', stage_inprogress), - ('create_date', '>', week_ago)]) - in_progress_ls = [data.id for data in in_progress_id] - canceled = request.env["help.ticket"].search_count( - [('stage_id', '=', stage_canceled), - ('create_date', '>', week_ago)]) - canceled_id = request.env["help.ticket"].search( - [('stage_id', '=', stage_canceled), - ('create_date', '>', week_ago)]) - canceled_id_ls = [data.id for data in canceled_id] - done = request.env["help.ticket"].search_count( - [('stage_id', '=', stage_done), ('create_date', '>', week_ago)]) - done_id = request.env["help.ticket"].search( - [('stage_id', '=', stage_done), ('create_date', '>', week_ago)]) - done_id_ls = [data.id for data in done_id] - closed = request.env["help.ticket"].search_count( - [('stage_id', '=', stage_closed), ('create_date', '>', week_ago)]) - closed_id = request.env["help.ticket"].search( - [('stage_id', '=', stage_closed), ('create_date', '>', week_ago)]) - closed_id_ls = [data.id for data in closed_id] - dashboard_values = { - 'new': new, - 'in_progress': in_progress, - 'canceled': canceled, - 'done': done, - 'closed': closed, - 'new_id': new_id_ls, - 'in_progress_id': in_progress_ls, - 'canceled_id': canceled_id_ls, - 'done_id': done_id_ls, - 'closed_id': closed_id_ls, - } - return dashboard_values - - @http.route(['/helpdesk_dashboard_month'], type='json', auth="public") - def helpdesk_dashboard_month(self): - """Month based sorting controller""" - today = DT.date.today() - stage_new = request.env['ticket.stage'].search( - [('name', '=', 'Inbox')], limit=1).id - stage_draft = request.env['ticket.stage'].search( - [('name', '=', 'Draft')], limit=1).id - stage_inprogress = request.env['ticket.stage'].search( - [('name', '=', 'In Progress')], limit=1).id - stage_canceled = request.env['ticket.stage'].search( - [('name', '=', 'Canceled')], limit=1).id - stage_done = request.env['ticket.stage'].search( - [('name', '=', 'Done')], limit=1).id - stage_closed = request.env['ticket.stage'].search( - [('name', '=', 'Closed')], limit=1).id - stage_ids = [stage_new, stage_draft] - week_ago = str(today - DT.timedelta(days=30)) + ' ' - new = request.env["help.ticket"].search_count( - [('stage_id', 'in', stage_ids), ('create_date', '>', week_ago)]) - new_id = request.env["help.ticket"].search( - [('stage_id', 'in', stage_ids), ('create_date', '>', week_ago)]) - new_id_ls = [data.id for data in new_id] - in_progress = request.env["help.ticket"].search_count( - [('stage_id', '=', stage_inprogress), - ('create_date', '>', week_ago)]) - in_progress_id = request.env["help.ticket"].search( - [('stage_id', '=', stage_inprogress), - ('create_date', '>', week_ago)]) - in_progress_ls = [data.id for data in in_progress_id] - canceled = request.env["help.ticket"].search_count( - [('stage_id', '=', stage_canceled), - ('create_date', '>', week_ago)]) - canceled_id = request.env["help.ticket"].search( - [('stage_id', '=', stage_canceled), - ('create_date', '>', week_ago)]) - canceled_id_ls = [data.id for data in canceled_id] - done = request.env["help.ticket"].search_count( - [('stage_id', '=', stage_done), ('create_date', '>', week_ago)]) - done_id = request.env["help.ticket"].search( - [('stage_id', '=', stage_done), ('create_date', '>', week_ago)]) - done_id_ls = [data.id for data in done_id] - closed = request.env["help.ticket"].search_count( - [('stage_id', '=', stage_closed), ('create_date', '>', week_ago)]) - closed_id = request.env["help.ticket"].search( - [('stage_id', '=', stage_closed), ('create_date', '>', week_ago)]) - closed_id_ls = [data.id for data in closed_id] - dashboard_values = { - 'new': new, - 'in_progress': in_progress, - 'canceled': canceled, - 'done': done, - 'closed': closed, - 'new_id': new_id_ls, - 'in_progress_id': in_progress_ls, - 'canceled_id': canceled_id_ls, - 'done_id': done_id_ls, - 'closed_id': closed_id_ls, - } - return dashboard_values - - @http.route(['/helpdesk_dashboard_year'], type='json', auth="public") - def helpdesk_dashboard_year(self): - """Year based sorting""" - today = DT.date.today() - stage_new = request.env['ticket.stage'].search( - [('name', '=', 'Inbox')], limit=1).id - stage_draft = request.env['ticket.stage'].search( - [('name', '=', 'Draft')], limit=1).id - stage_inprogress = request.env['ticket.stage'].search( - [('name', '=', 'In Progress')], limit=1).id - stage_canceled = request.env['ticket.stage'].search( - [('name', '=', 'Canceled')], limit=1).id - stage_done = request.env['ticket.stage'].search( - [('name', '=', 'Done')], limit=1).id - stage_closed = request.env['ticket.stage'].search( - [('name', '=', 'Closed')], limit=1).id - stage_ids = [stage_new, stage_draft] - week_ago = str(today - DT.timedelta(days=360)) + ' ' - new = request.env["help.ticket"].search_count( - [('stage_id', 'in', stage_ids), ('create_date', '>', week_ago)]) - new_id = request.env["help.ticket"].search( - [('stage_id', 'in', stage_ids), ('create_date', '>', week_ago)]) - new_id_ls = [data.id for data in new_id] - in_progress = request.env["help.ticket"].search_count( - [('stage_id', '=', stage_inprogress), - ('create_date', '>', week_ago)]) - in_progress_id = request.env["help.ticket"].search( - [('stage_id', '=', stage_inprogress), - ('create_date', '>', week_ago)]) - in_progress_ls = [data.id for data in in_progress_id] - canceled = request.env["help.ticket"].search_count( - [('stage_id', '=', stage_canceled), - ('create_date', '>', week_ago)]) - canceled_id = request.env["help.ticket"].search( - [('stage_id', '=', stage_canceled), - ('create_date', '>', week_ago)]) - canceled_id_ls = [data.id for data in canceled_id] - done = request.env["help.ticket"].search_count( - [('stage_id', '=', stage_done), ('create_date', '>', week_ago)]) - done_id = request.env["help.ticket"].search( - [('stage_id', '=', stage_done), ('create_date', '>', week_ago)]) - done_id_ls = [data.id for data in done_id] - closed = request.env["help.ticket"].search_count( - [('stage_id', '=', stage_closed), ('create_date', '>', week_ago)]) - closed_id = request.env["help.ticket"].search( - [('stage_id', '=', stage_closed), ('create_date', '>', week_ago)]) - closed_id_ls = [data.id for data in closed_id] - dashboard_values = { - 'new': new, - 'in_progress': in_progress, - 'canceled': canceled, - 'done': done, - 'closed': closed, - 'new_id': new_id_ls, - 'in_progress_id': in_progress_ls, - 'canceled_id': canceled_id_ls, - 'done_id': done_id_ls, - 'closed_id': closed_id_ls, - } - return dashboard_values diff --git a/odoo_website_helpdesk/controller/odoo_website_helpdesk.py b/odoo_website_helpdesk/controller/odoo_website_helpdesk.py new file mode 100644 index 000000000..17a99a560 --- /dev/null +++ b/odoo_website_helpdesk/controller/odoo_website_helpdesk.py @@ -0,0 +1,162 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Bhagyadev KP () +# +# 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 . +# +################################################################################ +import datetime as DT +from odoo import http +from odoo.http import request + + +class HelpDeskDashboard(http.Controller): + """Controller for handling Help Desk dashboard requests.""" + + @http.route(['/helpdesk_dashboard'], type='json', auth="public") + def helpdesk_dashboard(self): + """Retrieves statistics for tickets in different stages. + Returns:dict: Dashboard statistics including counts and IDs for each + stage. + """ + stage_names = ['Inbox', 'Draft', 'In Progress', 'Canceled', 'Done', + 'Closed'] + stage_ids = { + name: request.env['ticket.stage'].search([('name', '=', name)], + limit=1).id for name in + stage_names} + new_stages = [stage_ids['Inbox'], stage_ids['Draft']] + def get_ticket_data(stage_ids): + tickets = request.env["ticket.helpdesk"].search( + [('stage_id', 'in', stage_ids)]) + return len(tickets), [ticket.id for ticket in tickets] + dashboard_values = { + 'new': (get_ticket_data(new_stages))[0], + 'new_id': (get_ticket_data(new_stages))[1], + 'in_progress': (get_ticket_data([stage_ids['In Progress']]))[0], + 'in_progress_id': (get_ticket_data([stage_ids['In Progress']]))[1], + 'canceled': (get_ticket_data([stage_ids['Canceled']]))[0], + 'canceled_id': (get_ticket_data([stage_ids['Canceled']]))[1], + 'done': (get_ticket_data([stage_ids['Done']]))[0], + 'done_id': (get_ticket_data([stage_ids['Done']]))[1], + 'closed': (get_ticket_data([stage_ids['Closed']]))[0], + 'closed_id': (get_ticket_data([stage_ids['Closed']]))[1]} + return dashboard_values + + def helpdesk_dashboard_week(self): + """ Retrieves statistics for tickets created in the past week. + Returns: + dict: Dashboard statistics including counts and IDs for each stage.""" + today = DT.date.today() + week_ago = str(today - DT.timedelta(days=7)) + ' ' + stage_names = ['Inbox', 'Draft', 'In Progress', 'Canceled', 'Done', + 'Closed'] + stages = { + name: request.env['ticket.stage'].search([('name', '=', name)], + limit=1).id for name in + stage_names} + stage_ids = [stages['Inbox'], stages['Draft']] + def get_ticket_data(stage_id): + count = request.env["ticket.helpdesk"].search_count( + [('stage_id', '=', stage_id), ('create_date', '>', week_ago)]) + ids = request.env["ticket.helpdesk"].search( + [('stage_id', '=', stage_id), + ('create_date', '>', week_ago)]).ids + return count, ids + new_count, new_ids = get_ticket_data(stage_ids) + in_progress_count, in_progress_ids = get_ticket_data( + stages['In Progress']) + canceled_count, canceled_ids = get_ticket_data(stages['Canceled']) + done_count, done_ids = get_ticket_data(stages['Done']) + closed_count, closed_ids = get_ticket_data(stages['Closed']) + dashboard_values = { + 'new': new_count, + 'in_progress': in_progress_count, + 'canceled': canceled_count, + 'done': done_count, + 'closed': closed_count, + 'new_id': new_ids, + 'in_progress_id': in_progress_ids, + 'canceled_id': canceled_ids, + 'done_id': done_ids, + 'closed_id': closed_ids, + } + return dashboard_values + + @http.route(['/helpdesk_dashboard_month'], type='json', auth="public") + def helpdesk_dashboard_month(self): + """Retrieves statistics for tickets created in the past month. + Returns: + dict: Dashboard statistics including counts and IDs for each stage.""" + today = DT.date.today() + month_ago = today - DT.timedelta(days=30) + week_ago = str(month_ago) + ' ' + stages = request.env['ticket.stage'].search([('name', 'in', + ['Inbox', 'Draft', + 'In Progress', + 'Canceled', 'Done', + 'Closed'])]) + stage_ids = {stage.name: stage.id for stage in stages} + def get_stage_data(stage_names): + stage_ids_list = [stage_ids[name] for name in stage_names] + tickets = request.env["ticket.helpdesk"].search( + [('stage_id', 'in', stage_ids_list), + ('create_date', '>', week_ago)]) + return len(tickets), [ticket.id for ticket in tickets] + new_count, new_ids = get_stage_data(['Inbox', 'Draft']) + in_progress_count, in_progress_ids = get_stage_data(['In Progress']) + canceled_count, canceled_ids = get_stage_data(['Canceled']) + done_count, done_ids = get_stage_data(['Done']) + closed_count, closed_ids = get_stage_data(['Closed']) + dashboard_values = { + 'new': new_count, + 'in_progress': in_progress_count, + 'canceled': canceled_count, + 'done': done_count, + 'closed': closed_count, + 'new_id': new_ids, + 'in_progress_id': in_progress_ids, + 'canceled_id': canceled_ids, + 'done_id': done_ids, + 'closed_id': closed_ids, + } + return dashboard_values + + @http.route(['/helpdesk_dashboard_year'], type='json', auth="public") + def helpdesk_dashboard_year(self): + """Retrieves statistics for tickets created in the past year. + Returns: + dict: Dashboard statistics including counts and IDs for each stage. + """ + today = DT.date.today() + year_ago = today - DT.timedelta(days=360) + stages = ['Inbox', 'Draft', 'In Progress', 'Canceled', 'Done', 'Closed'] + stage_ids = { + stage: request.env['ticket.stage'].search([('name', '=', stage)], + limit=1).id for stage in + stages} + def get_ticket_data(stage_name): + stage_id = stage_ids[stage_name] + tickets = request.env["ticket.helpdesk"].search( + [('stage_id', '=', stage_id), ('create_date', '>', year_ago)]) + return len(tickets), [ticket.id for ticket in tickets] + dashboard_values = {} + for stage in stages: + count, ids = get_ticket_data(stage) + dashboard_values[stage.lower()] = count + dashboard_values[f'{stage.lower()}_id'] = ids + return dashboard_values diff --git a/odoo_website_helpdesk/controller/portal.py b/odoo_website_helpdesk/controller/portal.py index 3a9d18043..d7b150250 100644 --- a/odoo_website_helpdesk/controller/portal.py +++ b/odoo_website_helpdesk/controller/portal.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- -############################################################################# +################################################################################ # # Cybrosys Technologies Pvt. Ltd. # -# Copyright (C) 2023-TODAY Cybrosys Technologies() -# Author: Cybrosys Techno Solutions() +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Bhagyadev KP () # # You can modify it under the terms of the GNU LESSER # GENERAL PUBLIC LICENSE (LGPL v3), Version 3. @@ -18,38 +18,46 @@ # (LGPL v3) along with this program. # If not, see . # -############################################################################# +################################################################################ from odoo import http from odoo.addons.portal.controllers import portal from odoo.http import request class TicketPortal(portal.CustomerPortal): - """ Controller for handling customer portal related actions related to - helpdesk tickets. - """ + def _prepare_home_portal_values(self, counters): - """Prepares a dictionary of values to be used in the home portal view - and get their count.""" + """ + Prepare values for the home portal, including ticket count. Args: + counters (dict): A dictionary containing counters for various portal + information. Returns: dict: A dictionary of values for the home portal. + """ values = super()._prepare_home_portal_values(counters) if 'ticket_count' in counters: - ticket_count = request.env['help.ticket'].search_count( + ticket_count = request.env['ticket.helpdesk'].search_count( self._get_tickets_domain()) if request.env[ - 'help.ticket'].check_access_rights( + 'ticket.helpdesk'].check_access_rights( 'read', raise_exception=False) else 0 values['ticket_count'] = ticket_count return values def _get_tickets_domain(self): - """Checking the domain""" + """ + Define the domain for searching tickets related to the current customer. + Returns: + list: A list representing the domain for ticket search. + """ return [('customer_id', '=', request.env.user.partner_id.id)] @http.route(['/my/tickets'], type='http', auth="user", website=True) def portal_my_tickets(self): - """Displays a list of tickets for the current user in the user's - portal.""" + """ + Route to display the tickets associated with the current customer. + Returns: + http.Response: The HTTP response rendering the tickets page. + """ domain = self._get_tickets_domain() - tickets = request.env['help.ticket'].search(domain) + tickets = request.env['ticket.helpdesk'].sudo().search(domain) values = { 'default_url': "/my/tickets", 'tickets': tickets, @@ -60,10 +68,16 @@ class TicketPortal(portal.CustomerPortal): @http.route(['/my/tickets/'], type='http', auth="public", website=True) - 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)]) + def portal_tickets_details(self, **kwargs): + """ + Route to display the details of a specific ticket. + Args: + ticket_id (int): The ID of the ticket to be displayed. + Returns: + http.Response: The HTTP response rendering the ticket details page. + """ + ticket_id = kwargs.get("id") + details = request.env['ticket.helpdesk'].sudo().browse(ticket_id) data = { 'page_name': 'ticket', 'ticket': True, @@ -75,60 +89,23 @@ class TicketPortal(portal.CustomerPortal): @http.route('/my/tickets/download/', auth='public', type='http', website=True) - def ticket_download_portal(self, id): - """Download the ticket information in a pdf formate of the current - event ticket.""" + def ticket_download_portal(self, **kwargs): + """ + Route to download a PDF version of a specific ticket. + Args: + ticket (str): The ID of the ticket to be downloaded. + Returns: + http.Response: The HTTP response with the PDF file for download. + """ + ticket_id = int(kwargs.get('id')) data = { - 'help': request.env['help.ticket'].sudo().browse(int(id))} + 'help': request.env['ticket.helpdesk'].sudo().browse(ticket_id)} report = request.env.ref( - 'odoo_website_helpdesk.action_report_helpdesk_ticket') - pdf, _ = request.env.ref( - 'odoo_website_helpdesk.action_report_helpdesk_ticket').sudo()._render_qweb_pdf( - report, data=data) + 'odoo_website_helpdesk.report_ticket') + pdf, _ = report.sudo()._render_qweb_pdf( + report, res_ids=ticket_id, data=data) pdf_http_headers = [('Content-Type', 'application/pdf'), ('Content-Length', len(pdf)), ('Content-Disposition', 'attachment; filename="Helpdesk Ticket.pdf"')] return request.make_response(pdf, headers=pdf_http_headers) - - -class WebsiteDesk(http.Controller): - """Control for handling the helpdesk tickets form and its submission.""" - @http.route(['/helpdesk_ticket'], type='http', auth="public", - website=True, sitemap=True) - def helpdesk_ticket(self): - """Render the helpdesk ticket form.""" - types = request.env['helpdesk.types'].sudo().search([]) - categories = request.env['helpdesk.categories'].sudo().search([]) - product = request.env['product.template'].sudo().search([]) - values = {} - values.update({ - 'types': types, - 'categories': categories, - 'product_website': product - }) - return request.render('odoo_website_helpdesk.ticket_form', values) - - @http.route(['/rating/'], type='http', auth="public", - website=True, - sitemap=True) - def rating(self, ticket_id): - """Render the helpdesk ticket rating form.""" - ticket = request.env['help.ticket'].browse(ticket_id) - data = { - 'ticket': ticket.id, - } - return request.render('odoo_website_helpdesk.rating_form', data) - - @http.route(['/rating//submit'], type='http', - auth="user", - website=True, csrf=False, - sitemap=True) - 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.write({ - 'customer_rating': post['rating'], - 'review': post['message'], - }) - return request.render('odoo_website_helpdesk.rating_thanks') diff --git a/odoo_website_helpdesk/controller/ticket_group_by.py b/odoo_website_helpdesk/controller/ticket_group_by.py index ca9c1a9a7..a3a968bd4 100644 --- a/odoo_website_helpdesk/controller/ticket_group_by.py +++ b/odoo_website_helpdesk/controller/ticket_group_by.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- -############################################################################# +################################################################################ # # Cybrosys Technologies Pvt. Ltd. # -# Copyright (C) 2023-TODAY Cybrosys Technologies() -# Author: Cybrosys Techno Solutions() +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Bhagyadev KP () # # You can modify it under the terms of the GNU LESSER # GENERAL PUBLIC LICENSE (LGPL v3), Version 3. @@ -18,29 +18,40 @@ # (LGPL v3) along with this program. # If not, see . # -############################################################################# +################################################################################ from odoo import http from odoo.http import request class TicketGroupBy(http.Controller): - """Control for handle the customer portal groupBy - filtering by the tickets.""" + """Controller for handling ticket grouping based on different criteria.""" + @http.route(['/ticketgroupby'], type='json', auth="public", website=True) def ticket_group_by(self, **kwargs): - """Display the list of tickets based on the groupBy filtering""" + """grouping tickets based on user-defined criteria. + Args: + - kwargs (dict): Keyword arguments received from the HTTP request. + Returns: + - http.Response: Rendered HTTP response containing grouped ticket information. + """ context = [] group_value = kwargs.get("search_value") if group_value == '0': context = [] - tickets = request.env["help.ticket"].search([]) - context.append(tickets) + tickets = request.env["ticket.helpdesk"].search( + [('user_id', '=', request.env.user.id)]) + if tickets: + context.append({ + 'name': '', + 'data': tickets + }) if group_value == '1': context = [] stage_ids = request.env['ticket.stage'].search([]) for stage in stage_ids: - ticket_ids = request.env['help.ticket'].search([ - ('stage_id', '=', stage.id) + ticket_ids = request.env['ticket.helpdesk'].search([ + ('stage_id', '=', stage.id), + ('user_id', '=', request.env.user.id) ]) if ticket_ids: context.append({ @@ -49,10 +60,11 @@ class TicketGroupBy(http.Controller): }) if group_value == '2': context = [] - type_ids = request.env['helpdesk.types'].search([]) + type_ids = request.env['helpdesk.type'].search([]) for types in type_ids: - ticket_ids_1 = request.env['help.ticket'].search([ - ('ticket_type', '=', types.id) + ticket_ids_1 = request.env['ticket.helpdesk'].search([ + ('ticket_type_id', '=', types.id), + ('user_id', '=', request.env.user.id) ]) if ticket_ids_1: context.append({ diff --git a/odoo_website_helpdesk/controller/ticket_search.py b/odoo_website_helpdesk/controller/ticket_search.py index b965041fa..12a7a6195 100644 --- a/odoo_website_helpdesk/controller/ticket_search.py +++ b/odoo_website_helpdesk/controller/ticket_search.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- -############################################################################# +################################################################################ # # Cybrosys Technologies Pvt. Ltd. # -# Copyright (C) 2023-TODAY Cybrosys Technologies() -# Author: Cybrosys Techno Solutions() +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Bhagyadev KP () # # You can modify it under the terms of the GNU LESSER # GENERAL PUBLIC LICENSE (LGPL v3), Version 3. @@ -18,20 +18,23 @@ # (LGPL v3) along with this program. # If not, see . # -############################################################################# +################################################################################ from odoo import http from odoo.http import request class TicketSearch(http.Controller): - """Control for handle the customer portal search - filtering by the tickets.""" @http.route(['/ticketsearch'], type='json', auth="public", website=True) def ticket_search(self, **kwargs): - """ Display the list of tickets satisfying the searching condition. - Searching the ticket based on name or subject""" + """ + Search for tickets based on the provided search value. + :param search_value: The value to search for in the ticket name or subject. + :type search_value: str + :return: A JSON response containing the matching tickets. + :rtype: http.Response + """ search_value = kwargs.get("search_value") - tickets = request.env["help.ticket"].search( + tickets = request.env["ticket.helpdesk"].search( ['|', ('name', 'ilike', search_value), ('subject', 'ilike', search_value)]) values = { diff --git a/odoo_website_helpdesk/controller/website.py b/odoo_website_helpdesk/controller/website.py deleted file mode 100644 index 2a3dc9069..000000000 --- a/odoo_website_helpdesk/controller/website.py +++ /dev/null @@ -1,173 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################# -# -# Cybrosys Technologies Pvt. Ltd. -# -# Copyright (C) 2023-TODAY Cybrosys Technologies() -# Author: Cybrosys Techno Solutions() -# -# 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 . -# -############################################################################# -import base64 -import json -from odoo import _, http -from psycopg2 import IntegrityError -from odoo.http import request -from odoo.exceptions import ValidationError -from odoo.addons.website.controllers.form import WebsiteForm - - -class HelpdeskProduct(http.Controller): - """It controls the website products and return the product.""" - @http.route('/product', auth='public', type='json') - def product(self): - """Product control function""" - products = request.env['product.template'].sudo().search_read([], - ['name', - 'id']) - return products - - -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): - """Website Help Desk Form""" - if model_name == 'help.ticket': - tickets = request.env['ticket.stage'].sudo().search([]) - for rec in tickets: - sequence = tickets.mapped('sequence') - lowest_sequence = tickets.filtered( - lambda x: x.sequence == min(sequence)) - if rec == lowest_sequence: - lowest_stage_id = lowest_sequence - products = kwargs.get('product') - partner_create = request.env['res.partner'].sudo().create({ - 'name':kwargs.get('customer_name'), - 'company_name':kwargs.get('company'), - 'phone':kwargs.get('phone'), - 'email':kwargs.get('email_from') - }) - if products: - splited_product = products.split(',') - product_list = [int(i) for i in splited_product] - rec_val = { - 'customer_name': kwargs.get('customer_name'), - 'subject': kwargs.get('subject'), - 'description': kwargs.get('description'), - 'email': kwargs.get('email_from'), - 'phone': kwargs.get('phone'), - 'priority': kwargs.get('priority'), - 'product_ids': product_list, - 'stage_id': lowest_stage_id.id, - 'customer_id': partner_create.id, - 'ticket_type': kwargs.get('ticket_type'), - 'category_id': kwargs.get('category'), - } - ticket_id = request.env['help.ticket'].sudo().create(rec_val) - request.session['ticket_number'] = ticket_id.name - request.session['ticket_id'] = ticket_id.id - model_record = request.env['ir.model'].sudo().search( - [('model', '=', model_name)]) - data = self.extract_data(model_record, request.params) - if ('ticket_attachment' in request.params or - request.httprequest.files or data.get( - 'attachments')): - attached_files = data.get('attachments') - for attachment in attached_files: - attached_file = attachment.read() - request.env['ir.attachment'].sudo().create({ - 'name': attachment.filename, - 'res_model': 'help.ticket', - 'res_id': ticket_id.id, - 'type': 'binary', - 'datas': base64.encodebytes(attached_file), - }) - request.session[ - 'form_builder_model_model'] = model_record.model - request.session['form_builder_model'] = model_record.name - request.session['form_builder_id'] = ticket_id.id - return json.dumps({'id': ticket_id.id}) - else: - rec_val = { - 'customer_name': kwargs.get('customer_name'), - 'subject': kwargs.get('subject'), - 'description': kwargs.get('description'), - 'email': kwargs.get('email_from'), - 'phone': kwargs.get('phone'), - 'priority': kwargs.get('priority'), - 'stage_id': lowest_stage_id.id, - 'customer_id': partner_create.id, - 'ticket_type': kwargs.get('ticket_type'), - 'category_id': kwargs.get('category'), - } - ticket_id = request.env['help.ticket'].sudo().create(rec_val) - request.session['ticket_number'] = ticket_id.name - request.session['ticket_id'] = ticket_id.id - model_record = request.env['ir.model'].sudo().search( - [('model', '=', model_name)]) - data = self.extract_data(model_record, request.params) - if ('ticket_attachment' in request.params or - request.httprequest.files or data.get( - 'attachments')): - attached_files = data.get('attachments') - for attachment in attached_files: - attached_file = attachment.read() - request.env['ir.attachment'].sudo().create({ - 'name': attachment.filename, - 'res_model': 'help.ticket', - 'res_id': ticket_id.id, - 'type': 'binary', - 'datas': base64.encodebytes(attached_file), - }) - request.session['form_builder_model_model'] = model_record.model - request.session['form_builder_model'] = model_record.name - request.session['form_builder_id'] = ticket_id.id - return json.dumps({'id': ticket_id.id}) - else: - model_record = request.env['ir.model'].sudo().search( - [('model', '=', model_name)]) - if not model_record: - return json.dumps({ - 'error': _("The form's specified model does not exist") - }) - try: - data = self.extract_data(model_record, request.params) - # If we encounter an issue while extracting data - except ValidationError as e: - return json.dumps({'error_fields': e.args[0]}) - try: - id_record = self.insert_record(request, model_record, - data['record'], data['custom'], - data.get('meta')) - if id_record: - self.insert_attachment(model_record, id_record, - data['attachments']) - # In case of an email, we want to send it immediately instead of waiting - # For the email queue to process - if model_name == 'mail.mail': - request.env[model_name].sudo().browse(id_record).send() - - # Some fields have additional SQL constraints that we can't check generically - # Ex: crm.lead.probability which is a float between 0 and 1 - # TODO: How to get the name of the erroneous field ? - except IntegrityError: - return json.dumps(False) - request.session['form_builder_model_model'] = model_record.model - request.session['form_builder_model'] = model_record.name - request.session['form_builder_id'] = id_record - return json.dumps({'id': id_record}) diff --git a/odoo_website_helpdesk/controller/website_form.py b/odoo_website_helpdesk/controller/website_form.py new file mode 100644 index 000000000..5f303e717 --- /dev/null +++ b/odoo_website_helpdesk/controller/website_form.py @@ -0,0 +1,169 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Bhagyadev KP () +# +# 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 . +# +################################################################################ +import base64 +import json +from psycopg2 import IntegrityError +from odoo import http, _ +from odoo.http import request +from odoo.exceptions import ValidationError +from odoo.addons.website.controllers.form import WebsiteForm + + +class HelpdeskProduct(http.Controller): + """ Controller for handling helpdesk products. + """ + + @http.route('/product', auth='public', type='json') + def product(self): + prols = [] + acc = request.env['product.template'].sudo().search([]) + for i in acc: + dic = {'name': i['name'], + 'id': i['id']} + prols.append(dic) + return prols + + +class WebsiteFormInherit(WebsiteForm): + + def _handle_website_form(self, model_name, **kwargs): + """ + Handle the submission of website forms. + :param model_name: The name of the model associated with the form. + :type model_name: str + :param kwargs: Keyword arguments containing form data. + :type kwargs: dict + :return: JSON response indicating the success or failure of form submission. + :rtype: str + """ + lowest_stage_id = None + if model_name == 'ticket.helpdesk': + tickets = request.env['ticket.stage'].sudo().search([]) + if tickets: + sequence = tickets.mapped('sequence') + lowest_sequence = tickets.filtered( + lambda x: x.sequence == min(sequence)) + if lowest_sequence: + lowest_stage_id = lowest_sequence[0] + if lowest_stage_id is None: + return json.dumps( + {'error': "No stage found with the lowest sequence."}) + products = kwargs.get('product') + partner_create = request.env['res.partner'].sudo().create({ + 'name': kwargs.get('customer_name'), + 'company_name': kwargs.get('company'), + 'phone': kwargs.get('phone'), + 'email': kwargs.get('email_from') + }) + if products: + split_product = products.split(',') + product_list = [int(i) for i in split_product] + rec_val = { + 'customer_name': kwargs.get('customer_name'), + 'subject': kwargs.get('subject'), + 'description': kwargs.get('description'), + 'email': kwargs.get('email_from'), + 'phone': kwargs.get('phone'), + 'priority': kwargs.get('priority'), + 'product_ids': product_list, + 'stage_id': lowest_stage_id.id, + 'customer_id': partner_create.id, + 'ticket_type_id': kwargs.get('ticket_type_id'), + 'category_id': kwargs.get('category'), + } + else: + rec_val = { + 'customer_name': kwargs.get('customer_name'), + 'subject': kwargs.get('subject'), + 'description': kwargs.get('description'), + 'email': kwargs.get('email_from'), + 'phone': kwargs.get('phone'), + 'priority': kwargs.get('priority'), + 'stage_id': lowest_stage_id.id, + 'customer_id': partner_create.id, + 'ticket_type_id': kwargs.get('ticket_type_id'), + 'category_id': kwargs.get('category'), + } + ticket_id = request.env['ticket.helpdesk'].sudo().create(rec_val) + if ticket_id and partner_create.email: + request.env['mail.mail'].sudo().create({ + 'subject': 'Your Ticket Has Been Created', + 'body_html': f"

Hello {partner_create.name},

Your ticket {ticket_id.name} with the subject {ticket_id.subject} has been successfully submitted. Our support team will contact you soon.

Thank You.

", + 'email_to': partner_create.email, + 'email_from': request.env.user.email or 'support@example.com', + }).send() + ticket_id.message_post( + body="A confirmation email regarding the ticket creation has been sent to the customer.", + subject="Ticket Confirmation Email", + message_type='email', + subtype_xmlid="mail.mt_comment", + ) + request.session['ticket_number'] = ticket_id.name + request.session['ticket_id'] = ticket_id.id + model_record = request.env['ir.model'].sudo().search( + [('model', '=', model_name)]) + attachments = [] + attachment_index = 0 + while f"ticket_attachment[0][{attachment_index}]" in kwargs: + attachment_key = f"ticket_attachment[0][{attachment_index}]" + if attachment_key in kwargs: + attachment = kwargs[attachment_key] + attachments.append(attachment) + attachment_index += 1 + for attachment in attachments: + attached_file = attachment.read() + request.env['ir.attachment'].sudo().create({ + 'name': attachment.filename, + 'res_model': 'ticket.helpdesk', + 'res_id': ticket_id.id, + 'type': 'binary', + 'datas': base64.encodebytes(attached_file), + }) + request.session['form_builder_model_model'] = model_record.model + request.session['form_builder_model'] = model_record.name + request.session['form_builder_id'] = ticket_id.id + return json.dumps({'id': ticket_id.id}) + else: + model_record = request.env['ir.model'].sudo().search( + [('model', '=', model_name)]) + if not model_record: + return json.dumps( + {'error': _("The form's specified model does not exist")}) + try: + data = self.extract_data(model_record, request.params) + except ValidationError as e: + return json.dumps({'error_fields': e.args[0]}) + try: + id_record = self.insert_record(request, model_record, + data['record'], data['custom'], + data.get('meta')) + if id_record: + self.insert_attachment(model_record, id_record, + data['attachments']) + if model_name == 'mail.mail': + request.env[model_name].sudo().browse(id_record).send() + except IntegrityError: + return json.dumps(False) + request.session['form_builder_model_model'] = model_record.model + request.session['form_builder_model'] = model_record.name + request.session['form_builder_id'] = id_record + return json.dumps({'id': id_record}) diff --git a/odoo_website_helpdesk/controller/website_ticket.py b/odoo_website_helpdesk/controller/website_ticket.py new file mode 100644 index 000000000..4065b86f0 --- /dev/null +++ b/odoo_website_helpdesk/controller/website_ticket.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Bhagyadev KP () +# +# 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 . +# +################################################################################ +from odoo import http +from odoo.http import request + + +class WebsiteDesk(http.Controller): + @http.route(['/helpdesk_ticket'], type='http', auth="public", website=True, + sitemap=True) + def helpdesk_ticket(self, **kwargs): + """ + Route to display the helpdesk ticket creation form. + Returns: + http.Response: The HTTP response rendering the helpdesk ticket form. + """ + types = request.env['helpdesk.type'].sudo().search([]) + categories = request.env['helpdesk.category'].sudo().search([]) + product = request.env['product.template'].sudo().search([]) + values = {} + values.update({ + 'types': types, + 'categories': categories, + 'product_website': product + }) + return request.render('odoo_website_helpdesk.ticket_form', values) + + @http.route(['/rating/'], type='http', auth="public", + website=True, + sitemap=True) + def rating(self, ticket_id): + """ + Route to display the rating form for a specific ticket. Args: + ticket_id (int): The ID of the ticket for which the rating form is + displayed. Returns: http.Response: The HTTP response rendering the + rating form. + """ + ticket = request.env['ticket.helpdesk'].browse(ticket_id) + data = { + 'ticket': ticket.id, + } + return request.render('odoo_website_helpdesk.rating_form', data) + + @http.route(['/rating//submit'], type='http', auth="user", + website=True, csrf=False, + sitemap=True) + def rating_backend(self, ticket_id, **post): + """ + Customer Rating + """ + ticket = request.env['ticket.helpdesk'].browse(ticket_id) + ticket.write({ + 'customer_rating': post['rating'], + 'review': post['message'], + }) + return request.render('odoo_website_helpdesk.rating_thanks') diff --git a/odoo_website_helpdesk/data/helpdesk_category_data.xml b/odoo_website_helpdesk/data/helpdesk_category_data.xml new file mode 100644 index 000000000..9d45f79b4 --- /dev/null +++ b/odoo_website_helpdesk/data/helpdesk_category_data.xml @@ -0,0 +1,13 @@ + + + + + + Internal + + + + Technical + + + diff --git a/odoo_website_helpdesk/views/helpdesk_replay_template.xml b/odoo_website_helpdesk/data/helpdesk_replay_template_data.xml similarity index 78% rename from odoo_website_helpdesk/views/helpdesk_replay_template.xml rename to odoo_website_helpdesk/data/helpdesk_replay_template_data.xml index a2ea88c6d..fa2d7ca56 100644 --- a/odoo_website_helpdesk/views/helpdesk_replay_template.xml +++ b/odoo_website_helpdesk/data/helpdesk_replay_template_data.xml @@ -1,18 +1,16 @@ - + Helpdesk Reply Email Template + ref="odoo_website_helpdesk.model_ticket_helpdesk"/> {{ object.name }} Replay

Helpdesk Replay

-
- message........ -
+
message........
@@ -25,12 +23,10 @@ Name - - - - - username + + + username @@ -40,9 +36,7 @@ - - Team name - + Team name diff --git a/odoo_website_helpdesk/data/helpdesk_type_data.xml b/odoo_website_helpdesk/data/helpdesk_type_data.xml new file mode 100644 index 000000000..8a8142416 --- /dev/null +++ b/odoo_website_helpdesk/data/helpdesk_type_data.xml @@ -0,0 +1,21 @@ + + + + + + Question + + + + Issue + + + + Repair + + + + Maintenance + + + diff --git a/odoo_website_helpdesk/data/helpdesk_types_data.xml b/odoo_website_helpdesk/data/helpdesk_types_data.xml deleted file mode 100644 index f2bc285c2..000000000 --- a/odoo_website_helpdesk/data/helpdesk_types_data.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - Question - - - Issue - - - Repair - - - Maintenance - - - Internal - - - Technical - - diff --git a/odoo_website_helpdesk/data/ir_cron_data.xml b/odoo_website_helpdesk/data/ir_cron_data.xml index 17894d9ed..f05189555 100644 --- a/odoo_website_helpdesk/data/ir_cron_data.xml +++ b/odoo_website_helpdesk/data/ir_cron_data.xml @@ -1,17 +1,15 @@ - - + + Auto Close Ticket - + code model.auto_close_ticket() 1 days - -1 diff --git a/odoo_website_helpdesk/data/ir_sequence_data.xml b/odoo_website_helpdesk/data/ir_sequence_data.xml index 0323aafd7..8dd4772d8 100644 --- a/odoo_website_helpdesk/data/ir_sequence_data.xml +++ b/odoo_website_helpdesk/data/ir_sequence_data.xml @@ -1,20 +1,23 @@ - - - Helpdesk - help.ticket - TKT - 5 - 1 - - - - Helpdesk Invoice - ticket.invoice - INV/TKT/%(year)s/ - 3 - - - + + + + Helpdesk + ticket.helpdesk + TKT + 5 + + + + + + Helpdesk Invoice + ticket.invoice + INV/TKT/%(year)s/ + 3 + + + + diff --git a/odoo_website_helpdesk/data/mail_template_data.xml b/odoo_website_helpdesk/data/mail_template_data.xml index 56cfd5d36..66236e8eb 100644 --- a/odoo_website_helpdesk/data/mail_template_data.xml +++ b/odoo_website_helpdesk/data/mail_template_data.xml @@ -1,140 +1,142 @@ - - - Create Ticket - - - {{object.customer_id.email}} - Ticket Created - -

- Dear - -
- Your Ticket - - is Created and Assigned.Kindly Wait while we're resolving - your Query -
-
- Thanks. -

-
-
- - - Close Ticket And Feedback - - - {{object.customer_id.email}} - Ticket Closed - -

- Dear - - Your Ticket - - Is Closed -
- -
-
- Thanks. -

-
-
- - - Reopened Ticket - - - {{object.customer_id.email}} - Ticket Reopened - -

- Dear - -
- Your Ticket - - is Reopened -
-
- Thanks. -

-
-
- - - Approve Ticket - - - {{object.customer_id.email}} - Ticket Solved - -

- Dear - -
- i think your Problem is Solved. - Your Ticket - - is Done -
-
- Thanks. -

-
-
- - - Cancel Ticket - - - {{object.customer_id.email}} - Ticket Canceled - -

- Dear - -
- Your Ticket - - is Canceled Due to Some Reasons -
-
- Thanks. -

-
-
- - + + + Create Ticket + + + {{object.customer_id.email}} + Ticket Created + +

+ Dear + +
+ Your Ticket + + is Created and Assigned. Kindly Wait while we're resolving your Query +
+
+ Thanks. +

+
+
+ + + Close Ticket And Feedback + + + {{object.customer_id.email}} + Ticket Closed + +

+ Dear + + Your Ticket + + Is Closed +
+ +
+
+ Thanks. +

+ +
+
+ + + Reopened Ticket + + + {{object.customer_id.email}} + Ticket Reopened + +

+ Dear + +
+ Your Ticket + + is Reopened +
+
+ Thanks. +

+
+
+ + + Approve Ticket + + + {{object.customer_id.email}} + Ticket Solved + +

+ Dear + +
+ i think your Problem is Solved. + Your Ticket + + is Done +
+
+ Thanks. +

+
+
+ + + + Cancel Ticket + + + {{object.customer_id.email}} + Ticket Canceled + +

+ Dear + +
+ Your Ticket + + is Canceled Due to Some Reasons +
+
+ Thanks. +

+
+
+ + + + Ticket Assign + ref="odoo_website_helpdesk.model_ticket_helpdesk"/>

Dear, - +

-

Your team has been given the ticket [] kindly complete your work +

Your team has been given the ticket [] kindly complete your work carefully.


@@ -153,22 +155,21 @@
- - + Ticket Assign to User + ref="odoo_website_helpdesk.model_ticket_helpdesk"/>

Dear, - +

-

Ticket [] Assign to you , kindly - complete your work carefully. +

Ticket [] Assign to you , kindly complete your work carefully.


Details

@@ -186,26 +187,27 @@
- - + Mail To Customer Assign to User + ref="odoo_website_helpdesk.model_ticket_helpdesk"/>

Dear,

-

Ticket [] successfully assigned - to "". +

Ticket [] successfully assigned to "".


Best regards

+
diff --git a/odoo_website_helpdesk/data/ticket_stage_data.xml b/odoo_website_helpdesk/data/ticket_stage_data.xml index 0ee6cbb5e..43ccbd24e 100644 --- a/odoo_website_helpdesk/data/ticket_stage_data.xml +++ b/odoo_website_helpdesk/data/ticket_stage_data.xml @@ -1,39 +1,39 @@ - - - 10 - Inbox - - - - 15 - Draft - - - - 20 - - In Progress - - - - 25 - Done - - - - - 30 - Canceled - - - - - - 29 - Closed - - - - + + + + + 10 + Inbox + + + + 15 + Draft + + + + 25 + Done + + + + 20 + + In Progress + + + + 30 + True + Closed + + + + 35 + True + Canceled + + + \ No newline at end of file diff --git a/odoo_website_helpdesk/doc/RELEASE_NOTES.md b/odoo_website_helpdesk/doc/RELEASE_NOTES.md index d7dc12c50..1f9bec8cb 100644 --- a/odoo_website_helpdesk/doc/RELEASE_NOTES.md +++ b/odoo_website_helpdesk/doc/RELEASE_NOTES.md @@ -1,11 +1,25 @@ ## Module -#### 04.12.2023 -#### Version 16.0.1.0.0 +#### 30.10.2024 +#### Version 18.0.1.0.0 #### ADD + - Initial commit for Website Helpdesk Support Ticket Management #### 12.02.2025 -#### Version 16.0.3.0.1 -#### UPDT +#### Version 18.0.1.0.1 +##### UPDT -A new contact record is created upon form submission. + +#### 13.05.2025 +#### Version 18.0.1.0.2 +##### UPDT +-A confirmation email will be sent to the customer upon ticket creation. + + + + + + + + diff --git a/odoo_website_helpdesk/models/__init__.py b/odoo_website_helpdesk/models/__init__.py index 8e55983aa..ed5cef70b 100644 --- a/odoo_website_helpdesk/models/__init__.py +++ b/odoo_website_helpdesk/models/__init__.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- -############################################################################# +################################################################################ # # Cybrosys Technologies Pvt. Ltd. # -# Copyright (C) 2023-TODAY Cybrosys Technologies() -# Author: Cybrosys Techno Solutions() +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Bhagyadev KP () # # You can modify it under the terms of the GNU LESSER # GENERAL PUBLIC LICENSE (LGPL v3), Version 3. @@ -18,17 +18,17 @@ # (LGPL v3) along with this program. # If not, see . # -############################################################################# +################################################################################ from . import account_move -from . import help_team -from . import help_ticket -from . import helpdesk_categories +from . import helpdesk_category from . import helpdesk_tag -from . import helpdesk_types +from . import helpdesk_type from . import mail_compose_message -from . import merge_tickets +from . import merge_ticket from . import project_task from . import res_config_settings -from . import support_tickets +from . import support_ticket +from . import team_helpdesk +from . import ticket_helpdesk from . import ticket_stage from . import website_menu diff --git a/odoo_website_helpdesk/models/account_move.py b/odoo_website_helpdesk/models/account_move.py index 0e7b24da0..bb22cd759 100644 --- a/odoo_website_helpdesk/models/account_move.py +++ b/odoo_website_helpdesk/models/account_move.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- -############################################################################# +################################################################################ # # Cybrosys Technologies Pvt. Ltd. # -# Copyright (C) 2023-TODAY Cybrosys Technologies() -# Author: Cybrosys Techno Solutions() +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Bhagyadev KP () # # You can modify it under the terms of the GNU LESSER # GENERAL PUBLIC LICENSE (LGPL v3), Version 3. @@ -18,14 +18,13 @@ # (LGPL v3) along with this program. # If not, see . # -############################################################################# +################################################################################ from odoo import fields, models class AccountMove(models.Model): - """ This class extends the functionality of the 'account.move' model to - include a reference to a help ticket through the 'ticket_id' field.""" + """Inheriting the account.move model""" _inherit = 'account.move' - ticket_id = fields.Many2one('help.ticket', string='Ticket', - help='Choose the tickets') + ticket_id = fields.Many2one('ticket.helpdesk', + string='Ticket', help='ID of the ticket.') diff --git a/odoo_website_helpdesk/models/help_team.py b/odoo_website_helpdesk/models/help_team.py deleted file mode 100644 index d4839a50a..000000000 --- a/odoo_website_helpdesk/models/help_team.py +++ /dev/null @@ -1,65 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################# -# -# Cybrosys Technologies Pvt. Ltd. -# -# Copyright (C) 2023-TODAY Cybrosys Technologies() -# Author: Cybrosys Techno Solutions() -# -# 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 . -# -############################################################################# -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)]}} diff --git a/odoo_website_helpdesk/models/help_ticket.py b/odoo_website_helpdesk/models/help_ticket.py deleted file mode 100644 index eccdd8fb6..000000000 --- a/odoo_website_helpdesk/models/help_ticket.py +++ /dev/null @@ -1,465 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################# -# -# Cybrosys Technologies Pvt. Ltd. -# -# Copyright (C) 2023-TODAY Cybrosys Technologies() -# Author: Cybrosys Techno Solutions() -# -# 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 . -# -############################################################################# -import logging -from odoo import api, fields, models, _ -from odoo.exceptions import UserError -from odoo.exceptions import ValidationError - -_logger = logging.getLogger(__name__) - -PRIORITIES = [ - ('0', 'Very Low'), - ('1', 'Low'), - ('2', 'Normal'), - ('3', 'High'), - ('4', 'Very High'), -] -RATING = [ - ('0', 'Very Low'), - ('1', 'Low'), - ('2', 'Normal'), - ('3', 'High'), - ('4', 'Very High'), - ('5', 'Extreme High') -] - - -class HelpTicket(models.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' - _description = 'Help Ticket' - _inherit = ['mail.thread', 'mail.activity.mixin'] - - name = fields.Char(string='Name', default=lambda self: _('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', - string='Customer Name', - help='Select the Customer Name') - customer_name = fields.Char(string='Customer Name', - help='Add the Customer Name') - subject = fields.Text(string='Subject', required=True, - help='Subject of the Ticket') - description = fields.Text(string='Description', required=True, - help='Issue Description') - email = fields.Char(string='Email', help='Email of the User.') - phone = fields.Char(string='Phone', help='Phone Number of the user') - team_id = fields.Many2one('help.team', string='Helpdesk Team', - help='The helpdesk team responsible for ' - 'handling requests related to this ' - 'record') - 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', - string='Project', - readonly=False, - related='team_id.project_id', - store=True, - help='The project associated with this team.' - 'This field is automatically filled ' - 'based on the project assigned to ' - 'the team.') - priority = fields.Selection(PRIORITIES, - default='1', - help='Set the priority level', - string='Priority') - stage_id = fields.Many2one('ticket.stage', string='Stage', - default=lambda self: self.env[ - 'ticket.stage'].search( - [('name', '=', 'Draft')], limit=1).id, - tracking=True, - group_expand='_read_group_stage_ids', - help='Stages of the ticket.') - user_id = fields.Many2one('res.users', - default=lambda self: self.env.user, - check_company=True, - index=True, tracking=True, - help='Login User') - 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', - string='Service Product', - help='The product associated with this' - 'service. Only service products ' - 'are available for selection.', - domain=[ - ('detailed_type', '=', 'service')]) - create_date = fields.Datetime(string='Creation Date', help='Created date of' - 'the Ticket') - 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') - invoice_ids = fields.Many2many('account.move', - string='Invoices', - help='To Generate Invoice based on hours ' - 'spent on the ticket' - ) - task_ids = fields.Many2many('project.task', - string='Tasks', - help='Related Task of the Ticket') - color = fields.Integer(string="Color", help='Color') - replied_date = fields.Datetime(string='Replied date', - help='Replied Date of the Ticket') - last_update_date = fields.Datetime(string='Last Update Date', - help='Last Update Date of Ticket') - ticket_type = fields.Many2one('helpdesk.types', - string='Ticket Type', help='Ticket Type') - team_head = fields.Many2one('res.users', string='Team Leader', - compute='_compute_team_head', - help='Team Leader Name') - assigned_user = fields.Many2one( - 'res.users', - string='Assigned User', - domain=lambda self: [('groups_id', 'in', self.env.ref( - 'odoo_website_helpdesk.helpdesk_user').id)], - help='Choose the Assigned User Name') - category_id = fields.Many2one('helpdesk.categories', - help='Choose the Category', string='Category') - tags = fields.Many2many('helpdesk.tag', help='Choose the Tags', - string='Tag') - assign_user = fields.Boolean(string='Assigned User', help='Assign User') - attachment_ids = fields.One2many('ir.attachment', - 'res_id', - help='Attachment Line', - string='Attachment') - merge_ticket_invisible = fields.Boolean(string='Merge Ticket', - help='Merge Ticket Invisible or ' - 'Not') - merge_count = fields.Integer(string='Merge Count', help='Merged Tickets ' - 'Count') - - @api.onchange('team_id', 'team_head') - def team_leader_domain(self): - """Update the domain for the assigned user based on the selected team. - - 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: - teams.append(rec.id) - return {'domain': {'assigned_user': [('id', 'in', teams)]}} - - @api.depends('team_id') - def _compute_team_head(self): - """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 - - @api.onchange('stage_id') - def mail_snd(self): - """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 - data = self.env['help.ticket'].search([('id', '=', rec_id)]) - data.last_update_date = fields.Datetime.now() - if self.stage_id.starting_stage: - data.start_date = fields.Datetime.now() - if self.stage_id.closing_stage or self.stage_id.cancel_stage: - data.end_date = fields.Datetime.now() - if self.stage_id.template_id: - mail_template = self.stage_id.template_id - mail_template.send_mail(self._origin.id, force_send=True) - - def assign_to_teamleader(self): - """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: - self.team_head = self.team_id.team_lead_id.id - mail_template = self.env.ref( - 'odoo_website_helpdesk.' - 'mail_template_odoo_website_helpdesk_assign') - mail_template.sudo().write({ - 'email_to': self.team_head.email, - 'subject': self.name - }) - mail_template.sudo().send_mail(self.id, force_send=True) - else: - raise ValidationError("Please choose a Helpdesk Team") - - def _default_show_create_task(self): - """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( - 'odoo_website_helpdesk.show_create_task') - - show_create_task = fields.Boolean(string="Create Task", - default=_default_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, - related='team_id.create_task', - 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): - """Its display the default category""" - return self.env['ir.config_parameter'].sudo().get_param( - 'odoo_website_helpdesk.show_category') - - show_category = fields.Boolean(default=_default_show_category, - compute='_compute_show_category', - help='Display the default category') - customer_rating = fields.Selection(RATING, default='0', 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([ - ('normal', 'Ready'), - ('done', 'In Progress'), - ('blocked', 'Blocked'), ], default='normal') - - def _compute_show_category(self): - """Compute show category""" - show_category = self._default_show_category() - for rec in self: - rec.show_category = show_category - - def _compute_show_create_task(self): - """Compute the value of the 'show_create_task' field for each record in - the current recordset.""" - show_create_task = self._default_show_create_task() - for record in self: - record.show_create_task = show_create_task - - def auto_close_ticket(self): - """Automatically closing the ticket based on the closing date.""" - auto_close = self.env['ir.config_parameter'].sudo().get_param( - 'odoo_website_helpdesk.auto_close_ticket') - if auto_close: - no_of_days = self.env['ir.config_parameter'].sudo().get_param( - 'odoo_website_helpdesk.no_of_days') - records = self.env['help.ticket'].search([]) - for rec in records: - days = (fields.Datetime.today() - rec.create_date).days - if days >= int(no_of_days): - close_stage_id = self.env['ticket.stage'].search( - [('closing_stage', '=', True)]) - if close_stage_id: - rec.stage_id = close_stage_id - - def default_stage_id(self): - """Search your stage""" - return self.env['ticket.stage'].search( - [('name', '=', 'Draft')], limit=1).id - - @api.model - def _read_group_stage_ids(self, stages, domain, order): - """ - Return the 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([]) - return stage_ids - - @api.model - def create(self, vals_list): - """Create a new helpdesk ticket. - This method is called when creating a new helpdesk ticket. It - generates a unique name for the ticket using a sequence if no - name is provided. - """ - if vals_list.get('name', _('New')) == _('New'): - vals_list['name'] = self.env['ir.sequence'].next_by_code( - 'help.ticket') or _('New') - return super().create(vals_list) - - 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( - [('project_id', '=', self.project_id.id), - ('ticket_id', '=', self.id)]).filtered( - lambda line: line.ticket_billed == True) - if not tasks: - raise UserError('No Tasks to Bill') - total = sum(x.effective_hours for x in tasks if x.effective_hours > 0) - invoice_no = self.env['ir.sequence'].next_by_code( - 'ticket.invoice') - self.env['account.move'].create([ - { - 'name': invoice_no, - 'move_type': 'out_invoice', - 'partner_id': self.customer_id.id, - 'ticket_id': self.id, - 'date': fields.Date.today(), - 'invoice_date': fields.Date.today(), - 'invoice_line_ids': - [(0, 0, {'product_id': self.service_product_id.id, - 'name': self.service_product_id.name, - 'quantity': total, - 'product_uom_id': self.service_product_id.uom_id.id, - 'price_unit': self.cost, - 'account_id': - self.service_product_id.categ_id.property_account_income_categ_id.id, - })], - }, ]) - for task in tasks: - task.ticket_billed = True - return { - 'effect': { - 'fadeout': 'medium', - 'message': 'Billed Successfully!', - 'type': 'rainbow_man', - } - } - - def action_create_tasks(self): - """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({ - 'name': self.name + '-' + self.subject, - 'project_id': self.project_id.id, - 'company_id': self.env.company.id, - 'ticket_id': self.id, - }) - self.write({ - 'task_ids': [(4, task_id.id)] - }) - return { - 'name': 'Tasks', - 'res_model': 'project.task', - 'view_id': False, - 'res_id': task_id.id, - 'view_mode': 'form', - 'type': 'ir.actions.act_window', - 'target': 'new', - } - - def action_open_tasks(self): - """Smart Button of Task to view the Tasks of HelpDesk Ticket""" - return { - 'name': 'Tasks', - 'domain': [('ticket_id', '=', self.id)], - 'res_model': 'project.task', - 'view_id': False, - 'view_mode': 'tree,form', - 'type': 'ir.actions.act_window', - } - - def action_open_invoices(self): - """Smart Button of Invoice to view the Invoices for HelpDesk Ticket""" - return { - 'name': 'Invoice', - 'domain': [('ticket_id', '=', self.id)], - 'res_model': 'account.move', - 'view_id': False, - 'view_mode': 'tree,form', - 'type': 'ir.actions.act_window', - } - - def action_open_merged_tickets(self): - """ Smart button of the merged tickets""" - ticket_ids = self.env['support.tickets'].search( - [('merged_ticket', '=', self.id)]) - # Get the display_name matching records from the support.tickets - helpdesk_ticket_ids = ticket_ids.mapped('display_name') - # Get the IDs of the help.ticket records matching the display names - help_ticket_records = self.env['help.ticket'].search( - [('name', 'in', helpdesk_ticket_ids)]) - return { - 'type': 'ir.actions.act_window', - 'name': 'Helpdesk Ticket', - 'view_mode': 'tree,form', - 'res_model': 'help.ticket', - 'domain': [('id', 'in', help_ticket_records.ids)], - 'context': self.env.context, - } - - def action_send_reply(self): - """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( - 'odoo_website_helpdesk.reply_template_id' - ) - template_id = self.env['mail.template'].browse(int(template_id)) - if template_id: - return { - 'type': 'ir.actions.act_window', - 'name': 'mail', - 'res_model': 'mail.compose.message', - 'view_mode': 'form', - 'target': 'new', - 'views': [[False, 'form']], - 'context': { - 'default_model': 'help.ticket', - 'default_res_id': self.id, - 'default_template_id': template_id.id - } - } - return { - 'type': 'ir.actions.act_window', - 'name': 'mail', - 'res_model': 'mail.compose.message', - 'view_mode': 'form', - 'target': 'new', - 'views': [[False, 'form']], - 'context': { - 'default_model': 'help.ticket', - 'default_res_id': self.id, - } - } diff --git a/odoo_website_helpdesk/models/helpdesk_categories.py b/odoo_website_helpdesk/models/helpdesk_category.py similarity index 56% rename from odoo_website_helpdesk/models/helpdesk_categories.py rename to odoo_website_helpdesk/models/helpdesk_category.py index f9b553d63..30d314ebe 100644 --- a/odoo_website_helpdesk/models/helpdesk_categories.py +++ b/odoo_website_helpdesk/models/helpdesk_category.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- -############################################################################# +################################################################################ # # Cybrosys Technologies Pvt. Ltd. # -# Copyright (C) 2023-TODAY Cybrosys Technologies() -# Author: Cybrosys Techno Solutions() +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Bhagyadev KP () # # You can modify it under the terms of the GNU LESSER # GENERAL PUBLIC LICENSE (LGPL v3), Version 3. @@ -18,17 +18,15 @@ # (LGPL v3) along with this program. # If not, see . # -############################################################################# +################################################################################ 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' +class HelpdeskCategory(models.Model): + """Category Model""" + _name = 'helpdesk.category' + _description = 'Categories' - name = fields.Char(string='Name', help='Category Name') - sequence = fields.Integer(string='Sequence', default=0, - help='Sequence of a Category') + name = fields.Char('Name', help='Category name of the helpdesk') + sequence = fields.Integer('Sequence', default=0, + help='Sequence of the helpdesk category') diff --git a/odoo_website_helpdesk/models/helpdesk_tag.py b/odoo_website_helpdesk/models/helpdesk_tag.py index 5dc59c085..4252223f6 100644 --- a/odoo_website_helpdesk/models/helpdesk_tag.py +++ b/odoo_website_helpdesk/models/helpdesk_tag.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- -############################################################################# +################################################################################ # # Cybrosys Technologies Pvt. Ltd. # -# Copyright (C) 2023-TODAY Cybrosys Technologies() -# Author: Cybrosys Techno Solutions() +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Bhagyadev KP () # # You can modify it under the terms of the GNU LESSER # GENERAL PUBLIC LICENSE (LGPL v3), Version 3. @@ -18,13 +18,13 @@ # (LGPL v3) along with this program. # If not, see . # -############################################################################# +################################################################################ from odoo import fields, models class HelpdeskTag(models.Model): - """ Its handle to control the helpdesk ticket tags""" + """Helpdesk tags""" _name = 'helpdesk.tag' - _description = 'Helpdesk Tag' + _description = 'Helpdesk Tags' - name = fields.Char(string='Tag', help='Choose the tags') + name = fields.Char(string='Tag', help='Tag name of the helpdesk.') diff --git a/odoo_website_helpdesk/models/helpdesk_types.py b/odoo_website_helpdesk/models/helpdesk_type.py similarity index 67% rename from odoo_website_helpdesk/models/helpdesk_types.py rename to odoo_website_helpdesk/models/helpdesk_type.py index be3205d71..f42fc2039 100644 --- a/odoo_website_helpdesk/models/helpdesk_types.py +++ b/odoo_website_helpdesk/models/helpdesk_type.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- -############################################################################# +################################################################################ # # Cybrosys Technologies Pvt. Ltd. # -# Copyright (C) 2023-TODAY Cybrosys Technologies() -# Author: Cybrosys Techno Solutions() +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Bhagyadev KP () # # You can modify it under the terms of the GNU LESSER # GENERAL PUBLIC LICENSE (LGPL v3), Version 3. @@ -18,13 +18,13 @@ # (LGPL v3) along with this program. # If not, see . # -############################################################################# +################################################################################ from odoo import fields, models -class HelpdeskTypes(models.Model): - """Its handle to control helpdesk ticket types """ - _name = 'helpdesk.types' - _description = 'Helpdesk Types' +class HelpdeskType(models.Model): + """Helpdesk type """ + _name = 'helpdesk.type' + _description = 'Helpdesk Type' - name = fields.Char(string='Type', help='Types helpdesk tickets') + name = fields.Char(string='Type', help='Types of help desk.') diff --git a/odoo_website_helpdesk/models/mail_compose_message.py b/odoo_website_helpdesk/models/mail_compose_message.py index de16c4861..7159622e1 100644 --- a/odoo_website_helpdesk/models/mail_compose_message.py +++ b/odoo_website_helpdesk/models/mail_compose_message.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- -############################################################################# +################################################################################ # # Cybrosys Technologies Pvt. Ltd. # -# Copyright (C) 2023-TODAY Cybrosys Technologies() -# Author: Cybrosys Techno Solutions() +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Bhagyadev KP () # # You can modify it under the terms of the GNU LESSER # GENERAL PUBLIC LICENSE (LGPL v3), Version 3. @@ -18,25 +18,25 @@ # (LGPL v3) along with this program. # If not, see . # -############################################################################# +################################################################################ from odoo import fields, models class MailComposeMessage(models.TransientModel): - """ This class extends the functionality of the 'mail.compose.message' - model to include custom behavior for sending emails related to help tickets. - """ + """Inheriting the Mail compose message""" _inherit = 'mail.compose.message' def _action_send_mail(self, auto_commit=False): - """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': - ticket_id = self.env['help.ticket'].browse(self.res_id) - ticket_id.replied_date = fields.Date.today() + """Send mail function""" + if self.model == 'ticket.helpdesk': + try: + res_ids_list = eval(self.res_ids) + if not isinstance(res_ids_list, list): + raise ValueError("Invalid format for res_ids") + except Exception as e: + raise ValueError( + "Error converting res_ids to list: {}".format(e)) + ticket_ids = self.env['ticket.helpdesk'].browse(res_ids_list) + ticket_ids.replied_date = fields.Date.today() return super(MailComposeMessage, self)._action_send_mail( auto_commit=auto_commit) diff --git a/odoo_website_helpdesk/models/merge_tickets.py b/odoo_website_helpdesk/models/merge_ticket.py similarity index 68% rename from odoo_website_helpdesk/models/merge_tickets.py rename to odoo_website_helpdesk/models/merge_ticket.py index 4c9afb47c..ff37be365 100644 --- a/odoo_website_helpdesk/models/merge_tickets.py +++ b/odoo_website_helpdesk/models/merge_ticket.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- -############################################################################# +################################################################################ # # Cybrosys Technologies Pvt. Ltd. # -# Copyright (C) 2023-TODAY Cybrosys Technologies() -# Author: Cybrosys Techno Solutions() +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Bhagyadev KP () # # You can modify it under the terms of the GNU LESSER # GENERAL PUBLIC LICENSE (LGPL v3), Version 3. @@ -18,64 +18,60 @@ # (LGPL v3) along with this program. # If not, see . # -############################################################################# +################################################################################ from odoo import api, fields, models -class MergeTickets(models.Model): - """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' - _description = 'Merge Tickets' +class MergeTicket(models.Model): + """Tickets merging class""" + _name = 'merge.ticket' + _description = 'Merging the selected tickets' _rec_name = 'support_ticket_id' user_id = fields.Many2one('res.partner', string='Responsible User', - help='Responsible user name', + help='User name of responsible person.', default=lambda self: self.env.user.partner_id.id) - support_team_id = fields.Many2one('help.team', + support_team_id = fields.Many2one('team.helpdesk', string='Support Team', - help='Support Team Name') - customer_id = fields.Many2one('res.partner', - string='Customer', - help='Customer Name' - ) - support_ticket_id = fields.Many2one('help.ticket', - string='Support Ticket') + help='Name of the support team.') + customer_id = fields.Many2one('res.partner', string='Customer', + help='Name of the Customer ') + support_ticket_id = fields.Many2one('ticket.helpdesk', + string='Support Ticket', + help="Name of the support ticket") new_ticket = fields.Boolean(string='Create New Ticket ?', help='Creating new tickets or not.', - ) + default=False) subject = fields.Char(string='Subject', help='Enter the New Ticket Subject') - merge_reason = fields.Char(string='Merge Reason', help='Merging Reason') - support_ticket_ids = fields.One2many('support.tickets', + merge_reason = fields.Char(string='Merge Reason', + help='Reason for Merging the tickets. ') + support_ticket_ids = fields.One2many('support.ticket', 'support_ticket_id', string='Support Tickets', - helps='Merged tickets') - active = fields.Boolean(string='Disable Record', help='Disable Record') + help='Merged tickets') + active = fields.Boolean(string='Disable Record', help='Disable Record', + default=True) def default_get(self, fields_list): - """It handles to get the default pre-filled the values """ - defaults = super().default_get(fields_list) + """Override the default_get method to provide default values for fields + when creating a new record.""" + defaults = super(MergeTicket, self).default_get(fields_list) active_ids = self._context.get('active_ids', []) - selected_tickets = self.env['help.ticket'].browse(active_ids) + selected_tickets = self.env['ticket.helpdesk'].browse(active_ids) customer_ids = selected_tickets.mapped('customer_id') subjects = selected_tickets.mapped('subject') display_names = selected_tickets.mapped('display_name') helpdesk_team = selected_tickets.mapped('team_id') descriptions = selected_tickets.mapped('description') - # Ensure both selected records have the same customer if len(customer_ids): defaults.update({ 'customer_id': customer_ids[0].id, 'support_team_id': helpdesk_team, - 'support_ticket_ids': [(0, 0, { 'subject': subject, 'display_name': display_name, 'description': description, - }) for subject, display_name, description in zip(subjects, display_names, descriptions)] @@ -86,11 +82,10 @@ class MergeTickets(models.Model): """Merging the tickets or creating new tickets""" if self.new_ticket: description = "\n\n".join( - f"{ticket.subject}\n{'-' * len(ticket.subject)}\n" - f"{ticket.description}" + f"{ticket.subject}\n{'-' * len(ticket.subject)}\n{ticket.description}" for ticket in self.support_ticket_ids ) - self.env['help.ticket'].create({ + self.env['ticket.helpdesk'].create({ 'subject': self.subject, 'description': description, 'customer_id': self.customer_id.id, @@ -99,12 +94,9 @@ class MergeTickets(models.Model): else: if len(self.support_ticket_ids): description = "\n\n".join( - f"{ticket.subject}\n{'-' * len(ticket.subject)}\n" - f"{ticket.description}" + f"{ticket.subject}\n{'-' * len(ticket.subject)}\n{ticket.description}" for ticket in self.support_ticket_ids ) - # Update the existing support_ticket with the combined - # Information self.support_ticket_id.write({ 'description': description, 'merge_ticket_invisible': True, diff --git a/odoo_website_helpdesk/models/project_task.py b/odoo_website_helpdesk/models/project_task.py index 38e3c4d23..a626abcd6 100644 --- a/odoo_website_helpdesk/models/project_task.py +++ b/odoo_website_helpdesk/models/project_task.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- -############################################################################# +################################################################################ # # Cybrosys Technologies Pvt. Ltd. # -# Copyright (C) 2023-TODAY Cybrosys Technologies() -# Author: Cybrosys Techno Solutions() +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Bhagyadev KP () # # You can modify it under the terms of the GNU LESSER # GENERAL PUBLIC LICENSE (LGPL v3), Version 3. @@ -18,25 +18,15 @@ # (LGPL v3) along with this program. # If not, see . # -############################################################################# +################################################################################ 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 - """ + """Inheriting the project task""" _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.') + ticket_id = fields.Many2one('ticket.helpdesk', string='Ticket', + help='ID of the ticket .') + ticket_billed = fields.Boolean('Billed', default=False, + help='Billed Tickets') diff --git a/odoo_website_helpdesk/models/res_config_settings.py b/odoo_website_helpdesk/models/res_config_settings.py index 0d30e44f4..d3262529f 100644 --- a/odoo_website_helpdesk/models/res_config_settings.py +++ b/odoo_website_helpdesk/models/res_config_settings.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- -############################################################################# +################################################################################ # # Cybrosys Technologies Pvt. Ltd. # -# Copyright (C) 2023-TODAY Cybrosys Technologies() -# Author: Cybrosys Techno Solutions() +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Bhagyadev KP () # # You can modify it under the terms of the GNU LESSER # GENERAL PUBLIC LICENSE (LGPL v3), Version 3. @@ -18,74 +18,68 @@ # (LGPL v3) along with this program. # If not, see . # -############################################################################# +################################################################################ 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. - """ + """Inheriting the res config settings model""" _inherit = 'res.config.settings' - show_create_task = fields.Boolean( - string="Create Tasks", - config_parameter='odoo_website_helpdesk.show_create_task', - help='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( + show_create_task = fields.Boolean(string="Create Tasks", + config_parameter='odoo_website_helpdesk.show_create_task', + help='Enable this option to allow users' + 'to create tasks directly from the ' + 'helpdesk module. When activated, users ' + 'will have the ability to generate and ' + 'assign tasks as part of their workflow ' + 'within the helpdesk interface.') + show_category = fields.Boolean(string="Category", + config_parameter='odoo_website_helpdesk.show_category', + help='Enable this option to display the ' + 'category field in the helpdesk tickets. ' + 'This can be useful for organizing and ' + 'filtering tickets based on their category.', + implied_group='odoo_website_helpdesk.group_show_category') + product_website = fields.Boolean(string="Product On Website", + config_parameter='odoo_website_helpdesk.product_website', + help='Product on website') + auto_close_ticket = fields.Boolean(string="Auto Close Ticket", + config_parameter='odoo_website_helpdesk.auto_close_ticket', + help='Auto Close ticket') + no_of_days = fields.Integer(string="No Of Days", + config_parameter='odoo_website_helpdesk.no_of_days', + help='No of Days') + closed_stage_id = fields.Many2one( 'ticket.stage', string='Closing stage', - help='Closing Stage', - config_parameter='odoo_website_helpdesk.closed_stage') + help='Closing Stage of the ticket.', + config_parameter='odoo_website_helpdesk.closed_stage_id') - 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') + reply_template_id = fields.Many2one('mail.template', + domain="[('model', '=', 'ticket.helpdesk')]", + config_parameter='odoo_website_helpdesk.reply_template_id', + help='Reply Template of the helpdesk' + ' ticket.') + helpdesk_menu_show = fields.Boolean('Helpdesk Menu', + config_parameter= + 'odoo_website_helpdesk.helpdesk_menu_show', + help='Helpdesk menu') - @api.onchange('closed_stage') - 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.onchange('closed_stage_id') + def _onchange_closed_stage_id(self): + """Closing stage function""" + if self.closed_stage_id: + stage = self.closed_stage_id.id + in_stage = self.env['ticket.stage'].search([('id', '=', stage)]) + not_in_stage = self.env['ticket.stage'].search( + [('id', '!=', stage)]) + in_stage.closing_stage = True + for each in not_in_stage: + each.closing_stage = False @api.constrains('show_category') - def 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. - """ + def _constrains_show_category_subcategory(self): + """Show category and the sub category""" if self.show_category: group_cat = self.env.ref( 'odoo_website_helpdesk.group_show_category') diff --git a/odoo_website_helpdesk/models/support_tickets.py b/odoo_website_helpdesk/models/support_ticket.py similarity index 73% rename from odoo_website_helpdesk/models/support_tickets.py rename to odoo_website_helpdesk/models/support_ticket.py index 5d5460b39..296408676 100644 --- a/odoo_website_helpdesk/models/support_tickets.py +++ b/odoo_website_helpdesk/models/support_ticket.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- -############################################################################# +################################################################################ # # Cybrosys Technologies Pvt. Ltd. # -# Copyright (C) 2023-TODAY Cybrosys Technologies() -# Author: Cybrosys Techno Solutions() +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Bhagyadev KP () # # You can modify it under the terms of the GNU LESSER # GENERAL PUBLIC LICENSE (LGPL v3), Version 3. @@ -18,22 +18,22 @@ # (LGPL v3) along with this program. # If not, see . # -############################################################################# +################################################################################ from odoo import fields, models -class SupportTickets(models.Model): - """Creating onetoMany model to handle the merging ticket""" - _name = 'support.tickets' +class SupportTicket(models.Model): + """Creating onetoMany model""" + _name = 'support.ticket' _description = 'Support Tickets' subject = fields.Char(string='Subject', help='Subject of the merged ' - 'tickets') + 'tickets.') display_name = fields.Char(string='Display Name', - help='Display name of the merged tickets') + help='Display name of the merged tickets.') description = fields.Char(string='Description', - help='Description of the tickets') - support_ticket_id = fields.Many2one('merge.tickets', + help='Description of the tickets.') + support_ticket_id = fields.Many2one('merge.ticket', string='Support Tickets', help='Support tickets') merged_ticket = fields.Integer(string='Merged Ticket ID', diff --git a/odoo_website_helpdesk/models/team_helpdesk.py b/odoo_website_helpdesk/models/team_helpdesk.py new file mode 100644 index 000000000..c9ede6880 --- /dev/null +++ b/odoo_website_helpdesk/models/team_helpdesk.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Bhagyadev KP () +# +# 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 . +# +################################################################################ +from odoo import api, fields, models + + +class TeamHelpDesk(models.Model): + """Helpdesk team""" + _name = 'team.helpdesk' + _description = 'Helpdesk Team' + + name = fields.Char('Name', help='Helpdesk Team Name') + team_lead_id = fields.Many2one('res.users', string='Team Leader', + help='Team Leader Name', + domain=lambda self: [ + ('groups_id', 'in', self.env.ref( + 'odoo_website_helpdesk.helpdesk_team_leader').id)]) + member_ids = fields.Many2many('res.users', string='Members', + help='Team Members', + domain=lambda self: [ + ('groups_id', 'in', self.env.ref( + 'odoo_website_helpdesk.helpdesk_user').id)]) + email = fields.Char('Email', help='Email of the team member.') + project_id = fields.Many2one('project.project', + string='Project', + help='Projects related helpdesk team.') + create_task = fields.Boolean(string="Create Task", + help="Task created or not") + + @api.onchange('team_lead_id') + def _onchange_team_lead_id(self): + """Members selection function""" + fetch_members = self.env['res.users'].search([]) + filtered_members = fetch_members.filtered( + lambda x: x.id != self.team_lead_id.id) + return {'domain': {'member_ids': + [('id', '=', filtered_members.ids), ( + 'groups_id', 'in', + self.env.ref('base.group_user').id), + ('groups_id', 'not in', self.env.ref( + 'odoo_website_helpdesk.helpdesk_team_leader').id)]}} diff --git a/odoo_website_helpdesk/models/ticket_helpdesk.py b/odoo_website_helpdesk/models/ticket_helpdesk.py new file mode 100644 index 000000000..c6195b2df --- /dev/null +++ b/odoo_website_helpdesk/models/ticket_helpdesk.py @@ -0,0 +1,387 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Bhagyadev KP () +# +# 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 . +# +################################################################################ +import logging +from odoo import api, fields, models, _ +from odoo.exceptions import UserError +from odoo.exceptions import ValidationError + +_logger = logging.getLogger(__name__) + +PRIORITIES = [ + ('0', 'Very Low'), + ('1', 'Low'), + ('2', 'Normal'), + ('3', 'High'), + ('4', 'Very High'), +] +RATING = [ + ('0', 'Very Low'), + ('1', 'Low'), + ('2', 'Normal'), + ('3', 'High'), + ('4', 'Very High'), + ('5', 'Extreme High') +] + + +class TicketHelpDesk(models.Model): + """Help_ticket model""" + _name = 'ticket.helpdesk' + _description = 'Helpdesk Ticket' + _inherit = ['mail.thread', 'mail.activity.mixin'] + + def _default_show_create_task(self): + """Task creation""" + return self.env['ir.config_parameter'].sudo().get_param( + 'odoo_website_helpdesk.show_create_task') + + def _default_show_category(self): + """Show category default""" + return self.env['ir.config_parameter'].sudo().get_param( + 'odoo_website_helpdesk.show_category') + + name = fields.Char('Name', default=lambda self: self.env['ir.sequence']. + next_by_code('ticket.helpdesk') or _('New'), + help='Ticket Name') + customer_id = fields.Many2one('res.partner', + string='Customer Name', + help='Customer Name') + customer_name = fields.Char('Customer Name', help='Customer Name') + subject = fields.Text('Subject', required=True, + help='Subject of the Ticket') + description = fields.Text('Description', required=True, + help='Description') + email = fields.Char('Email', help='Email') + phone = fields.Char('Phone', help='Contact Number') + team_id = fields.Many2one('team.helpdesk', string='Helpdesk Team', + help='Helpdesk Team Name') + product_ids = fields.Many2many('product.template', + string='Product', + help='Product Name') + project_id = fields.Many2one('project.project', + string='Project', + readonly=False, + related='team_id.project_id', + store=True, + help='Project Name') + priority = fields.Selection(PRIORITIES, default='1', help='Priority of the' + ' Ticket') + stage_id = fields.Many2one('ticket.stage', string='Stage', + tracking=True, + group_expand='_read_group_stage_ids', + help='Stages') + user_id = fields.Many2one('res.users', + default=lambda self: self.env.user, + check_company=True, + index=True, tracking=True, + help='Login User', string='User') + cost = fields.Float('Cost per hour', help='Cost Per Unit') + service_product_id = fields.Many2one('product.product', + string='Service Product', + help='Service Product', + domain=[ + ('type', '=', 'service')]) + create_date = fields.Datetime('Creation Date', help='Created date') + start_date = fields.Datetime('Start Date', help='Start Date') + end_date = fields.Datetime('End Date', help='End Date') + public_ticket = fields.Boolean(string="Public Ticket", + help='Public Ticket') + invoice_ids = fields.Many2many('account.move', + string='Invoices', + help='Invoicing id' + ) + task_ids = fields.Many2many('project.task', + string='Tasks', + help='Task id') + color = fields.Integer(string="Color", help='Color') + replied_date = fields.Datetime('Replied date', help='Replied Date') + last_update_date = fields.Datetime('Last Update Date', + help='Last Update Date') + ticket_type_id = fields.Many2one('helpdesk.type', + string='Ticket Type', help='Ticket Type') + team_head_id = fields.Many2one('res.users', string='Team Leader', + compute='_compute_team_head_id', + help='Team Leader Name') + assigned_user_id = fields.Many2one('res.users', string='Assigned User', + domain=lambda self: [('groups_id', 'in', + self.env.ref( + 'odoo_website_helpdesk.helpdesk_user').id)], + help='Assigned User Name') + category_id = fields.Many2one('helpdesk.category', string='Category', + help='Category') + tags_ids = fields.Many2many('helpdesk.tag', help='Tags', string='Tags') + assign_user = fields.Boolean(default=False, help='Assign User', + string='Assign User') + attachment_ids = fields.One2many('ir.attachment', 'res_id', + help='Attachment Line', + string='Attachments') + merge_ticket_invisible = fields.Boolean(string='Merge Ticket', + help='Merge Ticket Invisible or ' + 'Not', default=False) + merge_count = fields.Integer(string='Merge Count', help='Merged Tickets ' + 'Count') + active = fields.Boolean(default=True, help='Active', string='Active') + + show_create_task = fields.Boolean(string="Show Create Task", + help='Show created task or not', + default=_default_show_create_task, + compute='_compute_show_create_task') + create_task = fields.Boolean(string="Create Task", readonly=False, + help='Create task or not', + related='team_id.create_task', store=True) + billable = fields.Boolean(string="Billable", default=False, + help='Is billable or not', ) + show_category = fields.Boolean(default=_default_show_category, + string="Show Category", + help='Show category or not', + compute='_compute_show_category') + customer_rating = fields.Selection(RATING, default='0', readonly=True) + review = fields.Char('Review', readonly=True, help='Ticket review') + kanban_state = fields.Selection([ + ('normal', 'Ready'), + ('done', 'In Progress'), + ('blocked', 'Blocked'), ], default='normal') + + @api.onchange('team_id', 'team_head_id') + def _onchange_team_id(self): + """Changing the team leader when selecting the team""" + li = self.team_id.member_ids.mapped(id) + return {'domain': {'assigned_user_id': [('id', 'in', li)]}} + + @api.depends('team_id') + def _compute_team_head_id(self): + """Compute the team head function""" + self.team_head_id = self.team_id.team_lead_id.id + + @api.onchange('stage_id') + def _onchange_stage_id(self): + """Sending mail to the user function""" + rec_id = self._origin.id + data = self.env['ticket.helpdesk'].search([('id', '=', rec_id)]) + data.last_update_date = fields.Datetime.now() + if self.stage_id.starting_stage: + data.start_date = fields.Datetime.now() + if self.stage_id.closing_stage or self.stage_id.cancel_stage: + data.end_date = fields.Datetime.now() + if self.stage_id.template_id: + mail_template = self.stage_id.template_id + mail_template.send_mail(self._origin.id, force_send=True) + + def assign_to_teamleader(self): + """Assigning team leader function""" + if self.team_id: + self.team_head_id = self.team_id.team_lead_id.id + mail_template = self.env.ref( + 'odoo_website_helpdesk.odoo_website_helpdesk_assign') + mail_template.sudo().write({ + 'email_to': self.team_head_id.email, + 'subject': self.name + }) + mail_template.sudo().send_mail(self.id, force_send=True) + else: + raise ValidationError("Please choose a Helpdesk Team") + + def _compute_show_category(self): + """Compute show category""" + show_category = self._default_show_category() + for rec in self: + rec.show_category = show_category + + def _compute_show_create_task(self): + """Compute the created task""" + show_create_task = self._default_show_create_task() + for record in self: + record.show_create_task = show_create_task + + def auto_close_ticket(self): + """Automatically closing the ticket""" + auto_close = self.env['ir.config_parameter'].sudo().get_param( + 'odoo_website_helpdesk.auto_close_ticket') + if auto_close: + no_of_days = self.env['ir.config_parameter'].sudo().get_param( + 'odoo_website_helpdesk.no_of_days') + records = self.env['ticket.helpdesk'].search([]) + for rec in records: + days = (fields.Datetime.today() - rec.create_date).days + if days >= int(no_of_days): + close_stage_id = self.env['ticket.stage'].search( + [('closing_stage', '=', True)]) + if close_stage_id: + rec.stage_id = close_stage_id + + def default_stage_id(self): + """Method to return the default stage""" + return self.env['ticket.stage'].search( + [('name', '=', 'Draft')], limit=1).id + + def _read_group_stage_ids(self, stages, domain): + """ + return the stages to stage_ids + """ + stage_ids = self.env['ticket.stage'].search([]) + return stage_ids + + @api.model_create_multi + def create(self, vals_list): + """Create function""" + for vals in vals_list: + if vals.get('name', _('New')) == _('New'): + vals['name'] = self.env['ir.sequence'].next_by_code( + 'ticket.helpdesk') + return super(TicketHelpDesk, self).create(vals_list) + + def write(self, vals): + """Write function""" + result = super(TicketHelpDesk, self).write(vals) + return result + + def action_create_invoice(self): + """Create Invoice based on the ticket""" + tasks = self.env['project.task'].search( + [('project_id', '=', self.project_id.id), + ('ticket_id', '=', self.id)]).filtered( + lambda line: not line.ticket_billed) + if not tasks: + raise UserError('No Tasks to Bill') + total = sum(x.effective_hours for x in tasks if + x.effective_hours > 0 and not x.some_flag) + invoice_no = self.env['ir.sequence'].next_by_code( + 'ticket.invoice') + self.env['account.move'].create([ + { + 'name': invoice_no, + 'move_type': 'out_invoice', + 'partner_id': self.customer_id.id, + 'ticket_id': self.id, + 'date': fields.Date.today(), + 'invoice_date': fields.Date.today(), + 'invoice_line_ids': [(0, 0, + { + 'product_id': self.service_product_id.id, + 'name': self.service_product_id.name, + 'quantity': total, + 'product_uom_id': self.service_product_id.uom_id.id, + 'price_unit': self.cost, + 'account_id': self.service_product_id.categ_id.property_account_income_categ_id.id, + })], + }, ]) + for task in tasks: + task.ticket_billed = True + return { + 'effect': { + 'fadeout': 'medium', + 'message': 'Billed Successfully!', + 'type': 'rainbow_man', + } + } + + def action_create_tasks(self): + """Task creation""" + task_id = self.env['project.task'].create({ + 'name': self.name + '-' + self.subject, + 'project_id': self.project_id.id, + 'company_id': self.env.company.id, + 'ticket_id': self.id, + }) + self.write({ + 'task_ids': [(4, task_id.id)] + }) + return { + 'name': 'Tasks', + 'res_model': 'project.task', + 'view_id': False, + 'res_id': task_id.id, + 'view_mode': 'form', + 'type': 'ir.actions.act_window', + 'target': 'new', + } + + def action_open_tasks(self): + """View the Created task """ + return { + 'name': 'Tasks', + 'domain': [('ticket_id', '=', self.id)], + 'res_model': 'project.task', + 'view_id': False, + 'view_mode': 'list,form', + 'type': 'ir.actions.act_window', + } + + def action_open_invoices(self): + """View the Created invoice""" + return { + 'name': 'Invoice', + 'domain': [('ticket_id', '=', self.id)], + 'res_model': 'account.move', + 'view_id': False, + 'view_mode': 'list,form', + 'type': 'ir.actions.act_window', + } + + def action_open_merged_tickets(self): + """Open the merged tickets list view""" + ticket_ids = self.env['support.ticket'].search( + [('merged_ticket', '=', self.id)]) + helpdesk_ticket_ids = ticket_ids.mapped('display_name') + help_ticket_records = self.env['ticket.helpdesk'].search( + [('name', 'in', helpdesk_ticket_ids)]) + return { + 'type': 'ir.actions.act_window', + 'name': 'Helpdesk Ticket', + 'view_mode': 'list,form', + 'res_model': 'ticket.helpdesk', + 'domain': [('id', 'in', help_ticket_records.ids)], + 'context': self.env.context, + } + + def action_send_reply(self): + """Action to sent reply button""" + template_id = self.env['ir.config_parameter'].sudo().get_param( + 'odoo_website_helpdesk.reply_template_id' + ) + template_id = self.env['mail.template'].browse(int(template_id)) + if template_id: + return { + 'type': 'ir.actions.act_window', + 'name': 'mail', + 'res_model': 'mail.compose.message', + 'view_mode': 'form', + 'target': 'new', + 'views': [[False, 'form']], + 'context': { + 'default_model': 'ticket.helpdesk', + 'default_res_ids': self.ids, + 'default_template_id': template_id.id + } + } + return { + 'type': 'ir.actions.act_window', + 'name': 'mail', + 'res_model': 'mail.compose.message', + 'view_mode': 'form', + 'target': 'new', + 'views': [[False, 'form']], + 'context': { + 'default_model': 'ticket.helpdesk', + 'default_res_ids': self.ids, + } + } diff --git a/odoo_website_helpdesk/models/ticket_stage.py b/odoo_website_helpdesk/models/ticket_stage.py index 30545c33b..34c893d4c 100644 --- a/odoo_website_helpdesk/models/ticket_stage.py +++ b/odoo_website_helpdesk/models/ticket_stage.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- -############################################################################# +################################################################################ # # Cybrosys Technologies Pvt. Ltd. # -# Copyright (C) 2023-TODAY Cybrosys Technologies() -# Author: Cybrosys Techno Solutions() +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Bhagyadev KP () # # You can modify it under the terms of the GNU LESSER # GENERAL PUBLIC LICENSE (LGPL v3), Version 3. @@ -18,72 +18,40 @@ # (LGPL v3) along with this program. # If not, see . # -############################################################################# +################################################################################ 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.""" - + """Stage Ticket model """ _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.') + name = fields.Char('Name', help='Name of the ticket stage') + active = fields.Boolean(string='Active', default=True, help='Active option' + 'for ticket ' + 'stage.') + sequence = fields.Integer(string='Sequence', default=50, + help='Sequence number of the ticket stage.') + closing_stage = fields.Boolean('Closing Stage', default=False, + help='Closing stage of the ticket.') + cancel_stage = fields.Boolean('Cancel Stage', default=False, + help='Cancel stage of the ticket.') + starting_stage = fields.Boolean('Start Stage', default=False, + help='Starting Stage of the ticket.') + folded = fields.Boolean('Folded in Kanban', default=False, + help='Folded Stage of the ticket.') template_id = fields.Many2one('mail.template', - 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') + help='Templates', string='Template', + domain="[('model', '=', 'ticket.helpdesk')]") + group_ids = fields.Many2many('res.groups', help='Group', string='Groups') + fold = fields.Boolean(string='Fold', help='Folded option in ticket.') def unlink(self): - """Deleting the helpdesk tickets from various stage.""" + """Unlinking Function to unlink the stage""" for rec in self: tickets = rec.search([]) sequence = tickets.mapped('sequence') diff --git a/odoo_website_helpdesk/models/website_menu.py b/odoo_website_helpdesk/models/website_menu.py index d0b47a395..e6a0906ce 100644 --- a/odoo_website_helpdesk/models/website_menu.py +++ b/odoo_website_helpdesk/models/website_menu.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- -############################################################################# +################################################################################ # # Cybrosys Technologies Pvt. Ltd. # -# Copyright (C) 2023-TODAY Cybrosys Technologies() -# Author: Cybrosys Techno Solutions() +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Bhagyadev KP () # # You can modify it under the terms of the GNU LESSER # GENERAL PUBLIC LICENSE (LGPL v3), Version 3. @@ -18,44 +18,22 @@ # (LGPL v3) along with this program. # If not, see . # -############################################################################# +################################################################################ 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. - """ + """Inheriting the website menu""" _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. - """ + """Compute function for to visible the menu based on the boolean + field visibility""" super()._compute_visible() show_menu_header = self.env['ir.config_parameter'].sudo().get_param( 'odoo_website_helpdesk.helpdesk_menu_show') for menu in self: - if menu.name == 'Helpdesk' and show_menu_header is False: + if menu.name == 'Helpdesk' and not show_menu_header: menu.is_visible = False - if menu.name == 'Helpdesk' and show_menu_header is True: + if menu.name == 'Helpdesk' and show_menu_header: menu.is_visible = True diff --git a/odoo_website_helpdesk/report/help_ticket_templates.xml b/odoo_website_helpdesk/report/help_ticket_templates.xml deleted file mode 100644 index 5d01bd1c4..000000000 --- a/odoo_website_helpdesk/report/help_ticket_templates.xml +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - Helpdesk Ticket Report - help.ticket - qweb-pdf - odoo_website_helpdesk.report_helpdesk_ticket - odoo_website_helpdesk.report_helpdesk_ticket - report - - diff --git a/odoo_website_helpdesk/views/report_templates.xml b/odoo_website_helpdesk/report/helpdesk_ticket_report_template.xml similarity index 83% rename from odoo_website_helpdesk/views/report_templates.xml rename to odoo_website_helpdesk/report/helpdesk_ticket_report_template.xml index c0545b097..7fafdb0b1 100644 --- a/odoo_website_helpdesk/views/report_templates.xml +++ b/odoo_website_helpdesk/report/helpdesk_ticket_report_template.xml @@ -1,7 +1,7 @@ - -