Show weight report sale invoice reference
This commit is contained in:
@@ -846,8 +846,8 @@ class ShipmentIn(metaclass=PoolMeta):
|
|||||||
add_invoice = fields.Boolean("Add invoice")
|
add_invoice = fields.Boolean("Add invoice")
|
||||||
returned_id = fields.Char("Returned ID")
|
returned_id = fields.Char("Returned ID")
|
||||||
result = fields.Char("Result",readonly=True)
|
result = fields.Char("Result",readonly=True)
|
||||||
sale_invoice_numbers = fields.Function(
|
sale_invoice_ref = fields.Function(
|
||||||
fields.Char("Sale Invoice"), 'get_sale_invoice_numbers')
|
fields.Char("Sale invoice ref."), 'get_sale_invoice_ref')
|
||||||
agent = fields.Many2One('party.party',"Booking Agent")
|
agent = fields.Many2One('party.party',"Booking Agent")
|
||||||
service_order_key = fields.Integer("Service Order Key")
|
service_order_key = fields.Integer("Service Order Key")
|
||||||
|
|
||||||
@@ -3054,35 +3054,41 @@ class ShipmentIn(metaclass=PoolMeta):
|
|||||||
def get_sh(self, name):
|
def get_sh(self, name):
|
||||||
return self.id
|
return self.id
|
||||||
|
|
||||||
def get_sale_invoice_numbers(self, name=None):
|
def get_sale_invoice_ref(self, name=None):
|
||||||
invoices = []
|
invoice_ref = self._sale_invoice_ref_from_instructions()
|
||||||
|
if invoice_ref:
|
||||||
|
return invoice_ref
|
||||||
|
return self._sale_invoice_ref_from_fintrade()
|
||||||
|
|
||||||
|
def _sale_invoice_ref_from_instructions(self):
|
||||||
|
instructions = self.html_to_text(self.instructions or '')
|
||||||
|
match = re.search(
|
||||||
|
r'Invoice\s+Nb:\s*([^|\r\n]+)', instructions, re.IGNORECASE)
|
||||||
|
if match:
|
||||||
|
return match.group(1).strip()
|
||||||
|
|
||||||
|
def _sale_invoice_ref_from_fintrade(self):
|
||||||
|
if not self.reference:
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
booking_number = int(self.reference)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
return None
|
||||||
|
t = Table('freight_booking_lots')
|
||||||
|
cursor = Transaction().connection.cursor()
|
||||||
|
query = t.select(
|
||||||
|
t.SALE_INVOICE,
|
||||||
|
where=(t.BOOKING_NUMBER == booking_number),
|
||||||
|
group_by=[t.SALE_INVOICE])
|
||||||
|
cursor.execute(*query)
|
||||||
|
refs = []
|
||||||
seen = set()
|
seen = set()
|
||||||
|
for row in cursor.fetchall():
|
||||||
def add_invoice(invoice):
|
ref = str(row[0] or '').strip()
|
||||||
invoice_id = getattr(invoice, 'id', None)
|
if ref and ref not in seen:
|
||||||
key = invoice_id or id(invoice)
|
refs.append(ref)
|
||||||
if not invoice or key in seen:
|
seen.add(ref)
|
||||||
return
|
return ', '.join(refs)
|
||||||
seen.add(key)
|
|
||||||
invoices.append(
|
|
||||||
getattr(invoice, 'rec_name', None)
|
|
||||||
or getattr(invoice, 'number', None)
|
|
||||||
or getattr(invoice, 'reference', None)
|
|
||||||
or str(invoice_id or ''))
|
|
||||||
|
|
||||||
for lotqt in self.lotqt or []:
|
|
||||||
lots = [
|
|
||||||
getattr(lotqt, 'lot_p', None),
|
|
||||||
getattr(lotqt, 'lot_s', None),
|
|
||||||
]
|
|
||||||
for lot in lots:
|
|
||||||
if not lot or getattr(lot, 'lot_type', None) != 'physic':
|
|
||||||
continue
|
|
||||||
invoice_line = (
|
|
||||||
getattr(lot, 'sale_invoice_line', None)
|
|
||||||
or getattr(lot, 'sale_invoice_line_prov', None))
|
|
||||||
add_invoice(getattr(invoice_line, 'invoice', None))
|
|
||||||
return ', '.join(filter(None, invoices))
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def default_transport_type(cls):
|
def default_transport_type(cls):
|
||||||
|
|||||||
@@ -7417,34 +7417,22 @@ description</t></is></c>
|
|||||||
shipment.report_insurance_issue_place_and_date,
|
shipment.report_insurance_issue_place_and_date,
|
||||||
'GENEVA, 06-04-2026')
|
'GENEVA, 06-04-2026')
|
||||||
|
|
||||||
def test_shipment_sale_invoice_numbers_use_physical_lot_invoices(self):
|
def test_shipment_sale_invoice_ref_uses_weight_report_message(self):
|
||||||
'shipment tree helper lists sale invoices linked to physical lots'
|
'shipment tree helper reads the sale invoice ref from instructions'
|
||||||
final_invoice = SimpleNamespace(id=1, rec_name='SINV-001')
|
shipment = SimpleNamespace(
|
||||||
provisional_invoice = SimpleNamespace(id=2, rec_name='SPRO-002')
|
instructions=(
|
||||||
final_line = SimpleNamespace(invoice=final_invoice)
|
'<p><strong>Customer:</strong> CLIENT | '
|
||||||
provisional_line = SimpleNamespace(invoice=provisional_invoice)
|
'<strong>Invoice Nb:</strong> 4661 | '
|
||||||
physical_final = SimpleNamespace(
|
'<strong>Invoice Date:</strong> 2026-07-28</p>'),
|
||||||
lot_type='physic',
|
html_to_text=Mock(side_effect=lambda html_content:
|
||||||
sale_invoice_line=final_line,
|
stock_module.ShipmentIn.html_to_text(
|
||||||
sale_invoice_line_prov=provisional_line)
|
SimpleNamespace(), html_content)),
|
||||||
physical_provisional = SimpleNamespace(
|
_sale_invoice_ref_from_fintrade=Mock(return_value='IGNORED'))
|
||||||
lot_type='physic',
|
|
||||||
sale_invoice_line=None,
|
|
||||||
sale_invoice_line_prov=provisional_line)
|
|
||||||
virtual = SimpleNamespace(
|
|
||||||
lot_type='virtual',
|
|
||||||
sale_invoice_line=SimpleNamespace(
|
|
||||||
invoice=SimpleNamespace(id=3, rec_name='IGNORED')),
|
|
||||||
sale_invoice_line_prov=None)
|
|
||||||
shipment = SimpleNamespace(lotqt=[
|
|
||||||
SimpleNamespace(lot_p=physical_final, lot_s=virtual),
|
|
||||||
SimpleNamespace(lot_p=physical_provisional, lot_s=None),
|
|
||||||
SimpleNamespace(lot_p=physical_final, lot_s=None),
|
|
||||||
])
|
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
stock_module.ShipmentIn.get_sale_invoice_numbers(shipment),
|
stock_module.ShipmentIn.get_sale_invoice_ref(shipment),
|
||||||
'SINV-001, SPRO-002')
|
'4661')
|
||||||
|
shipment._sale_invoice_ref_from_fintrade.assert_not_called()
|
||||||
|
|
||||||
def test_shipment_insurance_amount_fallback_uses_lot_and_incoming_moves(self):
|
def test_shipment_insurance_amount_fallback_uses_lot_and_incoming_moves(self):
|
||||||
'insurance amount falls back to lot unit price and shipment quantities'
|
'insurance amount falls back to lot unit price and shipment quantities'
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ this repository contains the full copyright notices and license terms. -->
|
|||||||
<xpath expr="/tree/field[@name='reference']" position="after">
|
<xpath expr="/tree/field[@name='reference']" position="after">
|
||||||
<field name="returned_id" optional="1"/>
|
<field name="returned_id" optional="1"/>
|
||||||
<field name="result" optional="1"/>
|
<field name="result" optional="1"/>
|
||||||
<field name="sale_invoice_numbers" optional="1"/>
|
<field name="sale_invoice_ref" optional="1"/>
|
||||||
<field name="vessel" string="Vessel name" optional="1"/>
|
<field name="vessel" string="Vessel name" optional="1"/>
|
||||||
<field name="list_from_locations" optional="1"/>
|
<field name="list_from_locations" optional="1"/>
|
||||||
<field name="list_to_locations" optional="1"/>
|
<field name="list_to_locations" optional="1"/>
|
||||||
|
|||||||
Reference in New Issue
Block a user