diff --git a/__init__.py b/__init__.py
index 3f890db..0f527b6 100644
--- a/__init__.py
+++ b/__init__.py
@@ -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')
diff --git a/locale/ca_ES.po b/locale/ca_ES.po
new file mode 100644
index 0000000..1e49fc8
--- /dev/null
+++ b/locale/ca_ES.po
@@ -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"
diff --git a/locale/es_ES.po b/locale/es_ES.po
new file mode 100644
index 0000000..ab9d680
--- /dev/null
+++ b/locale/es_ES.po
@@ -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"
diff --git a/operation.py b/operation.py
index 4af0a19..5686257 100644
--- a/operation.py
+++ b/operation.py
@@ -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:
diff --git a/operation.xml b/operation.xml
index 2a652df..12a59c3 100644
--- a/operation.xml
+++ b/operation.xml
@@ -1,46 +1,22 @@