[IMP] quality_control: black, isort

This commit is contained in:
ps-tubtim
2020-03-16 17:32:22 +07:00
committed by Enrique Martín
parent 7c94dfb8f8
commit d6bd05b4b4
25 changed files with 878 additions and 684 deletions

View File

@@ -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,
} }

View File

@@ -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>

View File

@@ -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>

View File

@@ -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",
)

View File

@@ -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",
)

View File

@@ -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",
)

View File

@@ -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
)

View File

@@ -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.",
)

View File

@@ -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.",
)

View File

@@ -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",
)

View File

@@ -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

View File

@@ -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.

View File

@@ -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>

View File

@@ -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})],
}) }
)

View File

@@ -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 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>
@@ -16,7 +15,10 @@
<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>

View File

@@ -6,18 +6,23 @@
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
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" />
@@ -27,5 +32,4 @@
</page> </page>
</field> </field>
</record> </record>
</odoo> </odoo>

View File

@@ -6,52 +6,65 @@
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
name="action_draft"
type="object" type="object"
attrs="{'invisible': [('state', '!=', 'canceled')]}" attrs="{'invisible': [('state', '!=', 'canceled')]}"
string="Draft" /> string="Draft"
<button name="action_todo" />
<button
name="action_todo"
type="object" type="object"
class="oe_highlight" class="oe_highlight"
states="draft" states="draft"
string="Mark todo" /> string="Mark todo"
<button name="action_confirm" />
<button
name="action_confirm"
type="object" type="object"
class="oe_highlight" class="oe_highlight"
states="ready" states="ready"
string="Confirm" string="Confirm"
icon="fa-check" /> icon="fa-check"
<button name="action_approve" />
<button
name="action_approve"
type="object" type="object"
states="waiting" states="waiting"
class="oe_highlight" class="oe_highlight"
groups="quality_control.group_quality_control_manager" groups="quality_control.group_quality_control_manager"
string="Approve" /> string="Approve"
<button name="action_cancel" />
<button
name="action_cancel"
type="object" type="object"
attrs="{'invisible': [('state', 'not in', ['waiting', 'ready', 'failed', 'success'])]}" attrs="{'invisible': [('state', 'not in', ['waiting', 'ready', 'failed', 'success'])]}"
string="Cancel" string="Cancel"
icon="fa-ban" /> icon="fa-ban"
<field name="state" />
<field
name="state"
widget="statusbar" widget="statusbar"
statusbar_visible="draft,waiting,success" statusbar_visible="draft,waiting,success"
statusbar_colors='{"success": "blue", "failed": "red"}' /> 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
class="oe_inline oe_stat_button"
type="action" type="action"
name="%(action_qc_inspection_set_test)d" name="%(action_qc_inspection_set_test)d"
icon="fa-bookmark-o" icon="fa-bookmark-o"
states="draft" states="draft"
string="Set test" /> string="Set test"
/>
</div> </div>
<h1> <h1>
<label string="Inspection " for="name" /> <label string="Inspection " for="name" />
@@ -74,17 +87,28 @@
<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
name="quantitative_value"
attrs="{'readonly': [('question_type', '=', 'qualitative')]}"
/>
<field
name="uom_id"
groups="uom.group_uom" groups="uom.group_uom"
attrs="{'readonly': [('question_type', '=', 'qualitative')]}" /> attrs="{'readonly': [('question_type', '=', 'qualitative')]}"
/>
<field name="test_uom_category" invisible="1" /> <field name="test_uom_category" invisible="1" />
<field name="min_value" invisible="1" /> <field name="min_value" invisible="1" />
<field name="max_value" invisible="1" /> <field name="max_value" invisible="1" />
@@ -95,24 +119,25 @@
</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
name="message_follower_ids"
widget="mail_followers"
groups="base.group_user"
/>
<field name="message_ids" widget="mail_thread" /> <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
string="Correct"
name="correct" name="correct"
domain="[('success', '=', True)]"/> domain="[('success', '=', True)]"
<filter string="Incorrect" />
<filter
string="Incorrect"
name="incorrect" name="incorrect"
domain="[('success', '=', False)]"/> domain="[('success', '=', False)]"
/>
<newline /> <newline />
<group expand="0" string="Group by..."> <group expand="0" string="Group by...">
<filter string="Reference" <filter
string="Reference"
name="group_by_object_id" name="group_by_object_id"
domain="[]" domain="[]"
context="{'group_by': 'object_id'}" /> context="{'group_by': 'object_id'}"
<filter string="Test" />
<filter
string="Test"
name="group_by_test" name="group_by_test"
domain="[]" domain="[]"
context="{'group_by': 'test'}" /> context="{'group_by': 'test'}"
<filter string="Responsible" />
<filter
string="Responsible"
name="group_by_user" name="group_by_user"
domain="[]" domain="[]"
context="{'group_by': 'user'}" /> context="{'group_by': 'user'}"
<filter string="Product" />
<filter
string="Product"
name="group_by_product_id" name="group_by_product_id"
domain="[]" domain="[]"
context="{'group_by': 'product_id'}" /> context="{'group_by': 'product_id'}"
<filter string="State" />
<filter
string="State"
name="group_by_state" name="group_by_state"
domain="[]" domain="[]"
context="{'group_by': 'state'}" /> context="{'group_by': 'state'}"
<filter string="Success" />
<filter
string="Success"
name="group_by_success" name="group_by_success"
domain="[]" domain="[]"
context="{'group_by': 'success'}" /> context="{'group_by': 'success'}"
<filter string="Auto-generated" />
<filter
string="Auto-generated"
name="group_by_auto_generated" name="group_by_auto_generated"
domain="[]" domain="[]"
context="{'group_by': 'auto_generated'}" /> 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
name="quantitative_value"
attrs="{'readonly': [('question_type', '=', 'qualitative')]}"
/>
<field
name="uom_id"
groups="uom.group_uom" groups="uom.group_uom"
attrs="{'readonly': [('question_type', '=', 'qualitative')]}" /> attrs="{'readonly': [('question_type', '=', 'qualitative')]}"
/>
<field name="test_uom_category" invisible="1" /> <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
string="Correct"
name="correct" name="correct"
domain="[('success', '=', True)]"/> domain="[('success', '=', True)]"
<filter string="Incorrect" />
<filter
string="Incorrect"
name="incorrect" name="incorrect"
domain="[('success', '=', False)]"/> domain="[('success', '=', False)]"
/>
<newline /> <newline />
<group expand="0" string="Group by..."> <group expand="0" string="Group by...">
<filter string="Inspection" <filter
string="Inspection"
name="group_by_inspection_id" name="group_by_inspection_id"
domain="[]" domain="[]"
context="{'group_by': 'inspection_id'}" /> context="{'group_by': 'inspection_id'}"
<filter string="Product" />
<filter
string="Product"
name="group_by_product_id" name="group_by_product_id"
domain="[]" domain="[]"
context="{'group_by': 'product_id'}" /> context="{'group_by': 'product_id'}"
<filter string="Question" />
<filter
string="Question"
name="group_by_name" name="group_by_name"
domain="[]" domain="[]"
context="{'group_by': 'name'}" /> context="{'group_by': 'name'}"
<filter string="Success" />
<filter
string="Success"
name="group_by_success" name="group_by_success"
domain="[]" domain="[]"
context="{'group_by': 'success'}" /> 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>

