[ADD] nan_prodlot_quality_control: new module nan_prodlot_quality_control with a generic infraestructure to add quality control tests to prodlots. this module without others doesn't provide final functionalities

This commit is contained in:
Guillem Barba 2012-02-20 17:05:49 +01:00 committed by Àngel Àlvarez
commit 5b83f0eb07
15 changed files with 1122 additions and 0 deletions

35
__init__.py Normal file
View File

@ -0,0 +1,35 @@
##############################################################################
#
# Copyright (c) 2010-2012 NaN Projectes de Programari Lliure, S.L.
# All Rights Reserved.
# http://www.NaN-tic.com
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU Affero General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import quality_control
import company
import product
import stock
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

73
__openerp__.py Normal file
View File

@ -0,0 +1,73 @@
##############################################################################
#
# Copyright (c) 2010-2012 NaN Projectes de Programari Lliure, S.L.
# All Rights Reserved.
# http://www.NaN-tic.com
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU Affero General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
{
"name" : "Production Lot Quality Control",
"version" : "0.2",
"author" : "NaN Projectes de Programari Lliure S.L.",
"category" : "Generic Modules/Quality Control",
"website": "http://www.nan-tic.com",
"description": """
Module developed for Trod y Avia, S.L.
This module supply an infrastructure to define Quality Test that the
Production Lots must pass in some situations. It adds a workflow to
Production Lot.
Adds a new simple model for Quality Test to define Triggers (a mark to
specify when a test must be passed) a model related to product with
one2many field which define which tests must to pass the lots of the product
specifying the Test Template and the Trigger. In the Company there are a
similar field and one2many to define the general tests (when a product is
created take the default values from these values).
In the Production Lot there are a similar model and one2many field but
relates the Lot with a trigger and Test.
IMPORTANT: This module without anything else do not define any Test to pass.
It will be defined in other dependant modules.
""",
"depends" : [
'stock',
'nan_quality_control',
],
"init_xml" : [],
"update_xml" : [
'security/security.xml',
'quality_control_view.xml',
'company_view.xml',
'product_view.xml',
'stock_view.xml',
'prodlot_workflow.xml',
'security/ir.model.access.csv',
],
"demo_xml" : [],
"active": False,
"installable": True,
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

84
company.py Normal file
View File

@ -0,0 +1,84 @@
##############################################################################
#
# Copyright (c) 2012 NaN Projectes de Programari Lliure, S.L.
# All Rights Reserved.
# http://www.NaN-tic.com
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU Affero General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from osv import osv, fields
class res_company_qc_trigger_template(osv.osv):
'''
Model to configure the default Quality Control Templates/Tests triggers by
Company. Define the template to use for a trigger, ordering it by sequence.
'''
_name = 'res.company.qc.trigger.template'
_description = 'Quality Control Template Triggers by Company'
_order = 'company_id, sequence'
_columns = {
'company_id': fields.many2one('res.company', 'Company', required=True),
'sequence': fields.integer('Sequence', required=True),
'trigger_id': fields.many2one('qc.trigger', 'Trigger', required=True,
help="The Quality Control Trigger Tag which defines when must "
"to be created a Test (using the specified template) for a "
"Production Lot."),
'template_id': fields.many2one('qc.test.template', 'Template',
domain=[('type','=','generic')], required=True,
help="The Quality Control Template to use."),
}
_defaults = {
'sequence': 0,
}
_sql_constraints = [
('company_trigger_uniq', 'unique (company_id, trigger_id)',
"The QC Trigger Tag must be unique for each Company!"),
]
res_company_qc_trigger_template()
class res_company(osv.osv):
'''
Adds to the company a one2many field to the model which configures Quality
Control Templates/Tests triggers.
It will be used as default values when a new Product is created.
'''
_inherit = 'res.company'
_columns = {
'qc_template_trigger_ids': fields.one2many(
'res.company.qc.trigger.template', 'company_id', 'QC Triggers',
help="Defines when a Production Lot must to pass a Quality "
"Control Test (based on the defined Template).\n"
"It defines the default Template Triggers which will be used "
"when a Product is created. Only the Product's field define "
"the final behavior of its lots: which template to use or "
"don't require any test if there aren't any trigger defined."),
}
res_company()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

60
company_view.xml Normal file
View File

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!-- res.company.qc.trigger.template -->
<record id="company_qc_trigger_template_form" model="ir.ui.view">
<field name="name">res.company.qc.trigger.template.form</field>
<field name="model">res.company.qc.trigger.template</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="QC Template Trigger by Company">
<field name="company_id" select="1"/>
<field name="sequence"/>
<field name="trigger_id" select="1"/>
<field name="template_id"/>
</form>
</field>
</record>
<record id="company_qc_trigger_template_tree" model="ir.ui.view">
<field name="name">res.company.qc.trigger.template.tree</field>
<field name="model">res.company.qc.trigger.template</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="QC Template Triggers by Company">
<field name="company_id"/>
<field name="sequence"/>
<field name="trigger_id"/>
<field name="template_id"/>
</tree>
</field>
</record>
<!-- res.company -->
<record id="company_prodlot_qc_form" model="ir.ui.view">
<field name="name">res.company.prodlot.quality_control.form</field>
<field name="model">res.company</field>
<field name="type">form</field>
<field name="inherit_id" ref="base.view_company_form"/>
<field name="arch" type="xml">
<page string="Configuration" position="inside">
<group name="prodlot_qc" colspan="2" col="2">
<separator string="Quality Control Triggers" colspan="2"/>
<field name="qc_template_trigger_ids" nolabel="1" colspan="2">
<tree string="Quality Control Triggers" editable="bottom">
<field name="sequence"/>
<field name="trigger_id"/>
<field name="template_id"/>
</tree>
<form string="Quality Control Trigger">
<field name="trigger_id"/>
<field name="template_id"/>
</form>
</field>
</group>
</page>
</field>
</record>
</data>
</openerp>

BIN
doc/models.dia Normal file

Binary file not shown.

BIN
doc/workflow.dia Normal file

Binary file not shown.

137
prodlot_workflow.xml Normal file
View File

@ -0,0 +1,137 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="wkf_prodlot" model="workflow">
<field name="name">stock.production.lot.basic</field>
<field name="osv">stock.production.lot</field>
<field name="on_create">True</field>
</record>
<!-- Activity -->
<record id="act_draft" model="workflow.activity">
<field name="wkf_id" ref="wkf_prodlot"/>
<field name="name">draft</field>
<field name="flow_start">True</field>
<field name="kind">function</field>
<field name="action">action_wofkflow_draft()</field>
<field name="signal_send">subflow.draft</field>
</record>
<record id="act_next_test" model="workflow.activity">
<field name="wkf_id" ref="wkf_prodlot"/>
<field name="name">next_test</field>
</record>
<record id="act_pending_test" model="workflow.activity">
<field name="wkf_id" ref="wkf_prodlot"/>
<field name="name">pending_test</field>
<field name="kind">subflow</field>
<field name="subflow_id" ref="nan_quality_control.wkf_qc_test"/>
<field name="action">action_wofkflow_pending_test()</field>
</record>
<record id="act_valid" model="workflow.activity">
<field name="wkf_id" ref="wkf_prodlot"/>
<field name="name">valid</field>
<field name="kind">subflow</field>
<field name="subflow_id" ref="nan_quality_control.wkf_qc_test"/>
<field name="action">action_wofkflow_valid()</field>
</record>
<record id="act_test_failed" model="workflow.activity">
<field name="wkf_id" ref="wkf_prodlot"/>
<field name="name">test_failed</field>
<field name="kind">subflow</field>
<field name="subflow_id" ref="nan_quality_control.wkf_qc_test"/>
<field name="action">action_wofkflow_test_failed()</field>
</record>
<record id="act_cancel" model="workflow.activity">
<field name="wkf_id" ref="wkf_prodlot"/>
<field name="name">cancel</field>
<field name="kind">function</field>
<field name="action">action_wofkflow_cancel()</field>
</record>
<!-- Transistion -->
<record id="trans_draft_next_test" model="workflow.transition">
<field name="act_from" ref="act_draft"/>
<field name="act_to" ref="act_next_test"/>
<field name="signal">confirm</field>
</record>
<!-- Next Test Output Transitions -->
<record id="trans_next_test_pending_test" model="workflow.transition">
<field name="act_from" ref="act_next_test"/>
<field name="act_to" ref="act_pending_test"/>
<field name="condition">test_pending_test()</field>
</record>
<record id="trans_next_test_valid" model="workflow.transition">
<field name="act_from" ref="act_next_test"/>
<field name="act_to" ref="act_valid"/>
<field name="condition">test_valid()</field>
</record>
<!-- Pending Test Output Transitions -->
<record id="trans_pending_test_valid" model="workflow.transition">
<field name="act_from" ref="act_pending_test"/>
<field name="act_to" ref="act_valid"/>
<!-- <field name="condition">test_valid()</field> -->
<field name="signal">subflow.success</field>
</record>
<record id="trans_pending_test_test_failed" model="workflow.transition">
<field name="act_from" ref="act_pending_test"/>
<field name="act_to" ref="act_test_failed"/>
<field name="signal">subflow.failed</field>
</record>
<record id="trans_valid_cancel" model="workflow.transition">
<field name="act_from" ref="act_valid"/>
<field name="act_to" ref="act_cancel"/>
<field name="signal">cancel</field>
</record>
<!-- Valid Output Transitions -->
<record id="trans_valid_next_test" model="workflow.transition">
<field name="act_from" ref="act_valid"/>
<field name="act_to" ref="act_next_test"/>
<field name="signal">next_test</field>
</record>
<record id="trans_valid_pending_test" model="workflow.transition">
<field name="act_from" ref="act_valid"/>
<field name="act_to" ref="act_pending_test"/>
<field name="signal">subflow.draft</field>
</record>
<record id="trans_valid_cancel" model="workflow.transition">
<field name="act_from" ref="act_valid"/>
<field name="act_to" ref="act_cancel"/>
<field name="signal">cancel</field>
</record>
<!-- Test Failed Output Transitions -->
<record id="trans_test_failed_pending_test" model="workflow.transition">
<field name="act_from" ref="act_test_failed"/>
<field name="act_to" ref="act_pending_test"/>
<field name="signal">subflow.draft</field>
</record>
<record id="trans_test_failed_cancel" model="workflow.transition">
<field name="act_from" ref="act_test_failed"/>
<field name="act_to" ref="act_cancel"/>
<field name="signal">cancel</field>
</record>
<!-- Cancel Output Transitions -->
<record id="trans_cancel_draft" model="workflow.transition">
<field name="act_from" ref="act_cancel"/>
<field name="act_to" ref="act_draft"/>
<field name="signal">draft</field>
</record>
</data>
</openerp>

109
product.py Normal file
View File

@ -0,0 +1,109 @@
##############################################################################
#
# Copyright (c) 2010-2012 NaN Projectes de Programari Lliure, S.L.
# All Rights Reserved.
# http://www.NaN-tic.com
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU Affero General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from osv import osv, fields
class product_qc_trigger_template(osv.osv):
'''
Model to configure Quality Control Templates/Tests triggers by Product.
Define the template to use for a trigger, ordering it by sequence.
'''
_name = 'product.qc.trigger.template'
_description = 'Quality Control Template Triggers by Product'
_order = 'product_id, company_id, sequence'
_columns = {
'product_id': fields.many2one('product.product', 'Product',
required=True),
'sequence': fields.integer('Sequence', required=True),
'trigger_id': fields.many2one('qc.trigger', 'Trigger', required=True,
help="The Quality Control Trigger Tag which defines when must "
"to be created a Test (using the specified template) for a "
"Production Lot of this Product."),
'template_type': fields.selection([
('generic', 'Generic'),
('related', 'Specific'),
], "Template's Type", required=True),
'template_id': fields.many2one('qc.test.template', 'Template',
domain="[('type','=',template_type)]", required=True,
help="The Quality Control Template to use."),
'company_id': fields.many2one('res.company', 'Company'),
}
_defaults = {
'sequence': 0,
}
_sql_constraints = [
('product_trigger_type_company_uniq',
'unique (product_id, trigger_id, template_type, company_id)',
"The tuple QC Trigger Tag and Template Type must be unique for "
"each Product and Company!"),
]
product_qc_trigger_template()
class product_product(osv.osv):
'''
Adds to the Product a one2many field to the model which configures Quality
Control Templates/Tests triggers.
The generic Templates get it's default value from the user's Company.
'''
_inherit = 'product.product'
_columns = {
'qc_template_trigger_ids': fields.one2many(
'product.qc.trigger.template', 'product_id', 'QC Triggers',
help="Defines when a Production Lot must to pass a Quality "
"Control Test (based on the defined Template).\n"
"It gets its default value for generic templates from the "
"Company."),
}
# product.product
def _default_qc_template_trigger_ids(self, cr, uid, context=None):
user = self.pool.get('res.users').browse(cr, uid, uid, context)
res = []
for generic_trigger in user.company_id.qc_template_trigger_ids:
res.append({
'sequence': generic_trigger.sequence,
'trigger_id': generic_trigger.trigger_id.id,
'template_type': 'generic',
'template_id': generic_trigger.template_id.id,
'company_id': user.company_id.id,
})
return res
_defaults = {
'qc_template_trigger_ids': _default_qc_template_trigger_ids,
}
product_product()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

70
product_view.xml Normal file
View File

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!-- product.qc.trigger.template -->
<record id="product_qc_trigger_template_form" model="ir.ui.view">
<field name="name">product.qc.trigger.template.form</field>
<field name="model">product.qc.trigger.template</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="QC Template Trigger by Product" col="6">
<field name="product_id" select="1"/>
<field name="sequence"/>
<field name="company_id" select="1"/>
<field name="trigger_id" select="1"/>
<field name="template_type" select="1"/>
<field name="template_id"/>
</form>
</field>
</record>
<record id="product_qc_trigger_template_tree" model="ir.ui.view">
<field name="name">product.qc.trigger.template.tree</field>
<field name="model">product.qc.trigger.template</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="QC Template Triggers by Product">
<field name="product_id"/>
<field name="sequence"/>
<field name="trigger_id"/>
<field name="template_type"/>
<field name="template_id"/>
<field name="company_id"/>
</tree>
</field>
</record>
<!-- product.product -->
<record id="product_prodlot_qc_form" model="ir.ui.view">
<field name="name">product.prodlot.quality_control.form</field>
<field name="model">product.product</field>
<field name="type">form</field>
<field name="inherit_id" ref="stock.view_normal_stock_property_form"/>
<field name="arch" type="xml">
<group name="lot" position="after">
<group name="lot_qc" colspan="2" col="2" groups="base.group_extended">
<separator string="Quality Control Triggers" colspan="2"/>
<field name="qc_template_trigger_ids" nolabel="1" colspan="2">
<tree string="Quality Control Triggers" editable="bottom">
<field name="sequence"/>
<field name="trigger_id"/>
<field name="template_type"/>
<field name="template_id"/>
<field name="company_id"/>
</tree>
<form string="Quality Control Trigger" col="6">
<field name="company_id" select="1"/>
<newline/>
<field name="trigger_id" select="1"/>
<field name="template_type" select="1"/>
<field name="template_id"/>
</form>
</field>
</group>
</group>
</field>
</record>
</data>
</openerp>

46
quality_control.py Normal file
View File

@ -0,0 +1,46 @@
##############################################################################
#
# Copyright (c) 2010-2012 NaN Projectes de Programari Lliure, S.L.
# All Rights Reserved.
# http://www.NaN-tic.com
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU Affero General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from osv import osv, fields
class qc_trigger(osv.osv):
_name = 'qc.trigger'
_description = 'Quality Control Trigger Tag'
_columns = {
'name':fields.char('Name', size=128, required=True),
}
_sql_constraints = [
('name_uniq', 'unique (name)',
"The Name of the Quality Control Trigger Tags must be unique!"),
]
qc_trigger()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

53
quality_control_view.xml Normal file
View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<openerp>
<data>
<!-- qc.trigger -->
<record id="qc_trigger_form" model="ir.ui.view">
<field name="name">qc.trigger.form</field>
<field name="model">qc.trigger</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Trigger Tag">
<field name="name" select="1"/>
</form>
</field>
</record>
<record id="qc_trigger_tree" model="ir.ui.view">
<field name="name">qc.trigger.tree</field>
<field name="model">qc.trigger</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Trigger Tags">
<field name="name"/>
</tree>
</field>
</record>
<record id="act_trigger_tag_view" model="ir.actions.act_window">
<field name="name">Trigger Tags</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">qc.trigger</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem id="menu_action_trigger_tag"
action="act_trigger_tag_view"
parent="nan_quality_control.qc_menu_config" sequence="50"/>
<!-- qc.test -->
<record id="action_qc_test_prodlot_view" model="ir.actions.act_window">
<field name="name">Production Lot Tests</field>
<field name="res_model">qc.test</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('object_id','like','stock.production.lot,')]</field>
</record>
<menuitem id="qc_test_prodlot_menu" action="action_qc_test_prodlot_view"
name="Production Lot Tests"
parent="nan_quality_control.qc_test_menu"/>
</data>
</openerp>

View File

@ -0,0 +1,10 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
"access_qc_trigger_all","qc.trigger all","model_qc_trigger",,1,0,0,0
"access_company_qc_trigger_template_employee","res.company.qc.trigger.template employee","model_res_company_qc_trigger_template","base.group_user",1,0,0,0
"access_company_qc_trigger_template_stock_user","res.company.qc.trigger.template stock user","model_res_company_qc_trigger_template","stock.group_stock_user",1,0,0,0
"access_company_qc_trigger_template_stock_manager","res.company.qc.trigger.template stock manager","model_res_company_qc_trigger_template","stock.group_stock_manager",1,1,1,1
"access_company_qc_trigger_template_qc_manager","res.company.qc.trigger.template qc manager","model_res_company_qc_trigger_template","nan_quality_control.group_quality_control_manager",1,1,1,1
"access_product_qc_trigger_template_employee","product.qc.trigger.template employee","model_product_qc_trigger_template","base.group_user",1,0,0,0
"access_product_qc_trigger_template_stock_user","product.qc.trigger.template stock user","model_product_qc_trigger_template","stock.group_stock_user",1,0,0,0
"access_product_qc_trigger_template_stock_manager","product.qc.trigger.template stock manager","model_product_qc_trigger_template","stock.group_stock_manager",1,1,1,1
"access_product_qc_trigger_template_qc_manager","product.qc.trigger.template qc manager","model_product_qc_trigger_template","nan_quality_control.group_quality_control_manager",1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_qc_trigger_all qc.trigger all model_qc_trigger 1 0 0 0
3 access_company_qc_trigger_template_employee res.company.qc.trigger.template employee model_res_company_qc_trigger_template base.group_user 1 0 0 0
4 access_company_qc_trigger_template_stock_user res.company.qc.trigger.template stock user model_res_company_qc_trigger_template stock.group_stock_user 1 0 0 0
5 access_company_qc_trigger_template_stock_manager res.company.qc.trigger.template stock manager model_res_company_qc_trigger_template stock.group_stock_manager 1 1 1 1
6 access_company_qc_trigger_template_qc_manager res.company.qc.trigger.template qc manager model_res_company_qc_trigger_template nan_quality_control.group_quality_control_manager 1 1 1 1
7 access_product_qc_trigger_template_employee product.qc.trigger.template employee model_product_qc_trigger_template base.group_user 1 0 0 0
8 access_product_qc_trigger_template_stock_user product.qc.trigger.template stock user model_product_qc_trigger_template stock.group_stock_user 1 0 0 0
9 access_product_qc_trigger_template_stock_manager product.qc.trigger.template stock manager model_product_qc_trigger_template stock.group_stock_manager 1 1 1 1
10 access_product_qc_trigger_template_qc_manager product.qc.trigger.template qc manager model_product_qc_trigger_template nan_quality_control.group_quality_control_manager 1 1 1 1

