Delete dependency with field cost_lines from stock_lot_cost module. (#3)

Task #068419
This commit is contained in:
Juanjo Garcia Pagan 2023-05-16 15:22:21 +02:00 committed by Juanjo Garcia
parent a3300f6297
commit bca59513ed
5 changed files with 1 additions and 242 deletions

View File

@ -6,13 +6,6 @@ from . import production
def register():
Pool.register(
production.BOM,
production.Lot,
production.Production,
production.StockMove,
module='production_lot_cost', type_='model')
Pool.register(
production.LotCostLine,
production.Operation,
depends=['production_operation'],
module='production_lot_cost', type_='model')

View File

@ -2,13 +2,7 @@
# copyright notices and license terms.
from decimal import Decimal
from trytond.model import fields
from trytond.pool import Pool, PoolMeta
from trytond.transaction import Transaction
from trytond.exceptions import UserError
from trytond.i18n import gettext
from trytond.modules.product import price_digits, round_price
__all__ = ['BOM', 'Lot', 'Production', 'StockMove', 'LotCostLine', 'Operation']
from trytond.pool import PoolMeta
class BOM(metaclass=PoolMeta):
@ -18,22 +12,6 @@ class BOM(metaclass=PoolMeta):
help='Infrastructure cost per lot unit')
class Lot(metaclass=PoolMeta):
__name__ = 'stock.lot'
def _on_change_product_cost_lines(self):
pool = Pool()
Move = pool.get('stock.move')
context = Transaction().context
if context.get('from_move'):
move = Move(context['from_move'])
if getattr(move, 'production_output', False):
return {}
return super(Lot, self)._on_change_product_cost_lines()
class Production(metaclass=PoolMeta):
__name__ = 'production'
@ -66,208 +44,3 @@ class Production(metaclass=PoolMeta):
cost += (Decimal(str(output.internal_quantity)) *
self.infrastructure_cost)
return cost
#def explode_bom(self):
#super(Production, self).explode_bom()
#outputs = self.outputs
#for move in outputs:
#if self.infrastructure_cost and move.product == self.product:
#move.unit_price += self.infrastructure_cost
@classmethod
def set_cost(cls, productions):
pool = Pool()
Lot = pool.get('stock.lot')
CostLot = pool.get('stock.lot.cost_line')
try:
Operation = pool.get('production.operation')
except:
pass
super(Production, cls).set_cost(productions)
to_save = []
to_check = []
for production in productions:
output_quantity = sum([x.internal_quantity for x in
production.outputs if x.product == production.product])
if hasattr(production, 'operations') and hasattr(cls, 'lot'):
ops = []
for output in production.outputs:
ops += [x for x in production.operations if
output.lot and x.lot == output.lot]
for output in production.outputs:
cost_lines = []
if not output.lot:
continue
if not output.lot.cost_lines:
cost_lines = output._get_production_output_lot_cost_lines()
if hasattr(production, 'operations') and hasattr(cls, 'lot'):
operations = [x for x in production.operations if
output.lot and x.lot == output.lot]
cost_lines += Operation._get_operation_lot_cost_line(
operations, output.internal_quantity, output)
operations = [x for x in production.operations if
(x.lot is None or x not in ops)]
cost_lines += Operation._get_operation_lot_cost_line(
operations, output_quantity, output)
to_save += cost_lines
to_check.append((output, output.lot))
if to_save:
CostLot.save(to_save)
if to_check:
for move, lot in to_check:
move.check_lot_cost(lot)
class LotCostLine(metaclass=PoolMeta):
__name__ = 'stock.lot.cost_line'
@classmethod
def _get_origin(cls):
return super()._get_origin() + ['production.operation',]
class Operation(metaclass=PoolMeta):
__name__ = 'production.operation'
@classmethod
def _get_operation_lot_cost_line(cls, operations, quantity, move):
pool = Pool()
Category = pool.get('stock.lot.cost_category')
LotCostLine = pool.get('stock.lot.cost_line')
categories = dict((x.name, x) for x in Category.search([]))
vals = {}
for operation in operations:
cat = operation.operation_type.name
if cat not in categories:
category = Category(name=cat)
category.save()
categories[cat] = category
else:
category = categories[cat]
if category not in vals:
vals[category] = 0
vals[category] += operation.cost
cost_lines = []
for category, cost in vals.items():
cost_line = LotCostLine(
category=category.id,
lot = move.lot,
unit_price=Decimal(float(cost)/quantity if quantity else 0),
origin=str(move),
)
cost_lines += [cost_line]
return cost_lines
class StockMove(metaclass=PoolMeta):
__name__ = 'stock.move'
def check_lot_cost(self, lot):
'''
If production output quantity is changed manually, it cannot be
computed the lot cost, so lot must be created manually.
'''
production = self.production_output
if self.uom != production.uom:
unit_price = self.uom.compute_price(self.uom, self.unit_price,
production.uom)
else:
unit_price = self.unit_price
cost_price = round_price(lot.cost_price)
unit_price = round_price(unit_price)
if unit_price != cost_price:
raise UserError(gettext('production_lot_cost.msg_uneven_costs',
move=self.rec_name,
move_unit_price=self.unit_price,
lot=self.lot,
lot_unit_price=lot.cost_price,
))
def get_production_output_lot(self):
lot = super(StockMove, self).get_production_output_lot()
if lot:
cost_lines = self._get_production_output_lot_cost_lines()
if cost_lines and not getattr(lot, 'cost_lines', False):
lot.cost_lines = cost_lines
return lot
def _get_production_output_lot_cost_lines(self):
'''
Return a list of unpersistent stock.lot.cost_line instances to be
writen in cost_lines field of output_move's lot (the returned lines
doesn't have the lot's field)
'''
pool = Pool()
ModelData = pool.get('ir.model.data')
inputs_category_id = ModelData.get_id('production_lot_cost',
'cost_category_inputs_cost')
infrastructure_category_id = ModelData.get_id('production_lot_cost',
'cost_category_infrastructure_cost')
# Unit price of cost_line should not include infrastructure_cost but
# as production.cost computed method is overriden and it includes this
# cost, here we must compute the original production cost again
production = self.production_output
cost = Decimal(0)
for input_ in production.inputs:
if input_.lot and input_.lot.cost_price:
cost_price = input_.lot.cost_price
elif input_.cost_price is not None:
cost_price = input_.cost_price
else:
cost_price = input_.product.cost_price
cost += (Decimal(str(input_.internal_quantity)) * cost_price)
factor = 1
res = []
if production.bom:
factor = production.bom.compute_factor(production.product,
production.quantity or 0, production.uom)
for output in production.bom and production.bom.outputs or []:
quantity = output.compute_quantity(factor)
if output.product == self.product and quantity:
res.append(
self._get_production_output_lot_cost_line(
inputs_category_id,
Decimal(cost / Decimal(str(quantity))), self.lot)
)
elif (self.product == production.product and self.quantity):
quantity = production.output_qty
if quantity:
res.append(
self._get_production_output_lot_cost_line(
inputs_category_id,
Decimal(cost / Decimal(str(quantity))), self.lot)
)
if (self.product == production.product and
production.infrastructure_cost):
infrastructure_cost = self._get_production_output_lot_cost_line(
infrastructure_category_id, production.infrastructure_cost,
self.lot)
res.append(infrastructure_cost)
return res
def _get_production_output_lot_cost_line(self, category_id, cost, lot):
pool = Pool()
LotCostLine = pool.get('stock.lot.cost_line')
return LotCostLine(
category=category_id,
unit_price=cost,
origin=str(self),
lot=lot,
)

View File

@ -211,8 +211,6 @@ Make a production with infrastructure cost::
>>> output, = production.outputs
>>> output.state
'done'
>>> len(output.lot.cost_lines)
2
>>> production.cost == Decimal('27')
True
>>> output, = production.outputs

View File

@ -183,8 +183,6 @@ production is Running::
>>> output, = production.outputs
>>> output.state
'done'
>>> len(output.lot.cost_lines)
2
>>> production.cost == Decimal('27')
True
>>> output.unit_price
@ -231,7 +229,5 @@ production is done::
True
>>> output.unit_price
Decimal('13.5000')
>>> len(output.lot.cost_lines)
2
>>> output.lot.cost_price == Decimal('13.5')
True

View File

@ -5,7 +5,6 @@ depends:
stock_lot_cost
extras_depend:
production_output_lot
production_operation
xml:
production.xml
message.xml