Skip to content

Commit 4a93d9a

Browse files
committed
[IMP] hr_timesheet,sale_{project,timesheet}: add various improvements
Before this commit: - project.task form view > it makes no sense to timesheet on a down payment as this is not the service that was sold to the customer. - users are not alerted that there are no remaining hours on the task as the information can be a bit hidden under the timesheets notebook After this commit: - project.task form view > it's not possible to select an SOL linked to a down payment for projects, tasks, timesheets and tickets. - project.task form view > the progress is displayed in red if > 100%. task-3476795
1 parent 7232654 commit 4a93d9a

File tree

11 files changed

+28
-22
lines changed

11 files changed

+28
-22
lines changed

addons/hr_timesheet/models/project_task.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ def _compute_progress_hours(self):
9898
if (task.allocated_hours > 0.0):
9999
task_total_hours = task.effective_hours + task.subtask_effective_hours
100100
task.overtime = max(task_total_hours - task.allocated_hours, 0)
101-
task.progress = round(100.0 * task_total_hours / task.allocated_hours, 2)
101+
task.progress = round(task_total_hours / task.allocated_hours, 2)
102102
else:
103103
task.progress = 0.0
104104
task.overtime = 0

addons/hr_timesheet/tests/test_timesheet.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -685,4 +685,4 @@ def test_percentage_of_allocated_hours(self):
685685
'employee_id': self.empl_employee.id,
686686
},
687687
])
688-
self.assertEqual(self.task1.progress, 100, 'The percentage of allocated hours should be 100%.')
688+
self.assertEqual(self.task1.progress, 1, 'The progress of allocated hours should be 1.')

addons/hr_timesheet/views/project_task_portal_templates.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
</div>
2424
</xpath>
2525
<xpath expr="//div[@name='portal_my_task_allocated_hours']" position="after">
26-
<div t-if="task.allocated_hours > 0 and allow_timesheets"><strong>Progress:</strong> <span t-field="task.progress"/>%</div>
26+
<div t-if="task.allocated_hours > 0 and allow_timesheets"><strong>Progress:</strong> <span t-esc="task.progress * 100"/>%</div>
2727
</xpath>
2828
<xpath expr="//div[@name='portal_my_task_allocated_hours']/t" position="replace">
2929
<t t-call="hr_timesheet.portal_my_task_allocated_hours_template"></t>

