[IMP] sale_{project,timesheet}: display price_unit when 2 SOLs for the same service

Before this commit, the `name_get` method is override in
`sale_timesheet` module to add the price_unit when more than one SOL is
shown for the same product in the same Sale Order. This override adds
the price unit only when the `with_price_unit` key is in the context, so
it is only used in the `sale_line_id` field defined in `project.project`
and `project.task` models and also `so_line` field in
`analytic.account.line` model when the user wants to set a SOL for those
models. However, the Sales section displayed in project right side
panel is added in `sale_project` and so we cannot use the override in
that module since `sale_timesheet` is not installed when `sale_project`.

This commit moves the part concerning the `with_price_unit` of the
`name_get` override defined in `sale_timesheet` module to `sale_project`
one. And then, we will use the context key in the Sales section to
display the price unit when there are more than one SOL for a same
product in a same Sales Order.

task-2814466

Part-of: odoo/odoo#88219
This commit is contained in:
Xavier BOL (xbo)
2022-04-08 17:13:30 +02:00
parent 3c5de9490a
commit e41a8b924c
3 changed files with 58 additions and 52 deletions
+1 -1
View File
@@ -272,7 +272,7 @@ class Project(models.Model):
return [{
**sol_read,
**get_action(sol_read['id']),
} for sol_read in sols.read(['display_name', 'product_uom_qty', 'qty_delivered', 'qty_invoiced', 'product_uom'])]
} for sol_read in sols.with_context(with_price_unit=True).read(['display_name', 'product_uom_qty', 'qty_delivered', 'qty_invoiced', 'product_uom'])]
def _get_sale_items_domain(self, additional_domain=None):
sale_orders = self._get_sale_order_items().sudo().order_id
@@ -1,7 +1,10 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from collections import defaultdict
from odoo import api, Command, fields, models, _
from odoo.tools import format_amount
from odoo.tools.sql import column_exists, create_column
@@ -18,6 +21,28 @@ class SaleOrderLine(models.Model):
is_service = fields.Boolean("Is a Service", compute='_compute_is_service', store=True, compute_sudo=True, help="Sales Order item should generate a task and/or a project, depending on the product settings.")
reached_milestones_ids = fields.One2many('project.milestone', 'sale_line_id', string='Reached Milestones', domain=[('is_reached', '=', True)])
def name_get(self):
res = super().name_get()
with_price_unit = self.env.context.get('with_price_unit')
if with_price_unit:
names = dict(res)
result = []
sols_by_so_dict = defaultdict(lambda: self.env[self._name]) # key: (sale_order_id, product_id), value: sale order line
for line in self:
sols_by_so_dict[line.order_id.id, line.product_id.id] += line
for sols in sols_by_so_dict.values():
if len(sols) > 1 and all(sols.mapped('is_service')):
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 += [(line.id, names.get(line.id)) for line in sols]
return result
return res
@api.depends('product_id.type')
def _compute_is_service(self):
for so_line in self:
+32 -51
View File
@@ -6,7 +6,7 @@ from collections import defaultdict
from odoo import api, fields, models, _
from odoo.osv import expression
from odoo.tools import float_compare, format_amount
from odoo.tools import float_compare
class SaleOrder(models.Model):
@@ -125,60 +125,41 @@ class SaleOrderLine(models.Model):
def name_get(self):
res = super(SaleOrderLine, self).name_get()
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:
if with_remaining_hours:
names = dict(res)
result = []
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
uom_hour = self.env.ref('uom.product_uom_hour')
uom_day = self.env.ref('uom.product_uom_day')
for line in self:
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 = 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_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)))
name = '{name}{remaining_time}'.format(
name=name,
remaining_time=remaining_time
)
result.append((line.id, name))
return result
return res