implement funcionality

This commit is contained in:
?ngel ?lvarez Serra 2014-01-03 13:10:49 +01:00
parent f9f0fb399d
commit 11a07886b4
20 changed files with 1459 additions and 377 deletions

View File

@ -4,13 +4,10 @@
from trytond.pool import Pool
from .operation import *
def register():
Pool.register(
WorkCenterCategory,
WorkCenter,
Route,
RouteOperation,
Operation,
OperationLine,
OperationTracking,
Production,
module='production_operation', type_='model')

438
locale/ca_ES.po Normal file
View File

@ -0,0 +1,438 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "error:production.operation:"
msgid "You can not create an operation for Production \"%s\"."
msgstr "No podeu crear una operació per la producció \"%s\"."
msgctxt "error:production:"
msgid ""
"Production \"%(production)s\" can not be done because their operation "
"\"%(operation)s\" is not done."
msgstr ""
"No es pot realitzar la producció \"%(production)s\" perquè la seva operació "
"\"%(operation)s\" no està realitzada."
msgctxt "field:production,operations:"
msgid "Operations"
msgstr "Operacions"
msgctxt "field:production,route:"
msgid "Route"
msgstr "Ruta"
msgctxt "field:production.operation,cost:"
msgid "Cost"
msgstr "Cost"
msgctxt "field:production.operation,create_date:"
msgid "Create Date"
msgstr "Data de creació"
msgctxt "field:production.operation,create_uid:"
msgid "Create User"
msgstr "Usuari de creació"
msgctxt "field:production.operation,id:"
msgid "ID"
msgstr "Identificador"
msgctxt "field:production.operation,lines:"
msgid "Lines"
msgstr "Línies"
msgctxt "field:production.operation,name:"
msgid "Name"
msgstr "Nom"
msgctxt "field:production.operation,operation_type:"
msgid "Operation Type"
msgstr "Tipus d'operació"
msgctxt "field:production.operation,production:"
msgid "Production"
msgstr "Producció"
msgctxt "field:production.operation,rec_name:"
msgid "Name"
msgstr "Nom"
msgctxt "field:production.operation,route_operation:"
msgid "Route Operation"
msgstr "Ruta"
msgctxt "field:production.operation,sequence:"
msgid "Sequence"
msgstr "Seqüència"
msgctxt "field:production.operation,state:"
msgid "State"
msgstr "Estat"
msgctxt "field:production.operation,work_center:"
msgid "Work Center"
msgstr "Centre de treball"
msgctxt "field:production.operation,write_date:"
msgid "Write Date"
msgstr "Data modificació"
msgctxt "field:production.operation,write_uid:"
msgid "Write User"
msgstr "Usuari modificació"
msgctxt "field:production.operation.tracking,cost:"
msgid "Cost"
msgstr "Cost"
msgctxt "field:production.operation.tracking,create_date:"
msgid "Create Date"
msgstr "Data de creació"
msgctxt "field:production.operation.tracking,create_uid:"
msgid "Create User"
msgstr "Usuari de creació"
msgctxt "field:production.operation.tracking,id:"
msgid "ID"
msgstr "Identificador"
msgctxt "field:production.operation.tracking,operation:"
msgid "Operation"
msgstr "Operació"
msgctxt "field:production.operation.tracking,quantity:"
msgid "Quantity"
msgstr "Quantitat"
msgctxt "field:production.operation.tracking,rec_name:"
msgid "Name"
msgstr "Nom"
msgctxt "field:production.operation.tracking,uom:"
msgid "Uom"
msgstr "UdM"
msgctxt "field:production.operation.tracking,work_center:"
msgid "Work Center"
msgstr "Centre de treball"
msgctxt "field:production.operation.tracking,write_date:"
msgid "Write Date"
msgstr "Data modificació"
msgctxt "field:production.operation.tracking,write_uid:"
msgid "Write User"
msgstr "Usuari modificació"
msgctxt "field:production.operation.type,create_date:"
msgid "Create Date"
msgstr "Data de creació"
msgctxt "field:production.operation.type,create_uid:"
msgid "Create User"
msgstr "Usuari de creació"
msgctxt "field:production.operation.type,id:"
msgid "ID"
msgstr "Identificador"
msgctxt "field:production.operation.type,name:"
msgid "Name"
msgstr "Nom"
msgctxt "field:production.operation.type,rec_name:"
msgid "Name"
msgstr "Nom"
msgctxt "field:production.operation.type,write_date:"
msgid "Write Date"
msgstr "Data modificació"
msgctxt "field:production.operation.type,write_uid:"
msgid "Write User"
msgstr "Usuari modificació"
msgctxt "field:production.route,create_date:"
msgid "Create Date"
msgstr "Data de creació"
msgctxt "field:production.route,create_uid:"
msgid "Create User"
msgstr "Usuari de creació"
msgctxt "field:production.route,id:"
msgid "ID"
msgstr "Identificador"
msgctxt "field:production.route,name:"
msgid "Name"
msgstr "Nom"
msgctxt "field:production.route,operations:"
msgid "Operations"
msgstr "Operacions"
msgctxt "field:production.route,rec_name:"
msgid "Name"
msgstr "Nom"
msgctxt "field:production.route,write_date:"
msgid "Write Date"
msgstr "Data modificació"
msgctxt "field:production.route,write_uid:"
msgid "Write User"
msgstr "Usuari modificació"
msgctxt "field:production.route.operation,create_date:"
msgid "Create Date"
msgstr "Data de creació"
msgctxt "field:production.route.operation,create_uid:"
msgid "Create User"
msgstr "Usuari de creació"
msgctxt "field:production.route.operation,id:"
msgid "ID"
msgstr "Identificador"
msgctxt "field:production.route.operation,name:"
msgid "Name"
msgstr "Nom"
msgctxt "field:production.route.operation,operation_type:"
msgid "Operation Type"
msgstr "Tipus d'operació"
msgctxt "field:production.route.operation,rec_name:"
msgid "Name"
msgstr "Nom"
msgctxt "field:production.route.operation,route:"
msgid "Route"
msgstr "Ruta"
msgctxt "field:production.route.operation,sequence:"
msgid "Sequence"
msgstr "Seqüència"
msgctxt "field:production.route.operation,work_center:"
msgid "Work Center"
msgstr "Centre de treball"
msgctxt "field:production.route.operation,write_date:"
msgid "Write Date"
msgstr "Data modificació"
msgctxt "field:production.route.operation,write_uid:"
msgid "Write User"
msgstr "Usuari modificació"
msgctxt "field:production.work_center,category:"
msgid "Category"
msgstr "Categoria"
msgctxt "field:production.work_center,cost_price:"
msgid "Cost Price"
msgstr "Preu de cost"
msgctxt "field:production.work_center,create_date:"
msgid "Create Date"
msgstr "Data de creació"
msgctxt "field:production.work_center,create_uid:"
msgid "Create User"
msgstr "Usuari de creació"
msgctxt "field:production.work_center,employee:"
msgid "Employee"
msgstr "Empleat"
msgctxt "field:production.work_center,id:"
msgid "ID"
msgstr "Identificador"
msgctxt "field:production.work_center,name:"
msgid "Name"
msgstr "Nom"
msgctxt "field:production.work_center,rec_name:"
msgid "Name"
msgstr "Nom"
msgctxt "field:production.work_center,type:"
msgid "Type"
msgstr "Tipus"
msgctxt "field:production.work_center,uom:"
msgid "Uom"
msgstr "UdM"
msgctxt "field:production.work_center,write_date:"
msgid "Write Date"
msgstr "Data modificació"
msgctxt "field:production.work_center,write_uid:"
msgid "Write User"
msgstr "Usuari modificació"
msgctxt "field:production.work_center.category,create_date:"
msgid "Create Date"
msgstr "Data de creació"
msgctxt "field:production.work_center.category,create_uid:"
msgid "Create User"
msgstr "Usuari de creació"
msgctxt "field:production.work_center.category,id:"
msgid "ID"
msgstr "Identificador"
msgctxt "field:production.work_center.category,name:"
msgid "Name"
msgstr "Nom"
msgctxt "field:production.work_center.category,rec_name:"
msgid "Name"
msgstr "Nom"
msgctxt "field:production.work_center.category,write_date:"
msgid "Write Date"
msgstr "Data modificació"
msgctxt "field:production.work_center.category,write_uid:"
msgid "Write User"
msgstr "Usuari modificació"
msgctxt "model:ir.action,name:act_production_operation"
msgid "Operation"
msgstr "Operació"
msgctxt "model:ir.action,name:act_production_operation_tracking"
msgid "Operation Tracking"
msgstr "Registre d'operació"
msgctxt "model:ir.action,name:act_production_operation_type"
msgid "Operation Type"
msgstr "Tipus d'operació"
msgctxt ""
"model:ir.action.act_window.domain,name:act_production_operation_domain_all"
msgid "All"
msgstr "Tots"
msgctxt ""
"model:ir.action.act_window.domain,name:act_production_operation_domain_running"
msgid "Running"
msgstr "En curs"
msgctxt ""
"model:ir.action.act_window.domain,name:act_production_operation_domain_waiting"
msgid "Waiting"
msgstr "Esperant"
msgctxt "model:ir.ui.menu,name:menu_production_operation"
msgid "Operations"
msgstr "Operacions"
msgctxt "model:ir.ui.menu,name:menu_production_operation_type"
msgid "Operation Types"
msgstr "Tipus d'operacions"
msgctxt "model:production.operation,name:"
msgid "Operation"
msgstr "Operació"
msgctxt "model:production.operation.tracking,name:"
msgid "operation.tracking"
msgstr "Registre d'operació"
msgctxt "model:production.operation.type,name:"
msgid "Operation Type"
msgstr "Tipus d'operació"
msgctxt "model:production.route,name:"
msgid "Production Route"
msgstr "Ruta de producció"
msgctxt "model:production.route.operation,name:"
msgid "Route Operation"
msgstr "Ruta"
msgctxt "model:production.work_center,name:"
msgid "Work Center"
msgstr "Centre de treball"
msgctxt "model:production.work_center.category,name:"
msgid "Work Center Category"
msgstr "Categoria del centre de treball"
msgctxt "selection:production.operation,state:"
msgid "Done"
msgstr "Realitzat"
msgctxt "selection:production.operation,state:"
msgid "Planned"
msgstr "Planificat"
msgctxt "selection:production.operation,state:"
msgid "Running"
msgstr "En curs"
msgctxt "selection:production.operation,state:"
msgid "Waiting"
msgstr "Esperant"
msgctxt "selection:production.work_center,type:"
msgid "Employee"
msgstr "Empleat"
msgctxt "selection:production.work_center,type:"
msgid "Machine"
msgstr "Màquina"
msgctxt "view:production.operation.tracking:"
msgid "Operation Tracking"
msgstr "Registre d'operació"
msgctxt "view:production.operation.type:"
msgid "Operation Type"
msgstr "Tipus d'operació"
msgctxt "view:production.operation:"
msgid "Done"
msgstr "Realitzat"
msgctxt "view:production.operation:"
msgid "Operation"
msgstr "Operació"
msgctxt "view:production.operation:"
msgid "Run"
msgstr "Executa"
msgctxt "view:production.operation:"
msgid "Wait"
msgstr "En espera"
msgctxt "view:production.route.operation:"
msgid "Route Operation"
msgstr "Ruta"
msgctxt "view:production.route:"
msgid "Route"
msgstr "Ruta"
msgctxt "view:production.work_center.category:"
msgid "Work Center Category"
msgstr "Categoria del centre de treball"
msgctxt "view:production.work_center:"
msgid "Work Center"
msgstr "Centre de treball"
msgctxt "view:production:"
msgid "Operations"
msgstr "Operacions"