View File

@@ -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
<menuitem name="Inspections" name="Inspections"
parent="qc_menu" parent="qc_menu"
id="qc_inspection_menu_parent" id="qc_inspection_menu_parent"
sequence="10"/> sequence="10"
/>
<menuitem parent="qc_menu" <menuitem
parent="qc_menu"
name="Tests" name="Tests"
id="qc_menu_test_parent" id="qc_menu_test_parent"
groups="group_quality_control_manager" groups="group_quality_control_manager"
sequence="20"/> sequence="20"
/>
<menuitem name="Configuration" <menuitem
name="Configuration"
id="menu_qc_config" id="menu_qc_config"
groups="base.group_system" groups="base.group_system"
parent="qc_menu" parent="qc_menu"
sequence="100"/> sequence="100"
/>
</odoo> </odoo>

View File

@@ -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 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>
@@ -19,19 +18,18 @@
</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>

View File

@@ -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 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>
@@ -20,14 +19,19 @@
<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">
@@ -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>
@@ -59,14 +62,12 @@
</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
name="qualitative"
string="Answers" string="Answers"
colspan="4" colspan="4"
attrs="{'invisible': [('type', '!=', 'qualitative')]}"> attrs="{'invisible': [('type', '!=', 'qualitative')]}"
<field name="ql_values" >
<field
name="ql_values"
nolabel="1" nolabel="1"
attrs="{'required': [('type','=','qualitative')]}"> 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
name="quantitative"
align="center" align="center"
attrs="{'invisible': [('type', '!=', 'quantitative')]}" > 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
name="min_value"
class="oe_inline" class="oe_inline"
nolabel="1" nolabel="1"
attrs="{'required': [('type','=', 'quantitative')]}" /> attrs="{'required': [('type','=', 'quantitative')]}"
/>
<span> - </span> <span> - </span>
<field name="max_value" <field
name="max_value"
class="oe_inline" class="oe_inline"
nolabel="1" nolabel="1"
attrs="{'required': [('type', '=', 'quantitative')]}" /> attrs="{'required': [('type', '=', 'quantitative')]}"
/>
</span> </span>
<span name="quantitative-uom"> <span name="quantitative-uom">
<field name="uom_id" <field
name="uom_id"
class="oe_inline" class="oe_inline"
nolabel="1" nolabel="1"
attrs="{'required': [('type', '=', 'quantitative')]}" /> 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>

View File

@@ -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 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>
@@ -23,7 +22,6 @@
</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>
@@ -34,6 +32,4 @@
</tree> </tree>
</field> </field>
</record> </record>
</odoo> </odoo>

View File

@@ -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

View File

@@ -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
name="action_create_test"
string="Accept" string="Accept"
type="object" type="object"
class="oe_highlight"/> 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>