addons/hr_timesheet/views/project_task_sharing_views.xml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@
1717
<field name="effective_hours" widget="timesheet_uom" sum="Effective Hours" optional="hide" column_invisible="not parent.allow_timesheets" invisible="not allow_timesheets"/>
1818
<field name="subtask_effective_hours" string="Sub-tasks Hours Spent" widget="timesheet_uom" sum="Sub-tasks Hours Spent" optional="hide" column_invisible="not parent.allow_timesheets" invisible="not allow_timesheets"/>
1919
<field name="total_hours_spent" string="Total Hours" widget="timesheet_uom" sum="Total Hours" optional="hide" column_invisible="not parent.allow_timesheets" invisible="not allow_timesheets"/>
20-
<field name="remaining_hours" widget="timesheet_uom" sum="Remaining Hours" optional="hide" decoration-danger="progress &gt;= 100" decoration-warning="progress &gt;= 80 and progress &lt; 100" column_invisible="not parent.allow_timesheets" invisible="not allow_timesheets"/>
20+
<field name="remaining_hours" widget="timesheet_uom" sum="Remaining Hours" optional="hide" decoration-danger="progress &gt;= 1" decoration-warning="progress &gt;= 0.8 and progress &lt; 1" column_invisible="not parent.allow_timesheets" invisible="not allow_timesheets"/>
2121
<field name="progress" widget="project_task_progressbar" optional="hide" options="{'overflow_class': 'bg-danger'}" column_invisible="not parent.allow_timesheets" invisible="not allow_timesheets"/>
2222
</xpath>
2323
<xpath expr="//field[@name='depend_on_ids']/tree/field[@name='portal_user_names']" position="after">
2424
<field name="allocated_hours" widget="timesheet_uom_no_toggle" sum="Total Allocated Time" optional="hide" column_invisible="not parent.allow_timesheets" invisible="not allow_timesheets"/>
2525
<field name="effective_hours" widget="timesheet_uom" sum="Effective Hours" optional="hide" column_invisible="not parent.allow_timesheets" invisible="not allow_timesheets"/>
2626
<field name="subtask_effective_hours" string="Sub-tasks Hours Spent" widget="timesheet_uom" sum="Sub-tasks Hours Spent" optional="hide" column_invisible="not parent.allow_timesheets" invisible="not allow_timesheets"/>
2727
<field name="total_hours_spent" string="Total Hours" widget="timesheet_uom" sum="Total Hours" optional="hide" column_invisible="not parent.allow_timesheets" invisible="not allow_timesheets"/>
28-
<field name="remaining_hours" widget="timesheet_uom" sum="Remaining Hours" optional="hide" decoration-danger="progress &gt;= 100" decoration-warning="progress &gt;= 80 and progress &lt; 100" column_invisible="not parent.allow_timesheets" invisible="not allow_timesheets"/>
28+
<field name="remaining_hours" widget="timesheet_uom" sum="Remaining Hours" optional="hide" decoration-danger="progress &gt;= 1" decoration-warning="progress &gt;= 0.8 and progress &lt; 1" column_invisible="not parent.allow_timesheets" invisible="not allow_timesheets"/>
2929
<field name="progress" widget="project_task_progressbar" optional="hide" options="{'overflow_class': 'bg-danger'}" column_invisible="not parent.allow_timesheets" invisible="not allow_timesheets"/>
3030
</xpath>
3131
<xpath expr="//field[@name='partner_id']" position="after">
@@ -38,7 +38,7 @@
3838
(incl. <field name="subtask_allocated_hours" nolabel="1" widget="timesheet_uom_no_toggle" class="oe_inline"/> on
3939
<span class="fw-bold text-dark"> Sub-tasks</span>)
4040
</span>
41-
<span class="ps-1">(<field name="progress" class="oe_inline" nolabel="1" widget="integer"/> %)</span>
41+
(<field name="progress" invisible="not project_id" class="oe_inline" nolabel="1" decoration-danger="progress > 1.005" digits="[1, 0]" widget="percentage"/>)
4242
</div>
4343
</xpath>
4444
<xpath expr="//notebook/page[@name='description_page']" position="after">
@@ -141,7 +141,7 @@
141141
<div class="oe_kanban_bottom_left" position="inside">
142142
<t name="allocated_hours" t-if="record.allocated_hours.raw_value &gt; 0 and record.allow_timesheets.raw_value">
143143
<t t-set="badge" t-value="'border border-success'"/>
144-
<t t-set="badge" t-value="'border border-warning'" t-if="record.progress.raw_value &gt;= 80 and record.progress.raw_value &lt;= 100"/>
144+
<t t-set="badge" t-value="'border border-warning'" t-if="record.progress.raw_value &gt;= 0.8 and record.progress.raw_value &lt;= 1"/>
145145
<t t-set="badge" t-value="'border border-danger'" t-if="record.remaining_hours.raw_value &lt; 0"/>
146146
<t t-set="title" t-value="'Remaining days'" t-if="record.encode_uom_in_days.raw_value"/>
147147
<t t-set="title" t-value="'Remaining hours'" t-else=""/>

