From 8088fd52543afd8f47cbfd29ad2d6a3ed8fc7d33 Mon Sep 17 00:00:00 2001 From: laurentbarontini Date: Sat, 25 Jul 2026 18:16:13 +0200 Subject: [PATCH] Purchase form --- modules/purchase_trade/purchase.py | 101 +++++++++++++++--- modules/purchase_trade/view/purchase_form.xml | 5 +- 2 files changed, 91 insertions(+), 15 deletions(-) diff --git a/modules/purchase_trade/purchase.py b/modules/purchase_trade/purchase.py index 6aefdb1..42ff5c3 100755 --- a/modules/purchase_trade/purchase.py +++ b/modules/purchase_trade/purchase.py @@ -971,6 +971,63 @@ class Purchase(metaclass=PoolMeta): data = dict(data, type='execution-summary') return "d3:" + json.dumps(data) + @staticmethod + def _summary_link(model, records): + unique = [] + seen = set() + for record in records: + record_id = getattr(record, 'id', None) + if not record_id: + continue + key = (model, record_id) + if key in seen: + continue + seen.add(key) + unique.append(record) + link = { + "model": model, + "count": len(unique), + } + if len(unique) == 1: + link["res_id"] = unique[0].id + return link + + @staticmethod + def _summary_mixed_link(records): + unique = [] + seen = set() + for model, record in records: + record_id = getattr(record, 'id', None) + if not model or not record_id: + continue + key = (model, record_id) + if key in seen: + continue + seen.add(key) + unique.append((model, record)) + link = { + "count": len(unique), + } + if len(unique) == 1: + model, record = unique[0] + link.update({ + "model": model, + "res_id": record.id, + }) + elif unique: + link["model"] = unique[0][0] + return link + + @staticmethod + def _summary_shipment_record(record): + if getattr(record, 'lot_shipment_in', None): + return ('stock.shipment.in', record.lot_shipment_in) + if getattr(record, 'lot_shipment_internal', None): + return ('stock.shipment.internal', record.lot_shipment_internal) + if getattr(record, 'lot_shipment_out', None): + return ('stock.shipment.out', record.lot_shipment_out) + return (None, None) + @staticmethod def _summary_number(value): if value is None: @@ -1013,10 +1070,9 @@ class Purchase(metaclass=PoolMeta): rows = [] totals = defaultdict(float) - for line in (self.lines or []): - if getattr(line, 'type', 'line') != 'line': - continue - + for index, line in enumerate(( + l for l in (self.lines or []) + if getattr(l, 'type', 'line') == 'line'), 1): quantity = self._execution_summary_quantity( getattr(line, 'quantity_theorical', None) or getattr(line, 'quantity', None)) @@ -1024,6 +1080,8 @@ class Purchase(metaclass=PoolMeta): shipped = 0.0 lots_count = 0 shipped_routes = [] + sales = [] + shipments = [] line_lots = list(getattr(line, 'lots', None) or []) lot_ids = [lot.id for lot in line_lots if getattr(lot, 'id', None)] lot_qts = LotQt.search([('lot_p', 'in', lot_ids)]) if lot_ids else [] @@ -1035,11 +1093,13 @@ class Purchase(metaclass=PoolMeta): or getattr(lqt, 'lot_qt', None)) if getattr(lqt, 'lot_s', None): matched += lot_quantity - shipment = ( - getattr(lqt, 'lot_shipment_in', None) - or getattr(lqt, 'lot_shipment_internal', None) - or getattr(lqt, 'lot_shipment_out', None)) + sale_line = getattr(lqt.lot_s, 'sale_line', None) + sale = getattr(sale_line, 'sale', None) + if sale: + sales.append(sale) + shipment_model, shipment = self._summary_shipment_record(lqt) if shipment: + shipments.append((shipment_model, shipment)) shipped += lot_quantity route_from = getattr( getattr(shipment, 'from_location', None), @@ -1062,11 +1122,15 @@ class Purchase(metaclass=PoolMeta): getattr(lot, 'lot_qt', None)) if getattr(lot, 'lot_s', None) or getattr(lot, 'sale_line', None): matched += lot_quantity - shipment = ( - getattr(lot, 'lot_shipment_in', None) - or getattr(lot, 'lot_shipment_internal', None) - or getattr(lot, 'lot_shipment_out', None)) + sale_line = getattr(lot, 'sale_line', None) + if getattr(lot, 'lot_s', None): + sale_line = getattr(lot.lot_s, 'sale_line', None) + sale = getattr(sale_line, 'sale', None) + if sale: + sales.append(sale) + shipment_model, shipment = self._summary_shipment_record(lot) if shipment: + shipments.append((shipment_model, shipment)) shipped += lot_quantity route_from = getattr( getattr(shipment, 'from_location', None), @@ -1084,6 +1148,12 @@ class Purchase(metaclass=PoolMeta): shipped_routes.append( '%s > %s' % (route_from or '-', route_to or '-')) + invoices = [ + invoice_line.invoice + for invoice_line in (getattr(line, 'invoice_lines', None) or []) + if (getattr(invoice_line, 'invoice', None) + and getattr(invoice_line.invoice, 'state', None) != 'cancelled') + ] unit = getattr(getattr(line, 'unit', None), 'rec_name', '') or '' product = getattr(getattr(line, 'product', None), 'rec_name', '') or '' route = (shipped_routes[0] if shipped_routes else '%s > %s' % ( @@ -1093,7 +1163,9 @@ class Purchase(metaclass=PoolMeta): or '-')) rows.append({ + 'index': index, 'product': product, + 'physical': shipped, 'quantity': quantity, 'matched': matched, 'shipped': shipped, @@ -1101,6 +1173,9 @@ class Purchase(metaclass=PoolMeta): 'unit': unit, 'lots': lots_count, 'route': route, + 'sales': self._summary_link('sale.sale', sales), + 'shipments': self._summary_mixed_link(shipments), + 'invoices': self._summary_link('account.invoice', invoices), }) totals['quantity'] += quantity totals['matched'] += matched @@ -1111,7 +1186,7 @@ class Purchase(metaclass=PoolMeta): return { 'unit': rows[0]['unit'] if rows else '', 'totals': dict(totals), - 'rows': rows[:4], + 'rows': rows[:3], } @staticmethod diff --git a/modules/purchase_trade/view/purchase_form.xml b/modules/purchase_trade/view/purchase_form.xml index f9d9ee7..0a83c59 100755 --- a/modules/purchase_trade/view/purchase_form.xml +++ b/modules/purchase_trade/view/purchase_form.xml @@ -100,8 +100,9 @@ this repository contains the full copyright notices and license terms. --> - +