438
locale/es_ES.po Normal file
View File

@ -0,0 +1,438 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "error:production.operation:"
msgid "You can not create an operation for Production \"%s\"."
msgstr "No puede craer una operación para la producción \"%s\"."
msgctxt "error:production:"
msgid ""
"Production \"%(production)s\" can not be done because their operation "
"\"%(operation)s\" is not done."
msgstr ""
"No se puede realizar la producción \"%(production)s\" porqué la operación "
"\"%(operation)s\" todavía no esta realizada."
msgctxt "field:production,operations:"
msgid "Operations"
msgstr "Operaciones"
msgctxt "field:production,route:"
msgid "Route"
msgstr "Ruta"
msgctxt "field:production.operation,cost:"
msgid "Cost"
msgstr "Coste"
msgctxt "field:production.operation,create_date:"
msgid "Create Date"
msgstr "Fecha de creación"
msgctxt "field:production.operation,create_uid:"
msgid "Create User"
msgstr "Usuario de creación"
msgctxt "field:production.operation,id:"
msgid "ID"
msgstr "Identificador"
msgctxt "field:production.operation,lines:"
msgid "Lines"
msgstr "Líneas"
msgctxt "field:production.operation,name:"
msgid "Name"
msgstr "Nombre"
msgctxt "field:production.operation,operation_type:"
msgid "Operation Type"
msgstr "Tipo de operación"
msgctxt "field:production.operation,production:"
msgid "Production"
msgstr "Producción"
msgctxt "field:production.operation,rec_name:"
msgid "Name"
msgstr "Nombre"
msgctxt "field:production.operation,route_operation:"
msgid "Route Operation"
msgstr "Ruta de operación"
msgctxt "field:production.operation,sequence:"
msgid "Sequence"
msgstr "Secuencia"
msgctxt "field:production.operation,state:"
msgid "State"
msgstr "Estado"
msgctxt "field:production.operation,work_center:"
msgid "Work Center"
msgstr "Centro de trabajo"
msgctxt "field:production.operation,write_date:"
msgid "Write Date"
msgstr "Fecha modificación"
msgctxt "field:production.operation,write_uid:"
msgid "Write User"
msgstr "Usuario modificación"
msgctxt "field:production.operation.tracking,cost:"
msgid "Cost"
msgstr "Coste"
msgctxt "field:production.operation.tracking,create_date:"
msgid "Create Date"
msgstr "Fecha de creación"
msgctxt "field:production.operation.tracking,create_uid:"
msgid "Create User"
msgstr "Usuario de creación"
msgctxt "field:production.operation.tracking,id:"
msgid "ID"
msgstr "Identificador"
msgctxt "field:production.operation.tracking,operation:"
msgid "Operation"
msgstr "Operación"
msgctxt "field:production.operation.tracking,quantity:"
msgid "Quantity"
msgstr "Cantidad"
msgctxt "field:production.operation.tracking,rec_name:"
msgid "Name"
msgstr "Nombre"
msgctxt "field:production.operation.tracking,uom:"
msgid "Uom"
msgstr "UdM"
msgctxt "field:production.operation.tracking,work_center:"
msgid "Work Center"
msgstr "Centro de trabajo"
msgctxt "field:production.operation.tracking,write_date:"
msgid "Write Date"
msgstr "Fecha modificación"
msgctxt "field:production.operation.tracking,write_uid:"
msgid "Write User"
msgstr "Usuario modificación"
msgctxt "field:production.operation.type,create_date:"
msgid "Create Date"
msgstr "Fecha de creación"
msgctxt "field:production.operation.type,create_uid:"
msgid "Create User"
msgstr "Usuario de creación"
msgctxt "field:production.operation.type,id:"
msgid "ID"
msgstr "Identificador"
msgctxt "field:production.operation.type,name:"
msgid "Name"
msgstr "Nombre"
msgctxt "field:production.operation.type,rec_name:"
msgid "Name"
msgstr "Nombre"
msgctxt "field:production.operation.type,write_date:"
msgid "Write Date"
msgstr "Fecha modificación"
msgctxt "field:production.operation.type,write_uid:"
msgid "Write User"
msgstr "Usuario modificación"
msgctxt "field:production.route,create_date:"
msgid "Create Date"
msgstr "Fecha de creación"
msgctxt "field:production.route,create_uid:"
msgid "Create User"
msgstr "Usuario de creación"
msgctxt "field:production.route,id:"
msgid "ID"
msgstr "Identificador"
msgctxt "field:production.route,name:"
msgid "Name"
msgstr "Nombre"
msgctxt "field:production.route,operations:"
msgid "Operations"
msgstr "Operaciones"
msgctxt "field:production.route,rec_name:"
msgid "Name"
msgstr "Nombre"
msgctxt "field:production.route,write_date:"
msgid "Write Date"
msgstr "Fecha modificación"
msgctxt "field:production.route,write_uid:"
msgid "Write User"
msgstr "Usuario modificación"
msgctxt "field:production.route.operation,create_date:"
msgid "Create Date"
msgstr "Fecha de creación"
msgctxt "field:production.route.operation,create_uid:"
msgid "Create User"
msgstr "Usuario de creación"
msgctxt "field:production.route.operation,id:"
msgid "ID"
msgstr "Identificador"
msgctxt "field:production.route.operation,name:"
msgid "Name"
msgstr "Nombre"
msgctxt "field:production.route.operation,operation_type:"
msgid "Operation Type"
msgstr "Tipo de operación"
msgctxt "field:production.route.operation,rec_name:"
msgid "Name"
msgstr "Nombre"
msgctxt "field:production.route.operation,route:"
msgid "Route"
msgstr "Ruta"
msgctxt "field:production.route.operation,sequence:"
msgid "Sequence"
msgstr "Secuencia"
msgctxt "field:production.route.operation,work_center:"
msgid "Work Center"
msgstr "Centro de trabajo"
msgctxt "field:production.route.operation,write_date:"
msgid "Write Date"
msgstr "Fecha modificación"
msgctxt "field:production.route.operation,write_uid:"
msgid "Write User"
msgstr "Usuario modificación"
msgctxt "field:production.work_center,category:"
msgid "Category"
msgstr "Categoría"
msgctxt "field:production.work_center,cost_price:"
msgid "Cost Price"
msgstr "Precio de coste"
msgctxt "field:production.work_center,create_date:"
msgid "Create Date"
msgstr "Fecha de creación"
msgctxt "field:production.work_center,create_uid:"
msgid "Create User"
msgstr "Usuario de creación"
msgctxt "field:production.work_center,employee:"
msgid "Employee"
msgstr "Empleado"
msgctxt "field:production.work_center,id:"
msgid "ID"
msgstr "Identificador"
msgctxt "field:production.work_center,name:"
msgid "Name"
msgstr "Nombre"
msgctxt "field:production.work_center,rec_name:"
msgid "Name"
msgstr "Nombre"
msgctxt "field:production.work_center,type:"
msgid "Type"
msgstr "Tipo"
msgctxt "field:production.work_center,uom:"
msgid "Uom"
msgstr "UdM"
msgctxt "field:production.work_center,write_date:"
msgid "Write Date"
msgstr "Fecha modificación"
msgctxt "field:production.work_center,write_uid:"
msgid "Write User"
msgstr "Usuario modificación"
msgctxt "field:production.work_center.category,create_date:"
msgid "Create Date"
msgstr "Fecha de creación"
msgctxt "field:production.work_center.category,create_uid:"
msgid "Create User"
msgstr "Usuario de creación"
msgctxt "field:production.work_center.category,id:"
msgid "ID"
msgstr "Identificador"
msgctxt "field:production.work_center.category,name:"
msgid "Name"
msgstr "Nombre"
msgctxt "field:production.work_center.category,rec_name:"
msgid "Name"
msgstr "Nombre"
msgctxt "field:production.work_center.category,write_date:"
msgid "Write Date"
msgstr "Fecha modificación"
msgctxt "field:production.work_center.category,write_uid:"
msgid "Write User"
msgstr "Usuario modificación"
msgctxt "model:ir.action,name:act_production_operation"
msgid "Operation"
msgstr "Operación"
msgctxt "model:ir.action,name:act_production_operation_tracking"
msgid "Operation Tracking"
msgstr "Registro de operación"
msgctxt "model:ir.action,name:act_production_operation_type"
msgid "Operation Type"
msgstr "Tipo de operación"
msgctxt ""
"model:ir.action.act_window.domain,name:act_production_operation_domain_all"
msgid "All"
msgstr "Todos"
msgctxt ""
"model:ir.action.act_window.domain,name:act_production_operation_domain_running"
msgid "Running"
msgstr "En ejecución"
msgctxt ""
"model:ir.action.act_window.domain,name:act_production_operation_domain_waiting"
msgid "Waiting"
msgstr "En espera"
msgctxt "model:ir.ui.menu,name:menu_production_operation"
msgid "Operations"
msgstr "Operaciones"
msgctxt "model:ir.ui.menu,name:menu_production_operation_type"
msgid "Operation Types"
msgstr "Tipos de operación"
msgctxt "model:production.operation,name:"
msgid "Operation"
msgstr "Operación"
msgctxt "model:production.operation.tracking,name:"
msgid "operation.tracking"
msgstr "Registro de operación"
msgctxt "model:production.operation.type,name:"
msgid "Operation Type"
msgstr "Tipo de operación"
msgctxt "model:production.route,name:"
msgid "Production Route"
msgstr "Ruta de producción"
msgctxt "model:production.route.operation,name:"
msgid "Route Operation"
msgstr "Ruta de operación"
msgctxt "model:production.work_center,name:"
msgid "Work Center"
msgstr "Centro de trabajo"
msgctxt "model:production.work_center.category,name:"
msgid "Work Center Category"
msgstr "Centro de trabajo"
msgctxt "selection:production.operation,state:"
msgid "Done"
msgstr "Realizado"
msgctxt "selection:production.operation,state:"
msgid "Planned"
msgstr "Planificado"
msgctxt "selection:production.operation,state:"
msgid "Running"
msgstr "En ejecución"
msgctxt "selection:production.operation,state:"
msgid "Waiting"
msgstr "En espera"
msgctxt "selection:production.work_center,type:"
msgid "Employee"
msgstr "Empleado"
msgctxt "selection:production.work_center,type:"
msgid "Machine"
msgstr "Maquina"
msgctxt "view:production.operation.tracking:"
msgid "Operation Tracking"
msgstr "Registro de operación"
msgctxt "view:production.operation.type:"
msgid "Operation Type"
msgstr "Tipo de operación"
msgctxt "view:production.operation:"
msgid "Done"
msgstr "Realizado"
msgctxt "view:production.operation:"
msgid "Operation"
msgstr "Operación"
msgctxt "view:production.operation:"
msgid "Run"
msgstr "Ejecutar"
msgctxt "view:production.operation:"
msgid "Wait"
msgstr "Esperando"
msgctxt "view:production.route.operation:"
msgid "Route Operation"
msgstr "Ruta de operación"
msgctxt "view:production.route:"
msgid "Route"
msgstr "Ruta"
msgctxt "view:production.work_center.category:"
msgid "Work Center Category"
msgstr "Centro de trabajo"
msgctxt "view:production.work_center:"
msgid "Work Center"
msgstr "Centro de trabajo"
msgctxt "view:production:"
msgid "Operations"
msgstr "Operaciones"