addons/hr_timesheet/views/project_task_views.xml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<field name="effective_hours" widget="timesheet_uom" sum="Hours Spent" optional="hide" groups="hr_timesheet.group_hr_timesheet_user"/>
1212
<field name="subtask_effective_hours" widget="timesheet_uom" sum="Sub-tasks Hours Spent" optional="hide" groups="hr_timesheet.group_hr_timesheet_user"/>
1313
<field name="total_hours_spent" widget="timesheet_uom" sum="Total Hours" optional="hide" groups="hr_timesheet.group_hr_timesheet_user"/>
14-
<field name="remaining_hours" widget="timesheet_uom" sum="Remaining Hours" optional="hide" decoration-danger="progress &gt;= 100" decoration-warning="progress &gt;= 80 and progress &lt; 100" groups="hr_timesheet.group_hr_timesheet_user"/>
14+
<field name="remaining_hours" widget="timesheet_uom" sum="Remaining Hours" optional="hide" decoration-danger="progress &gt;= 1" decoration-warning="progress &gt;= 0.8 and progress &lt; 1" groups="hr_timesheet.group_hr_timesheet_user"/>
1515
<field name="progress" widget="project_task_progressbar" optional="hide" options="{'overflow_class': 'bg-danger'}" groups="hr_timesheet.group_hr_timesheet_user"/>
1616
</xpath>
1717
<xpath expr="//label[@for='date_deadline']" position="before">
@@ -24,7 +24,7 @@
2424
(incl. <field name="subtask_allocated_hours" nolabel="1" widget="timesheet_uom_no_toggle" class="oe_inline"/> on
2525
<span class="fw-bold text-dark"> Sub-tasks</span>)
2626
</span>
27-
<span invisible="not project_id">(<field name="progress" class="oe_inline" nolabel="1" widget="integer"/> %)</span>
27+
(<field name="progress" invisible="not project_id" class="oe_inline" nolabel="1" decoration-danger="progress > 1.005" digits="[1, 0]" widget="percentage"/>)
2828
</div>
2929
</xpath>
3030
<xpath expr="//notebook/page[@name='description_page']" position="after">
@@ -147,7 +147,7 @@
147147
<field name="effective_hours" widget="timesheet_uom" sum="Effective Hours" optional="hide" groups="hr_timesheet.group_hr_timesheet_user"/>
148148
<field name="subtask_effective_hours" widget="timesheet_uom" optional="hide" groups="hr_timesheet.group_hr_timesheet_user"/>
149149
<field name="total_hours_spent" widget="timesheet_uom" optional="hide" groups="hr_timesheet.group_hr_timesheet_user"/>
150-
<field name="remaining_hours" widget="timesheet_uom" sum="Remaining Hours" optional="hide" decoration-danger="progress &gt;= 100" decoration-warning="progress &gt;= 80 and progress &lt; 100" groups="hr_timesheet.group_hr_timesheet_user"/>
150+
<field name="remaining_hours" widget="timesheet_uom" sum="Remaining Hours" optional="hide" decoration-danger="progress &gt;= 1" decoration-warning="progress &gt;= 0.8 and progress &lt; 1" groups="hr_timesheet.group_hr_timesheet_user"/>
151151
<field name="progress" widget="project_task_progressbar" optional="hide" options="{'overflow_class': 'bg-danger'}" groups="hr_timesheet.group_hr_timesheet_user"/>
152152
</xpath>
153153
</field>
@@ -165,7 +165,7 @@
165165
<field name="effective_hours" widget="timesheet_uom" sum="Effective Hours" optional="show" invisible="effective_hours == 0"/>
166166
<field name="subtask_effective_hours" widget="timesheet_uom" sum="Sub-tasks Total Effective Hours" optional="hide"/>
167167
<field name="total_hours_spent" widget="timesheet_uom" sum="Total Hours" optional="hide"/>
168-
<field name="remaining_hours" widget="timesheet_uom" sum="Total Remaining Hours" optional="hide" decoration-danger="progress &gt;= 100" decoration-warning="progress &gt;= 80 and progress &lt; 100" invisible="allocated_hours == 0"/>
168+
<field name="remaining_hours" widget="timesheet_uom" sum="Total Remaining Hours" optional="hide" decoration-danger="progress &gt;= 1" decoration-warning="progress &gt;= 0.8 and progress &lt; 1" invisible="allocated_hours == 0"/>
169169
<field name="progress" widget="project_task_progressbar" avg="Average of Progress" optional="show" groups="hr_timesheet.group_hr_timesheet_user" invisible="allocated_hours == 0" options="{'overflow_class': 'bg-danger'}" />
170170
</field>
171171
</field>
@@ -186,7 +186,7 @@
186186
<div class="oe_kanban_bottom_left" position="inside">
187187
<t name="allocated_hours" t-if="record.allocated_hours.raw_value &gt; 0 and record.allow_timesheets.raw_value" groups="hr_timesheet.group_hr_timesheet_user">
188188
<t t-set="badge" t-value=""/>
189-
<t t-set="badge" t-value="'border border-warning'" t-if="record.progress.raw_value &gt;= 80 and record.progress.raw_value &lt;= 100"/>
189+
<t t-set="badge" t-value="'border border-warning'" t-if="record.progress.raw_value &gt;= 0.8 and record.progress.raw_value &lt;= 1"/>
190190
<t t-set="badge" t-value="'border border-danger'" t-if="record.remaining_hours.raw_value &lt; 0"/>
191191
<t t-set="title" t-value="'Remaining days'" t-if="record.encode_uom_in_days.raw_value"/>
192192
<t t-set="title" t-value="'Remaining hours'" t-else=""/>

