From b5ad9ad269e3d2fe1b71dcdcf351f40c28a7e668 Mon Sep 17 00:00:00 2001 From: Aungkokolin1997 Date: Thu, 6 Jun 2024 10:13:39 +0000 Subject: [PATCH] [IMP] quality_control_oca, quality_control_stock_oca This commit adds date_done field, update views and filters and the timing field in the QC trigger line to enable following scenarios: - When timing is 'Before', an inspection is generated for each related move when a picking with the trigger is confirmed. - When timing is 'Plan Ahead', a 'Plan' inspection is generated for each related move when a picking with the trigger is confirmed. A plan inspection is just a plan, and cannot be updated except for the date. A plan inspection gets converted into an executable inspection once the picking is done. --- quality_control_oca/models/qc_inspection.py | 27 ++++- quality_control_oca/models/qc_trigger_line.py | 18 ++- .../qc_trigger_product_category_line.py | 5 +- .../models/qc_trigger_product_line.py | 5 +- .../qc_trigger_product_template_line.py | 5 +- .../tests/test_quality_control.py | 7 +- .../views/product_template_view.xml | 1 + .../views/qc_inspection_view.xml | 28 ++++- quality_control_stock_oca/README.rst | 17 +++ quality_control_stock_oca/models/__init__.py | 1 + .../models/qc_inspection.py | 5 + .../models/stock_move.py | 68 +++++++++++ .../models/stock_picking.py | 57 +++++---- .../readme/CONFIGURE.rst | 8 ++ .../readme/CONTRIBUTORS.rst | 5 + .../static/description/index.html | 42 ++++--- .../tests/test_quality_control_stock.py | 109 +++++++++++++++++- 17 files changed, 353 insertions(+), 55 deletions(-) create mode 100644 quality_control_stock_oca/models/stock_move.py create mode 100644 quality_control_stock_oca/readme/CONFIGURE.rst diff --git a/quality_control_oca/models/qc_inspection.py b/quality_control_oca/models/qc_inspection.py index 885d841b0ba..897e24fe407 100644 --- a/quality_control_oca/models/qc_inspection.py +++ b/quality_control_oca/models/qc_inspection.py @@ -5,6 +5,8 @@ # Copyright 2017 Simone Rubino - Agile Business Group # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from datetime import datetime + from odoo import _, api, exceptions, fields, models from odoo.tools import formatLang @@ -43,12 +45,14 @@ def _compute_product_id(self): copy=False, ) date = fields.Datetime( + string="Plan Date", required=True, readonly=True, copy=False, default=fields.Datetime.now, - states={"draft": [("readonly", False)]}, + states={"plan": [("readonly", False)], "draft": [("readonly", False)]}, ) + date_done = fields.Datetime("Completion Date", readonly=True) object_id = fields.Reference( string="Reference", selection="object_selection_values", @@ -76,6 +80,7 @@ def _compute_product_id(self): ) state = fields.Selection( [ + ("plan", "Plan"), ("draft", "Draft"), ("ready", "Ready"), ("waiting", "Waiting supervisor approval"), @@ -119,6 +124,14 @@ def create(self, val_list): vals["name"] = self.env["ir.sequence"].next_by_code("qc.inspection") return super().create(vals) + def write(self, vals): + if "state" in vals: + if vals["state"] in ["success", "failed"]: + vals["date_done"] = datetime.now() + elif vals["state"] == "draft": + vals["date_done"] = False + return super().write(vals) + def unlink(self): for inspection in self: if inspection.auto_generated: @@ -184,7 +197,7 @@ def set_test(self, trigger_line, force_fill=False): trigger_line.test, force_fill=force_fill ) - def _make_inspection(self, object_ref, trigger_line): + def _make_inspection(self, object_ref, trigger_line, date=None): """Overridable hook method for creating inspection from test. :param object_ref: Object instance :param trigger_line: Trigger line instance @@ -193,6 +206,8 @@ def _make_inspection(self, object_ref, trigger_line): inspection = self.create( self._prepare_inspection_header(object_ref, trigger_line) ) + if date: + inspection.date = date inspection.set_test(trigger_line) return inspection @@ -206,7 +221,7 @@ def _prepare_inspection_header(self, object_ref, trigger_line): "object_id": object_ref and "{},{}".format(object_ref._name, object_ref.id) or False, - "state": "ready", + "state": trigger_line.timing == "plan_ahead" and "plan" or "ready", "test": trigger_line.test.id, "user": trigger_line.user.id, "auto_generated": True, @@ -245,6 +260,12 @@ def _prepare_inspection_line(self, test, line, fill=None): data["quantitative_value"] = (line.min_value + line.max_value) * 0.5 return data + def _get_existing_inspections(self, records): + reference_vals = [] + for rec in records: + reference_vals.append(",".join([rec._name, str(rec.id)])) + return self.sudo().search([("object_id", "in", reference_vals)]) + class QcInspectionLine(models.Model): _name = "qc.inspection.line" diff --git a/quality_control_oca/models/qc_trigger_line.py b/quality_control_oca/models/qc_trigger_line.py index 0c0b6e9591f..6bc54d85b0b 100644 --- a/quality_control_oca/models/qc_trigger_line.py +++ b/quality_control_oca/models/qc_trigger_line.py @@ -38,8 +38,24 @@ class QcTriggerLine(models.AbstractModel): " created.", domain="[('parent_id', '=', False)]", ) + timing = fields.Selection( + selection=[ + ("before", "Before"), + ("after", "After"), + ("plan_ahead", "Plan Ahead"), + ], + default="after", + help="* Before: An executable inspection is generated before the record " + "related to the trigger is completed (e.g. when picking is confirmed).\n" + "* After: An executable inspection is generated when the record related to the " + "trigger is completed (e.g. when picking is done).\n" + "* Plan Ahead: A non-executable inspection is generated before the record " + "related to the trigger is completed (e.g. when picking is confirmed), and the " + "inspection becomes executable when the record related to the trigger is " + "completed (e.g. when picking is done).", + ) - def get_trigger_line_for_product(self, trigger, product, partner=False): + def get_trigger_line_for_product(self, trigger, timings, product, partner=False): """Overridable method for getting trigger_line associated to a product. Each inherited model will complete this module to make the search by product, template or category. diff --git a/quality_control_oca/models/qc_trigger_product_category_line.py b/quality_control_oca/models/qc_trigger_product_category_line.py index 8a814afac5c..cfc7edf11c0 100644 --- a/quality_control_oca/models/qc_trigger_product_category_line.py +++ b/quality_control_oca/models/qc_trigger_product_category_line.py @@ -15,14 +15,15 @@ class QcTriggerProductCategoryLine(models.Model): product_category = fields.Many2one(comodel_name="product.category") - def get_trigger_line_for_product(self, trigger, product, partner=False): + def get_trigger_line_for_product(self, trigger, timings, product, partner=False): trigger_lines = super().get_trigger_line_for_product( - trigger, product, partner=partner + trigger, timings, product, partner=partner ) category = product.categ_id while category: for trigger_line in category.qc_triggers.filtered( lambda r: r.trigger == trigger + and r.timing in timings and ( not r.partners or not partner diff --git a/quality_control_oca/models/qc_trigger_product_line.py b/quality_control_oca/models/qc_trigger_product_line.py index 85040185881..39357020206 100644 --- a/quality_control_oca/models/qc_trigger_product_line.py +++ b/quality_control_oca/models/qc_trigger_product_line.py @@ -15,12 +15,13 @@ class QcTriggerProductLine(models.Model): 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, timings, product, partner=False): trigger_lines = super().get_trigger_line_for_product( - trigger, product, partner=partner + trigger, timings, product, partner=partner ) for trigger_line in product.qc_triggers.filtered( lambda r: r.trigger == trigger + and r.timing in timings and ( not r.partners or not partner diff --git a/quality_control_oca/models/qc_trigger_product_template_line.py b/quality_control_oca/models/qc_trigger_product_template_line.py index a5b48cf1b77..7fa739eb91c 100644 --- a/quality_control_oca/models/qc_trigger_product_template_line.py +++ b/quality_control_oca/models/qc_trigger_product_template_line.py @@ -15,12 +15,13 @@ class QcTriggerProductTemplateLine(models.Model): product_template = fields.Many2one(comodel_name="product.template") - def get_trigger_line_for_product(self, trigger, product, partner=False): + def get_trigger_line_for_product(self, trigger, timings, product, partner=False): trigger_lines = super().get_trigger_line_for_product( - trigger, product, partner=partner + trigger, timings, product, partner=partner ) for trigger_line in product.product_tmpl_id.qc_triggers.filtered( lambda r: r.trigger == trigger + and r.timing in timings and ( not r.partners or not partner diff --git a/quality_control_oca/tests/test_quality_control.py b/quality_control_oca/tests/test_quality_control.py index 9dd08200b56..c8fb8c1a967 100644 --- a/quality_control_oca/tests/test_quality_control.py +++ b/quality_control_oca/tests/test_quality_control.py @@ -67,6 +67,10 @@ def test_inspection_correct(self): self.assertEqual(self.inspection1.state, "success") self.inspection1.action_approve() self.assertEqual(self.inspection1.state, "success") + self.assertTrue(bool(self.inspection1.date_done)) + self.inspection1.action_cancel() + self.inspection1.action_draft() + self.assertFalse(self.inspection1.date_done) def test_inspection_incorrect(self): for line in self.inspection1.inspection_lines: @@ -86,6 +90,7 @@ def test_inspection_incorrect(self): self.assertEqual(self.inspection1.state, "waiting") self.inspection1.action_approve() self.assertEqual(self.inspection1.state, "failed") + self.assertTrue(bool(self.inspection1.date_done)) def test_actions_errors(self): inspection2 = self.inspection1.copy() @@ -166,7 +171,7 @@ def test_get_qc_trigger_product(self): ]: trigger_lines = trigger_lines.union( self.env[model].get_trigger_line_for_product( - self.qc_trigger, self.product + self.qc_trigger, ["after"], self.product ) ) self.assertEqual(len(trigger_lines), 3) diff --git a/quality_control_oca/views/product_template_view.xml b/quality_control_oca/views/product_template_view.xml index e64886ffbfb..16516d5702a 100644 --- a/quality_control_oca/views/product_template_view.xml +++ b/quality_control_oca/views/product_template_view.xml @@ -23,6 +23,7 @@ + diff --git a/quality_control_oca/views/qc_inspection_view.xml b/quality_control_oca/views/qc_inspection_view.xml index b02e6cfa3fc..b9f21804e38 100644 --- a/quality_control_oca/views/qc_inspection_view.xml +++ b/quality_control_oca/views/qc_inspection_view.xml @@ -79,6 +79,7 @@ + @@ -142,8 +143,18 @@ + + - + @@ -171,6 +182,9 @@ domain="[('success', '=', False)]" /> + + + + + diff --git a/quality_control_stock_oca/README.rst b/quality_control_stock_oca/README.rst index 8da328bf303..729f1133d49 100644 --- a/quality_control_stock_oca/README.rst +++ b/quality_control_stock_oca/README.rst @@ -37,6 +37,18 @@ It also adds some shortcuts on picking and lots to these inspections. .. contents:: :local: +Configuration +============= + +Configure a QC trigger line in the product, product template, or product category to create the inspection. + +There are three timing options, which you can set according to your requirements: + +* Timing: Select 'Before', 'After', or 'Plan Ahead' as necessary. + * Before: An inspection is generated for each related move when a picking with the trigger is confirmed. + * After: An inspection is generated for each related move when a picking with the trigger is completed. + * Plan Ahead: A 'Plan' inspection is generated for each related move when a picking with the trigger is confirmed. A plan inspection is just a plan and cannot be updated except for the date. It gets converted into an executable inspection once the picking is done. + Known issues / Roadmap ====================== @@ -76,6 +88,11 @@ Contributors * Pedro M. Baeza * Carlos Roca +* `Quartile `_: + + * Aung Ko Ko Lin + * Yoshi Tashiro + Maintainers ~~~~~~~~~~~ diff --git a/quality_control_stock_oca/models/__init__.py b/quality_control_stock_oca/models/__init__.py index 634e9396bfb..41ad15aba3c 100644 --- a/quality_control_stock_oca/models/__init__.py +++ b/quality_control_stock_oca/models/__init__.py @@ -2,6 +2,7 @@ from . import qc_trigger from . import qc_inspection +from . import stock_move from . import stock_picking_type from . import stock_picking from . import stock_production_lot diff --git a/quality_control_stock_oca/models/qc_inspection.py b/quality_control_stock_oca/models/qc_inspection.py index 3a6eeb4f1b2..59e325bca67 100644 --- a/quality_control_stock_oca/models/qc_inspection.py +++ b/quality_control_stock_oca/models/qc_inspection.py @@ -72,6 +72,11 @@ def _prepare_inspection_header(self, object_ref, trigger_line): # Fill qty when coming from pack operations if object_ref and object_ref._name == "stock.move": res["qty"] = object_ref.product_uom_qty + if object_ref.picking_id.immediate_transfer and trigger_line.timing in [ + "before", + "plan_ahead", + ]: + res["qty"] = object_ref.quantity_done return res diff --git a/quality_control_stock_oca/models/stock_move.py b/quality_control_stock_oca/models/stock_move.py new file mode 100644 index 00000000000..5cbfcb54b83 --- /dev/null +++ b/quality_control_stock_oca/models/stock_move.py @@ -0,0 +1,68 @@ +# Copyright 2014 Serv. Tec. Avanzados - Pedro M. Baeza +# Copyright 2018 Simone Rubino - Agile Business Group +# Copyright 2019 Andrii Skrypka +# Copyright 2024 Quartile +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from functools import lru_cache + +from odoo import models + +from odoo.addons.quality_control_oca.models.qc_trigger_line import _filter_trigger_lines + + +class StockMove(models.Model): + _inherit = "stock.move" + + def write(self, vals): + if "date" in vals: + existing_inspections = self.env["qc.inspection"]._get_existing_inspections( + self + ) + existing_inspections.write({"date": vals.get("date")}) + return super().write(vals) + + def _get_partner_for_trigger_line(self): + return self.picking_id.partner_id + + def trigger_inspection(self, timings, partner=False): + @lru_cache() + def get_qc_trigger(picking_type): + return ( + self.env["qc.trigger"] + .sudo() + .search([("picking_type_id", "=", picking_type.id)]) + ) + + self.ensure_one() + inspection_model = self.env["qc.inspection"].sudo() + qc_trigger = get_qc_trigger(self.picking_type_id) + if qc_trigger.partner_selectable: + partner = partner or self._get_partner_for_trigger_line() + else: + partner = False + trigger_lines = set() + for model in [ + "qc.trigger.product_category_line", + "qc.trigger.product_template_line", + "qc.trigger.product_line", + ]: + trigger_lines = trigger_lines.union( + self.env[model] + .sudo() + .get_trigger_line_for_product( + qc_trigger, timings, self.product_id.sudo(), partner=partner + ) + ) + for trigger_line in _filter_trigger_lines(trigger_lines): + date = False + if trigger_line.timing in ["before", "plan_ahead"]: + # To pass scheduled date to the generated inspection + date = self.date + inspection_model._make_inspection(self, trigger_line, date=date) + + def _action_confirm(self, merge=True, merge_into=False): + moves = super()._action_confirm(merge=merge, merge_into=merge_into) + for move in moves: + move.trigger_inspection(["before", "plan_ahead"]) + return moves diff --git a/quality_control_stock_oca/models/stock_picking.py b/quality_control_stock_oca/models/stock_picking.py index e99a0d8d63e..8476ea33432 100644 --- a/quality_control_stock_oca/models/stock_picking.py +++ b/quality_control_stock_oca/models/stock_picking.py @@ -1,12 +1,11 @@ # Copyright 2014 Serv. Tec. Avanzados - Pedro M. Baeza # Copyright 2018 Simone Rubino - Agile Business Group # Copyright 2019 Andrii Skrypka +# Copyright 2024 Quartile # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from odoo import api, fields, models -from odoo.addons.quality_control_oca.models.qc_trigger_line import _filter_trigger_lines - class StockPicking(models.Model): _inherit = "stock.picking" @@ -56,29 +55,37 @@ def _compute_count_inspections(self): picking.passed_inspections + picking.failed_inspections ) + def trigger_inspections(self, timings): + """Triggers the creation of or an update on inspections for attached stock moves + + :param: timings: list of timings among 'before', 'after' and 'plan_ahead' + """ + self.ensure_one() + moves_with_inspections = self.env["stock.move"] + existing_inspections = self.env["qc.inspection"]._get_existing_inspections( + self.move_ids + ) + for inspection in existing_inspections: + inspection.onchange_object_id() + moves_with_inspections += inspection.object_id + for operation in self.move_ids - moves_with_inspections: + operation.trigger_inspection(timings, self.partner_id) + + def action_cancel(self): + res = super().action_cancel() + self.qc_inspections_ids.filtered(lambda x: x.state == "plan").action_cancel() + return res + def _action_done(self): res = super()._action_done() - inspection_model = self.env["qc.inspection"].sudo() - qc_trigger = ( - self.env["qc.trigger"] - .sudo() - .search([("picking_type_id", "=", self.picking_type_id.id)]) - ) - for operation in self.move_ids: - trigger_lines = set() - for model in [ - "qc.trigger.product_category_line", - "qc.trigger.product_template_line", - "qc.trigger.product_line", - ]: - partner = self.partner_id if qc_trigger.partner_selectable else False - trigger_lines = trigger_lines.union( - self.env[model] - .sudo() - .get_trigger_line_for_product( - qc_trigger, operation.product_id.sudo(), partner=partner - ) - ) - for trigger_line in _filter_trigger_lines(trigger_lines): - inspection_model._make_inspection(operation, trigger_line) + plan_inspections = self.qc_inspections_ids.filtered(lambda x: x.state == "plan") + plan_inspections.write({"state": "ready", "date": fields.Datetime.now()}) + for picking in self: + picking.trigger_inspections(["after"]) + return res + + def _create_backorder(self): + res = super()._create_backorder() + # To re-allocate backorder moves to the new backorder picking + self.qc_inspections_ids._compute_picking() return res diff --git a/quality_control_stock_oca/readme/CONFIGURE.rst b/quality_control_stock_oca/readme/CONFIGURE.rst new file mode 100644 index 00000000000..b4fc5ab2ae1 --- /dev/null +++ b/quality_control_stock_oca/readme/CONFIGURE.rst @@ -0,0 +1,8 @@ +Configure a QC trigger line in the product, product template, or product category to create the inspection. + +There are three timing options, which you can set according to your requirements: + +* Timing: Select 'Before', 'After', or 'Plan Ahead' as necessary. + * Before: An inspection is generated for each related move when a picking with the trigger is confirmed. + * After: An inspection is generated for each related move when a picking with the trigger is completed. + * Plan Ahead: A 'Plan' inspection is generated for each related move when a picking with the trigger is confirmed. A plan inspection is just a plan and cannot be updated except for the date. It gets converted into an executable inspection once the picking is done. diff --git a/quality_control_stock_oca/readme/CONTRIBUTORS.rst b/quality_control_stock_oca/readme/CONTRIBUTORS.rst index 42989acc3da..1670310d2c3 100644 --- a/quality_control_stock_oca/readme/CONTRIBUTORS.rst +++ b/quality_control_stock_oca/readme/CONTRIBUTORS.rst @@ -7,3 +7,8 @@ * Pedro M. Baeza * Carlos Roca + +* `Quartile `_: + + * Aung Ko Ko Lin + * Yoshi Tashiro diff --git a/quality_control_stock_oca/static/description/index.html b/quality_control_stock_oca/static/description/index.html index 6291209f81a..bcdd93cc8bd 100644 --- a/quality_control_stock_oca/static/description/index.html +++ b/quality_control_stock_oca/static/description/index.html @@ -1,4 +1,3 @@ - @@ -375,24 +374,36 @@