View File

@ -1,94 +1,111 @@
from decimal import Decimal
from trytond.model import fields, ModelSQL, ModelView, Workflow
from trytond.pool import PoolMeta
from trytond.pyson import Eval
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Eval, If, Bool
from trytond.transaction import Transaction
__all__ = ['WorkCenterCategory', 'WorkCenter', 'Route', 'RouteOperation',
'Operation', 'OperationLine', 'Production']
__all__ = ['Operation', 'OperationTracking', 'Production']
__metaclass__ = PoolMeta
class WorkCenterCategory(ModelSQL, ModelView):
'Work Center Category'
__name__ = 'production.work_center.category'
name = fields.Char('Name', required=True)
cost_price = fields.Numeric('Cost Price', digits=(16, 4), required=True)
uom = fields.Many2One('product.uom', 'Uom', required=True)
STATES = {
'readonly': Eval('state').in_(['running', 'done'])
}
DEPENDS = ['state']
class WorkCenter(ModelSQL, ModelView):
'Work Center'
__name__ = 'production.work_center'
name = fields.Char('Name', required=True)
category = fields.Many2One('production.work_center.category', 'Category')
type = fields.Selection([
('machine', 'Machine'),
('employee', 'Employee'),
], 'Type')
employee = fields.Many2One('company.employee', 'Employee', states={
'invisible': Eval('type') != 'employee',
'required': Eval('type') == 'employee',
}, depends=['type'])
cost_price = fields.Numeric('Cost Price', digits=(16, 4), required=True)
uom = fields.Many2One('product.uom', 'Uom', required=True)
class Route(ModelSQL, ModelView):
'Production Route'
__name__ = 'production.route'
name = fields.Char('Name', required=True)
operations = fields.One2Many('production.route.operation', 'bom',
'Operations')
class OperationType(ModelSQL, ModelView):
'Operation Type'
__name__ = 'production.operation.type'
name = fields.Char('Name', required=True)
class RouteOperation(ModelSQL, ModelView):
'Route Operation'
__name__ = 'production.route.operation'
route = fields.Many2One('production.route', 'Route', required=True)
name = fields.Char('Name', required=True)
sequence = fields.Integer('Sequence')
work_center = fields.Many2One('production.work_center', 'Work Center')
work_center_category = fields.Many2One('production.work_center', 'Work Center')
operation_type = fields.Many2One('production.operation.type', 'Operation Type')
@classmethod
def __setup__(cls):
super(RouteOperation, cls).__setup__()
cls._order.insert(0, ('sequence', 'ASC'))
@staticmethod
def order_sequence(tables):
table, _ = tables[None]
return [table.sequence == None, table.sequence]
class Operation(ModelSQL, ModelView):
class Operation(Workflow, ModelSQL, ModelView):
'Operation'
__name__ = 'production.operation'
production = fields.Many2One('production', 'Production', required=True)
name = fields.Char('Name', required=True)
sequence = fields.Integer('Sequence')
work_center = fields.Many2One('production.work_center', 'Work Center')
route_operation = fields.Many2One('production.route.operation',
'Route Operation')
lines = fields.One2Many('production.operation.line', 'operation', 'Lines')
cost = fields.Function(fields.Numeric('Cost'), 'get_cost')
operation_type = fields.Many2One('production.operation.type', 'Operation Type')
# TODO: Add workflow
production = fields.Many2One('production', 'Production', required=True,
states=STATES, depends=DEPENDS)
sequence = fields.Integer('Sequence', states=STATES, depends=DEPENDS)
work_center = fields.Many2One('production.work_center', 'Work Center',
states=STATES, depends=DEPENDS)
route_operation = fields.Many2One('production.route.operation',
'Route Operation', states=STATES, depends=DEPENDS)
lines = fields.One2Many('production.operation.tracking', 'operation',
'Lines', states=STATES, depends=DEPENDS, context={
'work_center': Eval('work_center'),
})
cost = fields.Function(fields.Numeric('Cost'), 'get_cost')
operation_type = fields.Many2One('production.operation.type',
'Operation Type', states=STATES, depends=DEPENDS, required=True)
uom_category = fields.Function(fields.Many2One(
'product.uom.category', 'Uom Category', on_change_with=[
'work_center']),
'on_change_with_uom_category')
state = fields.Selection([
('planned', 'Planned'),
('waiting', 'Waiting'),
('running', 'Running'),
('done', 'Done'),
], 'State', readonly=True)
@classmethod
def __setup__(cls):
super(Operation, cls).__setup__()
cls._order.insert(0, ('sequence', 'ASC'))
cls._invalid_production_states_on_create = ['running', 'done']
cls._error_messages.update({
'invalid_production_state': ('You can not create an operation'
' for Production "%s".'),
})
cls._transitions |= set((
('planned', 'waiting'),
('waiting', 'running'),
('running', 'waiting'),
('running', 'done'),
))
cls._buttons.update({
'wait': {
'invisible': Eval('state') != 'running',
'icon': 'tryton-go-previous',
},
'run': {
'invisible': Eval('state') != 'waiting',
'icon': 'tryton-go-next',
},
'done': {
'invisible': Eval('state') != 'running',
},
})
@staticmethod
def default_state():
return 'planned'
def get_rec_name(self, name):
if self.operation_type:
return self.operation_type.rec_name
return super(Operation, self).get_rec_name()
@classmethod
def search_rec_name(cls, name, clause):
return [('operation_type.name',) + tuple(clause[1:])]
def on_change_with_uom_category(self, name=None):
if self.work_center:
return self.work_center.uom.category.id
@classmethod
def create(cls, vlist):
pool = Pool()
Production = pool.get('production')
productions = []
for value in vlist:
productions.append(value['production'])
invalid_productions = Production.search([
('id', 'in', productions),
('state', 'in', cls._invalid_production_states_on_create),
], limit=1)
if invalid_productions:
production, = invalid_productions
cls.raise_user_error('invalid_production_state',
production.rec_name)
super(Operation, cls).create(vlist)
@staticmethod
def order_sequence(tables):
@ -96,40 +113,109 @@ class Operation(ModelSQL, ModelView):
return [table.sequence == None, table.sequence]
def get_cost(self, name):
# TODO
return Decimal('0.0')
cost = Decimal('0.0')
for line in self.lines:
cost += line.cost
return cost
@classmethod
@ModelView.button
@Workflow.transition('waiting')
def wait(cls, operations):
pass
@classmethod
@ModelView.button
@Workflow.transition('running')
def run(cls, operations):
pass
@classmethod
def done(cls, operations):
pool = Pool()
Production = pool.get('production')
productions = set([o.production for o in operations])
cls.write(operations, {'state': 'done'})
with Transaction().set_context(from_done_operation=True):
Production.done(productions)
class OperationLine(ModelSQL, ModelView):
'Operation Line'
__name__ = 'production.operation.line'
class OperationTracking(ModelSQL, ModelView):
'operation.tracking'
__name__ = 'production.operation.tracking'
operation = fields.Many2One('production.operation', 'Operation',
required=True)
work_center = fields.Function(fields.Many2One('production.work_center',
'Work Center', on_change_with=['operation']),
'on_change_with_work_center')
# Maybe start and end in a new module?
start = fields.DateTime('Start')
end = fields.DateTime('End')
quantity = fields.Float('Quantity')
uom = fields.Many2One('product.uom', 'Uom', required=True)
uom = fields.Many2One('product.uom', 'Uom', required=True,
on_change_with=['operation'], domain=[
If(Bool(Eval('_parent_operation', 0)),
('category', '=', Eval('_parent_operation', {}).get(
'uom_category', 0)), (),
)])
unit_digits = fields.Function(fields.Integer('Unit Digits',
on_change_with=['uom']), 'on_change_with_unit_digits')
quantity = fields.Float('Quantity', required=True,
digits=(16, Eval('unit_digits', 2)), depends=['unit_digits'])
cost = fields.Function(fields.Numeric('Cost'), 'get_cost')
def get_cost(self, name):
# TODO
return Decimal('0.0')
@staticmethod
def default_quantity():
return 0.0
def on_change_with_work_center(self, name=None):
return (self.operation.work_center.id
if self.operation and self.operation.work_center else None)
@staticmethod
def default_uom():
pool = Pool()
WorkCenter = pool.get('production.work_center')
context = Transaction().context
if 'work_center' in context:
work_center = WorkCenter(context['work_center'])
return work_center.uom.id
def get_cost(self, name):
pool = Pool()
Uom = pool.get('product.uom')
work_center = self.operation.work_center
if not work_center:
return Decimal('0.0')
quantity = Uom.compute_qty(self.uom, self.quantity,
work_center.uom)
return Decimal(str(quantity)) * work_center.cost_price
def on_change_with_uom(self):
if self.operation.work_center:
return self.operation.work_center.uom.id
def on_change_with_unit_digits(self, name=None):
if self.uom:
return self.uom.digits
return 2
class Production:
__name__ = 'production'
route = fields.Many2One('production.route', 'Route',
on_change=['route', 'operations'])
on_change=['route', 'operations'], states={
'readonly': ~Eval('state').in_(['request', 'draft']),
})
operations = fields.One2Many('production.operation', 'production',
'Operations')
'Operations', order=[('sequence', 'ASC')], states={
'readonly': Eval('state') == 'done',
})
@classmethod
def __setup__(cls):
super(Production, cls).__setup__()
cls._error_messages.update({
'pending_operations': ('Production "%(production)s" can not be'
' done because their operation "%(operation)s" is not '
'done.'),
'no_work_center': ('We can not found any work center for '
'Operation "%s".'),
})
def update_operations(self):
if not self.route:
@ -143,10 +229,11 @@ class Production:
}
for operation in self.route.operations:
operations['add'].append({
'name': operation.name,
'sequence': operation.sequence,
'work_center': (operation.work_center.id
if operation.work_center else None),
'operation_type': (operation.operation_type.id
if operation.operation_type else None),
'route_operation': operation.id,
})
return changes
@ -154,6 +241,57 @@ class Production:
def on_change_route(self):
return self.update_operations()
@classmethod
def run(cls, productions):
pool = Pool()
Operation = pool.get('production.operation')
super(Production, cls).run(productions)
operations = []
for production in productions:
operations.extend(production.operations)
if operations:
Operation.wait(operations)
@classmethod
def done(cls, productions):
pool = Pool()
Operation = pool.get('production.operation')
Template = pool.get('product.template')
Product = pool.get('product.product')
pending_operations = Operation.search([
('production', 'in', [p.id for p in productions]),
('state', '!=', 'done'),
], limit=1)
if pending_operations:
if Transaction().context.get('from_done_operation', False):
return
operation, = pending_operations
cls.raise_user_error('pending_operations', error_args={
'production': operation.production.rec_name,
'operation': operation.rec_name,
})
if hasattr(Product, 'cost_price'):
digits = Product.cost_price.digits
else:
digits = Template.cost_price.digits
for production in productions:
operation_cost = sum(o.cost for o in production.operations)
total_quantity = Decimal(str(sum(o.quantity for o in
production.outputs)))
added_unit_price = Decimal(operation_cost / total_quantity
).quantize(Decimal(str(10 ** -digits[1])))
for output in production.outputs:
output.unit_price += added_unit_price
output.save()
super(Production, cls).done(productions)
def get_cost(self, name):
cost = super(Production, self).get_cost(name)
for operation in self.operations:

