parent
4af7b7ffe9
commit
9dd8d624fe
86
plan.py
86
plan.py
|
@ -1,8 +1,6 @@
|
||||||
# The COPYRIGHT file at the top level of this repository contains the full
|
# The COPYRIGHT file at the top level of this repository contains the full
|
||||||
# copyright notices and license terms.
|
# copyright notices and license terms.
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
|
||||||
from trytond.config import config
|
|
||||||
from trytond.model import ModelSQL, ModelView, DeactivableMixin, fields, tree
|
from trytond.model import ModelSQL, ModelView, DeactivableMixin, fields, tree
|
||||||
from trytond.pool import Pool
|
from trytond.pool import Pool
|
||||||
from trytond.pyson import Eval, Bool, If
|
from trytond.pyson import Eval, Bool, If
|
||||||
|
@ -10,8 +8,7 @@ from trytond.transaction import Transaction
|
||||||
from trytond.wizard import Wizard, StateView, StateAction, Button
|
from trytond.wizard import Wizard, StateView, StateAction, Button
|
||||||
from trytond.i18n import gettext
|
from trytond.i18n import gettext
|
||||||
from trytond.exceptions import UserWarning
|
from trytond.exceptions import UserWarning
|
||||||
|
from trytond.modules.product import price_digits, round_price
|
||||||
price_digits = (16, config.getint('product', 'price_decimal', default=4))
|
|
||||||
|
|
||||||
__all__ = ['PlanCostType', 'Plan', 'PlanBOM', 'PlanProductLine', 'PlanCost',
|
__all__ = ['PlanCostType', 'Plan', 'PlanBOM', 'PlanProductLine', 'PlanCost',
|
||||||
'CreateBomStart', 'CreateBom']
|
'CreateBomStart', 'CreateBom']
|
||||||
|
@ -181,8 +178,7 @@ class Plan(DeactivableMixin, ModelSQL, ModelView):
|
||||||
lines = Plan.get_all_inputs(self.products)
|
lines = Plan.get_all_inputs(self.products)
|
||||||
cost = sum(p.get_total_cost(None, round=False) for p in lines)
|
cost = sum(p.get_total_cost(None, round=False) for p in lines)
|
||||||
cost /= Decimal(str(self.quantity))
|
cost /= Decimal(str(self.quantity))
|
||||||
digits = self.__class__.products_cost.digits[1]
|
return round_price(cost)
|
||||||
return cost.quantize(Decimal(str(10 ** -digits)))
|
|
||||||
|
|
||||||
@fields.depends('product')
|
@fields.depends('product')
|
||||||
def on_change_with_product_cost_price(self, name=None):
|
def on_change_with_product_cost_price(self, name=None):
|
||||||
|
@ -273,7 +269,6 @@ class Plan(DeactivableMixin, ModelSQL, ModelView):
|
||||||
pool = Pool()
|
pool = Pool()
|
||||||
UoM = pool.get('product.uom')
|
UoM = pool.get('product.uom')
|
||||||
Input = pool.get('production.bom.input')
|
Input = pool.get('production.bom.input')
|
||||||
ProductLine = pool.get('product.cost.plan.product_line')
|
|
||||||
|
|
||||||
quantity = Input.compute_quantity(input_, factor)
|
quantity = Input.compute_quantity(input_, factor)
|
||||||
party_stock = getattr(input_, 'party_stock', False)
|
party_stock = getattr(input_, 'party_stock', False)
|
||||||
|
@ -282,22 +277,18 @@ class Plan(DeactivableMixin, ModelSQL, ModelView):
|
||||||
cost_factor = Decimal(
|
cost_factor = Decimal(
|
||||||
UoM.compute_qty(input_.product.default_uom, 1, input_.uom))
|
UoM.compute_qty(input_.product.default_uom, 1, input_.uom))
|
||||||
if cost_factor != Decimal('0.0'):
|
if cost_factor != Decimal('0.0'):
|
||||||
product_cost_price = input_.product.cost_price / cost_factor
|
product_cost_price = Decimal(input_.product.cost_price / cost_factor)
|
||||||
if not party_stock:
|
if not party_stock:
|
||||||
cost_price = product_cost_price
|
cost_price = product_cost_price
|
||||||
|
|
||||||
product_cost_price_digits = ProductLine.product_cost_price.digits[1]
|
|
||||||
cost_price_digits = ProductLine.cost_price.digits[1]
|
|
||||||
return {
|
return {
|
||||||
'name': input_.product.rec_name,
|
'name': input_.product.rec_name,
|
||||||
'product': input_.product.id,
|
'product': input_.product.id,
|
||||||
'quantity': quantity,
|
'quantity': quantity,
|
||||||
'uom': input_.uom.id,
|
'uom': input_.uom.id,
|
||||||
'party_stock': getattr(input_, 'party_stock', False),
|
'party_stock': getattr(input_, 'party_stock', False),
|
||||||
'product_cost_price': product_cost_price.quantize(
|
'product_cost_price': round_price(product_cost_price),
|
||||||
Decimal(str(10 ** -product_cost_price_digits))),
|
'cost_price': round_price(cost_price),
|
||||||
'cost_price': cost_price.quantize(
|
|
||||||
Decimal(str(10 ** -cost_price_digits))),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_costs(self):
|
def get_costs(self):
|
||||||
|
@ -339,13 +330,9 @@ class Plan(DeactivableMixin, ModelSQL, ModelView):
|
||||||
cost_price = Uom.compute_price(self.uom, self.cost_price,
|
cost_price = Uom.compute_price(self.uom, self.cost_price,
|
||||||
self.product.default_uom)
|
self.product.default_uom)
|
||||||
if hasattr(self.product.__class__, 'cost_price'):
|
if hasattr(self.product.__class__, 'cost_price'):
|
||||||
digits = self.product.__class__.cost_price.digits[1]
|
self.product.cost_price = round_price(cost_price)
|
||||||
cost_price = cost_price.quantize(Decimal(str(10 ** -digits)))
|
|
||||||
self.product.cost_price = cost_price
|
|
||||||
else:
|
else:
|
||||||
digits = self.product.template.__class__.cost_price.digits[1]
|
self.product.template.cost_price = round_price(cost_price)
|
||||||
cost_price = cost_price.quantize(Decimal(str(10 ** -digits)))
|
|
||||||
self.product.template.cost_price = cost_price
|
|
||||||
|
|
||||||
def create_bom(self, name):
|
def create_bom(self, name):
|
||||||
pool = Pool()
|
pool = Pool()
|
||||||
|
@ -511,39 +498,35 @@ class PlanProductLine(ModelSQL, ModelView, tree(separator='/')):
|
||||||
plan = fields.Many2One('product.cost.plan', 'Plan', required=False,
|
plan = fields.Many2One('product.cost.plan', 'Plan', required=False,
|
||||||
ondelete='CASCADE')
|
ondelete='CASCADE')
|
||||||
product = fields.Many2One('product.product', 'Product', domain=[
|
product = fields.Many2One('product.product', 'Product', domain=[
|
||||||
('type', '!=', 'service'),
|
('type', '!=', 'service'),
|
||||||
If(Bool(Eval('children')),
|
If(Bool(Eval('children')),
|
||||||
('default_uom.category', '=', Eval('uom_category')),
|
('default_uom.category', '=', Eval('uom_category')),
|
||||||
()),
|
()),
|
||||||
], depends=['children', 'uom_category'])
|
], depends=['children', 'uom_category'])
|
||||||
quantity = fields.Float('Quantity', required=True,
|
quantity = fields.Float('Quantity', required=True,
|
||||||
digits=(16, Eval('uom_digits', 2)), depends=['uom_digits'])
|
digits=(16, Eval('uom_digits', 2)), depends=['uom_digits'])
|
||||||
uom_category = fields.Function(fields.Many2One('product.uom.category',
|
uom_category = fields.Function(fields.Many2One('product.uom.category',
|
||||||
'UoM Category'),
|
'UoM Category'), 'on_change_with_uom_category')
|
||||||
'on_change_with_uom_category')
|
|
||||||
uom = fields.Many2One('product.uom', 'UoM', required=True, domain=[
|
uom = fields.Many2One('product.uom', 'UoM', required=True, domain=[
|
||||||
If(Bool(Eval('children')) | Bool(Eval('product')),
|
If(Bool(Eval('children')) | Bool(Eval('product')),
|
||||||
('category', '=', Eval('uom_category')),
|
('category', '=', Eval('uom_category')),
|
||||||
()),
|
()),
|
||||||
], depends=['children', 'product', 'uom_category'])
|
], depends=['children', 'product', 'uom_category'])
|
||||||
uom_digits = fields.Function(fields.Integer('UoM Digits'),
|
uom_digits = fields.Function(fields.Integer('UoM Digits'),
|
||||||
'on_change_with_uom_digits')
|
'on_change_with_uom_digits')
|
||||||
party_stock = fields.Boolean('Party Stock',
|
party_stock = fields.Boolean('Party Stock',
|
||||||
help='Use stock owned by party instead of company stock.')
|
help='Use stock owned by party instead of company stock.')
|
||||||
product_cost_price = fields.Numeric('Product Cost Price',
|
product_cost_price = fields.Numeric('Product Cost Price', digits=price_digits,
|
||||||
digits=price_digits,
|
|
||||||
states={
|
states={
|
||||||
'readonly': True,
|
'readonly': True,
|
||||||
}, depends=['product'])
|
}, depends=['product'])
|
||||||
cost_price = fields.Numeric('Cost Price', required=True,
|
cost_price = fields.Numeric('Cost Price', required=True,
|
||||||
digits=price_digits)
|
digits=price_digits)
|
||||||
unit_cost = fields.Function(fields.Numeric('Unit Cost',
|
unit_cost = fields.Function(fields.Numeric('Unit Cost', digits=price_digits,
|
||||||
digits=price_digits,
|
help="The cost of this product for each unit of plan's product."),
|
||||||
help="The cost of this product for each unit of plan's product."),
|
|
||||||
'get_unit_cost')
|
'get_unit_cost')
|
||||||
total_cost = fields.Function(fields.Numeric('Total Cost',
|
total_cost = fields.Function(fields.Numeric('Total Cost', digits=price_digits,
|
||||||
digits=price_digits,
|
help="The cost of this product for total plan's quantity."),
|
||||||
help="The cost of this product for total plan's quantity."),
|
|
||||||
'get_total_cost')
|
'get_total_cost')
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -603,10 +586,9 @@ class PlanProductLine(ModelSQL, ModelView, tree(separator='/')):
|
||||||
self.cost_price = Decimal('0.0')
|
self.cost_price = Decimal('0.0')
|
||||||
return
|
return
|
||||||
if not self.cost_price and self.product and self.uom:
|
if not self.cost_price and self.product and self.uom:
|
||||||
digits = self.__class__.cost_price.digits[1]
|
|
||||||
cost = UoM.compute_price(self.product.default_uom,
|
cost = UoM.compute_price(self.product.default_uom,
|
||||||
self.product.cost_price, self.uom)
|
self.product.cost_price, self.uom)
|
||||||
self.cost_price = cost.quantize(Decimal(str(10 ** -digits)))
|
self.cost_price = round_price(cost)
|
||||||
|
|
||||||
@fields.depends('product', 'uom', 'cost_price')
|
@fields.depends('product', 'uom', 'cost_price')
|
||||||
def on_change_with_cost_price(self):
|
def on_change_with_cost_price(self):
|
||||||
|
@ -620,8 +602,7 @@ class PlanProductLine(ModelSQL, ModelView, tree(separator='/')):
|
||||||
cost = UoM.compute_price(self.product.default_uom,
|
cost = UoM.compute_price(self.product.default_uom,
|
||||||
self.product.cost_price, self.uom)
|
self.product.cost_price, self.uom)
|
||||||
if cost:
|
if cost:
|
||||||
digits = self.__class__.cost_price.digits[1]
|
return round_price(cost)
|
||||||
return cost.quantize(Decimal(str(10 ** -digits)))
|
|
||||||
return cost
|
return cost
|
||||||
|
|
||||||
@fields.depends('product', 'uom')
|
@fields.depends('product', 'uom')
|
||||||
|
@ -634,8 +615,7 @@ class PlanProductLine(ModelSQL, ModelView, tree(separator='/')):
|
||||||
else:
|
else:
|
||||||
cost = UoM.compute_price(self.product.default_uom,
|
cost = UoM.compute_price(self.product.default_uom,
|
||||||
self.product.cost_price, self.uom)
|
self.product.cost_price, self.uom)
|
||||||
digits = self.__class__.product_cost_price.digits[1]
|
return round_price(cost)
|
||||||
return cost.quantize(Decimal(str(10 ** -digits)))
|
|
||||||
|
|
||||||
def get_plan(self):
|
def get_plan(self):
|
||||||
if self.plan:
|
if self.plan:
|
||||||
|
@ -648,8 +628,7 @@ class PlanProductLine(ModelSQL, ModelView, tree(separator='/')):
|
||||||
plan = self.get_plan()
|
plan = self.get_plan()
|
||||||
if unit_cost and plan and plan.quantity:
|
if unit_cost and plan and plan.quantity:
|
||||||
unit_cost /= Decimal(str(plan.quantity))
|
unit_cost /= Decimal(str(plan.quantity))
|
||||||
digits = self.__class__.unit_cost.digits[1]
|
return round_price(unit_cost)
|
||||||
return unit_cost.quantize(Decimal(str(10 ** -digits)))
|
|
||||||
|
|
||||||
def get_total_cost(self, name, round=True):
|
def get_total_cost(self, name, round=True):
|
||||||
if not self.cost_price:
|
if not self.cost_price:
|
||||||
|
@ -666,8 +645,7 @@ class PlanProductLine(ModelSQL, ModelView, tree(separator='/')):
|
||||||
total_cost = Decimal(str(quantity)) * self.cost_price
|
total_cost = Decimal(str(quantity)) * self.cost_price
|
||||||
if not round:
|
if not round:
|
||||||
return total_cost
|
return total_cost
|
||||||
digits = self.__class__.total_cost.digits[1]
|
return round_price(total_cost)
|
||||||
return total_cost.quantize(Decimal(str(10 ** -digits)))
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def copy(cls, lines, default=None):
|
def copy(cls, lines, default=None):
|
||||||
|
@ -704,12 +682,11 @@ class PlanCost(ModelSQL, ModelView):
|
||||||
sequence = fields.Integer('Sequence')
|
sequence = fields.Integer('Sequence')
|
||||||
type = fields.Many2One('product.cost.plan.cost.type', 'Type', domain=[
|
type = fields.Many2One('product.cost.plan.cost.type', 'Type', domain=[
|
||||||
('system', '=', Eval('system')),
|
('system', '=', Eval('system')),
|
||||||
],
|
], required=True, states=STATES, depends=DEPENDS)
|
||||||
required=True, states=STATES, depends=DEPENDS)
|
|
||||||
internal_cost = fields.Numeric('Cost (Internal Use)', digits=price_digits,
|
internal_cost = fields.Numeric('Cost (Internal Use)', digits=price_digits,
|
||||||
readonly=True)
|
readonly=True)
|
||||||
cost = fields.Function(fields.Numeric('Cost', digits=price_digits,
|
cost = fields.Function(fields.Numeric('Cost', digits=price_digits,
|
||||||
required=True, states=STATES, depends=DEPENDS),
|
required=True, states=STATES, depends=DEPENDS),
|
||||||
'get_cost', setter='set_cost')
|
'get_cost', setter='set_cost')
|
||||||
system = fields.Boolean('System Managed', readonly=True)
|
system = fields.Boolean('System Managed', readonly=True)
|
||||||
|
|
||||||
|
@ -739,8 +716,7 @@ class PlanCost(ModelSQL, ModelView):
|
||||||
cost = getattr(self.plan, self.type.plan_field_name)
|
cost = getattr(self.plan, self.type.plan_field_name)
|
||||||
else:
|
else:
|
||||||
cost = self.internal_cost
|
cost = self.internal_cost
|
||||||
digits = self.__class__.cost.digits[1]
|
return round_price(cost)
|
||||||
return cost.quantize(Decimal(str(10 ** -digits)))
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def set_cost(cls, records, name, value):
|
def set_cost(cls, records, name, value):
|
||||||
|
|
Loading…
Reference in New Issue