addons/sale_project/models/project.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class Project(models.Model):
2020
sale_line_id = fields.Many2one(
2121
'sale.order.line', 'Sales Order Item', copy=False,
2222
compute="_compute_sale_line_id", store=True, readonly=False, index='btree_not_null',
23-
domain="[('is_service', '=', True), ('is_expense', '=', False), ('state', '=', 'sale'), ('order_partner_id', '=?', partner_id)]",
23+
domain="[('is_service', '=', True), ('is_expense', '=', False), ('state', '=', 'sale'), ('order_partner_id', '=?', partner_id), ('is_downpayment', '=', False)]",
2424
help="Sales order item that will be selected by default on the tasks and timesheets of this project,"
2525
" except if the employee set on the timesheets is explicitely linked to another sales order item on the project.\n"
2626
"It can be modified on each task and timesheet entry individually if necessary.")
@@ -759,7 +759,7 @@ class ProjectTask(models.Model):
759759
domain="""[
760760
'|', ('order_partner_id.commercial_partner_id.id', 'parent_of', partner_id if partner_id else []),
761761
('order_partner_id', '=?', partner_id),
762-
('is_service', '=', True), ('is_expense', '=', False), ('state', '=', 'sale'),
762+
('is_service', '=', True), ('is_expense', '=', False), ('state', '=', 'sale'), ('is_downpayment', '=', False),
763763
]""",
764764
help="Sales Order Item to which the time spent on this task will be added in order to be invoiced to your customer.\n"
765765
"By default the sales order item set on the project will be selected. In the absence of one, the last prepaid sales order item that has time remaining will be used.\n"

addons/sale_project/models/sale_order.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ def action_create_project(self):
175175
return {'type': 'ir.actions.act_window_close'}
176176

177177
sorted_line = self.order_line.sorted('sequence')
178-
default_sale_line = next(sol for sol in sorted_line if sol.product_id.detailed_type == 'service')
178+
default_sale_line = next((sol for sol in sorted_line if sol.product_id.detailed_type == 'service' and not sol.is_downpayment), self.env['sale.order.line'])
179179
return {
180180
**self.env["ir.actions.actions"]._for_xml_id("project.open_create_project"),
181181
'context': {

addons/sale_timesheet/models/account.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ def _default_sale_line_domain(self):
3838
('is_service', '=', True),
3939
('is_expense', '=', False),
4040
('state', '=', 'sale'),
41-
('order_partner_id', 'child_of', self.commercial_partner_id.ids)
41+
('order_partner_id', 'child_of', self.commercial_partner_id.ids),
42+
('is_downpayment', '=', False),
4243
], super()._default_sale_line_domain()])
4344

4445
@api.depends('commercial_partner_id')

addons/sale_timesheet/models/project.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,8 @@ def _compute_sale_line_id(self):
194194
('order_partner_id', 'child_of', project.partner_id.commercial_partner_id.id),
195195
('is_expense', '=', False),
196196
('state', '=', 'sale'),
197-
('remaining_hours', '>', 0)
197+
('remaining_hours', '>', 0),
198+
('is_downpayment', '=', False),
198199
], limit=1)
199200
project.sale_line_id = sol or project.sale_line_employee_ids.sale_line_id[:1] # get the first SOL containing in the employee mappings if no sol found in the search
200201

@@ -618,6 +619,7 @@ def _get_last_sol_of_customer(self):
618619
('is_expense', '=', False),
619620
('state', '=', 'sale'),
620621
('remaining_hours', '>', 0),
622+
('is_downpayment', '=', False),
621623
]
622624
if self.project_id.pricing_type != 'task_rate' and self.project_sale_order_id and self.partner_id.commercial_partner_id == self.project_id.partner_id.commercial_partner_id:
623625
domain.append(('order_id', '=?', self.project_sale_order_id.id))

addons/sale_timesheet/models/project_sale_line_employee_map.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ class ProjectProductEmployeeMap(models.Model):
1818
('is_service', '=', True),
1919
('is_expense', '=', False),
2020
('state', '=', 'sale'),
21-
('order_partner_id', '=?', partner_id)]""")
21+
('order_partner_id', '=?', partner_id),
22+
('is_downpayment', '=', False)]""")
2223
sale_order_id = fields.Many2one(related="project_id.sale_order_id")
2324
company_id = fields.Many2one('res.company', string='Company', related='project_id.company_id')
2425
partner_id = fields.Many2one(related='project_id.partner_id')

0 commit comments

Comments
 (0)