diff --git a/modules/purchase_trade/tests/test_module.py b/modules/purchase_trade/tests/test_module.py index 9f5ff18..8601a30 100644 --- a/modules/purchase_trade/tests/test_module.py +++ b/modules/purchase_trade/tests/test_module.py @@ -870,6 +870,65 @@ class PurchaseTradeTestCase(ModuleTestCase): self.assertIsNone(values['weight_date']) self.assertEqual(values['report_date'].isoformat(), '2025-10-28') + def test_weight_report_create_from_json_accepts_bales_with_thousand_separator(self): + 'weight report import accepts OCR bale counts formatted like 1.100' + WeightReport = Pool().get('weight.report') + party_model = Mock() + vessel_model = Mock() + location_model = Mock() + party_model.getPartyByName.side_effect = lambda name: Mock(id={ + 'SELLER': 1, + 'BUYER': 2, + 'CARRIER': 3, + }[name]) + vessel_model.search.return_value = [] + location_model.search.return_value = [] + + payload = { + 'lab': 'LAB', + 'report': { + 'reference': 'REF', + 'file_no': 'FILE', + 'date': '02 Apr 2026', + }, + 'contract': {}, + 'parties': { + 'seller': 'SELLER', + 'buyer': 'BUYER', + 'carrier': 'CARRIER', + }, + 'shipment': { + 'bl_no': 'BL-1', + 'weighing_place': 'PORT', + 'weighing_method': 'METHOD', + 'bales': '1.100', + }, + 'weights': { + 'weight_date': None, + 'gross_landed_kg': '10', + 'tare_kg': '1', + 'net_landed_kg': '9', + 'invoice_net_kg': '9', + 'gain_loss_kg': '0', + 'gain_loss_percent': '0', + } + } + + with patch( + 'trytond.modules.purchase_trade.weight_report.Pool') as PoolMock, patch.object( + WeightReport, 'create', return_value=[payload]) as create_mock: + PoolMock.return_value.get.side_effect = lambda name: { + 'party.party': party_model, + 'trade.vessel': vessel_model, + 'stock.location': location_model, + }[name] + + created = WeightReport.create_from_json(payload) + + self.assertEqual(created, payload) + values = create_mock.call_args.args[0][0] + self.assertEqual(values['bales'], 1100) + def test_invoice_report_uses_invoice_template_from_configuration(self): 'invoice report path is resolved from purchase_trade configuration' report_class = Pool().get('account.invoice', type='report') diff --git a/modules/purchase_trade/weight_report.py b/modules/purchase_trade/weight_report.py index 62ccede..7bfc89d 100644 --- a/modules/purchase_trade/weight_report.py +++ b/modules/purchase_trade/weight_report.py @@ -219,6 +219,28 @@ class WeightReport(ModelSQL, ModelView): pass return None + def parse_bales(value): + if value in (None, ''): + return 0 + if isinstance(value, (int, float, Decimal)): + return int(Decimal(str(value)).quantize(Decimal('1'))) + text = str(value).strip() + if not text: + return 0 + text = text.replace(' ', '') + if ',' in text and '.' in text: + text = text.replace(',', '') + elif ',' in text: + text = text.replace(',', '.') + try: + decimal_value = Decimal(text) + except Exception: + if '.' in text: + decimal_value = Decimal(text.replace('.', '')) + else: + raise + return int(decimal_value.quantize(Decimal('1'))) + report['report_date'] = parse_date(report_data.get('date', '')) # 3. Contract Information contract_data = json_data.get('contract', {}) @@ -293,7 +315,7 @@ class WeightReport(ModelSQL, ModelView): report['weighing_place'] = shipment_data.get('weighing_place', '') report['weighing_method'] = shipment_data.get('weighing_method', '') - report['bales'] = int(shipment_data.get('bales', 0) or 0) + report['bales'] = parse_bales(shipment_data.get('bales', 0)) # 6. Weights Information weights_data = json_data.get('weights', {})