From 346a34951de64ababdef5b83396ceb03ac4ce57e Mon Sep 17 00:00:00 2001 From: laurentbarontini Date: Thu, 2 Apr 2026 11:16:26 +0200 Subject: [PATCH] 02.04.26 --- modules/account_invoice/invoice_ict.fodt | 11 ++- .../docs/template-properties.md | 9 +++ modules/purchase_trade/invoice.py | 73 +++++++++++++++++++ modules/purchase_trade/sale.py | 23 ++++++ modules/purchase_trade/tests/test_module.py | 6 ++ modules/sale/sale_ict.fodt | 9 +++ 6 files changed, 129 insertions(+), 2 deletions(-) diff --git a/modules/account_invoice/invoice_ict.fodt b/modules/account_invoice/invoice_ict.fodt index f8b8dc6..04f0604 100644 --- a/modules/account_invoice/invoice_ict.fodt +++ b/modules/account_invoice/invoice_ict.fodt @@ -3931,9 +3931,14 @@ QUANTITY: <format_number(invoice.report_lbs, invoice.party.lang) if invoice.report_lbs != '' else ''>LBS (<format_number(invoice.report_net, invoice.party.lang) if invoice.report_net != '' else ''> MTS) + <for each="line in invoice.report_quantity_lines.splitlines()"> + <line> + </for> <invoice.report_description_upper or invoice.report_product_description>CROP <invoice.report_crop_name> <invoice.report_attributes_name> - At <invoice.report_rate_currency_upper><invoice.report_rate_value>PER <invoice.report_rate_unit_upper>(<invoice.report_rate_price_words>) <invoice.report_rate_pricing_text> + <for each="line in invoice.report_rate_lines.splitlines()"> + At <line> + </for> <invoice.report_incoterm> @@ -4009,7 +4014,9 @@ - At <invoice.report_rate_currency_upper><invoice.report_rate_value>PER <invoice.report_rate_unit_upper>(<invoice.report_rate_price_words>) <invoice.report_rate_pricing_text> + <for each="line in invoice.report_rate_lines.splitlines()"> + At <line> + </for> FREIGHT VALUE: <invoice.report_freight_currency_symbol><format_number(invoice.report_freight_amount, invoice.party.lang) if invoice.report_freight_amount != '' else ''> diff --git a/modules/purchase_trade/docs/template-properties.md b/modules/purchase_trade/docs/template-properties.md index 2c7331c..eebe7ba 100644 --- a/modules/purchase_trade/docs/template-properties.md +++ b/modules/purchase_trade/docs/template-properties.md @@ -94,6 +94,10 @@ Source code: `modules/purchase_trade/invoice.py` - Usage: poids net converti en LBS - Source de verite: conversion de `report_net` +- `report_quantity_lines` + - Usage: detail quantite multi-lignes pour les templates facture + - Source de verite: `sale.report_quantity_lines` si vente source, sinon aggregation des `account.invoice.line` + ### Bloc prix type `sale_ict` - `report_rate_currency_upper` @@ -116,6 +120,10 @@ Source code: `modules/purchase_trade/invoice.py` - Usage: texte de pricing additionnel - Source de verite: premiere `account.invoice.line` de type `line` +- `report_rate_lines` + - Usage: detail multi-lignes du bloc `At ... PER ...` + - Source de verite: `sale.report_price_lines` si vente source, sinon aggregation des `account.invoice.line` + ### Logistique / shipment - `report_shipment` @@ -245,6 +253,7 @@ Source code: `modules/purchase_trade/sale.py` - `report_qt` - `report_total_quantity` - `report_quantity_unit_upper` +- `report_quantity_lines` - `report_nb_bale` - `report_deal` - `report_packing` diff --git a/modules/purchase_trade/invoice.py b/modules/purchase_trade/invoice.py index 65d2e97..1985548 100644 --- a/modules/purchase_trade/invoice.py +++ b/modules/purchase_trade/invoice.py @@ -6,12 +6,30 @@ from trytond.pool import Pool, PoolMeta class Invoice(metaclass=PoolMeta): __name__ = 'account.invoice' + @staticmethod + def _format_report_number(value, digits='0.0000', keep_trailing_decimal=False, + strip_trailing_zeros=True): + value = Decimal(str(value or 0)).quantize(Decimal(digits)) + text = format(value, 'f') + if strip_trailing_zeros: + text = text.rstrip('0').rstrip('.') + if keep_trailing_decimal and '.' not in text: + text += '.0' + return text or '0' + def _get_report_invoice_line(self): for line in self.lines or []: if getattr(line, 'type', None) == 'line': return line return self.lines[0] if self.lines else None + def _get_report_invoice_lines(self): + lines = [ + line for line in (self.lines or []) + if getattr(line, 'type', None) == 'line' + ] + return lines or list(self.lines or []) + def _get_report_purchase(self): purchases = list(self.purchases or []) return purchases[0] if purchases else None @@ -146,6 +164,32 @@ class Invoice(metaclass=PoolMeta): return trade.report_price return '' + @property + def report_quantity_lines(self): + sale = self._get_report_sale() + if sale and getattr(sale, 'report_quantity_lines', None): + return sale.report_quantity_lines + details = [] + for line in self._get_report_invoice_lines(): + quantity = getattr(line, 'report_net', '') + if quantity == '': + quantity = getattr(line, 'quantity', '') + if quantity == '': + continue + quantity_text = self._format_report_number( + quantity, keep_trailing_decimal=True) + unit = getattr(line, 'unit', None) + unit_name = unit.rec_name.upper() if unit and unit.rec_name else '' + lbs = getattr(line, 'report_lbs', '') + parts = [quantity_text, unit_name] + if lbs != '': + parts.append( + f"({self._format_report_number(lbs, digits='0.01')} LBS)") + detail = ' '.join(part for part in parts if part) + if detail: + details.append(detail) + return '\n'.join(details) + @property def report_rate_currency_upper(self): line = self._get_report_invoice_line() @@ -181,6 +225,35 @@ class Invoice(metaclass=PoolMeta): return line.report_rate_pricing_text return '' + @property + def report_rate_lines(self): + sale = self._get_report_sale() + if sale and getattr(sale, 'report_price_lines', None): + return sale.report_price_lines + details = [] + for line in self._get_report_invoice_lines(): + currency = getattr(line, 'report_rate_currency_upper', '') or '' + value = getattr(line, 'report_rate_value', '') + value_text = '' + if value != '': + value_text = self._format_report_number( + value, strip_trailing_zeros=False) + unit = getattr(line, 'report_rate_unit_upper', '') or '' + words = getattr(line, 'report_rate_price_words', '') or '' + pricing_text = getattr(line, 'report_rate_pricing_text', '') or '' + detail = ' '.join( + part for part in [ + currency, + value_text, + 'PER' if unit else '', + unit, + f"({words})" if words else '', + pricing_text, + ] if part) + if detail: + details.append(detail) + return '\n'.join(details) + @property def report_payment_date(self): trade = self._get_report_trade() diff --git a/modules/purchase_trade/sale.py b/modules/purchase_trade/sale.py index a579c4c..1b21b4d 100755 --- a/modules/purchase_trade/sale.py +++ b/modules/purchase_trade/sale.py @@ -408,6 +408,29 @@ class Sale(metaclass=PoolMeta): total = sum(Decimal(str(line.quantity or 0)) for line in lines) return quantity_to_words(total) return '' + + @property + def report_quantity_lines(self): + lines = self._get_report_lines() + if not lines: + return '' + details = [] + for line in lines: + quantity = self._format_report_number( + line.quantity, keep_trailing_decimal=True) + unit = line.unit.rec_name.upper() if line.unit and line.unit.rec_name else '' + words = quantity_to_words(Decimal(str(line.quantity or 0))) + period = line.del_period.description if getattr(line, 'del_period', None) else '' + detail = ' '.join( + part for part in [ + quantity, + unit, + f"({words})", + f"- {period}" if period else '', + ] if part) + if detail: + details.append(detail) + return '\n'.join(details) @property def report_nb_bale(self): diff --git a/modules/purchase_trade/tests/test_module.py b/modules/purchase_trade/tests/test_module.py index 3981557..4c8c929 100644 --- a/modules/purchase_trade/tests/test_module.py +++ b/modules/purchase_trade/tests/test_module.py @@ -185,6 +185,12 @@ class PurchaseTradeTestCase(ModuleTestCase): self.assertEqual(sale.report_quantity_unit_upper, 'MT') self.assertEqual(sale.report_qt, 'TWO THOUSAND METRIC TONS') self.assertEqual(sale.report_nb_bale, '') + self.assertEqual( + sale.report_quantity_lines.splitlines(), + [ + '1000.0 MT (ONE THOUSAND METRIC TONS) - MARCH 2026', + '1000.0 MT (ONE THOUSAND METRIC TONS) - MAY 2026', + ]) self.assertEqual( sale.report_shipment_periods.splitlines(), ['MARCH 2026', 'MAY 2026']) diff --git a/modules/sale/sale_ict.fodt b/modules/sale/sale_ict.fodt index eb63c65..d8e6d69 100644 --- a/modules/sale/sale_ict.fodt +++ b/modules/sale/sale_ict.fodt @@ -4095,6 +4095,15 @@ <sale.report_nb_bale> + + <for each="line in sale.report_quantity_lines.splitlines()"> + + + <line> + + + </for> +