quality_control: Total refactorization with new API, README files, and new concepts. * Triggers for product category * ACLs * Tolerances in questions * one2many copyable * Fix some views * Error on same tolerance * Colors on inspection lines * Unify inspection header data assignment in set_test method * key name in set_test * Change icon set

This commit is contained in:
Pedro M. Baeza
2014-12-10 23:35:21 +01:00
committed by Antoni Marroig Campomar
parent 2cea433a63
commit cf4646db3c
32 changed files with 2189 additions and 2281 deletions

View File

@@ -0,0 +1,44 @@
Quality control management for Odoo
===================================
This module provides a generic infrastructure for quality tests. The idea is
that it can be later reused for doing quality inspections on production lots
or any other area of the company.
Definitions
-----------
* Question: The thing to be checked. We have two types of questions:
* Qualitative: The result is a description, color, yes, no...
* Quantitative: The result must be within a range.
* Possible values: The values chosen in qualitative questions.
* Test: The set of questions to be used in inspections.
* Once these values are set, we define the inspection.
We have a *generic* test that can be applied to any model: shipments,
invoices or product, or a *test related*, making it specific to a particular
product and that eg apply whenever food is sold or when creating a batch.
Once these parameters are set, we can just pass the test. We create a
new inspection, selecting a relationship with the model (sale, stock move...),
and pressing "Select test" button to choose the test to pass. Then, you must
fill the lines depending on the chosen test.
The complete inspection workflow is:
Draft -> Confirmed -> Success
|
| -> Failure (Pending approval) -> Approved
Based on the nan_quality_control_* modules from NaN·tic.
Contributors
------------
* Pedro M. Baeza <pedro.baeza@serviciobaeza.com>
* Oihane Crucelaegui <oihanecrucelaegi@avanzosc.es>
* Ana Juaristi <ajuaristio@gmail.com>

View File

@@ -1,31 +1,6 @@
# -*- encoding: utf-8 -*-
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2010 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 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 General Public License for more details.
#
# You should have received a copy of the GNU 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.
#
# For copyright and license notices, see __openerp__.py file in root directory
##############################################################################
from . import models

View File

@@ -1,58 +1,52 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2010 NaN Projectes de Programari Lliure, S.L.
# All Rights Reserved.
# http://www.NaN-tic.com
# Copyright (c)
# 2010 NaN Projectes de Programari Lliure, S.L. (http://www.NaN-tic.com)
# 2014 Serv. Tec. Avanzados - Pedro M. Baeza (http://www.serviciosbaeza.com)
# 2014 AvanzOsc (http://www.avanzosc.es)
#
# 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 3 of the License, or
# (at your option) any later version.
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by 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.
#
# 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 General Public License for more details.
#
# You should have received a copy of the GNU 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.
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
"name": "Quality Control",
"version": "0.1",
"author": "NaN·tic",
"name": "Quality control",
"version": "1.0",
"author": "OdooMRP team",
"website": "http://www.odoomrp.com",
"contributors": [
"Pedro M. Baeza <pedro.baeza@serviciosbaeza.com",
"Oihane Crucelaegui <oihanecrucelaegi@avanzosc.es>",
"Ana Juaristi <ajuaristio@gmail.com>",
],
"category": "Generic Modules/Others",
"summary": "Quality control",
"description": """
This module provides a generic infrastructure for quality tests. The idea is
that it can be later be reused for doing quality tests in production lots but
also in any other areas a company may desire.
Developed for Trod y Avia, S.L.""",
"category": "Quality control",
"depends": [
'product'
'product',
],
"data": [
'data/quality_control_data.xml',
'security/quality_control_security.xml',
'security/ir.model.access.csv',
'workflow/test_workflow.xml',
'wizard/qc_test_wizard_view.xml',
'views/quality_control_view.xml',
'views/qc_menus.xml',
'views/qc_inspection_view.xml',
'views/qc_test_category_view.xml',
'views/qc_test_view.xml',
'views/qc_trigger_view.xml',
'views/product_template_view.xml',
'views/product_category_view.xml',
],
"installable": True,
}

View File

@@ -1,20 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="True">
<!-- res.partner.title -->
<record id="qc_test_template_category_generic" model="qc.test.template.category">
<data noupdate="1">
<record id="qc_test_template_category_generic" model="qc.test.category">
<field name="name">Generic</field>
</record>
<record id="qc_test_template_category_referenced" model="qc.test.template.category">
<record id="qc_test_template_category_referenced" model="qc.test.category">
<field name="name">Referenced</field>
</record>
</data>
<data>
<record model="ir.module.category" id="module_category_quality_control">
<field name="name">Quality Control</field>
<!-- <field name="description">Helps you handle your quotations, sale orders and invoicing.</field> -->
<!-- <field name="sequence">2</field> -->
<record id="seq_type_qc_inspection" model="ir.sequence.type">
<field name="name">Quality inspection</field>
<field name="code">qc.inspection</field>
</record>
<record id="seq_qc_inspection" model="ir.sequence">
<field name="name">Quality inspection</field>
<field name="code">qc.inspection</field>
<field name="prefix">QC-</field>
<field name="padding">6</field>
</record>
</data>
</openerp>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,31 +1,13 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2010 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 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 General Public License for more details.
#
# You should have received a copy of the GNU 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.
#
# For copyright and license notices, see __openerp__.py file in root directory
##############################################################################
from . import quality_control
from . import qc_trigger
from . import qc_trigger_line
from . import qc_test_category
from . import qc_test
from . import qc_inspection
from . import product_product
from . import product_template
from . import product_category

View File

@@ -0,0 +1,14 @@
# -*- coding: utf-8 -*-
##############################################################################
# For copyright and license notices, see __openerp__.py file in root directory
##############################################################################
from openerp import models, fields
class ProductCategory(models.Model):
_inherit = "product.category"
qc_triggers = fields.One2many(
comodel_name="qc.trigger.product_category_line",
inverse_name="product_category",
string="Quality control triggers")

View File

@@ -0,0 +1,13 @@
# -*- coding: utf-8 -*-
##############################################################################
# For copyright and license notices, see __openerp__.py file in root directory
##############################################################################
from openerp import models, fields
class ProductProduct(models.Model):
_inherit = "product.product"
qc_triggers = fields.One2many(
comodel_name="qc.trigger.product_line", inverse_name="product",
string="Quality control triggers")

View File

@@ -0,0 +1,14 @@
# -*- coding: utf-8 -*-
##############################################################################
# For copyright and license notices, see __openerp__.py file in root directory
##############################################################################
from openerp import models, fields
class ProductTemplate(models.Model):
_inherit = "product.template"
qc_triggers = fields.One2many(
comodel_name="qc.trigger.product_template_line",
inverse_name="product_template",
string="Quality control triggers")

View File

