[IMP] sale_timesheet: display price_unit in SOL name_get
Before this commit, when many sales order items have a same product with a different price_unit, the user cannot know which one of these sales order items has the product with the expensive price with just the name_get of the SOL in task form view. This commit adds the price_unit in the name_get of the sale order items only for the sales order items in a same sales order have the same product. task-2376382 closes #66157
This commit is contained in:
@@ -2,10 +2,11 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import math
|
||||
from collections import defaultdict
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.osv import expression
|
||||
from odoo.tools import float_compare
|
||||
from odoo.tools import float_compare, format_amount
|
||||
|
||||
|
||||
class SaleOrder(models.Model):
|
||||
@@ -134,41 +135,61 @@ class SaleOrderLine(models.Model):
|
||||
|
||||
def name_get(self):
|
||||
res = super(SaleOrderLine, self).name_get()
|
||||
if self.env.context.get('with_remaining_hours'):
|
||||
with_remaining_hours = self.env.context.get('with_remaining_hours')
|
||||
with_price_unit = self.env.context.get('with_price_unit')
|
||||
if with_remaining_hours or with_price_unit:
|
||||
names = dict(res)
|
||||
result = []
|
||||
uom_hour = self.env.ref('uom.product_uom_hour')
|
||||
uom_day = self.env.ref('uom.product_uom_day')
|
||||
uom_hour = with_remaining_hours and self.env.ref('uom.product_uom_hour')
|
||||
uom_day = with_remaining_hours and self.env.ref('uom.product_uom_day')
|
||||
sols_by_so_dict = with_price_unit and defaultdict(lambda: self.env[self._name]) # key: (sale_order_id, product_id), value: sale order line
|
||||
for line in self:
|
||||
name = names.get(line.id)
|
||||
if line.remaining_hours_available:
|
||||
company = self.env.company
|
||||
encoding_uom = company.timesheet_encode_uom_id
|
||||
remaining_time = ''
|
||||
if encoding_uom == uom_hour:
|
||||
hours, minutes = divmod(abs(line.remaining_hours) * 60, 60)
|
||||
round_minutes = minutes / 30
|
||||
minutes = math.ceil(round_minutes) if line.remaining_hours >= 0 else math.floor(round_minutes)
|
||||
if minutes > 1:
|
||||
minutes = 0
|
||||
hours += 1
|
||||
else:
|
||||
minutes = minutes * 30
|
||||
remaining_time = ' ({sign}{hours:02.0f}:{minutes:02.0f})'.format(
|
||||
sign='-' if line.remaining_hours < 0 else '',
|
||||
hours=hours,
|
||||
minutes=minutes)
|
||||
elif encoding_uom == uom_day:
|
||||
remaining_days = company.project_time_mode_id._compute_quantity(line.remaining_hours, encoding_uom, round=False)
|
||||
remaining_time = ' ({qty:.02f} {unit})'.format(
|
||||
qty=remaining_days,
|
||||
unit=_('days') if abs(remaining_days) > 1 else _('day')
|
||||
if with_remaining_hours:
|
||||
name = names.get(line.id)
|
||||
if line.remaining_hours_available:
|
||||
company = self.env.company
|
||||
encoding_uom = company.timesheet_encode_uom_id
|
||||
remaining_time = ''
|
||||
if encoding_uom == uom_hour:
|
||||
hours, minutes = divmod(abs(line.remaining_hours) * 60, 60)
|
||||
round_minutes = minutes / 30
|
||||
minutes = math.ceil(round_minutes) if line.remaining_hours >= 0 else math.floor(round_minutes)
|
||||
if minutes > 1:
|
||||
minutes = 0
|
||||
hours += 1
|
||||
else:
|
||||
minutes = minutes * 30
|
||||
remaining_time = ' ({sign}{hours:02.0f}:{minutes:02.0f})'.format(
|
||||
sign='-' if line.remaining_hours < 0 else '',
|
||||
hours=hours,
|
||||
minutes=minutes)
|
||||
elif encoding_uom == uom_day:
|
||||
remaining_days = company.project_time_mode_id._compute_quantity(line.remaining_hours, encoding_uom, round=False)
|
||||
remaining_time = ' ({qty:.02f} {unit})'.format(
|
||||
qty=remaining_days,
|
||||
unit=_('days') if abs(remaining_days) > 1 else _('day')
|
||||
)
|
||||
name = '{name}{remaining_time}'.format(
|
||||
name=name,
|
||||
remaining_time=remaining_time
|
||||
)
|
||||
name = '{name}{remaining_time}'.format(
|
||||
name=name,
|
||||
remaining_time=remaining_time
|
||||
)
|
||||
result.append((line.id, name))
|
||||
if with_price_unit:
|
||||
names[line.id] = name
|
||||
if not with_price_unit:
|
||||
result.append((line.id, name))
|
||||
if with_price_unit:
|
||||
sols_by_so_dict[line.order_id.id, line.product_id.id] += line
|
||||
|
||||
if with_price_unit:
|
||||
for sols in sols_by_so_dict.values():
|
||||
if len(sols) > 1:
|
||||
result += [(
|
||||
line.id,
|
||||
'%s - %s' % (
|
||||
names.get(line.id), format_amount(self.env, line.price_unit, line.currency_id))
|
||||
) for line in sols]
|
||||
else:
|
||||
result.append((sols.id, names.get(sols.id)))
|
||||
return result
|
||||
return res
|
||||
|
||||
|
||||
@@ -153,7 +153,7 @@
|
||||
<field name="timesheet_invoice_id" invisible="1"/>
|
||||
<field name="so_line"
|
||||
attrs="{'column_invisible': [('parent.allow_billable', '=', False)]}"
|
||||
context="{'with_remaining_hours': True}" options="{'no_create': True, 'no_open': 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.commercial_partner_id), ('is_expense', '=', False), ('state', 'in', ['sale', 'done']), ('order_id', '=?', parent.project_sale_order_id)]"
|
||||
optional="hide"/>
|
||||
</xpath>
|
||||
@@ -192,7 +192,7 @@
|
||||
<field name="inherit_id" ref="project.view_task_form2"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='sale_line_id']" position="attributes">
|
||||
<attribute name="context">{'with_remaining_hours': True}</attribute>
|
||||
<attribute name="context">{'with_remaining_hours': True, 'with_price_unit': True}</attribute>
|
||||
<attribute name="attrs">
|
||||
{'invisible': ['|', ('allow_billable', '=', False), ('partner_id', '=', False)]}
|
||||
</attribute>
|
||||
|
||||
Reference in New Issue
Block a user