Some fixes and improvements

This commit is contained in:
Guillem Barba 2015-01-19 19:16:09 +01:00
parent 0cd91d1a19
commit 2b32fa46c3
12 changed files with 608 additions and 391 deletions

View File

@ -1,3 +1,6 @@
Version 3.4.1 - 2015-01-19
* Some fix and improvements
Version 3.4.0 - 2014-11-03 Version 3.4.0 - 2014-11-03
Version 3.2.0 - 2014-06-02 Version 3.2.0 - 2014-06-02

View File

@ -1,4 +1,4 @@
Copyright (C) 2013 NaN·tic Copyright (C) 2014-15 NaN·tic
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View File

@ -10,6 +10,26 @@ msgstr ""
"No podeu eliminar el cost \"%(cost)s\" del pla \"%(plan)s\" perquè està " "No podeu eliminar el cost \"%(cost)s\" del pla \"%(plan)s\" perquè està "
"gestionat pel sistema." "gestionat pel sistema."
msgctxt "error:product.cost.plan:"
msgid "A bom already exists for cost plan \"%s\"."
msgstr "Ja existeix una LdM pel pla de cost \"%s\"."
msgctxt "error:product.cost.plan:"
msgid "It will remove the existing Product Lines in this plan."
msgstr "S'eliminaran les línies de producte d'aquest pla."
msgctxt "error:product.cost.plan:"
msgid ""
"Product \"%(product)s\" in Cost Plan \"%(plan)s\" has different units of "
"measure."
msgstr ""
"El producte \"%(product)s\" del pla de cost \"%(plan)s\" té una unitat de "
"mesura diferent."
msgctxt "error:product.cost.plan:"
msgid "Product \"%s\" already has a BOM assigned."
msgstr "El producte \"%s\" ja té una LdM assignada."
msgctxt "field:product.cost.plan,active:" msgctxt "field:product.cost.plan,active:"
msgid "Active" msgid "Active"
msgstr "Actiu" msgstr "Actiu"
@ -42,6 +62,10 @@ msgctxt "field:product.cost.plan,id:"
msgid "ID" msgid "ID"
msgstr "Identificador" msgstr "Identificador"
msgctxt "field:product.cost.plan,name:"
msgid "Name"
msgstr "Nom"
msgctxt "field:product.cost.plan,notes:" msgctxt "field:product.cost.plan,notes:"
msgid "Notes" msgid "Notes"
msgstr "Notes" msgstr "Notes"
@ -54,10 +78,6 @@ msgctxt "field:product.cost.plan,product:"
msgid "Product" msgid "Product"
msgstr "Producte" msgstr "Producte"
msgctxt "field:product.cost.plan,product_cost:"
msgid "Product Cost"
msgstr "Cost del producte"
msgctxt "field:product.cost.plan,product_uom_category:" msgctxt "field:product.cost.plan,product_uom_category:"
msgid "Product UoM Category" msgid "Product UoM Category"
msgstr "Categoria UdM del producte" msgstr "Categoria UdM del producte"
@ -66,18 +86,30 @@ msgctxt "field:product.cost.plan,products:"
msgid "Products" msgid "Products"
msgstr "Productes" msgstr "Productes"
msgctxt "field:product.cost.plan,products_cost:"
msgid "Products Cost"
msgstr "Cost dels materials"
msgctxt "field:product.cost.plan,products_tree:"
msgid "Products"
msgstr "Productes"
msgctxt "field:product.cost.plan,quantity:"
msgid "Quantity"
msgstr "Quantitat"
msgctxt "field:product.cost.plan,rec_name:" msgctxt "field:product.cost.plan,rec_name:"
msgid "Name" msgid "Name"
msgstr "Nom" msgstr "Nom"
msgctxt "field:product.cost.plan,state:"
msgid "State"
msgstr "Estat"
msgctxt "field:product.cost.plan,uom:" msgctxt "field:product.cost.plan,uom:"
msgid "UoM" msgid "UoM"
msgstr "UdM" msgstr "UdM"
msgctxt "field:product.cost.plan,uom_digits:"
msgid "UoM Digits"
msgstr "Digits UdM"
msgctxt "field:product.cost.plan,write_date:" msgctxt "field:product.cost.plan,write_date:"
msgid "Write Date" msgid "Write Date"
msgstr "Data modificació" msgstr "Data modificació"
@ -138,6 +170,10 @@ msgctxt "field:product.cost.plan.cost,id:"
msgid "ID" msgid "ID"
msgstr "Identificador" msgstr "Identificador"
msgctxt "field:product.cost.plan.cost,internal_cost:"
msgid "Cost (Internal Use)"
msgstr "Cost (ús intern)"
msgctxt "field:product.cost.plan.cost,plan:" msgctxt "field:product.cost.plan.cost,plan:"
msgid "Plan" msgid "Plan"
msgstr "Pla" msgstr "Pla"
@ -146,6 +182,10 @@ msgctxt "field:product.cost.plan.cost,rec_name:"
msgid "Name" msgid "Name"
msgstr "Nom" msgstr "Nom"
msgctxt "field:product.cost.plan.cost,sequence:"
msgid "Sequence"
msgstr "Seqüència"
msgctxt "field:product.cost.plan.cost,system:" msgctxt "field:product.cost.plan.cost,system:"
msgid "System Managed" msgid "System Managed"
msgstr "Gestionat pel sistema" msgstr "Gestionat pel sistema"
@ -178,10 +218,18 @@ msgctxt "field:product.cost.plan.cost.type,name:"
msgid "Name" msgid "Name"
msgstr "Nom" msgstr "Nom"
msgctxt "field:product.cost.plan.cost.type,plan_field_name:"
msgid "Plan Field Name"
msgstr "Nom camp del pla"
msgctxt "field:product.cost.plan.cost.type,rec_name:" msgctxt "field:product.cost.plan.cost.type,rec_name:"
msgid "Name" msgid "Name"
msgstr "Nom" msgstr "Nom"
msgctxt "field:product.cost.plan.cost.type,system:"
msgid "System Managed"
msgstr "Gestionat pel sistema"
msgctxt "field:product.cost.plan.cost.type,write_date:" msgctxt "field:product.cost.plan.cost.type,write_date:"
msgid "Write Date" msgid "Write Date"
msgstr "Data modificació" msgstr "Data modificació"
@ -194,14 +242,14 @@ msgctxt "field:product.cost.plan.create_bom.start,id:"
msgid "ID" msgid "ID"
msgstr "Identificador" msgstr "Identificador"
msgctxt "field:product.cost.plan.create_bom.start,inputs:"
msgid "Inputs"
msgstr "Entrades"
msgctxt "field:product.cost.plan.create_bom.start,name:" msgctxt "field:product.cost.plan.create_bom.start,name:"
msgid "Name" msgid "Name"
msgstr "Nom" msgstr "Nom"
msgctxt "field:product.cost.plan.product_line,children:"
msgid "Children"
msgstr "Fills"
msgctxt "field:product.cost.plan.product_line,cost_price:" msgctxt "field:product.cost.plan.product_line,cost_price:"
msgid "Cost Price" msgid "Cost Price"
msgstr "Preu de cost" msgstr "Preu de cost"
@ -218,14 +266,14 @@ msgctxt "field:product.cost.plan.product_line,id:"
msgid "ID" msgid "ID"
msgstr "Identificador" 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,name:" msgctxt "field:product.cost.plan.product_line,name:"
msgid "Name" msgid "Name"
msgstr "Nom" msgstr "Nom"
msgctxt "field:product.cost.plan.product_line,parent:"
msgid "Parent"
msgstr "Pare"
msgctxt "field:product.cost.plan.product_line,plan:" msgctxt "field:product.cost.plan.product_line,plan:"
msgid "Plan" msgid "Plan"
msgstr "Pla" msgstr "Pla"
@ -250,10 +298,14 @@ msgctxt "field:product.cost.plan.product_line,sequence:"
msgid "Sequence" msgid "Sequence"
msgstr "Seqüència" msgstr "Seqüència"
msgctxt "field:product.cost.plan.product_line,total:" msgctxt "field:product.cost.plan.product_line,total_cost:"
msgid "Total Cost" msgid "Total Cost"
msgstr "Cost total" msgstr "Cost total"
msgctxt "field:product.cost.plan.product_line,unit_cost:"
msgid "Unit Cost"
msgstr "Cost unitari"
msgctxt "field:product.cost.plan.product_line,uom:" msgctxt "field:product.cost.plan.product_line,uom:"
msgid "UoM" msgid "UoM"
msgstr "UdM" msgstr "UdM"
@ -278,6 +330,14 @@ msgctxt "field:production.configuration,product_cost_plan_sequence:"
msgid "Product Cost Plan Sequence" msgid "Product Cost Plan Sequence"
msgstr "Seqüencia pla de costsos de producte" msgstr "Seqüencia pla de costsos de producte"
msgctxt "help:product.cost.plan.product_line,total_cost:"
msgid "The cost of this product for total plan's quantity."
msgstr "El cost d'aquest producte per la quantitat total del pla."
msgctxt "help:product.cost.plan.product_line,unit_cost:"
msgid "The cost of this product for each unit of plan's product."
msgstr "El cost d'aquest producte per cada unitat del producte del pla."
msgctxt "model:ir.action,name:act_product_cost_plan" msgctxt "model:ir.action,name:act_product_cost_plan"
msgid "Product Cost Plan" msgid "Product Cost Plan"
msgstr "Pla de costos de producte" msgstr "Pla de costos de producte"
@ -354,14 +414,6 @@ msgctxt "model:res.group,name:group_product_cost_plan_admin"
msgid "Product Cost Plan Administration" msgid "Product Cost Plan Administration"
msgstr "Administració Pla de costos de producte" msgstr "Administració Pla de costos de producte"
msgctxt "selection:product.cost.plan,state:"
msgid "Computed"
msgstr "Calculat"
msgctxt "selection:product.cost.plan,state:"
msgid "Draft"
msgstr "Esborrany"
msgctxt "view:product.cost.plan.bom_line:" msgctxt "view:product.cost.plan.bom_line:"
msgid "Product Cost Plan BOM" msgid "Product Cost Plan BOM"
msgstr "LdM Pla de costos de producte" msgstr "LdM Pla de costos de producte"
@ -394,10 +446,6 @@ msgctxt "view:product.cost.plan:"
msgid "Costs" msgid "Costs"
msgstr "Costos" msgstr "Costos"
msgctxt "view:product.cost.plan:"
msgid "General"
msgstr "General"
msgctxt "view:product.cost.plan:" msgctxt "view:product.cost.plan:"
msgid "Notes" msgid "Notes"
msgstr "Notes" msgstr "Notes"
@ -407,8 +455,12 @@ msgid "Product Cost Plan"
msgstr "Pla de costos de producte" msgstr "Pla de costos de producte"
msgctxt "view:product.cost.plan:" msgctxt "view:product.cost.plan:"
msgid "Reset" msgid "Products"
msgstr "Reinicialitza" msgstr "Productes"
msgctxt "view:product.cost.plan:"
msgid "Update Product's Prices"
msgstr "Actualitza preus del producte"
msgctxt "wizard_button:product.cost.plan.create_bom,start,bom:" msgctxt "wizard_button:product.cost.plan.create_bom,start,bom:"
msgid "Ok" msgid "Ok"

