[IMP] {hr,sale}_timesheet: improve generic UX
Purpose of the commit is to improve the UX of the timesheet. So in this commit did the following changes: - SOL field display by default in timesheet list view - If the timesheet is invoiced, it will appear in read-only mode task-2918757 closes odoo/odoo#97203 Related: odoo/enterprise#30000 Related: odoo/upgrade#3729 Signed-off-by: Xavier Bol (xbo) <xbo@odoo.com>
This commit is contained in:
@@ -63,6 +63,7 @@ class AccountAnalyticLine(models.Model):
|
||||
manager_id = fields.Many2one('hr.employee', "Manager", related='employee_id.parent_id', store=True)
|
||||
encoding_uom_id = fields.Many2one('uom.uom', compute='_compute_encoding_uom_id')
|
||||
partner_id = fields.Many2one(compute='_compute_partner_id', store=True, readonly=False)
|
||||
readonly_timesheet = fields.Boolean(string="Readonly Timesheet", compute="_compute_readonly_timesheet")
|
||||
|
||||
def name_get(self):
|
||||
result = super().name_get()
|
||||
@@ -82,6 +83,16 @@ class AccountAnalyticLine(models.Model):
|
||||
timesheet_dict = {res['id']: _get_display_name(res['project_id'], res['task_id']) for res in timesheets_read}
|
||||
return list({**dict(result), **timesheet_dict}.items())
|
||||
|
||||
def _is_readonly(self):
|
||||
self.ensure_one()
|
||||
# is overridden in other timesheet related modules
|
||||
return False
|
||||
|
||||
def _compute_readonly_timesheet(self):
|
||||
readonly_timesheets = self.filtered(lambda timesheet: timesheet._is_readonly())
|
||||
readonly_timesheets.readonly_timesheet = True
|
||||
(self - readonly_timesheets).readonly_timesheet = False
|
||||
|
||||
def _compute_encoding_uom_id(self):
|
||||
for analytic_line in self:
|
||||
analytic_line.encoding_uom_id = analytic_line.company_id.timesheet_encode_uom_id
|
||||
|
||||
@@ -5,13 +5,14 @@
|
||||
<field name="name">account.analytic.line.tree.hr_timesheet</field>
|
||||
<field name="model">account.analytic.line</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree editable="bottom" string="Timesheet Activities" sample="1">
|
||||
<field name="date"/>
|
||||
<field name="employee_id" invisible="1"/>
|
||||
<field name="project_id" required="1" options="{'no_create_edit': True, 'no_open': 1}"/>
|
||||
<field name="task_id" optional="show" options="{'no_create_edit': True, 'no_open': True}" widget="task_with_hours" context="{'default_project_id': project_id}"/>
|
||||
<field name="name" optional="show" required="0"/>
|
||||
<field name="unit_amount" optional="show" widget="timesheet_uom" sum="Total" decoration-danger="unit_amount > 24 or unit_amount < 0"/>
|
||||
<tree editable="bottom" string="Timesheet Activities" sample="1" decoration-muted="readonly_timesheet == True">
|
||||
<field name="readonly_timesheet" invisible="1"/>
|
||||
<field name="date" attrs="{'readonly': [('readonly_timesheet', '=', True)]}"/>
|
||||
<field name="employee_id" invisible="1" attrs="{'readonly': [('readonly_timesheet', '=', True)]}"/>
|
||||
<field name="project_id" required="1" options="{'no_create_edit': True, 'no_open': 1}" attrs="{'readonly': [('readonly_timesheet', '=', True)]}"/>
|
||||
<field name="task_id" optional="show" options="{'no_create_edit': True, 'no_open': True}" widget="task_with_hours" context="{'default_project_id': project_id}" attrs="{'readonly': [('readonly_timesheet', '=', True)]}"/>
|
||||
<field name="name" optional="show" required="0" attrs="{'readonly': [('readonly_timesheet', '=', True)]}"/>
|
||||
<field name="unit_amount" optional="show" widget="timesheet_uom" sum="Total" decoration-danger="unit_amount > 24 or unit_amount < 0" attrs="{'readonly': [('readonly_timesheet', '=', True)]}"/>
|
||||
<field name="company_id" invisible="1"/>
|
||||
<field name="user_id" invisible="1"/>
|
||||
</tree>
|
||||
@@ -120,15 +121,18 @@
|
||||
<sheet string="Analytic Entry">
|
||||
<group>
|
||||
<group>
|
||||
<field name="project_id" required="1"/>
|
||||
<field name="task_id" widget="task_with_hours" context="{'default_project_id': project_id}"/>
|
||||
<field name="name"/>
|
||||
<field name="readonly_timesheet" invisible="1"/>
|
||||
<field name="project_id" required="1" attrs="{'readonly': [('readonly_timesheet', '=', True)]}"/>
|
||||
<field name="task_id" widget="task_with_hours" context="{'default_project_id': project_id}"
|
||||
attrs="{'readonly': [('readonly_timesheet', '=', True)]}"/>
|
||||
<field name="name" attrs="{'readonly': [('readonly_timesheet', '=', True)]}"/>
|
||||
<field name="company_id" groups="base.group_multi_company" invisible="1"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="date"/>
|
||||
<field name="date" attrs="{'readonly': [('readonly_timesheet', '=', True)]}"/>
|
||||
<field name="amount" invisible="1"/>
|
||||
<field name="unit_amount" widget="timesheet_uom" decoration-danger="unit_amount > 24"/>
|
||||
<field name="unit_amount" widget="timesheet_uom" decoration-danger="unit_amount > 24"
|
||||
attrs="{'readonly': [('readonly_timesheet', '=', True)]}"/>
|
||||
<field name="currency_id" invisible="1"/>
|
||||
<field name="company_id" invisible="1"/>
|
||||
</group>
|
||||
@@ -146,7 +150,7 @@
|
||||
<field name="priority">10</field>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='date']" position="before">
|
||||
<field name="employee_id" required="1" context="{'active_test': True}"/>
|
||||
<field name="employee_id" required="1" context="{'active_test': True}" attrs="{'readonly': [('readonly_timesheet', '=', True)]}"/>
|
||||
<field name="user_id" invisible="1"/>
|
||||
</xpath>
|
||||
</field>
|
||||
|
||||
@@ -40,12 +40,15 @@
|
||||
</div>
|
||||
</group>
|
||||
<field name="timesheet_ids" mode="tree,kanban" attrs="{'invisible': [('analytic_account_active', '=', False)]}" context="{'default_project_id': project_id, 'default_name':''}">
|
||||
<tree editable="bottom" string="Timesheet Activities" default_order="date">
|
||||
<field name="date"/>
|
||||
<tree editable="bottom" string="Timesheet Activities" default_order="date" decoration-muted="readonly_timesheet == True">
|
||||
<field name="readonly_timesheet" invisible="1"/>
|
||||
<field name="date" attrs="{'readonly': [('readonly_timesheet', '=', True)]}"/>
|
||||
<field name="user_id" invisible="1"/>
|
||||
<field name="employee_id" required="1" widget="many2one_avatar_employee" context="{'active_test': True}"/>
|
||||
<field name="name" required="0"/>
|
||||
<field name="unit_amount" widget="timesheet_uom" decoration-danger="unit_amount > 24 or unit_amount < 0"/>
|
||||
<field name="employee_id" required="1" widget="many2one_avatar_employee"
|
||||
context="{'active_test': True}" attrs="{'readonly': [('readonly_timesheet', '=', True)]}"/>
|
||||
<field name="name" required="0" attrs="{'readonly': [('readonly_timesheet', '=', True)]}"/>
|
||||
<field name="unit_amount" widget="timesheet_uom" decoration-danger="unit_amount > 24 or unit_amount < 0"
|
||||
attrs="{'readonly': [('readonly_timesheet', '=', True)]}"/>
|
||||
<field name="project_id" invisible="1"/>
|
||||
<field name="task_id" invisible="1"/>
|
||||
<field name="company_id" invisible="1"/>
|
||||
@@ -86,11 +89,14 @@
|
||||
<form string="Timesheet Activities">
|
||||
<sheet>
|
||||
<group>
|
||||
<field name="date"/>
|
||||
<field name="user_id" invisible="1"/>
|
||||
<field name="employee_id" required="1" widget="many2one_avatar_employee" context="{'active_test': True}"/>
|
||||
<field name="name" required="0"/>
|
||||
<field name="unit_amount" string="Duration" widget="float_time" decoration-danger="unit_amount > 24"/>
|
||||
<field name="readonly_timesheet" invisible="1"/>
|
||||
<field name="date" attrs="{'readonly': [('readonly_timesheet', '=', True)]}"/>
|
||||
<field name="user_id" invisible="1" attrs="{'readonly': [('readonly_timesheet', '=', True)]}"/>
|
||||
<field name="employee_id" required="1" widget="many2one_avatar_employee" context="{'active_test': True}"
|
||||
attrs="{'readonly': [('readonly_timesheet', '=', True)]}"/>
|
||||
<field name="name" required="0" attrs="{'readonly': [('readonly_timesheet', '=', True)]}"/>
|
||||
<field name="unit_amount" string="Duration" widget="float_time" decoration-danger="unit_amount > 24"
|
||||
attrs="{'readonly': [('readonly_timesheet', '=', True)]}"/>
|
||||
<field name="project_id" invisible="1"/>
|
||||
<field name="task_id" invisible="1"/>
|
||||
<field name="company_id" invisible="1"/>
|
||||
|
||||
@@ -79,6 +79,9 @@ class AccountAnalyticLine(models.Model):
|
||||
def _compute_project_id(self):
|
||||
super(AccountAnalyticLine, self.filtered(lambda t: t._is_not_billed()))._compute_project_id()
|
||||
|
||||
def _is_readonly(self):
|
||||
return super()._is_readonly() or not self._is_not_billed()
|
||||
|
||||
def _is_not_billed(self):
|
||||
self.ensure_one()
|
||||
return not self.timesheet_invoice_id or self.timesheet_invoice_id.state == 'cancel'
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
<field name="commercial_partner_id" invisible="1" groups="sales_team.group_sale_salesman"/>
|
||||
<field name="is_so_line_edited" invisible="1" groups="sales_team.group_sale_salesman"/>
|
||||
<field name="allow_billable" invisible="1" groups="sales_team.group_sale_salesman"/>
|
||||
<field name="so_line" widget="so_line_field" optional="hide" options="{'no_create': True}" context="{'create': False, 'edit': False, 'delete': False}" attrs="{'invisible': [('allow_billable', '=', False)]}" placeholder="Non-billable" groups="sales_team.group_sale_salesman"/>
|
||||
<field name="so_line" widget="so_line_field" optional="show" options="{'no_create': True}" context="{'create': False, 'edit': False, 'delete': False}" attrs="{'invisible': [('allow_billable', '=', False)], 'readonly': [('readonly_timesheet', '=', True)]}" placeholder="Non-billable" groups="sales_team.group_sale_salesman"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
@@ -59,7 +59,7 @@
|
||||
<field name="commercial_partner_id" invisible="1" groups="sales_team.group_sale_salesman"/>
|
||||
<field name="is_so_line_edited" invisible="1" groups="sales_team.group_sale_salesman"/>
|
||||
<field name="allow_billable" invisible="1" groups="sales_team.group_sale_salesman"/>
|
||||
<field name="so_line" widget="so_line_field" options='{"no_create": True}' context="{'create': False, 'edit': False, 'delete': False, 'with_price_unit': True}" attrs="{'invisible': [('allow_billable', '=', False)]}" placeholder="Non-billable" groups="sales_team.group_sale_salesman"/>
|
||||
<field name="so_line" widget="so_line_field" options='{"no_create": True}' context="{'create': False, 'edit': False, 'delete': False, 'with_price_unit': True}" attrs="{'invisible': [('allow_billable', '=', False)], 'readonly': [('readonly_timesheet', '=', True)]}" placeholder="Non-billable" groups="sales_team.group_sale_salesman"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -126,10 +126,6 @@
|
||||
<field name="model">project.task</field>
|
||||
<field name="inherit_id" ref="project.view_task_form2"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='timesheet_ids']/tree" position="attributes">
|
||||
<!-- <field name="timesheet_ids"/> is already inside a block groups="hr_timesheet.group_hr_timesheet_user" -->
|
||||
<attribute name="decoration-muted">timesheet_invoice_id != False</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='user_ids']" position="after">
|
||||
<field name="is_project_map_empty" invisible="1" groups="hr_timesheet.group_hr_timesheet_user"/>
|
||||
<field name="has_multi_sol" invisible="1" groups="hr_timesheet.group_hr_timesheet_user"/>
|
||||
@@ -149,12 +145,12 @@
|
||||
<!-- <field name="timesheet_ids"/> is already inside a block groups="hr_timesheet.group_hr_timesheet_user" -->
|
||||
<field name="timesheet_invoice_id" invisible="1"/>
|
||||
<field name="so_line" groups="!sales_team.group_sale_salesman"
|
||||
attrs="{'column_invisible': [('parent.allow_billable', '=', False)]}"
|
||||
attrs="{'column_invisible': [('parent.allow_billable', '=', False)], 'readonly': [('readonly_timesheet', '=', True)]}"
|
||||
context="{'with_remaining_hours': True, 'with_price_unit': True}" options="{'no_create': True, 'no_open': True}"
|
||||
domain="[('is_service', '=', True), ('order_partner_id', 'child_of', parent.partner_id), ('is_expense', '=', False), ('state', 'in', ['sale', 'done'])]"
|
||||
optional="hide"/>
|
||||
<field name="so_line" groups="sales_team.group_sale_salesman"
|
||||
attrs="{'column_invisible': [('parent.allow_billable', '=', False)]}"
|
||||
attrs="{'column_invisible': [('parent.allow_billable', '=', False)], 'readonly': [('readonly_timesheet', '=', True)]}"
|
||||
context="{'with_remaining_hours': True, 'with_price_unit': True}" options="{'no_create': True}"
|
||||
domain="[('is_service', '=', True), ('order_partner_id', 'child_of', parent.partner_id), ('is_expense', '=', False), ('state', 'in', ['sale', 'done'])]"
|
||||
optional="hide"/>
|
||||
|
||||
Reference in New Issue
Block a user