@@ -0,0 +1,293 @@
# -*- coding: utf-8 -*-
##############################################################################
# For copyright and license notices, see __openerp__.py file in root directory
##############################################################################
from openerp import models, fields, api, exceptions, _
class QcInspection(models.Model):
_name = 'qc.inspection'
_inherit = ['mail.thread', 'ir.needaction_mixin']
@api.one
@api.depends('inspection_lines', 'inspection_lines.success')
def _success(self):
self.success = all([x.success for x in self.inspection_lines])
@api.multi
def _links_get(self):
link_obj = self.env['res.request.link']
return [(r.object, r.name) for r in link_obj.search([])]
@api.one
@api.depends('object_id')
def _get_product(self):
if self.object_id and self.object_id._name == 'product.product':
self.product = self.object_id
else:
self.product = False
@api.one
@api.depends('object_id')
def _get_qty(self):
self.qty = 1.0
name = fields.Char(
string='Inspection number', required=True, default='/', select=True,
readonly=True, states={'draft': [('readonly', False)]}, copy=False)
date = fields.Datetime(
string='Date', required=True, readonly=True, copy=False,
default=fields.Datetime.now(),
states={'draft': [('readonly', False)]}, select=True)
object_id = fields.Reference(
string='Reference', selection=_links_get, readonly=True,
states={'draft': [('readonly', False)]}, ondelete="set null")
product = fields.Many2one(
comodel_name="product.product", compute="_get_product", store=True,
help="Product associated with the inspection")
qty = fields.Float(string="Quantity", compute="_get_qty", store=True)
test = fields.Many2one(
comodel_name='qc.test', string='Test', readonly=True, select=True)
inspection_lines = fields.One2many(
comodel_name='qc.inspection.line', inverse_name='inspection_id',
string='Inspection lines', readonly=True,
states={'ready': [('readonly', False)]})
internal_notes = fields.Text(string='Internal notes')
external_notes = fields.Text(
string='External notes',
states={'success': [('readonly', True)],
'failed': [('readonly', True)]})
state = fields.Selection(
[('draft', 'Draft'),
('ready', 'Ready'),
('waiting', 'Waiting supervisor approval'),
('success', 'Quality success'),
('failed', 'Quality failed'),
('canceled', 'Cancelled')],
string='State', readonly=True, default='draft')
success = fields.Boolean(
compute="_success", string='Success',
help='This field will be marked if all tests have been succeeded.',
store=True)
auto_generated = fields.Boolean(
string='Auto-generated', readonly=True, copy=False,
help='If an inspection is auto-generated, it can be cancelled nor '
'removed')
company_id = fields.Many2one(
comodel_name='res.company', string='Company', readonly=True,
states={'draft': [('readonly', False)]},
default=lambda self: self.env['res.company']._company_default_get(
'qc.inspection'))
@api.model
def create(self, vals):
if vals.get('name', '/') == '/':
vals['name'] = self.env['ir.sequence'].get('qc.inspection')
return super(QcInspection, self).create(vals)
@api.multi
def unlink(self):
for inspection in self:
if inspection.auto_generated:
raise exceptions.Warning(
_("You cannot remove an auto-generated inspection"))
if inspection.state != 'draft':
raise exceptions.Warning(
_("You cannot remove an inspection that it's not in draft "
"state"))
return super(QcInspection, self).unlink()
@api.multi
def action_draft(self):
self.write({'state': 'draft'})
@api.multi
def action_todo(self):
for inspection in self:
if not inspection.test:
raise exceptions.Warning(
_("You must set the test to perform first."))
self.write({'state': 'ready'})
@api.multi
def action_confirm(self):
for inspection in self:
for line in inspection.inspection_lines:
if line.question_type == 'qualitative':
if not line.qualitative_value:
raise exceptions.Warning(
_("You should provide an answer for all "
"quantitative questions."))
else:
if not line.uom_id:
raise exceptions.Warning(
_("You should provide a unit of measure for "
"qualitative questions."))
if inspection.success:
inspection.state = 'success'
else:
inspection.state = 'waiting'
@api.multi
def action_approve(self):
for inspection in self:
if inspection.success:
inspection.state = 'success'
else:
inspection.state = 'failed'
@api.multi
def action_cancel(self):
self.write({'state': 'canceled'})
@api.multi
def set_test(self, test, force_fill=False):
for inspection in self:
header = self._prepare_inspection_header(
inspection.object_id, test)
del header['state'] # don't change current status
del header['auto_generated'] # don't change auto_generated flag
inspection.write(header)
self.inspection_lines.unlink()
inspection.inspection_lines = inspection._prepare_inspection_lines(
test, force_fill=force_fill)
@api.multi
def _make_inspection(self, object_ref, test):
"""Overridable hook method for creating inspection from test.
:param object_ref: Object instance
:param test: Test instance
:return: Inspection object
"""
inspection = self.create(self._prepare_inspection_header(
object_ref, test))
inspection.set_test(test)
return inspection
@api.multi
def _prepare_inspection_header(self, object_ref, test):
"""Overridable hook method for preparing inspection header.
:param object_ref: Object instance
:param test: Test instance
:return: List of values for creating the inspection
"""
return {
'object_id': object_ref and '%s,%s' % (object_ref._name,
object_ref.id) or False,
'state': 'ready',
'test': test.id,
'auto_generated': True,
}
@api.multi
def _prepare_inspection_lines(self, test, force_fill=False):
new_data = []
for line in test.test_lines:
data = self._prepare_inspection_line(
test, line, fill=test.fill_correct_values or force_fill)
new_data.append((0, 0, data))
return new_data
@api.multi
def _prepare_inspection_line(self, test, line, fill=None):
data = {
'name': line.name,
'test_line': line.id,
'notes': line.notes,
'min_value': line.min_value,
'max_value': line.max_value,
'test_uom_id': line.uom_id.id,
'uom_id': line.uom_id.id,
'question_type': line.type,
'possible_ql_values': [x.id for x in line.ql_values]
}
if fill:
if line.type == 'qualitative':
# Fill with the first correct value found
for value in line.ql_values:
if value.ok:
data['qualitative_value'] = value.id
break
else:
# Fill with a value inside the interval
data['quantitative_value'] = (line.min_value +
line.max_value) * 0.5
return data
class QcInspectionLine(models.Model):
_name = 'qc.inspection.line'
_description = "Quality control inspection line"
@api.one
@api.depends('question_type', 'uom_id', 'test_uom_id', 'max_value',
'min_value', 'quantitative_value', 'qualitative_value',
'possible_ql_values')
def quality_test_check(self):
if self.question_type == 'qualitative':
self.success = self.qualitative_value.ok
else:
if self.uom_id.id == self.test_uom_id.id:
amount = self.quantitative_value
else:
amount = self.env['product.uom']._compute_qty(
self.uom_id.id, self.quantitative_value,
self.test_uom_id.id)
self.success = self.max_value >= amount >= self.min_value
@api.one
@api.depends('possible_ql_values', 'min_value', 'max_value', 'test_uom_id',
'question_type')
def get_valid_values(self):
if self.question_type == 'qualitative':
self.valid_values = ", ".join([x.name for x in
self.possible_ql_values if x.ok])
else:
self.valid_values = "%s-%s" % (self.min_value, self.max_value)
if self.env.ref("product.group_uom") in self.env.user.groups_id:
self.valid_values += " %s" % self.test_uom_id.name
inspection_id = fields.Many2one(
comodel_name='qc.inspection', string='Inspection')
name = fields.Char(string="Question", readonly=True)
product = fields.Many2one(
comodel_name="product.product", related="inspection_id.product",
store=True)
test_line = fields.Many2one(
comodel_name='qc.test.question', string='Test question',
readonly=True)
possible_ql_values = fields.Many2many(
comodel_name='qc.test.question.value', string='Answers')
quantitative_value = fields.Float(
'Quantitative value', digits=(16, 5),
help="Value of the result if it's a quantitative question.")
qualitative_value = fields.Many2one(
comodel_name='qc.test.question.value', string='Qualitative value',
help="Value of the result if it's a qualitative question.",
domain="[('id', 'in', possible_ql_values[0][2])]")
notes = fields.Text(string='Notes')
min_value = fields.Float(
string='Min', digits=(16, 5), readonly=True,
help="Minimum valid value if it's a quantitative question.")
max_value = fields.Float(
string='Max', digits=(16, 5), readonly=True,
help="Maximum valid value if it's a quantitative question.")
test_uom_id = fields.Many2one(
comodel_name='product.uom', string='Test UoM', readonly=True,
help="UoM for minimum and maximum values if it's a quantitative "
"question.")
test_uom_category = fields.Many2one(
comodel_name="product.uom.categ", related="test_uom_id.category_id",
store=True)
uom_id = fields.Many2one(
comodel_name='product.uom', string='UoM',
domain="[('category_id', '=', test_uom_category)]",
help="UoM of the inspection value if it's a quantitative question.")
question_type = fields.Selection(
[('qualitative', 'Qualitative'),
('quantitative', 'Quantitative')],
string='Question type', readonly=True)
valid_values = fields.Char(string="Valid values", store=True,
compute="get_valid_values")
success = fields.Boolean(
compute="quality_test_check", string="Success?", store=True)

View File

@@ -0,0 +1,95 @@
# -*- coding: utf-8 -*-
##############################################################################
# For copyright and license notices, see __openerp__.py file in root directory
##############################################################################
from openerp import models, fields, api, exceptions, _
class QcTest(models.Model):
"""A test is a group of questions to with the values that make them valid.
"""
_name = 'qc.test'
_description = 'Quality control test'
@api.multi
def _links_get(self):
link_obj = self.env['res.request.link']
return [(r.object, r.name) for r in link_obj.search([])]
active = fields.Boolean('Active', default=True)
name = fields.Char(
string='Name', required=True, translate=True, select=True)
test_lines = fields.One2many(
comodel_name='qc.test.question', inverse_name='test',
string='Questions', copy=True)
object_id = fields.Reference(
string='Reference object', selection=_links_get,)
fill_correct_values = fields.Boolean(
string='Pre-fill with correct values')
type = fields.Selection(
[('generic', 'Generic'),
('related', 'Related')],
string='Type', select=True, required=True, default='generic')
category = fields.Many2one(
comodel_name='qc.test.category', string='Category')
company_id = fields.Many2one(
comodel_name='res.company', string='Company',
default=lambda self: self.env['res.company']._company_default_get(
'qc.test'))
class QcTestQuestion(models.Model):
"""Each test line is a question with its valid value(s)."""
_name = 'qc.test.question'
_description = 'Quality control question'
_order = 'sequence, id'
@api.one
@api.constrains('ql_values')
def _check_valid_answers(self):
if self.type == 'quantitative':
return
for value in self.ql_values:
if value.ok:
return
raise exceptions.Warning(
_("There isn't any value with OK marked. You have to mark at "
"least one."))
@api.one
@api.constrains('min_value', 'max_value')
def _check_valid_range(self):
if self.type == 'qualitative':
return
if self.min_value > self.max_value:
raise exceptions.Warning(
_("Minimum value can't be higher than maximum value."))
sequence = fields.Integer(
string='Sequence', required=True, default="10")
test = fields.Many2one(comodel_name='qc.test', string='Test')
name = fields.Char(
string='Name', required=True, select=True, translate=True)
type = fields.Selection(
[('qualitative', 'Qualitative'),
('quantitative', 'Quantitative')], string='Type', required=True)
ql_values = fields.One2many(
comodel_name='qc.test.question.value', inverse_name="test_line",
string='Qualitative values', copy=True)
notes = fields.Text(string='Notes')
min_value = fields.Float(string='Min', digits=(16, 5))
max_value = fields.Float(string='Max', digits=(15, 5))
uom_id = fields.Many2one(comodel_name='product.uom', string='Uom')
class QcTestQuestionValue(models.Model):
_name = 'qc.test.question.value'
_description = 'Possible values of qualitative questions.'
test_line = fields.Many2one(
comodel_name="qc.test.question", string="Test question")
name = fields.Char(
string='Name', required=True, select=True, translate=True)
ok = fields.Boolean(
string='Correct answer?',
help="When this field is marked, the answer is considered correct.")

View File

@@ -0,0 +1,48 @@
# -*- coding: utf-8 -*-
##############################################################################
# For copyright and license notices, see __openerp__.py file in root directory
##############################################################################
from openerp import models, fields, api, exceptions, _
class QcTestTemplateCategory(models.Model):
_name = 'qc.test.category'
_description = 'Test category'
@api.one
@api.depends('name', 'parent_id')
def _get_complete_name(self):
if self.name:
names = [self.name]
parent = self.parent_id
while parent:
names.append(parent.name)
parent = parent.parent_id
self.complete_name = " / ".join(reversed(names))
else:
self.complete_name = ""
@api.constrains('parent_id')
def _check_recursion(self):
ids = self.ids
level = 100
while ids:
parents = self.search([('id', 'in', ids),
('parent_id', '!=', False)])
ids = list(set([x.parent_id.id for x in parents]))
if not level:
raise exceptions.Warning(
_('Error ! You can not create recursive categories.'))
level -= 1
name = fields.Char('Name', required=True, translate=True)
parent_id = fields.Many2one(
comodel_name='qc.test.category', string='Parent category', select=True)
complete_name = fields.Char(
compute="_get_complete_name", string='Full name')
child_ids = fields.One2many(
comodel_name='qc.test.category', inverse_name='parent_id',
string='Child categories')
active = fields.Boolean(
string='Active', default=True,
help="This field allows you to hide the category without removing it.")

View File

@@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
##############################################################################
# For copyright and license notices, see __openerp__.py file in root directory
##############################################################################
from openerp import models, fields
class QcTrigger(models.Model):
_name = 'qc.trigger'
_description = 'Quality control trigger'
name = fields.Char(string='Name', required=True, select=True,
translate=True)
active = fields.Boolean(string='Active', default=True)
company_id = fields.Many2one(
comodel_name='res.company', string='Company',
default=lambda self: self.env['res.company']._company_default_get(
'qc.test'))

View File

@@ -0,0 +1,71 @@
# -*- coding: utf-8 -*-
##############################################################################
# For copyright and license notices, see __openerp__.py file in root directory
##############################################################################
from openerp import models, fields
class QcTriggerLine(models.AbstractModel):
_name = "qc.trigger.line"
_description = "Abstract line for defining triggers"
trigger = fields.Many2one(comodel_name="qc.trigger", required=True)
test = fields.Many2one(comodel_name="qc.test", required=True)
def get_test_for_product(self, trigger, product):
"""Overridable method for getting test associated to a product.
Each inherited model will complete this module to make the search by
product, template or category.
:param trigger: Trigger instance.
:param product: Product instance.
:return: Set of tests that matches to the given product and trigger.
"""
return set()
class QcTriggerProductCategoryLine(models.Model):
_inherit = "qc.trigger.line"
_name = "qc.trigger.product_category_line"
product_category = fields.Many2one(comodel_name="product.category")
def get_test_for_product(self, trigger, product):
tests = super(QcTriggerProductCategoryLine,
self).get_test_for_product(trigger, product)
category = product.categ_id
while category:
for trigger_line in category.qc_triggers:
if trigger_line.trigger.id == trigger.id:
tests.add(trigger_line.test)
category = category.parent_id
return tests
class QcTriggerProductTemplateLine(models.Model):
_inherit = "qc.trigger.line"
_name = "qc.trigger.product_template_line"
product_template = fields.Many2one(comodel_name="product.template")
def get_test_for_product(self, trigger, product):
tests = super(QcTriggerProductTemplateLine,
self).get_test_for_product(trigger, product)
for trigger_line in product.product_tmpl_id.qc_triggers:
if trigger_line.trigger.id == trigger.id:
tests.add(trigger_line.test)
return tests
class QcTriggerProductLine(models.Model):
_inherit = "qc.trigger.line"
_name = "qc.trigger.product_line"
product = fields.Many2one(comodel_name="product.product")
def get_test_for_product(self, trigger, product):
tests = super(QcTriggerProductLine, self).get_test_for_product(
trigger, product)
for trigger_line in product.qc_triggers:
if trigger_line.trigger.id == trigger.id:
tests.add(trigger_line.test)
return tests