View File

@ -10,6 +10,26 @@ msgstr ""
"No se puede eliminar el coste \"%(cost)s\" del plan \"%(plan)s\" porqué esta" "No se puede eliminar el coste \"%(cost)s\" del plan \"%(plan)s\" porqué esta"
" gestionado por el sistema." " gestionado por el sistema."
msgctxt "error:product.cost.plan:"
msgid "A bom already exists for cost plan \"%s\"."
msgstr "Ya existe una LdM para el plan de costes \"%s\"."
msgctxt "error:product.cost.plan:"
msgid "It will remove the existing Product Lines in this plan."
msgstr "Se eliminaran las líneas de producto de este plan."
msgctxt "error:product.cost.plan:"
msgid ""
"Product \"%(product)s\" in Cost Plan \"%(plan)s\" has different units of "
"measure."
msgstr ""
"El producto \"%(product)s\" del plan de costes \"%(plan)s\" tiene unidades "
"de medida diferentes.¡"
msgctxt "error:product.cost.plan:"
msgid "Product \"%s\" already has a BOM assigned."
msgstr "El producto \"%s\" ya tiene una LdM asociada."
msgctxt "field:product.cost.plan,active:" msgctxt "field:product.cost.plan,active:"
msgid "Active" msgid "Active"
msgstr "Activo" msgstr "Activo"
@ -42,6 +62,10 @@ msgctxt "field:product.cost.plan,id:"
msgid "ID" msgid "ID"
msgstr "Identificador" msgstr "Identificador"
msgctxt "field:product.cost.plan,name:"
msgid "Name"
msgstr "Nombre"
msgctxt "field:product.cost.plan,notes:" msgctxt "field:product.cost.plan,notes:"
msgid "Notes" msgid "Notes"
msgstr "Notas" msgstr "Notas"
@ -54,10 +78,6 @@ msgctxt "field:product.cost.plan,product:"
msgid "Product" msgid "Product"
msgstr "Producto" msgstr "Producto"
msgctxt "field:product.cost.plan,product_cost:"
msgid "Product Cost"
msgstr "Coste del producto"
msgctxt "field:product.cost.plan,product_uom_category:" msgctxt "field:product.cost.plan,product_uom_category:"
msgid "Product UoM Category" msgid "Product UoM Category"
msgstr "Categoría UdM del producto" msgstr "Categoría UdM del producto"
@ -66,18 +86,30 @@ msgctxt "field:product.cost.plan,products:"
msgid "Products" msgid "Products"
msgstr "Productos" msgstr "Productos"
msgctxt "field:product.cost.plan,products_cost:"
msgid "Products Cost"
msgstr "Coste materiales"
msgctxt "field:product.cost.plan,products_tree:"
msgid "Products"
msgstr "Productos"
msgctxt "field:product.cost.plan,quantity:"
msgid "Quantity"
msgstr "Cantidad"
msgctxt "field:product.cost.plan,rec_name:" msgctxt "field:product.cost.plan,rec_name:"
msgid "Name" msgid "Name"
msgstr "Nombre" msgstr "Nombre"
msgctxt "field:product.cost.plan,state:"
msgid "State"
msgstr "Estado"
msgctxt "field:product.cost.plan,uom:" msgctxt "field:product.cost.plan,uom:"
msgid "UoM" msgid "UoM"
msgstr "UdM" msgstr "UdM"
msgctxt "field:product.cost.plan,uom_digits:"
msgid "UoM Digits"
msgstr "Dígitos UdM"
msgctxt "field:product.cost.plan,write_date:" msgctxt "field:product.cost.plan,write_date:"
msgid "Write Date" msgid "Write Date"
msgstr "Fecha modificación" msgstr "Fecha modificación"
@ -138,6 +170,10 @@ msgctxt "field:product.cost.plan.cost,id:"
msgid "ID" msgid "ID"
msgstr "Identificador" msgstr "Identificador"
msgctxt "field:product.cost.plan.cost,internal_cost:"
msgid "Cost (Internal Use)"
msgstr "Coste (uso interno)"
msgctxt "field:product.cost.plan.cost,plan:" msgctxt "field:product.cost.plan.cost,plan:"
msgid "Plan" msgid "Plan"
msgstr "Plan" msgstr "Plan"
@ -146,6 +182,10 @@ msgctxt "field:product.cost.plan.cost,rec_name:"
msgid "Name" msgid "Name"
msgstr "Nombre" msgstr "Nombre"
msgctxt "field:product.cost.plan.cost,sequence:"
msgid "Sequence"
msgstr "Secuencia"
msgctxt "field:product.cost.plan.cost,system:" msgctxt "field:product.cost.plan.cost,system:"
msgid "System Managed" msgid "System Managed"
msgstr "Gestinado por el sistema" msgstr "Gestinado por el sistema"
@ -178,10 +218,18 @@ msgctxt "field:product.cost.plan.cost.type,name:"
msgid "Name" msgid "Name"
msgstr "Nombre" msgstr "Nombre"
msgctxt "field:product.cost.plan.cost.type,plan_field_name:"
msgid "Plan Field Name"
msgstr "Nombre campo del plan"
msgctxt "field:product.cost.plan.cost.type,rec_name:" msgctxt "field:product.cost.plan.cost.type,rec_name:"
msgid "Name" msgid "Name"
msgstr "Nombre" msgstr "Nombre"
msgctxt "field:product.cost.plan.cost.type,system:"
msgid "System Managed"
msgstr "Gestinado por el sistema"
msgctxt "field:product.cost.plan.cost.type,write_date:" msgctxt "field:product.cost.plan.cost.type,write_date:"
msgid "Write Date" msgid "Write Date"
msgstr "Fecha modificación" msgstr "Fecha modificación"
@ -194,14 +242,14 @@ msgctxt "field:product.cost.plan.create_bom.start,id:"
msgid "ID" msgid "ID"
msgstr "Identificador" msgstr "Identificador"
msgctxt "field:product.cost.plan.create_bom.start,inputs:"
msgid "Inputs"
msgstr "Entradas"
msgctxt "field:product.cost.plan.create_bom.start,name:" msgctxt "field:product.cost.plan.create_bom.start,name:"
msgid "Name" msgid "Name"
msgstr "Nombre" msgstr "Nombre"
msgctxt "field:product.cost.plan.product_line,children:"
msgid "Children"
msgstr "Hijos"
msgctxt "field:product.cost.plan.product_line,cost_price:" msgctxt "field:product.cost.plan.product_line,cost_price:"
msgid "Cost Price" msgid "Cost Price"
msgstr "Precio de coste" msgstr "Precio de coste"
@ -218,14 +266,14 @@ msgctxt "field:product.cost.plan.product_line,id:"
msgid "ID" msgid "ID"
msgstr "Identificador" 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,name:" msgctxt "field:product.cost.plan.product_line,name:"
msgid "Name" msgid "Name"
msgstr "Nombre" msgstr "Nombre"
msgctxt "field:product.cost.plan.product_line,parent:"
msgid "Parent"
msgstr "Padre"
msgctxt "field:product.cost.plan.product_line,plan:" msgctxt "field:product.cost.plan.product_line,plan:"
msgid "Plan" msgid "Plan"
msgstr "Plan" msgstr "Plan"
@ -250,10 +298,14 @@ msgctxt "field:product.cost.plan.product_line,sequence:"
msgid "Sequence" msgid "Sequence"
msgstr "Secuencia" msgstr "Secuencia"
msgctxt "field:product.cost.plan.product_line,total:" msgctxt "field:product.cost.plan.product_line,total_cost:"
msgid "Total Cost" msgid "Total Cost"
msgstr "Coste total" msgstr "Coste total"
msgctxt "field:product.cost.plan.product_line,unit_cost:"
msgid "Unit Cost"
msgstr "Coste unitario"
msgctxt "field:product.cost.plan.product_line,uom:" msgctxt "field:product.cost.plan.product_line,uom:"
msgid "UoM" msgid "UoM"
msgstr "UdM" msgstr "UdM"
@ -278,6 +330,14 @@ msgctxt "field:production.configuration,product_cost_plan_sequence:"
msgid "Product Cost Plan Sequence" msgid "Product Cost Plan Sequence"
msgstr "Sequencia plan de coste del producto" msgstr "Sequencia plan de coste del producto"
msgctxt "help:product.cost.plan.product_line,total_cost:"
msgid "The cost of this product for total plan's quantity."
msgstr "El coste de este producto por la cantidad total del plan."
msgctxt "help:product.cost.plan.product_line,unit_cost:"
msgid "The cost of this product for each unit of plan's product."
msgstr "El coste de este producto por cada unidad del producto del plan."
msgctxt "model:ir.action,name:act_product_cost_plan" msgctxt "model:ir.action,name:act_product_cost_plan"
msgid "Product Cost Plan" msgid "Product Cost Plan"
msgstr "Plan de coste del producto" msgstr "Plan de coste del producto"
@ -354,14 +414,6 @@ msgctxt "model:res.group,name:group_product_cost_plan_admin"
msgid "Product Cost Plan Administration" msgid "Product Cost Plan Administration"
msgstr "Administración Plan de coste del producto" 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:" msgctxt "view:product.cost.plan.bom_line:"
msgid "Product Cost Plan BOM" msgid "Product Cost Plan BOM"
msgstr "LdM Plan de coste del producto" msgstr "LdM Plan de coste del producto"
@ -394,10 +446,6 @@ msgctxt "view:product.cost.plan:"
msgid "Costs" msgid "Costs"
msgstr "Costes" msgstr "Costes"
msgctxt "view:product.cost.plan:"
msgid "General"
msgstr "General"
msgctxt "view:product.cost.plan:" msgctxt "view:product.cost.plan:"
msgid "Notes" msgid "Notes"
msgstr "Notas" msgstr "Notas"
@ -407,8 +455,12 @@ msgid "Product Cost Plan"
msgstr "Plan de coste del producto" msgstr "Plan de coste del producto"
msgctxt "view:product.cost.plan:" msgctxt "view:product.cost.plan:"
msgid "Reset" msgid "Products"
msgstr "Reiniciar" msgstr "Productos"
msgctxt "view:product.cost.plan:"
msgid "Update Product's Prices"
msgstr "Actualizar precios producto"
msgctxt "wizard_button:product.cost.plan.create_bom,start,bom:" msgctxt "wizard_button:product.cost.plan.create_bom,start,bom:"
msgid "Ok" msgid "Ok"

