diff --git a/modules/account_invoice/purchase_commission_ict.fodt b/modules/account_invoice/purchase_commission_ict.fodt
index c6e2352..e43b195 100644
--- a/modules/account_invoice/purchase_commission_ict.fodt
+++ b/modules/account_invoice/purchase_commission_ict.fodt
@@ -17143,7 +17143,7 @@
- <for each="line in invoice.report_commission_address.splitlines()"><line></for>
+ <for each="line in invoice.report_purchase_commission_address.splitlines()"><line></for>
@@ -17155,11 +17155,11 @@
COMMISSION INVOICE
- INVOICE N. <invoice.report_commission_invoice_number>
- CONTRACT N. <invoice.report_commission_contract_number>
+ INVOICE N. <invoice.report_purchase_commission_invoice_number>
+ CONTRACT N. <invoice.report_purchase_commission_contract_number>
- <format_date(invoice.report_commission_date or today, invoice.party.lang)>
+ <format_date(invoice.report_purchase_commission_date or today, invoice.party.lang)>
@@ -17170,8 +17170,8 @@
- Bill of Lading N. <invoice.report_commission_bl_number> dated <format_date(invoice.report_commission_bl_date, invoice.party.lang) if invoice.report_commission_bl_date else ''>
- M/V <invoice.report_commission_vessel>
+ Bill of Lading N. <invoice.report_purchase_commission_bl_number> dated <format_date(invoice.report_purchase_commission_bl_date, invoice.party.lang) if invoice.report_purchase_commission_bl_date else ''>
+ M/V <invoice.report_purchase_commission_vessel>
@@ -17179,16 +17179,16 @@
COMMISSION
- <invoice.report_commission_invoice_line>
+ <invoice.report_purchase_commission_invoice_line>
- <invoice.report_commission_quantity_unit_upper>
+ <invoice.report_purchase_commission_quantity_unit_upper>
- <invoice.report_commission_quantity_display>
+ <invoice.report_purchase_commission_quantity_display>
@@ -17196,12 +17196,12 @@
Lbs
- <invoice.report_commission_lbs_display>
+ <invoice.report_purchase_commission_lbs_display>
- Your commission: <invoice.report_commission_rate_line>
- <invoice.report_commission_secondary_rate_line>
+ Your commission: <invoice.report_purchase_commission_rate_line>
+ <invoice.report_purchase_commission_secondary_rate_line>
VAT 0% RATE
@@ -17214,10 +17214,10 @@
TOTAL DUE TO YOU
- <invoice.report_commission_currency_name>
+ <invoice.report_purchase_commission_currency_name>
- <invoice.report_commission_total_display>
+ <invoice.report_purchase_commission_total_display>
@@ -17226,4 +17226,4 @@
</for>
-
\ No newline at end of file
+
diff --git a/modules/account_invoice/sale_commission_ict.fodt b/modules/account_invoice/sale_commission_ict.fodt
index 0252f76..9e109ab 100644
--- a/modules/account_invoice/sale_commission_ict.fodt
+++ b/modules/account_invoice/sale_commission_ict.fodt
@@ -3639,7 +3639,7 @@
- <for each="line in invoice.report_commission_address.splitlines()"><line></for>
+ <for each="line in invoice.report_sale_commission_address.splitlines()"><line></for>
@@ -3653,11 +3653,11 @@
COMMISSION INVOICE
- INVOICE N. <invoice.report_commission_invoice_number>
- CONTRACT N. <invoice.report_commission_contract_number>
+ INVOICE N. <invoice.report_sale_commission_invoice_number>
+ CONTRACT N. <invoice.report_sale_commission_contract_number>
- <format_date(invoice.report_commission_date or today, invoice.party.lang)>
+ <format_date(invoice.report_sale_commission_date or today, invoice.party.lang)>
@@ -3667,8 +3667,8 @@
- Bill of Lading N. <invoice.report_commission_bl_number> dated <format_date(invoice.report_commission_bl_date, invoice.party.lang) if invoice.report_commission_bl_date else ''>
- M/V <invoice.report_commission_vessel>
+ Bill of Lading N. <invoice.report_sale_commission_bl_number> dated <format_date(invoice.report_sale_commission_bl_date, invoice.party.lang) if invoice.report_sale_commission_bl_date else ''>
+ M/V <invoice.report_sale_commission_vessel>
@@ -3677,16 +3677,16 @@
COMMISSION
- <invoice.report_commission_invoice_line>
+ <invoice.report_sale_commission_invoice_line>
- <invoice.report_commission_quantity_unit_upper>
+ <invoice.report_sale_commission_quantity_unit_upper>
- <invoice.report_commission_quantity_display>
+ <invoice.report_sale_commission_quantity_display>
@@ -3694,12 +3694,12 @@
Lbs
- <invoice.report_commission_lbs_display>
+ <invoice.report_sale_commission_lbs_display>
- Your commission: <invoice.report_commission_rate_line>
- <invoice.report_commission_secondary_rate_line>
+ Your commission: <invoice.report_sale_commission_rate_line>
+ <invoice.report_sale_commission_secondary_rate_line>
VAT 0% RATE
@@ -3714,10 +3714,10 @@
- <invoice.report_commission_currency_name>
+ <invoice.report_sale_commission_currency_name>
- <invoice.report_commission_total_display>
+ <invoice.report_sale_commission_total_display>
@@ -3727,4 +3727,4 @@
</for>
-
\ No newline at end of file
+
diff --git a/modules/purchase_trade/invoice.py b/modules/purchase_trade/invoice.py
index 96f2bb5..76db961 100644
--- a/modules/purchase_trade/invoice.py
+++ b/modules/purchase_trade/invoice.py
@@ -319,7 +319,71 @@ class Invoice(metaclass=PoolMeta):
]
return lines or list(self.lines or [])
+ @staticmethod
+ def _report_record_name(record):
+ if not record:
+ return ''
+ return (
+ getattr(record, 'rec_name', None)
+ or getattr(record, 'name', None)
+ or getattr(record, 'code', None)
+ or '')
+
+ def _get_report_commission_fee(self):
+ for line in self._get_report_invoice_lines():
+ fee = getattr(line, 'fee', None)
+ if fee:
+ return fee
+ origin = getattr(line, 'origin', None)
+ fee = getattr(origin, 'fee_', None)
+ if fee:
+ return fee
+
+ def _get_report_commission_lots(self):
+ lots = []
+ seen = set()
+
+ def add_lot(lot):
+ if not lot:
+ return
+ lot_id = getattr(lot, 'id', None)
+ key = ('id', lot_id) if lot_id is not None else ('obj', id(lot))
+ if key in seen:
+ return
+ seen.add(key)
+ lots.append(lot)
+
+ for line in self._get_report_invoice_lines():
+ add_lot(getattr(line, 'lot', None))
+ fee = self._get_report_commission_fee()
+ if fee and hasattr(fee, '_get_effective_fee_lots'):
+ for lot in fee._get_effective_fee_lots():
+ add_lot(lot)
+ for lot in getattr(fee, 'lots', []) or []:
+ add_lot(lot)
+ return lots
+
+ def _get_report_commission_trade_for(self, kind):
+ fee = self._get_report_commission_fee()
+ if fee:
+ if kind == 'sale' and getattr(fee, 'sale_line', None):
+ return fee.sale_line.sale
+ if kind == 'purchase' and getattr(fee, 'line', None):
+ return fee.line.purchase
+ for lot in self._get_report_commission_lots():
+ if kind == 'sale' and getattr(lot, 'sale_line', None):
+ return lot.sale_line.sale
+ if kind == 'purchase' and getattr(lot, 'line', None):
+ return lot.line.purchase
+ records = getattr(self, kind + 's', None)
+ if records:
+ return records[0]
+
def _get_report_commission_trade(self):
+ for kind in ('sale', 'purchase'):
+ trade = self._get_report_commission_trade_for(kind)
+ if trade:
+ return trade
for line in self._get_report_invoice_lines():
origin = getattr(line, 'origin', None)
if not origin:
@@ -345,6 +409,10 @@ class Invoice(metaclass=PoolMeta):
trade = self._get_report_commission_trade()
return getattr(trade, name, '') if trade else ''
+ def _get_report_commission_value_for(self, kind, name):
+ trade = self._get_report_commission_trade_for(kind)
+ return getattr(trade, name, '') if trade else ''
+
@property
def report_commission_invoice_number(self):
return self._get_report_commission_value(
@@ -400,6 +468,76 @@ class Invoice(metaclass=PoolMeta):
return self._get_report_commission_value(
'report_commission_secondary_rate_line')
+ def _get_report_commission_base_amount_display_for(self, kind):
+ trade = self._get_report_commission_trade_for(kind)
+ if trade:
+ base = getattr(trade, 'report_commission_base_amount_display', None)
+ if base:
+ return base
+ amount = (
+ getattr(trade, 'untaxed_amount', None)
+ or getattr(trade, 'total_amount', None)
+ or 0)
+ return self._format_report_number(
+ amount, digits='0.01', strip_trailing_zeros=False)
+ return self.report_commission_total_display
+
+ def _get_report_commission_currency_name_for(self, kind):
+ trade = self._get_report_commission_trade_for(kind)
+ currency = getattr(trade, 'currency', None) if trade else self.currency
+ return self._report_record_name(currency)
+
+ def _get_report_commission_rate_line_for(self, kind):
+ fee = self._get_report_commission_fee()
+ if not fee:
+ return self._get_report_commission_value(
+ 'report_commission_rate_line')
+
+ mode = getattr(fee, 'mode', None)
+ price = getattr(fee, 'price', None) or 0
+ if mode in {'pprice', 'rate', 'pcost'}:
+ return ' '.join(part for part in [
+ self._format_report_number(price, digits='0.0000'),
+ '% on',
+ kind,
+ 'amount',
+ self._get_report_commission_base_amount_display_for(kind),
+ self._get_report_commission_currency_name_for(kind),
+ ] if part)
+
+ if (getattr(fee, 'enable_linked_currency', False)
+ and getattr(fee, 'linked_price', None) is not None):
+ price = fee.linked_price
+ currency = getattr(fee, 'linked_currency', None)
+ unit = getattr(fee, 'linked_unit', None)
+ else:
+ currency = getattr(fee, 'currency', None)
+ unit = getattr(fee, 'unit', None)
+ price_text = self._format_report_number(price, digits='0.0000')
+ currency_text = self._report_record_name(currency)
+ unit_text = self._report_record_name(unit)
+ if currency_text and unit_text:
+ return '%s %s/%s' % (price_text, currency_text, unit_text)
+ return ' '.join(part for part in [
+ price_text, currency_text or unit_text,
+ ] if part)
+
+ @property
+ def report_sale_commission_rate_line(self):
+ return self._get_report_commission_rate_line_for('sale')
+
+ @property
+ def report_purchase_commission_rate_line(self):
+ return self._get_report_commission_rate_line_for('purchase')
+
+ @property
+ def report_sale_commission_secondary_rate_line(self):
+ return ''
+
+ @property
+ def report_purchase_commission_secondary_rate_line(self):
+ return ''
+
@property
def report_commission_currency_name(self):
return self._get_report_commission_value(
@@ -410,6 +548,149 @@ class Invoice(metaclass=PoolMeta):
return self._get_report_commission_value(
'report_commission_total_display')
+ def _get_report_commission_address_for(self, kind):
+ trade = self._get_report_commission_trade_for(kind)
+ return getattr(trade, 'report_address', '') or ''
+
+ def _get_report_commission_date_for(self, kind):
+ trade = self._get_report_commission_trade_for(kind)
+ return (
+ getattr(trade, 'sale_date', None)
+ or getattr(trade, 'purchase_date', None)
+ or self.invoice_date)
+
+ def _get_report_commission_total_display_for(self, kind):
+ fee = self._get_report_commission_fee()
+ if fee and hasattr(fee, 'get_amount'):
+ amount = fee.get_amount()
+ else:
+ amount = self.total_amount or 0
+ return self._format_report_number(
+ abs(Decimal(str(amount or 0))), digits='0.01',
+ strip_trailing_zeros=False)
+
+ @property
+ def report_sale_commission_address(self):
+ return self._get_report_commission_address_for('sale')
+
+ @property
+ def report_purchase_commission_address(self):
+ return self._get_report_commission_address_for('purchase')
+
+ @property
+ def report_sale_commission_date(self):
+ return self._get_report_commission_date_for('sale')
+
+ @property
+ def report_purchase_commission_date(self):
+ return self._get_report_commission_date_for('purchase')
+
+ @property
+ def report_sale_commission_invoice_number(self):
+ return self._get_report_commission_value_for(
+ 'sale', 'report_commission_invoice_number')
+
+ @property
+ def report_purchase_commission_invoice_number(self):
+ return self._get_report_commission_value_for(
+ 'purchase', 'report_commission_invoice_number')
+
+ @property
+ def report_sale_commission_contract_number(self):
+ return self._get_report_commission_value_for(
+ 'sale', 'report_commission_contract_number')
+
+ @property
+ def report_purchase_commission_contract_number(self):
+ return self._get_report_commission_value_for(
+ 'purchase', 'report_commission_contract_number')
+
+ @property
+ def report_sale_commission_bl_number(self):
+ return self._get_report_commission_value_for(
+ 'sale', 'report_commission_bl_number')
+
+ @property
+ def report_purchase_commission_bl_number(self):
+ return self._get_report_commission_value_for(
+ 'purchase', 'report_commission_bl_number')
+
+ @property
+ def report_sale_commission_bl_date(self):
+ return self._get_report_commission_value_for(
+ 'sale', 'report_commission_bl_date')
+
+ @property
+ def report_purchase_commission_bl_date(self):
+ return self._get_report_commission_value_for(
+ 'purchase', 'report_commission_bl_date')
+
+ @property
+ def report_sale_commission_vessel(self):
+ return self._get_report_commission_value_for(
+ 'sale', 'report_commission_vessel')
+
+ @property
+ def report_purchase_commission_vessel(self):
+ return self._get_report_commission_value_for(
+ 'purchase', 'report_commission_vessel')
+
+ @property
+ def report_sale_commission_invoice_line(self):
+ return self._get_report_commission_value_for(
+ 'sale', 'report_commission_invoice_line')
+
+ @property
+ def report_purchase_commission_invoice_line(self):
+ return self._get_report_commission_value_for(
+ 'purchase', 'report_commission_invoice_line')
+
+ @property
+ def report_sale_commission_quantity_unit_upper(self):
+ return self._get_report_commission_value_for(
+ 'sale', 'report_commission_quantity_unit_upper')
+
+ @property
+ def report_purchase_commission_quantity_unit_upper(self):
+ return self._get_report_commission_value_for(
+ 'purchase', 'report_commission_quantity_unit_upper')
+
+ @property
+ def report_sale_commission_quantity_display(self):
+ return self._get_report_commission_value_for(
+ 'sale', 'report_commission_quantity_display')
+
+ @property
+ def report_purchase_commission_quantity_display(self):
+ return self._get_report_commission_value_for(
+ 'purchase', 'report_commission_quantity_display')
+
+ @property
+ def report_sale_commission_lbs_display(self):
+ return self._get_report_commission_value_for(
+ 'sale', 'report_commission_lbs_display')
+
+ @property
+ def report_purchase_commission_lbs_display(self):
+ return self._get_report_commission_value_for(
+ 'purchase', 'report_commission_lbs_display')
+
+ @property
+ def report_sale_commission_currency_name(self):
+ return self._report_record_name(self.currency)
+
+ @property
+ def report_purchase_commission_currency_name(self):
+ return self._report_record_name(self.currency)
+
+ @property
+ def report_sale_commission_total_display(self):
+ return self._get_report_commission_total_display_for('sale')
+
+ @property
+ def report_purchase_commission_total_display(self):
+ return self._get_report_commission_total_display_for('purchase')
+
@staticmethod
def _get_report_related_lots(line):
lots = []
diff --git a/modules/purchase_trade/tests/test_module.py b/modules/purchase_trade/tests/test_module.py
index 36ad46b..b5703ff 100644
--- a/modules/purchase_trade/tests/test_module.py
+++ b/modules/purchase_trade/tests/test_module.py
@@ -4,6 +4,7 @@
import datetime
from contextlib import nullcontext
from decimal import Decimal
+from types import SimpleNamespace
from unittest.mock import ANY, Mock, patch
from xml.etree import ElementTree
@@ -5210,6 +5211,68 @@ class PurchaseTradeTestCase(ModuleTestCase):
'amount': None,
}])
+ def test_sale_commission_invoice_uses_linked_perqt_fee_rate(self):
+ 'sale commission invoice shows linked fee price per sale quantity'
+ Invoice = Pool().get('account.invoice')
+ sale = SimpleNamespace(
+ currency=SimpleNamespace(rec_name='USD'),
+ untaxed_amount=Decimal('7960'),
+ total_amount=Decimal('7960'))
+ sale_line = SimpleNamespace(sale=sale)
+ lot = SimpleNamespace(id=1, sale_line=sale_line, line=None)
+ fee = SimpleNamespace(
+ mode='perqt',
+ price=Decimal('0.02'),
+ enable_linked_currency=True,
+ linked_price=Decimal('2'),
+ linked_currency=SimpleNamespace(rec_name='USC'),
+ linked_unit=SimpleNamespace(rec_name='Kilogram'),
+ currency=SimpleNamespace(rec_name='USD'),
+ unit=SimpleNamespace(rec_name='MT'),
+ sale_line=sale_line,
+ line=None,
+ lots=[lot],
+ _get_effective_fee_lots=lambda: [lot])
+ invoice = Invoice()
+ invoice.currency = SimpleNamespace(rec_name='USD')
+ invoice.lines = [
+ SimpleNamespace(type='line', fee=fee, lot=lot, origin=None)]
+
+ self.assertEqual(
+ invoice.report_sale_commission_rate_line,
+ '2 USC/Kilogram')
+ self.assertEqual(invoice.report_sale_commission_secondary_rate_line, '')
+
+ def test_purchase_commission_invoice_uses_purchase_amount_for_percent_fee(self):
+ 'purchase commission invoice shows percent fee on purchase amount'
+ Invoice = Pool().get('account.invoice')
+ purchase = SimpleNamespace(
+ currency=SimpleNamespace(rec_name='USD'),
+ untaxed_amount=Decimal('7960'),
+ total_amount=Decimal('7960'))
+ purchase_line = SimpleNamespace(purchase=purchase)
+ lot = SimpleNamespace(id=1, line=purchase_line, sale_line=None)
+ fee = SimpleNamespace(
+ mode='pprice',
+ price=Decimal('1.5'),
+ enable_linked_currency=False,
+ currency=SimpleNamespace(rec_name='USD'),
+ unit=SimpleNamespace(rec_name='MT'),
+ sale_line=None,
+ line=purchase_line,
+ lots=[lot],
+ _get_effective_fee_lots=lambda: [lot])
+ invoice = Invoice()
+ invoice.currency = SimpleNamespace(rec_name='USD')
+ invoice.lines = [
+ SimpleNamespace(type='line', fee=fee, lot=lot, origin=None)]
+
+ self.assertEqual(
+ invoice.report_purchase_commission_rate_line,
+ '1.5 % on purchase amount 7960.00 USD')
+ self.assertEqual(
+ invoice.report_purchase_commission_secondary_rate_line, '')
+
def test_fee_delete_detects_generated_ordered_purchase(self):
'ordered fee deletion targets only its generated service purchase'
Fee = Pool().get('fee.fee')