From ae39ff2f7db06e6778b15056de71d303c8843746 Mon Sep 17 00:00:00 2001 From: laurentbarontini Date: Tue, 7 Jul 2026 08:40:18 +0200 Subject: [PATCH] Melya template --- modules/purchase_trade/stock.py | 133 ++++++++++++++++++-- modules/purchase_trade/tests/test_module.py | 30 ++++- modules/stock/insurance.fodt | 3 +- 3 files changed, 152 insertions(+), 14 deletions(-) diff --git a/modules/purchase_trade/stock.py b/modules/purchase_trade/stock.py index 38b6afe..0a3f3e8 100755 --- a/modules/purchase_trade/stock.py +++ b/modules/purchase_trade/stock.py @@ -1024,6 +1024,92 @@ class ShipmentIn(metaclass=PoolMeta): getattr(lot_qt, 'lot_s', None))) return sales + def _get_report_physical_lots(self): + lots = [] + seen = set() + for move in (self.incoming_moves or []): + lot = getattr(move, 'lot', None) + if not lot or getattr(lot, 'lot_type', None) != 'physic': + continue + lot_id = getattr(lot, 'id', None) + key = lot_id if lot_id is not None else id(lot) + if key in seen: + continue + seen.add(key) + lots.append(lot) + return lots + + def _get_report_invoice_lines_from_physical_lots(self): + lines = [] + seen = set() + for lot in self._get_report_physical_lots(): + for name in ( + 'sale_invoice_line', + 'sale_invoice_line_prov', + 'invoice_line', + 'invoice_line_prov'): + line = getattr(lot, name, None) + if not line: + continue + line_id = getattr(line, 'id', None) + key = line_id if line_id is not None else id(line) + if key in seen: + continue + seen.add(key) + lines.append(line) + break + return lines + + @staticmethod + def _get_report_invoice_line_snapshot_quantity(line): + invoice = getattr(line, 'invoice', None) + weights = getattr(invoice, '_get_report_invoice_line_weights', None) + if callable(weights): + quantity, _ = weights(line) + unit_getter = getattr(invoice, '_get_report_invoice_line_unit', None) + unit = unit_getter(line) if callable(unit_getter) else None + return Decimal(str(quantity or 0)), unit + + snapshots = list(getattr(line, 'lot_weight_snapshots', []) or []) + if snapshots: + quantity = sum( + Decimal(str(getattr(snapshot, 'net_quantity', 0) or 0)) + for snapshot in snapshots) + unit = getattr(snapshots[0], 'unit', None) + return quantity, unit + + report_net = getattr(line, 'report_net', '') + try: + quantity = Decimal(str(report_net or 0)) + except Exception: + quantity = Decimal(0) + if not quantity: + quantity = Decimal(str(getattr(line, 'quantity', 0) or 0)) + return quantity, getattr(line, 'unit', None) + + @staticmethod + def _get_report_unit_text(unit): + return ( + getattr(unit, 'symbol', None) + or getattr(unit, 'rec_name', None) + or getattr(unit, 'name', None) + or '') + + def _get_report_insurance_invoice_quantity(self): + total = Decimal(0) + unit = None + matched = False + for line in self._get_report_invoice_lines_from_physical_lots(): + quantity, line_unit = self._get_report_invoice_line_snapshot_quantity( + line) + total += quantity + if not unit and line_unit: + unit = line_unit + matched = True + if not matched: + return None, None + return total, unit + def _get_report_weight_totals(self): net = Decimal('0') gross = Decimal('0') @@ -1091,20 +1177,49 @@ class ShipmentIn(metaclass=PoolMeta): @property def report_insurance_account_of(self): - line = self._get_report_trade_line() - trade = getattr(line, 'sale', None) or getattr(line, 'purchase', None) - party = getattr(trade, 'party', None) if trade else None - if party: - return party.rec_name or '' - return getattr(self.supplier, 'rec_name', '') or '' + company = getattr(self, 'company', None) + party = getattr(company, 'party', None) if company else None + if not party: + return '' + address_get = getattr(party, 'address_get', None) + address = address_get() if callable(address_get) else None + return ( + getattr(address, 'party_name', None) + or getattr(address, 'party_full_name', None) + or getattr(party, 'rec_name', None) + or '') @property def report_insurance_goods_description(self): name = self.report_product_name description = self.report_product_description - if description and description != name: - return ' - '.join(part for part in [name, description] if part) - return name or description + product = ( + ' - '.join(part for part in [name, description] if part) + if description and description != name else name or description) + quantity, unit = self._get_report_insurance_invoice_quantity() + if quantity is None: + return product + quantity_text = self._format_report_quantity(quantity, '0.0001') + unit_text = self._get_report_unit_text(unit) + quantity_label = ''.join( + part for part in [quantity_text, unit_text] if part) + return ' '.join(part for part in [quantity_label, product] if part) + + @property + def report_insurance_invoice_number(self): + numbers = [] + seen = set() + for line in self._get_report_invoice_lines_from_physical_lots(): + invoice = getattr(line, 'invoice', None) + number = ( + getattr(invoice, 'number', None) + or getattr(invoice, 'rec_name', None) + or '') + if not number or number in seen: + continue + seen.add(number) + numbers.append(number) + return ' '.join(numbers) @property def report_insurance_loading_port(self): diff --git a/modules/purchase_trade/tests/test_module.py b/modules/purchase_trade/tests/test_module.py index f499b7e..b2fa99c 100644 --- a/modules/purchase_trade/tests/test_module.py +++ b/modules/purchase_trade/tests/test_module.py @@ -6318,7 +6318,24 @@ class PurchaseTradeTestCase(ModuleTestCase): ) product = Mock(name='COTTON UPLAND', description='RAW WHITE COTTON') line = Mock(product=product, sale=sale) - lot = Mock(sale_line=line, line=None) + invoice = Mock(number='INV-001') + snapshot_unit = Mock(symbol='mt', rec_name='MT') + invoice_line = Mock( + invoice=invoice, + lot_weight_snapshots=[ + Mock(net_quantity=Decimal('24.0000'), unit=snapshot_unit), + ], + ) + lot = Mock( + id=1, + lot_type='physic', + sale_line=line, + line=None, + sale_invoice_line=invoice_line, + sale_invoice_line_prov=None, + invoice_line=None, + invoice_line_prov=None, + ) move = Mock(lot=lot, product=product) shipment.incoming_moves = [move] shipment.moves = [move] @@ -6343,19 +6360,24 @@ class PurchaseTradeTestCase(ModuleTestCase): shipment.company = Mock( party=Mock( rec_name='MELYA SA', - address_get=Mock(return_value=Mock(city='GENEVA')), + address_get=Mock(return_value=Mock( + city='GENEVA', + party_name='MELYA INTERNATIONAL TRADING SA')), ) ) self.assertEqual( shipment.report_insurance_certificate_number, 'BL-001') self.assertEqual( - shipment.report_insurance_account_of, 'SGT FR') + shipment.report_insurance_account_of, + 'MELYA INTERNATIONAL TRADING SA') self.assertEqual( shipment.report_insurance_goods_description, - 'COTTON UPLAND - RAW WHITE COTTON') + '24mt COTTON UPLAND - RAW WHITE COTTON') self.assertEqual( shipment.report_insurance_order_reference, 'P-12 S-34') + self.assertEqual( + shipment.report_insurance_invoice_number, 'INV-001') self.assertEqual( shipment.report_insurance_amount, 'USD 1234.56') self.assertEqual( diff --git a/modules/stock/insurance.fodt b/modules/stock/insurance.fodt index 313b8d0..73ecf52 100644 --- a/modules/stock/insurance.fodt +++ b/modules/stock/insurance.fodt @@ -1031,12 +1031,13 @@ Certificate of Insurance No. <records[0].report_insurance_certificate_number or ''> - This is to certify that we have insured for account of <records[0].company.party.rec_name if records[0].company and records[0].company.party else ''> + This is to certify that we have insured for account of <records[0].report_insurance_account_of or ''> Marine Insurance Policy No. 4.008.227.782the following shipment: Description of goods and/or services: <records[0].report_insurance_goods_description or ''> Order reference: <records[0].report_insurance_order_reference or ''> + Invoice no: <records[0].report_insurance_invoice_number or ''>