359
plan.py
View File

@ -1,10 +1,14 @@
# The COPYRIGHT file at the top level of this repository contains the full
# copyright notices and license terms.
from decimal import Decimal from decimal import Decimal
from trytond.config import config
from trytond.model import ModelSQL, ModelView, fields from trytond.model import ModelSQL, ModelView, fields
from trytond.pool import Pool from trytond.pool import Pool
from trytond.pyson import Eval, Bool, If from trytond.pyson import Eval, Bool, If
from trytond.transaction import Transaction from trytond.transaction import Transaction
from trytond.wizard import Wizard, StateView, StateAction, Button from trytond.wizard import Wizard, StateView, StateAction, Button
from trytond.config import config
DIGITS = int(config.get('digits', 'unit_price_digits', 4)) DIGITS = int(config.get('digits', 'unit_price_digits', 4))
__all__ = ['PlanCostType', 'Plan', 'PlanBOM', 'PlanProductLine', 'PlanCost', __all__ = ['PlanCostType', 'Plan', 'PlanBOM', 'PlanProductLine', 'PlanCost',
@ -15,6 +19,8 @@ class PlanCostType(ModelSQL, ModelView):
'Plan Cost Type' 'Plan Cost Type'
__name__ = 'product.cost.plan.cost.type' __name__ = 'product.cost.plan.cost.type'
name = fields.Char('Name', required=True, translate=True) name = fields.Char('Name', required=True, translate=True)
system = fields.Boolean('System Managed', readonly=True)
plan_field_name = fields.Char('Plan Field Name', readonly=True)
class Plan(ModelSQL, ModelView): class Plan(ModelSQL, ModelView):
@ -25,21 +31,21 @@ class Plan(ModelSQL, ModelView):
name = fields.Char('Name', select=True) name = fields.Char('Name', select=True)
active = fields.Boolean('Active') active = fields.Boolean('Active')
product = fields.Many2One('product.product', 'Product') product = fields.Many2One('product.product', 'Product')
product_uom_category = fields.Function(
fields.Many2One('product.uom.category', 'Product UoM Category'),
'on_change_with_product_uom_category')
quantity = fields.Float('Quantity', digits=(16, Eval('uom_digits', 2)), quantity = fields.Float('Quantity', digits=(16, Eval('uom_digits', 2)),
required=True, depends=['uom_digits']) required=True, depends=['uom_digits'])
uom = fields.Many2One('product.uom', 'UoM', required=True, domain=[ uom = fields.Many2One('product.uom', 'UoM', required=True, domain=[
If(Bool(Eval('product_uom_category')), If(Bool(Eval('product')),
('category', '=', Eval('product_uom_category')), ('category', '=', Eval('product_uom_category')),
('id', '!=', -1), ('id', '!=', -1),
)], )],
states={ states={
'readonly': Bool(Eval('product')), 'readonly': Bool(Eval('product')),
}, depends=['product_uom_category', 'product']) }, depends=['product', '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')
product_uom_category = fields.Function(
fields.Many2One('product.uom.category', 'Product UoM Category'),
'on_change_with_product_uom_category')
bom = fields.Many2One('production.bom', 'BOM', bom = fields.Many2One('production.bom', 'BOM',
depends=['product'], domain=[ depends=['product'], domain=[
('output_products', '=', Eval('product', 0)), ('output_products', '=', Eval('product', 0)),
@ -57,13 +63,13 @@ class Plan(ModelSQL, ModelView):
}, },
depends=['costs']), depends=['costs']),
'get_products_tree', setter='set_products_tree') 'get_products_tree', setter='set_products_tree')
product_cost = fields.Function(fields.Numeric('Product Cost', products_cost = fields.Function(fields.Numeric('Products Cost',
digits=(16, DIGITS)), digits=(16, DIGITS)),
'on_change_with_product_cost') 'get_products_cost')
costs = fields.One2Many('product.cost.plan.cost', 'plan', 'Costs') costs = fields.One2Many('product.cost.plan.cost', 'plan', 'Costs')
cost_price = fields.Function(fields.Numeric('Unit Cost Price', cost_price = fields.Function(fields.Numeric('Unit Cost Price',
digits=(16, DIGITS)), digits=(16, DIGITS)),
'on_change_with_cost_price') 'get_cost_price')
notes = fields.Text('Notes') notes = fields.Text('Notes')
@classmethod @classmethod
@ -73,14 +79,19 @@ class Plan(ModelSQL, ModelView):
'compute': { 'compute': {
'icon': 'tryton-spreadsheet', 'icon': 'tryton-spreadsheet',
}, },
'update_product_prices': {
'icon': 'tryton-refresh',
},
}) })
cls._error_messages.update({ cls._error_messages.update({
'bom_already_exists': ('A bom already exists for cost plan ' 'product_lines_will_be_removed': (
'"%s".'), 'It will remove the existing Product Lines in this plan.'),
'bom_already_exists': (
'A bom already exists for cost plan "%s".'),
'cannot_mix_input_uoms': ('Product "%(product)s" in Cost Plan ' 'cannot_mix_input_uoms': ('Product "%(product)s" in Cost Plan '
'"%(plan)s" has different units of measure.'), '"%(plan)s" has different units of measure.'),
'product_already_has_bom': ('Product "%s" already has a BOM ' 'product_already_has_bom': (
'assigned.'), 'Product "%s" already has a BOM assigned.'),
}) })
@ -119,10 +130,12 @@ class Plan(ModelSQL, ModelView):
def on_change_with_uom_digits(self, name=None): def on_change_with_uom_digits(self, name=None):
return self.uom.digits if self.uom else 2 return self.uom.digits if self.uom else 2
@fields.depends('product') @fields.depends('product', 'uom')
def on_change_with_product_uom_category(self, name=None): def on_change_with_product_uom_category(self, name=None):
if self.product: if self.product:
return self.product.default_uom_category.id return self.product.default_uom_category.id
if self.uom:
return self.uom.category.id
@fields.depends('product') @fields.depends('product')
def on_change_with_bom(self): def on_change_with_bom(self):
@ -168,44 +181,15 @@ class Plan(ModelSQL, ModelView):
'products': value, 'products': value,
}) })
@fields.depends('quantity', 'products', 'products_tree') def get_products_cost(self, name):
def on_change_with_product_cost(self, name=None):
if not self.quantity: if not self.quantity:
return Decimal('0.0') return Decimal('0.0')
cost = sum(p.total for p in self.products_tree if p.total) cost = sum(p.get_total_cost(None, round=False) for p in self.products)
cost /= Decimal(str(self.quantity)) cost /= Decimal(str(self.quantity))
digits = self.__class__.product_cost.digits[1] digits = self.__class__.products_cost.digits[1]
return cost.quantize(Decimal(str(10 ** -digits))) return cost.quantize(Decimal(str(10 ** -digits)))
@fields.depends('product_cost', 'costs', methods=['product_cost']) def get_cost_price(self, name):
def on_change_with_costs(self):
self.product_cost = self.on_change_with_product_cost()
return self._on_change_with_costs_cost_type('product_cost_plan',
'raw_materials', self.product_cost)
def _on_change_with_costs_cost_type(self, module, cost_type_xml_id, value):
"""
Updates the cost line for type_ with value of field
"""
pool = Pool()
CostType = pool.get('product.cost.plan.cost.type')
ModelData = pool.get('ir.model.data')
type_ = CostType(ModelData.get_id(module, cost_type_xml_id))
to_update = []
for cost in self.costs:
if cost.type == type_ and cost.system:
to_update.append(cost.update_cost_values(value))
cost.cost = value
if to_update:
return {
'update': to_update,
}
return {}
@fields.depends('costs', methods=['costs'])
def on_change_with_cost_price(self, name=None):
self.on_change_with_costs()
return sum(c.cost for c in self.costs if c.cost) return sum(c.cost for c in self.costs if c.cost)
@classmethod @classmethod
@ -214,20 +198,19 @@ class Plan(ModelSQL, ModelView):
ProductLine = pool.get('product.cost.plan.product_line') ProductLine = pool.get('product.cost.plan.product_line')
CostLine = pool.get('product.cost.plan.cost') CostLine = pool.get('product.cost.plan.cost')
types = [x[0]for x in cls.get_cost_types()] product_lines = ProductLine.search([
to_delete = [] ('plan', 'in', [p.id for p in plans]),
costs_to_delete = [] ])
for plan in plans: if product_lines:
to_delete.extend(plan.products) cls.raise_user_warning('remove_product_lines',
for line in plan.costs: 'product_lines_will_be_removed')
if line.type in types: ProductLine.delete(product_lines)
costs_to_delete.append(line)
if to_delete: with Transaction().set_context(reset_costs=True):
ProductLine.delete(to_delete) CostLine.delete(CostLine.search([
if costs_to_delete: ('plan', 'in', [p.id for p in plans]),
with Transaction().set_context(reset_costs=True): ('system', '=', True),
CostLine.delete(costs_to_delete) ]))
@classmethod @classmethod
@ModelView.button @ModelView.button
@ -251,37 +234,6 @@ class Plan(ModelSQL, ModelView):
if to_create: if to_create:
CostLine.create(to_create) CostLine.create(to_create)
def get_costs(self):
"Returns the cost lines to be created on compute"
ret = []
for cost_type, field_name in self.get_cost_types():
ret.append(self.get_cost_line(cost_type, field_name))
return ret
def get_cost_line(self, cost_type, field_name):
cost = getattr(self, field_name, 0.0)
return {
'type': cost_type.id,
'cost': Decimal(str(cost)),
'plan': self.id,
'system': True,
}
@classmethod
def get_cost_types(cls):
"""
Returns a list of values with the cost types and the field to get
their cost.
"""
pool = Pool()
CostType = pool.get('product.cost.plan.cost.type')
ModelData = pool.get('ir.model.data')
ret = []
type_ = CostType(ModelData.get_id('product_cost_plan',
'raw_materials'))
ret.append((type_, 'product_cost'))
return ret
def explode_bom(self, product, bom, quantity, uom): def explode_bom(self, product, bom, quantity, uom):
"Returns products for the especified products" "Returns products for the especified products"
pool = Pool() pool = Pool()
@ -323,11 +275,15 @@ class Plan(ModelSQL, ModelView):
cost_factor = Decimal(UoM.compute_qty(input_.product.default_uom, 1, cost_factor = Decimal(UoM.compute_qty(input_.product.default_uom, 1,
input_.uom)) input_.uom))
digits = ProductLine.product_cost_price.digits[1] digits = ProductLine.product_cost_price.digits[1]
product_cost_price = (input_.product.cost_price / if cost_factor == Decimal('0.0'):
cost_factor).quantize(Decimal(str(10 ** -digits))) product_cost_price = Decimal('0.0')
digits = ProductLine.cost_price.digits[1] cost_price = Decimal('0.0')
cost_price = (input_.product.cost_price / else:
cost_factor).quantize(Decimal(str(10 ** -digits))) product_cost_price = (input_.product.cost_price /
cost_factor).quantize(Decimal(str(10 ** -digits)))
digits = ProductLine.cost_price.digits[1]
cost_price = (input_.product.cost_price /
cost_factor).quantize(Decimal(str(10 ** -digits)))
return { return {
'name': input_.product.rec_name, 'name': input_.product.rec_name,
@ -338,6 +294,52 @@ class Plan(ModelSQL, ModelView):
'cost_price': cost_price, 'cost_price': cost_price,
} }
def get_costs(self):
"Returns the cost lines to be created on compute"
pool = Pool()
CostType = pool.get('product.cost.plan.cost.type')
ret = []
system_cost_types = CostType.search([
('system', '=', True),
])
for cost_type in system_cost_types:
ret.append(self._get_cost_line(cost_type))
return ret
def _get_cost_line(self, cost_type):
return {
'plan': self.id,
'type': cost_type.id,
'system': True,
}
@classmethod
@ModelView.button
def update_product_prices(cls, plans):
for plan in plans:
if not plan.product:
continue
plan._update_product_prices()
plan.product.save()
plan.product.template.save()
def _update_product_prices(self):
pool = Pool()
Uom = pool.get('product.uom')
assert self.product
cost_price = Uom.compute_price(self.uom, self.cost_price,
self.product.default_uom)
if hasattr(self.product.__class__, 'cost_price'):
digits = self.product.__class__.cost_price.digits[1]
cost_price = cost_price.quantize(Decimal(str(10 ** -digits)))
self.product.cost_price = cost_price
else:
digits = self.product.template.__class__.cost_price.digits[1]
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()
BOM = pool.get('production.bom') BOM = pool.get('production.bom')
@ -371,7 +373,7 @@ class Plan(ModelSQL, ModelView):
if self.product: if self.product:
output = BOMOutput() output = BOMOutput()
output.product = self.product output.product = self.product
output.uom = self.product.default_uom output.uom = self.uom
output.quantity = self.quantity output.quantity = self.quantity
outputs.append(output) outputs.append(output)
return outputs return outputs
@ -477,21 +479,22 @@ class PlanProductLine(ModelSQL, ModelView):
'Children') 'Children')
plan = fields.Many2One('product.cost.plan', 'Plan', required=True, plan = fields.Many2One('product.cost.plan', 'Plan', required=True,
ondelete='CASCADE') ondelete='CASCADE')
product = fields.Many2One('product.product', 'Product', product = fields.Many2One('product.product', 'Product', domain=[
domain=[
('type', '!=', 'service'), ('type', '!=', 'service'),
]) If(Bool(Eval('children')),
('default_uom.category', '=', Eval('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, uom = fields.Many2One('product.uom', 'UoM', required=True, domain=[
domain=[ If(Bool(Eval('children')) | Bool(Eval('product')),
If(Bool(Eval('product', 0)),
('category', '=', Eval('uom_category')), ('category', '=', Eval('uom_category')),
('id', '!=', 0)), ()),
], depends=['uom_category', 'product']) ], 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')
product_cost_price = fields.Numeric('Product Cost Price', product_cost_price = fields.Numeric('Product Cost Price',
@ -501,12 +504,14 @@ class PlanProductLine(ModelSQL, ModelView):
}, depends=['product']) }, depends=['product'])
cost_price = fields.Numeric('Cost Price', required=True, cost_price = fields.Numeric('Cost Price', required=True,
digits=(16, DIGITS)) digits=(16, DIGITS))
total = fields.Function(fields.Numeric('Total Cost', unit_cost = fields.Function(fields.Numeric('Unit Cost',
digits=(16, DIGITS)), digits=(16, DIGITS),
'on_change_with_total') help="The cost of this product for each unit of plan's product."),
total_unit = fields.Function(fields.Numeric('Total Unit Cost', 'get_unit_cost')
digits=(16, DIGITS)), total_cost = fields.Function(fields.Numeric('Total Cost',
'on_change_with_total_unit') digits=(16, DIGITS),
help="The cost of this product for total plan's quantity."),
'get_total_cost')
@classmethod @classmethod
def __setup__(cls): def __setup__(cls):
@ -536,49 +541,75 @@ class PlanProductLine(ModelSQL, ModelView):
res['product_cost_price'] = None res['product_cost_price'] = None
return res return res
@fields.depends('product') @fields.depends('children', '_parent_plan.uom' 'product', 'uom')
def on_change_with_uom_category(self, name=None): def on_change_with_uom_category(self, name=None):
if self.children:
# If product line has children, it must be have computable
# quantities of plan product
return self.plan.uom.category.id
if self.product: if self.product:
return self.product.default_uom.category.id return self.product.default_uom.category.id
@fields.depends('product', 'uom')
def on_change_with_product_cost_price(self):
UoM = Pool().get('product.uom')
if not self.product or not self.uom:
return
cost = Decimal(UoM.compute_qty(self.product.default_uom,
float(self.product.cost_price), self.uom, round=False))
digits = self.__class__.product_cost_price.digits[1]
return cost.quantize(Decimal(str(10 ** -digits)))
@fields.depends('quantity', 'cost_price', 'uom', 'product', 'children')
def on_change_with_total(self, name=None):
quantity = self.quantity
if not quantity:
return Decimal('0.0')
total = Decimal(str(quantity)) * (self.cost_price or Decimal('0.0'))
for child in self.children:
total += Decimal(str(quantity)) * (child.on_change_with_total()
or Decimal('0.0'))
digits = self.__class__.total.digits[1]
return total.quantize(Decimal(str(10 ** -digits)))
@fields.depends('_parent_plan.quantity', methods=['total'])
def on_change_with_total_unit(self, name=None):
total = self.on_change_with_total(None)
if total and self.plan and self.plan.quantity:
total /= Decimal(str(self.plan.quantity))
else:
total = Decimal('0.0')
digits = self.__class__.total_unit.digits[1]
return total.quantize(Decimal(str(10 ** -digits)))
@fields.depends('uom') @fields.depends('uom')
def on_change_with_uom_digits(self, name=None): def on_change_with_uom_digits(self, name=None):
if self.uom: if self.uom:
return self.uom.digits return self.uom.digits
return 2 return 2
@fields.depends('product', 'uom', 'cost_price')
def on_change_with_cost_price(self):
UoM = Pool().get('product.uom')
if (not self.product or not self.uom
or (self.cost_price
and self.cost_price != self.product.cost_price)):
cost = self.cost_price
else:
cost = UoM.compute_price(self.product.default_uom,
self.product.cost_price, self.uom)
if cost:
digits = self.__class__.cost_price.digits[1]
return cost.quantize(Decimal(str(10 ** -digits)))
return cost
@fields.depends('product', 'uom')
def on_change_with_product_cost_price(self):
UoM = Pool().get('product.uom')
if not self.product:
return
if not self.uom:
cost = self.product.cost_price
else:
cost = UoM.compute_price(self.product.default_uom,
self.product.cost_price, self.uom)
digits = self.__class__.product_cost_price.digits[1]
return cost.quantize(Decimal(str(10 ** -digits)))
def get_unit_cost(self, name):
unit_cost = self.total_cost
if unit_cost and self.plan and self.plan.quantity:
unit_cost /= Decimal(str(self.plan.quantity))
digits = self.__class__.unit_cost.digits[1]
return unit_cost.quantize(Decimal(str(10 ** -digits)))
def get_total_cost(self, name, round=True):
if not self.cost_price:
return Decimal('0.0')
# Quantity is the quantity of this line for all plan's quantity
quantity = self.quantity
line = self
while quantity and line.parent:
quantity *= line.parent.quantity
line = line.parent
if not quantity:
return Decimal('0.0')
total_cost = Decimal(str(quantity)) * self.cost_price
if not round:
return total_cost
digits = self.__class__.total_cost.digits[1]
return total_cost.quantize(Decimal(str(10 ** -digits)))
@classmethod @classmethod
def copy(cls, lines, default=None): def copy(cls, lines, default=None):
if default is None: if default is None:
@ -612,10 +643,15 @@ class PlanCost(ModelSQL, ModelView):
plan = fields.Many2One('product.cost.plan', 'Plan', required=True, plan = fields.Many2One('product.cost.plan', 'Plan', required=True,
ondelete='CASCADE') ondelete='CASCADE')
sequence = fields.Integer('Sequence') sequence = fields.Integer('Sequence')
type = fields.Many2One('product.cost.plan.cost.type', 'Type', type = fields.Many2One('product.cost.plan.cost.type', 'Type', domain=[
('system', '=', Eval('system')),
],
required=True, states=STATES, depends=DEPENDS) required=True, states=STATES, depends=DEPENDS)
cost = fields.Numeric('Cost', required=True, states=STATES, internal_cost = fields.Numeric('Cost (Internal Use)', digits=(16, DIGITS),
depends=DEPENDS, digits=(16, DIGITS)) readonly=True)
cost = fields.Function(fields.Numeric('Cost', digits=(16, DIGITS),
required=True, states=STATES, depends=DEPENDS),
'get_cost', setter='set_cost')
system = fields.Boolean('System Managed', readonly=True) system = fields.Boolean('System Managed', readonly=True)
@classmethod @classmethod
@ -627,10 +663,6 @@ class PlanCost(ModelSQL, ModelView):
'from plan "%(plan)s" because it\'s managed by system.'), 'from plan "%(plan)s" because it\'s managed by system.'),
}) })
@staticmethod
def default_system():
return False
@staticmethod @staticmethod
def order_sequence(tables): def order_sequence(tables):
table, _ = tables[None] table, _ = tables[None]
@ -643,6 +675,25 @@ class PlanCost(ModelSQL, ModelView):
def search_rec_name(cls, name, clause): def search_rec_name(cls, name, clause):
return [('type.name',) + tuple(clause[1:])] return [('type.name',) + tuple(clause[1:])]
@staticmethod
def default_system():
return False
def get_cost(self, name):
if self.system:
cost = getattr(self.plan, self.type.plan_field_name)
else:
cost = self.internal_cost
digits = self.__class__.cost.digits[1]
return cost.quantize(Decimal(str(10 ** -digits)))
@classmethod
def set_cost(cls, records, name, value):
records_todo = [r for r in records if not r.system]
cls.write(records, {
'internal_cost': value,
})
@classmethod @classmethod
def delete(cls, costs): def delete(cls, costs):
if not Transaction().context.get('reset_costs', False): if not Transaction().context.get('reset_costs', False):
@ -654,12 +705,6 @@ class PlanCost(ModelSQL, ModelView):
}) })
super(PlanCost, cls).delete(costs) super(PlanCost, cls).delete(costs)
def update_cost_values(self, value):
return {
'cost': value,
'id': self.id,
}
class CreateBomStart(ModelView): class CreateBomStart(ModelView):
'Create BOM Start' 'Create BOM Start'

