Update sale based on purchase request update state
It is simpler if the purchase triggers the update of the request and the update of the request triggers the process of the sale.
This commit is contained in:
1 parent
956040bca9
commit
d3264484c4
4 files changed
+66
-111
No files matched your search
@@ -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):
|
||||
|
||||
@@ -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'])
|
||||
@@ -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
|
||||
+41
-21
@@ -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):
|
||||
|
||||
Reference in new issue
Block a user