View File

@ -1,46 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<tryton>
<data>
<record model="ir.ui.view" id="production_route_operation_view_form">
<field name="model">production.route.operation</field>
<field name="type">form</field>
<field name="name">route_operation_form</field>
<field name="inherit"
ref="production_route.production_route_operation_view_form" />
</record>
<record model="ir.ui.view" id="production_route_operation_view_list">
<field name="model">production.route.operation</field>
<field name="type">tree</field>
<field name="name">route_operation_list</field>
<field name="inherit"
ref="production_route.production_route_operation_view_list" />
</record>
<record model="ir.action.act_window" id="act_production_route_operation">
<field name="name">Route Operation</field>
<field name="res_model">production.route.operation</field>
</record>
<record model="ir.action.act_window.view" id="act_production_route_operation_view1">
<field name="sequence" eval="10"/>
<field name="view" ref="production_route_operation_view_list"/>
<field name="act_window" ref="act_production_route_operation"/>
</record>
<record model="ir.action.act_window.view" id="act_production_route_operation_view2">
<field name="sequence" eval="20"/>
<field name="view" ref="production_route_operation_view_form"/>
<field name="act_window" ref="act_production_route_operation"/>
</record>
<record model="ir.model.access" id="access_production_route_operation">
<field name="model" search="[('model', '=', 'production.route.operation')]"/>
<field name="group" ref="production.group_production"/>
<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_production_route_operation_admin">
<field name="model" search="[('model', '=', 'production.route.operation')]"/>
<field name="group" ref="production.group_production_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="production_operation_view_form">
<field name="model">production.operation</field>
<field name="type">form</field>
@ -55,136 +31,86 @@
<field name="name">Operation</field>
<field name="res_model">production.operation</field>
</record>
<record model="ir.action.act_window.view" id="act_production_operation_view1">
<record model="ir.action.act_window.view"
id="act_production_operation_view1">
<field name="sequence" eval="10"/>
<field name="view" ref="production_operation_view_list"/>
<field name="act_window" ref="act_production_operation"/>
</record>
<record model="ir.action.act_window.view" id="act_production_operation_view2">
<record model="ir.action.act_window.view"
id="act_production_operation_view2">
<field name="sequence" eval="20"/>
<field name="view" ref="production_operation_view_form"/>
<field name="act_window" ref="act_production_operation"/>
</record>
<record model="ir.action.act_window.domain"
id="act_production_operation_domain_waiting">
<field name="name">Waiting</field>
<field name="sequence" eval="10"/>
<field name="domain">[('state', '=', 'waiting')]</field>
<field name="act_window" ref="act_production_operation"/>
</record>
<record model="ir.action.act_window.domain"
id="act_production_operation_domain_running">
<field name="name">Running</field>
<field name="sequence" eval="20"/>
<field name="domain">[('state', '=', 'running')]</field>
<field name="act_window" ref="act_production_operation"/>
</record>
<record model="ir.action.act_window.domain"
id="act_production_operation_domain_all">
<field name="name">All</field>
<field name="sequence" eval="30"/>
<field name="domain"></field>
<field name="act_window" ref="act_production_operation"/>
</record>
<record model="ir.model.access" id="access_production_operation">
<field name="model" search="[('model', '=', 'production.operation')]"/>
<field name="model"
search="[('model', '=', 'production.operation')]"/>
<field name="group" ref="production.group_production"/>
<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="production_operation_line_view_form">
<field name="model">production.operation.line</field>
<record model="ir.ui.view" id="production_operation_tracking_view_form">
<field name="model">production.operation.tracking</field>
<field name="type">form</field>
<field name="name">operation_line_form</field>
<field name="name">operation_tracking_form</field>
</record>
<record model="ir.ui.view" id="production_operation_line_view_list">
<field name="model">production.operation.line</field>
<record model="ir.ui.view" id="production_operation_tracking_view_list">
<field name="model">production.operation.tracking</field>
<field name="type">tree</field>
<field name="name">operation_line_list</field>
<field name="name">operation_tracking_list</field>
</record>
<record model="ir.action.act_window" id="act_production_operation_line">
<field name="name">Operation Line</field>
<field name="res_model">production.operation.line</field>
<record model="ir.action.act_window"
id="act_production_operation_tracking">
<field name="name">Operation Tracking</field>
<field name="res_model">production.operation.tracking</field>
</record>
<record model="ir.action.act_window.view" id="act_production_operation_line_view1">
<record model="ir.action.act_window.view"
id="act_production_operation_tracking_view1">
<field name="sequence" eval="10"/>
<field name="view" ref="production_operation_line_view_list"/>
<field name="act_window" ref="act_production_operation_line"/>
<field name="view" ref="production_operation_tracking_view_list"/>
<field name="act_window" ref="act_production_operation_tracking"/>
</record>
<record model="ir.action.act_window.view" id="act_production_operation_line_view2">
<record model="ir.action.act_window.view"
id="act_production_operation_tracking_view2">
<field name="sequence" eval="20"/>
<field name="view" ref="production_operation_line_view_form"/>
<field name="act_window" ref="act_production_operation_line"/>
<field name="view" ref="production_operation_tracking_view_form"/>
<field name="act_window" ref="act_production_operation_tracking"/>
</record>
<record model="ir.model.access" id="access_production_operation_line">
<field name="model" search="[('model', '=', 'production.operation.line')]"/>
<record model="ir.model.access"
id="access_production_operation_tracking">
<field name="model"
search="[('model', '=', 'production.operation.tracking')]"/>
<field name="group" ref="production.group_production"/>
<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="production_work_center_view_form">
<field name="model">production.work_center</field>
<field name="type">form</field>
<field name="name">work_center_form</field>
</record>
<record model="ir.ui.view" id="production_work_center_view_list">
<field name="model">production.work_center</field>
<field name="type">tree</field>
<field name="name">work_center_list</field>
</record>
<record model="ir.action.act_window" id="act_production_work_center">
<field name="name">Work Center</field>
<field name="res_model">production.work_center</field>
</record>
<record model="ir.action.act_window.view" id="act_production_work_center_view1">
<field name="sequence" eval="10"/>
<field name="view" ref="production_work_center_view_list"/>
<field name="act_window" ref="act_production_work_center"/>
</record>
<record model="ir.action.act_window.view" id="act_production_work_center_view2">
<field name="sequence" eval="20"/>
<field name="view" ref="production_work_center_view_form"/>
<field name="act_window" ref="act_production_work_center"/>
</record>
<record model="ir.model.access" id="access_production_work_center">
<field name="model" search="[('model', '=', 'production.work_center')]"/>
<field name="group" ref="production.group_production"/>
<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_production_work_center_admin">
<field name="model" search="[('model', '=', 'production.work_center')]"/>
<field name="group" ref="production.group_production_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="production_work_center_category_view_form">
<field name="model">production.work_center.category</field>
<field name="type">form</field>
<field name="name">work_center_category_form</field>
</record>
<record model="ir.ui.view" id="production_work_center_category_view_list">
<field name="model">production.work_center.category</field>
<field name="type">tree</field>
<field name="name">work_center_category_list</field>
</record>
<record model="ir.action.act_window" id="act_production_work_center_category">
<field name="name">Work Center Category</field>
<field name="res_model">production.work_center.category</field>
</record>
<record model="ir.action.act_window.view" id="act_production_work_center_category_view1">
<field name="sequence" eval="10"/>
<field name="view" ref="production_work_center_category_view_list"/>
<field name="act_window" ref="act_production_work_center_category"/>
</record>
<record model="ir.action.act_window.view" id="act_production_work_center_category_view2">
<field name="sequence" eval="20"/>
<field name="view" ref="production_work_center_category_view_form"/>
<field name="act_window" ref="act_production_work_center_category"/>
</record>
<record model="ir.model.access" id="access_production_work_center_category">
<field name="model" search="[('model', '=', 'production.work_center.category')]"/>
<field name="group" ref="production.group_production"/>
<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_production_work_center_category_admin">
<field name="model" search="[('model', '=', 'production.work_center.category')]"/>
<field name="group" ref="production.group_production_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="production_view_form">
<field name="model">production</field>
<field name="type">form</field>
@ -192,62 +118,11 @@
<field name="name">production_form</field>
</record>
<record model="ir.ui.view" id="production_route_view_form">
<field name="model">production.route</field>
<field name="type">form</field>
<field name="name">route_form</field>
</record>
<record model="ir.ui.view" id="production_route_view_list">
<field name="model">production.route</field>
<field name="type">tree</field>
<field name="name">route_list</field>
</record>
<record model="ir.action.act_window" id="act_production_route">
<field name="name">Route</field>
<field name="res_model">production.route</field>
</record>
<record model="ir.action.act_window.view" id="act_production_route_view1">
<field name="sequence" eval="10"/>
<field name="view" ref="production_route_view_list"/>
<field name="act_window" ref="act_production_route"/>
</record>
<record model="ir.action.act_window.view" id="act_production_route_view2">
<field name="sequence" eval="20"/>
<field name="view" ref="production_route_view_form"/>
<field name="act_window" ref="act_production_route"/>
</record>
<record model="ir.model.access" id="access_production_route">
<field name="model" search="[('model', '=', 'production.route')]"/>
<field name="group" ref="production.group_production"/>
<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_production_route_admin">
<field name="model" search="[('model', '=', 'production.route')]"/>
<field name="group" ref="production.group_production_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>
<!-- Menus -->
<menuitem action="act_production_route"
id="menu_production_route"
parent="production.menu_configuration"
sequence="30"
name="Routes"/>
<menuitem action="act_production_work_center_category"
id="menu_production_work_center_category"
parent="menu_production_route"
<menuitem action="act_production_operation"
id="menu_production_operation"
parent="production.menu_production_list"
sequence="10"
name="Work Center Categories"/>
<menuitem action="act_production_work_center"
id="menu_production_work_center"
parent="menu_production_route"
sequence="20"
name="Work Centers"/>
name="Operations"/>
</data>
</tryton>