386
plan.xml
View File

@ -1,18 +1,20 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<tryton> <tryton>
<data> <data>
<record model="res.group" id="group_product_cost_plan_admin"> <record model="res.group" id="group_product_cost_plan_admin">
<field name="name">Product Cost Plan Administration</field> <field name="name">Product Cost Plan Administration</field>
</record> </record>
<record model="res.user-res.group" id="user_admin_group_product_cost_plan_admin"> <record model="res.user-res.group"
id="user_admin_group_product_cost_plan_admin">
<field name="user" ref="res.user_admin"/> <field name="user" ref="res.user_admin"/>
<field name="group" ref="group_product_cost_plan_admin"/> <field name="group" ref="group_product_cost_plan_admin"/>
</record> </record>
<record model="res.user-res.group" id="user_trigger_group_product_cost_plan_admin"> <record model="res.user-res.group"
id="user_trigger_group_product_cost_plan_admin">
<field name="user" ref="res.user_trigger"/> <field name="user" ref="res.user_trigger"/>
<field name="group" ref="group_product_cost_plan_admin"/> <field name="group" ref="group_product_cost_plan_admin"/>
</record> </record>
<record model="res.group" id="group_product_cost_plan"> <record model="res.group" id="group_product_cost_plan">
<field name="name">Product Cost Plan</field> <field name="name">Product Cost Plan</field>
</record> </record>
@ -45,16 +47,19 @@
<field name="code">product_cost_plan</field> <field name="code">product_cost_plan</field>
</record> </record>
<!-- product.cost.plan -->
<record model="ir.ui.view" id="product_cost_plan_view_form"> <record model="ir.ui.view" id="product_cost_plan_view_form">
<field name="model">product.cost.plan</field> <field name="model">product.cost.plan</field>
<field name="type">form</field> <field name="type">form</field>
<field name="name">cost_plan_form</field> <field name="name">cost_plan_form</field>
</record> </record>
<record model="ir.ui.view" id="product_cost_plan_view_list"> <record model="ir.ui.view" id="product_cost_plan_view_list">
<field name="model">product.cost.plan</field> <field name="model">product.cost.plan</field>
<field name="type">tree</field> <field name="type">tree</field>
<field name="name">cost_plan_list</field> <field name="name">cost_plan_list</field>
</record> </record>
<record model="ir.action.act_window" id="act_product_cost_plan"> <record model="ir.action.act_window" id="act_product_cost_plan">
<field name="name">Product Cost Plan</field> <field name="name">Product Cost Plan</field>
<field name="res_model">product.cost.plan</field> <field name="res_model">product.cost.plan</field>
@ -69,6 +74,7 @@
<field name="view" ref="product_cost_plan_view_form"/> <field name="view" ref="product_cost_plan_view_form"/>
<field name="act_window" ref="act_product_cost_plan"/> <field name="act_window" ref="act_product_cost_plan"/>
</record> </record>
<record model="ir.model.access" id="access_product_cost_plan"> <record model="ir.model.access" id="access_product_cost_plan">
<field name="model" search="[('model', '=', 'product.cost.plan')]"/> <field name="model" search="[('model', '=', 'product.cost.plan')]"/>
<field name="perm_read" eval="True"/> <field name="perm_read" eval="True"/>
@ -76,6 +82,7 @@
<field name="perm_create" eval="False"/> <field name="perm_create" eval="False"/>
<field name="perm_delete" eval="False"/> <field name="perm_delete" eval="False"/>
</record> </record>
<record model="ir.model.access" id="access_product_cost_plan_admin"> <record model="ir.model.access" id="access_product_cost_plan_admin">
<field name="model" search="[('model', '=', 'product.cost.plan')]"/> <field name="model" search="[('model', '=', 'product.cost.plan')]"/>
<field name="group" ref="group_product_cost_plan_admin"/> <field name="group" ref="group_product_cost_plan_admin"/>
@ -84,163 +91,6 @@
<field name="perm_create" eval="True"/> <field name="perm_create" eval="True"/>
<field name="perm_delete" eval="True"/> <field name="perm_delete" eval="True"/>
</record> </record>
<record model="ir.ui.view" id="product_cost_plan_bom_line_view_form">
<field name="model">product.cost.plan.bom_line</field>
<field name="type">form</field>
<field name="name">cost_plan_bom_line_form</field>
</record>
<record model="ir.ui.view" id="product_cost_plan_bom_line_view_list">
<field name="model">product.cost.plan.bom_line</field>
<field name="type">tree</field>
<field name="name">cost_plan_bom_line_list</field>
</record>
<record model="ir.action.act_window" id="act_product_cost_plan_bom_line">
<field name="name">Product Cost Plan BOM</field>
<field name="res_model">product.cost.plan.bom_line</field>
</record>
<record model="ir.action.act_window.view" id="act_product_cost_plan_bom_line_view1">
<field name="sequence" eval="10"/>
<field name="view" ref="product_cost_plan_bom_line_view_list"/>
<field name="act_window" ref="act_product_cost_plan_bom_line"/>
</record>
<record model="ir.action.act_window.view" id="act_product_cost_plan_bom_line_view2">
<field name="sequence" eval="20"/>
<field name="view" ref="product_cost_plan_bom_line_view_form"/>
<field name="act_window" ref="act_product_cost_plan_bom_line"/>
</record>
<record model="ir.model.access" id="access_product_cost_plan_bom_line">
<field name="model" search="[('model', '=', 'product.cost.plan.bom_line')]"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="False"/>
<field name="perm_create" eval="False"/>
<field name="perm_delete" eval="False"/>
</record>
<record model="ir.model.access" id="access_product_cost_plan_bom_line_admin">
<field name="model" search="[('model', '=', 'product.cost.plan.bom_line')]"/>
<field name="group" ref="group_product_cost_plan_admin"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
<field name="perm_delete" eval="True"/>
</record>
<record model="ir.ui.view" id="product_cost_plan_product_line_view_form">
<field name="model">product.cost.plan.product_line</field>
<field name="type">form</field>
<field name="name">cost_plan_product_line_form</field>
</record>
<record model="ir.ui.view" id="product_cost_plan_product_line_view_list">
<field name="model">product.cost.plan.product_line</field>
<field name="type">tree</field>
<field name="name">cost_plan_product_line_list</field>
<field name="field_childs">children</field>
</record>
<record model="ir.action.act_window" id="act_product_cost_plan_product_line">
<field name="name">Product Cost Plan Product Line</field>
<field name="res_model">product.cost.plan.product_line</field>
</record>
<record model="ir.action.act_window.view" id="act_product_cost_plan_product_line_view1">
<field name="sequence" eval="10"/>
<field name="view" ref="product_cost_plan_product_line_view_list"/>
<field name="act_window" ref="act_product_cost_plan_product_line"/>
</record>
<record model="ir.action.act_window.view" id="act_product_cost_plan_product_line_view2">
<field name="sequence" eval="20"/>
<field name="view" ref="product_cost_plan_product_line_view_form"/>
<field name="act_window" ref="act_product_cost_plan_product_line"/>
</record>
<record model="ir.model.access" id="access_product_cost_plan_product_line">
<field name="model" search="[('model', '=', 'product.cost.plan.product_line')]"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="False"/>
<field name="perm_create" eval="False"/>
<field name="perm_delete" eval="False"/>
</record>
<record model="ir.model.access" id="access_product_cost_plan_product_line_admin">
<field name="model" search="[('model', '=', 'product.cost.plan.product_line')]"/>
<field name="group" ref="group_product_cost_plan_admin"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
<field name="perm_delete" eval="True"/>
</record>
<record model="ir.ui.view" id="product_cost_plan_cost_view_form">
<field name="model">product.cost.plan.cost</field>
<field name="type">form</field>
<field name="name">plan_cost_form</field>
</record>
<record model="ir.ui.view" id="product_cost_plan_cost_view_list">
<field name="model">product.cost.plan.cost</field>
<field name="type">tree</field>
<field name="name">plan_cost_list</field>
</record>
<record model="ir.action.act_window" id="act_product_cost_plan_cost">
<field name="name">Plan Costs</field>
<field name="res_model">product.cost.plan.cost</field>
</record>
<record model="ir.action.act_window.view" id="act_product_cost_plan_cost_view1">
<field name="sequence" eval="10"/>
<field name="view" ref="product_cost_plan_cost_view_list"/>
<field name="act_window" ref="act_product_cost_plan_cost"/>
</record>
<record model="ir.action.act_window.view" id="act_product_cost_plan_cost_view2">
<field name="sequence" eval="20"/>
<field name="view" ref="product_cost_plan_cost_view_form"/>
<field name="act_window" ref="act_product_cost_plan_cost"/>
</record>
<record model="ir.model.access" id="access_product_cost_plan_cost">
<field name="model" search="[('model', '=', 'product.cost.plan.cost')]"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="False"/>
<field name="perm_create" eval="False"/>
<field name="perm_delete" eval="False"/>
</record>
<record model="ir.model.access" id="access_product_cost_plan_cost_admin">
<field name="model" search="[('model', '=', 'product.cost.plan.cost')]"/>
<field name="group" ref="group_product_cost_plan_admin"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
<field name="perm_delete" eval="True"/>
</record>
<record model="ir.ui.view" id="product_cost_plan_cost_type_view_form">
<field name="model">product.cost.plan.cost.type</field>
<field name="type">form</field>
<field name="name">plan_cost_type_form</field>
</record>
<record model="ir.ui.view" id="product_cost_plan_cost_type_view_list">
<field name="model">product.cost.plan.cost.type</field>
<field name="type">tree</field>
<field name="name">plan_cost_type_list</field>
</record>
<record model="ir.action.act_window" id="act_product_cost_plan_cost_type">
<field name="name">Plan Cost Type</field>
<field name="res_model">product.cost.plan.cost.type</field>
</record>
<record model="ir.action.act_window.view" id="act_product_cost_plan_cost_type_view1">
<field name="sequence" eval="10"/>
<field name="view" ref="product_cost_plan_cost_type_view_list"/>
<field name="act_window" ref="act_product_cost_plan_cost_type"/>
</record>
<record model="ir.action.act_window.view" id="act_product_cost_plan_cost_type_view2">
<field name="sequence" eval="20"/>
<field name="view" ref="product_cost_plan_cost_type_view_form"/>
<field name="act_window" ref="act_product_cost_plan_cost_type"/>
</record>
<record model="ir.model.access" id="access_product_cost_plan_cost_type">
<field name="model" search="[('model', '=', 'product.cost.plan.cost.type')]"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="False"/>
<field name="perm_create" eval="False"/>
<field name="perm_delete" eval="False"/>
</record>
<record model="ir.model.access" id="access_product_cost_plan_cost_type_admin">
<field name="model" search="[('model', '=', 'product.cost.plan.cost.type')]"/>
<field name="group" ref="group_product_cost_plan_admin"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
<field name="perm_delete" eval="True"/>
</record>
<record model="ir.model.button" id="plan_compute_button"> <record model="ir.model.button" id="plan_compute_button">
<field name="name">compute</field> <field name="name">compute</field>
@ -251,6 +101,212 @@
<field name="group" ref="group_product_cost_plan"/> <field name="group" ref="group_product_cost_plan"/>
</record> </record>
<record model="ir.model.button" id="plan_update_product_prices_button">
<field name="name">update_product_prices</field>
<field name="model" search="[('model', '=', 'product.cost.plan')]"/>
</record>
<record model="ir.model.button-res.group"
id="plan_update_product_prices_button_group_product_admin">
<field name="button" ref="plan_compute_button"/>
<field name="group" ref="product.group_product_admin"/>
</record>
<!-- product.cost.plan.bom_line -->
<record model="ir.ui.view" id="product_cost_plan_bom_line_view_form">
<field name="model">product.cost.plan.bom_line</field>
<field name="type">form</field>
<field name="name">cost_plan_bom_line_form</field>
</record>
<record model="ir.ui.view" id="product_cost_plan_bom_line_view_list">
<field name="model">product.cost.plan.bom_line</field>
<field name="type">tree</field>
<field name="name">cost_plan_bom_line_list</field>
</record>
<record model="ir.action.act_window" id="act_product_cost_plan_bom_line">
<field name="name">Product Cost Plan BOM</field>
<field name="res_model">product.cost.plan.bom_line</field>
</record>
<record model="ir.action.act_window.view"
id="act_product_cost_plan_bom_line_view1">
<field name="sequence" eval="10"/>
<field name="view" ref="product_cost_plan_bom_line_view_list"/>
<field name="act_window" ref="act_product_cost_plan_bom_line"/>
</record>
<record model="ir.action.act_window.view"
id="act_product_cost_plan_bom_line_view2">
<field name="sequence" eval="20"/>
<field name="view" ref="product_cost_plan_bom_line_view_form"/>
<field name="act_window" ref="act_product_cost_plan_bom_line"/>
</record>
<record model="ir.model.access" id="access_product_cost_plan_bom_line">
<field name="model" search="[('model', '=', 'product.cost.plan.bom_line')]"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="False"/>
<field name="perm_create" eval="False"/>
<field name="perm_delete" eval="False"/>
</record>
<record model="ir.model.access" id="access_product_cost_plan_bom_line_admin">
<field name="model" search="[('model', '=', 'product.cost.plan.bom_line')]"/>
<field name="group" ref="group_product_cost_plan_admin"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
<field name="perm_delete" eval="True"/>
</record>
<!-- product.cost.plan.product_line -->
<record model="ir.ui.view" id="product_cost_plan_product_line_view_form">
<field name="model">product.cost.plan.product_line</field>
<field name="type">form</field>
<field name="name">cost_plan_product_line_form</field>
</record>
<record model="ir.ui.view" id="product_cost_plan_product_line_view_list">
<field name="model">product.cost.plan.product_line</field>
<field name="type">tree</field>
<field name="name">cost_plan_product_line_list</field>
<field name="field_childs">children</field>
</record>
<record model="ir.action.act_window" id="act_product_cost_plan_product_line">
<field name="name">Product Cost Plan Product Line</field>
<field name="res_model">product.cost.plan.product_line</field>
</record>
<record model="ir.action.act_window.view"
id="act_product_cost_plan_product_line_view1">
<field name="sequence" eval="10"/>
<field name="view" ref="product_cost_plan_product_line_view_list"/>
<field name="act_window" ref="act_product_cost_plan_product_line"/>
</record>
<record model="ir.action.act_window.view"
id="act_product_cost_plan_product_line_view2">
<field name="sequence" eval="20"/>
<field name="view" ref="product_cost_plan_product_line_view_form"/>
<field name="act_window" ref="act_product_cost_plan_product_line"/>
</record>
<record model="ir.model.access"
id="access_product_cost_plan_product_line">
<field name="model"
search="[('model', '=', 'product.cost.plan.product_line')]"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="False"/>
<field name="perm_create" eval="False"/>
<field name="perm_delete" eval="False"/>
</record>
<record model="ir.model.access"
id="access_product_cost_plan_product_line_admin">
<field name="model"
search="[('model', '=', 'product.cost.plan.product_line')]"/>
<field name="group" ref="group_product_cost_plan_admin"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
<field name="perm_delete" eval="True"/>
</record>
<!-- product.cost.plan.cost -->
<record model="ir.ui.view" id="product_cost_plan_cost_view_form">
<field name="model">product.cost.plan.cost</field>
<field name="type">form</field>
<field name="name">plan_cost_form</field>
</record>
<record model="ir.ui.view" id="product_cost_plan_cost_view_list">
<field name="model">product.cost.plan.cost</field>
<field name="type">tree</field>
<field name="name">plan_cost_list</field>
</record>
<record model="ir.action.act_window" id="act_product_cost_plan_cost">
<field name="name">Plan Costs</field>
<field name="res_model">product.cost.plan.cost</field>
</record>
<record model="ir.action.act_window.view" id="act_product_cost_plan_cost_view1">
<field name="sequence" eval="10"/>
<field name="view" ref="product_cost_plan_cost_view_list"/>
<field name="act_window" ref="act_product_cost_plan_cost"/>
</record>
<record model="ir.action.act_window.view" id="act_product_cost_plan_cost_view2">
<field name="sequence" eval="20"/>
<field name="view" ref="product_cost_plan_cost_view_form"/>
<field name="act_window" ref="act_product_cost_plan_cost"/>
</record>
<record model="ir.model.access" id="access_product_cost_plan_cost">
<field name="model" search="[('model', '=', 'product.cost.plan.cost')]"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="False"/>
<field name="perm_create" eval="False"/>
<field name="perm_delete" eval="False"/>
</record>
<record model="ir.model.access" id="access_product_cost_plan_cost_admin">
<field name="model" search="[('model', '=', 'product.cost.plan.cost')]"/>
<field name="group" ref="group_product_cost_plan_admin"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
<field name="perm_delete" eval="True"/>
</record>
<!-- product.cost.plan.cost.type -->
<record model="ir.ui.view" id="product_cost_plan_cost_type_view_form">
<field name="model">product.cost.plan.cost.type</field>
<field name="type">form</field>
<field name="name">plan_cost_type_form</field>
</record>
<record model="ir.ui.view" id="product_cost_plan_cost_type_view_list">
<field name="model">product.cost.plan.cost.type</field>
<field name="type">tree</field>
<field name="name">plan_cost_type_list</field>
</record>
<record model="ir.action.act_window" id="act_product_cost_plan_cost_type">
<field name="name">Plan Cost Type</field>
<field name="res_model">product.cost.plan.cost.type</field>
</record>
<record model="ir.action.act_window.view"
id="act_product_cost_plan_cost_type_view1">
<field name="sequence" eval="10"/>
<field name="view" ref="product_cost_plan_cost_type_view_list"/>
<field name="act_window" ref="act_product_cost_plan_cost_type"/>
</record>
<record model="ir.action.act_window.view"
id="act_product_cost_plan_cost_type_view2">
<field name="sequence" eval="20"/>
<field name="view" ref="product_cost_plan_cost_type_view_form"/>
<field name="act_window" ref="act_product_cost_plan_cost_type"/>
</record>
<record model="ir.model.access" id="access_product_cost_plan_cost_type">
<field name="model"
search="[('model', '=', 'product.cost.plan.cost.type')]"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="False"/>
<field name="perm_create" eval="False"/>
<field name="perm_delete" eval="False"/>
</record>
<record model="ir.model.access"
id="access_product_cost_plan_cost_type_admin">
<field name="model"
search="[('model', '=', 'product.cost.plan.cost.type')]"/>
<field name="group" ref="group_product_cost_plan_admin"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
<field name="perm_delete" eval="True"/>
</record>
<!-- product.cost.plan.create_bom -->
<record model="ir.ui.view" id="create_bom_start_view_form"> <record model="ir.ui.view" id="create_bom_start_view_form">
<field name="model">product.cost.plan.create_bom.start</field> <field name="model">product.cost.plan.create_bom.start</field>
<field name="type">form</field> <field name="type">form</field>
@ -276,13 +332,13 @@
<menuitem action="act_product_cost_plan" id="menu_product_cost_plan" <menuitem action="act_product_cost_plan" id="menu_product_cost_plan"
parent="product.menu_main_product" sequence="50" parent="product.menu_main_product" sequence="50"
name="Product Cost Plan"/> name="Product Cost Plan"/>
<record model="ir.ui.menu-res.group"
<record model="ir.ui.menu-res.group" id="menu_product_cost_plan_group_product_cost_plan"> id="menu_product_cost_plan_group_product_cost_plan">
<field name="menu" ref="menu_product_cost_plan"/> <field name="menu" ref="menu_product_cost_plan"/>
<field name="group" ref="group_product_cost_plan"/> <field name="group" ref="group_product_cost_plan"/>
</record> </record>
<record model="ir.ui.menu-res.group"
<record model="ir.ui.menu-res.group" id="menu_product_cost_plan_group_product_cost_plan_admin"> id="menu_product_cost_plan_group_product_cost_plan_admin">
<field name="menu" ref="menu_product_cost_plan"/> <field name="menu" ref="menu_product_cost_plan"/>
<field name="group" ref="group_product_cost_plan"/> <field name="group" ref="group_product_cost_plan"/>
</record> </record>
@ -296,6 +352,8 @@
<record model="product.cost.plan.cost.type" id="raw_materials"> <record model="product.cost.plan.cost.type" id="raw_materials">
<field name="name">Raw materials</field> <field name="name">Raw materials</field>
<field name="system" eval="True"/>
<field name="plan_field_name">products_cost</field>
</record> </record>
</data> </data>
</tryton> </tryton>