Quality control - Stock (OCA)

Table of contents

+
+

Configuration

+

Configure a QC trigger line in the product, product template, or product category to create the inspection.

+

There are three timing options, which you can set according to your requirements:

+
    +
  • Timing: Select ‘Before’, ‘After’, or ‘Plan Ahead’ as necessary. +* Before: An inspection is generated for each related move when a picking with the trigger is confirmed. +* After: An inspection is generated for each related move when a picking with the trigger is completed. +* Plan Ahead: A ‘Plan’ inspection is generated for each related move when a picking with the trigger is confirmed. A plan inspection is just a plan and cannot be updated except for the date. It gets converted into an executable inspection once the picking is done.
  • +
+
-

Known issues / Roadmap

+

Known issues / Roadmap

  • Put trigger in all languages.
-

Bug Tracker

+

Bug Tracker

Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed @@ -400,9 +411,9 @@

Bug Tracker

Do not contact contributors directly about support or help with technical issues.

-

Credits

+

Credits

-

Authors

+

Authors

  • OdooMRP team
  • AvanzOSC
  • @@ -411,7 +422,7 @@

    Authors

-

Contributors

+

Contributors

+
  • Quartile:
      +
    • Aung Ko Ko Lin
    • +
    • Yoshi Tashiro
    • +
    +
  • -

    Maintainers

    +

    Maintainers

    This module is maintained by the OCA.

    Odoo Community Association

    OCA, or the Odoo Community Association, is a nonprofit organization whose diff --git a/quality_control_stock_oca/tests/test_quality_control_stock.py b/quality_control_stock_oca/tests/test_quality_control_stock.py index f790f546fa3..66a572fb53c 100644 --- a/quality_control_stock_oca/tests/test_quality_control_stock.py +++ b/quality_control_stock_oca/tests/test_quality_control_stock.py @@ -1,6 +1,7 @@ # Copyright 2015 Oihane Crucelaegui - AvanzOSC # Copyright 2018 Simone Rubino - Agile Business Group # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + from odoo.tests import Form, new_test_user from odoo.tools import mute_logger @@ -57,15 +58,25 @@ def setUpClass(cls): move_form.product_id = cls.product move_form.product_uom_qty = 2 cls.picking1 = picking_form.save() - cls.picking1.action_confirm() - cls.picking1.move_ids.move_line_ids.qty_done = 1 + + def picking_confirmation(self): + self.picking1.action_confirm() + self.picking1.move_ids.move_line_ids.qty_done = 1 @mute_logger("odoo.models.unlink") def test_inspection_create_for_product(self): + self.picking_confirmation() self.product.qc_triggers = [ - (0, 0, {"trigger": self.trigger.id, "test": self.test.id}) + ( + 0, + 0, + {"trigger": self.trigger.id, "test": self.test.id, "timing": "after"}, + ) ] self.picking1._action_done() + # Just so _compute_count_inspections() is triggered + # pylint: disable=W0104 + self.picking1.qc_inspections_ids self.assertEqual( self.picking1.created_inspections, 1, "Only one inspection must be created" ) @@ -79,12 +90,71 @@ def test_inspection_create_for_product(self): inspection.onchange_object_id() self.assertEqual(inspection.qty, self.picking1.move_ids.product_uom_qty) + @mute_logger("odoo.models.unlink") + def test_inspection_create_for_product_with_before_timing(self): + self.product.qc_triggers = [ + ( + 0, + 0, + {"trigger": self.trigger.id, "test": self.test.id, "timing": "before"}, + ) + ] + self.picking_confirmation() + # Just so _compute_count_inspections() is triggered + # pylint: disable=W0104 + self.picking1.qc_inspections_ids + self.assertEqual( + self.picking1.created_inspections, 1, "Only one inspection must be created" + ) + inspection = self.picking1.qc_inspections_ids[:1] + self.assertEqual(inspection.state, "ready") + self.assertEqual(inspection.qty, self.picking1.move_ids.product_uom_qty) + self.assertEqual( + inspection.test, self.test, "Wrong test picked when creating inspection." + ) + + @mute_logger("odoo.models.unlink") + def test_inspection_create_for_product_with_plan_ahead_timing(self): + self.product.qc_triggers = [ + ( + 0, + 0, + { + "trigger": self.trigger.id, + "test": self.test.id, + "timing": "plan_ahead", + }, + ) + ] + self.picking_confirmation() + # Just so _compute_count_inspections() is triggered + # pylint: disable=W0104 + self.picking1.qc_inspections_ids + self.assertEqual( + self.picking1.created_inspections, 1, "Only one inspection must be created" + ) + inspection = self.picking1.qc_inspections_ids[:1] + self.assertEqual(inspection.state, "plan") + self.assertEqual(inspection.qty, self.picking1.move_ids.product_uom_qty) + self.assertEqual( + inspection.test, self.test, "Wrong test picked when creating inspection." + ) + self.picking1._action_done() + self.assertEqual(inspection.state, "ready") + @mute_logger("odoo.models.unlink") def test_inspection_create_for_template(self): + self.picking_confirmation() self.product.product_tmpl_id.qc_triggers = [ - (0, 0, {"trigger": self.trigger.id, "test": self.test.id}) + ( + 0, + 0, + {"trigger": self.trigger.id, "test": self.test.id, "timing": "after"}, + ) ] self.picking1._action_done() + # pylint: disable=W0104 + self.picking1.qc_inspections_ids self.assertEqual( self.picking1.created_inspections, 1, "Only one inspection must be created" ) @@ -96,10 +166,17 @@ def test_inspection_create_for_template(self): @mute_logger("odoo.models.unlink") def test_inspection_create_for_category(self): + self.picking_confirmation() self.product.categ_id.qc_triggers = [ - (0, 0, {"trigger": self.trigger.id, "test": self.test.id}) + ( + 0, + 0, + {"trigger": self.trigger.id, "test": self.test.id, "timing": "after"}, + ) ] self.picking1._action_done() + # pylint: disable=W0104 + self.picking1.qc_inspections_ids self.assertEqual( self.picking1.created_inspections, 1, "Only one inspection must be created" ) @@ -111,6 +188,7 @@ def test_inspection_create_for_category(self): @mute_logger("odoo.models.unlink") def test_inspection_create_for_product_partner(self): + self.picking_confirmation() self.product.qc_triggers = [ ( 0, @@ -123,6 +201,8 @@ def test_inspection_create_for_product_partner(self): ) ] self.picking1._action_done() + # pylint: disable=W0104 + self.picking1.qc_inspections_ids self.assertEqual( self.picking1.created_inspections, 1, "Only one inspection must be created" ) @@ -134,6 +214,7 @@ def test_inspection_create_for_product_partner(self): @mute_logger("odoo.models.unlink") def test_inspection_create_for_template_partner(self): + self.picking_confirmation() self.product.product_tmpl_id.qc_triggers = [ ( 0, @@ -146,6 +227,8 @@ def test_inspection_create_for_template_partner(self): ) ] self.picking1._action_done() + # pylint: disable=W0104 + self.picking1.qc_inspections_ids self.assertEqual( self.picking1.created_inspections, 1, "Only one inspection must be created" ) @@ -157,6 +240,7 @@ def test_inspection_create_for_template_partner(self): @mute_logger("odoo.models.unlink") def test_inspection_create_for_category_partner(self): + self.picking_confirmation() self.product.categ_id.qc_triggers = [ ( 0, @@ -169,6 +253,8 @@ def test_inspection_create_for_category_partner(self): ) ] self.picking1._action_done() + # pylint: disable=W0104 + self.picking1.qc_inspections_ids self.assertEqual( self.picking1.created_inspections, 1, "Only one inspection must be created" ) @@ -180,6 +266,7 @@ def test_inspection_create_for_category_partner(self): @mute_logger("odoo.models.unlink") def test_inspection_create_for_product_wrong_partner(self): + self.picking_confirmation() self.product.qc_triggers = [ ( 0, @@ -192,12 +279,15 @@ def test_inspection_create_for_product_wrong_partner(self): ) ] self.picking1._action_done() + # pylint: disable=W0104 + self.picking1.qc_inspections_ids self.assertEqual( self.picking1.created_inspections, 0, "No inspection must be created" ) @mute_logger("odoo.models.unlink") def test_inspection_create_for_template_wrong_partner(self): + self.picking_confirmation() self.product.product_tmpl_id.qc_triggers = [ ( 0, @@ -210,12 +300,15 @@ def test_inspection_create_for_template_wrong_partner(self): ) ] self.picking1._action_done() + # pylint: disable=W0104 + self.picking1.qc_inspections_ids self.assertEqual( self.picking1.created_inspections, 0, "No inspection must be created" ) @mute_logger("odoo.models.unlink") def test_inspection_create_for_category_wrong_partner(self): + self.picking_confirmation() self.product.categ_id.qc_triggers = [ ( 0, @@ -228,12 +321,15 @@ def test_inspection_create_for_category_wrong_partner(self): ) ] self.picking1._action_done() + # pylint: disable=W0104 + self.picking1.qc_inspections_ids self.assertEqual( self.picking1.created_inspections, 0, "No inspection must be created" ) @mute_logger("odoo.models.unlink") def test_inspection_create_only_one(self): + self.picking_confirmation() self.product.qc_triggers = [ (0, 0, {"trigger": self.trigger.id, "test": self.test.id}) ] @@ -241,6 +337,8 @@ def test_inspection_create_only_one(self): (0, 0, {"trigger": self.trigger.id, "test": self.test.id}) ] self.picking1._action_done() + # pylint: disable=W0104 + self.picking1.qc_inspections_ids self.assertEqual( self.picking1.created_inspections, 1, "Only one inspection must be created" ) @@ -293,6 +391,7 @@ def test_qc_inspection_picking(self): self.assertEqual(self.inspection1.picking_id, self.picking1) def test_qc_inspection_stock_move(self): + self.picking_confirmation() self.inspection1.write( { "name": self.picking1.move_ids[:1]._name + "inspection",