View File

@ -0,0 +1,251 @@
===================
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', '=', 'production_operation')])
>>> 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 a route with two operations on diferent work center::
>>> ProductUom = Model.get('product.uom')
>>> Route = Model.get('production.route')
>>> OperationType = Model.get('production.operation.type')
>>> RouteOperation = Model.get('production.route.operation')
>>> assembly = OperationType(name='Assembly')
>>> assembly.save()
>>> clean = OperationType(name='clean')
>>> clean.save()
>>> WorkCenter = Model.get('production.work_center')
>>> hour, = ProductUom.find([('name', '=', 'Hour')])
>>> workcenter1 = WorkCenter()
>>> workcenter1.name = 'Assembler Machine'
>>> workcenter1.type = 'machine'
>>> workcenter1.uom = hour
>>> workcenter1.cost_price = Decimal('25.0')
>>> workcenter1.save()
>>> workcenter2 = WorkCenter()
>>> workcenter2.name = 'Cleaner Machine'
>>> workcenter2.type = 'machine'
>>> workcenter2.uom = hour
>>> workcenter2.cost_price = Decimal('50.0')
>>> workcenter2.save()
>>> route = Route(name='default route')
>>> route_operation = RouteOperation()
>>> route.operations.append(route_operation)
>>> route_operation.sequence = 1
>>> route_operation.operation_type = assembly
>>> route_operation.work_center = workcenter1
>>> route_operation = RouteOperation()
>>> route.operations.append(route_operation)
>>> route_operation.sequence = 2
>>> route_operation.operation_type = clean
>>> route_operation.work_center = workcenter2
>>> route.save()
>>> route.reload()
>>> len(route.operations) == 2
True
Create product::
>>> 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::
>>> component1 = Product()
>>> template1 = ProductTemplate()
>>> template1.name = 'component 1'
>>> template1.default_uom = unit
>>> template1.type = 'goods'
>>> template1.list_price = Decimal(5)
>>> template1.cost_price = Decimal(1)
>>> template1.save()
>>> component1.template = template1
>>> component1.save()
>>> meter, = ProductUom.find([('name', '=', 'Meter')])
>>> centimeter, = ProductUom.find([('name', '=', 'centimeter')])
>>> 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')
>>> 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 an Inventory::
>>> Inventory = Model.get('stock.inventory')
>>> InventoryLine = Model.get('stock.inventory.line')
>>> storage, = Location.find([
... ('code', '=', 'STO'),
... ])
>>> inventory = Inventory()
>>> inventory.location = storage
>>> inventory_line1 = InventoryLine()
>>> inventory.lines.append(inventory_line1)
>>> inventory_line1.product = component1
>>> inventory_line1.quantity = 10
>>> inventory_line2 = InventoryLine()
>>> inventory.lines.append(inventory_line2)
>>> inventory_line2.product = component2
>>> inventory_line2.quantity = 5
>>> inventory.save()
>>> Inventory.confirm([inventory.id], config.context)
>>> inventory.state
u'done'
Make a production::
>>> Production = Model.get('production')
>>> Operation = Model.get('production.operation')
>>> OperationTracking = Model.get('production.operation.tracking')
>>> production = Production()
>>> production.product = product
>>> production.route = route
>>> len(production.operations) == 2
True
>>> [o.operation_type for o in production.operations] == [assembly, clean]
True
>>> production.bom = bom
>>> production.quantity = 2
>>> sorted([i.quantity for i in production.inputs]) == [10, 300]
True
>>> output, = production.outputs
>>> output.quantity == 2
True
>>> production.save()
>>> production.reload()
>>> [o.state for o in production.operations] == ['planned', 'planned']
True
>>> Production.wait([production.id], config.context)
>>> production.state
u'waiting'
>>> Production.assign_try([production.id], config.context)
True
>>> production.reload()
>>> all(i.state == 'assigned' for i in production.inputs)
True
>>> Production.run([production.id], config.context)
>>> production.reload()
>>> all(i.state == 'done' for i in production.inputs)
True
>>> Production.done([production.id], config.context)
Traceback (most recent call last):
...
UserError: ('UserError', (u'Production "1" can not be done because their operation "Assembly" is not done.', ''))
>>> operation1, operation2 = production.operations
>>> tracking = OperationTracking()
>>> operation1.lines.append(tracking)
>>> minute, = ProductUom.find([('name', '=', 'Minute')])
>>> tracking.quantity = 180.0
>>> tracking.uom = minute
>>> operation1.save()
>>> operations = [o.id for o in production.operations]
>>> Operation.run(operations, config.context)
>>> Operation.done(operations, config.context)
>>> production.reload()
>>> production.state
u'done'
>>> production.cost == Decimal('100')
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_production_operation.rst',
setUp=doctest_dropdb, tearDown=doctest_dropdb, encoding='utf-8',
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
return suite
if __name__ == '__main__':