View File

@ -1,5 +1,5 @@
[tryton] [tryton]
version=3.4.0 version=3.4.1
depends: depends:
production production
xml: xml:

View File

@ -21,8 +21,8 @@
<notebook colspan="6"> <notebook colspan="6">
<page string="Products" id="products"> <page string="Products" id="products">
<field name="products_tree" colspan="4"/> <field name="products_tree" colspan="4"/>
<label name="product_cost"/> <label name="products_cost"/>
<field name="product_cost"/> <field name="products_cost"/>
</page> </page>
<page id="costs" string="Costs"> <page id="costs" string="Costs">
<field name="costs" colspan="4"/> <field name="costs" colspan="4"/>
@ -36,4 +36,6 @@
</notebook> </notebook>
<label name="cost_price"/> <label name="cost_price"/>
<field name="cost_price"/> <field name="cost_price"/>
<button name="update_product_prices" string="Update Product's Prices"
colspan="2"/>
</form> </form>

View File

@ -20,6 +20,8 @@
<field name="product_cost_price"/> <field name="product_cost_price"/>
<label name="cost_price"/> <label name="cost_price"/>
<field name="cost_price"/> <field name="cost_price"/>
<label name="total"/> <label name="unit_cost"/>
<field name="total"/> <field name="unit_cost"/>
<label name="total_cost"/>
<field name="total_cost"/>
</form> </form>

View File

@ -9,8 +9,8 @@
<field name="uom"/> <field name="uom"/>
<field name="cost_price"/> <field name="cost_price"/>
<field name="product_cost_price"/> <field name="product_cost_price"/>
<field name="total"/> <field name="unit_cost"/>
<field name="total_unit"/> <field name="total_cost"/>
<field name="parent" tree_invisible="1"/> <field name="parent" tree_invisible="1"/>
<field name="children" tree_invisible="1"/> <field name="children" tree_invisible="1"/>
</tree> </tree>

View File

@ -4,4 +4,6 @@
<form string="Plan Cost Type"> <form string="Plan Cost Type">
<label name="name"/> <label name="name"/>
<field name="name"/> <field name="name"/>
<label name="system"/>
<field name="system"/>
</form> </form>

View File

@ -3,4 +3,5 @@
copyright notices and license terms. --> copyright notices and license terms. -->
<tree string="Plan Cost Type"> <tree string="Plan Cost Type">
<field name="name"/> <field name="name"/>
<field name="system"/>
</tree> </tree>