[IMP] (hr, sale)_timesheet, pad(_project): improve project general UX

Purpose fo the task is to improve the UX of timesheet, project and task.

Done the chages for below point:
  - improve the stage demo data to unified the project stage
  - on the task timesheet 'sub-tasks hours spent' should be clickable
and on click, it will display the list of subtask timesheet.
  - display in warning tasks for which Remaining Hours < 0 if Planned Hours > 0 in task list view
  - improve the settings of collabrative pad and planning and project form view

Task-2129052

closes odoo/odoo#41092

Closes: #41092
Signed-off-by: Yannick Tivisse (yti) <yti@odoo.com>
This commit is contained in:
Barad Mahendra
2020-01-16 10:56:05 +00:00
committed by Yannick Tivisse
parent de4d7e14f8
commit d16aa4cd39
12 changed files with 68 additions and 76 deletions
+10
View File
@@ -135,6 +135,16 @@ class Task(models.Model):
for task in self:
task.display_timesheet_timer = task.allow_timesheets and task.project_id.allow_timesheet_timer and task.analytic_account_active
def action_view_subtask_timesheet(self):
self.ensure_one()
return {
'type': 'ir.actions.act_window',
'name': _('Timesheets'),
'res_model': 'account.analytic.line',
'view_mode': 'list,form',
'domain': [('project_id', '!=', False), ('task_id', 'in', self.child_ids.ids)],
}
def write(self, values):
# a timesheet must have an analytic account (and a project)
if 'project_id' in values and self and not values.get('project_id'):
+5 -1
View File
@@ -178,7 +178,8 @@
<group attrs="{'invisible': [('analytic_account_active', '=', False)]}">
<group class="oe_subtotal_footer oe_right" name="project_hours">
<field name="effective_hours" widget="float_time" />
<field name="subtask_effective_hours" widget="float_time" attrs="{'invisible' : [('subtask_effective_hours', '=', 0.0)]}" />
<button name="action_view_subtask_timesheet" string="Sub-tasks Hours Spent:" type="object" class="oe_inline oe_link pl-0" attrs="{'invisible' : [('subtask_effective_hours', '=', 0.0)]}"/>
<field name="subtask_effective_hours" widget="float_time" attrs="{'invisible' : [('subtask_effective_hours', '=', 0.0)]}" nolabel="1"/>
<field name="total_hours_spent" widget="float_time" class="oe_subtotal_footer_separator" attrs="{'invisible' : [('subtask_effective_hours', '=', 0.0)]}" />
<field name="remaining_hours" widget="float_time" class="oe_subtotal_footer_separator" attrs="{'invisible' : [('planned_hours', '=', 0.0)]}"/>
</group>
@@ -194,6 +195,9 @@
<field name="inherit_id" ref="project.view_task_tree2" />
<field eval="2" name="priority"/>
<field name="arch" type="xml">
<xpath expr="//tree" position="attributes">
<attribute name="decoration-warning">planned_hours and (effective_hours&gt;planned_hours)</attribute>
</xpath>
<field name="user_id" position="after">
<field name="planned_hours" widget="float_time" sum="Initially Planned Hours" optional="show"/>
<field name="effective_hours" widget="float_time" sum="Effective Hours" optional="show"/>
+2 -2
View File
@@ -7,5 +7,5 @@ from odoo import fields, models
class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
pad_server = fields.Char(related='company_id.pad_server', string="Pad Server *", readonly=False)
pad_key = fields.Char(related='company_id.pad_key', string="Pad Api Key *", readonly=False)
pad_server = fields.Char(related='company_id.pad_server', string="Pad Server", readonly=False)
pad_key = fields.Char(related='company_id.pad_key', string="Pad API Key", readonly=False)
+1 -1
View File
@@ -4,7 +4,7 @@
<t t-name="FieldPad">
<div class="oe_form_field_text oe_pad">
<p class="oe_unconfigured d-none">
Please enter your Etherpad credentials through the menu 'Settings > General Settings'.
Please, enter your Etherpad credentials through the Settings.
</p>
<t t-if="widget.mode === 'readonly'">
<div class="oe_pad_content etherpad_readonly oe_configured" />
+17 -17
View File
@@ -1,20 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="res_config_settings_view_form" model="ir.ui.view">
<field name="name">res.config.settings.view.form.inherit.pad</field>
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="base_setup.res_config_settings_view_form"/>
<field name="arch" type="xml">
<div id="msg_module_pad" position="replace">
<div class="content-group" id="pad_configuration_settings" attrs="{'invisible': [('module_pad','=',False)]}">
<div class="mt16 row">
<label for="pad_server" string="Server" class="col-3 col-lg-3 o_light_label"/>
<field name="pad_server" placeholder="e.g. beta.primarypad.com"/>
<label for="pad_key" string="API Key" class="col-3 col-lg-3 o_light_label"/>
<field name="pad_key"/>
</div>
</div>
</div>
</field>
</record>
<record id="res_config_settings_view_form" model="ir.ui.view">
<field name="name">res.config.settings.view.form.inherit.pad</field>
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="base_setup.res_config_settings_view_form"/>
<field name="arch" type="xml">
<div id="msg_module_pad" position="replace">
<div class="content-group" id="pad_configuration_settings" attrs="{'invisible': [('module_pad', '=', False)]}">
<div class="mt16 row">
<label for="pad_server" string="Server" class="col-3 col-lg-3 o_light_label"/>
<field name="pad_server" placeholder="e.g. beta.primarypad.com" attrs="{'required': [('module_pad', '!=', False)]}"/>
<label for="pad_key" string="API Key" class="col-3 col-lg-3 o_light_label"/>
<field name="pad_key" attrs="{'required': [('module_pad', '!=', False)]}"/>
</div>
</div>
</div>
</field>
</record>
</odoo>
+1 -1
View File
@@ -24,4 +24,4 @@ class ProjectTask(models.Model):
class ProjectProject(models.Model):
_inherit = "project.project"
use_pads = fields.Boolean("Use collaborative pads", help="Use collaborative pad for the tasks on this project.")
use_pads = fields.Boolean("Use collaborative pads", default=True, help="Use collaborative pad for the tasks on this project.")
+13 -3
View File
@@ -20,9 +20,19 @@
<field name="model">project.project</field>
<field name="inherit_id" ref="project.edit_project"/>
<field name="arch" type="xml">
<field name="partner_id" position="after">
<field name="use_pads"/>
</field>
<xpath expr="//div[@id='rating_settings']" position="after">
<div class="col-lg-6 o_setting_box" id="pad_settings">
<div class="o_setting_left_pane">
<field name="use_pads"/>
</div>
<div class="o_setting_right_pane">
<label for="use_pads" string="Collaborative Pads"/>
<div class="text-muted">
Use collaborative rich text pads on tasks
</div>
</div>
</div>
</xpath>
</field>
</record>
@@ -6,15 +6,14 @@
<field name="inherit_id" ref="project.res_config_settings_view_form"/>
<field name="arch" type="xml">
<div name="pad_project_right_pane" position="inside">
<div class="content-group">
<field name='company_id' invisible="1"/>
<div class="content-group" attrs="{'invisible': [('module_pad', '=', False)]}">
<div class="row mt16">
<label for="pad_server" class="col-lg-3 o_light_label"/>
<field name="pad_server"/>
<field name="pad_server" attrs="{'required': [('module_pad', '!=', False)]}"/>
</div>
<div class="row">
<label for="pad_key" class="col-lg-3 o_light_label"/>
<field name="pad_key"/>
<field name="pad_key" attrs="{'required': [('module_pad', '!=', False)]}"/>
</div>
</div>
</div>
+3 -3
View File
@@ -103,19 +103,19 @@
<record forcecreate="False" id="project_stage_data_0" model="project.task.type">
<field name="sequence">1</field>
<field name="name">New</field>
<field name="name">Basic</field>
<field name="project_ids" eval="[(4, ref('project_project_data'))]"/>
</record>
<record forcecreate="False" id="project_stage_data_1" model="project.task.type">
<field name="sequence">2</field>
<field name="name">Basic</field>
<field name="name">Advanced</field>
<field name="project_ids" eval="[(4, ref('project_project_data'))]"/>
</record>
<record forcecreate="False" id="project_stage_data_2" model="project.task.type">
<field name="sequence">3</field>
<field name="name">Advanced</field>
<field name="name">Expert</field>
<field name="project_ids" eval="[(4, ref('project_project_data'))]"/>
</record>
+2 -2
View File
@@ -24,8 +24,8 @@
<!-- Stages -->
<record id="project_stage_0" model="project.task.type">
<field name="sequence">1</field>
<field name="name">To Do</field>
<field name="legend_blocked">Not validated</field>
<field name="name">New</field>
<field name="legend_blocked">Blocked</field>
<field name="mail_template_id" ref="project.mail_template_data_project_task"/>
</record>
<record id="project_stage_1" model="project.task.type">
+1 -1
View File
@@ -7,7 +7,7 @@ from odoo import api, fields, models
class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
module_project_forecast = fields.Boolean(string="Forecasts")
module_project_forecast = fields.Boolean(string="Planning")
module_hr_timesheet = fields.Boolean(string="Task Logs")
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')
@@ -11,14 +11,7 @@
<field name="product_uom_qty">5.0</field>
</record>
<!-- Projects, Analytic Account and Stages -->
<record id="project_stage_fixed" model="project.task.type">
<field name="sequence">30</field>
<field name="name">Fixed</field>
<field name="legend_blocked">Need functional or technical help</field>
<field name="legend_done">Done</field>
</record>
<!-- Projects and Analytic Account -->
<record id="account_analytic_account_project_support" model="account.analytic.account">
<field name="name">After-Sales Services</field>
<field name="code">INT</field>
@@ -29,7 +22,7 @@
<field name="date_start" eval="time.strftime('%Y-%m-01 10:00:00')"/>
<field name="name">After-Sales Services</field>
<field name="analytic_account_id" ref="account_analytic_account_project_support"/>
<field name="type_ids" eval="[(4, ref('project.project_stage_data_0')), (4, ref('project.project_stage_1')), (4, ref('project_stage_fixed'))]"/>
<field name="type_ids" eval="[(4, ref('project.project_stage_0')), (4, ref('project.project_stage_1')), (4, ref('project.project_stage_2'))]"/>
</record>
<!-- Project Task -->
@@ -418,44 +411,20 @@
<field name="unit_amount">1.00</field>
</record>
<!-- task on project generated by sale order 1 -->
<record id="project_from_sale_order_1_to_do" model="project.task.type">
<field name="sequence">10</field>
<field name="name">To Do</field>
<field name="legend_blocked">Not ready</field>
<field name="legend_done">Ready to be started</field>
<field name="project_ids" search="[('sale_order_id', '=', ref('sale_timesheet.sale_order_1'))]" />
<record id="project.project_stage_1" model="project.task.type">
<field name="project_ids" model="project.project" eval="[(4, obj().search([('sale_order_id', '=', ref('sale_timesheet.sale_order_1'))], limit=1).id)]"/>
</record>
<record id="project_from_sale_order_1_in_progress" model="project.task.type">
<field name="sequence">20</field>
<field name="name">In Progress</field>
<field name="legend_blocked">Need help</field>
<field name="legend_done">Work done</field>
<field name="project_ids" search="[('sale_order_id', '=', ref('sale_timesheet.sale_order_1'))]" />
<record id="project.project_stage_2" model="project.task.type">
<field name="project_ids" model="project.project" eval="[(4, obj().search([('sale_order_id', '=', ref('sale_timesheet.sale_order_1'))], limit=1).id)]"/>
</record>
<record id="project_from_sale_order_1_done" model="project.task.type">
<field name="sequence">30</field>
<field name="name">Done</field>
<field name="legend_blocked">Not done yet</field>
<field name="legend_done">Done</field>
<field name="project_ids" search="[('sale_order_id', '=', ref('sale_timesheet.sale_order_1'))]" />
</record>
<function model="project.task" name="write">
<value model="project.task" eval="obj().search([('sale_line_id','=',ref('sale_timesheet.sale_line_13')), ('stage_id', '=', False)]).id"/>
<value eval="{
'stage_id': ref('sale_timesheet.project_from_sale_order_1_to_do')
}"/>
</function>
<record id="project_task_1" model="project.task">
<field name="name">Decoration</field>
<field name="sale_line_id" ref="sale_timesheet.sale_line_13"/>
<field name="sale_order_id" ref="sale_timesheet.sale_order_1"/>
<field name="project_id" search="[('sale_order_id', '=', ref('sale_timesheet.sale_order_1'))]" />
<field name="stage_id" ref="project_from_sale_order_1_in_progress"/>
<field name="stage_id" ref="project.project_stage_2"/>
<field name="sale_line_id" ref="sale_timesheet.sale_line_13" />
<field name="sale_order_id" ref="sale_timesheet.sale_order_1" />
<field name="partner_id" ref="base.res_partner_2" />
@@ -466,7 +435,7 @@
<field name="sale_line_id" ref="sale_timesheet.sale_line_13"/>
<field name="sale_order_id" ref="sale_timesheet.sale_order_1"/>
<field name="project_id" search="[('sale_order_id', '=', ref('sale_timesheet.sale_order_1'))]" />
<field name="stage_id" ref="project_from_sale_order_1_done"/>
<field name="stage_id" ref="project.project_stage_2"/>
<field name="sale_line_id" ref="sale_timesheet.sale_line_13" />
<field name="sale_order_id" ref="sale_timesheet.sale_order_1" />
<field name="partner_id" ref="base.res_partner_2" />
@@ -477,7 +446,7 @@
<field name="sale_line_id" ref="sale_timesheet.sale_line_13"/>
<field name="sale_order_id" ref="sale_timesheet.sale_order_1"/>
<field name="project_id" search="[('sale_order_id', '=', ref('sale_timesheet.sale_order_1'))]" />
<field name="stage_id" ref="project_from_sale_order_1_in_progress"/>
<field name="stage_id" ref="project.project_stage_2"/>
<field name="sale_line_id" ref="sale_timesheet.sale_line_13" />
<field name="sale_order_id" ref="sale_timesheet.sale_order_1" />
<field name="partner_id" ref="base.res_partner_2" />
@@ -486,7 +455,7 @@
<record id="project_task_4" model="project.task">
<field name="name">Furniture Delivery</field>
<field name="project_id" search="[('sale_order_id', '=', ref('sale_timesheet.sale_order_1'))]" />
<field name="stage_id" ref="project_from_sale_order_1_to_do" />
<field name="stage_id" ref="project.project_stage_1" />
<field name="sale_line_id" ref="sale_timesheet.sale_line_13" />
<field name="sale_order_id" ref="sale_timesheet.sale_order_1" />
<field name="partner_id" ref="base.res_partner_2" />