View File

@ -1,6 +1,6 @@
[tryton]
version=2.9.0
depends:
production
production_route
xml:
operation.xml

View File

@ -2,14 +2,25 @@
<!-- The COPYRIGHT file at the top level of this repository contains the full
copyright notices and license terms. -->
<form string="Operation">
<label name="operation_type"/>
<field name="operation_type"/>
<label name="production"/>
<field name="production"/>
<newline/>
<label name="name"/>
<field name="name"/>
<label name="work_center"/>
<field name="work_center"/>
<label name="sequence"/>
<field name="sequence"/>
<field name="lines" colspan="4"/>
<group col="4" colspan="4" id="state_buttons">
<label name="state"/>
<field name="state"/>
<group col="6" colspan="2" id="buttons">
<button name="wait" string="Wait"/>
<button name="run" string="Run"
icon="tryton-go-next"/>
<button name="done" string="Done"
icon="tryton-go-next"/>
</group>
</group>
<field name="uom_category" invisible="1"/>
</form>

View File

@ -1,14 +1,7 @@
<?xml version="1.0"?>
<!-- The COPYRIGHT file at the top level of this repository contains the full
copyright notices and license terms. -->
<form string="Operation Line" col="4">
<label name="operation"/>
<field name="operation"/>
<newline/>
<label name="start"/>
<field name="start"/>
<label name="end"/>
<field name="end"/>
<form string="Operation Tracking" col="4">
<label name="quantity"/>
<field name="quantity"/>
<label name="uom"/>