View File

@@ -1,638 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2010 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 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 General Public License for more details.
#
# You should have received a copy of the GNU 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 openerp.tools.translate import _
from openerp.osv import orm, fields
import time
class QcProofMethod(orm.Model):
"""
This model stores a method for doing a test. Examples of methods are:
"Eu.Pharm.v.v. (2.2.32)" or "HPLC"
"""
_name = 'qc.proof.method'
_description = 'Method'
_columns = {
'name': fields.char('Name', size=100, required=True, select="1",
translate=True),
'active': fields.boolean('Active'),
}
_defaults = {
'active': True,
}
class QcPosibleValue(orm.Model):
"""
This model stores all possible values of qualitative proof.
"""
_name = 'qc.posible.value'
_columns = {
'name': fields.char('Name', size=200, required=True, select="1",
translate=True),
'active': fields.boolean('Active'),
'ok': fields.boolean('Correct answer',
help="When this field is marked, the answer "
"is considered correct."),
}
_defaults = {
'active': True,
}
def search(self, cr, uid, args, offset=0, limit=None, order=None,
context=None, count=False):
if context is None:
context = {}
if context.get('proof_id'):
ctx = context.copy()
del ctx['proof_id']
proof = self.pool['qc.proof'].browse(cr, uid, context['proof_id'],
ctx)
result = [x.id for x in proof.value_ids]
args = args[:]
args.append(('id', 'in', result))
return super(QcPosibleValue, self).search(cr, uid, args, offset, limit,
order, context, count)
class QcProof(orm.Model):
"""
This model stores proofs which will be part of a test. Proofs are
classified between qualitative (such as color) and quantitative (such as
density).
Proof must be related with method, and Poof-Method relation must be unique
A name_search on thish model will search on 'name' field but also on any of
its synonyms.
"""
_name = 'qc.proof'
def _synonyms(self, cr, uid, ids, field_name, arg, context=None):
result = {}
for proof in self.browse(cr, uid, ids, context=context):
texts = []
for syn in proof.synonym_ids:
texts.append(syn.name)
result[proof.id] = ', '.join(texts)
return result
_columns = {
'name': fields.char('Name', size=200, required=True, select="1",
translate=True),
'ref': fields.char('Code', size=30, select="1"),
'active': fields.boolean('Active'),
'synonym_ids': fields.one2many('qc.proof.synonym', 'proof_id',
'Synonyms'),
'type': fields.selection([('qualitative', 'Qualitative'),
('quantitative', 'Quantitative')], 'Type',
select="1", required=True),
'value_ids': fields.many2many('qc.posible.value',
'qc_proof_posible_value_rel', 'proof_id',
'posible_value_id', 'Posible Values'),
'synonyms': fields.function(_synonyms, method=True, type='char',
string='Synonyms', store=False),
}
_defaults = {
'active': True,
}
def name_search(self, cr, uid, name='', args=None, operator='ilike',
context=None, limit=None):
result = super(QcProof, self).name_search(cr, uid, name=name,
args=args, operator=operator,
context=context, limit=limit)
synonym_obj = self.pool['qc.proof.synonym']
if name:
ids = [x[0] for x in result]
new_ids = []
syns = synonym_obj.name_search(cr, uid, name=name, args=args,
operator=operator, context=context,
limit=limit)
syns = [x[0] for x in syns]
for syn in synonym_obj.browse(cr, uid, syns, context=context):
if syn.proof_id.id not in ids:
new_ids.append(syn.proof_id.id)
result += self.name_get(cr, uid, new_ids, context=context)
return result
# def name_get(self, cr, uid, ids, context=None):
# result = []
# for proof in self.browse(cr, uid, ids, context=context):
# text = proof.name
# if proof.synonym_ids:
# text += " [%s]" % proof.synonyms
# result.append((proof.id, text))
# return result
class QcProofSynonym(orm.Model):
"""
Proofs may have synonyms. These are used because suppliers may use
different names for the same proof.
"""
_name = 'qc.proof.synonym'
_columns = {
'name': fields.char('Name', size=200, required=True, select="1",
translate=True),
'proof_id': fields.many2one('qc.proof', 'Proof', required=True),
}
class QcTestTemplateCategory(orm.Model):
"""
This model is used to categorize proof templates.
"""
_name = 'qc.test.template.category'
_description = 'Test Template Category'
def name_get(self, cr, uid, ids, context=None):
if not len(ids):
return []
reads = self.read(cr, uid, ids, ['name', 'parent_id'], context=context)
res = []
for record in reads:
name = record['name']
if record['parent_id']:
name = record['parent_id'][1] + ' / ' + name
res.append((record['id'], name))
return res
def _name_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None):
res = self.name_get(cr, uid, ids, context=context)
return dict(res)
def _check_recursion(self, cr, uid, ids):
level = 100
while len(ids):
cr.execute('SELECT DISTINCT parent_id FROM'
' qc_test_template_category WHERE id IN (' +
','.join(map(str, ids)) + ')')
ids = [x[0] for x in cr.fetchall() if x[0] is not None]
if not level:
return False
level -= 1
return True
_columns = {
'name': fields.char('Category Name', required=True, size=64,
translate=True),
'parent_id': fields.many2one('qc.test.template.category',
'Parent Category', select=True),
'complete_name': fields.function(_name_get_fnc, method=True,
type="char", string='Full Name'),
'child_ids': fields.one2many('qc.test.template.category', 'parent_id',
'Child Categories'),
'active': fields.boolean('Active',
help="The active field allows you to hide the"
" category without removing it."),
}
_constraints = [
(_check_recursion,
_('Error ! You can not create recursive categories.'), ['parent_id'])
]
_defaults = {
'active': 1,
}
class QcTestTemplateTrigger(orm.Model):
_name = 'qc.test.template.trigger'
_description = 'Test Template Trigger'
_columns = {
'name': fields.char('Name', size=64, required=True, readonly=False,
translate=True),
'active': fields.boolean('Active', required=False),
}
_defaults = {
'active': 1,
}
class QcTestTemplate(orm.Model):
"""
A template is a group of proofs to with the values that make them valid.
"""
_name = 'qc.test.template'
_description = 'Test Template'
def _links_get(self, cr, uid, context=None):
# TODO: Select models
link_obj = self.pool['res.request.link']
ids = link_obj.search(cr, uid, [], context=context)
res = link_obj.read(cr, uid, ids, ['object', 'name'], context=context)
return [(r['object'], r['name']) for r in res]
def _default_name(self, cr, uid, context=None):
if context and context.get('reference_model', False):
if 'reference_id' in context:
source = self.pool[context['reference_model']].browse(
cr, uid, context.get('active_id'), context=context)
if hasattr(source, 'name'):
return source.name
def _default_object_id(self, cr, uid, context=None):
if context and context.get('reference_model', False):
return '%s,%d' % (context['reference_model'],
context['reference_id'])
else:
return False
def _default_type(self, cr, uid, context=None):
if context and context.get('reference_model'):
return 'related'
else:
return False
_columns = {
'active': fields.boolean('Active', select="1"),
'name': fields.char('Name', size=200, required=True, translate=True,
select="1"),
'test_template_line_ids': fields.one2many('qc.test.template.line',
'test_template_id', 'Lines'),
'object_id': fields.reference('Reference Object', selection=_links_get,
size=128),
'fill_correct_values': fields.boolean('Fill With Correct Values'),
'type': fields.selection([('generic', 'Generic'),
('related', 'Related')], 'Type', select="1"),
'category_id': fields.many2one('qc.test.template.category',
'Category'),
'trig_on': fields.many2one('qc.test.template.trigger', 'Trigger'),
}
_defaults = {
'name': _default_name,
'active': True,
'object_id': _default_object_id,
'type': _default_type,
}
class QcTestTemplateLine(orm.Model):
"""
Each test template line has a reference to a proof and the valid
value/values.
"""
_name = 'qc.test.template.line'
_description = 'Test Template Line'
_order = 'sequence asc'
_rec_name = 'sequence'
def onchange_proof_id(self, cr, uid, ids, proof_id, context=None):
if not proof_id:
return {}
proof = self.pool['qc.proof'].browse(cr, uid, proof_id,
context=context)
return {'value': {'type': proof.type}}
_columns = {
'sequence': fields.integer('Sequence', required=True),
'test_template_id': fields.many2one('qc.test.template',
'Test Template', select="1"),
'proof_id': fields.many2one('qc.proof', 'Question', required=True,
select="1"),
'valid_value_ids': fields.many2many('qc.posible.value',
'qc_template_value_rel',
'template_line_id', 'value_id',
'Answers'),
'method_id': fields.many2one('qc.proof.method', 'Method', select="1"),
'notes': fields.text('Notes'),
'min_value': fields.float('Min', digits=(16, 5)), # Quantitative only
'max_value': fields.float('Max', digits=(15, 5)), # Quantitative only
'uom_id': fields.many2one('product.uom', 'Uom'), # Quantitative only
'type': fields.selection([('qualitative', 'Qualitative'),
('quantitative', 'Quantitative')],
'Type', select="1"),
}
_defaults = {
'sequence': 1,
}
class QcTest(orm.Model):
"""
This model contains an instance of a test template.
"""
_name = 'qc.test'
_inherit = ['mail.thread', 'ir.needaction_mixin']
def _success(self, cr, uid, ids, field_name, arg, context=None):
result = {}
for test in self.browse(cr, uid, ids, context=context):
success = False
if len(test.test_line_ids):
success = True
proof = {}
for line in test.test_line_ids:
proof[line.proof_id.id] = (proof.get(line.proof_id.id,
False)
or line.success)
for p in proof:
if not proof[p]:
success = False
break
result[test.id] = success
return result
def _links_get(self, cr, uid, context=None):
# TODO: Select models
link_obj = self.pool['res.request.link']
ids = link_obj.search(cr, uid, [], context=context)
res = link_obj.read(cr, uid, ids, ['object', 'name'], context=context)
return [(r['object'], r['name']) for r in res]
def _default_object_id(self, cr, uid, context=None):
if context and context.get('reference_model', False):
return '%s,%d' % (context['reference_model'],
context['reference_id'])
else:
return False
_columns = {
'name': fields.datetime('Date', required=True, readonly=True,
states={'draft': [('readonly', False)]},
select="1"),
'object_id': fields.reference('Reference', selection=_links_get,
size=128, readonly=True,
states={'draft': [('readonly', False)]},
select="1"),
'test_template_id': fields.many2one('qc.test.template', 'Test',
states={'success':
[('readonly', True)],
'failed':
[('readonly', True)]},
select="1"),
'test_line_ids': fields.one2many('qc.test.line', 'test_id',
'Test Lines',
states={'success':
[('readonly', True)],
'failed':
[('readonly', True)]}),
'test_internal_note': fields.text('Internal Note',
states={'success':
[('readonly', True)],
'failed':
[('readonly', True)]}),
'test_external_note': fields.text('External Note',
states={'success':
[('readonly', True)],
'failed':
[('readonly', True)]}),
'state': fields.selection([
('draft', 'Draft'),
('waiting', 'Waiting Supervisor Approval'),
('success', 'Quality Success'),
('failed', 'Quality Failed'),
('canceled', 'Canceled'),
], 'State', readonly=True, select="1"),
'success': fields.function(_success, method=True, type='boolean',
string='Success',
help='This field will be active if all'
' tests have succeeded.', select="1",
store=True),
'enabled': fields.boolean('Enabled', readonly=True,
help='If a quality control test is not'
' enabled it means it can not be moved from'
' "Quality Success" or "Quality Failed"'
' state.', select="1"),
}
_defaults = {
'name': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
'state': 'draft',
'object_id': _default_object_id,
'enabled': True,
}
def copy(self, cr, uid, copy_id, default=None, context=None):
if context is None:
context = {}
if default is None:
default = {}
default['name'] = time.strftime('%Y-%m-%d %H:%M:%S')
return super(QcTest, self).copy(cr, uid, copy_id, default,
context=context)
def create(self, cr, uid, datas, context=None):
if context and context.get('reference_model', False):
datas['object_id'] = (context['reference_model'] + "," +
str(context['reference_id']))
return super(orm.Model, self).create(cr, uid, datas, context=context)
def qc_test_success(self, cr, uid, ids, context=None):
self.write(cr, uid, ids, {
'state': 'success'
}, context=context)
return True
def qc_test_failed(self, cr, uid, ids, context=None):
self.write(cr, uid, ids, {
'state': 'failed'
}, context=context)
return True
def test_state(self, cr, uid, ids, mode, *args):
quality_check = False
if mode == 'failed':
return not quality_check
if mode == 'success':
return quality_check
return False
def set_test_template(self, cr, uid, ids, template_id, force_fill=False,
context=None):
if context is None:
context = {}
test_obj = self.pool['qc.test']
test_line_obj = self.pool['qc.test.line']
for test_id in ids:
test_obj.write(cr, uid, test_id, {'test_template_id': template_id},
context)
test = test_obj.browse(cr, uid, test_id, context=context)
if len(test.test_line_ids) > 0:
test_line_obj.unlink(cr, uid,
[x.id for x in test.test_line_ids],
context=context)
test_lines = self._prepare_test_lines(
cr, uid, test, force_fill=force_fill, context=context)
if test_lines:
test_obj.write(cr, uid, id, {'test_line_ids': test_lines},
context)
def _prepare_test_lines(self, cr, uid, test, force_fill=False,
context=None):
new_data = []
fill = test.test_template_id.fill_correct_values
for line in test.test_template_id.test_template_line_ids:
data = self._prepare_test_line(
cr, uid, test, line, fill=fill or force_fill, context=context)
new_data.append((0, 0, data))
return new_data
def _prepare_test_line(self, cr, uid, test, line, fill=None, context=None):
data = {}
data = {'test_id': test.id,
'method_id': line.method_id.id,
'proof_id': line.proof_id.id,
'test_template_line_id': line.id,
'notes': line.notes,
'min_value': line.min_value,
'max_value': line.max_value,
'uom_id': line.uom_id.id,
'test_uom_id': line.uom_id.id,
'proof_type': line.type,
}
if fill:
if line.type == 'qualitative':
# Fill with the first correct value found.
data['actual_value_ql'] = (
len(line.valid_value_ids) and
line.valid_value_ids[0] and
line.valid_value_ids[0].id or False)
else:
# Fill with value inside range.
data['actual_value_qt'] = line.min_value
data['test_uom_id'] = line.uom_id.id
data['valid_value_ids'] = [(6, 0, [x.id for x in
line.valid_value_ids])]
return data
class QcTestLine(orm.Model):
"""
Each test line has a value and a reference to a proof template line.
"""
_name = 'qc.test.line'
_rec_name = 'proof_id'
def quality_test_check(self, cr, uid, ids, field_name, field_value,
context=None):
res = {}
lines = self.browse(cr, uid, ids, context=None)
for line in lines:
if line.proof_type == 'qualitative':
res[line.id] = self.quality_test_qualitative_check(
cr, uid, line, context=None)
else:
res[line.id] = self.quality_test_quantitative_check(
cr, uid, line, context=None)
return res
def quality_test_qualitative_check(self, cr, uid, test_line, context=None):
if test_line.actual_value_ql in test_line.valid_value_ids:
return test_line.actual_value_ql.ok
else:
return False
def quality_test_quantitative_check(self, cr, uid, test_line,
context=None):
amount = self.pool['product.uom']._compute_qty(
cr, uid, test_line.uom_id.id, test_line.actual_value_qt,
test_line.test_uom_id.id)
if amount >= test_line.min_value and amount <= test_line.max_value:
return True
else:
return False
_columns = {
'test_id': fields.many2one('qc.test', 'Test'),
'test_template_line_id': fields.many2one('qc.test.template.line',
'Test Template Line',
readonly=True),
'proof_id': fields.many2one('qc.proof', 'Question', readonly=True),
'method_id': fields.many2one('qc.proof.method', 'Method',
readonly=True),
'valid_value_ids': fields.many2many('qc.posible.value',
'qc_test_value_rel',
'test_line_id', 'value_id',
'Answers'),
'actual_value_qt': fields.float('Qt.Value', digits=(16, 5),
help="Value of the result if it is a"
" quantitative proof."),
'actual_value_ql': fields.many2one('qc.posible.value', 'Ql.Value',
help="Value of the result if it is"
" a qualitative proof."),
'notes': fields.text('Notes', readonly=True),
'min_value': fields.float('Min', digits=(16, 5), readonly=True,
help="Minimum valid value if it is a"
" quantitative proof."),
'max_value': fields.float('Max', digits=(16, 5), readonly=True,
help="Maximum valid value if it is a"
" quantitative proof."),
'uom_id': fields.many2one('product.uom', 'Uom', readonly=True,
help="UoM for minimum and maximum values if"
" it is a quantitative proof."),
'test_uom_id': fields.many2one('product.uom', 'Uom Test',
help="UoM of the value of the result"
" if it is a quantitative proof."),
'proof_type': fields.selection([('qualitative', 'Qualitative'),
('quantitative', 'Quantitative')],
'Proof Type', readonly=True),
'success': fields.function(quality_test_check, type='boolean',
method=True, string="Success?", select="1"),
}
def onchange_actual_value_qt(self, cr, uid, ids, uom_id, test_uom_id,
actual_value_qt, min_value, max_value,
context=None):
res = {}
if actual_value_qt:
amount = self.pool['product.uom']._compute_qty(cr, uid, uom_id,
actual_value_qt,
test_uom_id)
if amount >= min_value and amount <= max_value:
res['success'] = True
else:
res['success'] = False
return {'value': res}
def onchange_actual_value_ql(self, cr, uid, ids, actual_value_ql,
valid_value_ids, context=None):
res = {}
value_obj = self.pool['qc.posible.value']
if actual_value_ql:
valid = valid_value_ids[0][2]
if actual_value_ql in valid:
value = value_obj.browse(cr, uid, actual_value_ql, context)
res['success'] = value.ok
else:
res['success'] = False
return {'value': res}

