From 2cbc71847b41bacf4287ffd630838d161ecb924e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Fri, 8 Dec 2023 14:00:08 +0100 Subject: [PATCH] Factorize assign_supplied of Sale to reuse assign_try of Move --- modules/sale_supply/sale.py | 101 ++---------------------------------- modules/stock/CHANGELOG | 1 + modules/stock/move.py | 38 ++++++++------ modules/stock_lot/stock.py | 12 +++-- 4 files changed, 35 insertions(+), 117 deletions(-) diff --git a/modules/sale_supply/sale.py b/modules/sale_supply/sale.py index 74980c355d..fa5f14ae82 100644 --- a/modules/sale_supply/sale.py +++ b/modules/sale_supply/sale.py @@ -5,7 +5,7 @@ from collections import defaultdict from itertools import groupby from operator import attrgetter -from trytond.model import Model, fields +from trytond.model import fields from trytond.pool import Pool, PoolMeta from trytond.pyson import Eval from trytond.transaction import Transaction @@ -234,43 +234,15 @@ class Line(metaclass=PoolMeta): def assign_supplied(self, quantities, grouping=('product',)): ''' Assign supplied move - - location_quantities will be updated according to assigned - quantities. + The quantities will be updated according to assigned quantities. ''' pool = Pool() - Uom = pool.get('product.uom') Move = pool.get('stock.move') ShipmentOut = pool.get('stock.shipment.out') - Location = pool.get('stock.location') 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: shipment = move.shipment @@ -283,69 +255,6 @@ class Line(metaclass=PoolMeta): if inv_move.product == self.product: moves.add(inv_move) - child_locations = {} - to_write = [] - to_assign = [] - for move in moves: - if move.state != 'draft': - continue - - childs = child_locations.get(move.from_location) - if childs is None: - childs = Location.search([ - ('parent', 'child_of', [move.from_location.id]), - ('type', '!=', 'view'), - ]) - child_locations[move.from_location] = childs - # Prevent picking from the destination location - try: - childs.remove(move.to_location) - except ValueError: - pass - # Try first to pick from source location - try: - childs.remove(move.from_location) - childs.insert(0, move.from_location) - except ValueError: - # from_location may be a view - pass - 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.unit, - round=False) - qties_converted.append((key, qty)) - - location_qties = move.sort_quantities( - qties_converted, childs, grouping) - to_pick = move.pick_product(location_qties) - - picked_qties = sum(qty for _, qty in to_pick) - if picked_qties < move.quantity: - first = False - Move.write([move], { - 'quantity': move.quantity - picked_qties, - }) - else: - first = True - for key, qty in to_pick: - values = dict(get_values(key, 'from_location')) - values['quantity'] = move.unit.round(qty) - if first: - to_write.extend([[move], values]) - to_assign.append(move) - first = False - else: - with Transaction().set_context(_stock_move_split=True): - to_assign.extend(Move.copy([move], default=values)) - - qty_default_uom = Uom.compute_qty( - move.unit, qty, move.product.default_uom, round=False) - - quantities[key] -= qty_default_uom - if to_write: - Move.write(*to_write) - if to_assign: - Move.assign(to_assign) + Move.assign_try(list(moves), grouping=grouping, pblc={ + self.company.id: quantities, + }) diff --git a/modules/stock/CHANGELOG b/modules/stock/CHANGELOG index 2f600f4562..33c95ff580 100644 --- a/modules/stock/CHANGELOG +++ b/modules/stock/CHANGELOG @@ -1,3 +1,4 @@ +* Add pblc argument to assign_try Version 7.0.0 - 2023-10-30 -------------------------- diff --git a/modules/stock/move.py b/modules/stock/move.py index 9c72df83aa..b364c2d7f2 100644 --- a/modules/stock/move.py +++ b/modules/stock/move.py @@ -1002,9 +1002,12 @@ class Move(Workflow, ModelSQL, ModelView): return self.from_location @classmethod - def assign_try(cls, moves, with_childs=True, grouping=('product',)): + def assign_try( + cls, moves, with_childs=True, grouping=('product',), pblc=None): ''' Try to assign moves. + It uses pblc as product by location by company if provided otherwise it + computes based on today. It will split the moves to assign as much possible. Return True if succeed or False if not. ''' @@ -1027,26 +1030,27 @@ class Move(Workflow, ModelSQL, ModelView): locations = list(set((m.from_location for m in moves))) location_ids = [l.id for l in locations] product_ids = list(set((m.product.id for m in moves))) - companies = {m.company for m in moves} stock_date_end = Date.today() - pblc = {} - for company in companies: - with Transaction().set_context(company=company.id): - stock_date_end = Date.today() + if pblc is None: + pblc = {} + companies = {m.company for m in moves} + for company in companies: + with Transaction().set_context(company=company.id): + stock_date_end = Date.today() - cls._assign_try_lock( - product_ids, location_ids, [company.id], - stock_date_end, grouping) + cls._assign_try_lock( + product_ids, location_ids, [company.id], + stock_date_end, grouping) - with Transaction().set_context( - stock_date_end=stock_date_end, - stock_assign=True, - company=company.id): - pblc[company.id] = Product.products_by_location( - location_ids, - grouping=grouping, - grouping_filter=(product_ids,)) + with Transaction().set_context( + stock_date_end=stock_date_end, + stock_assign=True, + company=company.id): + pblc[company.id] = Product.products_by_location( + location_ids, + grouping=grouping, + grouping_filter=(product_ids,)) def get_key(move, location_id): key = (location_id,) diff --git a/modules/stock_lot/stock.py b/modules/stock_lot/stock.py index fe74a65181..80ded26eec 100644 --- a/modules/stock_lot/stock.py +++ b/modules/stock_lot/stock.py @@ -464,7 +464,8 @@ class Move(metaclass=PoolMeta): move.check_lot() @classmethod - def assign_try(cls, moves, with_childs=True, grouping=('product',)): + def assign_try( + cls, moves, with_childs=True, grouping=('product',), pblc=None): if 'lot' not in grouping: moves_with_lot, moves_without_lot = [], [] for move in moves: @@ -473,11 +474,14 @@ class Move(metaclass=PoolMeta): else: moves_without_lot.append(move) success = super().assign_try( - moves_with_lot, with_childs, grouping=grouping + ('lot',)) + moves_with_lot, with_childs=with_childs, + grouping=grouping + ('lot',), pblc=pblc) success &= super().assign_try( - moves_without_lot, with_childs, grouping=grouping) + moves_without_lot, with_childs=with_childs, + grouping=grouping, pblc=pblc) else: - success = super().assign_try(moves, with_childs, grouping) + success = super().assign_try( + moves, with_childs=with_childs, grouping=grouping, pblc=pblc) return success