View File

@ -1,10 +1,8 @@
<?xml version="1.0"?>
<!-- The COPYRIGHT file at the top level of this repository contains the full
copyright notices and license terms. -->
<tree string="Operation Line">
<tree string="Operation Tracking">
<field name="operation"/>
<field name="start"/>
<field name="end"/>
<field name="quantity"/>
<field name="uom"/>
</tree>

View File

@ -3,6 +3,7 @@
copyright notices and license terms. -->
<tree string="Operation" sequence="sequence">
<field name="production"/>
<field name="name"/>
<field name="operation_type"/>
<field name="work_center"/>
<field name="state"/>
</tree>

View File

@ -1,8 +0,0 @@
<?xml version="1.0"?>
<!-- The COPYRIGHT file at the top level of this repository contains the full
copyright notices and license terms. -->
<form string="Route">
<label name="name"/>
<field name="name"/>
<field name="operations" colspan="4"/>
</form>

View File

@ -1,6 +0,0 @@
<?xml version="1.0"?>
<!-- The COPYRIGHT file at the top level of this repository contains the full
copyright notices and license terms. -->
<tree string="Route">
<field name="name"/>
</tree>

View File

@ -1,14 +1,9 @@
<?xml version="1.0"?>
<!-- The COPYRIGHT file at the top level of this repository contains the full
copyright notices and license terms. -->
<form string="Route Operation">
<label name="route"/>
<field name="route"/>
<newline/>
<label name="name"/>
<field name="name"/>
<label name="work_center"/>
<field name="work_center"/>
<label name="sequence"/>
<field name="sequence"/>
</form>
<data>
<xpath expr="/form/label[@name='work_center_category']" position="before">
<label name="operation_type"/>
<field name="operation_type"/>
</xpath>
</data>

