[MERGE][IMP] mail: fine-tune new plan feature
We do the following improvement: - some wording changes - the activity templates can be edited directly in the list view instead of in a popup except in hr because sub module add too many field to be edited in directly in the list view. - when scheduling a plan, the due date of the created activities are computed as the plan_date_deadline + activity type delay and if the plan_date_deadline is not specified, as today + activity type delay. - there were 2 res_model fields in the mail_activity_plan_view_form that was causing a selection box to appears on many form where the model shouldn't be selectable. We remove one of them here. Add activity plan menus and configuration to sale, project. Re-add the launch plan button in HR. When generalizing the plan, we have removed the custom "launch plan" button in the hr module. We re-add it here. Task-3558929 closes odoo/odoo#138998 Related: odoo/enterprise#49414 Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
@@ -129,7 +129,7 @@
|
||||
sequence="10"/>
|
||||
<menuitem
|
||||
id="mail_activity_plan_menu_config_lead"
|
||||
name="Activity Plan"
|
||||
name="Activity Plans"
|
||||
parent="crm_menu_config"
|
||||
action="mail_activity_plan_action_lead"
|
||||
groups="sales_team.group_sale_manager"
|
||||
|
||||
@@ -461,6 +461,11 @@ msgid ""
|
||||
" you will have solid solving problem skills."
|
||||
msgstr ""
|
||||
|
||||
#. module: hr
|
||||
#: model:ir.model.fields,field_description:hr.field_mail_activity_plan_template__responsible_type
|
||||
msgid "Assignment"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr
|
||||
#: model:ir.model.fields,field_description:hr.field_hr_department__message_attachment_count
|
||||
#: model:ir.model.fields,field_description:hr.field_hr_employee__message_attachment_count
|
||||
@@ -1759,6 +1764,8 @@ msgstr ""
|
||||
|
||||
#. module: hr
|
||||
#: model:ir.actions.act_window,name:hr.plan_wizard_action
|
||||
#: model_terms:ir.ui.view,arch_db:hr.view_employee_form
|
||||
#: model_terms:ir.ui.view,arch_db:hr.view_employee_tree
|
||||
msgid "Launch Plan"
|
||||
msgstr ""
|
||||
|
||||
@@ -2640,11 +2647,6 @@ msgstr ""
|
||||
msgid "Responsibilities"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr
|
||||
#: model:ir.model.fields,field_description:hr.field_mail_activity_plan_template__responsible_type
|
||||
msgid "Responsible"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr
|
||||
#: model:ir.model.fields,field_description:hr.field_hr_employee__activity_user_id
|
||||
msgid "Responsible User"
|
||||
|
||||
@@ -196,8 +196,8 @@ class TestActivitySchedule(ActivityScheduleHRCase):
|
||||
form = self._instantiate_activity_schedule_wizard(employees)
|
||||
form.plan_id = self.plan_onboarding
|
||||
self.assertEqual(form.plan_assignation_summary,
|
||||
'<ul><li>To-Do - Manager: Plan training</li><li>To-Do - Coach: Training</li>'
|
||||
'<li>To-Do - Employee: Send feedback to the manager</li></ul>')
|
||||
'<ul><li>To-Do: Plan training</li><li>To-Do: Training</li>'
|
||||
'<li>To-Do: Send feedback to the manager</li></ul>')
|
||||
self.assertFalse(form.has_error)
|
||||
wizard = form.save()
|
||||
wizard.action_schedule_plan()
|
||||
|
||||
@@ -57,7 +57,9 @@
|
||||
<field name="last_activity_time" invisible="1"/>
|
||||
<field name="last_activity" invisible="1"/>
|
||||
<field name="work_contact_id" invisible="1"/>
|
||||
<header><!-- For extension --></header>
|
||||
<header>
|
||||
<button name="%(plan_wizard_action)d" string="Launch Plan" type="action" groups="hr.group_hr_user" invisible="not active"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<div name="button_box" class="oe_button_box">
|
||||
</div>
|
||||
@@ -241,6 +243,9 @@
|
||||
<field name="model">hr.employee</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Employees" expand="context.get('expand', False)" multi_edit="1" sample="1" js_class="hr_employee_list">
|
||||
<header>
|
||||
<button name="%(plan_wizard_action)d" string="Launch Plan" type="action" groups="hr.group_hr_user"/>
|
||||
</header>
|
||||
<field name="name" readonly="1"/>
|
||||
<field name="work_phone" class="o_force_ltr" readonly="1" optional="show"/>
|
||||
<field name="work_email"/>
|
||||
|
||||
@@ -21,11 +21,28 @@
|
||||
<field name="model">mail.activity.plan</field>
|
||||
<field name="inherit_id" ref="mail.mail_activity_plan_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='template_ids']/tree/field[@name='responsible_type']" position="replace">
|
||||
<!-- We can hide selection options specific to employee because employee plan templates are never
|
||||
edited in the list view, so that there are not present for other model that are edited in the
|
||||
list view. -->
|
||||
<field name="responsible_type" widget="filterable_selection"
|
||||
options="{'whitelisted_values': ['on_demand', 'other']}"/>
|
||||
</xpath>
|
||||
<xpath expr="//group[@name='group_plan_fields']" position="inside">
|
||||
<field name="department_id" invisible="res_model != 'hr.employee'"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='res_model']" position="attributes">
|
||||
<attribute name="invisible">res_model == 'hr.employee'</attribute>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="mail_activity_plan_view_form_hr_employee" model="ir.ui.view">
|
||||
<field name="name">mail.activity.plan.view.form.hr.employee</field>
|
||||
<field name="mode">primary</field>
|
||||
<field name="model">mail.activity.plan</field>
|
||||
<field name="priority">32</field>
|
||||
<field name="inherit_id" ref="mail.mail_activity_plan_view_form_fixed_model"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//tree" position="attributes">
|
||||
<attribute name="editable"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
@@ -55,6 +72,21 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="mail_activity_plan_action_employee_view_tree" model="ir.actions.act_window.view">
|
||||
<field name="sequence">1</field>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="mail.mail_activity_plan_view_tree"/>
|
||||
<field name="act_window_id" ref="hr.mail_activity_plan_action"/>
|
||||
</record>
|
||||
|
||||
<!-- Force the hr view which do the activity template edition in a popup. -->
|
||||
<record id="mail_activity_plan_action_employee_view_form" model="ir.actions.act_window.view">
|
||||
<field name="sequence">2</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="hr.mail_activity_plan_view_form_hr_employee"/>
|
||||
<field name="act_window_id" ref="hr.mail_activity_plan_action"/>
|
||||
</record>
|
||||
|
||||
<!-- This id is referenced in chatter message as a link to launch the plan -->
|
||||
<record id="plan_wizard_action" model="ir.actions.act_window">
|
||||
<field name="name">Launch Plan</field>
|
||||
|
||||
@@ -44,7 +44,7 @@ class TestActivitySchedule(ActivityScheduleHRCase):
|
||||
form = self._instantiate_activity_schedule_wizard(employees)
|
||||
form.plan_id = self.plan_fleet
|
||||
self.assertEqual(form.plan_assignation_summary,
|
||||
'<ul><li>To-Do - Fleet Manager: Car return</li></ul>')
|
||||
'<ul><li>To-Do: Car return</li></ul>')
|
||||
self.assertFalse(form.has_error)
|
||||
wizard = form.save()
|
||||
wizard.action_schedule_plan()
|
||||
|
||||
+31
-29
@@ -1199,6 +1199,11 @@ msgstr ""
|
||||
msgid "Are you sure you want to unblacklist this Email Address?"
|
||||
msgstr ""
|
||||
|
||||
#. module: mail
|
||||
#: model:ir.model.fields.selection,name:mail.selection__mail_activity_plan_template__responsible_type__on_demand
|
||||
msgid "Ask at launch"
|
||||
msgstr ""
|
||||
|
||||
#. module: mail
|
||||
#. odoo-javascript
|
||||
#: code:addons/mail/static/src/views/web/fields/assign_user_command_hook.js:0
|
||||
@@ -1213,22 +1218,16 @@ msgstr ""
|
||||
msgid "Assign to me"
|
||||
msgstr ""
|
||||
|
||||
#. module: mail
|
||||
#: model:ir.model.fields,field_description:mail.field_mail_activity_plan__assignation_summary
|
||||
#: model:ir.model.fields,field_description:mail.field_mail_activity_schedule__plan_assignation_summary
|
||||
#: model_terms:ir.ui.view,arch_db:mail.mail_activity_schedule_view_form
|
||||
msgid "Assignation summary"
|
||||
msgstr ""
|
||||
|
||||
#. module: mail
|
||||
#: model:ir.model.fields,field_description:mail.field_mail_activity_schedule__plan_on_demand_user_id
|
||||
msgid "Assigned To (On demand)"
|
||||
msgid "Assigned To"
|
||||
msgstr ""
|
||||
|
||||
#. module: mail
|
||||
#. odoo-javascript
|
||||
#: code:addons/mail/static/src/core/web/activity.xml:0
|
||||
#: model:ir.model.fields,field_description:mail.field_mail_activity__user_id
|
||||
#: model:ir.model.fields,field_description:mail.field_mail_activity_plan_template__responsible_id
|
||||
#: model:ir.model.fields,field_description:mail.field_mail_activity_schedule__activity_user_id
|
||||
#, python-format
|
||||
msgid "Assigned to"
|
||||
@@ -1244,6 +1243,11 @@ msgid ""
|
||||
"this activity."
|
||||
msgstr ""
|
||||
|
||||
#. module: mail
|
||||
#: model:ir.model.fields,field_description:mail.field_mail_activity_plan_template__responsible_type
|
||||
msgid "Assignment"
|
||||
msgstr ""
|
||||
|
||||
#. module: mail
|
||||
#. odoo-python
|
||||
#: code:addons/mail/models/mail_thread.py:0
|
||||
@@ -2611,6 +2615,11 @@ msgid ""
|
||||
"- email (using email_from or email field)"
|
||||
msgstr ""
|
||||
|
||||
#. module: mail
|
||||
#: model:ir.model.fields.selection,name:mail.selection__mail_activity_plan_template__responsible_type__other
|
||||
msgid "Default user"
|
||||
msgstr ""
|
||||
|
||||
#. module: mail
|
||||
#: model:ir.model.fields,help:mail.field_fetchmail_server__priority
|
||||
msgid "Defines the order of processing, lower values mean higher priority"
|
||||
@@ -6408,10 +6417,6 @@ msgstr ""
|
||||
msgid "Old values"
|
||||
msgstr ""
|
||||
|
||||
#. module: mail
|
||||
#: model:ir.model.fields.selection,name:mail.selection__mail_activity_plan_template__responsible_type__on_demand
|
||||
msgid "On demand"
|
||||
msgstr ""
|
||||
|
||||
#. module: mail
|
||||
#. odoo-javascript
|
||||
@@ -6581,16 +6586,6 @@ msgstr ""
|
||||
msgid "Original message was deleted"
|
||||
msgstr ""
|
||||
|
||||
#. module: mail
|
||||
#: model:ir.model.fields.selection,name:mail.selection__mail_activity_plan_template__responsible_type__other
|
||||
msgid "Other"
|
||||
msgstr ""
|
||||
|
||||
#. module: mail
|
||||
#: model:ir.model.fields,field_description:mail.field_mail_activity_plan_template__responsible_id
|
||||
msgid "Other Responsible"
|
||||
msgstr ""
|
||||
|
||||
#. module: mail
|
||||
#: model:ir.model.fields.selection,name:mail.selection__mail_mail__state__outgoing
|
||||
#: model_terms:ir.ui.view,arch_db:mail.view_mail_search
|
||||
@@ -6878,7 +6873,7 @@ msgstr ""
|
||||
|
||||
#. module: mail
|
||||
#: model:ir.model.fields,field_description:mail.field_mail_activity_schedule__plan_date_deadline
|
||||
msgid "Plan Due Date"
|
||||
msgid "Plan Date"
|
||||
msgstr ""
|
||||
|
||||
#. module: mail
|
||||
@@ -6886,6 +6881,17 @@ msgstr ""
|
||||
msgid "Plan Name"
|
||||
msgstr ""
|
||||
|
||||
#. module: mail
|
||||
#: model:ir.model.fields,field_description:mail.field_mail_activity_plan__assignation_summary
|
||||
#: model:ir.model.fields,field_description:mail.field_mail_activity_schedule__plan_assignation_summary
|
||||
msgid "Plan Summary"
|
||||
msgstr ""
|
||||
|
||||
#. module: mail
|
||||
#: model_terms:ir.ui.view,arch_db:mail.mail_activity_schedule_view_form
|
||||
msgid "Plan summary"
|
||||
msgstr ""
|
||||
|
||||
#. module: mail
|
||||
#. odoo-javascript
|
||||
#: code:addons/mail/static/src/core/web/activity_list_popover.xml:0
|
||||
@@ -7598,7 +7604,6 @@ msgstr ""
|
||||
#. module: mail
|
||||
#: model:ir.model.fields,field_description:mail.field_ir_actions_server__activity_user_id
|
||||
#: model:ir.model.fields,field_description:mail.field_ir_cron__activity_user_id
|
||||
#: model:ir.model.fields,field_description:mail.field_mail_activity_plan_template__responsible_type
|
||||
#: model:ir.model.fields,field_description:mail.field_mail_compose_message__res_domain_user_id
|
||||
msgid "Responsible"
|
||||
msgstr ""
|
||||
@@ -8344,10 +8349,6 @@ msgstr ""
|
||||
msgid "Specific User"
|
||||
msgstr ""
|
||||
|
||||
#. module: mail
|
||||
#: model:ir.model.fields,help:mail.field_mail_activity_plan_template__responsible_id
|
||||
msgid "Specific responsible of activity if not linked to the employee."
|
||||
msgstr ""
|
||||
|
||||
#. module: mail
|
||||
#: model:ir.model.fields,help:mail.field_mail_activity_plan__res_model
|
||||
@@ -10008,7 +10009,8 @@ msgstr ""
|
||||
#. odoo-python
|
||||
#: code:addons/mail/models/mail_activity_plan_template.py:0
|
||||
#, python-format
|
||||
msgid "When selecting responsible \"other\", you must specify a responsible."
|
||||
msgid ""
|
||||
"When selecting \"Default user\" assignment, you must specify a responsible."
|
||||
msgstr ""
|
||||
|
||||
#. module: mail
|
||||
|
||||
@@ -185,12 +185,26 @@ class MailActivity(models.Model):
|
||||
self.note = self.activity_type_id.default_note
|
||||
|
||||
@api.model
|
||||
def _calculate_date_deadline(self, activity_type):
|
||||
# Date.context_today is correct because date_deadline is a Date and is meant to be
|
||||
# expressed in user TZ
|
||||
base = fields.Date.context_today(self)
|
||||
if activity_type.delay_from == 'previous_activity' and 'activity_previous_deadline' in self.env.context:
|
||||
def _calculate_date_deadline(self, activity_type, force_base_date=None):
|
||||
""" Compute the activity deadline given its type, the force_base_date and the context.
|
||||
|
||||
The deadline is computed by adding the activity type delay to a base date defined as:
|
||||
- the force_base_date
|
||||
- or the activity_previous_deadline context value if the activity type delay_from is
|
||||
previous_activity
|
||||
- or the current date
|
||||
|
||||
:param activity_type: activity type
|
||||
:param date force_base_date: if set, this force the base date for computation
|
||||
"""
|
||||
if force_base_date:
|
||||
# Date.context_today is correct because date_deadline is a Date and is meant to be
|
||||
# expressed in user TZ
|
||||
base = force_base_date
|
||||
elif activity_type.delay_from == 'previous_activity' and 'activity_previous_deadline' in self.env.context:
|
||||
base = fields.Date.from_string(self.env.context.get('activity_previous_deadline'))
|
||||
else:
|
||||
base = fields.Date.context_today(self)
|
||||
return base + relativedelta(**{activity_type.delay_unit: activity_type.delay_count})
|
||||
|
||||
@api.onchange('recommended_activity_type_id')
|
||||
|
||||
@@ -33,7 +33,7 @@ class MailActivityPlan(models.Model):
|
||||
help='Specify a model if the activity should be specific to a model'
|
||||
' and not available when managing activities for other models.')
|
||||
steps_count = fields.Integer(compute='_compute_steps_count')
|
||||
assignation_summary = fields.Html('Assignation summary', compute='_compute_assignation')
|
||||
assignation_summary = fields.Html('Plan Summary', compute='_compute_assignation_summary')
|
||||
has_user_on_demand = fields.Boolean('Has on demand responsible', compute='_compute_has_user_on_demand')
|
||||
|
||||
@api.depends('res_model')
|
||||
@@ -51,13 +51,11 @@ class MailActivityPlan(models.Model):
|
||||
plan.steps_count = len(plan.template_ids)
|
||||
|
||||
@api.depends('template_ids.summary')
|
||||
def _compute_assignation(self):
|
||||
def _compute_assignation_summary(self):
|
||||
self.assignation_summary = ''
|
||||
for plan in self.filtered('template_ids'):
|
||||
resp_description = dict(self.env['mail.activity.plan.template']._fields['responsible_type']._description_selection(self.env))
|
||||
summaries = [
|
||||
f"{template.activity_type_id.name} - {resp_description[template.responsible_type]}" +
|
||||
(f": {template.summary}" if template.summary else '')
|
||||
template.activity_type_id.name + (f": {template.summary}" if template.summary else '')
|
||||
for template in plan.template_ids
|
||||
]
|
||||
if summaries:
|
||||
|
||||
@@ -25,14 +25,13 @@ class MailActivityPlanTemplate(models.Model):
|
||||
)
|
||||
summary = fields.Char('Summary', compute="_compute_summary", store=True, readonly=False)
|
||||
responsible_type = fields.Selection([
|
||||
('on_demand', 'On demand'),
|
||||
('other', 'Other'),
|
||||
], default='on_demand', string='Responsible', required=True)
|
||||
('on_demand', 'Ask at launch'),
|
||||
('other', 'Default user'),
|
||||
], default='on_demand', string='Assignment', required=True)
|
||||
responsible_id = fields.Many2one(
|
||||
'res.users',
|
||||
'Other Responsible',
|
||||
check_company=True, store=True, compute="_compute_responsible_id", readonly=False,
|
||||
help='Specific responsible of activity if not linked to the employee.')
|
||||
'Assigned to',
|
||||
check_company=True, store=True, compute="_compute_responsible_id", readonly=False)
|
||||
note = fields.Html('Note')
|
||||
|
||||
@api.constrains('activity_type_id', 'plan_id')
|
||||
@@ -58,7 +57,7 @@ class MailActivityPlanTemplate(models.Model):
|
||||
""" Ensure that responsible_id is set when responsible is set to "other". """
|
||||
for template in self:
|
||||
if template.responsible_type == 'other' and not template.responsible_id:
|
||||
raise ValidationError(_('When selecting responsible "other", you must specify a responsible.'))
|
||||
raise ValidationError(_('When selecting "Default user" assignment, you must specify a responsible.'))
|
||||
|
||||
@api.depends('activity_type_id')
|
||||
def _compute_summary(self):
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from contextlib import contextmanager
|
||||
from datetime import timedelta
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from unittest.mock import patch
|
||||
|
||||
from odoo import fields
|
||||
@@ -66,13 +66,13 @@ class ActivityScheduleCase(MailCommon):
|
||||
self.assertIn(activity_type.name, last_message.body)
|
||||
self.assertIn('done', last_message.body)
|
||||
|
||||
def assertActivitiesFromPlan(self, plan, record, force_date_deadline=None, force_responsible_id=None):
|
||||
def assertActivitiesFromPlan(self, plan, record, force_base_date_deadline=None, force_responsible_id=None):
|
||||
""" Check that the last activities on the record correspond to the one
|
||||
that the plan must create (number of activities and activities content).
|
||||
|
||||
:param <mail.activity.plan> plan: activity plan that has been applied on the record
|
||||
:param recordset record: record on which the plan has been applied
|
||||
:param date force_date_deadline: deadline provided when scheduling the plan
|
||||
:param date force_base_date_deadline: base plan date provided when scheduling the plan
|
||||
:param <res.user> force_responsible_id: responsible provided when scheduling the plan
|
||||
"""
|
||||
expected_number_of_activity = len(plan.template_ids)
|
||||
@@ -83,10 +83,10 @@ class ActivityScheduleCase(MailCommon):
|
||||
|
||||
for activity, template in zip(activities, plan.template_ids):
|
||||
self.assertEqual(activity.activity_type_id, template.activity_type_id)
|
||||
if force_date_deadline:
|
||||
self.assertEqual(activity.date_deadline, force_date_deadline)
|
||||
else:
|
||||
self.assertEqual(activity.date_deadline, fields.Date.today() + timedelta(days=template.activity_type_id.delay_count))
|
||||
self.assertEqual(
|
||||
activity.date_deadline,
|
||||
(force_base_date_deadline or fields.Date.today()) + relativedelta(
|
||||
**{template.activity_type_id.delay_unit: template.activity_type_id.delay_count}))
|
||||
self.assertEqual(activity.note, template.note)
|
||||
self.assertEqual(activity.summary, template.summary)
|
||||
if force_responsible_id:
|
||||
@@ -94,23 +94,21 @@ class ActivityScheduleCase(MailCommon):
|
||||
else:
|
||||
self.assertEqual(activity.user_id, template.responsible_id or self.env.user)
|
||||
|
||||
def assertMessagesFromPlan(self, plan, record, force_date_deadline=None, force_responsible_id=None):
|
||||
def assertMessagesFromPlan(self, plan, record, force_base_date_deadline=None, force_responsible_id=None):
|
||||
""" Check that the last posted message on the record correspond to the one
|
||||
that the plan must generate (number of activities and activities content).
|
||||
|
||||
:param <mail.activity.plan> plan: activity plan that has been applied on the record
|
||||
:param recordset record: record on which the plan has been applied
|
||||
:param date force_date_deadline: deadline provided when scheduling the plan
|
||||
:param date force_base_date_deadline: deadline provided when scheduling the plan
|
||||
:param <res.user> force_responsible_id: responsible provided when scheduling the plan
|
||||
"""
|
||||
message = record.message_ids[0]
|
||||
self.assertIn(f'The plan "{plan.name}" has been started', message.body)
|
||||
|
||||
for template in plan.template_ids:
|
||||
if force_date_deadline:
|
||||
date_deadline = force_date_deadline
|
||||
else:
|
||||
date_deadline = fields.Date.today() + timedelta(days=template.activity_type_id.delay_count)
|
||||
date_deadline = (force_base_date_deadline or fields.Date.today()) + relativedelta(
|
||||
**{template.activity_type_id.delay_unit: template.activity_type_id.delay_count})
|
||||
if force_responsible_id:
|
||||
responsible_id = force_responsible_id
|
||||
else:
|
||||
@@ -120,19 +118,19 @@ class ActivityScheduleCase(MailCommon):
|
||||
self.assertIn(f'{template.summary or template.activity_type_id.name}, '
|
||||
f'assigned to {responsible_id.name}, due on the {date_deadline}', message.body)
|
||||
|
||||
def assertPlanExecution(self, plan, records, force_date_deadline=None, force_responsible_id=None):
|
||||
def assertPlanExecution(self, plan, records, force_base_date_deadline=None, force_responsible_id=None):
|
||||
""" Check that the plan has created the right activities and send the
|
||||
right message on the records (see assertActivitiesFromPlan and
|
||||
assertMessagesFromPlan). """
|
||||
for record in records:
|
||||
self.assertActivitiesFromPlan(
|
||||
plan, record,
|
||||
force_date_deadline=force_date_deadline,
|
||||
force_base_date_deadline=force_base_date_deadline,
|
||||
force_responsible_id=force_responsible_id,
|
||||
)
|
||||
self.assertMessagesFromPlan(
|
||||
plan, record,
|
||||
force_date_deadline=force_date_deadline,
|
||||
force_base_date_deadline=force_base_date_deadline,
|
||||
force_responsible_id=force_responsible_id,
|
||||
)
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
<field name="arch" type="xml">
|
||||
<form string="Planning">
|
||||
<field name="company_id" invisible="1"/>
|
||||
<field name="res_model" invisible="1"/>
|
||||
<field name="active" invisible="1"/>
|
||||
<sheet>
|
||||
<widget name="web_ribbon" title="Archived" bg_color="text-bg-danger" invisible="active"/>
|
||||
@@ -53,10 +52,13 @@
|
||||
<field name="template_ids" nolabel="1">
|
||||
<tree default_order="sequence, id">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="activity_type_id" context="{'form_view_ref': 'mail.mail_activity_type_form_inherit'}"/>
|
||||
<field name="activity_type_id" context="{'form_view_ref': 'mail.mail_activity_type_form_inherit'}"
|
||||
options="{'no_quick_create': True}"/>
|
||||
<field name="summary"/>
|
||||
<field name="responsible_type"/>
|
||||
<field name="responsible_id" readonly="responsible_type != 'other'" optional="hide"/>
|
||||
<field name="responsible_id" readonly="responsible_type != 'other'"/>
|
||||
<field name="note"/>
|
||||
<field name="company_id" optional="hide"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
@@ -73,7 +75,12 @@
|
||||
<field name="priority">10</field>
|
||||
<field name="inherit_id" ref="mail.mail_activity_plan_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//group[@name='plan_res_model']" position="replace"/>
|
||||
<xpath expr="//tree" position="attributes">
|
||||
<attribute name="editable">bottom</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//group[@name='plan_res_model']" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -82,12 +89,6 @@
|
||||
<field name="res_model">mail.activity.plan</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="search_view_id" ref="mail_activity_plan_view_search"/>
|
||||
<!-- Force the admin view that allows to modify the target models of the plan. -->
|
||||
<field name="view_ids"
|
||||
eval="[(5, 0, 0),
|
||||
(0, 0, {'view_mode': 'tree', 'view_id': ref('mail.mail_activity_plan_view_tree')}),
|
||||
(0, 0, {'view_mode': 'form', 'view_id': ref('mail.mail_activity_plan_view_form')}),
|
||||
]"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Add a new plan
|
||||
@@ -95,5 +96,20 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="mail_activity_plan_view_tree_action" model="ir.actions.act_window.view">
|
||||
<field name="sequence">1</field>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="mail.mail_activity_plan_view_tree"/>
|
||||
<field name="act_window_id" ref="mail.mail_activity_plan_action"/>
|
||||
</record>
|
||||
|
||||
<!-- Force the admin view that allows to modify the target models of the plan. -->
|
||||
<record id="mail_activity_plan_view_form_action" model="ir.actions.act_window.view">
|
||||
<field name="sequence">2</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="mail.mail_activity_plan_view_form"/>
|
||||
<field name="act_window_id" ref="mail.mail_activity_plan_action"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
@@ -51,11 +51,11 @@ class MailActivitySchedule(models.TransientModel):
|
||||
plan_has_user_on_demand = fields.Boolean(related="plan_id.has_user_on_demand")
|
||||
plan_assignation_summary = fields.Html(related='plan_id.assignation_summary')
|
||||
plan_on_demand_user_id = fields.Many2one(
|
||||
'res.users', 'Assigned To (On demand)',
|
||||
'res.users', 'Assigned To',
|
||||
help='Choose assignation for activities with on demand assignation.',
|
||||
default=lambda self: self.env.user)
|
||||
plan_date_deadline = fields.Date(
|
||||
'Plan Due Date', compute='_compute_plan_date_deadline',
|
||||
'Plan Date', compute='_compute_plan_date_deadline',
|
||||
store=True, readonly=False)
|
||||
# activity-based
|
||||
activity_type_id = fields.Many2one(
|
||||
@@ -212,7 +212,7 @@ class MailActivitySchedule(models.TransientModel):
|
||||
else:
|
||||
responsible = template._determine_responsible(self.plan_on_demand_user_id, record)['responsible']
|
||||
date_deadline = self.env['mail.activity']._calculate_date_deadline(
|
||||
template.activity_type_id) if not self.plan_date_deadline else self.plan_date_deadline
|
||||
template.activity_type_id, force_base_date=self.plan_date_deadline)
|
||||
record.activity_schedule(
|
||||
activity_type_id=template.activity_type_id.id,
|
||||
summary=template.summary,
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
</group>
|
||||
<group>
|
||||
<label for="plan_assignation_summary" class="o_form_label"
|
||||
string="Assignation summary" colspan="2"/>
|
||||
string="Plan summary" colspan="2"/>
|
||||
<field name="plan_assignation_summary" colspan="2" nolabel="1"/>
|
||||
</group>
|
||||
</group>
|
||||
|
||||
@@ -559,8 +559,9 @@ msgid "Activity Exception Decoration"
|
||||
msgstr ""
|
||||
|
||||
#. module: project
|
||||
#: model:ir.ui.menu,name:project.mail_activity_plan_menu_config_task
|
||||
msgid "Activity Plan"
|
||||
#: model:ir.actions.act_window,name:project.mail_activity_plan_action_config_project_task_plan
|
||||
#: model:ir.ui.menu,name:project.mail_activity_plan_menu_config_project
|
||||
msgid "Activity Plans"
|
||||
msgstr ""
|
||||
|
||||
#. module: project
|
||||
@@ -591,6 +592,7 @@ msgid "Add Milestone"
|
||||
msgstr ""
|
||||
|
||||
#. module: project
|
||||
#: model_terms:ir.actions.act_window,help:project.mail_activity_plan_action_config_project_task_plan
|
||||
#: model_terms:ir.actions.act_window,help:project.mail_activity_plan_action_config_task_plan
|
||||
msgid "Add a new plan"
|
||||
msgstr ""
|
||||
|
||||
@@ -315,18 +315,18 @@
|
||||
</record>
|
||||
|
||||
<record id="mail_plan_rule_group_project_manager_task" model="ir.rule">
|
||||
<field name="name">Manager can manage task plans</field>
|
||||
<field name="name">Manager can manage project/task plans</field>
|
||||
<field name="groups" eval="[(4, ref('group_project_manager'))]"/>
|
||||
<field name="model_id" ref="mail.model_mail_activity_plan"/>
|
||||
<field name="domain_force">[('res_model', '=', 'project.task')]</field>
|
||||
<field name="domain_force">[('res_model', 'in', ('project.project', 'project.task'))]</field>
|
||||
<field name="perm_read" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record id="mail_plan_templates_rule_group_project_manager_task" model="ir.rule">
|
||||
<field name="name">Manager can manage task plan templates</field>
|
||||
<field name="name">Manager can manage project/task plan templates</field>
|
||||
<field name="groups" eval="[(4, ref('group_project_manager'))]"/>
|
||||
<field name="model_id" ref="mail.model_mail_activity_plan_template"/>
|
||||
<field name="domain_force">[('plan_id.res_model', '=', 'project.task')]</field>
|
||||
<field name="domain_force">[('plan_id.res_model', 'in', ('project.project', 'project.task'))]</field>
|
||||
<field name="perm_read" eval="False"/>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -1,6 +1,52 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<record id="mail_activity_plan_view_form_project_and_task" model="ir.ui.view">
|
||||
<field name="name">mail.activity.plan.view.form.project.and.task</field>
|
||||
<field name="model">mail.activity.plan</field>
|
||||
<field name="mode">primary</field>
|
||||
<field name="priority">32</field>
|
||||
<field name="inherit_id" ref="mail.mail_activity_plan_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='res_model']" position="attributes">
|
||||
<attribute name="widget">filterable_selection</attribute>
|
||||
<attribute name="options">{'whitelisted_values': ['project.project', 'project.task']}</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='template_ids']/tree" position="attributes">
|
||||
<attribute name="editable">bottom</attribute>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="mail_activity_plan_action_config_project_task_plan" model="ir.actions.act_window">
|
||||
<field name="name">Activity Plans</field>
|
||||
<field name="res_model">mail.activity.plan</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="search_view_id" ref="mail.mail_activity_plan_view_search"/>
|
||||
<field name="context">{'default_res_model': 'project.task'}</field>
|
||||
<field name="domain">[('res_model', 'in', ('project.project', 'project.task'))]</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Add a new plan
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="mail_activity_plan_action_project_task_view_tree" model="ir.actions.act_window.view">
|
||||
<field name="sequence">1</field>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="mail.mail_activity_plan_view_tree"/>
|
||||
<field name="act_window_id" ref="project.mail_activity_plan_action_config_project_task_plan"/>
|
||||
</record>
|
||||
|
||||
<!-- Force the project view that allows to modify the target models of the plan to project or task. -->
|
||||
<record id="mail_activity_plan_action_project_task_view_form" model="ir.actions.act_window.view">
|
||||
<field name="sequence">2</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="project.mail_activity_plan_view_form_project_and_task"/>
|
||||
<field name="act_window_id" ref="project.mail_activity_plan_action_config_project_task_plan"/>
|
||||
</record>
|
||||
|
||||
<record id="mail_activity_plan_action_config_task_plan" model="ir.actions.act_window">
|
||||
<field name="name">Task Plans</field>
|
||||
<field name="res_model">mail.activity.plan</field>
|
||||
|
||||
@@ -109,9 +109,9 @@
|
||||
action="mail_activity_type_action_config_project_types"
|
||||
/>
|
||||
<menuitem
|
||||
name="Activity Plan"
|
||||
id="mail_activity_plan_menu_config_task"
|
||||
action="mail_activity_plan_action_config_task_plan"
|
||||
name="Activity Plans"
|
||||
id="mail_activity_plan_menu_config_project"
|
||||
action="mail_activity_plan_action_config_project_task_plan"
|
||||
/>
|
||||
</menuitem>
|
||||
</menuitem>
|
||||
|
||||
@@ -47,6 +47,7 @@ This module contains all the common features of Sales Management and eCommerce.
|
||||
'views/account_views.xml',
|
||||
'views/crm_team_views.xml',
|
||||
'views/mail_activity_views.xml',
|
||||
'views/mail_activity_plan_views.xml',
|
||||
'views/payment_views.xml',
|
||||
'views/product_document_views.xml',
|
||||
'views/product_packaging_views.xml',
|
||||
|
||||
@@ -769,6 +769,11 @@ msgstr ""
|
||||
msgid "Activity Exception Decoration"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale
|
||||
#: model:ir.ui.menu,name:sale.sale_menu_config_activity_plan
|
||||
msgid "Activity Plans"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale
|
||||
#: model:ir.model.fields,field_description:sale.field_sale_order__activity_state
|
||||
msgid "Activity State"
|
||||
@@ -785,6 +790,11 @@ msgstr ""
|
||||
msgid "Activity Types"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale
|
||||
#: model_terms:ir.actions.act_window,help:sale.mail_activity_plan_action_sale_order
|
||||
msgid "Add a new plan"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale
|
||||
#: model_terms:ir.ui.view,arch_db:sale.view_order_form
|
||||
msgid "Add a note"
|
||||
@@ -3614,6 +3624,11 @@ msgstr ""
|
||||
msgid "Sale Order Count"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale
|
||||
#: model:ir.actions.act_window,name:sale.mail_activity_plan_action_sale_order
|
||||
msgid "Sale Order Plans"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale
|
||||
#: model:ir.model.fields,field_description:sale.field_res_config_settings__group_warning_sale
|
||||
msgid "Sale Order Warnings"
|
||||
|
||||
@@ -59,3 +59,5 @@ access_sale_advance_payment_inv,access.sale.advance.payment.inv,model_sale_advan
|
||||
access_sale_order_cancel,access.sale.order.cancel,model_sale_order_cancel,sales_team.group_sale_salesman,1,1,1,0
|
||||
access_sale_mass_cancel_orders,access.sale.mass.cancel.orders,model_sale_mass_cancel_orders,sales_team.group_sale_salesman,1,1,1,0
|
||||
access_sale_order_discount,access_sale_order_discount,model_sale_order_discount,sales_team.group_sale_salesman,1,1,1,0
|
||||
access_mail_activity_plan_sale_manager,mail.activity.plan.sale.manager,mail.model_mail_activity_plan,sales_team.group_sale_manager,1,1,1,1
|
||||
access_mail_activity_plan_template_sale_manager,mail.activity.plan.template.sale.manager,mail.model_mail_activity_plan_template,sales_team.group_sale_manager,1,1,1,1
|
||||
|
||||
|
@@ -182,4 +182,20 @@
|
||||
<field name="domain_force">[('create_uid', '=', user.id)]</field>
|
||||
</record>
|
||||
|
||||
<record id="mail_plan_rule_group_sale_manager" model="ir.rule">
|
||||
<field name="name">Manager can manage sale order plans</field>
|
||||
<field name="groups" eval="[(4, ref('sales_team.group_sale_manager'))]"/>
|
||||
<field name="model_id" ref="mail.model_mail_activity_plan"/>
|
||||
<field name="domain_force">[('res_model', '=', 'sale.order')]</field>
|
||||
<field name="perm_read" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record id="mail_plan_template_rule_group_sale_manager" model="ir.rule">
|
||||
<field name="name">Manager can manage sale order plan templates</field>
|
||||
<field name="groups" eval="[(4, ref('sales_team.group_sale_manager'))]"/>
|
||||
<field name="model_id" ref="mail.model_mail_activity_plan_template"/>
|
||||
<field name="domain_force">[('plan_id.res_model', '=', 'sale.order')]</field>
|
||||
<field name="perm_read" eval="False"/>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="mail_activity_plan_action_sale_order" model="ir.actions.act_window">
|
||||
<field name="name">Sale Order Plans</field>
|
||||
<field name="res_model">mail.activity.plan</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="search_view_id" ref="mail.mail_activity_plan_view_search"/>
|
||||
<field name="context">{'default_res_model': 'sale.order'}</field>
|
||||
<field name="domain">[('res_model', '=', 'sale.order')]</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Add a new plan
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -182,6 +182,14 @@
|
||||
groups="base.group_no_one"
|
||||
sequence="60"
|
||||
/>
|
||||
|
||||
<menuitem id="sale_menu_config_activity_plan"
|
||||
name="Activity Plans"
|
||||
action="mail_activity_plan_action_sale_order"
|
||||
groups="sales_team.group_sale_manager"
|
||||
sequence="70"
|
||||
/>
|
||||
|
||||
</menuitem>
|
||||
</menuitem>
|
||||
|
||||
|
||||
@@ -197,7 +197,7 @@ class TestActivitySchedule(ActivityScheduleCase):
|
||||
self.assertFalse(form.plan_assignation_summary)
|
||||
form.plan_id = self.plan_onboarding
|
||||
self.assertEqual(form.plan_assignation_summary,
|
||||
'<ul><li>To-Do - Other: Plan training</li><li>To-Do - Other: Training</li></ul>')
|
||||
'<ul><li>To-Do: Plan training</li><li>To-Do: Training</li></ul>')
|
||||
self.assertTrue(form._get_modifier('plan_on_demand_user_id', 'invisible'))
|
||||
form.plan_id = self.plan_party
|
||||
self.assertIn('Book a place', form.plan_assignation_summary)
|
||||
@@ -208,11 +208,11 @@ class TestActivitySchedule(ActivityScheduleCase):
|
||||
self.assertPlanExecution(self.plan_party, test_records)
|
||||
|
||||
# date_deadline specified, responsible specified
|
||||
force_date_deadline = date(2050, 1, 15)
|
||||
force_base_date_deadline = date(2050, 1, 15)
|
||||
force_responsible_id = self.user_admin
|
||||
form = self._instantiate_activity_schedule_wizard(test_records)
|
||||
form.plan_id = self.plan_party
|
||||
form.plan_date_deadline = force_date_deadline
|
||||
form.plan_date_deadline = force_base_date_deadline
|
||||
form.plan_on_demand_user_id = self.env['res.users']
|
||||
self.assertTrue(form.has_error)
|
||||
self.assertIn(f'No responsible specified for {self.activity_type_todo.name}: Book a place',
|
||||
@@ -224,7 +224,7 @@ class TestActivitySchedule(ActivityScheduleCase):
|
||||
|
||||
self.assertPlanExecution(
|
||||
self.plan_party, test_records,
|
||||
force_date_deadline=force_date_deadline,
|
||||
force_base_date_deadline=force_base_date_deadline,
|
||||
force_responsible_id=force_responsible_id)
|
||||
|
||||
@users('admin')
|
||||
|
||||
Reference in New Issue
Block a user