18
security/security.xml Normal file
View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="company_qc_trigger_template_rule" model="ir.rule">
<field name="name">Quality Control Template Triggers by Company multi-company</field>
<field model="ir.model" name="model_id" ref="model_res_company_qc_trigger_template"/>
<field eval="True" name="global"/>
<field name="domain_force">[('company_id','child_of',[user.company_id.id])]</field>
</record>
<record id="product_qc_trigger_template_rule" model="ir.rule">
<field name="name">Quality Control Template Triggers by Product multi-company</field>
<field model="ir.model" name="model_id" ref="model_product_qc_trigger_template"/>
<field eval="True" name="global"/>
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
</record>
</data>
</openerp>

301
stock.py Normal file
View File

@ -0,0 +1,301 @@
##############################################################################
#
# Copyright (c) 2012 NaN Projectes de Programari Lliure, S.L.
# All Rights Reserved.
# http://www.NaN-tic.com
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU Affero General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from osv import osv, fields
import netsvc
class stock_production_lot_qc_trigger_test(osv.osv):
'''
Model that defines the Quality Control Tests which a Production Lot must
to pass in certain situations defined by the Trigger Tag.
'''
_name = 'stock.production.lot.qc.trigger.test'
_description = 'Quality Control Test Triggers by Lot'
_order = 'prodlot_id, sequence'
def name_get(self, cr, uid, ids, context=None):
res = []
for trigger in self.read(cr, uid, ids, ['trigger_id', 'template_type'],
context):
name = trigger['trigger_id'][1] + ", " + trigger['template_type']
res.append((trigger['id'], name))
return res
# stock.production.lot.qc.trigger.test
def _calc_test_state_data(self, cr, uid, ids, fieldnames, args,
context=None):
"""
Calcs the value of fields 'test_approved' and 'test_success'.
The 'test_approved' field will be true if its test is in 'success' or
'failed' final states, and the fields 'test_success' will be True only
if its test is in 'success' state.
"""
res = {}
for lot_trigger in self.browse(cr, uid, ids, context):
res[lot_trigger.id] = {}.fromkeys(fieldnames, False)
if (not lot_trigger.test_id or
lot_trigger.test_id.state not in ('success', 'failed')):
continue
if 'test_approved' in fieldnames:
res[lot_trigger.id]['test_approved'] = True
if ('test_success' in fieldnames and
lot_trigger.test_id.state == 'success'):
res[lot_trigger.id]['test_success'] = True
return res
_columns = {
'prodlot_id': fields.many2one('stock.production.lot', 'Lot',
required=True),
'sequence': fields.integer('Sequence', required=True),
'trigger_id': fields.many2one('qc.trigger', 'Trigger', required=True,
help="The Quality Control Trigger Tag which defines when must "
"to be created a Test (using the specified template) for a "
"Production Lot of this Product."),
'template_type': fields.selection([
('generic', 'Generic'),
('related', 'Specific'),
], "Template's Type", required=True),
'test_id': fields.many2one('qc.test', 'Test', required=True,
domain="[('test_template_id.type','=',template_type)]"),
'test_approved': fields.function(_calc_test_state_data, method=True,
type='boolean', string="Test approved?", multi='test_state'),
'test_success': fields.function(_calc_test_state_data, method=True,
type='boolean', string="Test success?", multi='test_state'),
}
_defaults = {
'sequence': 0,
}
_sql_constraints = [
('prodlot_trigger_type_uniq',
'unique (prodlot_id, trigger_id, template_type)',
"The tuple QC Trigger Tag and Template Type must be unique for "
"each Production Lot!"),
]
stock_production_lot_qc_trigger_test()
class stock_production_lot(osv.osv):
'''
Adds to the Lot an 'state' field and a workflow to manage its status related
to the Quality test that has passed.
It also adds one2many field to the model which defines the Quality Control
Tests that it must to pass.
'''
_inherit = 'stock.production.lot'
# stock.production.lot
def _get_available_states(self, cr, uid, context=None):
"""
Returns the list of available states for Lot objects. It is defined as
a function to make easier to extend the list of states.
"""
return [
('draft', 'Draft'),
('pending_test', 'Waiting QC Test'),
('valid', 'Valid'),
('test_failed', 'QC Test Failed'),
('cancel', 'Cancelled'),
]
# stock.production.lot
def get_available_states(self, cr, uid, context=None):
"""
Returns the list of available states for Lot objects.
It call's the function '_get_available_states' which could be
reimplemented to extend or modify the list of available states.
@see: _get_available_states
"""
return self._get_available_states(cr, uid, context)
# stock.production.lot
def _calc_test_trigger_ro_ids(self, cr, uid, ids, fieldname, args,
context=None):
res = {}
for lot_triggers in self.read(cr, uid, ids, ['qc_test_trigger_ids'],
context):
res[lot_triggers['id']] = lot_triggers['qc_test_trigger_ids']
return res
_columns = {
# adds the 'readonly' and 'states' attributes
'product_id': fields.many2one('product.product', 'Product',
required=True, readonly=True,
states={'draft': [('readonly', False)]}),
'state': fields.selection(get_available_states,
'State', required=True, readonly=True),
# 'state': fields.selection(
# lambda self, cr, uid, context=None: self.get_available_states,
# 'State', required=True, readonly=True),
'qc_test_trigger_ids': fields.one2many(
'stock.production.lot.qc.trigger.test', 'prodlot_id',
'QC Tests', help="Defines the Quality Control Tests that this "
"Production Lot must to pass in certain situations defined by "
"the Trigger Tag."),
# Read Only version of previous field. Better solutions are wellcome
'qc_test_trigger_ro_ids': fields.function(_calc_test_trigger_ro_ids,
method=True, type='one2many', string='QC Tests',
relation='stock.production.lot.qc.trigger.test'),
'current_qc_test_trigger_id': fields.many2one(
'stock.production.lot.qc.trigger.test',
'Current QC Test Trigger',
domain="[('id','in',[x.id for x in qc_test_trigger_ids])]", readonly=True,
states={'valid':[('readonly',False)]}),
'current_qc_test_id': fields.related('current_qc_test_trigger_id',
'test_id', type='many2one', relation='qc.test',
string="Current QC Test", readonly=True),
}
_defaults = {
'state': 'draft',
}
# stock.production.lot
def action_wofkflow_draft(self, cr, uid, ids, context=None):
"""
Sets the State of Lot to 'Draft'
"""
self.write(cr, uid, ids, {'state': 'draft'}, context)
return True
# stock.production.lot
def test_pending_test(self, cr, uid, ids, context=None):
"""
Checks that Production Lot has a Current Test and it is not Approved
(test is not in any final state)
"""
for prodlot in self.browse(cr, uid, ids, context):
if (not prodlot.current_qc_test_id or
prodlot.current_qc_test_trigger_id.test_approved):
return False
return True
# stock.production.lot
def action_wofkflow_pending_test(self, cr, uid, ids, context=None):
"""
Sets the State of Lot to 'Pending Test'
"""
assert len(ids) == 1, "Unexpected number of Lot IDs in function of " \
"'Pending Test' workflow step."
self.write(cr, uid, ids, {'state': 'pending_test'}, context)
return self.browse(cr, uid, ids[0], context).current_qc_test_id.id
# stock.production.lot
def test_valid(self, cr, uid, ids, context=None):
"""
Checks that Production Lot doesn't has Current Test or it is in
'Success' state.
"""
for prodlot in self.browse(cr, uid, ids, context):
if (prodlot.current_qc_test_id and
prodlot.current_qc_test_id.state!='success'):
return False
return True
# stock.production.lot
def action_wofkflow_valid(self, cr, uid, ids, context=None):
"""
Sets the State of Lot to 'Valid' and, for Lots with Current Test,
search the next Test with the same Trigger (ordered by Test Trigger
sequence) and, if it exists, sets as 'Current QC Test Trigger' and
move the workflow of Lot to 'Next Test' step.
"""
assert len(ids) == 1, "Unexpected number of Lot IDs in function of " \
"'Pending Test' workflow step."
trigger_proxy = self.pool.get('stock.production.lot.qc.trigger.test')
wf_service = netsvc.LocalService("workflow")
prodlot = self.browse(cr, uid, ids[0], context)
if not prodlot.current_qc_test_id:
return True
current_trigger = prodlot.current_qc_test_trigger_id
next_trigger_ids = trigger_proxy.search(cr, uid, [
('prodlot_id', '=', prodlot.id),
('id', '!=', current_trigger.id),
('sequence', '>=', current_trigger.sequence),
('trigger_id', '=', current_trigger.trigger_id.id),
], limit=1, context=context)
if next_trigger_ids:
prodlot_w_next_test.append(prodlot.id)
self.write(cr, uid, prodlot.id, {
'current_qc_test_trigger_id': next_trigger_ids[0],
'state': 'valid',
}, context)
wf_service.trg_validate(uid, 'stock.production.lot',
next_trigger_ids[0], 'next_test', cr)
return True
self.write(cr, uid, ids, {'state': 'valid'}, context)
return current_trigger.test_id.id
# stock.production.lot
def action_wofkflow_test_failed(self, cr, uid, ids, context=None):
"""
Sets the State of Lot to 'Test Failed' and returns the ID of current
Test
"""
assert len(ids) == 1, "Unexpected number of Lot IDs in function of " \
"'Pending Test' workflow step."
prodlot = self.browse(cr, uid, ids[0], context)
self.write(cr, uid, ids, {'state': 'test_failed'}, context)
return prodlot.current_qc_test_trigger_id.test_id.id
# stock.production.lot
def action_wofkflow_cancel(self, cr, uid, ids, context=None):
"""
Sets the State of Lot to 'Cancel' and leave empty the 'Current QC Test
Trigger' field.
"""
self.write(cr, uid, ids, {
'current_qc_test_trigger_id': False,
'state': 'cancel',
}, context)
return True
stock_production_lot()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

126
stock_view.xml Normal file
View File

@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!-- stock.production.lot.qc.trigger.test -->
<record id="prodlot_qc_trigger_test_form" model="ir.ui.view">
<field name="name">stock.production.lot.qc.trigger.test.form</field>
<field name="model">stock.production.lot.qc.trigger.test</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="QC Test Trigger by Lot">
<field name="prodlot_id" select="1"/>
<field name="sequence"/>
<field name="trigger_id" select="1"/>
<field name="template_type" select="1"/>
<field name="test_id"/>
<group colspan="2" col="4">
<field name="test_approved"/>
<field name="test_success"/>
</group>
</form>
</field>
</record>
<record id="prodlot_qc_trigger_test_tree" model="ir.ui.view">
<field name="name">stock.production.lot.qc.trigger.test.tree</field>
<field name="model">stock.production.lot.qc.trigger.test</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="QC Test Triggers by Lot">
<field name="prodlot_id"/>
<field name="sequence"/>
<field name="trigger_id"/>
<field name="template_type"/>
<field name="test_id"/>
<field name="test_approved"/>
<field name="test_success"/>
</tree>
</field>
</record>
<!-- stock.production.lot -->
<record id="view_production_lot_qc_form" model="ir.ui.view">
<field name="name">stock.production.lot.quality_control.form</field>
<field name="model">stock.production.lot</field>
<field name="type">form</field>
<field name="inherit_id" ref="stock.view_production_lot_form" />
<field name="arch" type="xml">
<notebook position="inside">
<page string="Quality Control">
<separator string="Quality Control Triggers" colspan="4"/>
<field name="qc_test_trigger_ids" nolabel="1" colspan="4" groups="nan_quality_control.group_quality_control_manager">
<tree string="Quality Control Triggers" editable="bottom">
<field name="sequence"/>
<field name="trigger_id"/>
<field name="template_type"/>
<field name="test_id"/>
<field name="test_approved"/>
<field name="test_success"/>
</tree>
</field>
<field name="qc_test_trigger_ro_ids" nolabel="1" colspan="4" groups="nan_quality_control.group_quality_control_user">
<tree string="Quality Control Triggers">
<field name="sequence"/>
<field name="trigger_id"/>
<field name="template_type"/>
<field name="test_id"/>
<field name="test_approved"/>
<field name="test_success"/>
</tree>
</field>
<field name="current_qc_test_trigger_id" groups="nan_quality_control.group_quality_control_manager"/>
<field name="current_qc_test_id"/>
</page>
</notebook>
<form position="inside">
<group col="7" colspan="4">
<field name="state"/>
<button name="draft" states="cancel" string="Set To Draft" icon="gtk-new"/>
<button name="confirm" states="draft" string="Confirm" icon="gtk-ok"/>
<button name="next_test" states="valid" string="Next Test" icon="gtk-ok" />
<button name="cancel" states="pending_test,valid,test_failed" string="Cancel Prodlot" icon="gtk-cancel" />
</group>
</form>
</field>
</record>
<record id="view_production_lot_qc_tree" model="ir.ui.view">
<field name="name">stock.production.lot.quality_control.tree</field>
<field name="model">stock.production.lot</field>
<field name="type">tree</field>
<field name="inherit_id" ref="stock.view_production_lot_tree" />
<field name="arch" type="xml">
<field name="date" position="after">
<field name="current_qc_test_id"/>
<field name="state"/>
</field>
</field>
</record>
<record id="search_product_lot_filter" model="ir.ui.view">
<field name="name">stock.production.lot.quality_control.filter</field>
<field name="model">stock.production.lot</field>
<field name="type">search</field>
<field name="inherit_id" ref="stock.search_product_lot_filter"/>
<field name="arch" type="xml">
<filter string="Product" position="after">
<filter string="State" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/>
</filter>
</field>
</record>
<!--<record id="action_prodlot_test_popup" model="ir.actions.act_window">
<field name="name">Tests</field>
<field name="src_model">stock.production.lot</field>
<field name="res_model">qc.test</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('id', 'in', [x.test_id.id for x in qc_test_trigger_ids])]</field>
</record>-->
</data>
</openerp>