Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions quality_control_oca/views/product_category_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
/>
<field name="test" />
<field name="user" />
<field name="timing" />
<field name="partners" widget="many2many_tags" />
</list>
</field>
Expand Down
1 change: 1 addition & 0 deletions quality_control_oca/views/product_template_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
/>
<field name="test" />
<field name="user" />
<field name="timing" />
<field name="partners" widget="many2many_tags" />
<field name="timing" />
</list>
Expand Down
2 changes: 1 addition & 1 deletion quality_control_oca/views/qc_inspection_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
name="action_todo"
type="object"
class="oe_highlight"
invisible="state != 'draft'"
invisible="state not in ('draft', 'plan')"
string="Mark todo"
/>
<button
Expand Down
8 changes: 8 additions & 0 deletions quality_control_stock_oca/i18n/fr_FR.po
Original file line number Diff line number Diff line change
Expand Up @@ -168,3 +168,11 @@ msgstr ""
#: model_terms:ir.ui.view,arch_db:quality_control_stock_oca.stock_picking_qc_view
msgid "inspections"
msgstr ""

#. module: quality_control_stock_oca
#. odoo-python
#: code:addons/quality_control_stock_oca/models/stock_picking.py:0
#, python-format
msgid "Control quality is required to validate this Transfert."
msgstr "La qualité doit être contrôlée pour valider ce transfert."

31 changes: 30 additions & 1 deletion quality_control_stock_oca/models/qc_inspection.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,32 @@ class QcInspection(models.Model):
comodel_name="stock.lot", compute="_compute_lot", store=True
)

is_mandatory_to_validate = fields.Boolean(
compute="_compute_is_mandatory_to_validate",
)

@api.depends("picking_id")
def _compute_is_mandatory_to_validate(self):
for inspection in self:
if inspection.picking_id:
inspection.is_mandatory_to_validate = bool(
self.env["qc.trigger"]
.sudo()
.search(
[
(
"picking_type_id",
"=",
inspection.picking_id.picking_type_id.id,
),
("is_mandatory_to_validate", "=", True),
],
limit=1,
)
)
else:
inspection.is_mandatory_to_validate = False

def object_selection_values(self):
result = super().object_selection_values()
result.extend(
Expand Down Expand Up @@ -45,11 +71,14 @@ def _compute_lot(self):
)
for inspection in self.filtered("object_id"):
if inspection.object_id._name == "stock.move":
inspection.lot_id = first(
lot = first(
move_lines.filtered(
lambda x, ins=inspection: x.move_id == ins.object_id
)
).lot_id
if not lot and "restrict_lot_id" in inspection.object_id._fields:
lot = inspection.object_id and inspection.object_id.restrict_lot_id
inspection.lot_id = lot
elif inspection.object_id._name == "stock.lot":
inspection.lot_id = inspection.object_id

Expand Down
1 change: 1 addition & 0 deletions quality_control_stock_oca/models/qc_trigger.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ class QcTrigger(models.Model):
help="If checked, an inspection per used lot/serial number "
"will be created in stock pickings."
)
is_mandatory_to_validate = fields.Boolean()
29 changes: 28 additions & 1 deletion quality_control_stock_oca/models/stock_picking.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# Copyright 2024 Quartile
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo import api, fields, models
from odoo import _, api, fields, models


class StockPicking(models.Model):
Expand All @@ -30,6 +30,22 @@ class StockPicking(models.Model):
compute="_compute_count_inspections", string="Inspections failed"
)

inspection_required_message = fields.Html(
readonly=True, compute="_compute_inspection_required_message"
)

@api.depends("qc_inspections_ids")
def _compute_inspection_required_message(self):
message = _("Control quality is required to validate this " "Transfert.")
for rec in self:
if rec.qc_inspections_ids and rec.qc_inspections_ids.filtered(
lambda x: x.state not in ["success", "failed"]
and x.is_mandatory_to_validate
):
rec.inspection_required_message = message
else:
rec.inspection_required_message = False

@api.depends("qc_inspections_ids", "qc_inspections_ids.state")
def _compute_count_inspections(self):
data = (
Expand Down Expand Up @@ -79,6 +95,17 @@ def action_cancel(self):
return res

def _action_done(self):
for picking in self:
picking_names = ""
if picking.inspection_required_message:
picking_names += f"- {picking.name}\n"
if picking_names:
raise models.UserError(
_(
"You must validate the following inspections "
"before validating the picking:\n" + picking_names
)
)
res = super()._action_done()
plan_inspections = self.sudo().qc_inspections_ids.filtered(
lambda x: x.state == "plan"
Expand Down
45 changes: 41 additions & 4 deletions quality_control_stock_oca/tests/test_quality_control_stock.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# Copyright 2018 Simone Rubino - Agile Business Group
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo.exceptions import UserError
from odoo.tests import Form, new_test_user
from odoo.tools import mute_logger

Expand Down Expand Up @@ -50,16 +51,16 @@ def setUpClass(cls):
login="test_quality_control_stock_oca",
groups=f"{'stock.group_stock_user'},{'quality_control_oca.group_quality_control_user'}",
)
picking_form = Form(
cls.picking_form = Form(
cls.env["stock.picking"]
.with_user(cls.user)
.with_context(default_picking_type_id=cls.picking_type.id)
)
picking_form.partner_id = cls.partner1
with picking_form.move_ids_without_package.new() as move_form:
cls.picking_form.partner_id = cls.partner1
with cls.picking_form.move_ids_without_package.new() as move_form:
move_form.product_id = cls.product
move_form.product_uom_qty = 2
cls.picking1 = picking_form.save()
cls.picking1 = cls.picking_form.save()

def picking_confirmation(self):
self.picking1.action_confirm()
Expand Down Expand Up @@ -497,3 +498,39 @@ def test_qc_inspection_lot_multiple(self):
1,
"Created inspections for lot2 must be equal to 1.",
)

def test_qc_inspection_mandatory_to_validate(self):
self.trigger.is_mandatory_to_validate = True
self.product.qc_triggers = [
(
0,
0,
{
"trigger": self.trigger.id,
"test": self.test.id,
"timing": "plan_ahead",
},
)
]
with self.picking_form.move_ids_without_package.new() as move_form:
move_form.product_id = self.product
move_form.product_uom_qty = 2
picking2 = self.picking_form.save()
picking2.action_confirm()
inspection = picking2.qc_inspections_ids
self.assertTrue(inspection.is_mandatory_to_validate)
self.assertIn(
"Control quality is required", picking2.inspection_required_message
)
with self.assertRaises(UserError) as m:
picking2._action_done()
self.assertIn("inspections before validating", m.exception.args[0])
self.assertIn(picking2.name, m.exception.args[0])
# then we confirm the inspection, so we can validate the picking
for line in inspection.inspection_lines:
if line.question_type == "qualitative":
line.qualitative_value = self.val_ok
if line.question_type == "quantitative":
line.quantitative_value = 5.0
inspection.action_confirm()
picking2._action_done()
8 changes: 4 additions & 4 deletions quality_control_stock_oca/views/qc_trigger_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@
<xpath expr="//field[@name='partner_selectable']" position="after">
<field name="picking_type_id" readonly="1" />
<field name="inspection_per_lot" invisible="not picking_type_id" />
<field name="is_mandatory_to_validate" widget="boolean_toggle" />
</xpath>
</field>
</record>
<record model="ir.ui.view" id="qc_trigger_tree_view">
<field name="name">qc.trigger.form</field>
<field name="name">qc.trigger.tree</field>
<field name="model">qc.trigger</field>
<field name='inherit_id' ref='quality_control_oca.qc_trigger_tree_view' />
<field name="arch" type="xml">
<xpath expr="//field[@name='partner_selectable']" position="after">
<field name="picking_type_id" column_invisible="True" />
<field name="inspection_per_lot" invisible="not picking_type_id" />
<xpath expr="//field[@name='company_id']" position="before">
<field name="is_mandatory_to_validate" widget="boolean_toggle" />
</xpath>
</field>
</record>
Expand Down
24 changes: 19 additions & 5 deletions quality_control_stock_oca/views/stock_picking_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,44 +37,58 @@
<field name="model">stock.picking</field>
<field name="inherit_id" ref="stock.view_picking_form" />
<field name="arch" type="xml">
<sheet position="before">
<div
class="alert alert-danger alert-dismissable"
role="alert"
style="margin-bottom:0px;"
invisible="not inspection_required_message"
>
<field name="inspection_required_message" />
</div>
</sheet>
<div name="button_box" position="inside">
<button
class="oe_inline oe_stat_button"
type="action"
name="%(action_qc_inspection_per_picking)d"
icon="fa-list"
string="inspections"
groups="quality_control_oca.group_quality_control_user"
invisible="not created_inspections"
>
<field
name="created_inspections"
widget="statinfo"
string="inspections"
/>
<field name="created_inspections" widget="statinfo" />
</button>
<button
class="oe_inline oe_stat_button"
type="action"
string="Done inspections"
name="%(action_qc_inspection_per_picking_done)d"
icon="fa-pencil"
groups="quality_control_oca.group_quality_control_user"
invisible="not done_inspections"
>
<field name="done_inspections" widget="statinfo" />
</button>
<button
class="oe_inline oe_stat_button"
type="action"
string="Passed inspections"
name="%(action_qc_inspection_per_picking_passed)d"
icon="fa-thumbs-o-up"
groups="quality_control_oca.group_quality_control_user"
invisible="not passed_inspections"
>
<field name="passed_inspections" widget="statinfo" />
</button>
<button
class="oe_inline oe_stat_button"
type="action"
string="Failed inspections"
name="%(action_qc_inspection_per_picking_failed)d"
icon="fa-thumbs-o-down"
groups="quality_control_oca.group_quality_control_user"
invisible="not failed_inspections"
>
<field
name="failed_inspections"
Expand Down