diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 17:14:58 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 17:14:58 +0700 |
| commit | 1ca3b3df3421961caec3b747a364071c80f5c7da (patch) | |
| tree | 6778a1f0f3f9b4c6e26d6d87ccde16e24da6c9d6 /sh_helpdesk/models | |
| parent | b57188be371d36d96caac4b8d65a40745c0e972c (diff) | |
initial commit
Diffstat (limited to 'sh_helpdesk/models')
| -rw-r--r-- | sh_helpdesk/models/__init__.py | 19 | ||||
| -rw-r--r-- | sh_helpdesk/models/helpdesk_alarm.py | 162 | ||||
| -rw-r--r-- | sh_helpdesk/models/helpdesk_category.py | 19 | ||||
| -rw-r--r-- | sh_helpdesk/models/helpdesk_config_settings.py | 109 | ||||
| -rw-r--r-- | sh_helpdesk/models/helpdesk_policies.py | 55 | ||||
| -rw-r--r-- | sh_helpdesk/models/helpdesk_priority.py | 20 | ||||
| -rw-r--r-- | sh_helpdesk/models/helpdesk_so.py | 18 | ||||
| -rw-r--r-- | sh_helpdesk/models/helpdesk_stages.py | 31 | ||||
| -rw-r--r-- | sh_helpdesk/models/helpdesk_subcategory.py | 22 | ||||
| -rw-r--r-- | sh_helpdesk/models/helpdesk_subject_type.py | 12 | ||||
| -rw-r--r-- | sh_helpdesk/models/helpdesk_tags.py | 25 | ||||
| -rw-r--r-- | sh_helpdesk/models/helpdesk_team.py | 45 | ||||
| -rw-r--r-- | sh_helpdesk/models/helpdesk_ticket.py | 1079 | ||||
| -rw-r--r-- | sh_helpdesk/models/helpdesk_ticket_dashboard.py | 21 | ||||
| -rw-r--r-- | sh_helpdesk/models/helpdesk_ticket_type.py | 42 | ||||
| -rw-r--r-- | sh_helpdesk/models/helpdesk_ticket_update_wizard.py | 87 | ||||
| -rw-r--r-- | sh_helpdesk/models/res_users.py | 31 | ||||
| -rw-r--r-- | sh_helpdesk/models/send_mail_quick_reply.py | 18 |
18 files changed, 1815 insertions, 0 deletions
diff --git a/sh_helpdesk/models/__init__.py b/sh_helpdesk/models/__init__.py new file mode 100644 index 0000000..ecf1ad2 --- /dev/null +++ b/sh_helpdesk/models/__init__.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Part of Softhealer Technologies. + +from . import helpdesk_team +from . import helpdesk_ticket_type +from . import helpdesk_subject_type +from . import helpdesk_tags +from . import helpdesk_stages +from . import helpdesk_category +from . import helpdesk_subcategory +from . import helpdesk_priority +from . import helpdesk_policies +from . import helpdesk_config_settings +from . import res_users +from . import helpdesk_ticket +from . import helpdesk_alarm +from . import helpdesk_ticket_dashboard +from . import send_mail_quick_reply +from . import helpdesk_ticket_update_wizard diff --git a/sh_helpdesk/models/helpdesk_alarm.py b/sh_helpdesk/models/helpdesk_alarm.py new file mode 100644 index 0000000..c7231e6 --- /dev/null +++ b/sh_helpdesk/models/helpdesk_alarm.py @@ -0,0 +1,162 @@ +# -*- coding: utf-8 -*- +# Part of Softhealer Technologies. + +from odoo import fields, models, api, _ +from odoo.exceptions import ValidationError +from datetime import timedelta + +class TicketAlarm(models.Model): + _name = "sh.ticket.alarm" + _description = "Ticket Reminder" + + name = fields.Char(string="Name", readonly=True) + type = fields.Selection([('email', 'Email'), ( + 'popup', 'Popup')], string="Type", required=True, default='email') + sh_remind_before = fields.Integer( + string="Reminder Before") + sh_reminder_unit = fields.Selection([('Hour(s)', 'Hour(s)'), ( + 'Minute(s)', 'Minute(s)'), ('Second(s)', 'Second(s)')], string="Reminder Unit", default='Hour(s)',required=True) + company_id = fields.Many2one( + 'res.company', 'Company', default=lambda self: self.env.company) + + @api.constrains('sh_remind_before') + def _check_sh_reminder_unit(self): + if self.filtered(lambda c: c.sh_reminder_unit == 'Minute(s)' and c.sh_remind_before < 5): + raise ValidationError(_("Reminder Before can't set less than 5 Minutes.")) + elif self.filtered(lambda c: c.sh_reminder_unit == 'Second(s)' and c.sh_remind_before < 300): + raise ValidationError(_("Reminder Before can't set less than 300 Seconds.")) + elif self.filtered(lambda c: c.sh_reminder_unit == 'Hour(s)' and c.sh_remind_before < 1): + raise ValidationError(_("Reminder Before can't set less than 1 Hour.")) + + def name_get(self): + # Prefetch the fields used by the `name_get`, so `browse` doesn't fetch other fields + self.browse(self.ids).read(['sh_remind_before', 'sh_reminder_unit','type']) + return [(alarm.id, '%s%s%s' % (str(alarm.sh_remind_before)+' ',str(alarm.sh_reminder_unit)+' ','['+str(alarm.type)+']')) + for alarm in self] + + @api.onchange('sh_remind_before','type','sh_reminder_unit') + def _onchange_name(self): + for rec in self: + rec.name = rec.name_get()[0][1] + + @api.model + def _run_ticket_reminder(self): + if self.env.company.sh_display_ticket_reminder: + alarm_ids = self.env['sh.ticket.alarm'].sudo().search([]) + if alarm_ids: + for alarm in alarm_ids: + ticket_ids = self.env['helpdesk.ticket'].sudo().search([('sh_ticket_alarm_ids','in',[alarm.id])]) + if ticket_ids: + for ticket in ticket_ids: + deadline_date = False + if alarm.sh_reminder_unit == 'Hour(s)' and ticket.sh_due_date: + deadline_date_hours_added = ticket.sh_due_date + timedelta(hours = 5,minutes=30,seconds=0) + deadline_date = deadline_date_hours_added - timedelta(hours = alarm.sh_remind_before) + elif alarm.sh_reminder_unit == 'Minute(s)' and ticket.sh_due_date: + deadline_date_minutes_added = ticket.sh_due_date + timedelta(hours = 5,minutes=30,seconds=0) + deadline_date = deadline_date_minutes_added - timedelta(minutes = alarm.sh_remind_before) + elif alarm.sh_reminder_unit == 'Second(s)' and ticket.sh_due_date: + deadline_date_seconds_added = ticket.sh_due_date + timedelta(hours = 5,minutes=30,seconds=0) + deadline_date = deadline_date_seconds_added - timedelta(seconds = alarm.sh_remind_before) + if deadline_date and deadline_date != False: + if alarm.type == 'popup': + now = fields.Datetime.now() + timedelta(hours = 5,minutes=30,seconds=0) + if fields.Date.today() == deadline_date.date() and deadline_date.hour == now.hour and deadline_date.minute == now.minute: + notifications = [] + message="<h2><u>Ticket Information</u></h2></br>" + if ticket.create_date: + message+="<strong>Create Date :</strong>"+str(ticket.create_date) + "</br>" + if ticket.sh_due_date: + message+="<strong>Due Date :</strong>"+str(ticket.sh_due_date) + "</br>" + if ticket.subject_id: + message+="<strong>Subject :</strong>"+str(ticket.subject_id.name) + "</br>" + if ticket.ticket_type: + message+="<strong>Type :</strong>"+str(ticket.ticket_type.name) + "</br>" + if ticket.category_id: + message+="<strong>Category :</strong>"+str(ticket.category_id.name) + "</br>" + if ticket.sub_category_id: + message+="<strong>Sub Category :</strong>"+str(ticket.sub_category_id.name) + "</br>" + if ticket.priority: + message+="<strong>Priority :</strong>"+str(ticket.priority.name) + "</br>" + if ticket.team_id: + message+="<strong>Team :</strong>"+str(ticket.team_id.name) + "</br>" + if ticket.team_head: + message+="<strong>Team Head :</strong>"+str(ticket.team_head.name) + "</br>" + if ticket.user_id: + message+="<strong>Assigned To :</strong>"+str(ticket.user_id.name) + "</br>" + multi_users = [] + if ticket.sh_user_ids: + for user in ticket.sh_user_ids: + if user.name not in multi_users: + multi_users.append(user.name) + if len(multi_users) > 0: + message+='<strong>Assigned Users : </strong>' + for user_name in multi_users: + message+='<span class="badge badge-info" style="padding-right:5px">'+str(user_name) +'</span>' + message+='</br>' + tags = [] + if ticket.tag_ids: + for tag in ticket.tag_ids: + if tag.name not in tags: + tags.append(tag.name) + if len(tags) > 0: + message+='<strong>Tags : </strong>' + for tag_name in tags: + message+='<span class="badge badge-info" style="padding-right:5px">'+str(tag_name) +'</span>' + message+='</br>' + products = [] + if ticket.product_ids: + for product in ticket.product_ids: + if product.name_get()[0][1] not in products: + products.append(product.name_get()[0][1]) + if len(products) > 0: + message+='<strong>Products : </strong>' + for product_name in products: + message+='<span class="badge badge-info" style="padding-right:5px">'+str(product_name) +'</span>' + message+='</br>' + if ticket.partner_id: + message+="<strong>Partner :</strong>"+str(ticket.partner_id.name) + "</br>" + if ticket.person_name: + message+="<strong>Person Name :</strong>"+str(ticket.person_name) + "</br>" + if ticket.email: + message+="<strong>Email :</strong>"+str(ticket.email) + "</br>" + model_href = str(self.env['ir.config_parameter'].sudo().get_param('web.base.url')) + '/web#id='+str(ticket.id)+'&model=helpdesk.ticket&view_type=form' + message+="<a style='color:#7C7BAD;padding-right:10px' class='btn btn-link' data-dismiss='toast'>Close</a>" + message+="<a href="+str(model_href)+" target='_blank' class='btn btn-link' style='padding-right:10px;'>Ticket</a>" + partners=[] + if ticket.team_head: + if ticket.team_head.partner_id.id not in partners: + partners.append(ticket.team_head.partner_id.id) + if ticket.user_id: + if ticket.user_id.partner_id.id not in partners: + partners.append(ticket.user_id.partner_id.id) + if ticket.sh_user_ids: + for user_id in ticket.sh_user_ids: + if user_id.partner_id.id not in partners: + partners.append(user_id.partner_id.id) + if len(partners) > 0: + for partner_id in partners: + notifications.append([ + (self._cr.dbname, 'res.partner', partner_id), + {'type': 'user_connection', 'title': _('Ticket Reminder '+'('+str(ticket.name)+')'), 'message': message, 'sticky': True, 'warning': False} + ]) + self.env['bus.bus'].sendmany(notifications) + elif alarm.type == 'email': + now = fields.Datetime.now() + timedelta(hours = 5,minutes=30,seconds=0) + email_formatted=[] + if ticket.team_head: + if str(ticket.team_head.partner_id.email_formatted) not in email_formatted: + email_formatted.append(str(ticket.team_head.email_formatted)) + if ticket.user_id: + if str(ticket.user_id.partner_id.email_formatted) not in email_formatted: + email_formatted.append(str(ticket.user_id.email_formatted)) + if ticket.sh_user_ids: + for user_id in ticket.sh_user_ids: + if str(user_id.partner_id.email_formatted) not in email_formatted: + email_formatted.append(str(user_id.partner_id.email_formatted)) + if fields.Date.today() == deadline_date.date() and deadline_date.hour == now.hour and deadline_date.minute == now.minute: + reminder_template = self.env.ref('sh_helpdesk.sh_ticket_reminder_mail_template') + if reminder_template and len(email_formatted) > 0: + emails = ','.join(email_formatted) + email_values = {'email_to':emails} + reminder_template.sudo().send_mail(ticket.id, force_send=True,email_values=email_values) diff --git a/sh_helpdesk/models/helpdesk_category.py b/sh_helpdesk/models/helpdesk_category.py new file mode 100644 index 0000000..acbb430 --- /dev/null +++ b/sh_helpdesk/models/helpdesk_category.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Part of Softhealer Technologies. + +from odoo import models, fields, api + + +class HelpdeskCategory(models.Model): + _name = 'helpdesk.category' + _description = 'Helpdesk Category' + _rec_name = 'name' + + sequence = fields.Integer(string="Sequence") + name = fields.Char(required=True, string='Name',translate=True) + + @api.model + def create(self, values): + sequence = self.env['ir.sequence'].next_by_code('helpdesk.category') + values['sequence'] = sequence + return super(HelpdeskCategory, self).create(values) diff --git a/sh_helpdesk/models/helpdesk_config_settings.py b/sh_helpdesk/models/helpdesk_config_settings.py new file mode 100644 index 0000000..0136499 --- /dev/null +++ b/sh_helpdesk/models/helpdesk_config_settings.py @@ -0,0 +1,109 @@ +# -*- coding: utf-8 -*- +# Part of Softhealer Technologies. + +from odoo import models, fields, api + + +class ResCompany(models.Model): + _inherit = 'res.company' + + category = fields.Boolean('Category') + sub_category = fields.Boolean('Sub Category') + customer_rating = fields.Boolean('Customer Rating') + auto_close_ticket = fields.Boolean('Auto Close Ticket') + close_days = fields.Integer('No of Days') + new_stage_id = fields.Many2one( + 'helpdesk.stages', string="Draft/New Stage") + done_stage_id = fields.Many2one('helpdesk.stages', string="Resolved Stage") + cancel_stage_id = fields.Many2one('helpdesk.stages', string="Cancel Stage") + allocation_mail_template_id = fields.Many2one( + 'mail.template', string='Ticket Allocation To User Mail Template') + reply_mail_template_id = fields.Many2one( + 'mail.template', string='Ticket Reply Mail Template') + dashboard_filter = fields.Many2many( + 'helpdesk.stages', 'rel_company_stage_counter', string="Dashbaord Filter", required=True) + dashboard_tables = fields.Many2many( + 'helpdesk.stages', 'rel_company_stage_tables', string="Dashbaord Tables", required=True) + reopen_stage_id = fields.Many2one( + 'helpdesk.stages', string="Re-Opened Stage") + close_stage_id = fields.Many2one('helpdesk.stages', string="Closed Stage") + sh_default_team_id = fields.Many2one( + 'helpdesk.team', string="Default Team") + sh_default_user_id = fields.Many2one( + 'res.users', string="Default Assign User") + sh_display_multi_user = fields.Boolean('Display Multi Users ?') + sh_configure_activate = fields.Boolean( + 'Manage Products') + sh_display_ticket_reminder = fields.Boolean('Ticket Reminder ?') + sh_ticket_product_detail = fields.Boolean( + "Ticket Product details in Message?", default=True) + sh_signature = fields.Boolean("Signature?", default=True) + sh_display_in_chatter = fields.Boolean( + "Display in Chatter Message?", default=True) + sh_pdf_in_message = fields.Boolean( + "Send Report URL in Message?", default=True) + sh_ticket_url_in_message = fields.Boolean("Send Ticket URL in Message?", default=True) + sh_receive_email_seeing_ticket = fields.Boolean('Get email when customer view ticket ?') + sh_auto_add_customer_as_follower = fields.Boolean('Auto add customer as follower when create ticket ?',default=True) + + +class HelpdeskSettings(models.TransientModel): + _inherit = 'res.config.settings' + + company_id = fields.Many2one('res.company', string='Company', required=True, + default=lambda self: self.env.company) + category = fields.Boolean( + string='Category', related='company_id.category', readonly=False) + sub_category = fields.Boolean( + string='Sub Category', related='company_id.sub_category', readonly=False) + customer_rating = fields.Boolean( + string='Customer Rating', related='company_id.customer_rating', readonly=False) + auto_close_ticket = fields.Boolean( + string='Auto Close Ticket', related='company_id.auto_close_ticket', readonly=False) + close_days = fields.Integer( + string='No of Days', related='company_id.close_days', readonly=False) + new_stage_id = fields.Many2one('helpdesk.stages', string="Draft/New Stage", + related='company_id.new_stage_id', readonly=False) + done_stage_id = fields.Many2one( + 'helpdesk.stages', string="Resolved Stage", related='company_id.done_stage_id', readonly=False) + cancel_stage_id = fields.Many2one( + 'helpdesk.stages', string="Cancel Stage", related='company_id.cancel_stage_id', readonly=False) + allocation_mail_template_id = fields.Many2one( + 'mail.template', string='Ticket Allocation To User Mail Template', related='company_id.allocation_mail_template_id', readonly=False) + reply_mail_template_id = fields.Many2one( + 'mail.template', string='Ticket Reply Mail Template', related='company_id.reply_mail_template_id', readonly=False) + dashboard_filter = fields.Many2many('helpdesk.stages', 'rel_company_stage_counter', + string="Dashbaord Filter", related="company_id.dashboard_filter", readonly=False, required=True) + dashboard_tables = fields.Many2many('helpdesk.stages', 'rel_company_stage_tables', + string="Dashbaord Tables", related="company_id.dashboard_tables", readonly=False, required=True) + reopen_stage_id = fields.Many2one( + 'helpdesk.stages', string="Re-Opened Stage", readonly=False, related='company_id.reopen_stage_id') + close_stage_id = fields.Many2one( + 'helpdesk.stages', string="Closed Stage", readonly=False, related='company_id.close_stage_id') + sh_default_team_id = fields.Many2one( + 'helpdesk.team', string="Default Team", readonly=False, related='company_id.sh_default_team_id') + sh_default_user_id = fields.Many2one( + 'res.users', string="Default Assign User", readonly=False, related='company_id.sh_default_user_id') + sh_display_multi_user = fields.Boolean( + 'Display Multi Users ?', related='company_id.sh_display_multi_user', readonly=False) + sh_configure_activate = fields.Boolean( + 'Manage Products', related='company_id.sh_configure_activate', readonly=False) + sh_display_ticket_reminder = fields.Boolean('Ticket Reminder ?',related='company_id.sh_display_ticket_reminder',readonly=False) + sh_ticket_product_detail = fields.Boolean( + "Ticket Product details in Message?",related='company_id.sh_ticket_product_detail',readonly=False) + sh_signature = fields.Boolean("Signature?",related='company_id.sh_signature',readonly=False) + sh_display_in_chatter = fields.Boolean( + "Display in Chatter Message?",related='company_id.sh_display_in_chatter',readonly=False) + sh_pdf_in_message = fields.Boolean( + "Send Report URL in Message?",related='company_id.sh_pdf_in_message',readonly=False) + sh_ticket_url_in_message = fields.Boolean("Send Ticket URL in Message?",related='company_id.sh_ticket_url_in_message',readonly=False) + sh_receive_email_seeing_ticket = fields.Boolean('Get email when customer view ticket ?',related='company_id.sh_receive_email_seeing_ticket',readonly=False) + sh_auto_add_customer_as_follower = fields.Boolean('Auto add customer as follower when create ticket ?',related='company_id.sh_auto_add_customer_as_follower',readonly=False) + + @ api.onchange('sh_default_team_id') + def onchange_sh_default_team_id(self): + if self.sh_default_team_id: + domain = {} + domain = {'sh_default_user_id': [ + ('id', 'in', self.sh_default_team_id.team_members.ids)]} + return {'domain': domain} diff --git a/sh_helpdesk/models/helpdesk_policies.py b/sh_helpdesk/models/helpdesk_policies.py new file mode 100644 index 0000000..6efa762 --- /dev/null +++ b/sh_helpdesk/models/helpdesk_policies.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Part of Softhealer Technologies. + +from odoo import models, fields + + +class HelpdeskSLAPolicies(models.Model): + _name = 'sh.helpdesk.sla' + _description = 'Helpdesk SLA Policies' + + def get_deafult_company(self): + company_id = self.env.company + return company_id + + name = fields.Char('Name',required=True) + sh_team_id = fields.Many2one('helpdesk.team','Helpdesk Team',required=True) + sh_ticket_type_id = fields.Many2one('helpdesk.ticket.type','Helpdesk Team Type') + sh_sla_target_type = fields.Selection([('reaching_stage','Reaching Stage'),('assign_to','Assigned To')],default='reaching_stage',string='SLA Target Type') + sh_stage_id = fields.Many2one('helpdesk.stages',string='Reach Stage') + sh_days = fields.Integer('Days',required=True) + sh_hours = fields.Integer('Hours',required=True) + sh_minutes = fields.Integer('Minutes',required=True) + company_id = fields.Many2one( + 'res.company', string="Company", default=get_deafult_company) + sla_ticket_count = fields.Integer(compute='_compute_helpdesk_ticket_sla') + + def _compute_helpdesk_ticket_sla(self): + for record in self: + record.sla_ticket_count = 0 + tickets = self.env['helpdesk.ticket'].search( + [('sh_sla_policy_ids', 'in', self.ids)], limit=None) + record.sla_ticket_count = len(tickets.ids) + + + def action_view_tickets(self): + self.ensure_one() + tickets = self.env['helpdesk.ticket'].sudo().search( + [('sh_sla_policy_ids', 'in', self.ids)]) + action = self.env["ir.actions.actions"]._for_xml_id( + "sh_helpdesk.helpdesk_ticket_action") + if len(tickets) > 1: + action['domain'] = [('id', 'in', tickets.ids)] + elif len(tickets) == 1: + form_view = [ + (self.env.ref('sh_helpdesk.helpdesk_ticket_form_view').id, 'form')] + if 'views' in action: + action['views'] = form_view + \ + [(state, view) + for state, view in action['views'] if view != 'form'] + else: + action['views'] = form_view + action['res_id'] = tickets.id + else: + action = {'type': 'ir.actions.act_window_close'} + return action
\ No newline at end of file diff --git a/sh_helpdesk/models/helpdesk_priority.py b/sh_helpdesk/models/helpdesk_priority.py new file mode 100644 index 0000000..de1bf78 --- /dev/null +++ b/sh_helpdesk/models/helpdesk_priority.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Part of Softhealer Technologies. + +from odoo import models, fields, api + + +class HelpdeskPriority(models.Model): + _name = 'helpdesk.priority' + _description = 'Helpdesk Priority' + _rec_name = 'name' + + sequence = fields.Integer(string="Sequence") + name = fields.Char(required=True, translate=True, string="Name") + color = fields.Char(string="Color") + + @api.model + def create(self, values): + sequence = self.env['ir.sequence'].next_by_code('helpdesk.priority') + values['sequence'] = sequence + return super(HelpdeskPriority, self).create(values) diff --git a/sh_helpdesk/models/helpdesk_so.py b/sh_helpdesk/models/helpdesk_so.py new file mode 100644 index 0000000..07806e9 --- /dev/null +++ b/sh_helpdesk/models/helpdesk_so.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Part of Softhealer Technologies. + +from odoo import models, fields, api, _ +import random +import datetime +from odoo.exceptions import UserError +from odoo.tools import email_re + + +class HelpdeskSO(models.Model): + _name = 'sh.helpdesk.so' + _inherit = ['portal.mixin', 'mail.thread', 'mail.activity.mixin'] + _description = "Helpdesk Sale Order" + + + + diff --git a/sh_helpdesk/models/helpdesk_stages.py b/sh_helpdesk/models/helpdesk_stages.py new file mode 100644 index 0000000..66e4023 --- /dev/null +++ b/sh_helpdesk/models/helpdesk_stages.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# Part of Softhealer Technologies. + +from odoo import models, fields + + +class HelpdeskStages(models.Model): + _name = 'helpdesk.stages' + _description = "Helpdesk Stages" + _order = 'sequence ASC' + _rec_name = 'name' + + name = fields.Char("Name", required=True,translate=True) + mail_template_ids = fields.Many2many( + 'mail.template', string='Mail Template') + sh_next_stage = fields.Many2one( + comodel_name='helpdesk.stages', + string='Next Stage', + ) + + sh_group_ids = fields.Many2many( + comodel_name='res.groups', + string='Groups' + ) + is_cancel_button_visible = fields.Boolean( + string='Is Cancel Button Visible ?' + ) + is_done_button_visible = fields.Boolean( + string='Is Resolved Button Visible ?' + ) + sequence = fields.Integer(string="Sequence") diff --git a/sh_helpdesk/models/helpdesk_subcategory.py b/sh_helpdesk/models/helpdesk_subcategory.py new file mode 100644 index 0000000..1dea790 --- /dev/null +++ b/sh_helpdesk/models/helpdesk_subcategory.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Part of Softhealer Technologies. + +from odoo import models, fields, api + + +class HelpdeskSubCategory(models.Model): + _name = 'helpdesk.subcategory' + _description = 'Helpdesk SubCategory' + _rec_name = 'name' + + sequence = fields.Integer(string="Sequence") + name = fields.Char(required=True, translate=True, + string='Sub Category Name') + parent_category_id = fields.Many2one( + 'helpdesk.category', required=True, string="Parent Category") + + @api.model + def create(self, values): + sequence = self.env['ir.sequence'].next_by_code('helpdesk.subcategory') + values['sequence'] = sequence + return super(HelpdeskSubCategory, self).create(values) diff --git a/sh_helpdesk/models/helpdesk_subject_type.py b/sh_helpdesk/models/helpdesk_subject_type.py new file mode 100644 index 0000000..b5c4174 --- /dev/null +++ b/sh_helpdesk/models/helpdesk_subject_type.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +# Part of Softhealer Technologies. + +from odoo import models, fields + + +class HelpdeskSubjectType(models.Model): + _name = 'helpdesk.sub.type' + _description = 'Helpdesk Subject Type' + _rec_name = 'name' + + name = fields.Char('Name', required=True,translate=True) diff --git a/sh_helpdesk/models/helpdesk_tags.py b/sh_helpdesk/models/helpdesk_tags.py new file mode 100644 index 0000000..876ca08 --- /dev/null +++ b/sh_helpdesk/models/helpdesk_tags.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Part of Softhealer Technologies. + +from odoo import models, fields, api +import random + + +class HelpdeskTags(models.Model): + _name = 'helpdesk.tags' + _description = 'Helpdesk Tags' + _rec_name = 'name' + + name = fields.Char("Name", required=True,translate=True) + color = fields.Integer(string='Color Index') + + _sql_constraints = [ + ('name_uniq', 'unique (name)', "Tag name already exists!"), + ] + + @api.model + def create(self, vals): + res = super(HelpdeskTags, self).create(vals) + number = random.randrange(1, 10) + res.color = number + return res diff --git a/sh_helpdesk/models/helpdesk_team.py b/sh_helpdesk/models/helpdesk_team.py new file mode 100644 index 0000000..437cd67 --- /dev/null +++ b/sh_helpdesk/models/helpdesk_team.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Part of Softhealer Technologies. + +from odoo import models, fields + + +class HelpdeskTeam(models.Model): + _name = 'helpdesk.team' + _description = 'Helpdesk Team' + _rec_name = 'name' + + name = fields.Char('Name', required=True,translate=True) + team_head = fields.Many2one('res.users', 'Team Head', required=True,domain=['|',('share','=',False),('sh_portal_user_access','!=',False)]) + team_members = fields.Many2many('res.users', string="Team Members",domain=['|',('share','=',False),('sh_portal_user_access','!=',False)]) + sh_resource_calendar_id = fields.Many2one('resource.calendar',string="Working Schedule",required=True,default=lambda self: self.env.company.resource_calendar_id) + sla_count = fields.Integer(compute='_compute_helpdesk_sla') + + def _compute_helpdesk_sla(self): + for record in self: + record.sla_count = 0 + slas = self.env['helpdesk.ticket'].sudo().search( + [('team_id', '=', self.id),('sh_sla_status_ids','!=',False)]) + record.sla_count = len(slas.ids) + + def action_view_sla(self): + self.ensure_one() + slas = self.env['helpdesk.ticket'].sudo().search( + [('team_id', '=', self.id),('sh_sla_status_ids','!=',False)]) + action = self.env["ir.actions.actions"]._for_xml_id( + "sh_helpdesk.helpdesk_ticket_action") + if len(slas) > 1: + action['domain'] = [('id', 'in', slas.ids)] + elif len(slas) == 1: + form_view = [ + (self.env.ref('sh_helpdesk.helpdesk_ticket_form_view').id, 'form')] + if 'views' in action: + action['views'] = form_view + \ + [(state, view) + for state, view in action['views'] if view != 'form'] + else: + action['views'] = form_view + action['res_id'] = slas.id + else: + action = {'type': 'ir.actions.act_window_close'} + return action
\ No newline at end of file diff --git a/sh_helpdesk/models/helpdesk_ticket.py b/sh_helpdesk/models/helpdesk_ticket.py new file mode 100644 index 0000000..a2bcb45 --- /dev/null +++ b/sh_helpdesk/models/helpdesk_ticket.py @@ -0,0 +1,1079 @@ +# -*- coding: utf-8 -*- +# Part of Softhealer Technologies. + +from odoo import models, fields, api, _, SUPERUSER_ID +import random +from datetime import timedelta +from odoo.exceptions import UserError +from odoo.tools import email_re +import uuid + + +class HelpdeskSLAStatus(models.Model): + _name = 'sh.helpdesk.sla.status' + _description = "Helpdesk Ticket SLA Status" + _table = 'sh_helpdesk_sla_status' + _order = 'id ASC' + _rec_name = 'sh_sla_id' + + sh_ticket_id = fields.Many2one('helpdesk.ticket', + string='Ticket', + required=True, + ondelete='cascade', + index=True) + sh_sla_id = fields.Many2one('sh.helpdesk.sla', + required=True, + ondelete='cascade') + sh_sla_stage_id = fields.Many2one('helpdesk.stages', + related='sh_sla_id.sh_stage_id', + store=True) + sh_deadline = fields.Datetime("SLA Deadline", + compute='_compute_sh_deadline', + compute_sudo=True, + store=True) + sh_status = fields.Selection([('sla_failed', 'Failed'), + ('sla_passed', 'Passed'), + ('sh_partially_passed', 'Partially Passed')], + string="Status") + color = fields.Integer("Color Index", compute='_compute_sh_color') + sh_done_sla_date = fields.Datetime('SLA Done Date') + + @api.depends('sh_ticket_id.create_date', 'sh_sla_id') + def _compute_sh_deadline(self): + for rec in self: + sla_deadline = rec.sh_ticket_id.create_date + working_schedule = rec.sh_ticket_id.team_id.sh_resource_calendar_id + if not working_schedule: + rec.sh_deadline = sla_deadline + continue + if rec.sh_sla_id.sh_days > 0: + sla_deadline = working_schedule.plan_days( + rec.sh_sla_id.sh_days + 1, + sla_deadline, + compute_leaves=True) + ticket_create_dt = rec.sh_ticket_id.create_date + sla_deadline = sla_deadline.replace( + hour=ticket_create_dt.hour, + minute=ticket_create_dt.minute, + second=ticket_create_dt.second, + microsecond=ticket_create_dt.microsecond) + rec.sh_deadline = working_schedule.plan_hours( + rec.sh_sla_id.sh_hours, sla_deadline, compute_leaves=True) + + @api.depends('sh_status') + def _compute_sh_color(self): + for rec in self: + rec._compute_sh_deadline() + if rec.sh_status == 'sla_failed': + rec.color = 1 + elif rec.sh_status == 'sla_passed': + rec.color = 10 + elif rec.sh_status == 'sh_partially_passed': + rec.color = 4 + else: + rec.color = 0 + + +class HelpdeskTicket(models.Model): + _name = 'helpdesk.ticket' + _inherit = ['portal.mixin', 'mail.thread', 'mail.activity.mixin'] + _description = "Helpdesk Ticket" + _order = 'id DESC' + _rec_name = 'name' + _primary_email = ['email'] + + def get_deafult_company(self): + company_id = self.env.company + return company_id + + @api.model + def get_default_stage(self): + company_id = self.env.company + stage_id = self.env['helpdesk.stages'].sudo().search( + [('id', '=', company_id.new_stage_id.id)], limit=1) + return stage_id.id + + @api.model + def default_due_date(self): + return fields.Datetime.now() + + name = fields.Char("Name", tracking=True) + company_id = fields.Many2one('res.company', + string="Company", + default=get_deafult_company) + done_stage_boolean = fields.Boolean('Done Stage', + compute='_compute_stage_booleans', + store=True) + cancel_stage_boolean = fields.Boolean('Cancel Stage', + compute='_compute_stage_booleans', + store=True) + reopen_stage_boolean = fields.Boolean('Reopened Stage', + compute='_compute_stage_booleans', + store=True) + closed_stage_boolean = fields.Boolean('Closed Stage', + compute='_compute_stage_booleans', + store=True) + open_boolean = fields.Boolean('Open Ticket', + compute='_compute_stage_booleans', + store=True) + cancel_button_boolean = fields.Boolean( + "Cancel Button", + compute='_compute_cancel_button_boolean', + search='_search_cancel_button_boolean') + done_button_boolean = fields.Boolean( + "Done Button", + compute='_compute_done_button_boolean', + search='_search_done_button_boolean') + state = fields.Selection([('customer_replied', 'Customer Replied'), + ('staff_replied', 'Staff Replied')], + string="Replied Status", + default='customer_replied', + required=True, + tracking=True) + active = fields.Boolean( + 'Active', + default=True, + help= + "If unchecked, it will allow you to hide the product without removing it." + ) + ticket_from_website = fields.Boolean('Ticket From Website') + ticket_from_portal = fields.Boolean('Ticket From Portal') + cancel_reason = fields.Char("Cancel Reason", tracking=True, translate=True) + tag_ids = fields.Many2many('helpdesk.tags', string="Tags") + priority = fields.Many2one('helpdesk.priority', + string='Priority', + tracking=True) + stage_id = fields.Many2one('helpdesk.stages', + string="Stage", + default=get_default_stage, + tracking=True, + index=True, + group_expand='_read_group_stage_ids') + ticket_type = fields.Many2one('helpdesk.ticket.type', + string='Ticket Type', + tracking=True) + team_id = fields.Many2one('helpdesk.team', string='Team', tracking=True) + team_head = fields.Many2one('res.users', "Team Head", tracking=True) + user_id = fields.Many2one('res.users', + string="Assigned User", + tracking=True) + subject_id = fields.Many2one('helpdesk.sub.type', + string='Ticket Subject Type', + tracking=True) + category_id = fields.Many2one('helpdesk.category', + string="Category", + tracking=True) + sub_category_id = fields.Many2one('helpdesk.subcategory', + string="Sub Category") + partner_id = fields.Many2one('res.partner', + string='Partner', + tracking=True, + required=True) + person_name = fields.Char(string='Person Name', tracking=True) + email = fields.Char(string='Email', tracking=True) + close_date = fields.Datetime(string='Close Date', tracking=True) + close_by = fields.Many2one('res.users', string='Closed By', tracking=True) + cancel_date = fields.Datetime(string='Cancelled Date', tracking=True) + cancel_by = fields.Many2one('res.users', + string='Cancelled By', + tracking=True) + replied_date = fields.Datetime('Replied Date', tracking=True) + product_ids = fields.Many2many('product.product', string='Products') + + comment = fields.Text(string="Comment", tracking=True, translate=True) + description = fields.Html('Description', tracking=True) + color = fields.Integer(string='Color Index') + priority_new = fields.Selection([('1', 'Very Low'), ('2', 'Low'), + ('3', 'Normal'), ('4', 'High'), + ('5', 'Very High'), ('6', 'Excellent')], + string="Customer Rating", + tracking=True) + customer_comment = fields.Text("Customer Comment", tracking=True) + + attachment_ids = fields.Many2many('ir.attachment', string="Attachments") + form_url = fields.Char('Form Url', compute='_compute_form_url') + category_bool = fields.Boolean(string='Category Setting', + related='company_id.category', + store=True) + sub_category_bool = fields.Boolean(string='Sub Category Setting', + related='company_id.sub_category', + store=True) + rating_bool = fields.Boolean(string='Rating Setting', + related='company_id.customer_rating', + store=True) + ticket_allocated = fields.Boolean("Allocated") + sh_user_ids = fields.Many2many('res.users', string="Assign Multi Users") + sh_display_multi_user = fields.Boolean( + compute="_compute_sh_display_multi_user") + sh_display_product = fields.Boolean(compute='_compute_sh_display_product') + sh_status = fields.Selection([('sla_failed', 'Failed'), + ('sla_passed', 'Passed'), + ('sh_partially_passed', 'Partially Passed')], + string="Status") + sh_sla_policy_ids = fields.Many2many('sh.helpdesk.sla', + 'sh_helpdesk_sla_status', + 'sh_ticket_id', + 'sh_sla_id', + string="Helpdesk SLA Policies", + copy=False) + sh_sla_status_ids = fields.One2many('sh.helpdesk.sla.status', + 'sh_ticket_id', + string="Helpdesk SLA Status") + sh_sla_deadline = fields.Datetime('SLA Deadline', + compute='_compute_sh_sla_deadline', + store=True) + sh_status_boolean = fields.Boolean(compute='_compute_state_boolean') + sh_days_to_reach = fields.Float(string='SLA reached duration', + compute='_compute_days_to_reach', + store=True) + sh_days_to_late = fields.Float(string='SLA late duration', + compute='_compute_days_to_late', + store=True) + sh_due_date = fields.Datetime('Reminder Due Date', + default=default_due_date) + sh_ticket_alarm_ids = fields.Many2many('sh.ticket.alarm', + string='Ticket Reminders') + sh_ticket_report_url = fields.Char(compute='_compute_report_url') + report_token = fields.Char("Access Token") + portal_ticket_url_wp = fields.Char(compute='_compute_ticket_portal_url_wp') + mobile_no = fields.Char('Mobile') + email_subject = fields.Char('Subject') + + # <-- MULTI ACTION FOR MASS UPDATE ASSIGN-TO,MULTI-USER & STATE // ADD/REMOVE FOLLOWER--> + + def action_mass_update_wizard(self): + return { + 'name': + 'Mass Update Ticket', + 'res_model': + 'sh.helpdesk.ticket.mass.update.wizard', + 'view_mode': + 'form', + 'context': { + 'default_helpdesks_ticket_ids': + [(6, 0, self.env.context.get('active_ids'))], + 'default_check_sh_display_multi_user': + self.env.user.company_id.sh_display_multi_user + }, + 'view_id': + self.env.ref( + 'sh_helpdesk.sh_helpdesk_ticket_mass_update_wizard_form_view'). + id, + 'target': + 'new', + 'type': + 'ir.actions.act_window' + } + + @api.model + def _read_group_stage_ids(self, stages, domain, order): + all_stages = self.env['helpdesk.stages'].sudo().search([]) + search_domain = [('id', 'in', all_stages.ids)] + + # perform search + stage_ids = stages._search(search_domain, + order=order, + access_rights_uid=SUPERUSER_ID) + return stages.browse(stage_ids) + + def _search_done_button_boolean(self, operator, value): + not_done_ids = [] + done_ids = [] + for record in self.search([]): + if record.stage_id.is_done_button_visible: + done_ids.append(record.id) + else: + not_done_ids.append(record.id) + if operator == '=': + return [('id', 'in', done_ids)] + elif operator == '!=': + return [('id', 'in', not_done_ids)] + else: + return [] + + def _search_cancel_button_boolean(self, operator, value): + not_cancel_ids = [] + cancel_ids = [] + for record in self.search([]): + if record.stage_id.is_cancel_button_visible: + cancel_ids.append(record.id) + else: + not_cancel_ids.append(record.id) + if operator == '=': + return [('id', 'in', cancel_ids)] + elif operator == '!=': + return [('id', 'in', not_cancel_ids)] + else: + return [] + + def _compute_ticket_portal_url_wp(self): + for rec in self: + rec.portal_ticket_url_wp = False + if rec.company_id.sh_pdf_in_message: + base_url = self.env['ir.config_parameter'].sudo().get_param( + 'web.base.url') + ticket_url = base_url + rec.get_portal_url() + self.sudo().write({'portal_ticket_url_wp': ticket_url}) + + def _get_token(self): + """ Get the current record access token """ + if self.report_token: + return self.report_token + else: + report_token = str(uuid.uuid4()) + self.write({'report_token': report_token}) + return report_token + + def get_download_report_url(self): + url = '' + if self.id: + self.ensure_one() + url = '/download/ht/' + '%s?access_token=%s' % (self.id, + self._get_token()) + return url + + def _compute_report_url(self): + for rec in self: + rec.sh_ticket_report_url = False + if rec.company_id.sh_pdf_in_message: + base_url = self.env['ir.config_parameter'].sudo().get_param( + 'web.base.url') + ticket_url = "%0A%0A Click here to download Ticket Document : %0A" + \ + base_url+rec.get_download_report_url() + self.sudo().write({ + 'sh_ticket_report_url': + base_url + rec.get_download_report_url() + }) + + def action_send_whatsapp(self): + self.ensure_one() + if not self.partner_id.mobile: + raise UserError(_("Partner Mobile Number Not Exist !")) + template = self.env.ref('sh_helpdesk.sh_send_whatsapp_email_template') + + ctx = { + 'default_model': 'helpdesk.ticket', + 'default_res_id': self.ids[0], + 'default_use_template': bool(template.id), + 'default_template_id': template.id, + 'default_composition_mode': 'comment', + 'custom_layout': "mail.mail_notification_paynow", + 'force_email': True, + 'default_is_wp': True, + } + attachment_ids = self.env['ir.attachment'].sudo().search([ + ('res_model', '=', 'helpdesk.ticket'), + ('res_id', '=', str(self.id)) + ]) + if attachment_ids: + ctx.update({'attachment_ids': [(6, 0, attachment_ids.ids)]}) + return { + 'type': 'ir.actions.act_window', + 'view_mode': 'form', + 'res_model': 'mail.compose.message', + 'views': [(False, 'form')], + 'view_id': False, + 'target': 'new', + 'context': ctx, + } + + def _compute_days_to_reach(self): + if self: + for rec in self: + sh_days_to_reach = 0.0 + if rec.sh_sla_status_ids: + for line in rec.sh_sla_status_ids: + if line.sh_deadline and line.sh_done_sla_date: + delta = line.sh_done_sla_date - line.sh_deadline + sh_days_to_reach += delta.days + rec.sh_days_to_reach = sh_days_to_reach + + def _compute_days_to_late(self): + if self: + for rec in self: + sh_days_to_late = 0.0 + if rec.sh_sla_status_ids: + for line in rec.sh_sla_status_ids: + if line.sh_deadline and line.sh_done_sla_date: + delta = line.sh_done_sla_date - line.sh_deadline + sh_days_to_late += delta.days + rec.sh_days_to_late = sh_days_to_late + + def _compute_state_boolean(self): + if self: + for rec in self: + rec.sh_status_boolean = False + sla_passed = rec.sh_sla_status_ids.filtered( + lambda x: x.sh_status == 'sla_passed') + sla_failed = rec.sh_sla_status_ids.filtered( + lambda x: x.sh_status == 'sla_failed') + if sla_passed and sla_failed: + rec.sh_status = 'sh_partially_passed' + + @api.depends('sh_sla_status_ids.sh_deadline') + def _compute_sh_sla_deadline(self): + for rec in self: + sh_deadline = False + status_ids = rec.sh_sla_status_ids.filtered( + lambda x: x.sh_status == False) + rec.sh_sla_deadline = min(status_ids.mapped( + 'sh_deadline')) if status_ids else sh_deadline + + @api.model + def change_sh_status(self): + self.ensure_one() + if self.sh_sla_status_ids: + for line in self.sh_sla_status_ids: + if line.sh_sla_id and line.sh_sla_id.sh_sla_target_type == 'reaching_stage': + if line.sh_sla_id.sh_stage_id.id == self.stage_id.id: + line.sh_done_sla_date = fields.Datetime.now() + line.sh_status = False + self.sh_status = False + if line.sh_done_sla_date and line.sh_deadline: + line.sh_status = 'sla_passed' if line.sh_done_sla_date < line.sh_deadline else 'sla_failed' + self.sh_status = 'sla_passed' if line.sh_done_sla_date < line.sh_deadline else 'sla_failed' + else: + line.sh_status = False if ( + not line.sh_deadline or line.sh_deadline > + fields.Datetime.now()) else 'sla_failed' + self.sh_status = False if ( + not line.sh_deadline or line.sh_deadline > + fields.Datetime.now()) else 'sla_failed' + elif line.sh_sla_id and line.sh_sla_id.sh_sla_target_type == 'assign_to': + if self.user_id or self.sh_user_ids: + line.sh_done_sla_date = fields.Datetime.now() + line.sh_status = False + self.sh_status = False + if line.sh_done_sla_date and line.sh_deadline: + line.sh_status = 'sla_passed' if line.sh_done_sla_date < line.sh_deadline else 'sla_failed' + self.sh_status = 'sla_passed' if line.sh_done_sla_date < line.sh_deadline else 'sla_failed' + else: + line.sh_status = False if ( + not line.sh_deadline or line.sh_deadline > + fields.Datetime.now()) else 'sla_failed' + self.sh_status = False if ( + not line.sh_deadline or line.sh_deadline > + fields.Datetime.now()) else 'sla_failed' + + @api.onchange('team_id', 'ticket_type') + def _onchange_sh_helpdesk_policy_ids(self): + if self: + for rec in self: + rec.sh_sla_policy_ids = [ + (6, 0, + rec.helpdesk_sla_create(rec.team_id.id, + rec.ticket_type.id)) + ] + + @api.depends('company_id') + def _compute_sh_display_multi_user(self): + if self: + for rec in self: + rec.sh_display_multi_user = False + if rec.company_id and rec.company_id.sh_display_multi_user: + rec.sh_display_multi_user = True + + @api.depends('company_id') + def _compute_sh_display_product(self): + if self: + for rec in self: + rec.sh_display_product = False + if rec.company_id and rec.company_id.sh_configure_activate: + rec.sh_display_product = True + + @api.model + def message_new(self, msg_dict, custom_values=None): + """ Overrides mail_thread message_new that is called by the mailgateway + through message_process. + This override updates the document according to the email. + """ + defaults = { + 'email': msg_dict.get('from'), + 'partner_id': msg_dict.get('author_id', False), + 'description': msg_dict.get('body'), + 'email_subject': msg_dict.get('subject') or _("No Subject"), + 'state': 'customer_replied', + 'replied_date': msg_dict.get('date') + } + + return super(HelpdeskTicket, self).message_new(msg_dict, + custom_values=defaults) + + def _message_post_after_hook(self, message, msg_vals): + if self.email and not self.partner_id: + # we consider that posting a message with a specified recipient (not a follower, a specific one) + # on a document without customer means that it was created through the chatter using + # suggested recipients. This heuristic allows to avoid ugly hacks in JS. + new_partner = message.partner_ids.filtered( + lambda partner: partner.email == self.email) + if new_partner: + self.search([ + ('partner_id', '=', False), + ('email', '=', new_partner.email), + ]).write({'partner_id': new_partner.id}) + + return super(HelpdeskTicket, + self)._message_post_after_hook(message, msg_vals) + + def _compute_form_url(self): + if self: + base_url = self.env['ir.config_parameter'].sudo().get_param( + 'web.base.url') + url_str = '' + action = self.env.ref('sh_helpdesk.helpdesk_ticket_action').id + if base_url: + url_str += str(base_url) + '/web#' + for rec in self: + url_str += 'id='+str(rec.id)+'&action='+str(action) + \ + '&model=helpdesk.ticket&view_type=form' + rec.form_url = url_str + + def _compute_access_url(self): + super(HelpdeskTicket, self)._compute_access_url() + for ticket in self: + ticket.access_url = '/my/tickets/%s' % (ticket.id) + + def _get_report_base_filename(self): + self.ensure_one() + return '%s %s' % ('Ticket', self.name) + + @api.model + def helpdesk_sla_create(self, team_id, ticket_type): + self.ensure_one() + sla_policy_ids_list = [] + if self.sh_sla_status_ids: + self.sh_sla_status_ids.unlink() + if team_id: + sla_policy_ids = self.env['sh.helpdesk.sla'].sudo().search([ + ('sh_team_id', '=', team_id) + ]) + if sla_policy_ids: + for policy_id in sla_policy_ids: + if policy_id.id not in sla_policy_ids_list: + sla_policy_ids_list.append(policy_id.id) + if ticket_type: + if team_id: + sla_policy_ids = self.env['sh.helpdesk.sla'].sudo().search([ + ('sh_ticket_type_id', '=', ticket_type), + ('sh_team_id', '=', team_id) + ]) + if sla_policy_ids: + for policy_id in sla_policy_ids: + if policy_id.id not in sla_policy_ids_list: + sla_policy_ids_list.append(policy_id.id) + elif not team_id: + sla_policy_ids = self.env['sh.helpdesk.sla'].sudo().search([ + ('sh_ticket_type_id', '=', ticket_type) + ]) + if sla_policy_ids: + for policy_id in sla_policy_ids: + if policy_id.id not in sla_policy_ids_list: + sla_policy_ids_list.append(policy_id.id) + return sla_policy_ids_list + + @api.model + def create(self, vals): + if vals.get('partner_id') == False and vals.get('email', False): + emails = email_re.findall(vals.get('email') or '') + email = emails and emails[0] or '' + name = str(vals.get('email')).split('"') + partner_id = self.env['res.partner'].create({ + 'name': + name[1], + 'email': + email, + 'company_type': + 'person', + }) + vals.update({ + 'partner_id': partner_id.id, + 'email': email, + 'person_name': partner_id.name, + }) + if self.env.company.sh_default_team_id and not vals.get( + 'team_id') and not vals.get('user_id'): + vals.update({ + 'team_id': + self.env.company.sh_default_team_id.id, + 'team_head': + self.env.company.sh_default_team_id.team_head.id, + 'user_id': + self.env.company.sh_default_user_id.id, + }) + number = random.randrange(1, 10) + company_id = self.env.company + if 'company_id' in vals: + self = self.with_company(vals['company_id']) + vals['name'] = self.env['ir.sequence'].next_by_code( + 'helpdesk.ticket') or _('New') + if company_id.new_stage_id: + vals['stage_id'] = company_id.new_stage_id.id + + vals['color'] = number + res = super(HelpdeskTicket, self).create(vals) + #code by nida + template_id = self.env.ref('sh_helpdesk.sh_ticket_new_template_to_admin').id + template = self.env['mail.template'].browse(template_id) + template.sudo().send_mail(res.id, force_send=True) + # end by nida + if res.sh_sla_status_ids: + for line in res.sh_sla_status_ids: + line.sh_status = res.sh_status + if res.ticket_from_website and res.company_id.new_stage_id.mail_template_ids and res.partner_id: + for template in res.company_id.new_stage_id.mail_template_ids: + template.sudo().send_mail(res.id, force_send=True) + else: + if not res.ticket_from_website and res.company_id.new_stage_id.mail_template_ids and res.partner_id: + for template in res.company_id.new_stage_id.mail_template_ids: + template.sudo().send_mail(res.id, force_send=True) + if res.team_id and res.team_head and res.user_id and res.sh_user_ids: + allocation_template = res.company_id.allocation_mail_template_id + email_formatted = [] + if res.team_head.partner_id.email_formatted not in email_formatted: + email_formatted.append( + res.team_head.partner_id.email_formatted) + if res.user_id.partner_id.email_formatted not in email_formatted: + email_formatted.append(res.user_id.partner_id.email_formatted) + for user in res.sh_user_ids: + if user.id != res.user_id.id: + if user.partner_id.email_formatted not in email_formatted: + email_formatted.append(user.partner_id.email_formatted) + email_formatted_str = ','.join(email_formatted) + email_values = { + 'email_from': str(res.team_head.partner_id.email_formatted), + 'email_to': email_formatted_str + } + if allocation_template: + allocation_template.sudo().send_mail(res.id, + force_send=True, + email_values=email_values) + res.ticket_allocated = True + elif res.team_id and res.team_head and res.user_id and not res.sh_user_ids: + allocation_template = res.company_id.allocation_mail_template_id + email_formatted = [] + if res.team_head.partner_id.email_formatted not in email_formatted: + email_formatted.append( + res.team_head.partner_id.email_formatted) + if res.user_id.partner_id.email_formatted not in email_formatted: + email_formatted.append(res.user_id.partner_id.email_formatted) + email_formatted_str = ','.join(email_formatted) + email_values = { + 'email_from': str(res.team_head.partner_id.email_formatted), + 'email_to': email_formatted_str + } + if allocation_template: + allocation_template.sudo().send_mail(res.id, + force_send=True, + email_values=email_values) + res.ticket_allocated = True + elif res.team_id and res.team_head and not res.user_id and res.sh_user_ids: + allocation_template = res.company_id.allocation_mail_template_id + email_formatted = [] + for user in res.sh_user_ids: + if user.partner_id.email_formatted not in email_formatted: + email_formatted.append(user.partner_id.email_formatted) + email_formatted_str = ','.join(email_formatted) + email_values = { + 'email_from': str(res.team_head.partner_id.email_formatted), + 'email_to': email_formatted_str + } + if allocation_template: + allocation_template.sudo().send_mail(res.id, + force_send=True, + email_values=email_values) + res.ticket_allocated = True + elif not res.team_id and not res.team_head and res.user_id and res.sh_user_ids: + allocation_template = res.company_id.allocation_mail_template_id + email_formatted = [] + if res.user_id.partner_id.email_formatted not in email_formatted: + email_formatted.append(res.user_id.partner_id.email_formatted) + for user in res.sh_user_ids: + if user.id != res.user_id.id: + if user.partner_id.email_formatted not in email_formatted: + email_formatted.append(user.partner_id.email_formatted) + email_formatted_str = ','.join(email_formatted) + email_values = { + 'email_from': str(res.company_id.partner_id.email_formatted), + 'email_to': email_formatted_str + } + if allocation_template: + allocation_template.sudo().send_mail(res.id, + force_send=True, + email_values=email_values) + res.ticket_allocated = True + elif not res.team_id and not res.team_head and res.user_id and not res.sh_user_ids: + allocation_template = res.company_id.allocation_mail_template_id + allocation_template.sudo().write({ + 'email_from': + str(res.company_id.partner_id.email_formatted), + 'email_to': + str(res.user_id.partner_id.email_formatted), + 'partner_to': + str(res.user_id.partner_id.id) + }) + email_values = { + 'email_from': str(res.company_id.partner_id.email_formatted), + 'email_to': str(res.user_id.partner_id.email_formatted) + } + if allocation_template: + allocation_template.sudo().send_mail(res.id, + force_send=True, + email_values=email_values) + res.ticket_allocated = True + elif not res.team_id and not res.team_head and not res.user_id and res.sh_user_ids: + allocation_template = res.company_id.allocation_mail_template_id + email_formatted = [] + for user in res.sh_user_ids: + if user.partner_id.email_formatted not in email_formatted: + email_formatted.append(user.partner_id.email_formatted) + email_formatted_str = ','.join(email_formatted) + email_values = { + 'email_from': str(res.company_id.partner_id.email_formatted), + 'email_to': email_formatted_str + } + if allocation_template: + allocation_template.sudo().send_mail(res.id, + force_send=True, + email_values=email_values) + res.ticket_allocated = True + if self.env.company.sh_auto_add_customer_as_follower: + res.message_subscribe(partner_ids=res.partner_id.ids) + return res + + def write(self, vals): + user_groups = self.env.user.groups_id.ids + if vals.get('stage_id'): + stage_id = self.env['helpdesk.stages'].sudo().search( + [('id', '=', vals.get('stage_id'))], limit=1) + if stage_id and stage_id.sh_group_ids: + is_group_exist = False + list_user_groups = user_groups + list_stage_groups = stage_id.sh_group_ids.ids + for item in list_stage_groups: + if item in list_user_groups: + is_group_exist = True + break + if not is_group_exist: + raise UserError( + _('You have not access to edit this support request.')) + if vals.get('partner_id' + ) and self.env.company.new_stage_id.mail_template_ids: + for rec in self: + for template in rec.company_id.new_stage_id.mail_template_ids: + template.sudo().send_mail(rec.id, force_send=True) + res = super(HelpdeskTicket, self).write(vals) + if vals.get('team_id') and vals.get('team_head') and vals.get( + 'user_id') and vals.get( + 'sh_user_ids') and not vals.get('ticket_allocated'): + allocation_template = self.env.company.allocation_mail_template_id + team_head = self.env['res.users'].sudo().browse( + vals.get('team_head')) + user_id = self.env['res.users'].sudo().browse(vals.get('user_id')) + email_formatted = [] + if team_head.partner_id.email_formatted not in email_formatted: + email_formatted.append(team_head.partner_id.email_formatted) + if user_id.partner_id.email_formatted not in email_formatted: + email_formatted.append(user_id.partner_id.email_formatted) + users = vals.get('sh_user_ids')[0][2] + user_ids = self.env['res.users'].sudo().browse(users) + for user in user_ids: + if user.id != user_id.id: + if user.partner_id.email_formatted not in email_formatted: + email_formatted.append(user.partner_id.email_formatted) + email_formatted_str = ','.join(email_formatted) + email_values = { + 'email_from': str(team_head.partner_id.email_formatted), + 'email_to': email_formatted_str + } + if allocation_template: + for rec in self: + allocation_template.sudo().send_mail( + rec.id, force_send=True, email_values=email_values) + rec.ticket_allocated = True + elif vals.get('team_id') and vals.get('team_head') and vals.get( + 'user_id' + ) and not vals.get('sh_user_ids') and not vals.get('ticket_allocated'): + allocation_template = self.env.company.allocation_mail_template_id + team_head = self.env['res.users'].sudo().browse( + vals.get('team_head')) + user_id = self.env['res.users'].sudo().browse(vals.get('user_id')) + email_formatted = [] + if team_head.partner_id.email_formatted not in email_formatted: + email_formatted.append(team_head.partner_id.email_formatted) + if user_id.partner_id.email_formatted not in email_formatted: + email_formatted.append(user_id.partner_id.email_formatted) + email_formatted_str = ','.join(email_formatted) + email_values = { + 'email_from': str(team_head.partner_id.email_formatted), + 'email_to': email_formatted_str + } + if allocation_template: + for rec in self: + allocation_template.sudo().send_mail( + rec.id, force_send=True, email_values=email_values) + rec.ticket_allocated = True + elif vals.get('team_id') and vals.get( + 'team_head') and not vals.get('user_id') and vals.get( + 'sh_user_ids') and not vals.get('ticket_allocated'): + allocation_template = self.env.company.allocation_mail_template_id + email_formatted = [] + users = vals.get('sh_user_ids')[0][2] + user_ids = self.env['res.users'].sudo().browse(users) + team_head = self.env['res.users'].sudo().browse( + vals.get('team_head')) + for user in user_ids: + if user.partner_id.email_formatted not in email_formatted: + email_formatted.append(user.partner_id.email_formatted) + email_formatted_str = ','.join(email_formatted) + email_values = { + 'email_from': str(team_head.partner_id.email_formatted), + 'email_to': email_formatted_str + } + if allocation_template: + for rec in self: + allocation_template.sudo().send_mail( + rec.id, force_send=True, email_values=email_values) + rec.ticket_allocated = True + elif not vals.get('team_id') and not vals.get( + 'team_head') and vals.get('user_id') and vals.get( + 'sh_user_ids') and not vals.get('ticket_allocated'): + allocation_template = self.env.company.allocation_mail_template_id + email_formatted = [] + user_id = self.env['res.users'].sudo().browse(vals.get('user_id')) + users = vals.get('sh_user_ids')[0][2] + user_ids = self.env['res.users'].sudo().browse(users) + if user_id.partner_id.email_formatted not in email_formatted: + email_formatted.append(user_id.partner_id.email_formatted) + for user in user_ids: + if user.id != user_id.id: + if user.partner_id.email_formatted not in email_formatted: + email_formatted.append(user.partner_id.email_formatted) + email_formatted_str = ','.join(email_formatted) + email_values = { + 'email_from': str(self.env.company.partner_id.email_formatted), + 'email_to': email_formatted_str + } + if allocation_template: + for rec in self: + allocation_template.sudo().send_mail( + rec.id, force_send=True, email_values=email_values) + rec.ticket_allocated = True + elif not vals.get('team_id') and not vals.get( + 'team_head') and vals.get('user_id') and not vals.get( + 'sh_user_ids') and not vals.get('ticket_allocated'): + allocation_template = self.env.company.allocation_mail_template_id + user_id = self.env['res.users'].sudo().browse(vals.get('user_id')) + email_values = { + 'email_from': str(self.env.company.partner_id.email_formatted), + 'email_to': str(user_id.partner_id.email_formatted) + } + if allocation_template: + for rec in self: + allocation_template.sudo().send_mail( + rec.id, force_send=True, email_values=email_values) + rec.ticket_allocated = True + elif not vals.get('team_id') and not vals.get( + 'team_head') and not vals.get('user_id') and vals.get( + 'sh_user_ids') and not vals.get('ticket_allocated'): + allocation_template = self.env.company.allocation_mail_template_id + users = vals.get('sh_user_ids')[0][2] + + user_ids = self.env['res.users'].sudo().browse(users) + email_formatted = [] + for user in user_ids: + if user.partner_id.email_formatted not in email_formatted: + email_formatted.append(user.partner_id.email_formatted) + email_formatted_str = ','.join(email_formatted) + email_values = { + 'email_from': str(self.env.company.partner_id.email_formatted), + 'email_to': email_formatted_str + } + if allocation_template: + for rec in self: + allocation_template.sudo().send_mail( + rec.id, force_send=True, email_values=email_values) + rec.ticket_allocated = True + return res + + def preview_ticket(self): + self.ensure_one() + return { + 'type': 'ir.actions.act_url', + 'target': 'self', + 'url': self.get_portal_url(), + } + + @api.depends('stage_id') + def _compute_stage_booleans(self): + if self: + for rec in self: + rec.cancel_stage_boolean = False + rec.done_stage_boolean = False + rec.reopen_stage_boolean = False + rec.closed_stage_boolean = False + rec.open_boolean = False + if rec.stage_id.id == rec.company_id.cancel_stage_id.id: + rec.cancel_stage_boolean = True + rec.open_boolean = True + elif rec.stage_id.id == rec.company_id.done_stage_id.id: + rec.done_stage_boolean = True + rec.open_boolean = True + elif rec.stage_id.id == rec.company_id.reopen_stage_id.id: + rec.reopen_stage_boolean = True + rec.open_boolean = False + elif rec.stage_id.id == rec.company_id.close_stage_id.id: + rec.closed_stage_boolean = True + rec.open_boolean = True + + @api.depends('stage_id') + def _compute_cancel_button_boolean(self): + if self: + for rec in self: + rec.cancel_button_boolean = False + if rec.stage_id.is_cancel_button_visible: + rec.cancel_button_boolean = True + + @api.depends('stage_id') + def _compute_done_button_boolean(self): + if self: + for rec in self: + rec.done_button_boolean = False + if rec.stage_id.is_done_button_visible: + rec.done_button_boolean = True + + def action_approve(self): + self.ensure_one() + if self.stage_id.sh_next_stage: + self.stage_id = self.stage_id.sh_next_stage.id + self.change_sh_status() + self._compute_sh_sla_deadline() + if self.stage_id.mail_template_ids: + for template in self.stage_id.mail_template_ids: + template.sudo().send_mail(self.id, force_send=True) + + def aciton_draft(self): + self.ensure_one() + if self.company_id and self.company_id.new_stage_id: + self.stage_id = self.company_id.new_stage_id.id + + def action_done(self): + self.ensure_one() + if self.company_id and self.company_id.done_stage_id and self.company_id.done_stage_id.mail_template_ids: + for template in self.company_id.done_stage_id.mail_template_ids: + template.sudo().send_mail(self.id, force_send=True) + self.stage_id = self.company_id.done_stage_id.id + + def action_reply(self): + self.ensure_one() + ir_model_data = self.env['ir.model.data'] + template_id = self.company_id.reply_mail_template_id.id + try: + compose_form_id = ir_model_data.get_object_reference( + 'mail', 'email_compose_message_wizard_form')[1] + except ValueError: + compose_form_id = False + ctx = { + 'default_model': 'helpdesk.ticket', + 'default_res_id': self.ids[0], + 'default_use_template': bool(template_id), + 'default_template_id': template_id, + 'default_composition_mode': 'comment', + 'force_email': True + } + return { + 'type': 'ir.actions.act_window', + 'view_mode': 'form', + 'res_model': 'mail.compose.message', + 'views': [(compose_form_id, 'form')], + 'view_id': compose_form_id, + 'target': 'new', + 'context': ctx, + } + + def action_closed(self): + self.ensure_one() + if self.company_id and self.company_id.close_stage_id and self.company_id.close_stage_id.mail_template_ids: + for template in self.company_id.close_stage_id.mail_template_ids: + template.sudo().send_mail(self.id, force_send=True) + self.write({ + 'close_date': fields.Datetime.now(), + 'close_by': self.env.user.id, + 'closed_stage_boolean': True, + 'stage_id': self.company_id.close_stage_id.id + }) + + def action_cancel(self): + self.ensure_one() + if self.company_id and self.company_id.cancel_stage_id and self.company_id.cancel_stage_id.mail_template_ids: + for template in self.company_id.cancel_stage_id.mail_template_ids: + template.sudo().send_mail(self.id, force_send=True) + stage_id = self.company_id.cancel_stage_id + self.stage_id = stage_id.id + self.cancel_date = fields.Datetime.now() + self.cancel_by = self.env.user.id + self.cancel_stage_boolean = True + + def action_open(self): + if self.company_id and self.company_id.reopen_stage_id and self.company_id.reopen_stage_id.mail_template_ids: + for template in self.company_id.reopen_stage_id.mail_template_ids: + template.sudo().send_mail(self.id, force_send=True) + self.write({ + 'stage_id': self.company_id.reopen_stage_id.id, + 'open_boolean': True, + }) + + @api.onchange('team_id') + def onchange_team(self): + if self.team_id: + self.team_head = self.team_id.team_head + user_ids = self.env['helpdesk.team'].sudo().search([ + ('id', '=', self.team_id.id) + ]) + return { + 'domain': { + 'user_id': [('id', 'in', user_ids.team_members.ids)], + 'sh_user_ids': [('id', 'in', user_ids.team_members.ids)] + } + } + else: + self.team_head = False + + @api.onchange('category_id') + def onchange_category(self): + if self.category_id: + sub_category_ids = self.env['helpdesk.subcategory'].sudo().search([ + ('parent_category_id', '=', self.category_id.id) + ]).ids + return { + 'domain': { + 'sub_category_id': [('id', 'in', sub_category_ids)] + } + } + else: + self.sub_category_id = False + + @api.onchange('partner_id') + def onchange_partner_id(self): + if self.partner_id: + self.person_name = self.partner_id.name + self.email = self.partner_id.email + self.mobile_no = self.partner_id.mobile + else: + self.person_name = False + self.email = False + self.mobile_no = False + + @api.model + def _run_auto_close_ticket(self): + tikcet_ids = self.env['helpdesk.ticket'].sudo().search([ + ('done_stage_boolean', '=', False), + ('cancel_stage_boolean', '=', False) + ]) + for ticket in tikcet_ids: + replied_date = ticket.replied_date + if replied_date and ticket.company_id.auto_close_ticket == True: + no_of_days = ticket.company_id.close_days + end_date = replied_date + timedelta(days=no_of_days) + if end_date < fields.Datetime.now( + ) and ticket.state == 'staff_replied': + ticket.action_closed() diff --git a/sh_helpdesk/models/helpdesk_ticket_dashboard.py b/sh_helpdesk/models/helpdesk_ticket_dashboard.py new file mode 100644 index 0000000..8a175ac --- /dev/null +++ b/sh_helpdesk/models/helpdesk_ticket_dashboard.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Part of Softhealer Technologies. + +from odoo import models, fields, _ + + +class TicketDashboard(models.Model): + _name = 'ticket.dashboard' + _description = 'Ticket Dashboard' + + name = fields.Char('Name') + + def get_ticket_data(self, ids): + return { + 'name': _('Tickets'), + 'type': 'ir.actions.act_window', + 'res_model': 'helpdesk.ticket', + 'view_mode': 'tree,form', + 'domain': [('id', 'in', ids)], + 'target': 'current' + } diff --git a/sh_helpdesk/models/helpdesk_ticket_type.py b/sh_helpdesk/models/helpdesk_ticket_type.py new file mode 100644 index 0000000..8b061e3 --- /dev/null +++ b/sh_helpdesk/models/helpdesk_ticket_type.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Part of Softhealer Technologies. + +from odoo import models, fields + + +class HelpdeskTicketType(models.Model): + _name = 'helpdesk.ticket.type' + _description = 'Helpdesk Ticket Type' + _rec_name = 'name' + + name = fields.Char('Name', required=True,translate=True) + sla_count = fields.Integer(compute='_compute_helpdesk_sla') + + def _compute_helpdesk_sla(self): + for record in self: + record.sla_count = 0 + slas = self.env['helpdesk.ticket'].sudo().search( + [('ticket_type', '=', self.id),('sh_sla_status_ids','!=',False)]) + record.sla_count = len(slas.ids) + + def action_view_sla(self): + self.ensure_one() + slas = self.env['helpdesk.ticket'].sudo().search( + [('ticket_type', '=', self.id),('sh_sla_status_ids','!=',False)]) + action = self.env["ir.actions.actions"]._for_xml_id( + "sh_helpdesk.helpdesk_ticket_action") + if len(slas) > 1: + action['domain'] = [('id', 'in', slas.ids)] + elif len(slas) == 1: + form_view = [ + (self.env.ref('sh_helpdesk.helpdesk_ticket_form_view').id, 'form')] + if 'views' in action: + action['views'] = form_view + \ + [(state, view) + for state, view in action['views'] if view != 'form'] + else: + action['views'] = form_view + action['res_id'] = slas.id + else: + action = {'type': 'ir.actions.act_window_close'} + return action diff --git a/sh_helpdesk/models/helpdesk_ticket_update_wizard.py b/sh_helpdesk/models/helpdesk_ticket_update_wizard.py new file mode 100644 index 0000000..5e9c342 --- /dev/null +++ b/sh_helpdesk/models/helpdesk_ticket_update_wizard.py @@ -0,0 +1,87 @@ +# -*- coding: utf-8 -*- +# Part of Softhealer Technologies. +from odoo import fields, models, _, api +from odoo.exceptions import UserError + + +class MassUpdateWizard(models.TransientModel): + + _name = "sh.helpdesk.ticket.mass.update.wizard" + _description = "Mass Update Wizard" + + helpdesks_ticket_ids = fields.Many2many(comodel_name='helpdesk.ticket') + check_assign_to = fields.Boolean(string='Asssign To', default=False) + assign_to = fields.Many2one(comodel_name='res.users', + string='Assign To', + domain=[('share', '=', False)]) + check_sh_display_multi_user = fields.Boolean() + check_assign_to_multiuser = fields.Boolean(default=False, + string="Assign Multi User") + ticket_update_type = fields.Selection([ + ('add', 'Add'), + ('replace', 'Replace'), + ], + default="add", + string="Ticket Type Update") + assign_to_multiuser = fields.Many2many('res.users', + string="Assign Multi Users", + domain=[('share', '=', False)]) + + check_helpdesks_state = fields.Boolean(default=False, string="Stage") + helpdesk_stages = fields.Many2one('helpdesk.stages', string="Stage") + + check_add_remove = fields.Boolean(string="Add/Remove", default=False) + followers = fields.Many2many('res.partner', string="Followers") + + ticket_follower_update_type = fields.Selection([ + ('add', 'Add'), + ('remove', 'Remove'), + ], + default="add", + string="Ticket Type Update") + + def update_record(self): + + # <-- ASSIGN TO UPDATE --> + + if self.check_assign_to == True: + self.helpdesks_ticket_ids.write({'user_id': self.assign_to.id}) + + # <-- ASSIGN MULTIUSER UPDATE --> + + if self.check_assign_to_multiuser == True: + + if self.ticket_update_type == 'add': + get_list = [] + for rec in self.helpdesks_ticket_ids.sh_user_ids: + if rec: + get_list.append(rec.id) + for rec1 in self.assign_to_multiuser: + if rec1: + get_list.append(rec1.id) + self.helpdesks_ticket_ids.write( + {'sh_user_ids': [(6, 0, get_list)]}) + + if self.ticket_update_type == "replace": + self.helpdesks_ticket_ids.write( + {'sh_user_ids': [(6, 0, self.assign_to_multiuser.ids)]}) + + # <-- STATE UPDATE --> + + if self.check_helpdesks_state == True: + for rec in self.helpdesks_ticket_ids: + if self.helpdesk_stages: + rec.stage_id = self.helpdesk_stages.id + + # <-- ADD/REMOVE FOLLOWER UPDATE --> + + for rec in self.helpdesks_ticket_ids: + ids_list = [] + if self.ticket_follower_update_type == "add": + rec.message_subscribe(partner_ids=self.followers.ids) + if self.ticket_follower_update_type == "remove": + for follower in self.followers.ids: + if follower in rec.message_partner_ids.ids: + ids_list.append(follower) + final_list = ids_list + rec.message_unsubscribe(partner_ids=final_list)
\ No newline at end of file diff --git a/sh_helpdesk/models/res_users.py b/sh_helpdesk/models/res_users.py new file mode 100644 index 0000000..d80a80d --- /dev/null +++ b/sh_helpdesk/models/res_users.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# Part of Softhealer Technologies. + +from odoo import models, fields, api + + +class ResUsers(models.Model): + _inherit = 'res.users' + + sh_portal_user = fields.Boolean(string='Portal',compute='_compute_sh_portal_user',search='_search_sh_portal_user') + sh_portal_user_access = fields.Selection([('user','Portal Support User'),('manager','Portal Manager'),('leader','Portal Leader')],string='Portal Access') + sign = fields.Text('Signature') + + @api.depends('groups_id') + def _compute_sh_portal_user(self): + if self: + for rec in self: + if self.env.ref('base.group_portal').id in rec.groups_id.ids: + rec.sh_portal_user = True + else: + rec.sh_portal_user = False + + def _search_sh_portal_user(self, operator, value): + user_obj = self.env['res.users'] + domain = [] + domain.append(('sh_portal_user', operator, value)) + users = user_obj.sudo().search(domain).ids + if users: + return [('id', 'in', users)] + else: + return []
\ No newline at end of file diff --git a/sh_helpdesk/models/send_mail_quick_reply.py b/sh_helpdesk/models/send_mail_quick_reply.py new file mode 100644 index 0000000..607bf87 --- /dev/null +++ b/sh_helpdesk/models/send_mail_quick_reply.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Part of Softhealer Technologies. + +from odoo import models, fields + + +class SendQuickReply(models.Model): + _name = 'sh.quick.reply' + _description = 'Quick Reply' + + name = fields.Char('Title', required=True) + commom_for_all = fields.Boolean(string='Commom For All', default=False) + sh_user_id = fields.Many2one('res.users', + string='User', + required=True, + default=lambda self: self.env.user.id) + active = fields.Boolean(default=True) + sh_description = fields.Html('Body') |
