trytond-stock_lot_cost/stock.py

120 lines
4.0 KiB
Python
Raw Permalink Normal View History

# The COPYRIGHT file at the top level of this repository contains the full
# copyright notices and license terms.
from decimal import Decimal
import datetime
2016-07-22 11:34:33 +02:00
from trytond.model import ModelSQL, ModelView, Unique, fields
2013-09-18 10:09:46 +02:00
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Eval
from trytond.transaction import Transaction
from trytond.modules.product import round_price
2013-09-18 10:09:46 +02:00
class LotCostCategory(ModelSQL, ModelView):
'''Stock Lot Cost Category'''
__name__ = 'stock.lot.cost_category'
name = fields.Char('Name', translate=True, required=True)
@classmethod
def __setup__(cls):
super(LotCostCategory, cls).__setup__()
2016-07-22 11:34:33 +02:00
t = cls.__table__()
2013-09-18 10:09:46 +02:00
cls._sql_constraints += [
2016-07-22 11:34:33 +02:00
('name_uniq', Unique(t, t.name),
2019-06-17 23:51:19 +02:00
'stock_lot_cost.msg_category_name_unique'),
2013-09-18 10:09:46 +02:00
]
2018-10-15 00:15:37 +02:00
class Lot(metaclass=PoolMeta):
2013-09-18 10:09:46 +02:00
__name__ = 'stock.lot'
cost_price = fields.Function(fields.Numeric("Cost Price"),
'get_lot_prices')
total_cost = fields.Function(fields.Numeric("Total Cost"),
'get_lot_prices')
@classmethod
def get_lot_prices(cls, lots, names):
2013-09-18 10:09:46 +02:00
pool = Pool()
Move = pool.get('stock.move')
Product = pool.get('product.product')
Location = pool.get('stock.location')
res = {}
ids = [x.id for x in lots]
for name in ['cost_price', 'total_cost']:
res[name] = dict.fromkeys(ids)
warehouse_ids = [location.id for location in Location.search(
[('type', '=', 'warehouse')])]
product_ids = list(set(lot.product.id for lot in lots if lot.product))
lot_ids = list(set(lot.id for lot in lots))
moves = Move.search([
('lot', 'in', lot_ids),
('from_location.type', 'in', ['supplier', 'production']),
('to_location.type', '=', 'storage'),
('state', '=', 'done'),
])
with Transaction().set_context({'stock_date_end': datetime.date.max}):
pbl = Product.products_by_location(warehouse_ids,
with_childs=True,
grouping=('product', 'lot'),
grouping_filter=(product_ids, lot_ids))
lot_moves = {}
for move in moves:
if move.lot not in lot_moves:
lot_moves[move.lot] = []
lot_moves[move.lot].append(move)
for lot in lots:
res['total_cost'][lot.id] = Decimal(0)
res['cost_price'][lot.id] = Decimal(0)
if not lot in lot_moves:
continue
warehouse_quantity = Decimal(0)
for k, v in pbl.items():
key = k[1:]
if key == (lot.product.id, lot.id):
warehouse_quantity += Decimal(v)
total_price = Decimal(sum(Decimal(m.unit_price) * Decimal(
m.internal_quantity) for m in lot_moves[lot] if (
m.unit_price and m.internal_quantity)))
total_quantity = Decimal(
sum(m.internal_quantity for m in lot_moves[lot]))
res['cost_price'][lot.id] = round_price(total_price/total_quantity)
res['total_cost'][lot.id] = round_price(
total_price/total_quantity) * warehouse_quantity
for name in list(res.keys()):
if name not in names:
del res[name]
return res
2013-09-18 10:09:46 +02:00
2018-10-15 00:15:37 +02:00
class Move(metaclass=PoolMeta):
2013-09-18 10:09:46 +02:00
__name__ = 'stock.move'
@classmethod
def __setup__(cls):
super(Move, cls).__setup__()
cls.lot.context['from_move'] = Eval('id')
def get_cost_price(self, product_cost_price=None):
pool = Pool()
Lot = pool.get('stock.lot')
cost_price = super().get_cost_price(product_cost_price=None)
if self.lot and self.to_location.type == 'production':
with Transaction().set_context(date=self.effective_date):
lot = Lot(self.lot.id) # Need to reinstantiate to ensure the context is correct
if lot.cost_price is not None:
return lot.cost_price
return cost_price