Commit 29ac12f9 authored by Maxime Richez's avatar Maxime Richez
Browse files

Apply check_stock_quantity per warehouse line

parent 9655d8cf79d0
Pipeline #61614 passed with stages
in 14 minutes and 43 seconds
......@@ -3,6 +3,8 @@
import datetime
from collections import defaultdict
from itertools import groupby
from operator import attrgetter
from trytond.i18n import gettext
from trytond.model import ModelView, Workflow, fields
......@@ -85,10 +87,11 @@
return group in user.groups
def filter_line(line):
return (line.product
return (line.warehouse
and line.product
and line.product.type == 'goods'
and not line.product.consumable
and line.quantity > 0
# Use getattr as supply_on_sale comes from sale_supply module
and not getattr(line, 'supply_on_sale', False))
......@@ -89,9 +92,9 @@
and line.product.type == 'goods'
and not line.product.consumable
and line.quantity > 0
# Use getattr as supply_on_sale comes from sale_supply module
and not getattr(line, 'supply_on_sale', False))
def get_delta(date):
def get_delta(date, warehouse, products):
'Compute quantity delta at the date'
if date in date2delta:
......@@ -96,8 +99,8 @@
'Compute quantity delta at the date'
if date in date2delta:
return date2delta[date]
return date2delta[warehouse][date]
with transaction.set_context(forecast=True,
stock_date_start=date,
stock_date_end=date):
pbl = defaultdict(int)
......@@ -99,7 +102,8 @@
with transaction.set_context(forecast=True,
stock_date_start=date,
stock_date_end=date):
pbl = defaultdict(int)
for sub_product_ids in grouped_slice(product_ids):
for sub_products in grouped_slice(products):
sub_product_ids = [p.id for p in sub_products]
pbl.update(Product.products_by_location(
......@@ -105,3 +109,3 @@
pbl.update(Product.products_by_location(
[self.warehouse.id],
[warehouse.id],
with_childs=True,
......@@ -107,6 +111,6 @@
with_childs=True,
grouping_filter=(list(sub_product_ids),)))
grouping_filter=(sub_product_ids,)))
delta = {}
for key, qty in pbl.items():
_, product_id = key
delta[product_id] = qty
......@@ -109,6 +113,6 @@
delta = {}
for key, qty in pbl.items():
_, product_id = key
delta[product_id] = qty
date2delta[date] = delta
date2delta[warehouse][date] = delta
return delta
......@@ -114,5 +118,5 @@
return delta
date2delta = {}
date2delta = defaultdict(dict)
def raise_(line_id, message_values):
if not in_group():
......@@ -129,6 +133,7 @@
today = Date.today()
lang = Lang.get()
sale_date = self.sale_date or today
product_ids = {l.product.id for l in filter(filter_line, self.lines)}
product_ids = list(product_ids)
lines = filter(filter_line, self.lines)
lines = list(lines)
......@@ -134,8 +139,15 @@
with transaction.set_context(
locations=[self.warehouse.id],
stock_date_end=sale_date,
stock_assign=True):
products = Product.browse(product_ids)
quantities = {p: p.forecast_quantity for p in products}
quantities = defaultdict(lambda: defaultdict(int))
w_getter = attrgetter('warehouse')
w_products = {}
for warehouse, w_lines in groupby(
sorted(lines, key=w_getter), key=w_getter):
w_products[warehouse] = products = {l.product for l in w_lines}
with transaction.set_context(
locations=[warehouse.id],
stock_date_end=sale_date,
stock_assign=True):
products = Product.browse(products)
quantities[warehouse].update(
(p, p.forecast_quantity) for p in products)
......@@ -141,23 +153,25 @@
# Remove quantities from other sales
for sub_product_ids in grouped_slice(product_ids):
lines = Line.search([
('sale.company', '=', self.company.id),
('sale.state', 'in', self._stock_quantity_states()),
('sale.id', '!=', self.id),
['OR',
('sale.sale_date', '<=', sale_date),
('sale.sale_date', '=', None),
],
('product', 'in', sub_product_ids),
('quantity', '>', 0),
])
for line in lines:
product = line.product
date = line.sale.sale_date or today
if date > today or line.warehouse != self.warehouse:
continue
quantity = Uom.compute_qty(line.unit, line.quantity,
product.default_uom, round=False)
quantities[product] -= quantity
# Remove quantities from other sales
for sub_products in grouped_slice(products):
other_lines = Line.search([
('sale.company', '=', self.company.id),
('sale.state', 'in', self._stock_quantity_states()),
('sale.id', '!=', self.id),
['OR',
('sale.sale_date', '<=', sale_date),
('sale.sale_date', '=', None),
],
('product', 'in', sub_products),
('quantity', '>', 0),
])
for line in other_lines:
if line.warehouse != warehouse:
continue
product = line.product
date = line.sale.sale_date or today
if date > today:
continue
quantity = Uom.compute_qty(line.unit, line.quantity,
product.default_uom, round=False)
quantities[line.warehouse][product] -= quantity
......@@ -163,5 +177,6 @@
for line in filter(filter_line, self.lines):
for line in lines:
warehouse = line.warehouse
product = line.product
quantity = Uom.compute_qty(line.unit, line.quantity,
product.default_uom, round=False)
......@@ -169,8 +184,8 @@
message_values = {
'line': line.rec_name,
'forecast_quantity': lang.format_number_symbol(
quantities[product], product.default_uom,
product.default_uom.digits),
quantities[warehouse][product],
product.default_uom, product.default_uom.digits),
'quantity': lang.format_number_symbol(
line.quantity, line.unit, line.unit.digits),
}
......@@ -174,7 +189,7 @@
'quantity': lang.format_number_symbol(
line.quantity, line.unit, line.unit.digits),
}
if (quantities[product] < quantity
if (quantities[warehouse][product] < quantity
and sale_date < next_supply_date):
raise_(line.id, message_values)
# Update quantities if the same product is many times in lines
......@@ -178,7 +193,7 @@
and sale_date < next_supply_date):
raise_(line.id, message_values)
# Update quantities if the same product is many times in lines
quantities[product] -= quantity
quantities[warehouse][product] -= quantity
# Check other dates until next supply date
if next_supply_date != datetime.date.max:
......@@ -182,6 +197,7 @@
# Check other dates until next supply date
if next_supply_date != datetime.date.max:
forecast_quantity = quantities[product]
products = w_products[warehouse]
forecast_quantity = quantities[warehouse][product]
date = sale_date + datetime.timedelta(1)
while date < next_supply_date:
......@@ -186,6 +202,6 @@
date = sale_date + datetime.timedelta(1)
while date < next_supply_date:
delta = get_delta(date)
delta = get_delta(date, warehouse, products)
forecast_quantity += delta.get(product.id, 0)
if forecast_quantity < 0:
message_values['forecast_quantity'] = forecast_quantity
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment