implement funcionality

This commit is contained in:
?ngel ?lvarez 2014-01-04 17:53:24 +01:00
parent 73cbc662e6
commit 68f13fb2dc
8 changed files with 892 additions and 34 deletions

227
locale/ca_ES.po Normal file
View File

@ -0,0 +1,227 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:product.cost.plan,bom:"
msgid "BOM"
msgstr "Llista de materials"
msgctxt "field:product.cost.plan,boms:"
msgid "BOMs"
msgstr "Llistes de materials"
msgctxt "field:product.cost.plan,create_date:"
msgid "Create Date"
msgstr "Data de creació"
msgctxt "field:product.cost.plan,create_uid:"
msgid "Create User"
msgstr "Usuari de creació"
msgctxt "field:product.cost.plan,id:"
msgid "ID"
msgstr "Identificador"
msgctxt "field:product.cost.plan,product:"
msgid "Product"
msgstr "Producte"
msgctxt "field:product.cost.plan,product_cost:"
msgid "Product Cost"
msgstr "Cost del producte"
msgctxt "field:product.cost.plan,products:"
msgid "Products"
msgstr "Productes"
msgctxt "field:product.cost.plan,quantity:"
msgid "Quantity"
msgstr "Quantitat"
msgctxt "field:product.cost.plan,rec_name:"
msgid "Name"
msgstr "Nom"
msgctxt "field:product.cost.plan,state:"
msgid "State"
msgstr "Estat"
msgctxt "field:product.cost.plan,total_cost:"
msgid "Total Cost"
msgstr "Cost total"
msgctxt "field:product.cost.plan,write_date:"
msgid "Write Date"
msgstr "Data modificació"
msgctxt "field:product.cost.plan,write_uid:"
msgid "Write User"
msgstr "Usuari modificació"
msgctxt "field:product.cost.plan.bom_line,bom:"
msgid "BOM"
msgstr "Llista de materials"
msgctxt "field:product.cost.plan.bom_line,create_date:"
msgid "Create Date"
msgstr "Data de creació"
msgctxt "field:product.cost.plan.bom_line,create_uid:"
msgid "Create User"
msgstr "Usuari de creació"
msgctxt "field:product.cost.plan.bom_line,id:"
msgid "ID"
msgstr "Identificador"
msgctxt "field:product.cost.plan.bom_line,plan:"
msgid "Plan"
msgstr "Pla"
msgctxt "field:product.cost.plan.bom_line,product:"
msgid "Product"
msgstr "Producte"
msgctxt "field:product.cost.plan.bom_line,rec_name:"
msgid "Name"
msgstr "Nom"
msgctxt "field:product.cost.plan.bom_line,write_date:"
msgid "Write Date"
msgstr "Data modificació"
msgctxt "field:product.cost.plan.bom_line,write_uid:"
msgid "Write User"
msgstr "Usuari modificació"
msgctxt "field:product.cost.plan.product_line,cost_price:"
msgid "Cost Price"
msgstr "Preu de cost"
msgctxt "field:product.cost.plan.product_line,create_date:"
msgid "Create Date"
msgstr "Data de creació"
msgctxt "field:product.cost.plan.product_line,create_uid:"
msgid "Create User"
msgstr "Usuari de creació"
msgctxt "field:product.cost.plan.product_line,id:"
msgid "ID"
msgstr "Identificador"
msgctxt "field:product.cost.plan.product_line,last_purchase_price:"
msgid "Last Purchase Price"
msgstr "Últim preu de compra"
msgctxt "field:product.cost.plan.product_line,plan:"
msgid "Plan"
msgstr "Pla"
msgctxt "field:product.cost.plan.product_line,product:"
msgid "Product"
msgstr "Producte"
msgctxt "field:product.cost.plan.product_line,product_cost_price:"
msgid "Product Cost Price"
msgstr "Preu de cost del producte"
msgctxt "field:product.cost.plan.product_line,quantity:"
msgid "Quantity"
msgstr "Quantitat"
msgctxt "field:product.cost.plan.product_line,rec_name:"
msgid "Name"
msgstr "Nom"
msgctxt "field:product.cost.plan.product_line,total:"
msgid "Total Cost"
msgstr "Cost total"
msgctxt "field:product.cost.plan.product_line,uom:"
msgid "Uom"
msgstr "UdM"
msgctxt "field:product.cost.plan.product_line,uom_category:"
msgid "Uom Category"
msgstr "Categoria d'UdM"
msgctxt "field:product.cost.plan.product_line,write_date:"
msgid "Write Date"
msgstr "Data modificació"
msgctxt "field:product.cost.plan.product_line,write_uid:"
msgid "Write User"
msgstr "Usuari modificació"
msgctxt "model:ir.action,name:act_product_cost_plan"
msgid "Product Cost Plan"
msgstr "Pla de costos de producte"
msgctxt "model:ir.action,name:act_product_cost_plan_bom_line"
msgid "Product Cost Plan BOM"
msgstr "LdM Pla de costos de producte"
msgctxt "model:ir.action,name:act_product_cost_plan_product_line"
msgid "Product Cost Plan Product Line"
msgstr "Línia de producte de Pla de costos de producte"
msgctxt "model:ir.ui.menu,name:menu_product_cost_plan"
msgid "Product Cost Plan"
msgstr "Pla de costos de producte"
msgctxt "model:product.cost.plan,name:"
msgid "Product Cost Plan"
msgstr "Pla de costos de producte"
msgctxt "model:product.cost.plan.bom_line,name:"
msgid "Product Cost Plan BOM"
msgstr "LdM Pla de costos de producte"
msgctxt "model:product.cost.plan.product_line,name:"
msgid "Product Cost Plan Product Line"
msgstr "Línia de producte de Pla de costos de producte"
msgctxt "model:res.group,name:group_product_cost_plan"
msgid "Product Cost Plan"
msgstr "Pla de costos de producte"
msgctxt "model:res.group,name:group_product_cost_plan_admin"
msgid "Product Cost Plan Administration"
msgstr "Administració Pla de costos de producte"
msgctxt "selection:product.cost.plan,state:"
msgid "Computed"
msgstr "Calcul·lat"
msgctxt "selection:product.cost.plan,state:"
msgid "Draft"
msgstr "Esborrany"
msgctxt "view:product.cost.plan.bom_line:"
msgid "Product Cost Plan BOM"
msgstr "LdM Pla de costos de producte"
msgctxt "view:product.cost.plan.product_line:"
msgid "Product Cost Plan Product Line"
msgstr "Línia de producte de Pla de costos de producte"
msgctxt "view:product.cost.plan:"
msgid "BOM Configuration"
msgstr "Configuració de llistes de materials"
msgctxt "view:product.cost.plan:"
msgid "Compute"
msgstr "Calcula"
msgctxt "view:product.cost.plan:"
msgid "General"
msgstr "General"
msgctxt "view:product.cost.plan:"
msgid "Product Cost Plan"
msgstr "Pla de costos de producte"
msgctxt "view:product.cost.plan:"
msgid "Reset"
msgstr "Reinicialitza"

227
locale/es_ES.po Normal file
View File

@ -0,0 +1,227 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:product.cost.plan,bom:"
msgid "BOM"
msgstr "Lista de material"
msgctxt "field:product.cost.plan,boms:"
msgid "BOMs"
msgstr "Listas de material"
msgctxt "field:product.cost.plan,create_date:"
msgid "Create Date"
msgstr "Fecha de creación"
msgctxt "field:product.cost.plan,create_uid:"
msgid "Create User"
msgstr "Usuario de creación"
msgctxt "field:product.cost.plan,id:"
msgid "ID"
msgstr "Identificador"
msgctxt "field:product.cost.plan,product:"
msgid "Product"
msgstr "Producto"
msgctxt "field:product.cost.plan,product_cost:"
msgid "Product Cost"
msgstr "Coste del producto"
msgctxt "field:product.cost.plan,products:"
msgid "Products"
msgstr "Productos"
msgctxt "field:product.cost.plan,quantity:"
msgid "Quantity"
msgstr "Cantidad"
msgctxt "field:product.cost.plan,rec_name:"
msgid "Name"
msgstr "Nombre"
msgctxt "field:product.cost.plan,state:"
msgid "State"
msgstr "Estado"
msgctxt "field:product.cost.plan,total_cost:"
msgid "Total Cost"
msgstr "Coste total"
msgctxt "field:product.cost.plan,write_date:"
msgid "Write Date"
msgstr "Fecha modificación"
msgctxt "field:product.cost.plan,write_uid:"
msgid "Write User"
msgstr "Usuario modificación"
msgctxt "field:product.cost.plan.bom_line,bom:"
msgid "BOM"
msgstr "Lista de material"
msgctxt "field:product.cost.plan.bom_line,create_date:"
msgid "Create Date"
msgstr "Fecha de creación"
msgctxt "field:product.cost.plan.bom_line,create_uid:"
msgid "Create User"
msgstr "Usuario de creación"
msgctxt "field:product.cost.plan.bom_line,id:"
msgid "ID"
msgstr "Identificador"
msgctxt "field:product.cost.plan.bom_line,plan:"
msgid "Plan"
msgstr "Plan"
msgctxt "field:product.cost.plan.bom_line,product:"
msgid "Product"
msgstr "Producto"
msgctxt "field:product.cost.plan.bom_line,rec_name:"
msgid "Name"
msgstr "Nombre"
msgctxt "field:product.cost.plan.bom_line,write_date:"
msgid "Write Date"
msgstr "Fecha modificación"
msgctxt "field:product.cost.plan.bom_line,write_uid:"
msgid "Write User"
msgstr "Usuario modificación"
msgctxt "field:product.cost.plan.product_line,cost_price:"
msgid "Cost Price"
msgstr "Precio de coste"
msgctxt "field:product.cost.plan.product_line,create_date:"
msgid "Create Date"
msgstr "Fecha de creación"
msgctxt "field:product.cost.plan.product_line,create_uid:"
msgid "Create User"
msgstr "Usuario de creación"
msgctxt "field:product.cost.plan.product_line,id:"
msgid "ID"
msgstr "Identificador"
msgctxt "field:product.cost.plan.product_line,last_purchase_price:"
msgid "Last Purchase Price"
msgstr "Último precio de compra"
msgctxt "field:product.cost.plan.product_line,plan:"
msgid "Plan"
msgstr "Plan"
msgctxt "field:product.cost.plan.product_line,product:"
msgid "Product"
msgstr "Producto"
msgctxt "field:product.cost.plan.product_line,product_cost_price:"
msgid "Product Cost Price"
msgstr "Precio de coste del producto"
msgctxt "field:product.cost.plan.product_line,quantity:"
msgid "Quantity"
msgstr "Cantidad"
msgctxt "field:product.cost.plan.product_line,rec_name:"
msgid "Name"
msgstr "Nombre"
msgctxt "field:product.cost.plan.product_line,total:"
msgid "Total Cost"
msgstr "Coste total"
msgctxt "field:product.cost.plan.product_line,uom:"
msgid "Uom"
msgstr "UdM"
msgctxt "field:product.cost.plan.product_line,uom_category:"
msgid "Uom Category"
msgstr "Categoría de UdM"
msgctxt "field:product.cost.plan.product_line,write_date:"
msgid "Write Date"
msgstr "Fecha modificación"
msgctxt "field:product.cost.plan.product_line,write_uid:"
msgid "Write User"
msgstr "Usuario modificación"
msgctxt "model:ir.action,name:act_product_cost_plan"
msgid "Product Cost Plan"
msgstr "Plan de coste del producto"
msgctxt "model:ir.action,name:act_product_cost_plan_bom_line"
msgid "Product Cost Plan BOM"
msgstr "LdM Plan de coste del producto"
msgctxt "model:ir.action,name:act_product_cost_plan_product_line"
msgid "Product Cost Plan Product Line"
msgstr "Linea de producto Plan de coste del producto"
msgctxt "model:ir.ui.menu,name:menu_product_cost_plan"
msgid "Product Cost Plan"
msgstr "Plan de coste del producto"
msgctxt "model:product.cost.plan,name:"
msgid "Product Cost Plan"
msgstr "Plan de coste del producto"
msgctxt "model:product.cost.plan.bom_line,name:"
msgid "Product Cost Plan BOM"
msgstr "LdM Plan de coste del producto"
msgctxt "model:product.cost.plan.product_line,name:"
msgid "Product Cost Plan Product Line"
msgstr "Linea de producto Plan de coste del producto"
msgctxt "model:res.group,name:group_product_cost_plan"
msgid "Product Cost Plan"
msgstr "Plan de coste del producto"
msgctxt "model:res.group,name:group_product_cost_plan_admin"
msgid "Product Cost Plan Administration"
msgstr "Administración Plan de coste del producto"
msgctxt "selection:product.cost.plan,state:"
msgid "Computed"
msgstr "Calculado"
msgctxt "selection:product.cost.plan,state:"
msgid "Draft"
msgstr "Borrador"
msgctxt "view:product.cost.plan.bom_line:"
msgid "Product Cost Plan BOM"
msgstr "LdM Plan de coste del producto"
msgctxt "view:product.cost.plan.product_line:"
msgid "Product Cost Plan Product Line"
msgstr "Linea de producto Plan de coste del producto"
msgctxt "view:product.cost.plan:"
msgid "BOM Configuration"
msgstr "Configuración lista de material"
msgctxt "view:product.cost.plan:"
msgid "Compute"
msgstr "Calcular"
msgctxt "view:product.cost.plan:"
msgid "General"
msgstr "General"
msgctxt "view:product.cost.plan:"
msgid "Product Cost Plan"
msgstr "Plan de coste del producto"
msgctxt "view:product.cost.plan:"
msgid "Reset"
msgstr "Reiniciar"

186
plan.py
View File

@ -9,14 +9,25 @@ __all__ = ['Plan', 'PlanBOM', 'PlanProductLine']
class Plan(Workflow, ModelSQL, ModelView):
'Product Cost Plan'
__name__ = 'product.cost.plan'
product = fields.Many2One('product.product', 'Product', required=True)
product = fields.Many2One('product.product', 'Product', required=True,
states={
'readonly': Eval('state') != 'draft',
}, depends=['state'], on_change=['product', 'bom', 'boms'])
bom = fields.Many2One('production.bom', 'BOM', on_change_with=['product'],
required=True)
required=True, states={
'readonly': Eval('state') != 'draft',
}, depends=['state', 'product'],
domain=[
('output_products', '=', Eval('product', 0)),
],)
boms = fields.One2Many('product.cost.plan.bom_line', 'plan', 'BOMs',
states={
'readonly': Eval('state') != 'draft',
}, depends=['state'], on_change_with=['bom'])
quantity = fields.Float('Quantity', required=True)
}, depends=['state'], on_change_with=['bom', 'boms'])
quantity = fields.Float('Quantity', required=True, states={
'readonly': Eval('state') != 'draft',
}, depends=['state'])
products = fields.One2Many('product.cost.plan.product_line', 'plan',
'Products', states={
'readonly': Eval('state') == 'draft',
@ -24,7 +35,7 @@ class Plan(Workflow, ModelSQL, ModelView):
product_cost = fields.Function(fields.Numeric('Product Cost',
on_change_with=['products']), 'on_change_with_product_cost')
total_cost = fields.Function(fields.Numeric('Total Cost',
on_change_with=['products']),
on_change_with=['product_cost']),
'on_change_with_total_cost')
state = fields.Selection([
('draft', 'Draft'),
@ -39,11 +50,13 @@ class Plan(Workflow, ModelSQL, ModelView):
('computed', 'draft'),
))
cls._buttons.update({
'confirm': {
'invisible': Eval('state') == 'confirmed',
'compute': {
'invisible': Eval('state') == 'computed',
'icon': 'tryton-go-next',
},
'reset': {
'invisible': Eval('state') == 'draft',
'icon': 'tryton-go-previous',
}
})
@ -51,16 +64,45 @@ class Plan(Workflow, ModelSQL, ModelView):
def default_state():
return 'draft'
def on_change_product(self):
res = {'bom': None}
bom = self.on_change_with_bom()
self.bom = bom
res['boms'] = self.on_change_with_boms()
return res
def on_change_with_bom(self):
BOM = Pool().get('production.bom')
product_id = self.product.id if self.product else None
boms = BOM.search([('output_products', '=', product_id)])
if not self.product:
return
boms = BOM.search([('output_products', '=', self.product.id)])
if boms:
return boms[0].id
return None
def on_change_with_boms(self):
return []
boms = {
'remove': [x.id for x in self.boms],
'add': [],
}
if not self.bom:
return boms
def find_boms(inputs):
res = []
for input_ in inputs:
if input_.product.boms:
res.append(input_.product.id)
for product_bom in input_.product.boms:
if product_bom.bom and product_bom.bom.inputs:
res.extend(find_boms(product_bom.bom.inputs))
return res
products = set(find_boms(self.bom.inputs))
for product in products:
boms['add'].append({
'product': product,
})
return boms
def on_change_with_product_cost(self, name=None):
cost = Decimal('0.0')
@ -73,34 +115,134 @@ class Plan(Workflow, ModelSQL, ModelView):
@classmethod
@ModelView.button
@Workflow.transition('confirmed')
@Workflow.transition('draft')
def reset(cls, plans):
pool = Pool()
ProductLines = pool.get('product.cost.plan.product_line')
to_delete = []
for plan in plans:
to_delete.extend(plan.products)
if to_delete:
ProductLines.delete(to_delete)
@classmethod
@ModelView.button
@Workflow.transition('computed')
def compute(cls, plans):
'''
Create all necessary products and operations
'''
pass
pool = Pool()
ProductLines = pool.get('product.cost.plan.product_line')
to_create = []
for plan in plans:
to_create.extend(plan.explode_bom(plan.product, plan.bom,
plan.quantity, plan.product.default_uom))
if to_create:
ProductLines.create(to_create)
def explode_bom(self, product, bom, quantity, uom):
" Returns products for the especified products"
pool = Pool()
Input = pool.get('production.bom.input')
res = []
plan_boms = {}
for plan_bom in self.boms:
if plan_bom.bom:
plan_boms[plan_bom.product.id] = plan_bom.bom
factor = bom.compute_factor(product, quantity, uom)
for input_ in bom.inputs:
product = input_.product
if product.id in plan_boms:
quantity = Input.compute_quantity(input_, factor)
res.extend(self.explode_bom(product, plan_boms[product.id],
quantity, input_.uom))
else:
line = self.get_product_line(input_, factor)
if line:
line['plan'] = self.id
res.append(line)
return res
def get_product_line(self, input_, factor):
"""
Returns a dict with values of the new line to create
params:
*input_*: Production.bom.input record for the product
*factor*: The factor to calculate the quantity
"""
pool = Pool()
Input = pool.get('production.bom.input')
quantity = Input.compute_quantity(input_, factor)
return {
'product': input_.product.id,
'quantity': quantity,
'uom': input_.uom.id,
'product_cost_price': input_.product.cost_price,
'cost_price': input_.product.cost_price,
}
class PlanBOM(ModelSQL, ModelView):
'Product Cost Plan BOM'
__name__ = 'product.cost.plan.bom_line'
plan = fields.Many2One('product.cost.plan', 'Plan', required=True)
product = fields.Many2One('product.product', 'Product', required=True)
bom = fields.Many2One('production.bom', 'BOM')
bom = fields.Many2One('production.bom', 'BOM', domain=[
('output_products', '=', Eval('product', 0)),
], depends=['product'])
class PlanProductLine(ModelSQL, ModelView):
'Product Cost Plan Product Line'
__name__ = 'product.cost.plan.product_line'
plan = fields.Many2One('product.cost.plan', 'Plan', required=True)
product = fields.Many2One('product.product', 'Product', required=True)
product = fields.Many2One('product.product', 'Product', required=True,
domain=[
('type', '!=', 'service'),
], on_change=['product', 'uom'])
quantity = fields.Float('Quantity', required=True)
uom_category = fields.Function(fields.Many2One(
'product.uom.category', 'Uom Category',
on_change_with=['product']), 'on_change_with_uom_category')
uom = fields.Many2One('product.uom', 'Uom', required=True,
domain=[
('category', '=', Eval('uom_category')),
], depends=['uom_category'])
product_cost_price = fields.Numeric('Product Cost Price', required=True)
last_purchase_price = fields.Numeric('Last Purchase Price')
cost_price = fields.Numeric('Cost Price', required=True)
total = fields.Function(fields.Numeric('Total Cost', on_change_with=[
'quantity', 'cost_price']), 'on_change_with_total')
'quantity', 'cost_price', 'uom', 'product']),
'on_change_with_total')
def on_change_with_total(self):
return ((self.quantity or Decimal('0.0'))
* (self.cost_price or Decimal('0.0')))
def on_change_product(self):
res = {}
if self.product:
uoms = self.product.default_uom.category.uoms
if (not self.uom or self.uom not in uoms):
res['uom'] = self.product.default_uom.id
res['uom.rec_name'] = self.product.default_uom.rec_name
res['product_cost'] = self.product.cost_price
else:
res['uom'] = None
res['uom.rec_name'] = ''
res['product_cost'] = None
return res
def on_change_with_uom_category(self, name=None):
if self.product:
return self.product.default_uom.category.id
def on_change_with_total(self, name=None):
pool = Pool()
Uom = pool.get('product.uom')
quantity = Uom.compute_qty(self.uom, self.quantity,
self.product.default_uom, round=False)
return Decimal(str(quantity)) * (self.cost_price or Decimal('0.0'))

View File

@ -0,0 +1,257 @@
===================
Production Scenario
===================
=============
General Setup
=============
Imports::
>>> import datetime
>>> from dateutil.relativedelta import relativedelta
>>> from decimal import Decimal
>>> from proteus import config, Model, Wizard
>>> today = datetime.date.today()
Create database::
>>> config = config.set_trytond()
>>> config.pool.test = True
Install production Module::
>>> Module = Model.get('ir.module.module')
>>> modules = Module.find([('name', '=', 'product_cost_plan')])
>>> Module.install([x.id for x in modules], config.context)
>>> Wizard('ir.module.module.install_upgrade').execute('upgrade')
Create company::
>>> Currency = Model.get('currency.currency')
>>> CurrencyRate = Model.get('currency.currency.rate')
>>> Company = Model.get('company.company')
>>> Party = Model.get('party.party')
>>> company_config = Wizard('company.company.config')
>>> company_config.execute('company')
>>> company = company_config.form
>>> party = Party(name='Dunder Mifflin')
>>> party.save()
>>> company.party = party
>>> currencies = Currency.find([('code', '=', 'USD')])
>>> if not currencies:
... currency = Currency(name='Euro', symbol=u'$', code='USD',
... rounding=Decimal('0.01'), mon_grouping='[3, 3, 0]',
... mon_decimal_point=',')
... currency.save()
... CurrencyRate(date=today + relativedelta(month=1, day=1),
... rate=Decimal('1.0'), currency=currency).save()
... else:
... currency, = currencies
>>> company.currency = currency
>>> company_config.execute('add')
>>> company, = Company.find()
Reload the context::
>>> User = Model.get('res.user')
>>> config._context = User.get_preferences(True, config.context)
Configuration production location::
>>> Location = Model.get('stock.location')
>>> warehouse, = Location.find([('code', '=', 'WH')])
>>> production_location, = Location.find([('code', '=', 'PROD')])
>>> warehouse.production_location = production_location
>>> warehouse.save()
Create product::
>>> ProductUom = Model.get('product.uom')
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
>>> ProductTemplate = Model.get('product.template')
>>> Product = Model.get('product.product')
>>> product = Product()
>>> template = ProductTemplate()
>>> template.name = 'product'
>>> template.default_uom = unit
>>> template.type = 'goods'
>>> template.list_price = Decimal(30)
>>> template.cost_price = Decimal(20)
>>> template.save()
>>> product.template = template
>>> product.save()
Create Components::
>>> meter, = ProductUom.find([('name', '=', 'Meter')])
>>> centimeter, = ProductUom.find([('name', '=', 'centimeter')])
>>> componentA = Product()
>>> templateA = ProductTemplate()
>>> templateA.name = 'component A'
>>> templateA.default_uom = meter
>>> templateA.type = 'goods'
>>> templateA.list_price = Decimal(2)
>>> templateA.cost_price = Decimal(1)
>>> templateA.save()
>>> componentA.template = templateA
>>> componentA.save()
>>> componentB = Product()
>>> templateB = ProductTemplate()
>>> templateB.name = 'component B'
>>> templateB.default_uom = meter
>>> templateB.type = 'goods'
>>> templateB.list_price = Decimal(2)
>>> templateB.cost_price = Decimal(1)
>>> templateB.save()
>>> componentB.template = templateB
>>> componentB.save()
>>> component1 = Product()
>>> template1 = ProductTemplate()
>>> template1.name = 'component 1'
>>> template1.default_uom = unit
>>> template1.type = 'goods'
>>> template1.list_price = Decimal(5)
>>> template1.cost_price = Decimal(2)
>>> template1.save()
>>> component1.template = template1
>>> component1.save()
>>> component2 = Product()
>>> template2 = ProductTemplate()
>>> template2.name = 'component 2'
>>> template2.default_uom = meter
>>> template2.type = 'goods'
>>> template2.list_price = Decimal(7)
>>> template2.cost_price = Decimal(5)
>>> template2.save()
>>> component2.template = template2
>>> component2.save()
Create Bill of Material::
>>> BOM = Model.get('production.bom')
>>> BOMInput = Model.get('production.bom.input')
>>> BOMOutput = Model.get('production.bom.output')
>>> component_bom = BOM(name='component1')
>>> input1 = BOMInput()
>>> component_bom.inputs.append(input1)
>>> input1.product = componentA
>>> input1.quantity = 1
>>> input2 = BOMInput()
>>> component_bom.inputs.append(input2)
>>> input2.product = componentB
>>> input2.quantity = 1
>>> output = BOMOutput()
>>> component_bom.outputs.append(output)
>>> output.product = component1
>>> output.quantity = 1
>>> component_bom.save()
>>> ProductBom = Model.get('product.product-production.bom')
>>> component1.boms.append(ProductBom(bom=component_bom))
>>> component1.save()
>>> bom = BOM(name='product')
>>> input1 = BOMInput()
>>> bom.inputs.append(input1)
>>> input1.product = component1
>>> input1.quantity = 5
>>> input2 = BOMInput()
>>> bom.inputs.append(input2)
>>> input2.product = component2
>>> input2.quantity = 150
>>> input2.uom = centimeter
>>> output = BOMOutput()
>>> bom.outputs.append(output)
>>> output.product = product
>>> output.quantity = 1
>>> bom.save()
>>> ProductBom = Model.get('product.product-production.bom')
>>> product.boms.append(ProductBom(bom=bom))
>>> product.save()
Create a cost plan for product (without child boms)::
>>> CostPlan = Model.get('product.cost.plan')
>>> plan = CostPlan()
>>> plan.product = product
>>> len(plan.boms) == 1
True
>>> plan.boms[0].bom == None
True
>>> plan.quantity = 10
>>> plan.save()
>>> plan.state
u'draft'
>>> CostPlan.compute([plan.id], config.context)
>>> plan.reload()
>>> plan.state
u'computed'
>>> len(plan.products) == 2
True
>>> c1, = plan.products.find([
... ('product', '=', component1.id),
... ], limit=1)
>>> c1.quantity == 50.0
True
>>> c2, = plan.products.find([
... ('product', '=', component2.id),
... ], limit=1)
>>> c2.quantity == 1500.0
True
>>> cA = plan.products.find([
... ('product', '=', componentA.id),
... ], limit=1)
>>> len(cA) == 0
True
>>> cB = plan.products.find([
... ('product', '=', componentB.id),
... ], limit=1)
>>> len(cB) == 0
True
>>> plan.total_cost == Decimal('175.0')
True
Create a cost plan for product (with child boms)::
>>> CostPlan = Model.get('product.cost.plan')
>>> plan = CostPlan()
>>> plan.product = product
>>> len(plan.boms) == 1
True
>>> plan.quantity = 10
>>> plan.save()
>>> plan.state
u'draft'
>>> for product_bom in plan.boms:
... product_bom.bom = product_bom.product.boms[0]
... product_bom.save()
>>> plan.reload()
>>> CostPlan.compute([plan.id], config.context)
>>> plan.reload()
>>> plan.state
u'computed'
>>> len(plan.products) == 3
True
>>> cA, = plan.products.find([
... ('product', '=', componentA.id),
... ], limit=1)
>>> cA.quantity == 50.0
True
>>> cB, = plan.products.find([
... ('product', '=', componentB.id),
... ], limit=1)
>>> cB.quantity == 50.0
True
>>> c2, = plan.products.find([
... ('product', '=', component2.id),
... ], limit=1)
>>> c2.quantity == 1500.0
True
>>> plan.total_cost == Decimal('175.0')
True

View File

@ -10,7 +10,7 @@ if os.path.isdir(DIR):
sys.path.insert(0, os.path.dirname(DIR))
import unittest
#import doctest TODO: Remove if no sceneario needed.
import doctest
import trytond.tests.test_tryton
from trytond.tests.test_tryton import test_view, test_depends
from trytond.backend.sqlite.database import Database as SQLiteDatabase
@ -50,10 +50,9 @@ def doctest_dropdb(test):
def suite():
suite = trytond.tests.test_tryton.suite()
suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestCase))
# TODO: remove if no scenario needed.
#suite.addTests(doctest.DocFileSuite('scenario_invoice.rst',
# setUp=doctest_dropdb, tearDown=doctest_dropdb, encoding='utf-8',
# optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
suite.addTests(doctest.DocFileSuite('scenario_product_cost_plan.rst',
setUp=doctest_dropdb, tearDown=doctest_dropdb, encoding='utf-8',
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
return suite
if __name__ == '__main__':

View File

@ -21,8 +21,12 @@
<label name="total_cost"/>
<field name="total_cost"/>
<newline/>
<label name="state"/>
<field name="state"/>
<button name="compute"/>
<button name="reset"/>
<group id="state" colspan="6">
<label name="state"/>
<field name="state"/>
<group id="buttons" colspan="2">
<button name="compute" string="Compute"/>
<button name="reset" string="Reset"/>
</group>
</group>
</form>

View File

@ -2,13 +2,14 @@
<!-- The COPYRIGHT file at the top level of this repository contains the full
copyright notices and license terms. -->
<form string="Product Cost Plan Product Line">
<label name="plan"/>
<field name="plan"/>
<newline/>
<label name="product"/>
<field name="product"/>
<label name="plan"/>
<field name="plan"/>
<label name="quantity"/>
<field name="quantity"/>
<label name="uom"/>
<field name="uom"/>
<label name="product_cost_price"/>
<field name="product_cost_price"/>
<label name="last_purchase_price"/>

View File

@ -5,6 +5,7 @@
<field name="plan"/>
<field name="product"/>
<field name="quantity"/>
<field name="uom"/>
<field name="product_cost_price"/>
<field name="cost_price"/>
<field name="last_purchase_price"/>