View File

@ -1,7 +1,8 @@
<?xml version="1.0"?>
<!-- The COPYRIGHT file at the top level of this repository contains the full
copyright notices and license terms. -->
<tree string="Route Operation" sequence="sequence">
<field name="name"/>
<field name="work_center"/>
</tree>
<data>
<xpath expr="/tree/field[@name='work_center_category']" position="before">
<field name="operation_type"/>
</xpath>
</data>

View File

@ -1,7 +0,0 @@
<?xml version="1.0"?>
<!-- The COPYRIGHT file at the top level of this repository contains the full
copyright notices and license terms. -->
<form string="Work Center Category">
<label name="name"/>
<field name="name" colspan="3"/>
</form>

View File

@ -1,6 +0,0 @@
<?xml version="1.0"?>
<!-- The COPYRIGHT file at the top level of this repository contains the full
copyright notices and license terms. -->
<tree string="Work Center Category">
<field name="name"/>
</tree>

View File

@ -1,17 +0,0 @@
<?xml version="1.0"?>
<!-- The COPYRIGHT file at the top level of this repository contains the full
copyright notices and license terms. -->
<form string="Work Center">
<label name="name"/>
<field name="name"/>
<label name="type"/>
<field name="type"/>
<label name="category"/>
<field name="category"/>
<label name="employee"/>
<field name="employee"/>
<label name="cost_price"/>
<field name="cost_price"/>
<label name="uom"/>
<field name="uom"/>
</form>

View File

@ -1,9 +0,0 @@
<?xml version="1.0"?>
<!-- The COPYRIGHT file at the top level of this repository contains the full
copyright notices and license terms. -->
<tree string="Work Center">
<field name="category"/>
<field name="name"/>
<field name="type"/>
<field name="employee"/>
</tree>