Price composition
This commit is contained in:
@@ -916,6 +916,9 @@ class Invoice(metaclass=PoolMeta):
|
||||
|
||||
@property
|
||||
def report_rate_lines(self):
|
||||
price_composition_lines = self._get_report_price_composition_lines()
|
||||
if price_composition_lines:
|
||||
return price_composition_lines
|
||||
details = []
|
||||
for line in self._get_report_invoice_lines():
|
||||
currency = getattr(line, 'report_rate_currency_upper', '') or ''
|
||||
@@ -940,6 +943,18 @@ class Invoice(metaclass=PoolMeta):
|
||||
details.append(detail)
|
||||
return '\n'.join(details)
|
||||
|
||||
def _get_report_price_composition_lines(self):
|
||||
sale = self._get_report_sale()
|
||||
if sale and getattr(sale, 'report_price_composition_lines', None):
|
||||
return sale.report_price_composition_lines
|
||||
details = []
|
||||
for line in self._get_report_invoice_lines():
|
||||
origin = getattr(line, 'origin', None)
|
||||
sale = getattr(origin, 'sale', None)
|
||||
if sale and getattr(sale, 'report_price_composition_lines', None):
|
||||
return sale.report_price_composition_lines
|
||||
return '\n'.join(details)
|
||||
|
||||
@property
|
||||
def report_positive_rate_lines(self):
|
||||
sale = self._get_report_sale()
|
||||
|
||||
@@ -846,6 +846,37 @@ class Sale(metaclass=PoolMeta):
|
||||
return '\n'.join(self._format_report_price_line(line) for line in lines)
|
||||
return ''
|
||||
|
||||
@property
|
||||
def report_price_composition_lines(self):
|
||||
lines = []
|
||||
for line in self._get_report_lines():
|
||||
currency = self._get_report_display_currency(line)
|
||||
unit = self._get_report_display_unit(line)
|
||||
currency_name = (
|
||||
currency.rec_name.upper()
|
||||
if currency and currency.rec_name else '')
|
||||
unit_name = (
|
||||
unit.rec_name.upper()
|
||||
if unit and unit.rec_name else '')
|
||||
for composition in getattr(line, 'price_composition', []) or []:
|
||||
component = getattr(composition, 'component', '') or ''
|
||||
price = getattr(composition, 'price', None)
|
||||
if price in (None, ''):
|
||||
continue
|
||||
price_text = self._format_report_number(
|
||||
price, strip_trailing_zeros=False)
|
||||
detail = ' '.join(
|
||||
part for part in [
|
||||
component,
|
||||
currency_name,
|
||||
price_text,
|
||||
'PER' if unit_name else '',
|
||||
unit_name,
|
||||
] if part)
|
||||
if detail:
|
||||
lines.append(detail)
|
||||
return '\n'.join(lines)
|
||||
|
||||
@property
|
||||
def report_trade_blocks(self):
|
||||
lines = self._get_report_lines()
|
||||
|
||||
@@ -2589,6 +2589,50 @@ class PurchaseTradeTestCase(ModuleTestCase):
|
||||
'USC 70.2500 PER POUND (SEVENTY USC AND TWENTY FIVE CENTS) ON ICE Cotton #2 MAY 2026',
|
||||
])
|
||||
|
||||
def test_sale_report_price_composition_lines_uses_composition(self):
|
||||
'sale report exposes price composition lines for invoice_melya'
|
||||
Sale = Pool().get('sale.sale')
|
||||
|
||||
line = Mock()
|
||||
line.type = 'line'
|
||||
line.price_type = 'priced'
|
||||
line.linked_currency = None
|
||||
line.linked_unit = None
|
||||
line.unit = Mock(rec_name='MT')
|
||||
line.unit_price = Decimal('2525')
|
||||
line.price_composition = [
|
||||
Mock(component='FOB', price=Decimal('2500')),
|
||||
Mock(component='FREIGHT', price=Decimal('25')),
|
||||
]
|
||||
|
||||
sale = Sale()
|
||||
sale.currency = Mock(rec_name='EUR')
|
||||
sale.lines = [line]
|
||||
|
||||
self.assertEqual(
|
||||
sale.report_price_composition_lines.splitlines(),
|
||||
[
|
||||
'FOB EUR 2500.0000 PER MT',
|
||||
'FREIGHT EUR 25.0000 PER MT',
|
||||
])
|
||||
|
||||
def test_invoice_report_rate_lines_prefers_sale_price_composition(self):
|
||||
'invoice_melya rate block uses sale price composition when available'
|
||||
Invoice = Pool().get('account.invoice')
|
||||
sale = Mock(
|
||||
report_price_composition_lines=(
|
||||
'FOB EUR 2500.0000 PER MT\n'
|
||||
'FREIGHT EUR 25.0000 PER MT'))
|
||||
invoice = Invoice()
|
||||
invoice.sales = [sale]
|
||||
|
||||
self.assertEqual(
|
||||
invoice.report_rate_lines.splitlines(),
|
||||
[
|
||||
'FOB EUR 2500.0000 PER MT',
|
||||
'FREIGHT EUR 25.0000 PER MT',
|
||||
])
|
||||
|
||||
def test_sale_report_converts_mixed_units_for_total_and_words(self):
|
||||
'sale report totals prefer the virtual lot unit as common unit'
|
||||
Sale = Pool().get('sale.sale')
|
||||
|
||||
Reference in New Issue
Block a user