changeset 4893e9ec0c9e in modules/purchase:default
details: https://hg.tryton.org/modules/purchase?cmd=changeset&node=4893e9ec0c9e
description:
Split process method to avoid create/write in loop
issue10801
review372071002
diffstat:
CHANGELOG | 2 +
purchase.py | 105 +++++++++++++++++++++++++++++++++++++----------------------
2 files changed, 67 insertions(+), 40 deletions(-)
diffs (177 lines):
diff -r 030efcb9d8f4 -r 4893e9ec0c9e CHANGELOG
--- a/CHANGELOG Mon Oct 04 18:52:01 2021 +0200
+++ b/CHANGELOG Fri Oct 08 19:21:06 2021 +0200
@@ -1,3 +1,5 @@
+* Split process method
+
Version 6.0.0 - 2021-05-03
* Bug fixes (see mercurial logs for details)
* Add origin and set on returned purchase
diff -r 030efcb9d8f4 -r 4893e9ec0c9e purchase.py
--- a/purchase.py Mon Oct 04 18:52:01 2021 +0200
+++ b/purchase.py Fri Oct 08 19:21:06 2021 +0200
@@ -1,6 +1,7 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
import datetime
+from collections import defaultdict
from itertools import chain
from decimal import Decimal
@@ -582,16 +583,6 @@
return 'waiting'
return 'none'
- def set_invoice_state(self):
- '''
- Set the invoice state.
- '''
- state = self.get_invoice_state()
- if self.invoice_state != state:
- self.write([self], {
- 'invoice_state': state,
- })
-
get_shipments = get_shipments_returns('stock.shipment.in')
get_shipment_returns = get_shipments_returns('stock.shipment.in.return')
@@ -612,16 +603,6 @@
return 'waiting'
return 'none'
- def set_shipment_state(self):
- '''
- Set the shipment state.
- '''
- state = self.get_shipment_state()
- if self.shipment_state != state:
- self.write([self], {
- 'shipment_state': state,
- })
-
@classmethod
def _get_origin(cls):
"Return list of Model names for origin Reference"
@@ -804,10 +785,6 @@
if getattr(invoice, 'lines', None):
invoice_lines = list(invoice.lines) + invoice_lines
invoice.lines = invoice_lines
- invoice.save()
-
- invoice.update_taxes()
- self.copy_resources_to(invoice)
return invoice
def create_move(self, move_type):
@@ -845,12 +822,8 @@
'''
Create return shipment and return the shipment id
'''
- ShipmentInReturn = Pool().get('stock.shipment.in.return')
return_shipment = self._get_return_shipment()
return_shipment.moves = return_moves
- return_shipment.save()
- self.copy_resources_to(return_shipment)
- ShipmentInReturn.wait([return_shipment])
return return_shipment
def is_done(self):
@@ -932,26 +905,79 @@
@classmethod
@ModelView.button
def process(cls, purchases):
+ states = {'confirmed', 'processing', 'done'}
+ purchases = [p for p in purchases if p.state in states]
+ cls.lock(purchases)
+ cls._process_invoice(purchases)
+ cls._process_shipment(purchases)
+ cls._process_invoice_shipment_states(purchases)
+ cls._process_state(purchases)
+
+ @classmethod
+ def _process_invoice(cls, purchases):
+ pool = Pool()
+ Invoice = pool.get('account.invoice')
+
+ invoices = {}
+ for purchase in purchases:
+ invoice = purchase.create_invoice()
+ if invoice:
+ invoices[purchase] = invoice
+
+ Invoice.save(invoices.values())
+ Invoice.update_taxes(invoices.values())
+ for purchase, invoice in invoices.items():
+ purchase.copy_resources_to(invoice)
+
+ @classmethod
+ def _process_shipment(cls, purchases):
+ pool = Pool()
+ Move = pool.get('stock.move')
+ ShipmentInReturn = pool.get('stock.shipment.in.return')
+
+ moves, shipments_return = [], {}
+ for purchase in purchases:
+ moves.extend(purchase.create_move('in'))
+ return_moves = purchase.create_move('return')
+ if return_moves:
+ shipments_return[purchase] = purchase.create_return_shipment(
+ return_moves)
+
+ Move.save(moves)
+
+ ShipmentInReturn.save(shipments_return.values())
+ ShipmentInReturn.wait(shipments_return.values())
+ for purchase, shipment in shipments_return.items():
+ purchase.copy_resources_to(shipment)
+
+ @classmethod
+ def _process_invoice_shipment_states(cls, purchases):
pool = Pool()
Line = pool.get('purchase.line')
lines = []
- process, done = [], []
- cls.lock(purchases)
+ invoice_states, shipment_states = defaultdict(list), defaultdict(list)
for purchase in purchases:
- if purchase.state not in {'confirmed', 'processing', 'done'}:
- continue
- purchase.create_invoice()
- purchase.set_invoice_state()
- purchase.create_move('in')
- return_moves = purchase.create_move('return')
- if return_moves:
- purchase.create_return_shipment(return_moves)
- purchase.set_shipment_state()
+ invoice_state = purchase.get_invoice_state()
+ if purchase.invoice_state != invoice_state:
+ invoice_states[invoice_state].append(purchase)
+ shipment_state = purchase.get_shipment_state()
+ if purchase.shipment_state != shipment_state:
+ shipment_states[shipment_state].append(purchase)
for line in purchase.lines:
line.set_actual_quantity()
lines.append(line)
+ for invoice_state, purchases in invoice_states.items():
+ cls.write(purchases, {'invoice_state': invoice_state})
+ for shipment_state, purchases in shipment_states.items():
+ cls.write(purchases, {'shipment_state': shipment_state})
+ Line.save(lines)
+
+ @classmethod
+ def _process_state(cls, purchases):
+ process, done = [], []
+ for purchase in purchases:
if purchase.is_done():
if purchase.state != 'done':
if purchase.state == 'confirmed':
@@ -959,7 +985,6 @@
done.append(purchase)
elif purchase.state != 'processing':
process.append(purchase)
- Line.save(lines)
if process:
cls.proceed(process)
if done: