From 6ba5361269cd2c14d269f0e0c466a8355fa45e48 Mon Sep 17 00:00:00 2001 From: laurentbarontini Date: Wed, 17 Jun 2026 10:52:29 +0200 Subject: [PATCH] CN/DN --- .../commission__ict_final.fodt | 18 +-- modules/purchase_trade/invoice.py | 140 ++++++++++++++++++ modules/purchase_trade/tests/test_module.py | 30 ++++ 3 files changed, 179 insertions(+), 9 deletions(-) diff --git a/modules/account_invoice/commission__ict_final.fodt b/modules/account_invoice/commission__ict_final.fodt index 33fc9fa..fe3e494 100644 --- a/modules/account_invoice/commission__ict_final.fodt +++ b/modules/account_invoice/commission__ict_final.fodt @@ -3787,10 +3787,10 @@ Net Invoice Weight - <invoice.report_net_display> + <invoice.report_commission_invoice_weight_display> - <invoice.report_weight_unit_upper> + <invoice.report_commission_adjustment_unit_upper> @@ -3804,10 +3804,10 @@ Net Landed Weight - <invoice.report_gross_display> + <invoice.report_commission_landed_weight_display> - <invoice.report_weight_unit_upper> + <invoice.report_commission_adjustment_unit_upper> @@ -3815,7 +3815,7 @@ or - <invoice.report_gross_lbs_display> + <invoice.report_commission_landed_lbs_display> LBS @@ -3832,10 +3832,10 @@ Difference in Weight - <invoice.report_weight_difference_display> + <invoice.report_commission_weight_difference_display> - KG + <invoice.report_commission_adjustment_unit_upper> @@ -3843,7 +3843,7 @@ or - <invoice.report_weight_difference_lbs_display> + <invoice.report_commission_weight_difference_lbs_display> LBS @@ -3883,4 +3883,4 @@ - \ No newline at end of file + diff --git a/modules/purchase_trade/invoice.py b/modules/purchase_trade/invoice.py index 97fa988..dba3c3b 100644 --- a/modules/purchase_trade/invoice.py +++ b/modules/purchase_trade/invoice.py @@ -392,6 +392,146 @@ class Invoice(metaclass=PoolMeta): if trade: return trade + def _get_report_commission_kind(self): + fee = self._get_report_commission_fee() + if fee: + if getattr(fee, 'sale_line', None): + return 'sale' + if getattr(fee, 'line', None): + return 'purchase' + for lot in self._get_report_commission_lots(): + if getattr(lot, 'sale_line', None): + return 'sale' + if getattr(lot, 'line', None): + return 'purchase' + + def _get_report_commission_adjustment_unit(self): + fee = self._get_report_commission_fee() + if fee: + unit = ( + getattr(fee, 'linked_unit', None) + if getattr(fee, 'enable_linked_currency', False) else None) + if unit: + return unit + if getattr(fee, 'unit', None): + return fee.unit + lots = self._get_report_commission_lots() + if lots: + lot = lots[0] + return ( + getattr(lot, 'lot_unit_line', None) + or getattr(lot, 'lot_unit', None)) + line = self._get_report_invoice_line() + return getattr(line, 'unit', None) if line else None + + def _get_report_commission_provisional_line(self, lot, kind): + if kind == 'sale': + return getattr(lot, 'sale_invoice_line_prov', None) + return getattr(lot, 'invoice_line_prov', None) + + def _get_report_commission_lot_current_quantity(self, lot, unit): + if hasattr(lot, 'get_current_quantity_converted'): + try: + return Decimal(str( + lot.get_current_quantity_converted(0, unit) or 0)) + except TypeError: + return Decimal(str( + lot.get_current_quantity_converted() or 0)) + net, _ = self._get_report_lot_hist_weights(lot) + if net is None: + return Decimal(0) + return self._convert_report_quantity( + net, getattr(lot, 'lot_unit_line', None), unit) + + def _get_report_commission_lot_provisional_quantity(self, lot, kind, unit): + line = self._get_report_commission_provisional_line(lot, kind) + if not line: + return None + quantity = Decimal(str(getattr(line, 'quantity', 0) or 0)) + if kind == 'sale': + quantity -= Decimal(str( + getattr(lot, 'sale_invoice_padding', 0) or 0)) + return self._convert_report_quantity( + quantity, getattr(line, 'unit', None), unit) + + def _get_report_commission_adjustment_totals(self): + kind = self._get_report_commission_kind() + unit = self._get_report_commission_adjustment_unit() + if not kind or not unit: + return None + invoice_total = Decimal(0) + landed_total = Decimal(0) + matched = False + for lot in self._get_report_commission_lots(): + provisional_quantity = ( + self._get_report_commission_lot_provisional_quantity( + lot, kind, unit)) + if provisional_quantity is None: + continue + invoice_total += abs(provisional_quantity) + landed_total += abs( + self._get_report_commission_lot_current_quantity(lot, unit)) + matched = True + if not matched: + return None + return { + 'invoice': invoice_total, + 'landed': landed_total, + 'difference': abs(landed_total - invoice_total), + 'unit': unit, + } + + @property + def report_commission_adjustment_unit_upper(self): + totals = self._get_report_commission_adjustment_totals() + unit = totals['unit'] if totals else self._get_report_commission_adjustment_unit() + if unit: + return ( + getattr(unit, 'symbol', None) + or getattr(unit, 'rec_name', None) + or getattr(unit, 'name', None) + or '').upper() + return '' + + @property + def report_commission_invoice_weight_display(self): + totals = self._get_report_commission_adjustment_totals() + if not totals: + return self.report_net_display + return self._format_report_quantity_display(totals['invoice']) + + @property + def report_commission_landed_weight_display(self): + totals = self._get_report_commission_adjustment_totals() + if not totals: + return self.report_gross_display + return self._format_report_quantity_display(totals['landed']) + + @property + def report_commission_landed_lbs_display(self): + totals = self._get_report_commission_adjustment_totals() + if not totals: + return self.report_gross_lbs_display + lbs = self._convert_report_quantity_to_lbs( + totals['landed'], totals['unit']) + return self._format_report_quantity_display(lbs) + + @property + def report_commission_weight_difference_display(self): + totals = self._get_report_commission_adjustment_totals() + if not totals: + return self.report_weight_difference_display + return self._format_report_quantity_display(totals['difference']) + + @property + def report_commission_weight_difference_lbs_display(self): + totals = self._get_report_commission_adjustment_totals() + if not totals: + return self.report_weight_difference_lbs_display + lbs = self._convert_report_quantity_to_lbs( + totals['difference'], totals['unit']) + return self._format_report_quantity_display(lbs) + @property def report_commission_address(self): trade = self._get_report_commission_trade() diff --git a/modules/purchase_trade/tests/test_module.py b/modules/purchase_trade/tests/test_module.py index 9532e29..b20b231 100644 --- a/modules/purchase_trade/tests/test_module.py +++ b/modules/purchase_trade/tests/test_module.py @@ -5468,6 +5468,36 @@ class PurchaseTradeTestCase(ModuleTestCase): self.assertEqual( invoice.report_purchase_commission_secondary_rate_line, '') + def test_commission_cndn_weight_adjustment_uses_fee_lot_weights(self): + 'commission note adjustment uses provisional and current lot weights' + Invoice = Pool().get('account.invoice') + unit = SimpleNamespace(id=1, rec_name='MT', symbol='MT') + provisional_line = SimpleNamespace( + quantity=Decimal('400'), unit=unit) + lot = SimpleNamespace( + id=1, + sale_invoice_line_prov=provisional_line, + sale_invoice_padding=Decimal('0'), + get_current_quantity_converted=lambda state=0, unit=None: Decimal('397')) + fee = SimpleNamespace( + enable_linked_currency=False, + unit=unit, + sale_line=SimpleNamespace(sale=SimpleNamespace()), + line=None, + lots=[lot], + _get_effective_fee_lots=lambda: [lot]) + invoice = Invoice() + invoice.lines = [ + SimpleNamespace(type='line', fee=fee, quantity=Decimal('1'))] + + self.assertEqual( + invoice.report_commission_invoice_weight_display, '400.00') + self.assertEqual( + invoice.report_commission_landed_weight_display, '397.00') + self.assertEqual( + invoice.report_commission_weight_difference_display, '3.00') + self.assertEqual(invoice.report_commission_adjustment_unit_upper, 'MT') + def test_fee_delete_detects_generated_ordered_purchase(self): 'ordered fee deletion targets only its generated service purchase' Fee = Pool().get('fee.fee')