diff options
Diffstat (limited to 'addons/project')
| -rw-r--r-- | addons/project/__manifest__.py | 2 | ||||
| -rw-r--r-- | addons/project/data/project_data.xml | 23 | ||||
| -rw-r--r-- | addons/project/data/project_demo.xml | 46 | ||||
| -rw-r--r-- | addons/project/data/project_mail_template_data.xml | 85 | ||||
| -rw-r--r-- | addons/project/models/project.py | 101 | ||||
| -rw-r--r-- | addons/project/models/res_config_settings.py | 2 | ||||
| -rw-r--r-- | addons/project/security/project_security.xml | 5 | ||||
| -rw-r--r-- | addons/project/views/project_views.xml | 52 | ||||
| -rw-r--r-- | addons/project/views/rating_views.xml | 74 | ||||
| -rw-r--r-- | addons/project/views/res_config_settings_views.xml | 10 |
10 files changed, 393 insertions, 7 deletions
diff --git a/addons/project/__manifest__.py b/addons/project/__manifest__.py index d95a21d1ee7..43b36689d88 100644 --- a/addons/project/__manifest__.py +++ b/addons/project/__manifest__.py @@ -14,6 +14,7 @@ 'analytic', 'mail', 'portal', + 'rating', 'resource', 'web', 'web_tour', @@ -24,6 +25,7 @@ 'security/ir.model.access.csv', 'data/project_data.xml', 'report/project_report_views.xml', + 'views/rating_views.xml', 'views/project_views.xml', 'views/res_partner_views.xml', 'views/res_config_settings_views.xml', diff --git a/addons/project/data/project_data.xml b/addons/project/data/project_data.xml index de45107ae71..a8f8be15f2b 100644 --- a/addons/project/data/project_data.xml +++ b/addons/project/data/project_data.xml @@ -17,6 +17,15 @@ <field name="noupdate">True</field> </record> + <record id="ir_cron_rating_project" model="ir.cron"> + <field name="name">Project: Send rating</field> + <field name="model_id" ref="project.model_project_project"/> + <field name="state">code</field> + <field name="code">model._send_rating_all()</field> + <field name="interval_type">days</field> + <field name="numbercall">-1</field> + </record> + </data> @@ -46,6 +55,12 @@ <field name="default" eval="False"/> <field name="description">Stage changed</field> </record> + <record id="mt_task_rating" model="mail.message.subtype"> + <field name="name">Task Rating</field> + <field name="res_model">project.task</field> + <field name="default" eval="True"/> + <field name="description">Ratings</field> + </record> <!-- Project-related subtypes for messaging / Chatter --> <record id="mt_project_task_new" model="mail.message.subtype"> <field name="name">Task Opened</field> @@ -79,6 +94,14 @@ <field name="parent_id" eval="ref('mt_task_stage')"/> <field name="relation_field">project_id</field> </record> + <record id="mt_project_task_rating" model="mail.message.subtype"> + <field name="name">Task Rating</field> + <field name="sequence">14</field> + <field name="res_model">project.project</field> + <field name="default" eval="True"/> + <field name="parent_id" eval="ref('mt_task_rating')"/> + <field name="relation_field">project_id</field> + </record> <data noupdate="1"> diff --git a/addons/project/data/project_demo.xml b/addons/project/data/project_demo.xml index f5e53c769df..592acc33a7d 100644 --- a/addons/project/data/project_demo.xml +++ b/addons/project/data/project_demo.xml @@ -430,5 +430,51 @@ Send it ASAP, its urgent.</field> <function model="project.project" name="message_subscribe" eval="[ref('project.project_project_1')], [ref('base.partner_demo_portal')]"/> + + <!-- Rating Demo Data --> + <record id="rating_task_1" model="rating.rating"> + <field name="res_model_id" ref="project.model_project_task"/> + <field name="rated_partner_id" ref="base.partner_root"/> + <field name="partner_id" ref="base.partner_demo"/> + <field name="res_id" ref="project.project_task_3"/> + </record> + <record id="rating_task_2" model="rating.rating"> + <field name="res_model_id" ref="project.model_project_task"/> + <field name="rated_partner_id" ref="base.partner_demo"/> + <field name="partner_id" ref="base.partner_demo"/> + <field name="res_id" ref="project.project_task_8"/> + </record> + <record id="rating_task_3" model="rating.rating"> + <field name="res_model_id" ref="project.model_project_task"/> + <field name="rated_partner_id" ref="base.partner_root"/> + <field name="partner_id" ref="base.partner_root"/> + <field name="res_id" ref="project.project_task_15"/> + </record> + <record id="rating_task_4" model="rating.rating"> + <field name="res_model_id" ref="project.model_project_task"/> + <field name="rated_partner_id" ref="base.partner_root"/> + <field name="partner_id" ref="base.partner_root"/> + <field name="res_id" ref="project.project_task_18"/> + </record> + <record id="rating_task_5" model="rating.rating"> + <field name="res_model_id" ref="project.model_project_task"/> + <field name="rated_partner_id" ref="base.partner_root"/> + <field name="partner_id" ref="base.res_partner_4"/> + <field name="res_id" ref="project.project_task_24"/> + </record> + + <!-- add the email template as value for the project stage 2 --> + <record id="project.project_stage_2" model="project.task.type"> + <field name="rating_template_id" ref="rating_project_request_email_template"/> + </record> + <record id="project.project_project_3" model="project.project"> + <field name="rating_status">stage</field> + </record> + + <function model="project.task" name="rating_apply" eval="([ref('project.project_task_3')], 10)"/> + <function model="project.task" name="rating_apply" eval="([ref('project.project_task_18')], 10)"/> + <function model="project.task" name="rating_apply" eval="([ref('project.project_task_24')], 10)"/> + <function model="project.task" name="rating_apply" eval="([ref('project.project_task_8')], 1)"/> + <function model="project.task" name="rating_apply" eval="([ref('project.project_task_15')], 5)"/> </data> </odoo> diff --git a/addons/project/data/project_mail_template_data.xml b/addons/project/data/project_mail_template_data.xml index d33aabf2cd3..808c7d570d6 100644 --- a/addons/project/data/project_mail_template_data.xml +++ b/addons/project/data/project_mail_template_data.xml @@ -109,8 +109,91 @@ <function id="mail_template_function_module_install_project" - model="mail.template" + model="mail.template" name="send_mail" eval="[ref('mail_template_data_module_install_project'), ref('base.module_project')]"/> + + <!-- Mail sent to request a rating for a task --> + <record id="rating_project_request_email_template" model="mail.template"> + <field name="name">Task: Rating Request</field> + <field name="email_from">${object.rating_get_rated_partner_id().email or '' | safe}</field> + <field name="subject">${object.project_id.company_id.name}: Service Rating Request</field> + <field name="model_id" ref="project.model_project_task"/> + <field name="partner_to" >${object.rating_get_partner_id().id}</field> + <field name="auto_delete" eval="True"/> + <field name="body_html"><![CDATA[ +<div style="background:#F0F0F0;color:#515166;padding:10px 0px;font-family:Arial,Helvetica,sans-serif;font-size:14px;"> + % set access_token = object.rating_get_access_token() + <table style="width:600px;margin:5px auto;"> + <tbody> + <tr><td> + <a href="/"><img src="/web/binary/company_logo" style="vertical-align:baseline;max-width:100px;" /></a> + </td><td style="text-align:right;vertical-align:middle;"> + Satisfaction Survey + </td></tr> + </tbody> + </table> + <table style="width:600px;margin:0px auto;background:white;border:1px solid #e1e1e1;"> + <tbody> + <tr><td style="padding:15px 20px 10px 20px;"> + <p>Hello,</p> + <p>Please take a moment to rate our services related to the task "<strong>${object.name}</strong>" + assigned to <strong>${object.rating_get_rated_partner_id().name}</strong>.</p> + <p>We appreciate your feedback. It helps us to improve continuously.</p> + </td></tr> + <tr><td style="padding:10px 20px"> + <table summary="o_mail_notification" style="width:100%;border-top:1px solid #e1e1e1;"> + <tr> + <td style="text-align:center;"> + <h2 style="font-weight:300;font-size:18px;"> + Tell us how you feel about our service: + </h2> + <div style="text-color: #888888">(click on one of these smileys)</div> + </td> + </tr> + <tr> + <td style="padding:10px 10px;"> + <table style="width:100%;text-align:center;"> + <tr> + <td> + <a href="/rating/${access_token}/10"> + <img alt="Satisfied" src="/rating/static/src/img/rating_10.png" title="Satisfied"/> + </a> + </td> + <td> + <a href="/rating/${access_token}/5"> + <img alt="Not satisfied" src="/rating/static/src/img/rating_5.png" title="Not satisfied"/> + </a> + </td> + <td> + <a href="/rating/${access_token}/1"> + <img alt="Highly Dissatisfied" src="/rating/static/src/img/rating_1.png" title="Highly Dissatisfied"/> + </a> + </td> + </tr> + </table> + </td> + </tr> + </table> + </td></tr> + <tr><td style="padding:15px 20px 10px 20px;">${(object.user_id.signature or '')| safe}</td></tr> + </tbody> + </table> + <table style="width:600px;margin:auto;text-align:center;font-size:12px;"> + <tbody> + <tr><td style="padding-top:10px;color:#afafaf;"> + % if object.project_id.rating_status == 'stage': + <p>This customer survey has been sent because your task has been moved to the stage <b>${object.stage_id.name}</b></p> + % endif + % if object.project_id.rating_status == 'periodic': + <p>This customer survey is sent <b>${object.project_id.rating_status_period}</b> as long as the task is in the <b>${object.stage_id.name}</b> stage.</p> + % endif + <p>Email automatically sent by <a target="_blank" href="https://www.odoo.com/page/project-management" style="color:#875A7B;text-decoration:none;">Odoo Project</a> for <a href="${object.project_id.company_id.website}" style="color:#875A7B;text-decoration:none;">${object.project_id.company_id.name}</a></p> + </td></tr> + </tbody> + </table> +</div> +]]></field> + </record> </data> </odoo> diff --git a/addons/project/models/project.py b/addons/project/models/project.py index 2bb472fa2c3..4f5d68b0aea 100644 --- a/addons/project/models/project.py +++ b/addons/project/models/project.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. +from datetime import timedelta from lxml import etree from odoo import api, fields, models, tools, SUPERUSER_ID, _ @@ -41,6 +42,15 @@ class ProjectTaskType(models.Model): help="If set an email will be sent to the customer when the task or issue reaches this step.") fold = fields.Boolean(string='Folded in Kanban', help='This stage is folded in the kanban view when there are no records in that stage to display.') + rating_template_id = fields.Many2one( + 'mail.template', + string='Rating Email Template', + domain=[('model', '=', 'project.task')], + help="If set and if the project's rating configuration is 'Rating when changing stage', then an email will be sent to the customer when the task reaches this step.") + auto_validation_kanban_state = fields.Boolean('Automatic kanban status', default=False, + help="Automatically modify the kanban state when the customer replies to the feedback for this stage.\n" + " * A good feedback from the customer will update the kanban state to 'ready for the new stage' (green bullet).\n" + " * A medium or a bad feedback will set the kanban state to 'blocked' (red bullet).\n") class Project(models.Model): @@ -214,6 +224,20 @@ class Project(models.Model): date = fields.Date(string='Expiration Date', index=True, track_visibility='onchange') subtask_project_id = fields.Many2one('project.project', string='Sub-task Project', ondelete="restrict", help="Choosing a sub-tasks project will both enable sub-tasks and set their default project (possibly the project itself)") + # rating fields + percentage_satisfaction_task = fields.Integer( + compute='_compute_percentage_satisfaction_task', string="Happy % on Task", store=True, default=-1) + percentage_satisfaction_project = fields.Integer( + compute="_compute_percentage_satisfaction_project", string="Happy % on Project", store=True, default=-1) + rating_request_deadline = fields.Datetime(compute='_compute_rating_request_deadline', store=True) + rating_status = fields.Selection([('stage', 'Rating when changing stage'), ('periodic', 'Periodical Rating'), ('no','No rating')], 'Customer(s) Ratings', help="How to get the customer's feedbacks?\n" + "- Rating when changing stage: Email will be sent when a task/issue is pulled in another stage\n" + "- Periodical Rating: Email will be sent periodically\n\n" + "Don't forget to set up the mail templates on the stages for which you want to get the customer's feedbacks.", default="no", required=True) + rating_status_period = fields.Selection([ + ('daily', 'Daily'), ('weekly', 'Weekly'), ('bimonthly', 'Twice a Month'), + ('monthly', 'Once a Month'), ('quarterly', 'Quarterly'), ('yearly', 'Yearly') + ], 'Rating Frequency') _sql_constraints = [ ('project_date_greater', 'check(date >= date_start)', 'Error! project start-date must be lower than project end-date.') @@ -224,6 +248,26 @@ class Project(models.Model): for project in self: project.portal_url = '/my/project/%s' % project.id + @api.depends('percentage_satisfaction_task') + def _compute_percentage_satisfaction_project(self): + domain = [('create_date', '>=', fields.Datetime.to_string(fields.datetime.now() - timedelta(days=30)))] + for project in self: + activity = project.tasks.rating_get_grades(domain) + project.percentage_satisfaction_project = activity['great'] * 100 / sum(activity.values()) if sum(activity.values()) else -1 + + #TODO JEM: Only one field can be kept since project only contains task + @api.depends('tasks.rating_ids.rating') + def _compute_percentage_satisfaction_task(self): + for project in self: + activity = project.tasks.rating_get_grades() + project.percentage_satisfaction_task = activity['great'] * 100 / sum(activity.values()) if sum(activity.values()) else -1 + + @api.depends('rating_status', 'rating_status_period') + def _compute_rating_request_deadline(self): + periods = {'daily': 1, 'weekly': 7, 'bimonthly': 15, 'monthly': 30, 'quarterly': 90, 'yearly': 365} + for project in self: + project.rating_request_deadline = fields.datetime.now() + timedelta(days=periods.get(project.rating_status_period, 0)) + @api.multi def map_tasks(self, new_project_id): """ copy and map tasks from old to new project """ @@ -325,6 +369,10 @@ class Project(models.Model): return groups + # --------------------------------------------------- + # Actions + # --------------------------------------------------- + @api.multi def toggle_favorite(self): favorite_projects = not_fav_projects = self.env['project.project'].sudo() @@ -354,12 +402,33 @@ class Project(models.Model): 'context': ctx } + @api.multi + def action_view_all_rating(self): + """ return the action to see all the rating of the project, and activate default filters """ + action = self.env['ir.actions.act_window'].for_xml_id('project', 'rating_rating_action_view_project_rating') + action['name'] = _('Ratings of %s') % (self.name,) + action_context = safe_eval(action['context']) if action['context'] else {} + action_context.update(self._context) + action_context['search_default_rating_tasks'] = 1 + return dict(action, context=action_context) + + # --------------------------------------------------- + # Rating business + # --------------------------------------------------- + + # This method should be called once a day by the scheduler + @api.model + def _send_rating_all(self): + projects = self.search([('rating_status', '=', 'periodic'), ('rating_request_deadline', '<=', fields.Datetime.now())]) + projects.mapped('task_ids')._send_task_rating_mail() + projects._compute_rating_request_deadline() + class Task(models.Model): _name = "project.task" _description = "Task" _date_name = "date_start" - _inherit = ['mail.thread', 'mail.activity.mixin', 'portal.mixin'] + _inherit = ['mail.thread', 'mail.activity.mixin', 'portal.mixin', 'rating.mixin'] _mail_post_access = 'read' _order = "priority desc, sequence, date_start, name, id" @@ -656,7 +725,9 @@ class Task(models.Model): vals['date_assign'] = now result = super(Task, self).write(vals) - + # rating on stage + if 'stage_id' in vals and vals.get('stage_id'): + self.filtered(lambda x: x.project_id.rating_status == 'stage')._send_task_rating_mail(force_send=True) return result def update_date_end(self, stage_id): @@ -865,6 +936,32 @@ class Task(models.Model): 'type': 'ir.actions.act_window' } + # --------------------------------------------------- + # Rating business + # --------------------------------------------------- + + def _send_task_rating_mail(self, force_send=False): + for task in self: + rating_template = task.stage_id.rating_template_id + if rating_template: + task.rating_send_request(rating_template, lang=task.partner_id.lang, force_send=force_send) + + def rating_get_partner_id(self): + res = super(Task, self).rating_get_partner_id() + if not res and self.project_id.partner_id: + return self.project_id.partner_id + return res + + @api.multi + def rating_apply(self, rate, token=None, feedback=None, subtype=None): + return super(Task, self).rating_apply(rate, token=token, feedback=feedback, subtype="project.mt_task_rating") + + def rating_get_parent_model_name(self, vals): + return 'project.project' + + def rating_get_parent_id(self): + return self.project_id.id + class ProjectTags(models.Model): """ Tags of project's tasks """ diff --git a/addons/project/models/res_config_settings.py b/addons/project/models/res_config_settings.py index f008f52a5aa..ea1eb675904 100644 --- a/addons/project/models/res_config_settings.py +++ b/addons/project/models/res_config_settings.py @@ -8,6 +8,6 @@ class ResConfigSettings(models.TransientModel): _inherit = 'res.config.settings' module_hr_timesheet = fields.Boolean("Timesheets") - module_rating_project = fields.Boolean(string="Rating on Tasks") module_project_forecast = fields.Boolean(string="Forecasts") group_subtask_project = fields.Boolean("Sub-tasks", implied_group="project.group_subtask_project") + group_project_rating = fields.Boolean("Use Rating on Project", implied_group='project.group_project_rating') diff --git a/addons/project/security/project_security.xml b/addons/project/security/project_security.xml index c2cfb562e56..f2f70e949f9 100644 --- a/addons/project/security/project_security.xml +++ b/addons/project/security/project_security.xml @@ -24,6 +24,11 @@ <field name="category_id" ref="base.module_category_hidden"/> </record> + <record id="group_project_rating" model="res.groups"> + <field name="name">Use Rating on Project</field> + <field name="category_id" ref="base.module_category_hidden"/> + </record> + <data noupdate="1"> <record id="base.default_user" model="res.users"> <field name="groups_id" eval="[(4,ref('project.group_project_manager'))]"/> diff --git a/addons/project/views/project_views.xml b/addons/project/views/project_views.xml index 3656f306383..a09293f80df 100644 --- a/addons/project/views/project_views.xml +++ b/addons/project/views/project_views.xml @@ -47,6 +47,8 @@ <filter string="Future Activities" name="activities_upcoming_all" domain="[('activity_ids.date_deadline', '>', context_today().strftime('%Y-%m-%d')) ]"/> + <separator/> + <filter string="Rated tasks" name="rating_task" domain="[('rating_last_value', '!=', 0.0)]" groups="project.group_project_rating"/> <group expand="0" string="Group By"> <filter string="Project" name="project" context="{'group_by':'project_id'}"/> <filter string="Task" name="task" context="{'group_by':'name'}"/> @@ -113,12 +115,18 @@ name="%(act_project_project_2_project_task_all)d" icon="fa-tasks"> <field string="Tasks" name="task_count" widget="statinfo" options="{'label_field': 'label_tasks'}"/> </button> + <button name="action_view_all_rating" type="object" attrs="{'invisible': ['|', '|', ('rating_status', '=', 'no'), ('percentage_satisfaction_task', '=', -1)]}" class="oe_stat_button oe_percent" icon="fa-smile-o" groups="project.group_project_rating"> + <field string="% On tasks" name="percentage_satisfaction_task" widget="statinfo"/> + </button> <button name="toggle_active" type="object" confirm="(Un)archiving a project automatically (un)archives its tasks and issues. Do you want to proceed?" class="oe_stat_button" icon="fa-archive"> <field name="active" widget="boolean_button" options='{"terminology": "archive"}'/> </button> + <button name="%(project.rating_rating_action_view_project_rating_task)d" attrs="{'invisible': ['|', '|', ('rating_status', '=', 'no'), ('use_tasks','=', False), ('percentage_satisfaction_task', '=', -1)]}" class="oe_stat_button oe_percent" type="action" icon="fa-smile-o" groups="project.group_project_rating"> + <field string="% On tasks" name="percentage_satisfaction_task" widget="statinfo"/> + </button> </div> <div class="oe_title"> <h1> @@ -139,6 +147,14 @@ <field name="subtask_project_id" groups="project.group_subtask_project"/> <field name="privacy_visibility" widget="radio"/> <field name="partner_id" string="Customer"/> + <label for="rating_status" groups="project.group_project_rating"/> + <div groups="project.group_project_rating"> + <field name="rating_status" widget="radio"/> + <p attrs="{'invisible': [('rating_status','not in',('periodic','stage'))]}" class="text-muted oe_edit_only"> + Edit project's stages and set an email template on the stages on which you want to activate the rating. + </p> + </div> + <field name="rating_status_period" class="oe_inline" attrs="{'required': [('rating_status','=','periodic')], 'invisible': [('rating_status','!=','periodic')]}" groups="project.group_project_rating"/> </group> <group name="misc"> <group string="Configuration" groups="base.group_no_one"> @@ -286,6 +302,9 @@ <field name="alias_id"/> <field name="alias_name"/> <field name="alias_domain"/> + <field name="is_favorite"/> + <field name="percentage_satisfaction_project"/> + <field name="rating_status"/> <templates> <t t-name="kanban-box"> <div t-attf-class="#{kanban_color(record.color.raw_value)} oe_kanban_global_click o_has_icon"> @@ -301,6 +320,18 @@ <div t-if="record.alias_name.value and record.alias_domain.value"> <span><i class="fa fa-envelope"></i> <t t-esc="record.alias_id.value"/></span> </div> + <div t-if="record.rating_status.raw_value != 'no'" class="mt8 text-primary" title="Percentage of happy ratings over the past 30 days. Get rating details from the More menu."> + <b> + <t t-if="record.percentage_satisfaction_project.value == -1"> + <i class="fa fa-smile-o"/> No rating yet + </t> + <t t-if="record.percentage_satisfaction_project.value != -1"> + <a name="action_view_all_rating" type="object" context="{'search_default_rating_last_30_days':1}"> + <i class="fa fa-smile-o"/> <t t-esc="record.percentage_satisfaction_project.value"/>% + </a> + </t> + </b> + </div> </div> </div> <div class="o_kanban_card_manage_pane" groups="project.group_project_manager"> @@ -308,6 +339,9 @@ <div> <a type="edit">Edit</a> </div> + <div t-if="record.rating_status.raw_value != 'no'"> + <a name="action_view_all_rating" type="object">Customer Ratings</a> + </div> </div> <div class="o_project_kanban_colorpicker"> <ul class="oe_kanban_colorpicker" data-field="color"/> @@ -401,6 +435,9 @@ context="{'project_id': subtask_project_id, 'name': name, 'partner_id': partner_id}" groups="project.group_subtask_project"> <field string="Sub-tasks" name="subtask_count" widget="statinfo"/> </button> + <button name="%(rating_rating_action_task)d" type="action" attrs="{'invisible': [('rating_count', '=', 0)]}" class="oe_stat_button" icon="fa-smile-o" groups="project.group_project_rating"> + <field name="rating_count" string="Rating" widget="statinfo"/> + </button> <button name="toggle_active" type="object" groups="base.group_user" class="oe_stat_button" icon="fa-archive"> <field name="active" widget="boolean_button" @@ -496,6 +533,8 @@ <field name="legend_done"/> <field name="activity_ids"/> <field name="activity_state"/> + <field name="rating_last_value"/> + <field name="rating_ids"/> <progressbar field="kanban_state" colors='{"done": "success", "blocked": "danger"}'/> <templates> <t t-name="kanban-box"> @@ -540,6 +579,11 @@ <t t-if="record.message_needaction_counter.raw_value"> <span class='oe_kanban_mail_new' title='Unread Messages'><i class='fa fa-comments'/><t t-raw="record.message_needaction_counter.raw_value"/></span> </t> + <b t-if="record.rating_ids.raw_value.length"> + <span style="font-weight:bold;" class="fa fa-fw mt4 fa-smile-o text-success" t-if="record.rating_last_value.value == 10" title="Latest Rating: Satisfied"/> + <span style="font-weight:bold;" class="fa fa-fw mt4 fa-meh-o text-warning" t-if="record.rating_last_value.value == 5" title="Latest Rating: Not Satisfied"/> + <span style="font-weight:bold;" class="fa fa-fw mt4 fa-frown-o text-danger" t-if="record.rating_last_value.value == 1" title="Latest Rating: Higly Dissatisfied"/> + </b> </div> <div class="oe_kanban_bottom_right"> <field name="kanban_state" widget="state_selection" groups="base.group_user"/> @@ -741,6 +785,8 @@ <group> <field name="name"/> <field name="mail_template_id"/> + <field name="rating_template_id" groups="project.group_project_rating"/> + <field name="auto_validation_kanban_state" attrs="{'invisible': [('rating_template_id','=', False)]}" groups="project.group_project_rating"/> </group> <group> <field name="fold"/> @@ -891,4 +937,10 @@ parent="menu_project_report" sequence="10"/> + <menuitem id="rating_rating_menu_project" + action="rating_rating_action_project_report" + parent="menu_project_report" + groups="project.group_project_rating" + sequence="40"/> + </odoo> diff --git a/addons/project/views/rating_views.xml b/addons/project/views/rating_views.xml new file mode 100644 index 00000000000..87dc95ac43f --- /dev/null +++ b/addons/project/views/rating_views.xml @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + + <record id="rating_rating_view_search_project" model="ir.ui.view"> + <field name="name">rating.rating.search.project</field> + <field name="model">rating.rating</field> + <field name="inherit_id" ref="rating.rating_rating_view_search"/> + <field name="mode">primary</field> + <field name="arch" type="xml"> + <xpath expr="//filter[@name='resource']" position="after"> + <field name="parent_res_name"/> + <filter string="Project" name="groupby_project" context="{'group_by': 'parent_res_name'}"/> + </xpath> + <xpath expr="/search" position="inside"> + <filter string="Last 30 days" name="rating_last_30_days" domain="[('create_date', '>=', (context_today()-datetime.timedelta(days=30)).strftime('%Y-%m-%d'))]"/> + <separator/> + </xpath> + </field> + </record> + + <record id="rating_rating_action_view_project_rating" model="ir.actions.act_window"> + <field name="name">Rating</field> + <field name="res_model">rating.rating</field> + <field name="view_mode">kanban,tree,graph,pivot,form</field> + <field name="domain">[('consumed','=',True), ('parent_res_model','=','project.project'), ('parent_res_id','=',active_id)]</field> + <field name="search_view_id" ref="rating_rating_view_search_project"/> + <field name="help" type="html"> + <p> + There is no rating for this object at the moment. + </p> + </field> + </record> + + <record id="rating_rating_action_view_project_rating_task" model="ir.actions.act_window"> + <field name="name">Ratings for tasks</field> + <field name="res_model">rating.rating</field> + <field name="view_mode">kanban,tree,graph,pivot,form</field> + <field name="domain">[('consumed','=',True), ('parent_res_model','=','project.project'), ('parent_res_id','=',active_id), ('res_model','=','project.task')]</field> + <field name="search_view_id" ref="rating_rating_view_search_project"/> + <field name="help" type="html"> + <p> + There is no rating for tasks of this project at the moment. + </p> + </field> + </record> + + <record id="rating_rating_action_task" model="ir.actions.act_window"> + <field name="name">Customer Ratings</field> + <field name="res_model">rating.rating</field> + <field name="view_mode">kanban,tree,pivot,graph,form</field> + <field name="domain">[('res_model', '=', 'project.task'), ('res_id', '=', active_id), ('consumed', '=', True)]</field> + <field name="search_view_id" ref="rating_rating_view_search_project"/> + <field name="help" type="html"> + <p> + Customer ratings on tasks. If you have no rating, change your project Settings to activate it. + </p> + </field> + </record> + + <record id="rating_rating_action_project_report" model="ir.actions.act_window"> + <field name="name">Customer Ratings</field> + <field name="res_model">rating.rating</field> + <field name="view_mode">kanban,tree,pivot,graph,form</field> + <field name="domain">[('parent_res_model','=','project.project'), ('consumed', '=', True)]</field> + <field name="search_view_id" ref="rating_rating_view_search_project"/> + <field name="help" type="html"> + <p> + Customer ratings on tasks. If you have no rating, change your project Settings to activate it. + </p> + </field> + <field name="context">{}</field> + </record> + +</odoo> diff --git a/addons/project/views/res_config_settings_views.xml b/addons/project/views/res_config_settings_views.xml index 9914fe6b525..030b9090445 100644 --- a/addons/project/views/res_config_settings_views.xml +++ b/addons/project/views/res_config_settings_views.xml @@ -34,14 +34,18 @@ </div> <div class="col-xs-12 col-md-6 o_setting_box"> <div class="o_setting_left_pane"> - <field name="module_rating_project"/> + <field name="group_project_rating"/> </div> <div class="o_setting_right_pane"> - <label for="module_rating_project"/> + <label for="group_project_rating"/> <div class="text-muted"> Track customer satisfaction on tasks </div> - <div class="content-group" id="msg_module_rating_project"/> + <div class="content-group" attrs="{'invisible': [('group_project_rating', '=', False)]}"> + <div class="mt16"> + <button name="%(project.open_task_type_form)d" icon="fa-arrow-right" type="action" string="Set Email Template to Stages" class="btn-link"/> + </div> + </div> </div> </div> </div> |