View File

@@ -1,13 +1,17 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_user_qc_test,qc_test,quality_control.model_qc_test,quality_control.group_quality_control_user,1,1,1,1
access_user_qc_test_line,qc_test_line,quality_control.model_qc_test_line,quality_control.group_quality_control_user,1,1,1,1
access_user_qc_test_template,qc_test_template user,quality_control.model_qc_test_template,quality_control.group_quality_control_user,1,0,0,0
access_user_qc_test_template_line,qc_test_template_line user,quality_control.model_qc_test_template_line,quality_control.group_quality_control_user,1,0,0,0
access_manager_qc_test_template,qc_test_template manager,quality_control.model_qc_test_template,quality_control.group_quality_control_manager,1,1,1,1
access_manager_qc_test_template_line,qc_test_template_line manager,quality_control.model_qc_test_template_line,quality_control.group_quality_control_manager,1,1,1,1
access_manager_qc_proof_method,qc_proof_method,quality_control.model_qc_proof_method,quality_control.group_quality_control_manager,1,1,1,1
access_manager_qc_posible_value,qc_posible_value,quality_control.model_qc_posible_value,quality_control.group_quality_control_manager,1,1,1,1
access_manager_qc_proof,qc_proof,quality_control.model_qc_proof,quality_control.group_quality_control_manager,1,1,1,1
access_manager_qc_proof_synonym,qc_proof_synonym,quality_control.model_qc_proof_synonym,quality_control.group_quality_control_manager,1,1,1,1
access_manager_qc_test_template_category,qc_test_template_category,quality_control.model_qc_test_template_category,quality_control.group_quality_control_manager,1,1,1,1
access_manager_qc_test_template_trigger,qc_test_template_trigger,quality_control.model_qc_test_template_trigger,quality_control.group_quality_control_manager,1,1,1,1
access_user_qc_inspection,qc_inspection,quality_control.model_qc_inspection,quality_control.group_quality_control_user,1,1,1,1
access_user_qc_inspection_line,qc_inspection_line,quality_control.model_qc_inspection_line,quality_control.group_quality_control_user,1,1,1,1
access_user_qc_test,qc_test user,quality_control.model_qc_test,quality_control.group_quality_control_user,1,0,0,0
access_user_qc_test_question,qc_test_question user,quality_control.model_qc_test_question,quality_control.group_quality_control_user,1,0,0,0
access_manager_qc_test,qc_test manager,quality_control.model_qc_test,quality_control.group_quality_control_manager,1,1,1,1
access_manager_qc_test_question,qc_test_question manager,quality_control.model_qc_test_question,quality_control.group_quality_control_manager,1,1,1,1
access_manager_qc_test_question_value,qc_test_question_value,quality_control.model_qc_test_question_value,quality_control.group_quality_control_manager,1,1,1,1
access_manager_qc_test_category,qc_test_category,quality_control.model_qc_test_category,quality_control.group_quality_control_manager,1,1,1,1
access_manager_qc_trigger_user,qc_trigger user,quality_control.model_qc_trigger,quality_control.group_quality_control_user,1,0,0,0
access_manager_qc_trigger_manager,qc_trigger manager,quality_control.model_qc_trigger,quality_control.group_quality_control_manager,1,1,1,1
access_manager_qc_trigger_product_category_line_user,qc_trigger product_category line user,quality_control.model_qc_trigger_product_category_line,,1,0,0,0
access_manager_qc_trigger_product_category_line_manager,qc_trigger product_category line manager,quality_control.model_qc_trigger_product_category_line,quality_control.group_quality_control_user,1,1,1,1
access_manager_qc_trigger_product_template_line_user,qc_trigger product_template line user,quality_control.model_qc_trigger_product_template_line,,1,0,0,0
access_manager_qc_trigger_product_template_line_manager,qc_trigger product_template line manager,quality_control.model_qc_trigger_product_template_line,quality_control.group_quality_control_user,1,1,1,1
access_manager_qc_trigger_product_line_user,qc_trigger product line user,quality_control.model_qc_trigger_product_line,,1,0,0,0
access_manager_qc_trigger_product_line_manager,qc_trigger product line manager,quality_control.model_qc_trigger_product_line,quality_control.group_quality_control_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_user_qc_test access_user_qc_inspection qc_test qc_inspection quality_control.model_qc_test quality_control.model_qc_inspection quality_control.group_quality_control_user 1 1 1 1
3 access_user_qc_test_line access_user_qc_inspection_line qc_test_line qc_inspection_line quality_control.model_qc_test_line quality_control.model_qc_inspection_line quality_control.group_quality_control_user 1 1 1 1
4 access_user_qc_test_template access_user_qc_test qc_test_template user qc_test user quality_control.model_qc_test_template quality_control.model_qc_test quality_control.group_quality_control_user 1 0 0 0
5 access_user_qc_test_template_line access_user_qc_test_question qc_test_template_line user qc_test_question user quality_control.model_qc_test_template_line quality_control.model_qc_test_question quality_control.group_quality_control_user 1 0 0 0
6 access_manager_qc_test_template access_manager_qc_test qc_test_template manager qc_test manager quality_control.model_qc_test_template quality_control.model_qc_test quality_control.group_quality_control_manager 1 1 1 1
7 access_manager_qc_test_template_line access_manager_qc_test_question qc_test_template_line manager qc_test_question manager quality_control.model_qc_test_template_line quality_control.model_qc_test_question quality_control.group_quality_control_manager 1 1 1 1
8 access_manager_qc_proof_method access_manager_qc_test_question_value qc_proof_method qc_test_question_value quality_control.model_qc_proof_method quality_control.model_qc_test_question_value quality_control.group_quality_control_manager 1 1 1 1
9 access_manager_qc_posible_value access_manager_qc_test_category qc_posible_value qc_test_category quality_control.model_qc_posible_value quality_control.model_qc_test_category quality_control.group_quality_control_manager 1 1 1 1
10 access_manager_qc_proof access_manager_qc_trigger_user qc_proof qc_trigger user quality_control.model_qc_proof quality_control.model_qc_trigger quality_control.group_quality_control_manager quality_control.group_quality_control_user 1 1 0 1 0 1 0
11 access_manager_qc_proof_synonym access_manager_qc_trigger_manager qc_proof_synonym qc_trigger manager quality_control.model_qc_proof_synonym quality_control.model_qc_trigger quality_control.group_quality_control_manager 1 1 1 1
12 access_manager_qc_test_template_category access_manager_qc_trigger_product_category_line_user qc_test_template_category qc_trigger product_category line user quality_control.model_qc_test_template_category quality_control.model_qc_trigger_product_category_line quality_control.group_quality_control_manager 1 1 0 1 0 1 0
13 access_manager_qc_test_template_trigger access_manager_qc_trigger_product_category_line_manager qc_test_template_trigger qc_trigger product_category line manager quality_control.model_qc_test_template_trigger quality_control.model_qc_trigger_product_category_line quality_control.group_quality_control_manager quality_control.group_quality_control_user 1 1 1 1
14 access_manager_qc_trigger_product_template_line_user qc_trigger product_template line user quality_control.model_qc_trigger_product_template_line 1 0 0 0
15 access_manager_qc_trigger_product_template_line_manager qc_trigger product_template line manager quality_control.model_qc_trigger_product_template_line quality_control.group_quality_control_user 1 1 1 1
16 access_manager_qc_trigger_product_line_user qc_trigger product line user quality_control.model_qc_trigger_product_line 1 0 0 0
17 access_manager_qc_trigger_product_line_manager qc_trigger product line manager quality_control.model_qc_trigger_product_line quality_control.group_quality_control_user 1 1 1 1

View File

@@ -1,6 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<data>
<record model="ir.module.category" id="module_category_quality_control">
<field name="name">Quality control</field>
</record>
<record id="group_quality_control_user" model="res.groups">
<field name="name">User</field>
@@ -14,5 +18,26 @@
<field name="users" eval="[(4, ref('base.user_root'))]"/>
</record>
<record id="qc_test_multi_company_rule" model="ir.rule">
<field name="name">Quality control test multi-company</field>
<field name="model_id" ref="model_qc_test"/>
<field name="global" eval="True"/>
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])]</field>
</record>
<record id="qc_inspection_multi_company_rule" model="ir.rule">
<field name="name">Quality control inspection multi-company</field>
<field name="model_id" ref="model_qc_inspection"/>
<field name="global" eval="True"/>
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])]</field>
</record>
<record id="qc_trigger_multi_company_rule" model="ir.rule">
<field name="name">Quality control trigger multi-company</field>
<field name="model_id" ref="model_qc_trigger"/>
<field name="global" eval="True"/>
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])]</field>
</record>
</data>
</openerp>

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

@@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="svg2"
version="1.1"
inkscape:version="0.91 r"
width="256"
height="256"
viewBox="0 0 256 256"
sodipodi:docname="icon.svg"
inkscape:export-filename="icon.png"
inkscape:export-xdpi="45"
inkscape:export-ydpi="45">
<metadata
id="metadata8">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs6" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1855"
inkscape:window-height="1056"
id="namedview4"
showgrid="false"
showguides="false"
inkscape:zoom="2.6074563"
inkscape:cx="97.374622"
inkscape:cy="132.02575"
inkscape:window-x="65"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<path
style="fill:#3b4552;fill-opacity:1;stroke:none;stroke-width:1.93276381"
d="m 211.33966,96.067802 c 0,5.992928 7.91763,11.579358 6.74724,17.584548 -1.17039,6.00519 -11.48804,8.10481 -13.8219,13.58637 -2.33386,5.48156 3.54667,14.45202 0.2853,19.35834 -3.26137,4.90632 -13.42612,3.16349 -17.72981,7.43515 -4.30369,4.27166 -2.84179,14.82951 -7.85007,18.16415 -5.00827,3.33464 -14.16074,-2.55764 -19.80601,-0.26061 -5.64527,2.29703 -8.12649,12.89205 -13.9027,13.97052 -5.77621,1.07847 -11.48439,-7.0737 -17.64561,-7.0737 -6.16121,0 -12.25109,7.92446 -18.34832,6.62698 -6.09723,-1.29748 -7.59194,-10.41046 -12.762714,-12.66396 -5.170777,-2.2535 -13.376422,2.91752 -18.36,-0.36786 -4.983578,-3.28538 -5.262182,-14.36977 -9.53734,-18.79261 -4.275158,-4.42285 -12.851882,-1.69906 -16.45127,-7.12771 -3.599388,-5.42865 1.214828,-13.41741 -0.770599,-19.03959 -1.985426,-5.62218 -11.704615,-8.69661 -12.692518,-13.74392 -0.987903,-5.04731 7.500299,-12.47926 7.500299,-18.614887 0,-6.135628 -8.588091,-11.321696 -7.392633,-17.238661 C 39.996464,71.953386 50.643513,69.536 52.904546,64.153032 55.165579,58.770064 48.868664,50.58811 52.15073,45.63683 c 3.282066,-4.951281 13.747588,-4.272318 18.076133,-8.582161 4.328545,-4.309842 2.720858,-13.899039 7.694198,-17.198646 4.97334,-3.299607 13.104622,1.205446 18.503316,-1.022051 5.398693,-2.227496 7.894433,-11.1597399 13.714143,-12.3387556 5.81971,-1.1790158 12.1411,6.0407876 18.24461,6.0407876 6.10351,-1e-6 11.68483,-7.3111077 17.42643,-6.2026403 5.7416,1.1084674 8.13974,10.5614813 13.80595,12.8572833 5.6662,2.295802 14.94429,-2.23592 19.8907,1.108078 4.94641,3.343998 2.48246,11.892283 6.64749,15.99066 4.16503,4.098377 14.62827,3.666275 18.01677,8.682357 3.3885,5.016082 -2.02844,13.500558 0.32346,19.125397 2.3519,5.62484 12.47407,8.60159 13.61721,14.510953 1.14314,5.909363 -6.77148,11.466779 -6.77148,17.45971 z"
id="circle3368"
inkscape:connector-curvature="0"
sodipodi:nodetypes="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" />
<circle
r="63.531616"
cy="96.067802"
cx="128.38313"
id="circle3346"
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.34354317" />
<circle
style="fill:#2b78c2;fill-opacity:1;stroke:none;stroke-width:1.09952056"
id="path3342"
cx="128.38313"
cy="96.067802"
r="51.992611" />
<path
style="fill:#2b78c2;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
d="m 83.989904,184.28259 8.053826,-1.24642 c 9.05399,16.12754 16.49528,14.24662 24.0656,13.80656 l -10.83431,53.1169 -14.190079,-13.51892 -18.984019,4.79394 z"
id="path3338"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
<path
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0"
id="path3340"
d="m 171.81497,184.37847 -8.05383,-1.24642 c -9.05399,16.12754 -16.49528,14.24662 -24.0656,13.80656 l 10.83431,53.1169 14.19008,-13.51892 18.98402,4.79394 z"
style="fill:#2b78c2;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
inkscape:transform-center-x="-0.016606677"
inkscape:transform-center-y="-4.1513637"
d="m 147.10763,127.15966 -18.87851,-10.66672 -19.29578,10.61355 c -2.14644,1.18064 -5.60088,-1.48065 -5.11608,-3.87048 l 4.26518,-21.02547 -15.410855,-14.46528 c -1.952657,-1.832846 -1.388891,-6.342484 1.848072,-6.713162 l 20.920483,-2.395688 9.61304,-20.440593 c 0.75725,-1.610169 4.6613,-2.921345 5.96156,-0.04186 l 9.11939,20.195236 22.68645,2.860817 c 3.08062,0.388473 2.79381,4.411669 1.38356,5.705416 l -16.16599,14.830394 4.28375,22.429 c 0.38417,2.01144 -2.29024,4.63697 -5.21427,2.98484 z"
id="path3350"
inkscape:connector-curvature="0"
sodipodi:nodetypes="scsscsscsscsscss" />
</svg>

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record model="ir.ui.view" id="product_category_qc_form_view">
<field name="name">product.category.qc</field>
<field name="model">product.category</field>
<field name="inherit_id" ref="product.product_category_form_view"/>
<field name="arch" type="xml">
<sheet position="inside">
<group name="qc" string="Quality control">
<field name="qc_triggers" nolabel="1">
<tree string="Quality control triggers" editable="bottom">
<field name="trigger" widget="selection"/>
<field name="test"/>
</tree>
</field>
</group>
</sheet>
</field>
</record>
</data>
</openerp>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record model="ir.ui.view" id="product_template_qc_form_view">
<field name="name">product.template.qc</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_form_view"/>
<field name="arch" type="xml">
<page string="Inventory" position="inside">
<group name="qc" string="Quality control">
<field name="qc_triggers" nolabel="1">
<tree string="Quality control triggers" editable="bottom">
<field name="trigger" widget="selection"/>
<field name="test"/>
</tree>
</field>
</group>
</page>
</field>
</record>
</data>
</openerp>

View File

@@ -0,0 +1,245 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record model="ir.ui.view" id="qc_inspection_form_view">
<field name="name">qc.inspection.form</field>
<field name="model">qc.inspection</field>
<field name="arch" type="xml">
<form string="Inspection">
<header>
<button name="action_draft"
type="object"
attrs="{'invisible': [('state', '!=', 'canceled')]}"
string="Draft" />
<button name="action_todo"
type="object"
class="oe_highlight"
states="draft"
string="Mark todo" />
<button name="action_confirm"
type="object"
class="oe_highlight"
states="ready"
string="Confirm"
icon="gtk-ok" />
<button name="action_approve"
type="object"
states="waiting"
class="oe_highlight"
string="Approve" />
<button name="action_cancel"
type="object"
attrs="{'invisible': ['|', ('auto_generated', '=', True), ('state', 'not in', ['waiting', 'ready', 'failed', 'success'])]}"
string="Cancel"
icon="gtk-cancel" />
<field name="state"
widget="statusbar"
statusbar_visible="draft,waiting,success"
statusbar_colors='{"success": "blue", "failed": "red"}' />
</header>
<sheet>
<h1>
<label string="Inspection "/>
<field name="name" class="oe_inline"/>
</h1>
<div class="oe_right oe_button_box" name="buttons">
<button class="oe_inline oe_stat_button"
type="action"
name="%(action_qc_inspection_set_test)d"
icon="fa-bookmark-o"
states="draft"
string="Set test"/>
</div>
<group>
<group>
<field name="test"/>
<field name="object_id" />
<field name="product" />
</group>
<group>
<field name="date" />
<field name="success" />
<field name="auto_generated" />
</group>
</group>
<notebook>
<page string="Questions">
<field name="inspection_lines" nolabel="1">
<tree string="Inspection lines" editable="top" delete="false" create="false">
<field name="name" />
<field name="question_type" />
<field name="possible_ql_values" invisible="1" />
<field name="qualitative_value"
attrs="{'readonly': [('question_type', '=', 'quantitative')]}" />
<field name="quantitative_value"
attrs="{'readonly': [('question_type', '=', 'qualitative')]}" />
<field name="uom_id"
groups="product.group_uom"
attrs="{'readonly': [('question_type', '=', 'qualitative')]}" />
<field name="test_uom_category" invisible="1"/>
<field name="valid_values" />
<field name="success" />
</tree>
</field>
</page>
<page string="Notes">
<group string="Internal notes" >
<field name="internal_notes"
nolabel="1" />
</group>
<group string="External notes" >
<field name="external_notes"
nolabel="1" />
</group>
</page>
</notebook>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers" groups="base.group_user"/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
</record>
<record model="ir.ui.view" id="qc_inspection_tree_view">
<field name="name">qc.inspection.tree</field>
<field name="model">qc.inspection</field>
<field name="arch" type="xml">
<tree string="Inspections">
<field name="name" />
<field name="test" />
<field name="product" />
<field name="success" />
<field name="state" />
</tree>
</field>
</record>
<record model="ir.ui.view" id="qc_inspection_search_view">
<field name="name">qc.inspection.search</field>
<field name="model">qc.inspection</field>
<field name="arch" type="xml">
<search string="Search inspection">
<group>
<field name="name" />
<field name="object_id" />
<field name="product" />
<field name="test" />
</group>
<newline />
<filter string="Correct"
domain="[('success', '=', True)]"/>
<filter string="Incorrect"
domain="[('success', '=', False)]"/>
<newline />
<group expand="0" string="Group by...">
<filter string="Reference"
domain="[]"
context="{'group_by': 'object_id'}" />
<filter string="Test"
domain="[]"
context="{'group_by': 'test'}" />
<filter string="Product"
domain="[]"
context="{'group_by': 'product'}" />
<filter string="State"
domain="[]"
context="{'group_by': 'state'}" />
<filter string="Success"
domain="[]"
context="{'group_by': 'success'}" />
<filter string="Auto-generated"
domain="[]"
context="{'group_by': 'auto_generated'}" />
</group>
</search>
</field>
</record>
<record model="ir.actions.act_window" id="action_qc_inspection">
<field name="name">Inspections</field>
<field name="res_model">qc.inspection</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem name="Inspections"
parent="qc_inspection_menu_parent"
id="qc_inspection_menu"
action="action_qc_inspection" />
<record model="ir.ui.view" id="qc_inspection_line_tree_view">
<field name="name">qc.inspection.line.tree</field>
<field name="model">qc.inspection.line</field>
<field name="arch" type="xml">
<tree string="Inspection lines" delete="false" create="false" colors="red: success==False">
<field name="inspection_id" />
<field name="product" />
<field name="name" />
<field name="question_type" />
<field name="possible_ql_values" invisible="1" />
<field name="qualitative_value"
attrs="{'readonly': [('question_type', '=', 'quantitative')]}" />
<field name="quantitative_value"
attrs="{'readonly': [('question_type', '=', 'qualitative')]}" />
<field name="uom_id"
groups="product.group_uom"
attrs="{'readonly': [('question_type', '=', 'qualitative')]}" />
<field name="test_uom_category" invisible="1"/>
<field name="valid_values" />
<field name="success" />
</tree>
</field>
</record>
<record model="ir.ui.view" id="qc_inspection_line_search_view">
<field name="name">qc.inspection.line.search</field>
<field name="model">qc.inspection.line</field>
<field name="arch" type="xml">
<search string="Search inspection line">
<group>
<field name="name" />
<field name="inspection_id" />
<field name="product" />
<field name="success" />
</group>
<newline />
<filter string="Correct"
domain="[('success', '=', True)]"/>
<filter string="Incorrect"
domain="[('success', '=', False)]"/>
<newline />
<group expand="0" string="Group by...">
<filter string="Inspection"
domain="[]"
context="{'group_by': 'inspection_id'}" />
<filter string="Product"
domain="[]"
context="{'group_by': 'product'}" />
<filter string="Question"
domain="[]"
context="{'group_by': 'name'}" />
<filter string="Success"
domain="[]"
context="{'group_by': 'success'}" />
</group>
</search>
</field>
</record>
<record model="ir.actions.act_window" id="action_qc_inspection_line">
<field name="name">Inspection lines</field>
<field name="res_model">qc.inspection.line</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem name="Inspection lines"
parent="qc_inspection_menu_parent"
id="qc_inspection_lines_menu"
action="action_qc_inspection_line" />
</data>
</openerp>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<menuitem name="Quality control"
id="qc_menu"
groups="group_quality_control_user"
sequence="40" />
<menuitem name="Inspections"
parent="qc_menu"
id="qc_inspection_menu_parent"
sequence="10" />
<menuitem parent="qc_menu"
name="Tests"
id="qc_menu_test_parent"
sequence="20" />
</data>
</openerp>

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record model="ir.ui.view" id="qc_test_category_tree_view">
<field name="name">qc.test.category.tree</field>
<field name="model">qc.test.category</field>
<field name="arch" type="xml">
<tree string="Test categories" editable="bottom">
<field name="complete_name"/>
<field name="name"/>
<field name="parent_id"/>
<field name="active"/>
</tree>
</field>
</record>
<record model="ir.actions.act_window" id="action_qc_test_category">
<field name="name">Test categories</field>
<field name="res_model">qc.test.category</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem name="Test categories"
parent="qc_menu_test_parent"
id="qc_test_category_menu"
action="action_qc_test_category"
groups="group_quality_control_manager"
sequence="10" />
</data>
</openerp>

View File

@@ -0,0 +1,127 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record model="ir.ui.view" id="qc_test_form_view">
<field name="name">qc.test.form</field>
<field name="model">qc.test</field>
<field name="arch" type="xml">
<form string="Test">
<sheet>
<label for="name" class="oe_edit_only"/>
<h1>
<field name="name" class="oe_inline"/>
</h1>
<group>
<group>
<field name="type" />
<field name="object_id"
attrs="{'invisible': [('type','=','generic')]}"/>
<field name="active" />
</group>
<group>
<field name="category" />
<field name="fill_correct_values" />
<field name="company_id" groups="base.group_multi_company"/>
</group>
</group>
<field name="test_lines" nolabel="1" >
<tree string="Questions">
<field name="sequence" widget="handle"/>
<field name="name" />
<field name="type" />
<field name="min_value" />
<field name="max_value" />
<field name="uom_id" />
<field name="ql_values" />
</tree>
</field>
</sheet>
</form>
</field>
</record>
<record model="ir.ui.view" id="qc_test_tree_view">
<field name="name">qc.test.tree</field>
<field name="model">qc.test</field>
<field name="arch" type="xml">
<tree string="Tests">
<field name="name" />
<field name="category" />
<field name="type" />
<field name="object_id" />
<field name="company_id" groups="base.group_multi_company"/>
</tree>
</field>
</record>
<record model="ir.actions.act_window" id="action_qc_test">
<field name="name">Tests</field>
<field name="res_model">qc.test</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>
<record model="ir.ui.view" id="qc_test_question_form_view">
<field name="name">qc.test.question.form</field>
<field name="model">qc.test.question</field>
<field name="arch" type="xml">
<form string="Test question">
<label for="name"/>
<h1>
<field name="name" class="oe_edit_only"/>
</h1>
<group>
<field name="sequence" />
<field name="type" />
</group>
<group name="qualitative"
string="Answers"
colspan="4"
attrs="{'invisible': [('type', '!=', 'qualitative')]}">
<field name="ql_values"
nolabel="1"
attrs="{'required': [('type','=','qualitative')]}">
<tree string="Question value" editable="bottom">
<field name="name" />
<field name="ok" />
</tree>
</field>
</group>
<div name="quantitative"
align="center"
attrs="{'invisible': [('type', '!=', 'quantitative')]}" >
<h1 name="quantitative-data">
<span name="quantitative-interval" >
<field name="min_value"
class="oe_inline"
nolabel="1"
attrs="{'required': [('type',' =', 'quantitative')]}" />
<span> - </span>
<field name="max_value"
class="oe_inline"
nolabel="1"
attrs="{'required': [('type', '=', 'quantitative')]}" />
</span>
<span name="quantitative-uom" >
<field name="uom_id"
class="oe_inline"
nolabel="1"
attrs="{'required': [('type', '=', 'quantitative')]}" />
</span>
</h1>
</div>
<field name="notes" />
</form>
</field>
</record>
<menuitem name="Tests"
parent="qc_menu_test_parent"
id="qc_test_menu"
action="action_qc_test"
sequence="20" />
</data>
</openerp>

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record model="ir.ui.view" id="qc_trigger_form_view">
<field name="name">qc.trigger.form</field>
<field name="model">qc.trigger</field>
<field name="arch" type="xml">
<form string="Quality control trigger">
<group>
<field name="name" />
<field name="active" />
</group>
<group>
<field name="company_id" groups="base.group_multi_company"/>
</group>
</form>
</field>
</record>
<record model="ir.ui.view" id="qc_trigger_tree_view">
<field name="name">qc.trigger.tree</field>
<field name="model">qc.trigger</field>
<field name="arch" type="xml">
<tree string="Quality control triggers" editable="bottom">
<field name="name" />
<field name="company_id" groups="base.group_multi_company"/>
</tree>
</field>
</record>
</data>
</openerp>

View File

@@ -1,552 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<menuitem name="Quality Control" id="qc_menu" sequence="40" />
<menuitem parent="qc_menu" name="Configuration" id="qc_menu_config"
sequence="150" groups="group_quality_control_manager"/>
<!-- qc.proof.method -->
<record model="ir.ui.view" id="qc_method_form_view">
<field name="name">qc.proof.method.form</field>
<field name="model">qc.proof.method</field>
<field name="arch" type="xml">
<form string="Proof Method">
<group>
<field name="name" />
<field name="active" />
</group>
</form>
</field>
</record>
<record model="ir.ui.view" id="qc_proof_method_tree_view">
<field name="name">qc.proof.method.tree</field>
<field name="model">qc.proof.method</field>
<field name="arch" type="xml">
<tree string="Test Method">
<field name="name" />
</tree>
</field>
</record>
<record model="ir.actions.act_window" id="action_qc_proof_method">
<field name="name">Methods</field>
<field name="res_model">qc.proof.method</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem name="Method" parent="qc_menu_config" id="qc_proof_method_menu"
action="action_qc_proof_method" />
<!-- qc.posible.value -->
<record model="ir.ui.view" id="qc_posible_value_form_view">
<field name="name">qc.posible.value.form</field>
<field name="model">qc.posible.value</field>
<field name="arch" type="xml">
<form string="Proof Posible Value">
<group colspan="4" col="10">
<field name="name" colspan="6"/>
<field name="active" colspan="2" />
<field name="ok" colspan="2" />
</group>
</form>
</field>
</record>
<record model="ir.ui.view" id="qc_posible_value_tree_view">
<field name="name">qc.posible_value.tree</field>
<field name="model">qc.posible.value</field>
<field name="arch" type="xml">
<tree string="Posible Value">
<field name="name" />
<field name="ok" />
</tree>
</field>
</record>
<record model="ir.actions.act_window" id="action_qc_posible_value">
<field name="name">Posible Values</field>
<field name="res_model">qc.posible.value</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem name="Posible Values" parent="qc_menu_config"
id="qc_proof_posible_value_menu" action="action_qc_posible_value" />
<!-- qc.test.template.trigger -->
<record model="ir.ui.view" id="qc_test_template_trigger_form_view">
<field name="name">qc.test.template.trigger.form</field>
<field name="model">qc.test.template.trigger</field>
<field name="arch" type="xml">
<form string="Template Trigger">
<group>
<field name="name" />
<field name="active" />
</group>
</form>
</field>
</record>
<record model="ir.ui.view" id="qc_test_template_trigger_tree_view">
<field name="name">qc.test.template.trigger.tree</field>
<field name="model">qc.test.template.trigger</field>
<field name="arch" type="xml">
<tree string="Template Trigger">
<field name="name" select="1" />
</tree>
</field>
</record>
<record model="ir.actions.act_window" id="action_qc_test_template_trigger">
<field name="name">Template Trigger</field>
<field name="res_model">qc.test.template.trigger</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem name="Template Trigger" parent="qc_menu_config"
id="qc_test_template_trigger_menu" action="action_qc_test_template_trigger" />
<!-- qc.proof.synonym -->
<record model="ir.ui.view" id="qc_proof_synonym_form_view">
<field name="name">qc.proof.synonym</field>
<field name="model">qc.proof.synonym</field>
<field name="arch" type="xml">
<form string="Proof Synonym">
<group>
<field name="name" />
<field name="proof_id"/>
</group>
</form>
</field>
</record>
<record model="ir.ui.view" id="qc_test_synonym_tree_view">
<field name="name">qc.proof.synonym.tree</field>
<field name="model">qc.proof.synonym</field>
<field name="arch" type="xml">
<tree string="Test Synonym">
<field name="name" />
<field name="proof_id"/>
</tree>
</field>
</record>
<record model="ir.actions.act_window" id="action_proof_synonym">
<field name="name">Synonym</field>
<field name="res_model">qc.proof.synonym</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem name="Synonyms" parent="qc_menu_config"
id="qc_proof_synonyms_menu" action="action_proof_synonym" />
<!-- qc.proof -->
<record model="ir.ui.view" id="qc_proof_form_view">
<field name="name">qc.proof.form</field>
<field name="model">qc.proof</field>
<field name="arch" type="xml">
<form string="Proof" col="6">
<group col="2" colspan="4">
<field name="name" />
<field name="ref" />
<field name="type" />
<field name="active" />
</group>
<group col="2" colspan="4">
<separator string="Synonyms" colspan="2"/>
<field name="synonym_ids" nolabel="1" />
<group
attrs="{'invisible':[('type','!=','qualitative')]}"
col="2" colspan="2">
<separator string="Posible Values" colspan="2"/>
<field name="value_ids" nolabel="1"
colspan="2"
attrs="{'required':[('type','=','qualitative')]}" />
</group>
</group>
</form>
</field>
</record>
<record model="ir.ui.view" id="qc_proof_tree_view">
<field name="name">qc.proof.tree</field>
<field name="model">qc.proof</field>
<field name="arch" type="xml">
<tree string="Proof">
<field name="ref" select="1" />
<field name="name" />
<field name="type" />
</tree>
</field>
</record>
<record model="ir.actions.act_window" id="action_qc_proof">
<field name="name">Proof</field>
<field name="res_model">qc.proof</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem name="Proof" parent="qc_menu_config" id="qc_proof_menu"
action="action_qc_proof" />
<record model="ir.ui.view" id="qc_test_template_category_form_view">
<field name="name">qc.test.template.category.form</field>
<field name="model">qc.test.template.category</field>
<field name="arch" type="xml">
<form string="Test Template Category">
<group>
<field name="complete_name"/>
<field name="name"/>
<field name="parent_id"/>
<field name="active"/>
</group>
<group col="1">
<separator string="Child Categories"/>
<field name="child_ids" nolabel="1"/>
</group>
</form>
</field>
</record>
<record model="ir.ui.view" id="qc_test_template_category_tree_view">
<field name="name">qc.test.template.category.tree</field>
<field name="model">qc.test.template.category</field>
<field name="arch" type="xml">
<tree string="Test Template Category">
<field name="complete_name"/>
<field name="name"/>
<field name="parent_id"/>
<field name="active"/>
</tree>
</field>
</record>
<record model="ir.actions.act_window" id="action_qc_test_template_category">
<field name="name">Test Template Category</field>
<field name="res_model">qc.test.template.category</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem name="Test Template Categories" parent="qc_menu_config" id="qc_template_category_menu"
action="action_qc_test_template_category"/>
<menuitem name="Test Templates" parent="qc_menu_config"
id="qc_menu_config_templates" sequence="10" />
<!-- qc.test.template -->
<record model="ir.ui.view" id="qc_test_template_form_view">
<field name="name">qc.test.template.form</field>
<field name="model">qc.test.template</field>
<field name="priority">8</field>
<field name="arch" type="xml">
<form string="Test Template">
<sheet>
<h1>
<field name="name" class="oe_inline"/>
</h1>
<group col="2" colspan="4">
<field name="type" />
<field name="active" />
</group>
<group colspan="4" col="2">
<field name="category_id" />
<field name="fill_correct_values" />
<field name="trig_on" />
</group>
<group col="2" colspan="4"
attrs="{'invisible':[('type','=','generic')]}">
<field name="object_id" />
</group>
<field name="test_template_line_ids"
nolabel="1" colspan="4" />
</sheet>
</form>
</field>
</record>
<record model="ir.ui.view" id="qc_test_template_tree_view">
<field name="name">qc.test.template_tree</field>
<field name="model">qc.test.template</field>
<field name="arch" type="xml">
<tree string="Test Template">
<field name="name" />
<field name="type" />
<field name="category_id" />
<field name="object_id" />
<field name="test_template_line_ids" />
</tree>
</field>
</record>
<record model="ir.actions.act_window" id="action_qc_test_template">
<field name="name">Test Template</field>
<field name="res_model">qc.test.template</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem name="Test Template" parent="qc_menu_config_templates"
id="qc_test_template_menu" action="action_qc_test_template" />
<!-- qc.test.template.line -->
<record model="ir.ui.view" id="qc_test_template_line_form_view">
<field name="name">qc.test.template.line.form</field>
<field name="model">qc.test.template.line</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="proof Line">
<group col="8" colspan="4">
<field name="proof_id" on_change="onchange_proof_id(proof_id)" />
<field name="method_id" />
<field name="type" />
<field name="sequence" />
</group>
<group col="1" colspan="4">
<group col="2" colspan="4"
attrs="{'invisible':[('type','!=','qualitative')]}">
<field name="valid_value_ids" colspan="4"
attrs="{'required':[('type','=','qualitative')]}"
context="{'proof_id':proof_id}" />
</group>
<group col="6" colspan="4"
attrs="{'invisible':[('type','=','qualitative')]}">
<field name="min_value"
attrs="{'required':[('type','!=','qualitative')]}" />
<field name="max_value"
attrs="{'required':[('type','!=','qualitative')]}" />
<field name="uom_id"
attrs="{'required':[('type','!=','qualitative')]}" />
</group>
</group>
<field name="notes" colspan="4" />
</form>
</field>
</record>
<record model="ir.ui.view" id="qc_test_template_line_tree_view">
<field name="name">qc.test.template,line.tree</field>
<field name="model">qc.test.template.line</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Test Template Line" editable="bottom">
<field name="test_template_id" select="1" />
<field name="proof_id" select="1" />
<field name="method_id" select="1" />
<field name="type" select="1" />
<field name="notes" />
<field name="min_value" />
<field name="max_value" />
<field name="uom_id" />
<field name="sequence" />
<field name="valid_value_ids" />
</tree>
</field>
</record>
<record model="ir.actions.act_window" id="action_qc_test_template_line">
<field name="name">Test Template Line</field>
<field name="res_model">qc.test.template.line</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem name="Test Template Lines" parent="qc_menu_config_templates"
id="qc_test_template_line_menu" action="action_qc_test_template_line" />
<menuitem name="Tests" parent="qc_menu" id="qc_menu_tests"
sequence="10" />
<!-- qc.test -->
<record model="ir.ui.view" id="qc_test_form_view">
<field name="name">qc.test.form</field>
<field name="model">qc.test</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Test">
<header>
<button name="draft" states="canceled"
string="Draft" icon="gtk-ok" />
<button name="confirm" states="draft"
string="Confirm" icon="gtk-ok" />
<button name="approve" states="waiting"
string="Approve" icon="gtk-ok" />
<button name="cancel" states="waiting,failed,success"
string="Cancel" icon="gtk-cancel" />
<field name="state" widget="statusbar"
statusbar_visible="draft,waiting,success"
statusbar_colors='{"success":"blue","failed":"red"}' />
</header>
<sheet>
<div class="oe_title">
<label for="name" class="oe_edit_only" string="Test Name"/>
<h1>
<field name="name" string="Test Name"/>
</h1>
</div>
<div class="oe_right oe_button_box" name="buttons">
<button class="oe_inline oe_stat_button" type="action"
name="%(action_qc_test_set_template_wizard_form)d" icon="fa-bookmark-o" string="Template"/>
</div>
<group>
<field name="object_id" />
<field name="test_template_id"
readonly="True" select="1" />
</group>
<notebook>
<page string="questions">
<field name="test_line_ids"
nolabel="1" colspan="4" />
</page>
<page string="Notes">
<separator string="Internal Note" />
<field name="test_internal_note"
nolabel="1" select="2" />
<separator string="External Note" />
<field name="test_external_note"
nolabel="1" select="2" />
</page>
</notebook>
<footer>
<group col="4">
<field name="success" />
<field name="enabled" />
</group>
</footer>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers" groups="base.group_user"/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
</record>
<record model="ir.ui.view" id="qc_test_tree_view">
<field name="name">qc.test.tree</field>
<field name="model">qc.test</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Test">
<field name="name" />
<field name="test_template_id" />
<field name="state" />
<field name="success" />
</tree>
</field>
</record>
<record model="ir.ui.view" id="qc_test_search_view">
<field name="name">qc.test.extended.search.vieww</field>
<field name="model">qc.test</field>
<field name="arch" type="xml">
<search string="Search Test">
<group>
<field name="name" />
<field name="object_id" />
<field name="test_template_id" />
<field name="state" />
<field name="success" />
<field name="enabled" />
</group>
<newline />
<group expand="0" string="Group By...">
<filter string="Reference" domain="[]"
context="{'group_by':'object_id'}" />
<filter string="Template" domain="[]"
context="{'group_by':'test_template_id'}" />
<filter string="State" domain="[]"
context="{'group_by':'state'}" />
<filter string="Success" domain="[]"
context="{'group_by':'success'}" />
<filter string="Enabled" domain="[]"
context="{'group_by':'enabled'}" />
</group>
</search>
</field>
</record>
<record model="ir.actions.act_window" id="action_qc_new_test">
<field name="name">Test</field>
<field name="res_model">qc.test</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem name="Tests" parent="qc_menu_tests" id="qc_test_menu"
action="action_qc_new_test" />
<!-- qc.test.line -->
<record model="ir.ui.view" id="qc_test_line_form_view">
<field name="name">qc.test.line.form</field>
<field name="model">qc.test.line</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Test Line">
<sheet>
<group colspan="4"
attrs="{'invisible':[('proof_type','=','qualitative')]}">
<separator string="Test Result"
colspan="4" />
<field name="actual_value_qt"
on_change="onchange_actual_value_qt(uom_id, test_uom_id, actual_value_qt, min_value, max_value)" />
<field name="test_uom_id" />
</group>
<group col="2" colspan="4"
attrs="{'invisible':[('proof_type','!=','qualitative')]}">
<separator string="Test Values"
colspan="2" />
<field name="actual_value_ql"
on_change="onchange_actual_value_ql(actual_value_ql, valid_value_ids)" />
</group>
<group colspan="4">
<separator string="Check Values"
colspan="4" />
<group col="6" colspan="4">
<field name="proof_id" />
<field name="method_id" />
<field name="proof_type" />
</group>
<group colspan="4"
attrs="{'invisible':[('proof_type','!=','qualitative')]}">
<field name="valid_value_ids" />
</group>
<group col="6" colspan="4"
attrs="{'invisible':[('proof_type','=','qualitative')]}">
<field name="min_value" />
<field name="max_value" />
<field name="uom_id" />
</group>
<field name="notes" colspan="4" />
</group>
<field name="success" />
</sheet>
</form>
</field>
</record>
<record model="ir.ui.view" id="qc_test_line_tree_view">
<field name="name">qc.test.line.tree</field>
<field name="model">qc.test.line</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Test Line" editable="top">
<field name="proof_id" />
<field name="method_id" />
<field name="proof_type" />
<field name="actual_value_ql"
attrs="{'readonly':[('proof_type','=','quantitative')]}"
on_change="onchange_actual_value_ql(actual_value_ql, valid_value_ids)" />
<field name="valid_value_ids" readonly="1" invisible="1" />
<field name="actual_value_qt"
attrs="{'readonly':[('proof_type','=','qualitative')]}"
on_change="onchange_actual_value_qt(uom_id, test_uom_id, actual_value_qt, min_value, max_value)" />
<field name="test_uom_id" />
<field name="min_value" />
<field name="max_value" />
<field name="uom_id" />
<field name="success" />
</tree>
</field>
</record>
<record model="ir.actions.act_window" id="action_qc_test_line">
<field name="name">Test Line</field>
<field name="res_model">qc.test.line</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem name="Test Lines" parent="qc_menu_tests" id="qc_test_lines_menu"
action="action_qc_test_line" />
</data>
</openerp>

