mirror of
https://github.com/OCA/manufacture.git
synced 2025-01-28 16:37:15 +02:00
[IMP] quality_control: black, isort
This commit is contained in:
committed by
Enrique Martín
parent
7c94dfb8f8
commit
d6bd05b4b4
@@ -7,16 +7,13 @@
|
|||||||
|
|
||||||
{
|
{
|
||||||
"name": "Quality control",
|
"name": "Quality control",
|
||||||
"version": "12.0.1.2.0",
|
"version": "13.0.1.0.0",
|
||||||
"category": "Quality control",
|
"category": "Quality control",
|
||||||
"license": "AGPL-3",
|
"license": "AGPL-3",
|
||||||
"summary": "Generic infrastructure for quality tests.",
|
"summary": "Generic infrastructure for quality tests.",
|
||||||
"author": "OdooMRP team, "
|
"author": "OdooMRP team, " "Odoo Community Association (OCA)",
|
||||||
"Odoo Community Association (OCA)",
|
|
||||||
"website": "https://github.com/OCA/manufacture/tree/12.0/quality_control",
|
"website": "https://github.com/OCA/manufacture/tree/12.0/quality_control",
|
||||||
"depends": [
|
"depends": ["product"],
|
||||||
"product",
|
|
||||||
],
|
|
||||||
"data": [
|
"data": [
|
||||||
"data/quality_control_data.xml",
|
"data/quality_control_data.xml",
|
||||||
"security/quality_control_security.xml",
|
"security/quality_control_security.xml",
|
||||||
@@ -30,8 +27,6 @@
|
|||||||
"views/product_template_view.xml",
|
"views/product_template_view.xml",
|
||||||
"views/product_category_view.xml",
|
"views/product_category_view.xml",
|
||||||
],
|
],
|
||||||
"demo": [
|
"demo": ["demo/quality_control_demo.xml"],
|
||||||
"demo/quality_control_demo.xml",
|
|
||||||
],
|
|
||||||
"installable": True,
|
"installable": True,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<!-- Copyright 2010 NaN Projectes de Programari Lliure, S.L.
|
<!-- Copyright 2010 NaN Projectes de Programari Lliure, S.L.
|
||||||
Copyright 2014 Serv. Tec. Avanzados - Pedro M. Baeza
|
Copyright 2014 Serv. Tec. Avanzados - Pedro M. Baeza
|
||||||
Copyright 2014 Oihane Crucelaegui - AvanzOSC
|
Copyright 2014 Oihane Crucelaegui - AvanzOSC
|
||||||
@@ -10,17 +10,18 @@
|
|||||||
<record id="qc_test_template_category_generic" model="qc.test.category">
|
<record id="qc_test_template_category_generic" model="qc.test.category">
|
||||||
<field name="name">Generic</field>
|
<field name="name">Generic</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="qc_test_template_category_referenced" model="qc.test.category">
|
<record id="qc_test_template_category_referenced" model="qc.test.category">
|
||||||
<field name="name">Referenced</field>
|
<field name="name">Referenced</field>
|
||||||
</record>
|
</record>
|
||||||
|
<record
|
||||||
<record forcecreate="True" id="decimal_quality_control" model="decimal.precision">
|
forcecreate="True"
|
||||||
|
id="decimal_quality_control"
|
||||||
|
model="decimal.precision"
|
||||||
|
>
|
||||||
<field name="name">Quality Control</field>
|
<field name="name">Quality Control</field>
|
||||||
<field name="digits">5</field>
|
<field name="digits">5</field>
|
||||||
</record>
|
</record>
|
||||||
</data>
|
</data>
|
||||||
|
|
||||||
<data>
|
<data>
|
||||||
<record id="seq_qc_inspection" model="ir.sequence">
|
<record id="seq_qc_inspection" model="ir.sequence">
|
||||||
<field name="name">Quality inspection</field>
|
<field name="name">Quality inspection</field>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
<odoo>
|
<odoo>
|
||||||
<data noupdate="1">
|
<data noupdate="1">
|
||||||
<record model="qc.test" id="qc_test_1">
|
<record model="qc.test" id="qc_test_1">
|
||||||
@@ -7,25 +7,21 @@
|
|||||||
<field name="active" eval="True" />
|
<field name="active" eval="True" />
|
||||||
<field name="category" ref="qc_test_template_category_generic" />
|
<field name="category" ref="qc_test_template_category_generic" />
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="qc.test.question" id="qc_test_question_1">
|
<record model="qc.test.question" id="qc_test_question_1">
|
||||||
<field name="name">Overall quality</field>
|
<field name="name">Overall quality</field>
|
||||||
<field name="test" ref="qc_test_1" />
|
<field name="test" ref="qc_test_1" />
|
||||||
<field name="type">qualitative</field>
|
<field name="type">qualitative</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="qc.test.question.value" id="qc_test_question_value_1">
|
<record model="qc.test.question.value" id="qc_test_question_value_1">
|
||||||
<field name="name">Good</field>
|
<field name="name">Good</field>
|
||||||
<field name="ok" eval="True" />
|
<field name="ok" eval="True" />
|
||||||
<field name="test_line" ref="qc_test_question_1" />
|
<field name="test_line" ref="qc_test_question_1" />
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="qc.test.question.value" id="qc_test_question_value_2">
|
<record model="qc.test.question.value" id="qc_test_question_value_2">
|
||||||
<field name="name">Bad</field>
|
<field name="name">Bad</field>
|
||||||
<field name="ok" eval="False" />
|
<field name="ok" eval="False" />
|
||||||
<field name="test_line" ref="qc_test_question_1" />
|
<field name="test_line" ref="qc_test_question_1" />
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="qc.test.question" id="qc_test_question_2">
|
<record model="qc.test.question" id="qc_test_question_2">
|
||||||
<field name="name">Size</field>
|
<field name="name">Size</field>
|
||||||
<field name="test" ref="qc_test_1" />
|
<field name="test" ref="qc_test_1" />
|
||||||
@@ -34,6 +30,5 @@
|
|||||||
<field name="max_value" eval="10.0" />
|
<field name="max_value" eval="10.0" />
|
||||||
<field name="uom_id" ref="uom.product_uom_unit" />
|
<field name="uom_id" ref="uom.product_uom_unit" />
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
</data>
|
</data>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -14,4 +14,5 @@ class ProductCategory(models.Model):
|
|||||||
qc_triggers = fields.One2many(
|
qc_triggers = fields.One2many(
|
||||||
comodel_name="qc.trigger.product_category_line",
|
comodel_name="qc.trigger.product_category_line",
|
||||||
inverse_name="product_category",
|
inverse_name="product_category",
|
||||||
string="Quality control triggers")
|
string="Quality control triggers",
|
||||||
|
)
|
||||||
|
|||||||
@@ -12,5 +12,7 @@ class ProductProduct(models.Model):
|
|||||||
_inherit = "product.product"
|
_inherit = "product.product"
|
||||||
|
|
||||||
qc_triggers = fields.One2many(
|
qc_triggers = fields.One2many(
|
||||||
comodel_name="qc.trigger.product_line", inverse_name="product",
|
comodel_name="qc.trigger.product_line",
|
||||||
string="Quality control triggers")
|
inverse_name="product",
|
||||||
|
string="Quality control triggers",
|
||||||
|
)
|
||||||
|
|||||||
@@ -14,4 +14,5 @@ class ProductTemplate(models.Model):
|
|||||||
qc_triggers = fields.One2many(
|
qc_triggers = fields.One2many(
|
||||||
comodel_name="qc.trigger.product_template_line",
|
comodel_name="qc.trigger.product_template_line",
|
||||||
inverse_name="product_template",
|
inverse_name="product_template",
|
||||||
string="Quality control triggers")
|
string="Quality control triggers",
|
||||||
|
)
|
||||||
|
|||||||
@@ -5,17 +5,18 @@
|
|||||||
# Copyright 2017 Simone Rubino - Agile Business Group
|
# Copyright 2017 Simone Rubino - Agile Business Group
|
||||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
from odoo import api, exceptions, fields, models, _
|
from odoo import _, api, exceptions, fields, models
|
||||||
from odoo.tools import formatLang
|
from odoo.tools import formatLang
|
||||||
|
|
||||||
import odoo.addons.decimal_precision as dp
|
import odoo.addons.decimal_precision as dp
|
||||||
|
|
||||||
|
|
||||||
class QcInspection(models.Model):
|
class QcInspection(models.Model):
|
||||||
_name = 'qc.inspection'
|
_name = "qc.inspection"
|
||||||
_description = 'Quality control inspection'
|
_description = "Quality control inspection"
|
||||||
_inherit = ['mail.thread', 'mail.activity.mixin']
|
_inherit = ["mail.thread", "mail.activity.mixin"]
|
||||||
|
|
||||||
@api.depends('inspection_lines', 'inspection_lines.success')
|
@api.depends("inspection_lines", "inspection_lines.success")
|
||||||
def _compute_success(self):
|
def _compute_success(self):
|
||||||
for i in self:
|
for i in self:
|
||||||
i.success = all([x.success for x in i.inspection_lines])
|
i.success = all([x.success for x in i.inspection_lines])
|
||||||
@@ -28,74 +29,106 @@ class QcInspection(models.Model):
|
|||||||
"""
|
"""
|
||||||
return list()
|
return list()
|
||||||
|
|
||||||
@api.depends('object_id')
|
@api.depends("object_id")
|
||||||
def _compute_product_id(self):
|
def _compute_product_id(self):
|
||||||
for i in self:
|
for i in self:
|
||||||
if i.object_id and i.object_id._name == 'product.product':
|
if i.object_id and i.object_id._name == "product.product":
|
||||||
i.product_id = i.object_id
|
i.product_id = i.object_id
|
||||||
else:
|
else:
|
||||||
i.product_id = False
|
i.product_id = False
|
||||||
|
|
||||||
name = fields.Char(
|
name = fields.Char(
|
||||||
string='Inspection number', required=True, default='/',
|
string="Inspection number",
|
||||||
readonly=True, states={'draft': [('readonly', False)]}, copy=False)
|
required=True,
|
||||||
|
default="/",
|
||||||
|
readonly=True,
|
||||||
|
states={"draft": [("readonly", False)]},
|
||||||
|
copy=False,
|
||||||
|
)
|
||||||
date = fields.Datetime(
|
date = fields.Datetime(
|
||||||
string='Date', required=True, readonly=True, copy=False,
|
string="Date",
|
||||||
|
required=True,
|
||||||
|
readonly=True,
|
||||||
|
copy=False,
|
||||||
default=fields.Datetime.now,
|
default=fields.Datetime.now,
|
||||||
states={'draft': [('readonly', False)]})
|
states={"draft": [("readonly", False)]},
|
||||||
|
)
|
||||||
object_id = fields.Reference(
|
object_id = fields.Reference(
|
||||||
string='Reference',
|
string="Reference",
|
||||||
selection=lambda self: self.object_selection_values(),
|
selection=lambda self: self.object_selection_values(),
|
||||||
readonly=True, states={'draft': [('readonly', False)]},
|
readonly=True,
|
||||||
ondelete="set null")
|
states={"draft": [("readonly", False)]},
|
||||||
|
ondelete="set null",
|
||||||
|
)
|
||||||
product_id = fields.Many2one(
|
product_id = fields.Many2one(
|
||||||
comodel_name="product.product", compute="_compute_product_id",
|
comodel_name="product.product",
|
||||||
store=True, help="Product associated with the inspection",
|
compute="_compute_product_id",
|
||||||
oldname='product')
|
store=True,
|
||||||
|
help="Product associated with the inspection",
|
||||||
|
oldname="product",
|
||||||
|
)
|
||||||
qty = fields.Float(string="Quantity", default=1.0)
|
qty = fields.Float(string="Quantity", default=1.0)
|
||||||
test = fields.Many2one(
|
test = fields.Many2one(comodel_name="qc.test", string="Test", readonly=True)
|
||||||
comodel_name='qc.test', string='Test', readonly=True)
|
|
||||||
inspection_lines = fields.One2many(
|
inspection_lines = fields.One2many(
|
||||||
comodel_name='qc.inspection.line', inverse_name='inspection_id',
|
comodel_name="qc.inspection.line",
|
||||||
string='Inspection lines', readonly=True,
|
inverse_name="inspection_id",
|
||||||
states={'ready': [('readonly', False)]})
|
string="Inspection lines",
|
||||||
internal_notes = fields.Text(string='Internal notes')
|
readonly=True,
|
||||||
|
states={"ready": [("readonly", False)]},
|
||||||
|
)
|
||||||
|
internal_notes = fields.Text(string="Internal notes")
|
||||||
external_notes = fields.Text(
|
external_notes = fields.Text(
|
||||||
string='External notes',
|
string="External notes",
|
||||||
states={'success': [('readonly', True)],
|
states={"success": [("readonly", True)], "failed": [("readonly", True)]},
|
||||||
'failed': [('readonly', True)]})
|
)
|
||||||
state = fields.Selection(
|
state = fields.Selection(
|
||||||
[('draft', 'Draft'),
|
[
|
||||||
('ready', 'Ready'),
|
("draft", "Draft"),
|
||||||
('waiting', 'Waiting supervisor approval'),
|
("ready", "Ready"),
|
||||||
('success', 'Quality success'),
|
("waiting", "Waiting supervisor approval"),
|
||||||
('failed', 'Quality failed'),
|
("success", "Quality success"),
|
||||||
('canceled', 'Canceled')],
|
("failed", "Quality failed"),
|
||||||
string='State', readonly=True, default='draft',
|
("canceled", "Canceled"),
|
||||||
track_visibility='onchange')
|
],
|
||||||
|
string="State",
|
||||||
|
readonly=True,
|
||||||
|
default="draft",
|
||||||
|
track_visibility="onchange",
|
||||||
|
)
|
||||||
success = fields.Boolean(
|
success = fields.Boolean(
|
||||||
compute="_compute_success", string='Success',
|
compute="_compute_success",
|
||||||
help='This field will be marked if all tests have succeeded.',
|
string="Success",
|
||||||
store=True)
|
help="This field will be marked if all tests have succeeded.",
|
||||||
|
store=True,
|
||||||
|
)
|
||||||
auto_generated = fields.Boolean(
|
auto_generated = fields.Boolean(
|
||||||
string='Auto-generated', readonly=True, copy=False,
|
string="Auto-generated",
|
||||||
help='If an inspection is auto-generated, it can be canceled but not '
|
readonly=True,
|
||||||
'removed.')
|
copy=False,
|
||||||
|
help="If an inspection is auto-generated, it can be canceled but not "
|
||||||
|
"removed.",
|
||||||
|
)
|
||||||
company_id = fields.Many2one(
|
company_id = fields.Many2one(
|
||||||
comodel_name='res.company', string='Company', readonly=True,
|
comodel_name="res.company",
|
||||||
states={'draft': [('readonly', False)]},
|
string="Company",
|
||||||
default=lambda self: self.env['res.company']._company_default_get(
|
readonly=True,
|
||||||
'qc.inspection'))
|
states={"draft": [("readonly", False)]},
|
||||||
|
default=lambda self: self.env["res.company"]._company_default_get(
|
||||||
|
"qc.inspection"
|
||||||
|
),
|
||||||
|
)
|
||||||
user = fields.Many2one(
|
user = fields.Many2one(
|
||||||
comodel_name='res.users', string='Responsible',
|
comodel_name="res.users",
|
||||||
track_visibility='always', default=lambda self: self.env.user)
|
string="Responsible",
|
||||||
|
track_visibility="always",
|
||||||
|
default=lambda self: self.env.user,
|
||||||
|
)
|
||||||
|
|
||||||
@api.model_create_multi
|
@api.model_create_multi
|
||||||
def create(self, val_list):
|
def create(self, val_list):
|
||||||
for vals in val_list:
|
for vals in val_list:
|
||||||
if vals.get('name', '/') == '/':
|
if vals.get("name", "/") == "/":
|
||||||
vals['name'] = self.env['ir.sequence'] \
|
vals["name"] = self.env["ir.sequence"].next_by_code("qc.inspection")
|
||||||
.next_by_code('qc.inspection')
|
|
||||||
return super(QcInspection, self).create(vals)
|
return super(QcInspection, self).create(vals)
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
@@ -103,68 +136,74 @@ class QcInspection(models.Model):
|
|||||||
for inspection in self:
|
for inspection in self:
|
||||||
if inspection.auto_generated:
|
if inspection.auto_generated:
|
||||||
raise exceptions.UserError(
|
raise exceptions.UserError(
|
||||||
_("You cannot remove an auto-generated inspection."))
|
_("You cannot remove an auto-generated inspection.")
|
||||||
if inspection.state != 'draft':
|
)
|
||||||
|
if inspection.state != "draft":
|
||||||
raise exceptions.UserError(
|
raise exceptions.UserError(
|
||||||
_("You cannot remove an inspection that is not in draft "
|
_("You cannot remove an inspection that is not in draft " "state.")
|
||||||
"state."))
|
)
|
||||||
return super(QcInspection, self).unlink()
|
return super(QcInspection, self).unlink()
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def action_draft(self):
|
def action_draft(self):
|
||||||
self.write({'state': 'draft'})
|
self.write({"state": "draft"})
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def action_todo(self):
|
def action_todo(self):
|
||||||
for inspection in self:
|
for inspection in self:
|
||||||
if not inspection.test:
|
if not inspection.test:
|
||||||
raise exceptions.UserError(
|
raise exceptions.UserError(_("You must first set the test to perform."))
|
||||||
_("You must first set the test to perform."))
|
self.write({"state": "ready"})
|
||||||
self.write({'state': 'ready'})
|
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def action_confirm(self):
|
def action_confirm(self):
|
||||||
for inspection in self:
|
for inspection in self:
|
||||||
for line in inspection.inspection_lines:
|
for line in inspection.inspection_lines:
|
||||||
if line.question_type == 'qualitative':
|
if line.question_type == "qualitative":
|
||||||
if not line.qualitative_value:
|
if not line.qualitative_value:
|
||||||
raise exceptions.UserError(
|
raise exceptions.UserError(
|
||||||
_("You should provide an answer for all "
|
_(
|
||||||
"qualitative questions."))
|
"You should provide an answer for all "
|
||||||
|
"qualitative questions."
|
||||||
|
)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
if not line.uom_id:
|
if not line.uom_id:
|
||||||
raise exceptions.UserError(
|
raise exceptions.UserError(
|
||||||
_("You should provide a unit of measure for "
|
_(
|
||||||
"quantitative questions."))
|
"You should provide a unit of measure for "
|
||||||
|
"quantitative questions."
|
||||||
|
)
|
||||||
|
)
|
||||||
if inspection.success:
|
if inspection.success:
|
||||||
inspection.state = 'success'
|
inspection.state = "success"
|
||||||
else:
|
else:
|
||||||
inspection.state = 'waiting'
|
inspection.state = "waiting"
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def action_approve(self):
|
def action_approve(self):
|
||||||
for inspection in self:
|
for inspection in self:
|
||||||
if inspection.success:
|
if inspection.success:
|
||||||
inspection.state = 'success'
|
inspection.state = "success"
|
||||||
else:
|
else:
|
||||||
inspection.state = 'failed'
|
inspection.state = "failed"
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def action_cancel(self):
|
def action_cancel(self):
|
||||||
self.write({'state': 'canceled'})
|
self.write({"state": "canceled"})
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def set_test(self, trigger_line, force_fill=False):
|
def set_test(self, trigger_line, force_fill=False):
|
||||||
for inspection in self:
|
for inspection in self:
|
||||||
header = self._prepare_inspection_header(
|
header = self._prepare_inspection_header(inspection.object_id, trigger_line)
|
||||||
inspection.object_id, trigger_line)
|
del header["state"] # don't change current status
|
||||||
del header['state'] # don't change current status
|
del header["auto_generated"] # don't change auto_generated flag
|
||||||
del header['auto_generated'] # don't change auto_generated flag
|
del header["user"] # don't change current user
|
||||||
del header['user'] # don't change current user
|
|
||||||
inspection.write(header)
|
inspection.write(header)
|
||||||
inspection.inspection_lines.unlink()
|
inspection.inspection_lines.unlink()
|
||||||
inspection.inspection_lines = inspection._prepare_inspection_lines(
|
inspection.inspection_lines = inspection._prepare_inspection_lines(
|
||||||
trigger_line.test, force_fill=force_fill)
|
trigger_line.test, force_fill=force_fill
|
||||||
|
)
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def _make_inspection(self, object_ref, trigger_line):
|
def _make_inspection(self, object_ref, trigger_line):
|
||||||
@@ -173,8 +212,9 @@ class QcInspection(models.Model):
|
|||||||
:param trigger_line: Trigger line instance
|
:param trigger_line: Trigger line instance
|
||||||
:return: Inspection object
|
:return: Inspection object
|
||||||
"""
|
"""
|
||||||
inspection = self.create(self._prepare_inspection_header(
|
inspection = self.create(
|
||||||
object_ref, trigger_line))
|
self._prepare_inspection_header(object_ref, trigger_line)
|
||||||
|
)
|
||||||
inspection.set_test(trigger_line)
|
inspection.set_test(trigger_line)
|
||||||
return inspection
|
return inspection
|
||||||
|
|
||||||
@@ -186,12 +226,13 @@ class QcInspection(models.Model):
|
|||||||
:return: List of values for creating the inspection
|
:return: List of values for creating the inspection
|
||||||
"""
|
"""
|
||||||
return {
|
return {
|
||||||
'object_id': object_ref and '%s,%s' % (object_ref._name,
|
"object_id": object_ref
|
||||||
object_ref.id) or False,
|
and "{},{}".format(object_ref._name, object_ref.id)
|
||||||
'state': 'ready',
|
or False,
|
||||||
'test': trigger_line.test.id,
|
"state": "ready",
|
||||||
'user': trigger_line.user.id,
|
"test": trigger_line.test.id,
|
||||||
'auto_generated': True,
|
"user": trigger_line.user.id,
|
||||||
|
"auto_generated": True,
|
||||||
}
|
}
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
@@ -199,113 +240,144 @@ class QcInspection(models.Model):
|
|||||||
new_data = []
|
new_data = []
|
||||||
for line in test.test_lines:
|
for line in test.test_lines:
|
||||||
data = self._prepare_inspection_line(
|
data = self._prepare_inspection_line(
|
||||||
test, line, fill=test.fill_correct_values or force_fill)
|
test, line, fill=test.fill_correct_values or force_fill
|
||||||
|
)
|
||||||
new_data.append((0, 0, data))
|
new_data.append((0, 0, data))
|
||||||
return new_data
|
return new_data
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def _prepare_inspection_line(self, test, line, fill=None):
|
def _prepare_inspection_line(self, test, line, fill=None):
|
||||||
data = {
|
data = {
|
||||||
'name': line.name,
|
"name": line.name,
|
||||||
'test_line': line.id,
|
"test_line": line.id,
|
||||||
'notes': line.notes,
|
"notes": line.notes,
|
||||||
'min_value': line.min_value,
|
"min_value": line.min_value,
|
||||||
'max_value': line.max_value,
|
"max_value": line.max_value,
|
||||||
'test_uom_id': line.uom_id.id,
|
"test_uom_id": line.uom_id.id,
|
||||||
'uom_id': line.uom_id.id,
|
"uom_id": line.uom_id.id,
|
||||||
'question_type': line.type,
|
"question_type": line.type,
|
||||||
'possible_ql_values': [x.id for x in line.ql_values]
|
"possible_ql_values": [x.id for x in line.ql_values],
|
||||||
}
|
}
|
||||||
if fill:
|
if fill:
|
||||||
if line.type == 'qualitative':
|
if line.type == "qualitative":
|
||||||
# Fill with the first correct value found
|
# Fill with the first correct value found
|
||||||
for value in line.ql_values:
|
for value in line.ql_values:
|
||||||
if value.ok:
|
if value.ok:
|
||||||
data['qualitative_value'] = value.id
|
data["qualitative_value"] = value.id
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
# Fill with a value inside the interval
|
# Fill with a value inside the interval
|
||||||
data['quantitative_value'] = (line.min_value +
|
data["quantitative_value"] = (line.min_value + line.max_value) * 0.5
|
||||||
line.max_value) * 0.5
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
class QcInspectionLine(models.Model):
|
class QcInspectionLine(models.Model):
|
||||||
_name = 'qc.inspection.line'
|
_name = "qc.inspection.line"
|
||||||
_description = "Quality control inspection line"
|
_description = "Quality control inspection line"
|
||||||
|
|
||||||
@api.depends('question_type', 'uom_id', 'test_uom_id', 'max_value',
|
@api.depends(
|
||||||
'min_value', 'quantitative_value', 'qualitative_value',
|
"question_type",
|
||||||
'possible_ql_values')
|
"uom_id",
|
||||||
|
"test_uom_id",
|
||||||
|
"max_value",
|
||||||
|
"min_value",
|
||||||
|
"quantitative_value",
|
||||||
|
"qualitative_value",
|
||||||
|
"possible_ql_values",
|
||||||
|
)
|
||||||
def _compute_quality_test_check(self):
|
def _compute_quality_test_check(self):
|
||||||
for l in self:
|
for l in self:
|
||||||
if l.question_type == 'qualitative':
|
if l.question_type == "qualitative":
|
||||||
l.success = l.qualitative_value.ok
|
l.success = l.qualitative_value.ok
|
||||||
else:
|
else:
|
||||||
if l.uom_id.id == l.test_uom_id.id:
|
if l.uom_id.id == l.test_uom_id.id:
|
||||||
amount = l.quantitative_value
|
amount = l.quantitative_value
|
||||||
else:
|
else:
|
||||||
amount = self.env['uom.uom']._compute_quantity(
|
amount = self.env["uom.uom"]._compute_quantity(
|
||||||
l.quantitative_value,
|
l.quantitative_value, l.test_uom_id.id
|
||||||
l.test_uom_id.id)
|
)
|
||||||
l.success = l.max_value >= amount >= l.min_value
|
l.success = l.max_value >= amount >= l.min_value
|
||||||
|
|
||||||
@api.depends('possible_ql_values', 'min_value', 'max_value', 'test_uom_id',
|
@api.depends(
|
||||||
'question_type')
|
"possible_ql_values", "min_value", "max_value", "test_uom_id", "question_type"
|
||||||
|
)
|
||||||
def _compute_valid_values(self):
|
def _compute_valid_values(self):
|
||||||
for l in self:
|
for l in self:
|
||||||
if l.question_type == 'qualitative':
|
if l.question_type == "qualitative":
|
||||||
l.valid_values = \
|
l.valid_values = ", ".join(
|
||||||
", ".join([x.name for x in l.possible_ql_values if x.ok])
|
[x.name for x in l.possible_ql_values if x.ok]
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
l.valid_values = "%s ~ %s" % (
|
l.valid_values = "{} ~ {}".format(
|
||||||
formatLang(self.env, l.min_value),
|
formatLang(self.env, l.min_value),
|
||||||
formatLang(self.env, l.max_value))
|
formatLang(self.env, l.max_value),
|
||||||
if self.env.ref("uom.group_uom") \
|
)
|
||||||
in self.env.user.groups_id:
|
if self.env.ref("uom.group_uom") in self.env.user.groups_id:
|
||||||
l.valid_values += " %s" % l.test_uom_id.name
|
l.valid_values += " %s" % l.test_uom_id.name
|
||||||
|
|
||||||
inspection_id = fields.Many2one(
|
inspection_id = fields.Many2one(
|
||||||
comodel_name='qc.inspection', string='Inspection', ondelete='cascade')
|
comodel_name="qc.inspection", string="Inspection", ondelete="cascade"
|
||||||
|
)
|
||||||
name = fields.Char(string="Question", readonly=True)
|
name = fields.Char(string="Question", readonly=True)
|
||||||
product_id = fields.Many2one(
|
product_id = fields.Many2one(
|
||||||
comodel_name="product.product", related="inspection_id.product_id",
|
comodel_name="product.product",
|
||||||
store=True, oldname='product')
|
related="inspection_id.product_id",
|
||||||
|
store=True,
|
||||||
|
oldname="product",
|
||||||
|
)
|
||||||
test_line = fields.Many2one(
|
test_line = fields.Many2one(
|
||||||
comodel_name='qc.test.question', string='Test question',
|
comodel_name="qc.test.question", string="Test question", readonly=True
|
||||||
readonly=True)
|
)
|
||||||
possible_ql_values = fields.Many2many(
|
possible_ql_values = fields.Many2many(
|
||||||
comodel_name='qc.test.question.value', string='Answers')
|
comodel_name="qc.test.question.value", string="Answers"
|
||||||
|
)
|
||||||
quantitative_value = fields.Float(
|
quantitative_value = fields.Float(
|
||||||
'Quantitative value', digits=dp.get_precision('Quality Control'),
|
"Quantitative value",
|
||||||
help="Value of the result for a quantitative question.")
|
digits=dp.get_precision("Quality Control"),
|
||||||
|
help="Value of the result for a quantitative question.",
|
||||||
|
)
|
||||||
qualitative_value = fields.Many2one(
|
qualitative_value = fields.Many2one(
|
||||||
comodel_name='qc.test.question.value', string='Qualitative value',
|
comodel_name="qc.test.question.value",
|
||||||
|
string="Qualitative value",
|
||||||
help="Value of the result for a qualitative question.",
|
help="Value of the result for a qualitative question.",
|
||||||
domain="[('id', 'in', possible_ql_values)]")
|
domain="[('id', 'in', possible_ql_values)]",
|
||||||
notes = fields.Text(string='Notes')
|
)
|
||||||
|
notes = fields.Text(string="Notes")
|
||||||
min_value = fields.Float(
|
min_value = fields.Float(
|
||||||
string='Min', digits=dp.get_precision('Quality Control'),
|
string="Min",
|
||||||
readonly=True, help="Minimum valid value for a quantitative question.")
|
digits=dp.get_precision("Quality Control"),
|
||||||
|
readonly=True,
|
||||||
|
help="Minimum valid value for a quantitative question.",
|
||||||
|
)
|
||||||
max_value = fields.Float(
|
max_value = fields.Float(
|
||||||
string='Max', digits=dp.get_precision('Quality Control'),
|
string="Max",
|
||||||
readonly=True, help="Maximum valid value for a quantitative question.")
|
digits=dp.get_precision("Quality Control"),
|
||||||
|
readonly=True,
|
||||||
|
help="Maximum valid value for a quantitative question.",
|
||||||
|
)
|
||||||
test_uom_id = fields.Many2one(
|
test_uom_id = fields.Many2one(
|
||||||
comodel_name='uom.uom', string='Test UoM', readonly=True,
|
comodel_name="uom.uom",
|
||||||
help="UoM for minimum and maximum values for a quantitative "
|
string="Test UoM",
|
||||||
"question.")
|
readonly=True,
|
||||||
|
help="UoM for minimum and maximum values for a quantitative " "question.",
|
||||||
|
)
|
||||||
test_uom_category = fields.Many2one(
|
test_uom_category = fields.Many2one(
|
||||||
comodel_name="uom.category", related="test_uom_id.category_id",
|
comodel_name="uom.category", related="test_uom_id.category_id", store=True
|
||||||
store=True)
|
)
|
||||||
uom_id = fields.Many2one(
|
uom_id = fields.Many2one(
|
||||||
comodel_name='uom.uom', string='UoM',
|
comodel_name="uom.uom",
|
||||||
|
string="UoM",
|
||||||
domain="[('category_id', '=', test_uom_category)]",
|
domain="[('category_id', '=', test_uom_category)]",
|
||||||
help="UoM of the inspection value for a quantitative question.")
|
help="UoM of the inspection value for a quantitative question.",
|
||||||
|
)
|
||||||
question_type = fields.Selection(
|
question_type = fields.Selection(
|
||||||
[('qualitative', 'Qualitative'),
|
[("qualitative", "Qualitative"), ("quantitative", "Quantitative")],
|
||||||
('quantitative', 'Quantitative')],
|
string="Question type",
|
||||||
string='Question type', readonly=True)
|
readonly=True,
|
||||||
valid_values = fields.Char(string="Valid values", store=True,
|
)
|
||||||
compute="_compute_valid_values")
|
valid_values = fields.Char(
|
||||||
|
string="Valid values", store=True, compute="_compute_valid_values"
|
||||||
|
)
|
||||||
success = fields.Boolean(
|
success = fields.Boolean(
|
||||||
compute="_compute_quality_test_check", string="Success?", store=True)
|
compute="_compute_quality_test_check", string="Success?", store=True
|
||||||
|
)
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
# Copyright 2017 Simone Rubino - Agile Business Group
|
# Copyright 2017 Simone Rubino - Agile Business Group
|
||||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
from odoo import api, exceptions, fields, models, _
|
from odoo import _, api, exceptions, fields, models
|
||||||
|
|
||||||
import odoo.addons.decimal_precision as dp
|
import odoo.addons.decimal_precision as dp
|
||||||
|
|
||||||
|
|
||||||
@@ -13,92 +14,107 @@ class QcTest(models.Model):
|
|||||||
"""
|
"""
|
||||||
A test is a group of questions along with the values that make them valid.
|
A test is a group of questions along with the values that make them valid.
|
||||||
"""
|
"""
|
||||||
_name = 'qc.test'
|
|
||||||
_description = 'Quality control test'
|
_name = "qc.test"
|
||||||
|
_description = "Quality control test"
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def object_selection_values(self):
|
def object_selection_values(self):
|
||||||
return set()
|
return set()
|
||||||
|
|
||||||
@api.onchange('type')
|
@api.onchange("type")
|
||||||
def onchange_type(self):
|
def onchange_type(self):
|
||||||
if self.type == 'generic':
|
if self.type == "generic":
|
||||||
self.object_id = False
|
self.object_id = False
|
||||||
|
|
||||||
active = fields.Boolean('Active', default=True)
|
active = fields.Boolean("Active", default=True)
|
||||||
name = fields.Char(
|
name = fields.Char(string="Name", required=True, translate=True)
|
||||||
string='Name', required=True, translate=True)
|
|
||||||
test_lines = fields.One2many(
|
test_lines = fields.One2many(
|
||||||
comodel_name='qc.test.question', inverse_name='test',
|
comodel_name="qc.test.question",
|
||||||
string='Questions', copy=True)
|
inverse_name="test",
|
||||||
|
string="Questions",
|
||||||
|
copy=True,
|
||||||
|
)
|
||||||
object_id = fields.Reference(
|
object_id = fields.Reference(
|
||||||
string='Reference object', selection=object_selection_values,)
|
string="Reference object", selection=object_selection_values,
|
||||||
fill_correct_values = fields.Boolean(
|
)
|
||||||
string='Pre-fill with correct values')
|
fill_correct_values = fields.Boolean(string="Pre-fill with correct values")
|
||||||
type = fields.Selection(
|
type = fields.Selection(
|
||||||
[('generic', 'Generic'),
|
[("generic", "Generic"), ("related", "Related")],
|
||||||
('related', 'Related')],
|
string="Type",
|
||||||
string='Type', required=True, default='generic')
|
required=True,
|
||||||
category = fields.Many2one(
|
default="generic",
|
||||||
comodel_name='qc.test.category', string='Category')
|
)
|
||||||
|
category = fields.Many2one(comodel_name="qc.test.category", string="Category")
|
||||||
company_id = fields.Many2one(
|
company_id = fields.Many2one(
|
||||||
comodel_name='res.company', string='Company',
|
comodel_name="res.company",
|
||||||
default=lambda self: self.env['res.company']._company_default_get(
|
string="Company",
|
||||||
'qc.test'))
|
default=lambda self: self.env["res.company"]._company_default_get("qc.test"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class QcTestQuestion(models.Model):
|
class QcTestQuestion(models.Model):
|
||||||
"""Each test line is a question with its valid value(s)."""
|
"""Each test line is a question with its valid value(s)."""
|
||||||
_name = 'qc.test.question'
|
|
||||||
_description = 'Quality control question'
|
|
||||||
_order = 'sequence, id'
|
|
||||||
|
|
||||||
@api.constrains('ql_values')
|
_name = "qc.test.question"
|
||||||
|
_description = "Quality control question"
|
||||||
|
_order = "sequence, id"
|
||||||
|
|
||||||
|
@api.constrains("ql_values")
|
||||||
def _check_valid_answers(self):
|
def _check_valid_answers(self):
|
||||||
for tc in self:
|
for tc in self:
|
||||||
if (tc.type == 'qualitative' and tc.ql_values and
|
if (
|
||||||
not tc.ql_values.filtered('ok')):
|
tc.type == "qualitative"
|
||||||
|
and tc.ql_values
|
||||||
|
and not tc.ql_values.filtered("ok")
|
||||||
|
):
|
||||||
raise exceptions.ValidationError(
|
raise exceptions.ValidationError(
|
||||||
_("Question '%s' is not valid: "
|
_(
|
||||||
"you have to mark at least one value as OK.")
|
"Question '%s' is not valid: "
|
||||||
% tc.name_get()[0][1])
|
"you have to mark at least one value as OK."
|
||||||
|
)
|
||||||
|
% tc.name_get()[0][1]
|
||||||
|
)
|
||||||
|
|
||||||
@api.constrains('min_value', 'max_value')
|
@api.constrains("min_value", "max_value")
|
||||||
def _check_valid_range(self):
|
def _check_valid_range(self):
|
||||||
for tc in self:
|
for tc in self:
|
||||||
if tc.type == 'quantitative' and tc.min_value > tc.max_value:
|
if tc.type == "quantitative" and tc.min_value > tc.max_value:
|
||||||
raise exceptions.ValidationError(
|
raise exceptions.ValidationError(
|
||||||
_("Question '%s' is not valid: "
|
_(
|
||||||
"minimum value can't be higher than maximum value.")
|
"Question '%s' is not valid: "
|
||||||
% tc.name_get()[0][1])
|
"minimum value can't be higher than maximum value."
|
||||||
|
)
|
||||||
|
% tc.name_get()[0][1]
|
||||||
|
)
|
||||||
|
|
||||||
sequence = fields.Integer(
|
sequence = fields.Integer(string="Sequence", required=True, default="10")
|
||||||
string='Sequence', required=True, default="10")
|
test = fields.Many2one(comodel_name="qc.test", string="Test")
|
||||||
test = fields.Many2one(comodel_name='qc.test', string='Test')
|
name = fields.Char(string="Name", required=True, translate=True)
|
||||||
name = fields.Char(
|
|
||||||
string='Name', required=True, translate=True)
|
|
||||||
type = fields.Selection(
|
type = fields.Selection(
|
||||||
[('qualitative', 'Qualitative'),
|
[("qualitative", "Qualitative"), ("quantitative", "Quantitative")],
|
||||||
('quantitative', 'Quantitative')], string='Type', required=True)
|
string="Type",
|
||||||
|
required=True,
|
||||||
|
)
|
||||||
ql_values = fields.One2many(
|
ql_values = fields.One2many(
|
||||||
comodel_name='qc.test.question.value', inverse_name="test_line",
|
comodel_name="qc.test.question.value",
|
||||||
string='Qualitative values', copy=True)
|
inverse_name="test_line",
|
||||||
notes = fields.Text(string='Notes')
|
string="Qualitative values",
|
||||||
min_value = fields.Float(string='Min',
|
copy=True,
|
||||||
digits=dp.get_precision('Quality Control'))
|
)
|
||||||
max_value = fields.Float(string='Max',
|
notes = fields.Text(string="Notes")
|
||||||
digits=dp.get_precision('Quality Control'),)
|
min_value = fields.Float(string="Min", digits=dp.get_precision("Quality Control"))
|
||||||
uom_id = fields.Many2one(comodel_name='uom.uom', string='Uom')
|
max_value = fields.Float(string="Max", digits=dp.get_precision("Quality Control"),)
|
||||||
|
uom_id = fields.Many2one(comodel_name="uom.uom", string="Uom")
|
||||||
|
|
||||||
|
|
||||||
class QcTestQuestionValue(models.Model):
|
class QcTestQuestionValue(models.Model):
|
||||||
_name = 'qc.test.question.value'
|
_name = "qc.test.question.value"
|
||||||
_description = 'Possible values for qualitative questions.'
|
_description = "Possible values for qualitative questions."
|
||||||
|
|
||||||
test_line = fields.Many2one(
|
test_line = fields.Many2one(comodel_name="qc.test.question", string="Test question")
|
||||||
comodel_name="qc.test.question", string="Test question")
|
name = fields.Char(string="Name", required=True, translate=True)
|
||||||
name = fields.Char(
|
|
||||||
string='Name', required=True, translate=True)
|
|
||||||
ok = fields.Boolean(
|
ok = fields.Boolean(
|
||||||
string='Correct answer?',
|
string="Correct answer?",
|
||||||
help="When this field is marked, the answer is considered correct.")
|
help="When this field is marked, the answer is considered correct.",
|
||||||
|
)
|
||||||
|
|||||||
@@ -5,45 +5,51 @@
|
|||||||
# Copyright 2017 Simone Rubino - Agile Business Group
|
# Copyright 2017 Simone Rubino - Agile Business Group
|
||||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
from odoo import api, exceptions, fields, models, _
|
from odoo import _, api, exceptions, fields, models
|
||||||
|
|
||||||
|
|
||||||
class QcTestTemplateCategory(models.Model):
|
class QcTestTemplateCategory(models.Model):
|
||||||
_name = 'qc.test.category'
|
_name = "qc.test.category"
|
||||||
_description = 'Test category'
|
_description = "Test category"
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
@api.depends('name', 'parent_id')
|
@api.depends("name", "parent_id")
|
||||||
def _compute_get_complete_name(self):
|
def _compute_get_complete_name(self):
|
||||||
for record in self:
|
for record in self:
|
||||||
names = [record.name or '']
|
names = [record.name or ""]
|
||||||
parent = record.parent_id
|
parent = record.parent_id
|
||||||
while parent:
|
while parent:
|
||||||
names.append(parent.name)
|
names.append(parent.name)
|
||||||
parent = parent.parent_id
|
parent = parent.parent_id
|
||||||
record.complete_name = " / ".join(reversed(names))
|
record.complete_name = " / ".join(reversed(names))
|
||||||
|
|
||||||
@api.constrains('parent_id')
|
@api.constrains("parent_id")
|
||||||
def _check_recursion(self):
|
def _check_recursion(self):
|
||||||
ids = self.ids
|
ids = self.ids
|
||||||
level = 100
|
level = 100
|
||||||
while ids:
|
while ids:
|
||||||
parents = self.search([('id', 'in', ids),
|
parents = self.search([("id", "in", ids), ("parent_id", "!=", False)])
|
||||||
('parent_id', '!=', False)])
|
ids = list({x.parent_id.id for x in parents})
|
||||||
ids = list(set([x.parent_id.id for x in parents]))
|
|
||||||
if not level:
|
if not level:
|
||||||
raise exceptions.UserError(
|
raise exceptions.UserError(
|
||||||
_('Error! You can not create recursive categories.'))
|
_("Error! You can not create recursive categories.")
|
||||||
|
)
|
||||||
level -= 1
|
level -= 1
|
||||||
|
|
||||||
name = fields.Char('Name', required=True, translate=True)
|
name = fields.Char("Name", required=True, translate=True)
|
||||||
parent_id = fields.Many2one(
|
parent_id = fields.Many2one(
|
||||||
comodel_name='qc.test.category', string='Parent category')
|
comodel_name="qc.test.category", string="Parent category"
|
||||||
|
)
|
||||||
complete_name = fields.Char(
|
complete_name = fields.Char(
|
||||||
compute="_compute_get_complete_name", string='Full name')
|
compute="_compute_get_complete_name", string="Full name"
|
||||||
|
)
|
||||||
child_ids = fields.One2many(
|
child_ids = fields.One2many(
|
||||||
comodel_name='qc.test.category', inverse_name='parent_id',
|
comodel_name="qc.test.category",
|
||||||
string='Child categories')
|
inverse_name="parent_id",
|
||||||
|
string="Child categories",
|
||||||
|
)
|
||||||
active = fields.Boolean(
|
active = fields.Boolean(
|
||||||
string='Active', default=True,
|
string="Active",
|
||||||
help="This field allows you to hide the category without removing it.")
|
default=True,
|
||||||
|
help="This field allows you to hide the category without removing it.",
|
||||||
|
)
|
||||||
|
|||||||
@@ -9,17 +9,19 @@ from odoo import fields, models
|
|||||||
|
|
||||||
|
|
||||||
class QcTrigger(models.Model):
|
class QcTrigger(models.Model):
|
||||||
_name = 'qc.trigger'
|
_name = "qc.trigger"
|
||||||
_description = 'Quality control trigger'
|
_description = "Quality control trigger"
|
||||||
|
|
||||||
name = fields.Char(string='Name', required=True,
|
name = fields.Char(string="Name", required=True, translate=True)
|
||||||
translate=True)
|
active = fields.Boolean(string="Active", default=True)
|
||||||
active = fields.Boolean(string='Active', default=True)
|
|
||||||
company_id = fields.Many2one(
|
company_id = fields.Many2one(
|
||||||
comodel_name='res.company', string='Company',
|
comodel_name="res.company",
|
||||||
default=lambda self: self.env['res.company']._company_default_get(
|
string="Company",
|
||||||
'qc.test'))
|
default=lambda self: self.env["res.company"]._company_default_get("qc.test"),
|
||||||
|
)
|
||||||
partner_selectable = fields.Boolean(
|
partner_selectable = fields.Boolean(
|
||||||
string='Selectable by partner', default=False, readonly=True,
|
string="Selectable by partner",
|
||||||
help='This technical field is to allow to filter by partner in'
|
default=False,
|
||||||
' triggers')
|
readonly=True,
|
||||||
|
help="This technical field is to allow to filter by partner in" " triggers",
|
||||||
|
)
|
||||||
|
|||||||
@@ -25,13 +25,19 @@ class QcTriggerLine(models.AbstractModel):
|
|||||||
trigger = fields.Many2one(comodel_name="qc.trigger", required=True)
|
trigger = fields.Many2one(comodel_name="qc.trigger", required=True)
|
||||||
test = fields.Many2one(comodel_name="qc.test", required=True)
|
test = fields.Many2one(comodel_name="qc.test", required=True)
|
||||||
user = fields.Many2one(
|
user = fields.Many2one(
|
||||||
comodel_name='res.users', string='Responsible',
|
comodel_name="res.users",
|
||||||
track_visibility='always', default=lambda self: self.env.user)
|
string="Responsible",
|
||||||
|
track_visibility="always",
|
||||||
|
default=lambda self: self.env.user,
|
||||||
|
)
|
||||||
partners = fields.Many2many(
|
partners = fields.Many2many(
|
||||||
comodel_name='res.partner', string='Partners',
|
comodel_name="res.partner",
|
||||||
help='If filled, the test will only be created when the action is done'
|
string="Partners",
|
||||||
' for one of the specified partners. If empty, the test will always be'
|
help="If filled, the test will only be created when the action is done"
|
||||||
' created.', domain="[('parent_id', '=', False)]")
|
" for one of the specified partners. If empty, the test will always be"
|
||||||
|
" created.",
|
||||||
|
domain="[('parent_id', '=', False)]",
|
||||||
|
)
|
||||||
|
|
||||||
def get_trigger_line_for_product(self, trigger, product, partner=False):
|
def get_trigger_line_for_product(self, trigger, product, partner=False):
|
||||||
"""Overridable method for getting trigger_line associated to a product.
|
"""Overridable method for getting trigger_line associated to a product.
|
||||||
@@ -53,15 +59,18 @@ class QcTriggerProductCategoryLine(models.Model):
|
|||||||
|
|
||||||
def get_trigger_line_for_product(self, trigger, product, partner=False):
|
def get_trigger_line_for_product(self, trigger, product, partner=False):
|
||||||
trigger_lines = super(
|
trigger_lines = super(
|
||||||
QcTriggerProductCategoryLine,
|
QcTriggerProductCategoryLine, self
|
||||||
self).get_trigger_line_for_product(trigger, product,
|
).get_trigger_line_for_product(trigger, product, partner=partner)
|
||||||
partner=partner)
|
|
||||||
category = product.categ_id
|
category = product.categ_id
|
||||||
while category:
|
while category:
|
||||||
for trigger_line in category.qc_triggers.filtered(
|
for trigger_line in category.qc_triggers.filtered(
|
||||||
lambda r: r.trigger == trigger and (
|
lambda r: r.trigger == trigger
|
||||||
not r.partners or not partner or
|
and (
|
||||||
partner.commercial_partner_id in r.partners)):
|
not r.partners
|
||||||
|
or not partner
|
||||||
|
or partner.commercial_partner_id in r.partners
|
||||||
|
)
|
||||||
|
):
|
||||||
trigger_lines.add(trigger_line)
|
trigger_lines.add(trigger_line)
|
||||||
category = category.parent_id
|
category = category.parent_id
|
||||||
return trigger_lines
|
return trigger_lines
|
||||||
@@ -75,14 +84,17 @@ class QcTriggerProductTemplateLine(models.Model):
|
|||||||
|
|
||||||
def get_trigger_line_for_product(self, trigger, product, partner=False):
|
def get_trigger_line_for_product(self, trigger, product, partner=False):
|
||||||
trigger_lines = super(
|
trigger_lines = super(
|
||||||
QcTriggerProductTemplateLine,
|
QcTriggerProductTemplateLine, self
|
||||||
self).get_trigger_line_for_product(trigger, product,
|
).get_trigger_line_for_product(trigger, product, partner=partner)
|
||||||
partner=partner)
|
|
||||||
for trigger_line in product.product_tmpl_id.qc_triggers.filtered(
|
for trigger_line in product.product_tmpl_id.qc_triggers.filtered(
|
||||||
lambda r: r.trigger == trigger and (
|
lambda r: r.trigger == trigger
|
||||||
not r.partners or not partner or
|
and (
|
||||||
partner.commercial_partner_id in r.partners) and
|
not r.partners
|
||||||
r.test.active):
|
or not partner
|
||||||
|
or partner.commercial_partner_id in r.partners
|
||||||
|
)
|
||||||
|
and r.test.active
|
||||||
|
):
|
||||||
trigger_lines.add(trigger_line)
|
trigger_lines.add(trigger_line)
|
||||||
return trigger_lines
|
return trigger_lines
|
||||||
|
|
||||||
@@ -94,14 +106,17 @@ class QcTriggerProductLine(models.Model):
|
|||||||
product = fields.Many2one(comodel_name="product.product")
|
product = fields.Many2one(comodel_name="product.product")
|
||||||
|
|
||||||
def get_trigger_line_for_product(self, trigger, product, partner=False):
|
def get_trigger_line_for_product(self, trigger, product, partner=False):
|
||||||
trigger_lines = super(
|
trigger_lines = super(QcTriggerProductLine, self).get_trigger_line_for_product(
|
||||||
QcTriggerProductLine,
|
trigger, product, partner=partner
|
||||||
self).get_trigger_line_for_product(trigger, product,
|
)
|
||||||
partner=partner)
|
|
||||||
for trigger_line in product.qc_triggers.filtered(
|
for trigger_line in product.qc_triggers.filtered(
|
||||||
lambda r: r.trigger == trigger and (
|
lambda r: r.trigger == trigger
|
||||||
not r.partners or not partner or
|
and (
|
||||||
partner.commercial_partner_id in r.partners) and
|
not r.partners
|
||||||
r.test.active):
|
or not partner
|
||||||
|
or partner.commercial_partner_id in r.partners
|
||||||
|
)
|
||||||
|
and r.test.active
|
||||||
|
):
|
||||||
trigger_lines.add(trigger_line)
|
trigger_lines.add(trigger_line)
|
||||||
return trigger_lines
|
return trigger_lines
|
||||||
|
|||||||
@@ -26,4 +26,3 @@ The complete inspection workflow is:
|
|||||||
| -> Failure (Pending approval) -> Approved
|
| -> Failure (Pending approval) -> Approved
|
||||||
|
|
||||||
Based on the nan_quality_control_* modules from NaN·tic.
|
Based on the nan_quality_control_* modules from NaN·tic.
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
This module provides a generic infrastructure for quality tests. The idea is
|
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
|
that it can be later reused for doing quality inspections on production lots
|
||||||
or any other area of the company.
|
or any other area of the company.
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
* Make translatable the trigger name.
|
* Make translatable the trigger name.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<!-- Copyright 2010 NaN Projectes de Programari Lliure, S.L.
|
<!-- Copyright 2010 NaN Projectes de Programari Lliure, S.L.
|
||||||
Copyright 2014 Serv. Tec. Avanzados - Pedro M. Baeza
|
Copyright 2014 Serv. Tec. Avanzados - Pedro M. Baeza
|
||||||
Copyright 2014 Oihane Crucelaegui - AvanzOSC
|
Copyright 2014 Oihane Crucelaegui - AvanzOSC
|
||||||
@@ -6,42 +6,44 @@
|
|||||||
Copyright 2017 Simone Rubino - Agile Business Group
|
Copyright 2017 Simone Rubino - Agile Business Group
|
||||||
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
|
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
|
||||||
<odoo>
|
<odoo>
|
||||||
|
|
||||||
<record model="ir.module.category" id="module_category_quality_control">
|
<record model="ir.module.category" id="module_category_quality_control">
|
||||||
<field name="name">Quality control</field>
|
<field name="name">Quality control</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="group_quality_control_user" model="res.groups">
|
<record id="group_quality_control_user" model="res.groups">
|
||||||
<field name="name">User</field>
|
<field name="name">User</field>
|
||||||
<field name="category_id" ref="module_category_quality_control"/>
|
<field name="category_id" ref="module_category_quality_control" />
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="group_quality_control_manager" model="res.groups">
|
<record id="group_quality_control_manager" model="res.groups">
|
||||||
<field name="name">Manager</field>
|
<field name="name">Manager</field>
|
||||||
<field name="category_id" ref="module_category_quality_control"/>
|
<field name="category_id" ref="module_category_quality_control" />
|
||||||
<field name="implied_ids" eval="[(4, ref('group_quality_control_user'))]"/>
|
<field name="implied_ids" eval="[(4, ref('group_quality_control_user'))]" />
|
||||||
<field name="users" eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"/>
|
<field
|
||||||
|
name="users"
|
||||||
|
eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"
|
||||||
|
/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="qc_test_multi_company_rule" model="ir.rule">
|
<record id="qc_test_multi_company_rule" model="ir.rule">
|
||||||
<field name="name">Quality control test multi-company</field>
|
<field name="name">Quality control test multi-company</field>
|
||||||
<field name="model_id" ref="model_qc_test"/>
|
<field name="model_id" ref="model_qc_test" />
|
||||||
<field name="global" eval="True"/>
|
<field name="global" eval="True" />
|
||||||
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])]</field>
|
<field
|
||||||
|
name="domain_force"
|
||||||
|
>['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])]</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="qc_inspection_multi_company_rule" model="ir.rule">
|
<record id="qc_inspection_multi_company_rule" model="ir.rule">
|
||||||
<field name="name">Quality control inspection multi-company</field>
|
<field name="name">Quality control inspection multi-company</field>
|
||||||
<field name="model_id" ref="model_qc_inspection"/>
|
<field name="model_id" ref="model_qc_inspection" />
|
||||||
<field name="global" eval="True"/>
|
<field name="global" eval="True" />
|
||||||
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])]</field>
|
<field
|
||||||
|
name="domain_force"
|
||||||
|
>['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])]</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="qc_trigger_multi_company_rule" model="ir.rule">
|
<record id="qc_trigger_multi_company_rule" model="ir.rule">
|
||||||
<field name="name">Quality control trigger multi-company</field>
|
<field name="name">Quality control trigger multi-company</field>
|
||||||
<field name="model_id" ref="model_qc_trigger"/>
|
<field name="model_id" ref="model_qc_trigger" />
|
||||||
<field name="global" eval="True"/>
|
<field name="global" eval="True" />
|
||||||
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])]</field>
|
<field
|
||||||
|
name="domain_force"
|
||||||
|
>['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])]</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -5,204 +5,220 @@
|
|||||||
# Copyright 2017 Simone Rubino - Agile Business Group
|
# Copyright 2017 Simone Rubino - Agile Business Group
|
||||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
from odoo.tests.common import TransactionCase
|
|
||||||
from odoo import exceptions
|
from odoo import exceptions
|
||||||
from ..models.qc_trigger_line import\
|
from odoo.tests.common import TransactionCase
|
||||||
_filter_trigger_lines
|
|
||||||
|
from ..models.qc_trigger_line import _filter_trigger_lines
|
||||||
|
|
||||||
|
|
||||||
class TestQualityControl(TransactionCase):
|
class TestQualityControl(TransactionCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestQualityControl, self).setUp()
|
super(TestQualityControl, self).setUp()
|
||||||
self.inspection_model = self.env['qc.inspection']
|
self.inspection_model = self.env["qc.inspection"]
|
||||||
self.category_model = self.env['qc.test.category']
|
self.category_model = self.env["qc.test.category"]
|
||||||
self.question_model = self.env['qc.test.question']
|
self.question_model = self.env["qc.test.question"]
|
||||||
self.wizard_model = self.env['qc.inspection.set.test']
|
self.wizard_model = self.env["qc.inspection.set.test"]
|
||||||
self.qc_trigger = self.env['qc.trigger'].create({
|
self.qc_trigger = self.env["qc.trigger"].create(
|
||||||
'name': 'Test Trigger',
|
{"name": "Test Trigger", "active": True}
|
||||||
'active': True,
|
)
|
||||||
})
|
self.test = self.env.ref("quality_control.qc_test_1")
|
||||||
self.test = self.env.ref('quality_control.qc_test_1')
|
self.val_ok = self.env.ref("quality_control.qc_test_question_value_1")
|
||||||
self.val_ok = self.env.ref('quality_control.qc_test_question_value_1')
|
self.val_ko = self.env.ref("quality_control.qc_test_question_value_2")
|
||||||
self.val_ko = self.env.ref('quality_control.qc_test_question_value_2')
|
self.qn_question = self.env.ref("quality_control.qc_test_question_2")
|
||||||
self.qn_question = self.env.ref('quality_control.qc_test_question_2')
|
|
||||||
self.cat_generic = self.env.ref(
|
self.cat_generic = self.env.ref(
|
||||||
'quality_control.qc_test_template_category_generic')
|
"quality_control.qc_test_template_category_generic"
|
||||||
self.product = self.env.ref('product.product_product_11')
|
)
|
||||||
inspection_lines = (
|
self.product = self.env.ref("product.product_product_11")
|
||||||
self.inspection_model._prepare_inspection_lines(self.test))
|
inspection_lines = self.inspection_model._prepare_inspection_lines(self.test)
|
||||||
self.inspection1 = self.inspection_model.create({
|
self.inspection1 = self.inspection_model.create(
|
||||||
'name': 'Test Inspection',
|
{"name": "Test Inspection", "inspection_lines": inspection_lines}
|
||||||
'inspection_lines': inspection_lines,
|
)
|
||||||
})
|
|
||||||
self.wizard = self.wizard_model.with_context(
|
self.wizard = self.wizard_model.with_context(
|
||||||
active_id=self.inspection1.id).create({
|
active_id=self.inspection1.id
|
||||||
'test': self.test.id,
|
).create({"test": self.test.id})
|
||||||
})
|
|
||||||
self.wizard.action_create_test()
|
self.wizard.action_create_test()
|
||||||
self.inspection1.action_todo()
|
self.inspection1.action_todo()
|
||||||
|
|
||||||
def test_inspection_correct(self):
|
def test_inspection_correct(self):
|
||||||
for line in self.inspection1.inspection_lines:
|
for line in self.inspection1.inspection_lines:
|
||||||
if line.question_type == 'qualitative':
|
if line.question_type == "qualitative":
|
||||||
line.qualitative_value = self.val_ok
|
line.qualitative_value = self.val_ok
|
||||||
if line.question_type == 'quantitative':
|
if line.question_type == "quantitative":
|
||||||
line.quantitative_value = 5.0
|
line.quantitative_value = 5.0
|
||||||
self.inspection1.action_confirm()
|
self.inspection1.action_confirm()
|
||||||
for line in self.inspection1.inspection_lines:
|
for line in self.inspection1.inspection_lines:
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
line.success,
|
line.success, "Incorrect state in inspection line %s" % line.name
|
||||||
'Incorrect state in inspection line %s' % line.name)
|
)
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
self.inspection1.success,
|
self.inspection1.success,
|
||||||
'Incorrect state in inspection %s' % self.inspection1.name)
|
"Incorrect state in inspection %s" % self.inspection1.name,
|
||||||
self.assertEqual(self.inspection1.state, 'success')
|
)
|
||||||
|
self.assertEqual(self.inspection1.state, "success")
|
||||||
self.inspection1.action_approve()
|
self.inspection1.action_approve()
|
||||||
self.assertEqual(self.inspection1.state, 'success')
|
self.assertEqual(self.inspection1.state, "success")
|
||||||
|
|
||||||
def test_inspection_incorrect(self):
|
def test_inspection_incorrect(self):
|
||||||
for line in self.inspection1.inspection_lines:
|
for line in self.inspection1.inspection_lines:
|
||||||
if line.question_type == 'qualitative':
|
if line.question_type == "qualitative":
|
||||||
line.qualitative_value = self.val_ko
|
line.qualitative_value = self.val_ko
|
||||||
if line.question_type == 'quantitative':
|
if line.question_type == "quantitative":
|
||||||
line.quantitative_value = 15.0
|
line.quantitative_value = 15.0
|
||||||
self.inspection1.action_confirm()
|
self.inspection1.action_confirm()
|
||||||
for line in self.inspection1.inspection_lines:
|
for line in self.inspection1.inspection_lines:
|
||||||
self.assertFalse(
|
self.assertFalse(
|
||||||
line.success,
|
line.success, "Incorrect state in inspection line %s" % line.name
|
||||||
'Incorrect state in inspection line %s' % line.name)
|
)
|
||||||
self.assertFalse(
|
self.assertFalse(
|
||||||
self.inspection1.success,
|
self.inspection1.success,
|
||||||
'Incorrect state in inspection %s' % self.inspection1.name)
|
"Incorrect state in inspection %s" % self.inspection1.name,
|
||||||
self.assertEqual(self.inspection1.state, 'waiting')
|
)
|
||||||
|
self.assertEqual(self.inspection1.state, "waiting")
|
||||||
self.inspection1.action_approve()
|
self.inspection1.action_approve()
|
||||||
self.assertEqual(self.inspection1.state, 'failed')
|
self.assertEqual(self.inspection1.state, "failed")
|
||||||
|
|
||||||
def test_actions_errors(self):
|
def test_actions_errors(self):
|
||||||
inspection2 = self.inspection1.copy()
|
inspection2 = self.inspection1.copy()
|
||||||
inspection2.action_draft()
|
inspection2.action_draft()
|
||||||
inspection2.write({'test': False})
|
inspection2.write({"test": False})
|
||||||
with self.assertRaises(exceptions.UserError):
|
with self.assertRaises(exceptions.UserError):
|
||||||
inspection2.action_todo()
|
inspection2.action_todo()
|
||||||
inspection3 = self.inspection1.copy()
|
inspection3 = self.inspection1.copy()
|
||||||
inspection3.write({
|
inspection3.write(
|
||||||
'inspection_lines':
|
{
|
||||||
self.inspection_model._prepare_inspection_lines(inspection3.test)
|
"inspection_lines": self.inspection_model._prepare_inspection_lines(
|
||||||
})
|
inspection3.test
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
for line in inspection3.inspection_lines:
|
for line in inspection3.inspection_lines:
|
||||||
if line.question_type == 'quantitative':
|
if line.question_type == "quantitative":
|
||||||
line.quantitative_value = 15.0
|
line.quantitative_value = 15.0
|
||||||
with self.assertRaises(exceptions.UserError):
|
with self.assertRaises(exceptions.UserError):
|
||||||
inspection3.action_confirm()
|
inspection3.action_confirm()
|
||||||
inspection4 = self.inspection1.copy()
|
inspection4 = self.inspection1.copy()
|
||||||
inspection4.write({
|
inspection4.write(
|
||||||
'inspection_lines':
|
{
|
||||||
self.inspection_model._prepare_inspection_lines(inspection4.test)
|
"inspection_lines": self.inspection_model._prepare_inspection_lines(
|
||||||
})
|
inspection4.test
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
for line in inspection4.inspection_lines:
|
for line in inspection4.inspection_lines:
|
||||||
if line.question_type == 'quantitative':
|
if line.question_type == "quantitative":
|
||||||
line.write({
|
line.write({"uom_id": False, "quantitative_value": 15.0})
|
||||||
'uom_id': False,
|
elif line.question_type == "qualitative":
|
||||||
'quantitative_value': 15.0,
|
|
||||||
})
|
|
||||||
elif line.question_type == 'qualitative':
|
|
||||||
line.qualitative_value = self.val_ok
|
line.qualitative_value = self.val_ok
|
||||||
with self.assertRaises(exceptions.UserError):
|
with self.assertRaises(exceptions.UserError):
|
||||||
inspection4.action_confirm()
|
inspection4.action_confirm()
|
||||||
|
|
||||||
def test_categories(self):
|
def test_categories(self):
|
||||||
category1 = self.category_model.create({
|
category1 = self.category_model.create({"name": "Category ONE"})
|
||||||
'name': 'Category ONE',
|
category2 = self.category_model.create(
|
||||||
})
|
{"name": "Category TWO", "parent_id": category1.id}
|
||||||
category2 = self.category_model.create({
|
)
|
||||||
'name': 'Category TWO',
|
|
||||||
'parent_id': category1.id,
|
|
||||||
})
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
category2.complete_name,
|
category2.complete_name,
|
||||||
'%s / %s' % (category1.name, category2.name),
|
"{} / {}".format(category1.name, category2.name),
|
||||||
'Something went wrong when computing complete name')
|
"Something went wrong when computing complete name",
|
||||||
|
)
|
||||||
with self.assertRaises(exceptions.ValidationError):
|
with self.assertRaises(exceptions.ValidationError):
|
||||||
category1.parent_id = category2.id
|
category1.parent_id = category2.id
|
||||||
|
|
||||||
def test_get_qc_trigger_product(self):
|
def test_get_qc_trigger_product(self):
|
||||||
self.test.write({
|
self.test.write({"fill_correct_values": True})
|
||||||
'fill_correct_values': True,
|
|
||||||
})
|
|
||||||
trigger_lines = set()
|
trigger_lines = set()
|
||||||
self.product.write({
|
self.product.write(
|
||||||
'qc_triggers': [(0, 0, {'trigger': self.qc_trigger.id,
|
{
|
||||||
'test': self.test.id})],
|
"qc_triggers": [
|
||||||
})
|
(0, 0, {"trigger": self.qc_trigger.id, "test": self.test.id})
|
||||||
self.product.product_tmpl_id.write({
|
],
|
||||||
'qc_triggers': [(0, 0, {'trigger': self.qc_trigger.id,
|
}
|
||||||
'test': self.test.id})],
|
)
|
||||||
})
|
self.product.product_tmpl_id.write(
|
||||||
self.product.categ_id.write({
|
{
|
||||||
'qc_triggers': [(0, 0, {'trigger': self.qc_trigger.id,
|
"qc_triggers": [
|
||||||
'test': self.test.id})],
|
(0, 0, {"trigger": self.qc_trigger.id, "test": self.test.id})
|
||||||
})
|
],
|
||||||
for model in ['qc.trigger.product_category_line',
|
}
|
||||||
'qc.trigger.product_template_line',
|
)
|
||||||
'qc.trigger.product_line']:
|
self.product.categ_id.write(
|
||||||
|
{
|
||||||
|
"qc_triggers": [
|
||||||
|
(0, 0, {"trigger": self.qc_trigger.id, "test": self.test.id})
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
for model in [
|
||||||
|
"qc.trigger.product_category_line",
|
||||||
|
"qc.trigger.product_template_line",
|
||||||
|
"qc.trigger.product_line",
|
||||||
|
]:
|
||||||
trigger_lines = trigger_lines.union(
|
trigger_lines = trigger_lines.union(
|
||||||
self.env[model].get_trigger_line_for_product(
|
self.env[model].get_trigger_line_for_product(
|
||||||
self.qc_trigger, self.product))
|
self.qc_trigger, self.product
|
||||||
|
)
|
||||||
|
)
|
||||||
self.assertEqual(len(trigger_lines), 3)
|
self.assertEqual(len(trigger_lines), 3)
|
||||||
filtered_trigger_lines = _filter_trigger_lines(trigger_lines)
|
filtered_trigger_lines = _filter_trigger_lines(trigger_lines)
|
||||||
self.assertEqual(len(filtered_trigger_lines), 1)
|
self.assertEqual(len(filtered_trigger_lines), 1)
|
||||||
for trigger_line in filtered_trigger_lines:
|
for trigger_line in filtered_trigger_lines:
|
||||||
inspection = self.inspection_model._make_inspection(
|
inspection = self.inspection_model._make_inspection(
|
||||||
self.product, trigger_line)
|
self.product, trigger_line
|
||||||
self.assertEqual(inspection.state, 'ready')
|
)
|
||||||
|
self.assertEqual(inspection.state, "ready")
|
||||||
self.assertTrue(inspection.auto_generated)
|
self.assertTrue(inspection.auto_generated)
|
||||||
self.assertEqual(inspection.test, self.test)
|
self.assertEqual(inspection.test, self.test)
|
||||||
for line in inspection.inspection_lines:
|
for line in inspection.inspection_lines:
|
||||||
if line.question_type == 'qualitative':
|
if line.question_type == "qualitative":
|
||||||
self.assertEqual(line.qualitative_value, self.val_ok)
|
self.assertEqual(line.qualitative_value, self.val_ok)
|
||||||
elif line.question_type == 'quantitative':
|
elif line.question_type == "quantitative":
|
||||||
self.assertAlmostEqual(
|
self.assertAlmostEqual(
|
||||||
round(line.quantitative_value, 2), round((
|
round(line.quantitative_value, 2),
|
||||||
self.qn_question.min_value +
|
round(
|
||||||
self.qn_question.max_value) * 0.5, 2))
|
(self.qn_question.min_value + self.qn_question.max_value)
|
||||||
|
* 0.5,
|
||||||
|
2,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
def test_qc_inspection_not_draft_unlink(self):
|
def test_qc_inspection_not_draft_unlink(self):
|
||||||
with self.assertRaises(exceptions.UserError):
|
with self.assertRaises(exceptions.UserError):
|
||||||
self.inspection1.unlink()
|
self.inspection1.unlink()
|
||||||
inspection2 = self.inspection1.copy()
|
inspection2 = self.inspection1.copy()
|
||||||
inspection2.action_cancel()
|
inspection2.action_cancel()
|
||||||
self.assertEqual(inspection2.state, 'canceled')
|
self.assertEqual(inspection2.state, "canceled")
|
||||||
inspection2.action_draft()
|
inspection2.action_draft()
|
||||||
self.assertEqual(inspection2.state, 'draft')
|
self.assertEqual(inspection2.state, "draft")
|
||||||
inspection2.unlink()
|
inspection2.unlink()
|
||||||
|
|
||||||
def test_qc_inspection_auto_generate_unlink(self):
|
def test_qc_inspection_auto_generate_unlink(self):
|
||||||
inspection2 = self.inspection1.copy()
|
inspection2 = self.inspection1.copy()
|
||||||
inspection2.write({
|
inspection2.write({"auto_generated": True})
|
||||||
'auto_generated': True,
|
|
||||||
})
|
|
||||||
with self.assertRaises(exceptions.UserError):
|
with self.assertRaises(exceptions.UserError):
|
||||||
inspection2.unlink()
|
inspection2.unlink()
|
||||||
|
|
||||||
def test_qc_inspection_product(self):
|
def test_qc_inspection_product(self):
|
||||||
self.inspection1.write({
|
self.inspection1.write(
|
||||||
'object_id': '%s,%d' % (self.product._name, self.product.id),
|
{"object_id": "%s,%d" % (self.product._name, self.product.id)}
|
||||||
})
|
)
|
||||||
self.assertEqual(self.inspection1.product_id, self.product)
|
self.assertEqual(self.inspection1.product_id, self.product)
|
||||||
|
|
||||||
def test_qc_test_question_constraints(self):
|
def test_qc_test_question_constraints(self):
|
||||||
with self.assertRaises(exceptions.ValidationError):
|
with self.assertRaises(exceptions.ValidationError):
|
||||||
self.question_model.create({
|
self.question_model.create(
|
||||||
'name': 'Quantitative Question',
|
{
|
||||||
'type': 'quantitative',
|
"name": "Quantitative Question",
|
||||||
'min_value': 1.0,
|
"type": "quantitative",
|
||||||
'max_value': 0.0,
|
"min_value": 1.0,
|
||||||
})
|
"max_value": 0.0,
|
||||||
|
}
|
||||||
|
)
|
||||||
with self.assertRaises(exceptions.ValidationError):
|
with self.assertRaises(exceptions.ValidationError):
|
||||||
self.question_model.create({
|
self.question_model.create(
|
||||||
'name': 'Qualitative Question',
|
{
|
||||||
'type': 'qualitative',
|
"name": "Qualitative Question",
|
||||||
'ql_values': [(0, 0, {'name': 'Qualitative answer',
|
"type": "qualitative",
|
||||||
'ok': False})],
|
"ql_values": [(0, 0, {"name": "Qualitative answer", "ok": False})],
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<!-- Copyright 2010 NaN Projectes de Programari Lliure, S.L.
|
<!-- Copyright 2010 NaN Projectes de Programari Lliure, S.L.
|
||||||
Copyright 2014 Serv. Tec. Avanzados - Pedro M. Baeza
|
Copyright 2014 Serv. Tec. Avanzados - Pedro M. Baeza
|
||||||
Copyright 2014 Oihane Crucelaegui - AvanzOSC
|
Copyright 2014 Oihane Crucelaegui - AvanzOSC
|
||||||
@@ -6,17 +6,19 @@
|
|||||||
Copyright 2017 Simone Rubino - Agile Business Group
|
Copyright 2017 Simone Rubino - Agile Business Group
|
||||||
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
|
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
|
||||||
<odoo>
|
<odoo>
|
||||||
|
|
||||||
<record model="ir.ui.view" id="product_category_qc_form_view">
|
<record model="ir.ui.view" id="product_category_qc_form_view">
|
||||||
<field name="name">product.category.qc</field>
|
<field name="name">product.category.qc</field>
|
||||||
<field name="model">product.category</field>
|
<field name="model">product.category</field>
|
||||||
<field name="inherit_id" ref="product.product_category_form_view"/>
|
<field name="inherit_id" ref="product.product_category_form_view" />
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<group name="first" position="after">
|
<group name="first" position="after">
|
||||||
<group name="qc" string="Quality control">
|
<group name="qc" string="Quality control">
|
||||||
<field name="qc_triggers" nolabel="1">
|
<field name="qc_triggers" nolabel="1">
|
||||||
<tree string="Quality control triggers" editable="bottom">
|
<tree string="Quality control triggers" editable="bottom">
|
||||||
<field name="trigger" options="{'no_create': True, 'no_edit': True, 'no_open': True}" />
|
<field
|
||||||
|
name="trigger"
|
||||||
|
options="{'no_create': True, 'no_edit': True, 'no_open': True}"
|
||||||
|
/>
|
||||||
<field name="test" />
|
<field name="test" />
|
||||||
<field name="user" />
|
<field name="user" />
|
||||||
<field name="partners" widget="many2many_tags" />
|
<field name="partners" widget="many2many_tags" />
|
||||||
@@ -26,5 +28,4 @@
|
|||||||
</group>
|
</group>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<!-- Copyright 2010 NaN Projectes de Programari Lliure, S.L.
|
<!-- Copyright 2010 NaN Projectes de Programari Lliure, S.L.
|
||||||
Copyright 2014 Serv. Tec. Avanzados - Pedro M. Baeza
|
Copyright 2014 Serv. Tec. Avanzados - Pedro M. Baeza
|
||||||
Copyright 2014 Oihane Crucelaegui - AvanzOSC
|
Copyright 2014 Oihane Crucelaegui - AvanzOSC
|
||||||
@@ -6,19 +6,24 @@
|
|||||||
Copyright 2017 Simone Rubino - Agile Business Group
|
Copyright 2017 Simone Rubino - Agile Business Group
|
||||||
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
|
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
|
||||||
<odoo>
|
<odoo>
|
||||||
|
|
||||||
<record model="ir.ui.view" id="product_template_qc_form_view">
|
<record model="ir.ui.view" id="product_template_qc_form_view">
|
||||||
<field name="name">product.template.qc</field>
|
<field name="name">product.template.qc</field>
|
||||||
<field name="model">product.template</field>
|
<field name="model">product.template</field>
|
||||||
<field name="inherit_id" ref="product.product_template_only_form_view"/>
|
<field name="inherit_id" ref="product.product_template_only_form_view" />
|
||||||
<field name="groups_id" eval="[(4, ref('quality_control.group_quality_control_user'))]" />
|
<field
|
||||||
|
name="groups_id"
|
||||||
|
eval="[(4, ref('quality_control.group_quality_control_user'))]"
|
||||||
|
/>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<page name="inventory" position="inside">
|
<page name="inventory" position="inside">
|
||||||
<group name="qc" string="Quality control">
|
<group name="qc" string="Quality control">
|
||||||
<field name="qc_triggers" nolabel="1">
|
<field name="qc_triggers" nolabel="1">
|
||||||
<tree string="Quality control triggers" editable="bottom">
|
<tree string="Quality control triggers" editable="bottom">
|
||||||
<field name="trigger" options="{'no_create': True, 'no_edit': True, 'no_open': True}"/>
|
<field
|
||||||
<field name="test"/>
|
name="trigger"
|
||||||
|
options="{'no_create': True, 'no_edit': True, 'no_open': True}"
|
||||||
|
/>
|
||||||
|
<field name="test" />
|
||||||
<field name="user" />
|
<field name="user" />
|
||||||
<field name="partners" widget="many2many_tags" />
|
<field name="partners" widget="many2many_tags" />
|
||||||
</tree>
|
</tree>
|
||||||
@@ -27,5 +32,4 @@
|
|||||||
</page>
|
</page>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<!-- Copyright 2010 NaN Projectes de Programari Lliure, S.L.
|
<!-- Copyright 2010 NaN Projectes de Programari Lliure, S.L.
|
||||||
Copyright 2014 Serv. Tec. Avanzados - Pedro M. Baeza
|
Copyright 2014 Serv. Tec. Avanzados - Pedro M. Baeza
|
||||||
Copyright 2014 Oihane Crucelaegui - AvanzOSC
|
Copyright 2014 Oihane Crucelaegui - AvanzOSC
|
||||||
@@ -6,56 +6,69 @@
|
|||||||
Copyright 2017 Simone Rubino - Agile Business Group
|
Copyright 2017 Simone Rubino - Agile Business Group
|
||||||
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
|
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
|
||||||
<odoo>
|
<odoo>
|
||||||
|
|
||||||
<record model="ir.ui.view" id="qc_inspection_form_view">
|
<record model="ir.ui.view" id="qc_inspection_form_view">
|
||||||
<field name="name">qc.inspection.form</field>
|
<field name="name">qc.inspection.form</field>
|
||||||
<field name="model">qc.inspection</field>
|
<field name="model">qc.inspection</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="Inspection">
|
<form string="Inspection">
|
||||||
<header>
|
<header>
|
||||||
<button name="action_draft"
|
<button
|
||||||
type="object"
|
name="action_draft"
|
||||||
attrs="{'invisible': [('state', '!=', 'canceled')]}"
|
type="object"
|
||||||
string="Draft" />
|
attrs="{'invisible': [('state', '!=', 'canceled')]}"
|
||||||
<button name="action_todo"
|
string="Draft"
|
||||||
type="object"
|
/>
|
||||||
class="oe_highlight"
|
<button
|
||||||
states="draft"
|
name="action_todo"
|
||||||
string="Mark todo" />
|
type="object"
|
||||||
<button name="action_confirm"
|
class="oe_highlight"
|
||||||
type="object"
|
states="draft"
|
||||||
class="oe_highlight"
|
string="Mark todo"
|
||||||
states="ready"
|
/>
|
||||||
string="Confirm"
|
<button
|
||||||
icon="fa-check" />
|
name="action_confirm"
|
||||||
<button name="action_approve"
|
type="object"
|
||||||
type="object"
|
class="oe_highlight"
|
||||||
states="waiting"
|
states="ready"
|
||||||
class="oe_highlight"
|
string="Confirm"
|
||||||
groups="quality_control.group_quality_control_manager"
|
icon="fa-check"
|
||||||
string="Approve" />
|
/>
|
||||||
<button name="action_cancel"
|
<button
|
||||||
type="object"
|
name="action_approve"
|
||||||
attrs="{'invisible': [('state', 'not in', ['waiting', 'ready', 'failed', 'success'])]}"
|
type="object"
|
||||||
string="Cancel"
|
states="waiting"
|
||||||
icon="fa-ban" />
|
class="oe_highlight"
|
||||||
<field name="state"
|
groups="quality_control.group_quality_control_manager"
|
||||||
widget="statusbar"
|
string="Approve"
|
||||||
statusbar_visible="draft,waiting,success"
|
/>
|
||||||
statusbar_colors='{"success": "blue", "failed": "red"}' />
|
<button
|
||||||
|
name="action_cancel"
|
||||||
|
type="object"
|
||||||
|
attrs="{'invisible': [('state', 'not in', ['waiting', 'ready', 'failed', 'success'])]}"
|
||||||
|
string="Cancel"
|
||||||
|
icon="fa-ban"
|
||||||
|
/>
|
||||||
|
<field
|
||||||
|
name="state"
|
||||||
|
widget="statusbar"
|
||||||
|
statusbar_visible="draft,waiting,success"
|
||||||
|
statusbar_colors='{"success": "blue", "failed": "red"}'
|
||||||
|
/>
|
||||||
</header>
|
</header>
|
||||||
<sheet>
|
<sheet>
|
||||||
<div class="oe_right oe_button_box" name="buttons">
|
<div class="oe_right oe_button_box" name="buttons">
|
||||||
<button class="oe_inline oe_stat_button"
|
<button
|
||||||
type="action"
|
class="oe_inline oe_stat_button"
|
||||||
name="%(action_qc_inspection_set_test)d"
|
type="action"
|
||||||
icon="fa-bookmark-o"
|
name="%(action_qc_inspection_set_test)d"
|
||||||
states="draft"
|
icon="fa-bookmark-o"
|
||||||
string="Set test" />
|
states="draft"
|
||||||
|
string="Set test"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<h1>
|
<h1>
|
||||||
<label string="Inspection " for="name"/>
|
<label string="Inspection " for="name" />
|
||||||
<field name="name" class="oe_inline"/>
|
<field name="name" class="oe_inline" />
|
||||||
</h1>
|
</h1>
|
||||||
<group>
|
<group>
|
||||||
<group>
|
<group>
|
||||||
@@ -74,45 +87,57 @@
|
|||||||
<notebook>
|
<notebook>
|
||||||
<page string="Questions">
|
<page string="Questions">
|
||||||
<field name="inspection_lines" nolabel="1">
|
<field name="inspection_lines" nolabel="1">
|
||||||
<tree string="Inspection lines" editable="top" delete="false" create="false">
|
<tree
|
||||||
|
string="Inspection lines"
|
||||||
|
editable="top"
|
||||||
|
delete="false"
|
||||||
|
create="false"
|
||||||
|
>
|
||||||
<field name="name" />
|
<field name="name" />
|
||||||
<field name="question_type" />
|
<field name="question_type" />
|
||||||
<field name="possible_ql_values" invisible="1" />
|
<field name="possible_ql_values" invisible="1" />
|
||||||
<field name="qualitative_value"
|
<field
|
||||||
attrs="{'readonly': [('question_type', '=', 'quantitative')]}" />
|
name="qualitative_value"
|
||||||
<field name="quantitative_value"
|
attrs="{'readonly': [('question_type', '=', 'quantitative')]}"
|
||||||
attrs="{'readonly': [('question_type', '=', 'qualitative')]}" />
|
/>
|
||||||
<field name="uom_id"
|
<field
|
||||||
groups="uom.group_uom"
|
name="quantitative_value"
|
||||||
attrs="{'readonly': [('question_type', '=', 'qualitative')]}" />
|
attrs="{'readonly': [('question_type', '=', 'qualitative')]}"
|
||||||
<field name="test_uom_category" invisible="1"/>
|
/>
|
||||||
<field name="min_value" invisible="1"/>
|
<field
|
||||||
<field name="max_value" invisible="1"/>
|
name="uom_id"
|
||||||
|
groups="uom.group_uom"
|
||||||
|
attrs="{'readonly': [('question_type', '=', 'qualitative')]}"
|
||||||
|
/>
|
||||||
|
<field name="test_uom_category" invisible="1" />
|
||||||
|
<field name="min_value" invisible="1" />
|
||||||
|
<field name="max_value" invisible="1" />
|
||||||
<field name="valid_values" />
|
<field name="valid_values" />
|
||||||
<field name="success" />
|
<field name="success" />
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</page>
|
</page>
|
||||||
<page string="Notes">
|
<page string="Notes">
|
||||||
<group string="Internal notes" >
|
<group string="Internal notes">
|
||||||
<field name="internal_notes"
|
<field name="internal_notes" nolabel="1" />
|
||||||
nolabel="1" />
|
|
||||||
</group>
|
</group>
|
||||||
<group string="External notes" >
|
<group string="External notes">
|
||||||
<field name="external_notes"
|
<field name="external_notes" nolabel="1" />
|
||||||
nolabel="1" />
|
|
||||||
</group>
|
</group>
|
||||||
</page>
|
</page>
|
||||||
</notebook>
|
</notebook>
|
||||||
</sheet>
|
</sheet>
|
||||||
<div class="oe_chatter">
|
<div class="oe_chatter">
|
||||||
<field name="message_follower_ids" widget="mail_followers" groups="base.group_user"/>
|
<field
|
||||||
<field name="message_ids" widget="mail_thread"/>
|
name="message_follower_ids"
|
||||||
|
widget="mail_followers"
|
||||||
|
groups="base.group_user"
|
||||||
|
/>
|
||||||
|
<field name="message_ids" widget="mail_thread" />
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="ir.ui.view" id="qc_inspection_tree_view">
|
<record model="ir.ui.view" id="qc_inspection_tree_view">
|
||||||
<field name="name">qc.inspection.tree</field>
|
<field name="name">qc.inspection.tree</field>
|
||||||
<field name="model">qc.inspection</field>
|
<field name="model">qc.inspection</field>
|
||||||
@@ -128,7 +153,6 @@
|
|||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="ir.ui.view" id="qc_inspection_search_view">
|
<record model="ir.ui.view" id="qc_inspection_search_view">
|
||||||
<field name="name">qc.inspection.search</field>
|
<field name="name">qc.inspection.search</field>
|
||||||
<field name="model">qc.inspection</field>
|
<field name="model">qc.inspection</field>
|
||||||
@@ -142,83 +166,110 @@
|
|||||||
<field name="test" />
|
<field name="test" />
|
||||||
</group>
|
</group>
|
||||||
<newline />
|
<newline />
|
||||||
<filter string="Correct"
|
<filter
|
||||||
name="correct"
|
string="Correct"
|
||||||
domain="[('success', '=', True)]"/>
|
name="correct"
|
||||||
<filter string="Incorrect"
|
domain="[('success', '=', True)]"
|
||||||
name="incorrect"
|
/>
|
||||||
domain="[('success', '=', False)]"/>
|
<filter
|
||||||
|
string="Incorrect"
|
||||||
|
name="incorrect"
|
||||||
|
domain="[('success', '=', False)]"
|
||||||
|
/>
|
||||||
<newline />
|
<newline />
|
||||||
<group expand="0" string="Group by...">
|
<group expand="0" string="Group by...">
|
||||||
<filter string="Reference"
|
<filter
|
||||||
name="group_by_object_id"
|
string="Reference"
|
||||||
domain="[]"
|
name="group_by_object_id"
|
||||||
context="{'group_by': 'object_id'}" />
|
domain="[]"
|
||||||
<filter string="Test"
|
context="{'group_by': 'object_id'}"
|
||||||
name="group_by_test"
|
/>
|
||||||
domain="[]"
|
<filter
|
||||||
context="{'group_by': 'test'}" />
|
string="Test"
|
||||||
<filter string="Responsible"
|
name="group_by_test"
|
||||||
name="group_by_user"
|
domain="[]"
|
||||||
domain="[]"
|
context="{'group_by': 'test'}"
|
||||||
context="{'group_by': 'user'}" />
|
/>
|
||||||
<filter string="Product"
|
<filter
|
||||||
name="group_by_product_id"
|
string="Responsible"
|
||||||
domain="[]"
|
name="group_by_user"
|
||||||
context="{'group_by': 'product_id'}" />
|
domain="[]"
|
||||||
<filter string="State"
|
context="{'group_by': 'user'}"
|
||||||
name="group_by_state"
|
/>
|
||||||
domain="[]"
|
<filter
|
||||||
context="{'group_by': 'state'}" />
|
string="Product"
|
||||||
<filter string="Success"
|
name="group_by_product_id"
|
||||||
name="group_by_success"
|
domain="[]"
|
||||||
domain="[]"
|
context="{'group_by': 'product_id'}"
|
||||||
context="{'group_by': 'success'}" />
|
/>
|
||||||
<filter string="Auto-generated"
|
<filter
|
||||||
name="group_by_auto_generated"
|
string="State"
|
||||||
domain="[]"
|
name="group_by_state"
|
||||||
context="{'group_by': 'auto_generated'}" />
|
domain="[]"
|
||||||
|
context="{'group_by': 'state'}"
|
||||||
|
/>
|
||||||
|
<filter
|
||||||
|
string="Success"
|
||||||
|
name="group_by_success"
|
||||||
|
domain="[]"
|
||||||
|
context="{'group_by': 'success'}"
|
||||||
|
/>
|
||||||
|
<filter
|
||||||
|
string="Auto-generated"
|
||||||
|
name="group_by_auto_generated"
|
||||||
|
domain="[]"
|
||||||
|
context="{'group_by': 'auto_generated'}"
|
||||||
|
/>
|
||||||
</group>
|
</group>
|
||||||
</search>
|
</search>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="ir.actions.act_window" id="action_qc_inspection">
|
<record model="ir.actions.act_window" id="action_qc_inspection">
|
||||||
<field name="name">Inspections</field>
|
<field name="name">Inspections</field>
|
||||||
<field name="res_model">qc.inspection</field>
|
<field name="res_model">qc.inspection</field>
|
||||||
<field name="view_type">form</field>
|
<field name="view_type">form</field>
|
||||||
<field name="view_mode">tree,form</field>
|
<field name="view_mode">tree,form</field>
|
||||||
</record>
|
</record>
|
||||||
|
<menuitem
|
||||||
<menuitem name="Inspections"
|
name="Inspections"
|
||||||
parent="qc_inspection_menu_parent"
|
parent="qc_inspection_menu_parent"
|
||||||
id="qc_inspection_menu"
|
id="qc_inspection_menu"
|
||||||
action="action_qc_inspection" />
|
action="action_qc_inspection"
|
||||||
|
/>
|
||||||
<record model="ir.ui.view" id="qc_inspection_line_tree_view">
|
<record model="ir.ui.view" id="qc_inspection_line_tree_view">
|
||||||
<field name="name">qc.inspection.line.tree</field>
|
<field name="name">qc.inspection.line.tree</field>
|
||||||
<field name="model">qc.inspection.line</field>
|
<field name="model">qc.inspection.line</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<tree string="Inspection lines" delete="false" create="false" colors="red: success==False">
|
<tree
|
||||||
|
string="Inspection lines"
|
||||||
|
delete="false"
|
||||||
|
create="false"
|
||||||
|
colors="red: success==False"
|
||||||
|
>
|
||||||
<field name="inspection_id" />
|
<field name="inspection_id" />
|
||||||
<field name="product_id" />
|
<field name="product_id" />
|
||||||
<field name="name" />
|
<field name="name" />
|
||||||
<field name="question_type" />
|
<field name="question_type" />
|
||||||
<field name="possible_ql_values" invisible="1" />
|
<field name="possible_ql_values" invisible="1" />
|
||||||
<field name="qualitative_value"
|
<field
|
||||||
attrs="{'readonly': [('question_type', '=', 'quantitative')]}" />
|
name="qualitative_value"
|
||||||
<field name="quantitative_value"
|
attrs="{'readonly': [('question_type', '=', 'quantitative')]}"
|
||||||
attrs="{'readonly': [('question_type', '=', 'qualitative')]}" />
|
/>
|
||||||
<field name="uom_id"
|
<field
|
||||||
groups="uom.group_uom"
|
name="quantitative_value"
|
||||||
attrs="{'readonly': [('question_type', '=', 'qualitative')]}" />
|
attrs="{'readonly': [('question_type', '=', 'qualitative')]}"
|
||||||
<field name="test_uom_category" invisible="1"/>
|
/>
|
||||||
|
<field
|
||||||
|
name="uom_id"
|
||||||
|
groups="uom.group_uom"
|
||||||
|
attrs="{'readonly': [('question_type', '=', 'qualitative')]}"
|
||||||
|
/>
|
||||||
|
<field name="test_uom_category" invisible="1" />
|
||||||
<field name="valid_values" />
|
<field name="valid_values" />
|
||||||
<field name="success" />
|
<field name="success" />
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="ir.ui.view" id="qc_inspection_line_search_view">
|
<record model="ir.ui.view" id="qc_inspection_line_search_view">
|
||||||
<field name="name">qc.inspection.line.search</field>
|
<field name="name">qc.inspection.line.search</field>
|
||||||
<field name="model">qc.inspection.line</field>
|
<field name="model">qc.inspection.line</field>
|
||||||
@@ -231,46 +282,56 @@
|
|||||||
<field name="success" />
|
<field name="success" />
|
||||||
</group>
|
</group>
|
||||||
<newline />
|
<newline />
|
||||||
<filter string="Correct"
|
<filter
|
||||||
name="correct"
|
string="Correct"
|
||||||
domain="[('success', '=', True)]"/>
|
name="correct"
|
||||||
<filter string="Incorrect"
|
domain="[('success', '=', True)]"
|
||||||
name="incorrect"
|
/>
|
||||||
domain="[('success', '=', False)]"/>
|
<filter
|
||||||
|
string="Incorrect"
|
||||||
|
name="incorrect"
|
||||||
|
domain="[('success', '=', False)]"
|
||||||
|
/>
|
||||||
<newline />
|
<newline />
|
||||||
<group expand="0" string="Group by...">
|
<group expand="0" string="Group by...">
|
||||||
<filter string="Inspection"
|
<filter
|
||||||
name="group_by_inspection_id"
|
string="Inspection"
|
||||||
domain="[]"
|
name="group_by_inspection_id"
|
||||||
context="{'group_by': 'inspection_id'}" />
|
domain="[]"
|
||||||
<filter string="Product"
|
context="{'group_by': 'inspection_id'}"
|
||||||
name="group_by_product_id"
|
/>
|
||||||
domain="[]"
|
<filter
|
||||||
context="{'group_by': 'product_id'}" />
|
string="Product"
|
||||||
<filter string="Question"
|
name="group_by_product_id"
|
||||||
name="group_by_name"
|
domain="[]"
|
||||||
domain="[]"
|
context="{'group_by': 'product_id'}"
|
||||||
context="{'group_by': 'name'}" />
|
/>
|
||||||
<filter string="Success"
|
<filter
|
||||||
name="group_by_success"
|
string="Question"
|
||||||
domain="[]"
|
name="group_by_name"
|
||||||
context="{'group_by': 'success'}" />
|
domain="[]"
|
||||||
|
context="{'group_by': 'name'}"
|
||||||
|
/>
|
||||||
|
<filter
|
||||||
|
string="Success"
|
||||||
|
name="group_by_success"
|
||||||
|
domain="[]"
|
||||||
|
context="{'group_by': 'success'}"
|
||||||
|
/>
|
||||||
</group>
|
</group>
|
||||||
</search>
|
</search>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="ir.actions.act_window" id="action_qc_inspection_line">
|
<record model="ir.actions.act_window" id="action_qc_inspection_line">
|
||||||
<field name="name">Inspection lines</field>
|
<field name="name">Inspection lines</field>
|
||||||
<field name="res_model">qc.inspection.line</field>
|
<field name="res_model">qc.inspection.line</field>
|
||||||
<field name="view_type">form</field>
|
<field name="view_type">form</field>
|
||||||
<field name="view_mode">tree</field>
|
<field name="view_mode">tree</field>
|
||||||
</record>
|
</record>
|
||||||
|
<menuitem
|
||||||
<menuitem name="Inspection lines"
|
name="Inspection lines"
|
||||||
parent="qc_inspection_menu_parent"
|
parent="qc_inspection_menu_parent"
|
||||||
id="qc_inspection_lines_menu"
|
id="qc_inspection_lines_menu"
|
||||||
action="action_qc_inspection_line" />
|
action="action_qc_inspection_line"
|
||||||
|
/>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<!-- Copyright 2010 NaN Projectes de Programari Lliure, S.L.
|
<!-- Copyright 2010 NaN Projectes de Programari Lliure, S.L.
|
||||||
Copyright 2014 Serv. Tec. Avanzados - Pedro M. Baeza
|
Copyright 2014 Serv. Tec. Avanzados - Pedro M. Baeza
|
||||||
Copyright 2014 Oihane Crucelaegui - AvanzOSC
|
Copyright 2014 Oihane Crucelaegui - AvanzOSC
|
||||||
@@ -6,29 +6,31 @@
|
|||||||
Copyright 2017 Simone Rubino - Agile Business Group
|
Copyright 2017 Simone Rubino - Agile Business Group
|
||||||
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
|
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
|
||||||
<odoo>
|
<odoo>
|
||||||
|
<menuitem
|
||||||
<menuitem name="Quality control"
|
name="Quality control"
|
||||||
id="qc_menu"
|
id="qc_menu"
|
||||||
groups="group_quality_control_user"
|
groups="group_quality_control_user"
|
||||||
web_icon="quality_control,static/description/icon.png"
|
web_icon="quality_control,static/description/icon.png"
|
||||||
sequence="40"
|
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"
|
||||||
|
groups="group_quality_control_manager"
|
||||||
|
sequence="20"
|
||||||
|
/>
|
||||||
|
<menuitem
|
||||||
|
name="Configuration"
|
||||||
|
id="menu_qc_config"
|
||||||
|
groups="base.group_system"
|
||||||
|
parent="qc_menu"
|
||||||
|
sequence="100"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<menuitem name="Inspections"
|
|
||||||
parent="qc_menu"
|
|
||||||
id="qc_inspection_menu_parent"
|
|
||||||
sequence="10"/>
|
|
||||||
|
|
||||||
<menuitem parent="qc_menu"
|
|
||||||
name="Tests"
|
|
||||||
id="qc_menu_test_parent"
|
|
||||||
groups="group_quality_control_manager"
|
|
||||||
sequence="20"/>
|
|
||||||
|
|
||||||
<menuitem name="Configuration"
|
|
||||||
id="menu_qc_config"
|
|
||||||
groups="base.group_system"
|
|
||||||
parent="qc_menu"
|
|
||||||
sequence="100"/>
|
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<!-- Copyright 2010 NaN Projectes de Programari Lliure, S.L.
|
<!-- Copyright 2010 NaN Projectes de Programari Lliure, S.L.
|
||||||
Copyright 2014 Serv. Tec. Avanzados - Pedro M. Baeza
|
Copyright 2014 Serv. Tec. Avanzados - Pedro M. Baeza
|
||||||
Copyright 2014 Oihane Crucelaegui - AvanzOSC
|
Copyright 2014 Oihane Crucelaegui - AvanzOSC
|
||||||
@@ -6,32 +6,30 @@
|
|||||||
Copyright 2017 Simone Rubino - Agile Business Group
|
Copyright 2017 Simone Rubino - Agile Business Group
|
||||||
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
|
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
|
||||||
<odoo>
|
<odoo>
|
||||||
|
|
||||||
<record model="ir.ui.view" id="qc_test_category_tree_view">
|
<record model="ir.ui.view" id="qc_test_category_tree_view">
|
||||||
<field name="name">qc.test.category.tree</field>
|
<field name="name">qc.test.category.tree</field>
|
||||||
<field name="model">qc.test.category</field>
|
<field name="model">qc.test.category</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<tree string="Test categories" editable="bottom">
|
<tree string="Test categories" editable="bottom">
|
||||||
<field name="complete_name"/>
|
<field name="complete_name" />
|
||||||
<field name="name"/>
|
<field name="name" />
|
||||||
<field name="parent_id"/>
|
<field name="parent_id" />
|
||||||
<field name="active"/>
|
<field name="active" />
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="ir.actions.act_window" id="action_qc_test_category">
|
<record model="ir.actions.act_window" id="action_qc_test_category">
|
||||||
<field name="name">Test categories</field>
|
<field name="name">Test categories</field>
|
||||||
<field name="res_model">qc.test.category</field>
|
<field name="res_model">qc.test.category</field>
|
||||||
<field name="view_type">form</field>
|
<field name="view_type">form</field>
|
||||||
<field name="view_mode">tree,form</field>
|
<field name="view_mode">tree,form</field>
|
||||||
</record>
|
</record>
|
||||||
|
<menuitem
|
||||||
<menuitem name="Test categories"
|
name="Test categories"
|
||||||
parent="qc_menu_test_parent"
|
parent="qc_menu_test_parent"
|
||||||
id="qc_test_category_menu"
|
id="qc_test_category_menu"
|
||||||
action="action_qc_test_category"
|
action="action_qc_test_category"
|
||||||
groups="group_quality_control_manager"
|
groups="group_quality_control_manager"
|
||||||
sequence="10" />
|
sequence="10"
|
||||||
|
/>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<!-- Copyright 2010 NaN Projectes de Programari Lliure, S.L.
|
<!-- Copyright 2010 NaN Projectes de Programari Lliure, S.L.
|
||||||
Copyright 2014 Serv. Tec. Avanzados - Pedro M. Baeza
|
Copyright 2014 Serv. Tec. Avanzados - Pedro M. Baeza
|
||||||
Copyright 2014 Oihane Crucelaegui - AvanzOSC
|
Copyright 2014 Oihane Crucelaegui - AvanzOSC
|
||||||
@@ -6,33 +6,37 @@
|
|||||||
Copyright 2017 Simone Rubino - Agile Business Group
|
Copyright 2017 Simone Rubino - Agile Business Group
|
||||||
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
|
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
|
||||||
<odoo>
|
<odoo>
|
||||||
|
|
||||||
<record model="ir.ui.view" id="qc_test_form_view">
|
<record model="ir.ui.view" id="qc_test_form_view">
|
||||||
<field name="name">qc.test.form</field>
|
<field name="name">qc.test.form</field>
|
||||||
<field name="model">qc.test</field>
|
<field name="model">qc.test</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="Test">
|
<form string="Test">
|
||||||
<sheet>
|
<sheet>
|
||||||
<label for="name" class="oe_edit_only"/>
|
<label for="name" class="oe_edit_only" />
|
||||||
<h1>
|
<h1>
|
||||||
<field name="name" class="oe_inline"/>
|
<field name="name" class="oe_inline" />
|
||||||
</h1>
|
</h1>
|
||||||
<group>
|
<group>
|
||||||
<group>
|
<group>
|
||||||
<field name="type" />
|
<field name="type" />
|
||||||
<field name="object_id"
|
<field
|
||||||
attrs="{'invisible': [('type','=','generic')]}"/>
|
name="object_id"
|
||||||
|
attrs="{'invisible': [('type','=','generic')]}"
|
||||||
|
/>
|
||||||
<field name="active" />
|
<field name="active" />
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group>
|
||||||
<field name="category" />
|
<field name="category" />
|
||||||
<field name="fill_correct_values" />
|
<field name="fill_correct_values" />
|
||||||
<field name="company_id" groups="base.group_multi_company"/>
|
<field
|
||||||
|
name="company_id"
|
||||||
|
groups="base.group_multi_company"
|
||||||
|
/>
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
<field name="test_lines" nolabel="1" >
|
<field name="test_lines" nolabel="1">
|
||||||
<tree string="Questions">
|
<tree string="Questions">
|
||||||
<field name="sequence" widget="handle"/>
|
<field name="sequence" widget="handle" />
|
||||||
<field name="name" />
|
<field name="name" />
|
||||||
<field name="type" />
|
<field name="type" />
|
||||||
<field name="min_value" />
|
<field name="min_value" />
|
||||||
@@ -45,7 +49,6 @@
|
|||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="ir.ui.view" id="qc_test_tree_view">
|
<record model="ir.ui.view" id="qc_test_tree_view">
|
||||||
<field name="name">qc.test.tree</field>
|
<field name="name">qc.test.tree</field>
|
||||||
<field name="model">qc.test</field>
|
<field name="model">qc.test</field>
|
||||||
@@ -55,18 +58,16 @@
|
|||||||
<field name="category" />
|
<field name="category" />
|
||||||
<field name="type" />
|
<field name="type" />
|
||||||
<field name="object_id" />
|
<field name="object_id" />
|
||||||
<field name="company_id" groups="base.group_multi_company"/>
|
<field name="company_id" groups="base.group_multi_company" />
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="ir.actions.act_window" id="action_qc_test">
|
<record model="ir.actions.act_window" id="action_qc_test">
|
||||||
<field name="name">Tests</field>
|
<field name="name">Tests</field>
|
||||||
<field name="res_model">qc.test</field>
|
<field name="res_model">qc.test</field>
|
||||||
<field name="view_type">form</field>
|
<field name="view_type">form</field>
|
||||||
<field name="view_mode">tree,form</field>
|
<field name="view_mode">tree,form</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="ir.ui.view" id="qc_test_question_form_view">
|
<record model="ir.ui.view" id="qc_test_question_form_view">
|
||||||
<field name="name">qc.test.question.form</field>
|
<field name="name">qc.test.question.form</field>
|
||||||
<field name="model">qc.test.question</field>
|
<field name="model">qc.test.question</field>
|
||||||
@@ -80,39 +81,51 @@
|
|||||||
<field name="sequence" />
|
<field name="sequence" />
|
||||||
<field name="type" />
|
<field name="type" />
|
||||||
</group>
|
</group>
|
||||||
<group name="qualitative"
|
<group
|
||||||
string="Answers"
|
name="qualitative"
|
||||||
colspan="4"
|
string="Answers"
|
||||||
attrs="{'invisible': [('type', '!=', 'qualitative')]}">
|
colspan="4"
|
||||||
<field name="ql_values"
|
attrs="{'invisible': [('type', '!=', 'qualitative')]}"
|
||||||
nolabel="1"
|
>
|
||||||
attrs="{'required': [('type','=','qualitative')]}">
|
<field
|
||||||
|
name="ql_values"
|
||||||
|
nolabel="1"
|
||||||
|
attrs="{'required': [('type','=','qualitative')]}"
|
||||||
|
>
|
||||||
<tree string="Question value" editable="bottom">
|
<tree string="Question value" editable="bottom">
|
||||||
<field name="name" />
|
<field name="name" />
|
||||||
<field name="ok" />
|
<field name="ok" />
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</group>
|
</group>
|
||||||
<div name="quantitative"
|
<div
|
||||||
align="center"
|
name="quantitative"
|
||||||
attrs="{'invisible': [('type', '!=', 'quantitative')]}" >
|
align="center"
|
||||||
|
attrs="{'invisible': [('type', '!=', 'quantitative')]}"
|
||||||
|
>
|
||||||
<h1 name="quantitative-data">
|
<h1 name="quantitative-data">
|
||||||
<span name="quantitative-interval" >
|
<span name="quantitative-interval">
|
||||||
<field name="min_value"
|
<field
|
||||||
class="oe_inline"
|
name="min_value"
|
||||||
nolabel="1"
|
class="oe_inline"
|
||||||
attrs="{'required': [('type','=', 'quantitative')]}" />
|
nolabel="1"
|
||||||
|
attrs="{'required': [('type','=', 'quantitative')]}"
|
||||||
|
/>
|
||||||
<span> - </span>
|
<span> - </span>
|
||||||
<field name="max_value"
|
<field
|
||||||
class="oe_inline"
|
name="max_value"
|
||||||
nolabel="1"
|
class="oe_inline"
|
||||||
attrs="{'required': [('type', '=', 'quantitative')]}" />
|
nolabel="1"
|
||||||
|
attrs="{'required': [('type', '=', 'quantitative')]}"
|
||||||
|
/>
|
||||||
</span>
|
</span>
|
||||||
<span name="quantitative-uom" >
|
<span name="quantitative-uom">
|
||||||
<field name="uom_id"
|
<field
|
||||||
class="oe_inline"
|
name="uom_id"
|
||||||
nolabel="1"
|
class="oe_inline"
|
||||||
attrs="{'required': [('type', '=', 'quantitative')]}" />
|
nolabel="1"
|
||||||
|
attrs="{'required': [('type', '=', 'quantitative')]}"
|
||||||
|
/>
|
||||||
</span>
|
</span>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
@@ -120,12 +133,12 @@
|
|||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
<menuitem
|
||||||
<menuitem name="Tests"
|
name="Tests"
|
||||||
parent="qc_menu_test_parent"
|
parent="qc_menu_test_parent"
|
||||||
id="qc_test_menu"
|
id="qc_test_menu"
|
||||||
action="action_qc_test"
|
action="action_qc_test"
|
||||||
groups="group_quality_control_manager"
|
groups="group_quality_control_manager"
|
||||||
sequence="20" />
|
sequence="20"
|
||||||
|
/>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<!-- Copyright 2010 NaN Projectes de Programari Lliure, S.L.
|
<!-- Copyright 2010 NaN Projectes de Programari Lliure, S.L.
|
||||||
Copyright 2014 Serv. Tec. Avanzados - Pedro M. Baeza
|
Copyright 2014 Serv. Tec. Avanzados - Pedro M. Baeza
|
||||||
Copyright 2014 Oihane Crucelaegui - AvanzOSC
|
Copyright 2014 Oihane Crucelaegui - AvanzOSC
|
||||||
@@ -6,34 +6,30 @@
|
|||||||
Copyright 2017 Simone Rubino - Agile Business Group
|
Copyright 2017 Simone Rubino - Agile Business Group
|
||||||
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
|
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
|
||||||
<odoo>
|
<odoo>
|
||||||
|
|
||||||
<record model="ir.ui.view" id="qc_trigger_form_view">
|
<record model="ir.ui.view" id="qc_trigger_form_view">
|
||||||
<field name="name">qc.trigger.form</field>
|
<field name="name">qc.trigger.form</field>
|
||||||
<field name="model">qc.trigger</field>
|
<field name="model">qc.trigger</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="Quality control trigger">
|
<form string="Quality control trigger">
|
||||||
<group>
|
<group>
|
||||||
<field name="name" />
|
<field name="name" />
|
||||||
<field name="active" />
|
<field name="active" />
|
||||||
<field name="partner_selectable" />
|
<field name="partner_selectable" />
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group>
|
||||||
<field name="company_id" groups="base.group_multi_company"/>
|
<field name="company_id" groups="base.group_multi_company" />
|
||||||
</group>
|
</group>
|
||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="ir.ui.view" id="qc_trigger_tree_view">
|
<record model="ir.ui.view" id="qc_trigger_tree_view">
|
||||||
<field name="name">qc.trigger.tree</field>
|
<field name="name">qc.trigger.tree</field>
|
||||||
<field name="model">qc.trigger</field>
|
<field name="model">qc.trigger</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<tree string="Quality control triggers" editable="bottom">
|
<tree string="Quality control triggers" editable="bottom">
|
||||||
<field name="name" />
|
<field name="name" />
|
||||||
<field name="company_id" groups="base.group_multi_company"/>
|
<field name="company_id" groups="base.group_multi_company" />
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|
||||||
|
|||||||
@@ -14,17 +14,16 @@ class QcInspectionSetTest(models.TransientModel):
|
|||||||
also fill in all lines of the inspection with the corresponding lines of
|
also fill in all lines of the inspection with the corresponding lines of
|
||||||
the template.
|
the template.
|
||||||
"""
|
"""
|
||||||
_name = 'qc.inspection.set.test'
|
|
||||||
_description = 'Set test for inspection'
|
|
||||||
|
|
||||||
test = fields.Many2one(comodel_name='qc.test', string='Test')
|
_name = "qc.inspection.set.test"
|
||||||
|
_description = "Set test for inspection"
|
||||||
|
|
||||||
|
test = fields.Many2one(comodel_name="qc.test", string="Test")
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def action_create_test(self):
|
def action_create_test(self):
|
||||||
inspection = self.env['qc.inspection'].browse(
|
inspection = self.env["qc.inspection"].browse(self.env.context["active_id"])
|
||||||
self.env.context['active_id'])
|
|
||||||
inspection.test = self.test
|
inspection.test = self.test
|
||||||
inspection.inspection_lines.unlink()
|
inspection.inspection_lines.unlink()
|
||||||
inspection.inspection_lines = inspection._prepare_inspection_lines(
|
inspection.inspection_lines = inspection._prepare_inspection_lines(self.test)
|
||||||
self.test)
|
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
<!-- Copyright 2010 NaN Projectes de Programari Lliure, S.L.
|
<!-- Copyright 2010 NaN Projectes de Programari Lliure, S.L.
|
||||||
Copyright 2014 Serv. Tec. Avanzados - Pedro M. Baeza
|
Copyright 2014 Serv. Tec. Avanzados - Pedro M. Baeza
|
||||||
Copyright 2014 Oihane Crucelaegui - AvanzOSC
|
Copyright 2014 Oihane Crucelaegui - AvanzOSC
|
||||||
@@ -6,7 +6,6 @@
|
|||||||
Copyright 2017 Simone Rubino - Agile Business Group
|
Copyright 2017 Simone Rubino - Agile Business Group
|
||||||
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
|
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
|
||||||
<odoo>
|
<odoo>
|
||||||
|
|
||||||
<record id="view_qc_test_set_test_form" model="ir.ui.view">
|
<record id="view_qc_test_set_test_form" model="ir.ui.view">
|
||||||
<field name="name">qc.inspection.set.test.form</field>
|
<field name="name">qc.inspection.set.test.form</field>
|
||||||
<field name="model">qc.inspection.set.test</field>
|
<field name="model">qc.inspection.set.test</field>
|
||||||
@@ -16,19 +15,18 @@
|
|||||||
<field name="test" />
|
<field name="test" />
|
||||||
</group>
|
</group>
|
||||||
<footer>
|
<footer>
|
||||||
<button name="action_create_test"
|
<button
|
||||||
string="Accept"
|
name="action_create_test"
|
||||||
type="object"
|
string="Accept"
|
||||||
class="oe_highlight"/>
|
type="object"
|
||||||
|
class="oe_highlight"
|
||||||
|
/>
|
||||||
or
|
or
|
||||||
<button special="cancel"
|
<button special="cancel" class="oe_link" string="Cancel" />
|
||||||
class="oe_link"
|
|
||||||
string="Cancel" />
|
|
||||||
</footer>
|
</footer>
|
||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="action_qc_inspection_set_test" model="ir.actions.act_window">
|
<record id="action_qc_inspection_set_test" model="ir.actions.act_window">
|
||||||
<field name="name">Select test</field>
|
<field name="name">Select test</field>
|
||||||
<field name="type">ir.actions.act_window</field>
|
<field name="type">ir.actions.act_window</field>
|
||||||
@@ -37,5 +35,4 @@
|
|||||||
<field name="view_mode">form</field>
|
<field name="view_mode">form</field>
|
||||||
<field name="target">new</field>
|
<field name="target">new</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
Reference in New Issue
Block a user