diff --git a/modules/purchase_request/purchase.py b/modules/purchase_request/purchase.py index 96725ea0fb..d5cf3d2573 100644 --- a/modules/purchase_request/purchase.py +++ b/modules/purchase_request/purchase.py @@ -20,8 +20,12 @@ def process_request(func): pool = Pool() Request = pool.get('purchase.request') func(cls, purchases) - requests = [r for p in purchases for l in p.lines for r in l.requests] - Request.update_state(requests) + with without_check_access(): + requests = [ + r for p in cls.browse(purchases) + for l in p.lines + for r in l.requests] + Request.update_state(requests) return wrapper @@ -77,10 +81,10 @@ class Purchase(metaclass=PoolMeta): super(Purchase, cls).cancel(purchases) @classmethod + @ModelView.button @process_request - @Workflow.transition('done') - def do(cls, purchases): - super(Purchase, cls).do(purchases) + def process(cls, purchases): + super().process(purchases) class Line(metaclass=PoolMeta): diff --git a/modules/sale_supply/__init__.py b/modules/sale_supply/__init__.py index bdb0dfb946..3761891064 100644 --- a/modules/sale_supply/__init__.py +++ b/modules/sale_supply/__init__.py @@ -11,14 +11,10 @@ def register(): sale.Sale, sale.Line, purchase.Request, - purchase.Purchase, stock.ShipmentIn, product.Template, product.Product, module='sale_supply', type_='model') - Pool.register( - purchase.HandlePurchaseCancellationException, - module='sale_supply', type_='wizard') Pool.register( stock.OrderPoint, module='sale_supply', type_='model', depends=['stock_supply']) diff --git a/modules/sale_supply/purchase.py b/modules/sale_supply/purchase.py index 4ed25eb64f..9984f39cb7 100644 --- a/modules/sale_supply/purchase.py +++ b/modules/sale_supply/purchase.py @@ -1,10 +1,8 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. -from functools import wraps -from trytond.model import ModelView, Workflow, fields +from trytond.model import fields from trytond.pool import Pool, PoolMeta -from trytond.tools import grouped_slice from trytond.transaction import Transaction, without_check_access @@ -18,6 +16,21 @@ class Request(metaclass=PoolMeta): def _get_origin(cls): return super()._get_origin() | {'sale.sale'} + @classmethod + def update_state(cls, requests): + pool = Pool() + Sale = pool.get('sale.sale') + transaction = Transaction() + context = transaction.context + + super().update_state(requests) + + sales = {r.origin for r in requests if isinstance(r.origin, Sale)} + if sales: + with transaction.set_context( + queue_batch=context.get('queue_batch', True)): + Sale.__queue__.process(Sale.browse(sales)) + @classmethod def delete(cls, requests): pool = Pool() @@ -41,81 +54,3 @@ class Request(metaclass=PoolMeta): with transaction.set_context( queue_batch=context.get('queue_batch', True)): Sale.__queue__.process(sales) - - -def process_sale_supply(func): - @wraps(func) - def wrapper(cls, purchases): - pool = Pool() - Request = pool.get('purchase.request') - Sale = pool.get('sale.sale') - transaction = Transaction() - context = transaction.context - - sales = set() - with without_check_access(): - for sub_purchases in grouped_slice(purchases): - ids = [x.id for x in sub_purchases] - requests = Request.search([ - ('purchase_line.purchase.id', 'in', ids), - ('origin', 'like', 'sale.sale,%'), - ]) - sales.update(r.origin.id for r in requests) - func(cls, purchases) - if sales: - with transaction.set_context( - queue_batch=context.get('queue_batch', True)): - Sale.__queue__.process(sales) - return wrapper - - -class Purchase(metaclass=PoolMeta): - __name__ = 'purchase.purchase' - - @classmethod - @ModelView.button - @process_sale_supply - def process(cls, purchases): - super(Purchase, cls).process(purchases) - - @classmethod - @ModelView.button - @Workflow.transition('cancelled') - @process_sale_supply - def cancel(cls, purchases): - super(Purchase, cls).cancel(purchases) - - -class HandlePurchaseCancellationException(metaclass=PoolMeta): - __name__ = 'purchase.request.handle.purchase.cancellation' - - def transition_cancel_request(self): - pool = Pool() - SaleLine = pool.get('sale.line') - Move = pool.get('stock.move') - Shipment = pool.get('stock.shipment.out') - - next_state = super(HandlePurchaseCancellationException, - self).transition_cancel_request() - moves = [] - shipments = set() - for sub_ids in grouped_slice(list(map(int, self.records))): - sale_lines = SaleLine.search([ - ('purchase_request', 'in', sub_ids), - ]) - for sale_line in sale_lines: - moves.extend(sale_line.moves) - for shipment in sale_line.sale.shipments: - if shipment.state in ['draft', 'waiting']: - shipments.add(shipment) - if moves: - shipments_waiting = [s for s in shipments if s.state == 'waiting'] - Shipment.draft(shipments) # clear inventory moves - Move.cancel(moves) - Shipment.wait([ - s for s in shipments_waiting - if any(m.state != 'cancelled' for m in s.outgoing_moves)]) - Shipment.cancel([ - s for s in shipments_waiting - if all(m.state == 'cancelled' for m in s.outgoing_moves)]) - return next_state diff --git a/modules/sale_supply/sale.py b/modules/sale_supply/sale.py index 38df1b68c5..81ab2bba00 100644 --- a/modules/sale_supply/sale.py +++ b/modules/sale_supply/sale.py @@ -51,25 +51,18 @@ class Sale(metaclass=PoolMeta): def _process_supply(cls, sales, product_quantities): pool = Pool() Line = pool.get('sale.line') - Move = pool.get('stock.move') PurchaseRequest = pool.get('purchase.request') - ShipmentOut = pool.get('stock.shipment.out') requests, lines = [], [] - moves_to_draft, shipments_to_wait = [], set() for sale in sales: reqs, lns = sale.create_purchase_requests(product_quantities) requests.extend(reqs) lines.extend(lns) - moves, shipments = sale.create_move_from_supply() - moves_to_draft.extend(moves) - shipments_to_wait.update(shipments) - shipments_to_wait = ShipmentOut.browse(list(shipments_to_wait)) PurchaseRequest.save(requests) Line.save(lines) - Move.draft(moves_to_draft) - ShipmentOut.wait(shipments_to_wait) + + cls._update_moves_from_supply(sales) def create_purchase_requests(self, product_quantities): requests, lines = [], [] @@ -83,19 +76,46 @@ class Sale(metaclass=PoolMeta): lines.append(line) return requests, lines - def create_move_from_supply(self): - 'Set to draft move linked to supply' + @classmethod + def _update_moves_from_supply(cls, sales): pool = Pool() - ShipmentOut = pool.get('stock.shipment.out') - moves = [] - for line in self.lines: - if line.supply_state in {'supplied', 'cancelled'}: - for move in line.moves: - if move.state == 'staging': - moves.append(move) - shipments = {m.shipment for m in moves - if isinstance(m.shipment, ShipmentOut)} - return moves, shipments + Shipment = pool.get('stock.shipment.out') + Move = pool.get('stock.move') + + shipments = set() + + def add_shipment(shipment): + if (isinstance(shipment, Shipment) + and shipment.state in {'draft', 'waiting'}): + shipments.add(shipment) + + moves_to_draft, moves_to_cancel = [], [] + for sale in sales: + for line in sale.lines: + if line.supply_state == 'supplied': + for move in line.moves: + if move.state == 'staging': + moves_to_draft.append(move) + add_shipment(move.shipment) + elif line.supply_state == 'cancelled': + for move in line.moves: + moves_to_cancel.append(move) + add_shipment(move.shipment) + if moves_to_draft: + Move.draft(moves_to_draft) + shipments = Shipment.browse(shipments) + shipments_waiting = [s for s in shipments if s.state == 'waiting'] + if shipments: + Shipment.draft(shipments) # clear inventory moves + if moves_to_cancel: + Move.cancel(moves_to_cancel) + if shipments: + Shipment.wait([ + s for s in shipments_waiting + if any(m.state != 'cancelled' for m in s.moves)]) + Shipment.cancel([ + s for s in shipments + if all(m.state == 'cancelled' for m in s.moves)]) class Line(metaclass=PoolMeta):