Skip to content
Snippets Groups Projects
Commit b28d22ff authored by Cédric Krier's avatar Cédric Krier :atom:
Browse files

Recompute cost price of drop shipment

Since issue9962 the unit price of the supplier move can be updated later so we
must recompute the cost price of the customer moves.

issue11295
review364951003
parent 6a2afcc8
No related branches found
No related tags found
1 merge request!114Return an empty list when the treeview has no selection
* Recompute cost price of drop shipment
* Add support for Python 3.10
* Remove support for Python 3.6
......
......@@ -3,7 +3,7 @@
from trytond.pool import Pool
from . import party, purchase, sale, stock
from . import party, product, purchase, sale, stock
def register():
......@@ -22,6 +22,7 @@
purchase.Purchase,
purchase.Line,
purchase.ProductSupplier,
product.Product,
module='sale_supply_drop_shipment', type_='model')
Pool.register(
purchase.RequestCreatePurchase,
......
# 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.pool import Pool, PoolMeta
from trytond.tools import grouped_slice
class Product(metaclass=PoolMeta):
__name__ = 'product.product'
@classmethod
def recompute_cost_price(cls, products, start=None):
pool = Pool()
Move = pool.get('stock.move')
Shipment = pool.get('stock.shipment.drop')
shipments = set()
for sub_products in grouped_slice(products):
domain = [
('unit_price_updated', '=', True),
cls._domain_moves_cost(),
('product', 'in', [p.id for p in sub_products]),
('shipment', 'like', 'stock.shipment.drop,%'),
]
if start:
domain.append(('effective_date', '>=', start))
for move in Move.search(domain, order=[]):
shipments.add(move.shipment)
shipments = Shipment.browse(list(shipments))
Shipment.set_cost(shipments)
super().recompute_cost_price(products, start=start)
......@@ -443,7 +443,6 @@
to_save = []
for shipment in shipments:
product_qty = defaultdict(int)
product_cost = defaultdict(int)
for c_move in shipment.customer_moves:
if c_move.state == 'cancelled':
......@@ -456,10 +455,6 @@
for s_move in shipment.supplier_moves:
if s_move.state == 'cancelled':
continue
internal_quantity = Decimal(str(s_move.internal_quantity))
product_cost[s_move.product] += (
s_move.get_cost_price() * internal_quantity)
quantity = UoM.compute_qty(
s_move.uom, s_move.quantity, s_move.product.default_uom,
round=False)
......@@ -488,8 +483,4 @@
new_customer_move.unit_price = unit_price
to_save.append(new_customer_move)
for product, cost in product_cost.items():
qty = Decimal(str(s_product_qty[product]))
if qty:
product_cost[product] = round_price(cost / qty)
for c_move in list(shipment.customer_moves) + to_save:
......@@ -495,8 +486,5 @@
for c_move in list(shipment.customer_moves) + to_save:
if c_move.id is not None and c_move.state == 'cancelled':
continue
c_move.cost_price = product_cost[c_move.product]
if c_move.id is None:
if c_move.id is None or c_move.state == 'cancelled':
continue
if product_qty[c_move.product] > 0:
exc_qty = UoM.compute_qty(
......@@ -528,6 +516,41 @@
)
@classmethod
def set_cost(cls, shipments):
pool = Pool()
Move = pool.get('stock.move')
UoM = pool.get('product.uom')
to_save = []
for shipment in shipments:
product_cost = defaultdict(int)
s_product_qty = defaultdict(int)
for s_move in shipment.supplier_moves:
if s_move.state == 'cancelled':
continue
internal_quantity = Decimal(str(s_move.internal_quantity))
product_cost[s_move.product] += (
s_move.get_cost_price() * internal_quantity)
quantity = UoM.compute_qty(
s_move.uom, s_move.quantity, s_move.product.default_uom,
round=False)
s_product_qty[s_move.product] += quantity
for product, cost in product_cost.items():
qty = Decimal(str(s_product_qty[product]))
if qty:
product_cost[product] = round_price(cost / qty)
for c_move in shipment.customer_moves:
cost_price = product_cost[c_move.product]
if cost_price != c_move.cost_price:
c_move.cost_price = cost_price
to_save.append(c_move)
if to_save:
Move.save(to_save)
@classmethod
@ModelView.button
@Workflow.transition('waiting')
def wait(cls, shipments):
......@@ -590,6 +613,7 @@
pool = Pool()
Move = pool.get('stock.move')
Date = pool.get('ir.date')
cls.set_cost(shipments)
Move.do([m for s in shipments for m in s.customer_moves])
for company, shipments in groupby(shipments, key=lambda s: s.company):
with Transaction().set_context(company=company.id):
......
......@@ -62,5 +62,8 @@
>>> stock_force_group, = Group.find([
... ('name', '=', 'Stock Force Assignment'),
... ])
>>> product_admin_group, = Group.find([
... ('name', '=', "Product Administration"),
... ])
>>> stock_user.groups.append(stock_group)
>>> stock_user.groups.append(stock_force_group)
......@@ -65,4 +68,5 @@
>>> stock_user.groups.append(stock_group)
>>> stock_user.groups.append(stock_force_group)
>>> stock_user.groups.append(product_admin_group)
>>> stock_user.save()
......@@ -67,5 +71,14 @@
>>> stock_user.save()
Create account user::
>>> account_user = User()
>>> account_user.name = "Account"
>>> account_user.login = 'account'
>>> account_group, = Group.find([('name', '=', "Account")])
>>> account_user.groups.append(account_group)
>>> account_user.save()
Create fiscal year::
>>> fiscalyear = set_fiscalyear_invoice_sequences(
......@@ -190,7 +203,6 @@
>>> move.unit_price
Decimal('10.0000')
>>> move.cost_price
Decimal('3.0000')
>>> set_user(sale_user)
>>> sale.reload()
>>> sale.shipments
......@@ -204,6 +216,9 @@
>>> shipment.click('done')
>>> shipment.state
'done'
>>> move, = shipment.customer_moves
>>> move.cost_price
Decimal('3.0000')
>>> set_user(sale_user)
>>> sale.reload()
>>> sale.shipments
......@@ -251,5 +266,25 @@
>>> sale.shipment_state
'exception'
Receive purchase invoice at different price::
>>> set_user(account_user)
>>> invoice, = purchase.invoices
>>> invoice_line, = invoice.lines
>>> invoice_line.unit_price = Decimal('4.0000')
>>> invoice.invoice_date = today
>>> invoice.click('post')
>>> set_user(stock_user)
>>> recompute = Wizard('product.recompute_cost_price', [product])
>>> recompute.execute('recompute')
>>> shipment, = [s for s in purchase.drop_shipments
... if s.state == 'done']
>>> move, = shipment.customer_moves
>>> move.cost_price
Decimal('4.0000')
Cancelling the workflow on the purchase step::
......@@ -254,5 +289,6 @@
Cancelling the workflow on the purchase step::
>>> set_user(sale_user)
>>> sale = Sale()
>>> sale.party = customer
>>> sale.payment_term = payment_term
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment