changeset a04e65b1a308 in modules/sale_supply:default
details:
https://hg.tryton.org/modules/sale_supply?cmd=changeset;node=a04e65b1a308
description:
Fill grouping values when assigning supplied moves
issue9480
review296301002
diffstat:
sale.py | 69 ++++++++++++++++++++++++++++++++++++++++++++++++---------------
stock.py | 50 +++++++++++++++++++++++++++++++++------------
2 files changed, 88 insertions(+), 31 deletions(-)
diffs (180 lines):
diff -r c200371bfea6 -r a04e65b1a308 sale.py
--- a/sale.py Thu Jul 09 10:21:06 2020 +0100
+++ b/sale.py Sun Oct 11 16:08:46 2020 +0200
@@ -1,8 +1,9 @@
# 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 trytond.model import fields
+from trytond.model import Model, fields
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Eval
+from trytond.transaction import Transaction
class Sale(metaclass=PoolMeta):
@@ -169,7 +170,7 @@
origin=self.sale,
)
- def assign_supplied(self, location_quantities):
+ def assign_supplied(self, quantities, grouping=('product',)):
'''
Assign supplied move
@@ -182,20 +183,50 @@
if self.supply_state != 'supplied':
return
+
+ def get_key(move, location_id):
+ key = (location_id,)
+ for field in grouping:
+ value = getattr(move, field)
+ if isinstance(value, Model):
+ value = value.id
+ key += (value,)
+ return key
+
+ def get_values(key, location_name):
+ yield location_name, key[0]
+ for field, value in zip(grouping, key[1:]):
+ if value is not None and '.' not in field:
+ yield field, value
+
+ def match(key, pattern):
+ for k, p in zip(key, pattern):
+ if p is None or k == p:
+ continue
+ else:
+ return False
+ else:
+ return True
+
moves = set()
for move in self.moves:
for inv_move in move.shipment.inventory_moves:
if inv_move.product.id == self.product.id:
moves.add(inv_move)
+ to_write = []
+ to_assign = []
for move in moves:
if move.state != 'draft':
continue
- location_qties_converted = {}
- for location_id, quantity in location_quantities.items():
- location_qties_converted[location_id] = (
- Uom.compute_qty(move.product.default_uom,
- quantity, move.uom, round=False))
- to_pick = move.pick_product(location_qties_converted)
+ qties_converted = []
+ for key, quantity in quantities.items():
+ move_key = get_key(move, key[0])
+ if match(key, move_key):
+ qty = Uom.compute_qty(
+ move.product.default_uom, quantity, move.uom,
+ round=False)
+ qties_converted.append((key, qty))
+ to_pick = move.pick_product(qties_converted)
picked_qties = sum(qty for _, qty in to_pick)
if picked_qties < move.quantity:
@@ -205,18 +236,22 @@
})
else:
first = True
- for from_location, qty in to_pick:
- values = {
- 'from_location': from_location.id,
- 'quantity': qty,
- }
+ for key, qty in to_pick:
+ values = dict(get_values(key, 'from_location'))
+ values['quantity'] = move.uom.round(qty)
if first:
- Move.write([move], values)
- Move.assign([move])
+ to_write.extend([[move], values])
+ to_assign.append(move)
+ first = False
else:
- Move.assign(Move.copy([move], default=values))
+ with Transaction().set_context(_stock_move_split=True):
+ to_assign.extend(Move.copy([move], default=values))
qty_default_uom = Uom.compute_qty(move.uom, qty,
move.product.default_uom, round=False)
- location_quantities[from_location] -= qty_default_uom
+ quantities[key] -= qty_default_uom
+ if to_write:
+ Move.write(*to_write)
+ if to_assign:
+ Move.assign(to_assign)
diff -r c200371bfea6 -r a04e65b1a308 stock.py
--- a/stock.py Thu Jul 09 10:21:06 2020 +0100
+++ b/stock.py Sun Oct 11 16:08:46 2020 +0200
@@ -2,7 +2,7 @@
# this repository contains the full copyright notices and license terms.
from collections import defaultdict
-from trytond.model import ModelView, Workflow
+from trytond.model import Model, ModelView, Workflow
from trytond.pool import Pool, PoolMeta
@@ -13,20 +13,42 @@
@ModelView.button
@Workflow.transition('done')
def done(cls, shipments):
- SaleLine = Pool().get('sale.line')
-
super(ShipmentIn, cls).done(shipments)
# Assigned sale move lines
for shipment in shipments:
- move_ids = [x.id for x in shipment.incoming_moves]
- sale_lines = SaleLine.search([
- ('purchase_request.purchase_line.moves',
- 'in', move_ids),
- ('purchase_request.origin', 'like', 'sale.sale,%'),
- ])
- pbl = defaultdict(lambda: defaultdict(int))
- for move in shipment.inventory_moves:
- pbl[move.product][move.to_location] += move.internal_quantity
- for sale_line in sale_lines:
- sale_line.assign_supplied(pbl[sale_line.product])
+ shipment.assign_supplied()
+
+ def assign_supplied(self, grouping=('product',), filter_=None):
+ pool = Pool()
+ SaleLine = pool.get('sale.line')
+
+ def filter_func(move):
+ if filter_ is None:
+ return True
+ for fieldname, values in filter_:
+ value = getattr(move, fieldname)
+ if isinstance(value, Model):
+ value = value.id
+ if value not in values:
+ return False
+
+ def get_key(move):
+ key = (move.to_location.id,)
+ for field in grouping:
+ value = getattr(move, field)
+ if isinstance(value, Model):
+ value = value.id
+ key += (value,)
+ return key
+ move_ids = [m.id for m in filter(filter_func, self.incoming_moves)]
+ sale_lines = SaleLine.search([
+ ('purchase_request.purchase_line.moves', 'in', move_ids),
+ ('purchase_request.origin', 'like', 'sale.sale,%'),
+ ])
+ pbl = defaultdict(lambda: defaultdict(int))
+ for move in filter(filter_func, self.inventory_moves):
+ pbl[move.product][get_key(move)] += move.internal_quantity
+ for sale_line in sale_lines:
+ sale_line.assign_supplied(
+ pbl[sale_line.product], grouping=grouping)