[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:
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user