View File

@@ -1,31 +1,5 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2010 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 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 General Public License for more details.
#
# You should have received a copy of the GNU 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.
#
# For copyright and license notices, see __openerp__.py file in root directory
##############################################################################
from . import qc_test_wizard

View File

@@ -1,70 +1,23 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2010 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 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 General Public License for more details.
#
# You should have received a copy of the GNU 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.
#
# For copyright and license notices, see __openerp__.py file in root directory
##############################################################################
from openerp.osv import orm, fields
from openerp import models, fields, api
class QcTestWizard(orm.TransientModel):
class QcInspectionSetTest(models.TransientModel):
"""This wizard is responsible for setting the test for a given
inspection. This will not only fill in the 'test' field, but will
also fill in all lines of the inspection with the corresponding lines of
the template.
"""
This wizard is responsible for setting the proof template for a given test.
This will not only fill in the 'test_template_id' field, but will also fill
in all lines of the test with the corresponding lines of the template.
"""
_name = 'qc.test.set.template.wizard'
_name = 'qc.inspection.set.test'
def _default_test_template_id(self, cr, uid, context=None):
test = self.pool['qc.test'].browse(
cr, uid, context.get('active_id', False), context=context)
cond = [('object_id', '=', test.object_id.id)]
ids = self.pool['qc.test.template'].search(cr, uid, cond,
context=context)
return ids and ids[0] or False
test = fields.Many2one(comodel_name='qc.test', string='Test')
_columns = {
'test_template_id': fields.many2one('qc.test.template', 'Template'),
}
_defaults = {
'test_template_id': _default_test_template_id,
}
def action_create_test(self, cr, uid, ids, context=None):
wizard = self.browse(cr, uid, ids[0], context=context)
self.pool['qc.test'].set_test_template(cr, uid, [context['active_id']],
wizard.test_template_id.id,
context=context)
return {
'type': 'ir.actions.act_window_close',
}
def action_cancel(self, cr, uid, ids, context=None):
return {
'type': 'ir.actions.act_window_close',
}
@api.multi
def action_create_test(self):
inspection_obj = self.env['qc.inspection']
inspection_obj.browse(self.env.context['active_id']).set_test(
self.test)
return True

View File

@@ -1,31 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<openerp>
<data>
<!-- qc.test.set.template.wizard -->
<record id="view_qc_test_set_template_wizard_form" model="ir.ui.view">
<field name="name">qc.test.set.template.wizard</field>
<field name="model">qc.test.set.template.wizard</field>
<record id="view_qc_test_set_test_form" model="ir.ui.view">
<field name="name">qc.inspection.set.test.form</field>
<field name="model">qc.inspection.set.test</field>
<field name="arch" type="xml">
<form string="Select Test Template" version="7.0">
<form string="Select test" version="7.0">
<group>
<field name="test_template_id" />
<field name="test" />
</group>
<footer>
<button name="action_create_test"
string="Accept" type="object" class="oe_highlight"/>
string="Accept"
type="object"
class="oe_highlight"/>
or
<button special="cancel" class="oe_link"
string="Cancel" />
<button special="cancel"
class="oe_link"
string="Cancel" />
</footer>
</form>
</field>
</record>
<record id="action_qc_test_set_template_wizard_form"
model="ir.actions.act_window">
<field name="name">Select Test Template</field>
<record id="action_qc_inspection_set_test" model="ir.actions.act_window">
<field name="name">Select test</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">qc.test.set.template.wizard</field>
<field name="res_model">qc.inspection.set.test</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>

View File

@@ -1,90 +0,0 @@
<?xml version="1.0" ?>
<openerp>
<data>
<record model="workflow" id="wkf_qc_test">
<field name="name">quality.control.basic</field>
<field name="osv">qc.test</field>
<field name="on_create">True</field>
</record>
<!-- states -->
<record id="qc-draft" model="workflow.activity">
<field name="wkf_id" ref="wkf_qc_test" />
<field name="flow_start">True</field>
<field name="name">draft</field>
<field name="kind">function</field>
<field name="action">write({'state': 'draft'})</field>
<field name="signal_send">subflow.draft</field>
</record>
<record id="qc-cancel" model="workflow.activity">
<field name="wkf_id" ref="wkf_qc_test" />
<field name="name">canceled</field>
<field name="kind">function</field>
<field name="action">write({'state': 'canceled'})</field>
<field name="signal_send">subflow.waiting</field>
</record>
<record id="qc-waiting" model="workflow.activity">
<field name="wkf_id" ref="wkf_qc_test" />
<field name="name">waiting</field>
<field name="kind">function</field>
<field name="action">write({'state': 'waiting'})</field>
<field name="signal_send">subflow.waiting</field>
</record>
<record id="qc-success" model="workflow.activity">
<field name="wkf_id" ref="wkf_qc_test" />
<field name="name">success</field>
<field name="kind">function</field>
<field name="action">write({'state': 'success'})</field>
<field name="signal_send">subflow.success</field>
</record>
<record id="qc-failed" model="workflow.activity">
<field name="wkf_id" ref="wkf_qc_test" />
<field name="name">failed</field>
<field name="kind">function</field>
<field name="action">write({'state': 'failed'})</field>
<field name="signal_send">subflow.failed</field>
</record>
<!-- transitions -->
<record id="trans_draft_waiting" model="workflow.transition">
<field name="act_from" ref="qc-draft" />
<field name="act_to" ref="qc-waiting" />
<field name="signal">confirm</field>
</record>
<record id="trans_waiting_failed" model="workflow.transition">
<field name="act_from" ref="qc-waiting" />
<field name="act_to" ref="qc-failed" />
<field name="condition">not success</field>
<field name="signal">approve</field>
</record>
<record id="trans_waiting_success" model="workflow.transition">
<field name="act_from" ref="qc-waiting" />
<field name="act_to" ref="qc-success" />
<field name="condition">success</field>
<field name="signal">approve</field>
</record>
<record id="trans_waiting_draft" model="workflow.transition">
<field name="act_from" ref="qc-waiting" />
<field name="act_to" ref="qc-cancel" />
<field name="signal">cancel</field>
</record>
<record id="trans_failed_draft" model="workflow.transition">
<field name="act_from" ref="qc-failed" />
<field name="act_to" ref="qc-cancel" />
<field name="condition">enabled</field>
<field name="signal">cancel</field>
</record>
<record id="trans_success_draft" model="workflow.transition">
<field name="act_from" ref="qc-success" />
<field name="act_to" ref="qc-cancel" />
<field name="condition">enabled</field>
<field name="signal">cancel</field>
</record>
<record id="trans_cancel_draft" model="workflow.transition">
<field name="act_from" ref="qc-cancel" />
<field name="act_to" ref="qc-draft" />
<field name="condition">enabled</field>
<field name="signal">draft</field>
</record>
</data>
</openerp>