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 ''>