From 7e843212bb8d9d93c057dfa4efcf7815dcd04c8e Mon Sep 17 00:00:00 2001 From: "Pedro M. Baeza" Date: Wed, 10 Dec 2014 23:35:21 +0100 Subject: [PATCH 01/18] [IMP] Total refactorization of quality control modules with new API, README files, and new concepts. WIP of quality_control_tolerance Merge branch '8.0' of github.com:odoomrp/odoomrp-wip into 8.0 [FIX] quality_control_stock: * File missing * Triggers for product category --- quality_control_stock/README.rst | 10 ++ quality_control_stock/__init__.py | 16 +++ quality_control_stock/__openerp__.py | 45 ++++++++ .../data/quality_control_stock_data.xml | 21 ++++ quality_control_stock/i18n/es.po | 94 +++++++++++++++++ .../i18n/quality_control_stock.pot | 99 ++++++++++++++++++ quality_control_stock/models/__init__.py | 10 ++ quality_control_stock/models/qc_inspection.py | 68 ++++++++++++ quality_control_stock/models/qc_trigger.py | 12 +++ quality_control_stock/models/stock_picking.py | 49 +++++++++ .../models/stock_picking_type.py | 41 ++++++++ .../models/stock_production_lot.py | 32 ++++++ .../static/description/icon.png | Bin 0 -> 10971 bytes .../views/qc_inspection_view.xml | 79 ++++++++++++++ .../views/stock_picking_view.xml | 70 +++++++++++++ .../views/stock_production_lot_view.xml | 72 +++++++++++++ 16 files changed, 718 insertions(+) create mode 100644 quality_control_stock/README.rst create mode 100644 quality_control_stock/__init__.py create mode 100644 quality_control_stock/__openerp__.py create mode 100644 quality_control_stock/data/quality_control_stock_data.xml create mode 100644 quality_control_stock/i18n/es.po create mode 100644 quality_control_stock/i18n/quality_control_stock.pot create mode 100644 quality_control_stock/models/__init__.py create mode 100644 quality_control_stock/models/qc_inspection.py create mode 100644 quality_control_stock/models/qc_trigger.py create mode 100644 quality_control_stock/models/stock_picking.py create mode 100644 quality_control_stock/models/stock_picking_type.py create mode 100644 quality_control_stock/models/stock_production_lot.py create mode 100644 quality_control_stock/static/description/icon.png create mode 100644 quality_control_stock/views/qc_inspection_view.xml create mode 100644 quality_control_stock/views/stock_picking_view.xml create mode 100644 quality_control_stock/views/stock_production_lot_view.xml diff --git a/quality_control_stock/README.rst b/quality_control_stock/README.rst new file mode 100644 index 000000000..937772c0e --- /dev/null +++ b/quality_control_stock/README.rst @@ -0,0 +1,10 @@ +Stock extension for quality control +=================================== + +This module defines triggers that creates inspections when stock moves are done. + +It also adds some shortcuts on picking and lots to these inspections. + +Contributors +------------ +* Pedro M. Baeza diff --git a/quality_control_stock/__init__.py b/quality_control_stock/__init__.py new file mode 100644 index 000000000..86bcf7d2e --- /dev/null +++ b/quality_control_stock/__init__.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +############################################################################## +# For copyright and license notices, see __openerp__.py file in root directory +############################################################################## + +from . import models +from openerp import SUPERUSER_ID + + +def post_init_hook(cr, registry): + # Create QC triggers + picking_type_ids = registry['stock.picking.type'].search( + cr, SUPERUSER_ID, []) + for picking_type_id in picking_type_ids: + registry['stock.picking.type']._create_qc_trigger( + cr, SUPERUSER_ID, picking_type_id) diff --git a/quality_control_stock/__openerp__.py b/quality_control_stock/__openerp__.py new file mode 100644 index 000000000..d0b38c80a --- /dev/null +++ b/quality_control_stock/__openerp__.py @@ -0,0 +1,45 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Copyright (c) +# 2014 Serv. Tec. Avanzados - Pedro M. Baeza (http://www.serviciosbaeza.com) +# 2014 AvanzOsc (http://www.avanzosc.es) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +{ + "name": "Quality control - Stock", + "version": "1.0", + "author": "OdooMRP team", + "website": "http://www.odoomrp.com", + "contributors": [ + "Pedro M. Baeza + + + + + Stock Move + stock.move + + + + Picking List + stock.picking + + + + Lot + stock.production.lot + + + + diff --git a/quality_control_stock/i18n/es.po b/quality_control_stock/i18n/es.po new file mode 100644 index 000000000..203f5f67d --- /dev/null +++ b/quality_control_stock/i18n/es.po @@ -0,0 +1,94 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * quality_control_stock +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-12-10 19:26+0000\n" +"PO-Revision-Date: 2014-12-10 19:26+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: quality_control_stock +#: help:stock.production.lot,qc_inspections:0 +msgid "Inspections related to this lot." +msgstr "Inspecciones relativas a este lote." + +#. module: quality_control_stock +#: help:stock.picking,qc_inspections:0 +msgid "Inspections related to this picking." +msgstr "Inspecciones relativas a este albarán." + +#. module: quality_control_stock +#: view:qc.inspection:quality_control_stock.qc_inspection_search_view_picking +#: field:qc.inspection,lot:0 +#: view:qc.inspection.line:quality_control_stock.qc_inspection_line_search_stock_view +#: field:qc.inspection.line,lot:0 +msgid "Lot" +msgstr "Lote" + +#. module: quality_control_stock +#: view:qc.inspection:quality_control_stock.qc_inspection_search_view_picking +#: field:qc.inspection,picking:0 +#: view:qc.inspection.line:quality_control_stock.qc_inspection_line_search_stock_view +#: field:qc.inspection.line,picking:0 +msgid "Picking" +msgstr "Albarán" + +#. module: quality_control_stock +#: field:qc.trigger,picking_type:0 +msgid "Picking type" +msgstr "Tipo de albarán" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_lot_done +msgid "Quality inspection from lot done" +msgstr "Inspecciones desde lote realizadas" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_lot_passed +msgid "Quality inspection from lot passed" +msgstr "Inspecciones desde lote pasadas" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_picking_done +msgid "Quality inspection from picking done" +msgstr "Inspecciones desde albarán realizadas" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_picking_passed +msgid "Quality inspection from picking passed" +msgstr "Inspecciones desde albarán realizadas" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_lot +msgid "Quality inspections from lot" +msgstr "Inspecciones desde lote" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_lot_failed +msgid "Quality inspections from lot failed" +msgstr "Inspecciones desde lote fallidas" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_picking +msgid "Quality inspections from picking" +msgstr "Inspecciones desde albarán" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_picking_failed +msgid "Quality inspections from picking failed" +msgstr "Inspecciones desde albarán falladas" + +#. module: quality_control_stock +#: view:stock.picking:quality_control_stock.stock_picking_qc_view +#: view:stock.production.lot:quality_control_stock.stock_lot_qc_view +msgid "inspections" +msgstr "inspecciones" + diff --git a/quality_control_stock/i18n/quality_control_stock.pot b/quality_control_stock/i18n/quality_control_stock.pot new file mode 100644 index 000000000..2f4ec2a15 --- /dev/null +++ b/quality_control_stock/i18n/quality_control_stock.pot @@ -0,0 +1,99 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * quality_control_stock +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-12-10 19:26+0000\n" +"PO-Revision-Date: 2014-12-10 19:26+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: quality_control_stock +#: help:stock.production.lot,qc_inspections:0 +msgid "Inspections related to this lot." +msgstr "" + +#. module: quality_control_stock +#: help:stock.picking,qc_inspections:0 +msgid "Inspections related to this picking." +msgstr "" + +#. module: quality_control_stock +#: view:qc.inspection:quality_control_stock.qc_inspection_search_view_putvalid +#: field:qc.inspection,lot:0 +#: view:qc.inspection.line:quality_control_stock.qc_inspection_line_search_stock_view +#: field:qc.inspection.line,lot:0 +msgid "Lot" +msgstr "" + +#. module: quality_control_stock +#: model:ir.model,name:quality_control_stock.model_stock_production_lot +msgid "Lot/Serial" +msgstr "" + +#. module: quality_control_stock +#: view:qc.inspection:quality_control_stock.qc_inspection_search_view_putvalid +#: field:qc.inspection,picking:0 +#: view:qc.inspection.line:quality_control_stock.qc_inspection_line_search_stock_view +#: field:qc.inspection.line,picking:0 +msgid "Picking" +msgstr "" + +#. module: quality_control_stock +#: field:qc.trigger,picking_type:0 +msgid "Picking type" +msgstr "" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_lot_done +msgid "Quality inspection from lot done" +msgstr "" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_lot_passed +msgid "Quality inspection from lot passed" +msgstr "" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_picking_done +msgid "Quality inspection from picking done" +msgstr "" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_picking_passed +msgid "Quality inspection from picking passed" +msgstr "" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_lot +msgid "Quality inspections from lot" +msgstr "" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_lot_failed +msgid "Quality inspections from lot failed" +msgstr "" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_picking +msgid "Quality inspections from picking" +msgstr "" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_picking_failed +msgid "Quality inspections from picking failed" +msgstr "" + +#. module: quality_control_stock +#: view:stock.picking:quality_control_stock.stock_picking_qc_view +#: view:stock.production.lot:quality_control_stock.stock_lot_qc_view +msgid "inspections" +msgstr "" + diff --git a/quality_control_stock/models/__init__.py b/quality_control_stock/models/__init__.py new file mode 100644 index 000000000..bf7cb46e4 --- /dev/null +++ b/quality_control_stock/models/__init__.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +############################################################################## +# For copyright and license notices, see __openerp__.py file in root directory +############################################################################## + +from . import qc_trigger +from . import qc_inspection +from . import stock_picking_type +from . import stock_picking +from . import stock_production_lot diff --git a/quality_control_stock/models/qc_inspection.py b/quality_control_stock/models/qc_inspection.py new file mode 100644 index 000000000..22b79396d --- /dev/null +++ b/quality_control_stock/models/qc_inspection.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +############################################################################## +# For copyright and license notices, see __openerp__.py file in root directory +############################################################################## +from openerp import models, fields, api + + +class QcInspection(models.Model): + _inherit = 'qc.inspection' + + @api.one + @api.depends('object_id') + def get_picking(self): + self.picking = False + if self.object_id: + if self.object_id._name == 'stock.move': + self.picking = self.object_id.picking_id + elif self.object_id._name == 'stock.picking': + self.picking = self.object_id + elif self.object_id._name == 'stock.pack.operation': + self.picking = self.object_id.picking_id + + @api.one + @api.depends('object_id') + def get_lot(self): + self.lot = False + if self.object_id: + if self.object_id._name == 'stock.pack.operation': + self.lot = self.object_id.lot_id + elif self.object_id._name == 'stock.move': + self.lot = self.object_id.lots_id[0] + + @api.one + @api.depends('object_id') + def _get_product(self): + """Overriden for getting the product from a stock move.""" + super(QcInspection, self)._get_product() + if self.object_id: + if self.object_id._name == 'stock.move': + self.product = self.object_id.product_id + elif self.object_id._name == 'stock.pack.operation': + self.product = self.object_id.product_id + + @api.one + @api.depends('object_id') + def _get_qty(self): + super(QcInspection, self)._get_qty() + if self.object_id: + if self.object_id._name == 'stock.move': + self.qty = self.object_id.product_qty + elif self.object_id._name == 'stock.pack.operation': + self.qty = self.object_id.product_qty + + picking = fields.Many2one( + comodel_name="stock.picking", compute="get_picking", store=True) + lot = fields.Many2one( + comodel_name='stock.production.lot', compute="get_lot", store=True) + + +class QcInspectionLine(models.Model): + _inherit = 'qc.inspection.line' + + picking = fields.Many2one( + comodel_name="stock.picking", related="inspection_id.picking", + store=True) + lot = fields.Many2one( + comodel_name="stock.production.lot", related="inspection_id.lot", + store=True) diff --git a/quality_control_stock/models/qc_trigger.py b/quality_control_stock/models/qc_trigger.py new file mode 100644 index 000000000..e53003749 --- /dev/null +++ b/quality_control_stock/models/qc_trigger.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +############################################################################## +# For copyright and license notices, see __openerp__.py file in root directory +############################################################################## +from openerp import models, fields + + +class QcTrigger(models.Model): + _inherit = 'qc.trigger' + + picking_type = fields.Many2one( + comodel_name="stock.picking.type", readonly=True) diff --git a/quality_control_stock/models/stock_picking.py b/quality_control_stock/models/stock_picking.py new file mode 100644 index 000000000..b3c14aca2 --- /dev/null +++ b/quality_control_stock/models/stock_picking.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +############################################################################## +# For copyright and license notices, see __openerp__.py file in root directory +############################################################################## +from openerp import models, fields, api + + +class StockPicking(models.Model): + _inherit = 'stock.picking' + + @api.one + @api.depends('qc_inspections', 'qc_inspections.state') + def _count_inspections(self): + self.created_inspections = len(self.qc_inspections) + self.passed_inspections = len([x for x in self.qc_inspections if + x.state == 'success']) + self.failed_inspections = len([x for x in self.qc_inspections if + x.state == 'failed']) + self.done_inspections = (self.passed_inspections + + self.failed_inspections) + + qc_inspections = fields.One2many( + comodel_name='qc.inspection', inverse_name='picking', copy=False, + string='Inspections', help="Inspections related to this picking.") + created_inspections = fields.Integer( + compute="_count_inspections", string="Created inspections") + done_inspections = fields.Integer( + compute="_count_inspections", string="Done inspections") + passed_inspections = fields.Integer( + compute="_count_inspections", string="Inspections OK") + failed_inspections = fields.Integer( + compute="_count_inspections", string="Inspections failed") + + @api.multi + def do_transfer(self): + res = super(StockPicking, self).do_transfer() + inspection_model = self.env['qc.inspection'] + for operation in self.pack_operation_ids: + qc_trigger = self.env['qc.trigger'].search( + [('picking_type', '=', self.picking_type_id.id)]) + tests = set() + for model in ['qc.trigger.product_category_line', + 'qc.trigger.product_template_line', + 'qc.trigger.product_line']: + tests = tests.union(self.env[model].get_test_for_product( + qc_trigger, operation.product_id)) + for test in tests: + inspection_model._make_inspection(operation, test) + return res diff --git a/quality_control_stock/models/stock_picking_type.py b/quality_control_stock/models/stock_picking_type.py new file mode 100644 index 000000000..c09cae31a --- /dev/null +++ b/quality_control_stock/models/stock_picking_type.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +############################################################################## +# For copyright and license notices, see __openerp__.py file in root directory +############################################################################## +from openerp import models, api + + +class StockPickingType(models.Model): + _inherit = 'stock.picking.type' + + @api.multi + def _create_qc_trigger(self): + qc_trigger = { + # Synchronize all translations + 'name': self.complete_name, + 'company_id': self.warehouse_id.company_id.id, + 'picking_type': self.id, + } + return self.env['qc.trigger'].sudo().create(qc_trigger) + + @api.model + def create(self, vals): + picking_type = super(StockPickingType, self).create(vals) + picking_type._create_qc_trigger() + return picking_type + + @api.multi + def write(self, vals): + res = super(StockPickingType, self).write(vals) + if vals.get('name') or vals.get('warehouse_id'): + qc_trigger_model = self.env['qc.trigger'].sudo() + qc_trigger = qc_trigger_model.search( + [('picking_type', '=', self.id)]) + qc_trigger.name = self.complete_name + return res + + @api.multi + def unlink(self): + self.env['qc.trigger'].sudo().search( + [('picking_type', '=', self.id)]).unlink() + return super(StockPickingType, self).unlink() diff --git a/quality_control_stock/models/stock_production_lot.py b/quality_control_stock/models/stock_production_lot.py new file mode 100644 index 000000000..ed67fb25f --- /dev/null +++ b/quality_control_stock/models/stock_production_lot.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +############################################################################## +# For copyright and license notices, see __openerp__.py file in root directory +############################################################################## +from openerp import models, fields, api + + +class StockProductionLot(models.Model): + _inherit = 'stock.production.lot' + + @api.one + @api.depends('qc_inspections', 'qc_inspections.state') + def _count_inspections(self): + self.created_inspections = len(self.qc_inspections) + self.passed_inspections = len([x for x in self.qc_inspections if + x.state == 'success']) + self.failed_inspections = len([x for x in self.qc_inspections if + x.state == 'failed']) + self.done_inspections = (self.passed_inspections + + self.failed_inspections) + + qc_inspections = fields.One2many( + comodel_name='qc.inspection', inverse_name='lot', copy=False, + string='Inspections', help="Inspections related to this lot.") + created_inspections = fields.Integer( + compute="_count_inspections", string="Created inspections") + done_inspections = fields.Integer( + compute="_count_inspections", string="Done inspections") + passed_inspections = fields.Integer( + compute="_count_inspections", string="Inspections OK") + failed_inspections = fields.Integer( + compute="_count_inspections", string="Inspections failed") diff --git a/quality_control_stock/static/description/icon.png b/quality_control_stock/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..26561d6c0b898ddfee4f4d67a22a89a346aa0e89 GIT binary patch literal 10971 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 xD`f? + + + + + qc.inspection.form.view.picking + qc.inspection + + + + + + + + + + + qc.inspection.tree.view.picking + qc.inspection + + + + + + + + + + + qc.inspection.search.view.picking + qc.inspection + + + + + + + + + + + qc.inspection.line.tree.stock + qc.inspection.line + + + + + + + + + + + qc.inspection.line.search.stock + qc.inspection.line + + + + + + + + + + + + + + + diff --git a/quality_control_stock/views/stock_picking_view.xml b/quality_control_stock/views/stock_picking_view.xml new file mode 100644 index 000000000..1c53c4d06 --- /dev/null +++ b/quality_control_stock/views/stock_picking_view.xml @@ -0,0 +1,70 @@ + + + + + + Quality inspections from picking + qc.inspection + tree,form + [('picking', '=', active_id)] + + + + Quality inspection from picking done + qc.inspection + tree,form + [('picking', '=', active_id), ('state', 'not in', ['draft', 'waiting'])] + + + + Quality inspection from picking passed + qc.inspection + tree,form + [('picking', '=', active_id), ('state', '=', 'success')] + + + + Quality inspections from picking failed + qc.inspection + tree,form + [('picking', '=', active_id), ('state', '=', 'failed')] + + + + stock.picking.qc.view + stock.picking + + +
+ + + + +
+
+
+ +
+
\ No newline at end of file diff --git a/quality_control_stock/views/stock_production_lot_view.xml b/quality_control_stock/views/stock_production_lot_view.xml new file mode 100644 index 000000000..6b55c5402 --- /dev/null +++ b/quality_control_stock/views/stock_production_lot_view.xml @@ -0,0 +1,72 @@ + + + + + + Quality inspections from lot + qc.inspection + tree,form + [('lot', '=', active_id)] + + + + Quality inspection from lot done + qc.inspection + tree,form + [('lot', '=', active_id), ('state', 'not in', ['draft', 'waiting'])] + + + + Quality inspection from lot passed + qc.inspection + tree,form + [('lot', '=', active_id), ('state', '=', 'success')] + + + + Quality inspections from lot failed + qc.inspection + tree,form + [('lot', '=', active_id), ('state', '=', 'failed')] + + + + stock.production.lot.qc.view + stock.production.lot + + +
+
+ + + + +
+
+
+
+ +
+
\ No newline at end of file From 5bba57b9554d7d7de4d88f363babba2196954183 Mon Sep 17 00:00:00 2001 From: oihane Date: Fri, 19 Dec 2014 11:17:08 +0100 Subject: [PATCH 02/18] [FIX] Little changes in quality modules --- quality_control_stock/models/qc_inspection.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quality_control_stock/models/qc_inspection.py b/quality_control_stock/models/qc_inspection.py index 22b79396d..38b63f977 100644 --- a/quality_control_stock/models/qc_inspection.py +++ b/quality_control_stock/models/qc_inspection.py @@ -28,7 +28,7 @@ class QcInspection(models.Model): if self.object_id._name == 'stock.pack.operation': self.lot = self.object_id.lot_id elif self.object_id._name == 'stock.move': - self.lot = self.object_id.lots_id[0] + self.lot = self.object_id.lot_ids[0] @api.one @api.depends('object_id') From dd2d98d8ea3eafc4162be1f9ef04c88b501f928c Mon Sep 17 00:00:00 2001 From: "Pedro M. Baeza" Date: Mon, 5 Jan 2015 04:44:24 +0100 Subject: [PATCH 03/18] [FIX] quality_control_stock: * Omit lot when it's not present * Change icon set --- quality_control_stock/models/qc_inspection.py | 3 ++- .../static/description/icon.png | Bin 10971 -> 9215 bytes 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/quality_control_stock/models/qc_inspection.py b/quality_control_stock/models/qc_inspection.py index 38b63f977..22a7466a3 100644 --- a/quality_control_stock/models/qc_inspection.py +++ b/quality_control_stock/models/qc_inspection.py @@ -28,7 +28,8 @@ class QcInspection(models.Model): if self.object_id._name == 'stock.pack.operation': self.lot = self.object_id.lot_id elif self.object_id._name == 'stock.move': - self.lot = self.object_id.lot_ids[0] + if self.object_id.lot_ids: + self.lot = self.object_id.lot_ids[0] @api.one @api.depends('object_id') diff --git a/quality_control_stock/static/description/icon.png b/quality_control_stock/static/description/icon.png index 26561d6c0b898ddfee4f4d67a22a89a346aa0e89..84b3a163a72c74a425d2ff8386e3da608b8d8334 100644 GIT binary patch literal 9215 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 xD`f? Date: Fri, 20 Feb 2015 13:43:32 +0100 Subject: [PATCH 04/18] [MOD] Trigger lines instead of test --- quality_control_stock/models/stock_picking.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/quality_control_stock/models/stock_picking.py b/quality_control_stock/models/stock_picking.py index b3c14aca2..55c132832 100644 --- a/quality_control_stock/models/stock_picking.py +++ b/quality_control_stock/models/stock_picking.py @@ -38,12 +38,13 @@ class StockPicking(models.Model): for operation in self.pack_operation_ids: qc_trigger = self.env['qc.trigger'].search( [('picking_type', '=', self.picking_type_id.id)]) - tests = set() + trigger_lines = set() for model in ['qc.trigger.product_category_line', 'qc.trigger.product_template_line', 'qc.trigger.product_line']: - tests = tests.union(self.env[model].get_test_for_product( - qc_trigger, operation.product_id)) - for test in tests: - inspection_model._make_inspection(operation, test) + trigger_lines = trigger_lines.union( + self.env[model].get_trigger_line_for_product( + qc_trigger, operation.product_id)) + for trigger_line in trigger_lines: + inspection_model._make_inspection(operation, trigger_line) return res From f346ce78f685cc473d4ca1a40df2abb2878fb574 Mon Sep 17 00:00:00 2001 From: "Pedro M. Baeza" Date: Wed, 25 Mar 2015 20:48:43 +0100 Subject: [PATCH 05/18] [IMP] Expand AUTHORS --- quality_control_stock/__openerp__.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/quality_control_stock/__openerp__.py b/quality_control_stock/__openerp__.py index d0b38c80a..c00356e92 100644 --- a/quality_control_stock/__openerp__.py +++ b/quality_control_stock/__openerp__.py @@ -23,7 +23,9 @@ { "name": "Quality control - Stock", "version": "1.0", - "author": "OdooMRP team", + "author": "OdooMRP team," + "AvanzOSC," + "Serv. Tecnol. Avanzados - Pedro M. Baeza", "website": "http://www.odoomrp.com", "contributors": [ "Pedro M. Baeza Date: Wed, 1 Apr 2015 18:19:08 +0200 Subject: [PATCH 06/18] [MOD] Smartbuttons all in one div --- quality_control_stock/i18n/sl.po | 100 ++++++++++++++++++ .../views/stock_production_lot_view.xml | 58 +++++----- 2 files changed, 128 insertions(+), 30 deletions(-) create mode 100644 quality_control_stock/i18n/sl.po diff --git a/quality_control_stock/i18n/sl.po b/quality_control_stock/i18n/sl.po new file mode 100644 index 000000000..7d9c384e1 --- /dev/null +++ b/quality_control_stock/i18n/sl.po @@ -0,0 +1,100 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * quality_control_stock +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-08-01 20:50+0200\n" +"PO-Revision-Date: 2015-08-01 20:53+0200\n" +"Last-Translator: Matjaz Mozetic \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n" +"X-Generator: Poedit 1.8.2\n" +"Language: sl\n" + +#. module: quality_control_stock +#: help:stock.production.lot,qc_inspections:0 +msgid "Inspections related to this lot." +msgstr "Inšpekcije vezane na ta lot." + +#. module: quality_control_stock +#: help:stock.picking,qc_inspections:0 +msgid "Inspections related to this picking." +msgstr "Inšpekcije vezane na ta zbirnik." + +#. module: quality_control_stock +#: view:qc.inspection:quality_control_stock.qc_inspection_search_view_putvalid +#: field:qc.inspection,lot:0 +#: view:qc.inspection.line:quality_control_stock.qc_inspection_line_search_stock_view +#: field:qc.inspection.line,lot:0 +msgid "Lot" +msgstr "Lot" + +#. module: quality_control_stock +#: model:ir.model,name:quality_control_stock.model_stock_production_lot +msgid "Lot/Serial" +msgstr "Lot/serijska št." + +#. module: quality_control_stock +#: view:qc.inspection:quality_control_stock.qc_inspection_search_view_putvalid +#: field:qc.inspection,picking:0 +#: view:qc.inspection.line:quality_control_stock.qc_inspection_line_search_stock_view +#: field:qc.inspection.line,picking:0 +msgid "Picking" +msgstr "Zbirnik" + +#. module: quality_control_stock +#: field:qc.trigger,picking_type:0 +msgid "Picking type" +msgstr "Tip zbirnika" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_lot_done +msgid "Quality inspection from lot done" +msgstr "Opravljene inšpekcije kakovosti na lotu" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_lot_passed +msgid "Quality inspection from lot passed" +msgstr "Izpolnjene inšpekcije kakovosti na lotu" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_picking_done +msgid "Quality inspection from picking done" +msgstr "Opravljene inšpekcije kakovosti na zbirniku" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_picking_passed +msgid "Quality inspection from picking passed" +msgstr "Izpolnjene inšpekcije kakovosti na zbirniku" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_lot +msgid "Quality inspections from lot" +msgstr "Inšpekcije kakovosti na lotu" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_lot_failed +msgid "Quality inspections from lot failed" +msgstr "Neuspešne inšpekcije kakovosti na lotu" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_picking +msgid "Quality inspections from picking" +msgstr "Inšpekcije kakovosti na zbirniku" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_picking_failed +msgid "Quality inspections from picking failed" +msgstr "Neuspešne inšpekcije kakovosti na zbirniku" + +#. module: quality_control_stock +#: view:stock.picking:quality_control_stock.stock_picking_qc_view +#: view:stock.production.lot:quality_control_stock.stock_lot_qc_view +msgid "inspections" +msgstr "inšpekcije" diff --git a/quality_control_stock/views/stock_production_lot_view.xml b/quality_control_stock/views/stock_production_lot_view.xml index 6b55c5402..c503a6633 100644 --- a/quality_control_stock/views/stock_production_lot_view.xml +++ b/quality_control_stock/views/stock_production_lot_view.xml @@ -35,38 +35,36 @@ stock.production.lot -
-
- - - - -
+
+ + + +
- \ No newline at end of file + From c0013020deee0e2f2ed2f5681c82581055427811 Mon Sep 17 00:00:00 2001 From: oihane Date: Thu, 13 Aug 2015 11:42:41 +0200 Subject: [PATCH 07/18] [IMP] and * Added "partner_selectable" field, so that inspections can by made by partner * Stock inspections are "partner_selectable" * Little view fixing, field was oe_edit_only instead of label * Added partner to creation from stock_picking * Added tests * Picking pack operations automatically created --- quality_control_stock/i18n/es.po | 68 +++++++- quality_control_stock/i18n/fr.po | 144 ++++++++++++++++ quality_control_stock/i18n/pt_BR.po | 144 ++++++++++++++++ quality_control_stock/i18n/sl.po | 69 ++++++-- quality_control_stock/models/stock_picking.py | 8 +- .../models/stock_picking_type.py | 1 + quality_control_stock/tests/__init__.py | 5 + .../tests/test_quality_control_stock.py | 159 ++++++++++++++++++ 8 files changed, 575 insertions(+), 23 deletions(-) create mode 100644 quality_control_stock/i18n/fr.po create mode 100644 quality_control_stock/i18n/pt_BR.po create mode 100644 quality_control_stock/tests/__init__.py create mode 100644 quality_control_stock/tests/test_quality_control_stock.py diff --git a/quality_control_stock/i18n/es.po b/quality_control_stock/i18n/es.po index 203f5f67d..4e20d7a75 100644 --- a/quality_control_stock/i18n/es.po +++ b/quality_control_stock/i18n/es.po @@ -1,19 +1,27 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: -# * quality_control_stock -# +# * quality_control_stock +# +# Translators: msgid "" msgstr "" -"Project-Id-Version: Odoo Server 8.0\n" +"Project-Id-Version: odoomrp-wip (8.0)\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-12-10 19:26+0000\n" -"PO-Revision-Date: 2014-12-10 19:26+0000\n" -"Last-Translator: <>\n" -"Language-Team: \n" +"POT-Creation-Date: 2015-10-07 10:44+0000\n" +"PO-Revision-Date: 2015-10-09 10:50+0000\n" +"Last-Translator: Pedro M. Baeza \n" +"Language-Team: Spanish (http://www.transifex.com/oca/odoomrp-wip-8-0/language/es/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" -"Plural-Forms: \n" +"Language: es\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: quality_control_stock +#: field:stock.picking,qc_inspections:0 +#: field:stock.production.lot,qc_inspections:0 +msgid "Inspections" +msgstr "Inspecciones" #. module: quality_control_stock #: help:stock.production.lot,qc_inspections:0 @@ -30,9 +38,15 @@ msgstr "Inspecciones relativas a este albarán." #: field:qc.inspection,lot:0 #: view:qc.inspection.line:quality_control_stock.qc_inspection_line_search_stock_view #: field:qc.inspection.line,lot:0 +#: model:res.request.link,name:quality_control_stock.req_link_stock_production_lot msgid "Lot" msgstr "Lote" +#. module: quality_control_stock +#: model:ir.model,name:quality_control_stock.model_stock_production_lot +msgid "Lot/Serial" +msgstr "Lote/Nº de serie" + #. module: quality_control_stock #: view:qc.inspection:quality_control_stock.qc_inspection_search_view_picking #: field:qc.inspection,picking:0 @@ -41,11 +55,38 @@ msgstr "Lote" msgid "Picking" msgstr "Albarán" +#. module: quality_control_stock +#: model:ir.model,name:quality_control_stock.model_stock_picking +#: model:res.request.link,name:quality_control_stock.req_link_stock_picking +msgid "Picking List" +msgstr "Albarán" + #. module: quality_control_stock #: field:qc.trigger,picking_type:0 msgid "Picking type" msgstr "Tipo de albarán" +#. module: quality_control_stock +#: view:qc.inspection:quality_control_stock.qc_inspection_search_view_picking +#: view:qc.inspection.line:quality_control_stock.qc_inspection_line_search_stock_view +msgid "Product" +msgstr "Producto" + +#. module: quality_control_stock +#: model:ir.model,name:quality_control_stock.model_qc_inspection +msgid "Quality control inspection" +msgstr "Inspección del control de calidad" + +#. module: quality_control_stock +#: model:ir.model,name:quality_control_stock.model_qc_inspection_line +msgid "Quality control inspection line" +msgstr "Línea de inspección de control de calidad" + +#. module: quality_control_stock +#: model:ir.model,name:quality_control_stock.model_qc_trigger +msgid "Quality control trigger" +msgstr "Disparador del control de calidad" + #. module: quality_control_stock #: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_lot_done msgid "Quality inspection from lot done" @@ -86,9 +127,18 @@ msgstr "Inspecciones desde albarán" msgid "Quality inspections from picking failed" msgstr "Inspecciones desde albarán falladas" +#. module: quality_control_stock +#: model:res.request.link,name:quality_control_stock.req_link_stock_move +msgid "Stock Move" +msgstr "Movimiento de stock" + +#. module: quality_control_stock +#: model:ir.model,name:quality_control_stock.model_stock_picking_type +msgid "The picking type determines the picking view" +msgstr "" + #. module: quality_control_stock #: view:stock.picking:quality_control_stock.stock_picking_qc_view #: view:stock.production.lot:quality_control_stock.stock_lot_qc_view msgid "inspections" msgstr "inspecciones" - diff --git a/quality_control_stock/i18n/fr.po b/quality_control_stock/i18n/fr.po new file mode 100644 index 000000000..b94f7cb7a --- /dev/null +++ b/quality_control_stock/i18n/fr.po @@ -0,0 +1,144 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * quality_control_stock +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: odoomrp-wip (8.0)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-07 10:44+0000\n" +"PO-Revision-Date: 2015-09-10 16:38+0000\n" +"Last-Translator: <>\n" +"Language-Team: French (http://www.transifex.com/oca/odoomrp-wip-8-0/language/fr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: fr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#. module: quality_control_stock +#: field:stock.picking,qc_inspections:0 +#: field:stock.production.lot,qc_inspections:0 +msgid "Inspections" +msgstr "" + +#. module: quality_control_stock +#: help:stock.production.lot,qc_inspections:0 +msgid "Inspections related to this lot." +msgstr "" + +#. module: quality_control_stock +#: help:stock.picking,qc_inspections:0 +msgid "Inspections related to this picking." +msgstr "" + +#. module: quality_control_stock +#: view:qc.inspection:quality_control_stock.qc_inspection_search_view_picking +#: field:qc.inspection,lot:0 +#: view:qc.inspection.line:quality_control_stock.qc_inspection_line_search_stock_view +#: field:qc.inspection.line,lot:0 +#: model:res.request.link,name:quality_control_stock.req_link_stock_production_lot +msgid "Lot" +msgstr "Lot" + +#. module: quality_control_stock +#: model:ir.model,name:quality_control_stock.model_stock_production_lot +msgid "Lot/Serial" +msgstr "Lot/n° de série" + +#. module: quality_control_stock +#: view:qc.inspection:quality_control_stock.qc_inspection_search_view_picking +#: field:qc.inspection,picking:0 +#: view:qc.inspection.line:quality_control_stock.qc_inspection_line_search_stock_view +#: field:qc.inspection.line,picking:0 +msgid "Picking" +msgstr "" + +#. module: quality_control_stock +#: model:ir.model,name:quality_control_stock.model_stock_picking +#: model:res.request.link,name:quality_control_stock.req_link_stock_picking +msgid "Picking List" +msgstr "" + +#. module: quality_control_stock +#: field:qc.trigger,picking_type:0 +msgid "Picking type" +msgstr "" + +#. module: quality_control_stock +#: view:qc.inspection:quality_control_stock.qc_inspection_search_view_picking +#: view:qc.inspection.line:quality_control_stock.qc_inspection_line_search_stock_view +msgid "Product" +msgstr "Article" + +#. module: quality_control_stock +#: model:ir.model,name:quality_control_stock.model_qc_inspection +msgid "Quality control inspection" +msgstr "" + +#. module: quality_control_stock +#: model:ir.model,name:quality_control_stock.model_qc_inspection_line +msgid "Quality control inspection line" +msgstr "" + +#. module: quality_control_stock +#: model:ir.model,name:quality_control_stock.model_qc_trigger +msgid "Quality control trigger" +msgstr "" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_lot_done +msgid "Quality inspection from lot done" +msgstr "" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_lot_passed +msgid "Quality inspection from lot passed" +msgstr "" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_picking_done +msgid "Quality inspection from picking done" +msgstr "" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_picking_passed +msgid "Quality inspection from picking passed" +msgstr "" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_lot +msgid "Quality inspections from lot" +msgstr "" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_lot_failed +msgid "Quality inspections from lot failed" +msgstr "" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_picking +msgid "Quality inspections from picking" +msgstr "" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_picking_failed +msgid "Quality inspections from picking failed" +msgstr "" + +#. module: quality_control_stock +#: model:res.request.link,name:quality_control_stock.req_link_stock_move +msgid "Stock Move" +msgstr "" + +#. module: quality_control_stock +#: model:ir.model,name:quality_control_stock.model_stock_picking_type +msgid "The picking type determines the picking view" +msgstr "" + +#. module: quality_control_stock +#: view:stock.picking:quality_control_stock.stock_picking_qc_view +#: view:stock.production.lot:quality_control_stock.stock_lot_qc_view +msgid "inspections" +msgstr "" diff --git a/quality_control_stock/i18n/pt_BR.po b/quality_control_stock/i18n/pt_BR.po new file mode 100644 index 000000000..79fc0c706 --- /dev/null +++ b/quality_control_stock/i18n/pt_BR.po @@ -0,0 +1,144 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * quality_control_stock +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: odoomrp-wip (8.0)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-07 10:44+0000\n" +"PO-Revision-Date: 2015-10-09 03:43+0000\n" +"Last-Translator: danimaribeiro \n" +"Language-Team: Portuguese (Brazil) (http://www.transifex.com/oca/odoomrp-wip-8-0/language/pt_BR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: pt_BR\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#. module: quality_control_stock +#: field:stock.picking,qc_inspections:0 +#: field:stock.production.lot,qc_inspections:0 +msgid "Inspections" +msgstr "" + +#. module: quality_control_stock +#: help:stock.production.lot,qc_inspections:0 +msgid "Inspections related to this lot." +msgstr "" + +#. module: quality_control_stock +#: help:stock.picking,qc_inspections:0 +msgid "Inspections related to this picking." +msgstr "" + +#. module: quality_control_stock +#: view:qc.inspection:quality_control_stock.qc_inspection_search_view_picking +#: field:qc.inspection,lot:0 +#: view:qc.inspection.line:quality_control_stock.qc_inspection_line_search_stock_view +#: field:qc.inspection.line,lot:0 +#: model:res.request.link,name:quality_control_stock.req_link_stock_production_lot +msgid "Lot" +msgstr "" + +#. module: quality_control_stock +#: model:ir.model,name:quality_control_stock.model_stock_production_lot +msgid "Lot/Serial" +msgstr "Lote/Serial" + +#. module: quality_control_stock +#: view:qc.inspection:quality_control_stock.qc_inspection_search_view_picking +#: field:qc.inspection,picking:0 +#: view:qc.inspection.line:quality_control_stock.qc_inspection_line_search_stock_view +#: field:qc.inspection.line,picking:0 +msgid "Picking" +msgstr "Separação" + +#. module: quality_control_stock +#: model:ir.model,name:quality_control_stock.model_stock_picking +#: model:res.request.link,name:quality_control_stock.req_link_stock_picking +msgid "Picking List" +msgstr "Lista de separação" + +#. module: quality_control_stock +#: field:qc.trigger,picking_type:0 +msgid "Picking type" +msgstr "" + +#. module: quality_control_stock +#: view:qc.inspection:quality_control_stock.qc_inspection_search_view_picking +#: view:qc.inspection.line:quality_control_stock.qc_inspection_line_search_stock_view +msgid "Product" +msgstr "Produto" + +#. module: quality_control_stock +#: model:ir.model,name:quality_control_stock.model_qc_inspection +msgid "Quality control inspection" +msgstr "" + +#. module: quality_control_stock +#: model:ir.model,name:quality_control_stock.model_qc_inspection_line +msgid "Quality control inspection line" +msgstr "" + +#. module: quality_control_stock +#: model:ir.model,name:quality_control_stock.model_qc_trigger +msgid "Quality control trigger" +msgstr "" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_lot_done +msgid "Quality inspection from lot done" +msgstr "" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_lot_passed +msgid "Quality inspection from lot passed" +msgstr "" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_picking_done +msgid "Quality inspection from picking done" +msgstr "" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_picking_passed +msgid "Quality inspection from picking passed" +msgstr "" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_lot +msgid "Quality inspections from lot" +msgstr "" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_lot_failed +msgid "Quality inspections from lot failed" +msgstr "" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_picking +msgid "Quality inspections from picking" +msgstr "" + +#. module: quality_control_stock +#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_picking_failed +msgid "Quality inspections from picking failed" +msgstr "" + +#. module: quality_control_stock +#: model:res.request.link,name:quality_control_stock.req_link_stock_move +msgid "Stock Move" +msgstr "Movimentação de estoque" + +#. module: quality_control_stock +#: model:ir.model,name:quality_control_stock.model_stock_picking_type +msgid "The picking type determines the picking view" +msgstr "" + +#. module: quality_control_stock +#: view:stock.picking:quality_control_stock.stock_picking_qc_view +#: view:stock.production.lot:quality_control_stock.stock_lot_qc_view +msgid "inspections" +msgstr "" diff --git a/quality_control_stock/i18n/sl.po b/quality_control_stock/i18n/sl.po index 7d9c384e1..9f73fed1a 100644 --- a/quality_control_stock/i18n/sl.po +++ b/quality_control_stock/i18n/sl.po @@ -1,21 +1,28 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: -# * quality_control_stock -# +# * quality_control_stock +# +# Translators: +# Matjaž Mozetič , 2015 msgid "" msgstr "" -"Project-Id-Version: Odoo Server 8.0\n" +"Project-Id-Version: odoomrp-wip (8.0)\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-08-01 20:50+0200\n" -"PO-Revision-Date: 2015-08-01 20:53+0200\n" -"Last-Translator: Matjaz Mozetic \n" -"Language-Team: \n" +"POT-Creation-Date: 2015-10-07 10:44+0000\n" +"PO-Revision-Date: 2015-09-20 19:04+0000\n" +"Last-Translator: Matjaž Mozetič \n" +"Language-Team: Slovenian (http://www.transifex.com/oca/odoomrp-wip-8-0/language/sl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n" -"X-Generator: Poedit 1.8.2\n" +"Content-Transfer-Encoding: \n" "Language: sl\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n" + +#. module: quality_control_stock +#: field:stock.picking,qc_inspections:0 +#: field:stock.production.lot,qc_inspections:0 +msgid "Inspections" +msgstr "Inšpekcije" #. module: quality_control_stock #: help:stock.production.lot,qc_inspections:0 @@ -28,10 +35,11 @@ msgid "Inspections related to this picking." msgstr "Inšpekcije vezane na ta zbirnik." #. module: quality_control_stock -#: view:qc.inspection:quality_control_stock.qc_inspection_search_view_putvalid +#: view:qc.inspection:quality_control_stock.qc_inspection_search_view_picking #: field:qc.inspection,lot:0 #: view:qc.inspection.line:quality_control_stock.qc_inspection_line_search_stock_view #: field:qc.inspection.line,lot:0 +#: model:res.request.link,name:quality_control_stock.req_link_stock_production_lot msgid "Lot" msgstr "Lot" @@ -41,18 +49,45 @@ msgid "Lot/Serial" msgstr "Lot/serijska št." #. module: quality_control_stock -#: view:qc.inspection:quality_control_stock.qc_inspection_search_view_putvalid +#: view:qc.inspection:quality_control_stock.qc_inspection_search_view_picking #: field:qc.inspection,picking:0 #: view:qc.inspection.line:quality_control_stock.qc_inspection_line_search_stock_view #: field:qc.inspection.line,picking:0 msgid "Picking" msgstr "Zbirnik" +#. module: quality_control_stock +#: model:ir.model,name:quality_control_stock.model_stock_picking +#: model:res.request.link,name:quality_control_stock.req_link_stock_picking +msgid "Picking List" +msgstr "Zbirnik" + #. module: quality_control_stock #: field:qc.trigger,picking_type:0 msgid "Picking type" msgstr "Tip zbirnika" +#. module: quality_control_stock +#: view:qc.inspection:quality_control_stock.qc_inspection_search_view_picking +#: view:qc.inspection.line:quality_control_stock.qc_inspection_line_search_stock_view +msgid "Product" +msgstr "Proizvod" + +#. module: quality_control_stock +#: model:ir.model,name:quality_control_stock.model_qc_inspection +msgid "Quality control inspection" +msgstr "Inšpekcija nadzora kvalitete" + +#. module: quality_control_stock +#: model:ir.model,name:quality_control_stock.model_qc_inspection_line +msgid "Quality control inspection line" +msgstr "Inšpekcijska postavka kontrole kakovosti" + +#. module: quality_control_stock +#: model:ir.model,name:quality_control_stock.model_qc_trigger +msgid "Quality control trigger" +msgstr "Sprožilec kontrole kakovosti" + #. module: quality_control_stock #: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_lot_done msgid "Quality inspection from lot done" @@ -93,6 +128,16 @@ msgstr "Inšpekcije kakovosti na zbirniku" msgid "Quality inspections from picking failed" msgstr "Neuspešne inšpekcije kakovosti na zbirniku" +#. module: quality_control_stock +#: model:res.request.link,name:quality_control_stock.req_link_stock_move +msgid "Stock Move" +msgstr "Premik zaloge" + +#. module: quality_control_stock +#: model:ir.model,name:quality_control_stock.model_stock_picking_type +msgid "The picking type determines the picking view" +msgstr "Tip zbirnika določi prikaz zbirnika" + #. module: quality_control_stock #: view:stock.picking:quality_control_stock.stock_picking_qc_view #: view:stock.production.lot:quality_control_stock.stock_lot_qc_view diff --git a/quality_control_stock/models/stock_picking.py b/quality_control_stock/models/stock_picking.py index 55c132832..b1c9a12b8 100644 --- a/quality_control_stock/models/stock_picking.py +++ b/quality_control_stock/models/stock_picking.py @@ -3,6 +3,8 @@ # For copyright and license notices, see __openerp__.py file in root directory ############################################################################## from openerp import models, fields, api +from openerp.addons.quality_control.models.qc_trigger_line import\ + _filter_trigger_lines class StockPicking(models.Model): @@ -42,9 +44,11 @@ class StockPicking(models.Model): 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].get_trigger_line_for_product( - qc_trigger, operation.product_id)) - for trigger_line in trigger_lines: + qc_trigger, operation.product_id, partner=partner)) + for trigger_line in _filter_trigger_lines(trigger_lines): inspection_model._make_inspection(operation, trigger_line) return res diff --git a/quality_control_stock/models/stock_picking_type.py b/quality_control_stock/models/stock_picking_type.py index c09cae31a..385df6afd 100644 --- a/quality_control_stock/models/stock_picking_type.py +++ b/quality_control_stock/models/stock_picking_type.py @@ -15,6 +15,7 @@ class StockPickingType(models.Model): 'name': self.complete_name, 'company_id': self.warehouse_id.company_id.id, 'picking_type': self.id, + 'partner_selectable': True, } return self.env['qc.trigger'].sudo().create(qc_trigger) diff --git a/quality_control_stock/tests/__init__.py b/quality_control_stock/tests/__init__.py new file mode 100644 index 000000000..3dd12a3d9 --- /dev/null +++ b/quality_control_stock/tests/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# (c) 2015 Oihane Crucelaegui - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from . import test_quality_control_stock diff --git a/quality_control_stock/tests/test_quality_control_stock.py b/quality_control_stock/tests/test_quality_control_stock.py new file mode 100644 index 000000000..00c3d0834 --- /dev/null +++ b/quality_control_stock/tests/test_quality_control_stock.py @@ -0,0 +1,159 @@ +# -*- coding: utf-8 -*- +# (c) 2015 Oihane Crucelaegui - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from openerp.tests.common import TransactionCase + + +class TestQualityControl(TransactionCase): + + def setUp(self): + super(TestQualityControl, self).setUp() + self.picking_model = self.env['stock.picking'] + self.operation_model = self.env['stock.pack.operation'] + self.transfer_details_model = self.env['stock.transfer_details'] + self.qc_trigger_model = self.env['qc.trigger'] + self.product = self.env.ref('product.product_product_4') + self.partner1 = self.env.ref('base.res_partner_2') + self.partner2 = self.env.ref('base.res_partner_4') + self.test = self.env.ref('quality_control.qc_test_1') + self.picking_type = self.env.ref('stock.picking_type_out') + self.trigger = self.qc_trigger_model.search( + [('picking_type', '=', self.picking_type.id)]) + move_vals = { + 'name': self.product.name, + 'product_id': self.product.id, + 'product_uom': self.product.uom_id.id, + 'location_id': self.picking_type.default_location_src_id.id, + 'location_dest_id': self.picking_type.default_location_dest_id.id, + } + self.picking1 = self.picking_model.create({ + 'partner_id': self.partner1.id, + 'picking_type_id': self.picking_type.id, + 'move_lines': [(0, 0, move_vals)], + }) + self.picking1.action_confirm() + self.picking1.force_assign() + self.picking1.do_prepare_partial() + + def test_inspection_create_for_product(self): + self.product.qc_triggers = [( + 0, 0, { + 'trigger': self.trigger.id, + 'test': self.test.id, + } + )] + self.picking1.do_transfer() + self.assertEqual(self.picking1.created_inspections, 1, + 'Only one inspection must be created') + + def test_inspection_create_for_template(self): + self.product.product_tmpl_id.qc_triggers = [( + 0, 0, { + 'trigger': self.trigger.id, + 'test': self.test.id, + } + )] + self.picking1.do_transfer() + self.assertEqual(self.picking1.created_inspections, 1, + 'Only one inspection must be created') + + def test_inspection_create_for_category(self): + self.product.categ_id.qc_triggers = [( + 0, 0, { + 'trigger': self.trigger.id, + 'test': self.test.id, + } + )] + self.picking1.do_transfer() + self.assertEqual(self.picking1.created_inspections, 1, + 'Only one inspection must be created') + + def test_inspection_create_for_product_partner(self): + self.product.qc_triggers = [( + 0, 0, { + 'trigger': self.trigger.id, + 'test': self.test.id, + 'partners': [(6, 0, [self.partner1.id])], + } + )] + self.picking1.do_transfer() + self.assertEqual(self.picking1.created_inspections, 1, + 'Only one inspection must be created') + + def test_inspection_create_for_template_partner(self): + self.product.product_tmpl_id.qc_triggers = [( + 0, 0, { + 'trigger': self.trigger.id, + 'test': self.test.id, + 'partners': [(6, 0, [self.partner1.id])], + } + )] + self.picking1.do_transfer() + self.assertEqual(self.picking1.created_inspections, 1, + 'Only one inspection must be created') + + def test_inspection_create_for_category_partner(self): + self.product.categ_id.qc_triggers = [( + 0, 0, { + 'trigger': self.trigger.id, + 'test': self.test.id, + 'partners': [(6, 0, [self.partner1.id])], + } + )] + self.picking1.do_transfer() + self.assertEqual(self.picking1.created_inspections, 1, + 'Only one inspection must be created') + + def test_inspection_create_for_product_wrong_partner(self): + self.product.qc_triggers = [( + 0, 0, { + 'trigger': self.trigger.id, + 'test': self.test.id, + 'partners': [(6, 0, [self.partner2.id])], + } + )] + self.picking1.do_transfer() + self.assertEqual(self.picking1.created_inspections, 0, + 'No inspection must be created') + + def test_inspection_create_for_template_wrong_partner(self): + self.product.product_tmpl_id.qc_triggers = [( + 0, 0, { + 'trigger': self.trigger.id, + 'test': self.test.id, + 'partners': [(6, 0, [self.partner2.id])], + } + )] + self.picking1.do_transfer() + self.assertEqual(self.picking1.created_inspections, 0, + 'No inspection must be created') + + def test_inspection_create_for_category_wrong_partner(self): + self.product.categ_id.qc_triggers = [( + 0, 0, { + 'trigger': self.trigger.id, + 'test': self.test.id, + 'partners': [(6, 0, [self.partner2.id])], + } + )] + self.picking1.do_transfer() + self.assertEqual(self.picking1.created_inspections, 0, + 'No inspection must be created') + + def test_inspection_create_only_one(self): + self.product.qc_triggers = [( + 0, 0, { + 'trigger': self.trigger.id, + 'test': self.test.id, + } + )] + self.product.categ_id.qc_triggers = [( + 0, 0, { + 'trigger': self.trigger.id, + 'test': self.test.id, + } + )] + self.picking1.do_transfer() + self.assertEqual(self.picking1.created_inspections, 1, + 'Only one inspection must be created') From 35cc51058b1b38ec7d69e1b92c585e6a9d5240e1 Mon Sep 17 00:00:00 2001 From: oihane Date: Mon, 2 Nov 2015 18:09:19 +0100 Subject: [PATCH 08/18] [IMP] quality_control_stock: adapted to OCA * more tests to increase coveralls [IMP] quality_control_stock: * added demo data * replaced unlink method by ondelete="cascade" * required changes --- quality_control_stock/README.rst | 47 +++++++++ quality_control_stock/__init__.py | 5 +- quality_control_stock/__openerp__.py | 52 ++++------ .../i18n/quality_control_stock.pot | 99 ------------------- quality_control_stock/models/__init__.py | 5 +- quality_control_stock/models/qc_inspection.py | 9 +- quality_control_stock/models/qc_trigger.py | 8 +- quality_control_stock/models/stock_picking.py | 6 +- .../models/stock_picking_type.py | 13 +-- .../models/stock_production_lot.py | 6 +- .../tests/test_quality_control_stock.py | 88 +++++++++++++++-- .../views/stock_picking_view.xml | 4 +- .../views/stock_production_lot_view.xml | 2 + 13 files changed, 172 insertions(+), 172 deletions(-) delete mode 100644 quality_control_stock/i18n/quality_control_stock.pot diff --git a/quality_control_stock/README.rst b/quality_control_stock/README.rst index 937772c0e..116962b20 100644 --- a/quality_control_stock/README.rst +++ b/quality_control_stock/README.rst @@ -1,3 +1,8 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +=================================== Stock extension for quality control =================================== @@ -5,6 +10,48 @@ This module defines triggers that creates inspections when stock moves are done. It also adds some shortcuts on picking and lots to these inspections. + +Usage +===== + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/129/8.0 + + +Known issues / Roadmap +====================== + +* Put trigger in all languages. + + +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 smashing it by providing a detailed and welcomed feedback `here `_. + + +Credits +======= + Contributors ------------ * Pedro M. Baeza +* Oihane Crucelaegui + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +To contribute to this module, please visit http://odoo-community.org. diff --git a/quality_control_stock/__init__.py b/quality_control_stock/__init__.py index 86bcf7d2e..15f6ce448 100644 --- a/quality_control_stock/__init__.py +++ b/quality_control_stock/__init__.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- -############################################################################## -# For copyright and license notices, see __openerp__.py file in root directory -############################################################################## +# (c) 2014 Serv. Tec. Avanzados - Pedro M. Baeza +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html from . import models from openerp import SUPERUSER_ID diff --git a/quality_control_stock/__openerp__.py b/quality_control_stock/__openerp__.py index c00356e92..f1eaa316d 100644 --- a/quality_control_stock/__openerp__.py +++ b/quality_control_stock/__openerp__.py @@ -1,45 +1,31 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# Copyright (c) -# 2014 Serv. Tec. Avanzados - Pedro M. Baeza (http://www.serviciosbaeza.com) -# 2014 AvanzOsc (http://www.avanzosc.es) -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## +# -*- coding: utf-8 -*- +# (c) 2014 Serv. Tec. Avanzados - Pedro M. Baeza +# (c) 2014 Oihane Crucelaegui - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html { "name": "Quality control - Stock", - "version": "1.0", - "author": "OdooMRP team," - "AvanzOSC," - "Serv. Tecnol. Avanzados - Pedro M. Baeza", + "version": "8.0.1.0.0", + "category": "Quality control", + "license": "AGPL-3", + "author": "OdooMRP team, " + "AvanzOSC, " + "Serv. Tecnol. Avanzados - Pedro M. Baeza, " + "Odoo Community Association (OCA)", "website": "http://www.odoomrp.com", "contributors": [ - "Pedro M. Baeza ", + "Oihane Crucelaegui ", ], - "category": "Quality control", "depends": [ - 'quality_control', - 'stock', + "quality_control", + "stock", ], "data": [ - 'data/quality_control_stock_data.xml', - 'views/qc_inspection_view.xml', - 'views/stock_picking_view.xml', - 'views/stock_production_lot_view.xml', + "data/quality_control_stock_data.xml", + "views/qc_inspection_view.xml", + "views/stock_picking_view.xml", + "views/stock_production_lot_view.xml", ], "post_init_hook": "post_init_hook", "installable": True, diff --git a/quality_control_stock/i18n/quality_control_stock.pot b/quality_control_stock/i18n/quality_control_stock.pot deleted file mode 100644 index 2f4ec2a15..000000000 --- a/quality_control_stock/i18n/quality_control_stock.pot +++ /dev/null @@ -1,99 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * quality_control_stock -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 8.0\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-12-10 19:26+0000\n" -"PO-Revision-Date: 2014-12-10 19:26+0000\n" -"Last-Translator: <>\n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Plural-Forms: \n" - -#. module: quality_control_stock -#: help:stock.production.lot,qc_inspections:0 -msgid "Inspections related to this lot." -msgstr "" - -#. module: quality_control_stock -#: help:stock.picking,qc_inspections:0 -msgid "Inspections related to this picking." -msgstr "" - -#. module: quality_control_stock -#: view:qc.inspection:quality_control_stock.qc_inspection_search_view_putvalid -#: field:qc.inspection,lot:0 -#: view:qc.inspection.line:quality_control_stock.qc_inspection_line_search_stock_view -#: field:qc.inspection.line,lot:0 -msgid "Lot" -msgstr "" - -#. module: quality_control_stock -#: model:ir.model,name:quality_control_stock.model_stock_production_lot -msgid "Lot/Serial" -msgstr "" - -#. module: quality_control_stock -#: view:qc.inspection:quality_control_stock.qc_inspection_search_view_putvalid -#: field:qc.inspection,picking:0 -#: view:qc.inspection.line:quality_control_stock.qc_inspection_line_search_stock_view -#: field:qc.inspection.line,picking:0 -msgid "Picking" -msgstr "" - -#. module: quality_control_stock -#: field:qc.trigger,picking_type:0 -msgid "Picking type" -msgstr "" - -#. module: quality_control_stock -#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_lot_done -msgid "Quality inspection from lot done" -msgstr "" - -#. module: quality_control_stock -#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_lot_passed -msgid "Quality inspection from lot passed" -msgstr "" - -#. module: quality_control_stock -#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_picking_done -msgid "Quality inspection from picking done" -msgstr "" - -#. module: quality_control_stock -#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_picking_passed -msgid "Quality inspection from picking passed" -msgstr "" - -#. module: quality_control_stock -#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_lot -msgid "Quality inspections from lot" -msgstr "" - -#. module: quality_control_stock -#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_lot_failed -msgid "Quality inspections from lot failed" -msgstr "" - -#. module: quality_control_stock -#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_picking -msgid "Quality inspections from picking" -msgstr "" - -#. module: quality_control_stock -#: model:ir.actions.act_window,name:quality_control_stock.action_qc_inspection_per_picking_failed -msgid "Quality inspections from picking failed" -msgstr "" - -#. module: quality_control_stock -#: view:stock.picking:quality_control_stock.stock_picking_qc_view -#: view:stock.production.lot:quality_control_stock.stock_lot_qc_view -msgid "inspections" -msgstr "" - diff --git a/quality_control_stock/models/__init__.py b/quality_control_stock/models/__init__.py index bf7cb46e4..61f4c2b9e 100644 --- a/quality_control_stock/models/__init__.py +++ b/quality_control_stock/models/__init__.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- -############################################################################## -# For copyright and license notices, see __openerp__.py file in root directory -############################################################################## +# (c) 2014 Serv. Tec. Avanzados - Pedro M. Baeza +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html from . import qc_trigger from . import qc_inspection diff --git a/quality_control_stock/models/qc_inspection.py b/quality_control_stock/models/qc_inspection.py index 22a7466a3..a7bd4cc52 100644 --- a/quality_control_stock/models/qc_inspection.py +++ b/quality_control_stock/models/qc_inspection.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- -############################################################################## -# For copyright and license notices, see __openerp__.py file in root directory -############################################################################## +# (c) 2014 Serv. Tec. Avanzados - Pedro M. Baeza +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + from openerp import models, fields, api @@ -28,8 +28,7 @@ class QcInspection(models.Model): if self.object_id._name == 'stock.pack.operation': self.lot = self.object_id.lot_id elif self.object_id._name == 'stock.move': - if self.object_id.lot_ids: - self.lot = self.object_id.lot_ids[0] + self.lot = self.object_id.lot_ids[:1] @api.one @api.depends('object_id') diff --git a/quality_control_stock/models/qc_trigger.py b/quality_control_stock/models/qc_trigger.py index e53003749..5c0d7816e 100644 --- a/quality_control_stock/models/qc_trigger.py +++ b/quality_control_stock/models/qc_trigger.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- -############################################################################## -# For copyright and license notices, see __openerp__.py file in root directory -############################################################################## +# (c) 2014 Serv. Tec. Avanzados - Pedro M. Baeza +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + from openerp import models, fields @@ -9,4 +9,4 @@ class QcTrigger(models.Model): _inherit = 'qc.trigger' picking_type = fields.Many2one( - comodel_name="stock.picking.type", readonly=True) + comodel_name="stock.picking.type", readonly=True, ondelete="cascade") diff --git a/quality_control_stock/models/stock_picking.py b/quality_control_stock/models/stock_picking.py index b1c9a12b8..1583d9bd6 100644 --- a/quality_control_stock/models/stock_picking.py +++ b/quality_control_stock/models/stock_picking.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- -############################################################################## -# For copyright and license notices, see __openerp__.py file in root directory -############################################################################## +# (c) 2014 Serv. Tec. Avanzados - Pedro M. Baeza +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + from openerp import models, fields, api from openerp.addons.quality_control.models.qc_trigger_line import\ _filter_trigger_lines diff --git a/quality_control_stock/models/stock_picking_type.py b/quality_control_stock/models/stock_picking_type.py index 385df6afd..7010cf3ba 100644 --- a/quality_control_stock/models/stock_picking_type.py +++ b/quality_control_stock/models/stock_picking_type.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- -############################################################################## -# For copyright and license notices, see __openerp__.py file in root directory -############################################################################## +# (c) 2014 Serv. Tec. Avanzados - Pedro M. Baeza +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + from openerp import models, api @@ -11,7 +11,6 @@ class StockPickingType(models.Model): @api.multi def _create_qc_trigger(self): qc_trigger = { - # Synchronize all translations 'name': self.complete_name, 'company_id': self.warehouse_id.company_id.id, 'picking_type': self.id, @@ -34,9 +33,3 @@ class StockPickingType(models.Model): [('picking_type', '=', self.id)]) qc_trigger.name = self.complete_name return res - - @api.multi - def unlink(self): - self.env['qc.trigger'].sudo().search( - [('picking_type', '=', self.id)]).unlink() - return super(StockPickingType, self).unlink() diff --git a/quality_control_stock/models/stock_production_lot.py b/quality_control_stock/models/stock_production_lot.py index ed67fb25f..aeff0ad90 100644 --- a/quality_control_stock/models/stock_production_lot.py +++ b/quality_control_stock/models/stock_production_lot.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- -############################################################################## -# For copyright and license notices, see __openerp__.py file in root directory -############################################################################## +# (c) 2014 Serv. Tec. Avanzados - Pedro M. Baeza +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + from openerp import models, fields, api diff --git a/quality_control_stock/tests/test_quality_control_stock.py b/quality_control_stock/tests/test_quality_control_stock.py index 00c3d0834..000dcf43c 100644 --- a/quality_control_stock/tests/test_quality_control_stock.py +++ b/quality_control_stock/tests/test_quality_control_stock.py @@ -10,16 +10,27 @@ class TestQualityControl(TransactionCase): def setUp(self): super(TestQualityControl, self).setUp() self.picking_model = self.env['stock.picking'] - self.operation_model = self.env['stock.pack.operation'] - self.transfer_details_model = self.env['stock.transfer_details'] + self.inspection_model = self.env['qc.inspection'] self.qc_trigger_model = self.env['qc.trigger'] + self.picking_type_model = self.env['stock.picking.type'] self.product = self.env.ref('product.product_product_4') self.partner1 = self.env.ref('base.res_partner_2') self.partner2 = self.env.ref('base.res_partner_4') self.test = self.env.ref('quality_control.qc_test_1') self.picking_type = self.env.ref('stock.picking_type_out') + self.sequence = self.env.ref('stock.seq_type_picking_out') + inspection_lines = ( + self.inspection_model._prepare_inspection_lines(self.test)) + self.inspection1 = self.inspection_model.create({ + 'name': 'Test Inspection', + 'inspection_lines': inspection_lines, + }) self.trigger = self.qc_trigger_model.search( [('picking_type', '=', self.picking_type.id)]) + self.lot = self.env['stock.production.lot'].create({ + 'name': 'Lot for tests', + 'product_id': self.product.id, + }) move_vals = { 'name': self.product.name, 'product_id': self.product.id, @@ -35,6 +46,9 @@ class TestQualityControl(TransactionCase): self.picking1.action_confirm() self.picking1.force_assign() self.picking1.do_prepare_partial() + for line in self.picking1.pack_operation_ids.filtered( + lambda r: r.product_id == self.product): + line.write({'lot_id': self.lot.id}) def test_inspection_create_for_product(self): self.product.qc_triggers = [( @@ -46,6 +60,8 @@ class TestQualityControl(TransactionCase): self.picking1.do_transfer() self.assertEqual(self.picking1.created_inspections, 1, 'Only one inspection must be created') + self.assertEqual(self.picking1.qc_inspections[:1].test, self.test, + 'Wrong test picked when creating inspection.') def test_inspection_create_for_template(self): self.product.product_tmpl_id.qc_triggers = [( @@ -57,6 +73,8 @@ class TestQualityControl(TransactionCase): self.picking1.do_transfer() self.assertEqual(self.picking1.created_inspections, 1, 'Only one inspection must be created') + self.assertEqual(self.picking1.qc_inspections[:1].test, self.test, + 'Wrong test picked when creating inspection.') def test_inspection_create_for_category(self): self.product.categ_id.qc_triggers = [( @@ -68,49 +86,57 @@ class TestQualityControl(TransactionCase): self.picking1.do_transfer() self.assertEqual(self.picking1.created_inspections, 1, 'Only one inspection must be created') + self.assertEqual(self.picking1.qc_inspections[:1].test, self.test, + 'Wrong test picked when creating inspection.') def test_inspection_create_for_product_partner(self): self.product.qc_triggers = [( 0, 0, { 'trigger': self.trigger.id, 'test': self.test.id, - 'partners': [(6, 0, [self.partner1.id])], + 'partners': [(6, 0, self.partner1.ids)], } )] self.picking1.do_transfer() self.assertEqual(self.picking1.created_inspections, 1, 'Only one inspection must be created') + self.assertEqual(self.picking1.qc_inspections[:1].test, self.test, + 'Wrong test picked when creating inspection.') def test_inspection_create_for_template_partner(self): self.product.product_tmpl_id.qc_triggers = [( 0, 0, { 'trigger': self.trigger.id, 'test': self.test.id, - 'partners': [(6, 0, [self.partner1.id])], + 'partners': [(6, 0, self.partner1.ids)], } )] self.picking1.do_transfer() self.assertEqual(self.picking1.created_inspections, 1, 'Only one inspection must be created') + self.assertEqual(self.picking1.qc_inspections[:1].test, self.test, + 'Wrong test picked when creating inspection.') def test_inspection_create_for_category_partner(self): self.product.categ_id.qc_triggers = [( 0, 0, { 'trigger': self.trigger.id, 'test': self.test.id, - 'partners': [(6, 0, [self.partner1.id])], + 'partners': [(6, 0, self.partner1.ids)], } )] self.picking1.do_transfer() self.assertEqual(self.picking1.created_inspections, 1, 'Only one inspection must be created') + self.assertEqual(self.picking1.qc_inspections[:1].test, self.test, + 'Wrong test picked when creating inspection.') def test_inspection_create_for_product_wrong_partner(self): self.product.qc_triggers = [( 0, 0, { 'trigger': self.trigger.id, 'test': self.test.id, - 'partners': [(6, 0, [self.partner2.id])], + 'partners': [(6, 0, self.partner2.ids)], } )] self.picking1.do_transfer() @@ -122,7 +148,7 @@ class TestQualityControl(TransactionCase): 0, 0, { 'trigger': self.trigger.id, 'test': self.test.id, - 'partners': [(6, 0, [self.partner2.id])], + 'partners': [(6, 0, self.partner2.ids)], } )] self.picking1.do_transfer() @@ -134,7 +160,7 @@ class TestQualityControl(TransactionCase): 0, 0, { 'trigger': self.trigger.id, 'test': self.test.id, - 'partners': [(6, 0, [self.partner2.id])], + 'partners': [(6, 0, self.partner2.ids)], } )] self.picking1.do_transfer() @@ -157,3 +183,49 @@ class TestQualityControl(TransactionCase): self.picking1.do_transfer() self.assertEqual(self.picking1.created_inspections, 1, 'Only one inspection must be created') + self.assertEqual(self.picking1.qc_inspections[:1].test, self.test, + 'Wrong test picked when creating inspection.') + self.assertEqual(self.lot.created_inspections, 1, + 'Only one inspection must be created') + self.assertEqual(self.lot.qc_inspections[:1].test, self.test, + 'Wrong test picked when creating inspection.') + + def test_picking_type(self): + picking_type = self.picking_type_model.create({ + 'name': 'Test Picking Type', + 'sequence_id': self.sequence.id, + 'code': 'outgoing', + }) + trigger = self.qc_trigger_model.search( + [('picking_type', '=', picking_type.id)]) + self.assertEqual(len(trigger), 1, + 'One trigger must have been created.') + self.assertEqual(trigger.name, picking_type.complete_name, + 'Trigger name must match picking type name.') + picking_type.write({ + 'name': 'Test Name Change', + }) + self.assertEqual(trigger.name, picking_type.complete_name, + 'Trigger name must match picking type name.') + + def test_qc_inspection_picking(self): + self.inspection1.write({ + 'object_id': '%s,%d' % (self.picking1._model, + self.picking1.id), + }) + self.assertEquals(self.inspection1.picking, + self.picking1) + + def test_qc_inspection_stock_move(self): + self.inspection1.write({ + 'object_id': '%s,%d' % (self.picking1.move_lines[:1]._model, + self.picking1.move_lines[:1].id), + }) + self.assertEquals(self.inspection1.picking, + self.picking1) + self.assertEquals(self.inspection1.lot, + self.picking1.move_lines[:1].lot_ids[:1]) + self.assertEquals(self.inspection1.product, + self.picking1.move_lines[:1].product_id) + self.assertEquals(self.inspection1.qty, + self.picking1.move_lines[:1].product_qty) diff --git a/quality_control_stock/views/stock_picking_view.xml b/quality_control_stock/views/stock_picking_view.xml index 1c53c4d06..1ebb16078 100644 --- a/quality_control_stock/views/stock_picking_view.xml +++ b/quality_control_stock/views/stock_picking_view.xml @@ -34,6 +34,8 @@ stock.picking.qc.view stock.picking +
- - - -
-
- - - - + + stock.picking.qc.view + stock.picking + + + +
+ + + + +
+
+
+ diff --git a/quality_control_stock/views/stock_production_lot_view.xml b/quality_control_stock/views/stock_production_lot_view.xml index 9ec36c207..eabd58106 100644 --- a/quality_control_stock/views/stock_production_lot_view.xml +++ b/quality_control_stock/views/stock_production_lot_view.xml @@ -1,72 +1,70 @@ - - + + + + Quality inspections from lot + qc.inspection + tree,form + [('lot', '=', active_id)] + - - Quality inspections from lot - qc.inspection - tree,form - [('lot', '=', active_id)] - + + Quality inspection from lot done + qc.inspection + tree,form + [('lot', '=', active_id), ('state', 'not in', ['draft', 'waiting'])] + - - Quality inspection from lot done - qc.inspection - tree,form - [('lot', '=', active_id), ('state', 'not in', ['draft', 'waiting'])] - + + Quality inspection from lot passed + qc.inspection + tree,form + [('lot', '=', active_id), ('state', '=', 'success')] + - - Quality inspection from lot passed - qc.inspection - tree,form - [('lot', '=', active_id), ('state', '=', 'success')] - + + Quality inspections from lot failed + qc.inspection + tree,form + [('lot', '=', active_id), ('state', '=', 'failed')] + - - Quality inspections from lot failed - qc.inspection - tree,form - [('lot', '=', active_id), ('state', '=', 'failed')] - - - - stock.production.lot.qc.view - stock.production.lot - - - -
- - - - -
-
-
- -
-
+ + stock.production.lot.qc.view + stock.production.lot + + + +
+ + + + +
+
+
+ From 9dd0f8c8e245758831fbb98ec346a3fb56fcd790 Mon Sep 17 00:00:00 2001 From: Simone Rubino Date: Mon, 30 Jul 2018 16:18:49 +0200 Subject: [PATCH 13/18] [FIX][quality_control_stock] get_lot and get_picking should be able to manage recordsets --- quality_control_stock/__manifest__.py | 2 +- quality_control_stock/models/qc_inspection.py | 37 ++++++++++--------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/quality_control_stock/__manifest__.py b/quality_control_stock/__manifest__.py index 09e99ebe0..3254baa3c 100644 --- a/quality_control_stock/__manifest__.py +++ b/quality_control_stock/__manifest__.py @@ -6,7 +6,7 @@ { "name": "Quality control - Stock", - "version": "10.0.1.0.0", + "version": "10.0.1.0.1", "category": "Quality control", "license": "AGPL-3", "author": "OdooMRP team, " diff --git a/quality_control_stock/models/qc_inspection.py b/quality_control_stock/models/qc_inspection.py index ad801c767..ef99b2d9b 100644 --- a/quality_control_stock/models/qc_inspection.py +++ b/quality_control_stock/models/qc_inspection.py @@ -12,28 +12,29 @@ class QcInspection(models.Model): @api.multi @api.depends('object_id') def get_picking(self): - self.ensure_one() - self.picking = False - if self.object_id: - if self.object_id._name == 'stock.move': - self.picking = self.object_id.picking_id - elif self.object_id._name == 'stock.picking': - self.picking = self.object_id - elif self.object_id._name == 'stock.pack.operation': - self.picking = self.object_id.picking_id + for inspection in self: + inspection.picking = False + if inspection.object_id: + if inspection.object_id._name == 'stock.move': + inspection.picking = inspection.object_id.picking_id + elif inspection.object_id._name == 'stock.picking': + inspection.picking = inspection.object_id + elif inspection.object_id._name == 'stock.pack.operation': + inspection.picking = inspection.object_id.picking_id @api.multi @api.depends('object_id') def get_lot(self): - self.ensure_one() - self.lot = False - if self.object_id: - if self.object_id._name == 'stock.pack.operation': - self.lot = self.object_id.pack_lot_ids[:1].lot_id - elif self.object_id._name == 'stock.move': - self.lot = self.object_id.lot_ids[:1] - elif self.object_id._name == 'stock.production.lot': - self.lot = self.object_id + for inspection in self: + inspection.lot = False + if inspection.object_id: + if inspection.object_id._name == 'stock.pack.operation': + inspection.lot = \ + inspection.object_id.pack_lot_ids[:1].lot_id + elif inspection.object_id._name == 'stock.move': + inspection.lot = inspection.object_id.lot_ids[:1] + elif inspection.object_id._name == 'stock.production.lot': + inspection.lot = inspection.object_id @api.multi @api.depends('object_id') From 6a769659f5b79eea4a951995478b7077f8a9feac Mon Sep 17 00:00:00 2001 From: Simone Rubino Date: Wed, 8 Aug 2018 16:29:20 +0200 Subject: [PATCH 14/18] [FIX] count_inspections methods should be able to manage recordsets (#293) --- quality_control_stock/__manifest__.py | 2 +- quality_control_stock/models/qc_inspection.py | 9 +++--- quality_control_stock/models/stock_picking.py | 28 ++++++++++--------- .../models/stock_production_lot.py | 26 ++++++++--------- 4 files changed, 34 insertions(+), 31 deletions(-) diff --git a/quality_control_stock/__manifest__.py b/quality_control_stock/__manifest__.py index 3254baa3c..f47f852c0 100644 --- a/quality_control_stock/__manifest__.py +++ b/quality_control_stock/__manifest__.py @@ -6,7 +6,7 @@ { "name": "Quality control - Stock", - "version": "10.0.1.0.1", + "version": "10.0.1.0.2", "category": "Quality control", "license": "AGPL-3", "author": "OdooMRP team, " diff --git a/quality_control_stock/models/qc_inspection.py b/quality_control_stock/models/qc_inspection.py index ef99b2d9b..1e79c5abf 100644 --- a/quality_control_stock/models/qc_inspection.py +++ b/quality_control_stock/models/qc_inspection.py @@ -11,7 +11,7 @@ class QcInspection(models.Model): @api.multi @api.depends('object_id') - def get_picking(self): + def _compute_picking(self): for inspection in self: inspection.picking = False if inspection.object_id: @@ -24,7 +24,7 @@ class QcInspection(models.Model): @api.multi @api.depends('object_id') - def get_lot(self): + def _compute_lot(self): for inspection in self: inspection.lot = False if inspection.object_id: @@ -70,9 +70,10 @@ class QcInspection(models.Model): return res picking = fields.Many2one( - comodel_name="stock.picking", compute="get_picking", store=True) + comodel_name="stock.picking", compute="_compute_picking", store=True) lot = fields.Many2one( - comodel_name='stock.production.lot', compute="get_lot", store=True) + comodel_name='stock.production.lot', compute="_compute_lot", + store=True) class QcInspectionLine(models.Model): diff --git a/quality_control_stock/models/stock_picking.py b/quality_control_stock/models/stock_picking.py index 6f4ef9a57..dcbb6cc56 100644 --- a/quality_control_stock/models/stock_picking.py +++ b/quality_control_stock/models/stock_picking.py @@ -13,27 +13,29 @@ class StockPicking(models.Model): @api.multi @api.depends('qc_inspections', 'qc_inspections.state') - def _count_inspections(self): - self.ensure_one() - self.created_inspections = len(self.qc_inspections) - self.passed_inspections = len([x for x in self.qc_inspections if - x.state == 'success']) - self.failed_inspections = len([x for x in self.qc_inspections if - x.state == 'failed']) - self.done_inspections = (self.passed_inspections + - self.failed_inspections) + def _compute_count_inspections(self): + for picking in self: + picking.created_inspections = len(picking.qc_inspections) + picking.passed_inspections = \ + len([x for x in picking.qc_inspections + if x.state == 'success']) + picking.failed_inspections = \ + len([x for x in picking.qc_inspections + if x.state == 'failed']) + picking.done_inspections = \ + (picking.passed_inspections + picking.failed_inspections) qc_inspections = fields.One2many( comodel_name='qc.inspection', inverse_name='picking', copy=False, string='Inspections', help="Inspections related to this picking.") created_inspections = fields.Integer( - compute="_count_inspections", string="Created inspections") + compute="_compute_count_inspections", string="Created inspections") done_inspections = fields.Integer( - compute="_count_inspections", string="Done inspections") + compute="_compute_count_inspections", string="Done inspections") passed_inspections = fields.Integer( - compute="_count_inspections", string="Inspections OK") + compute="_compute_count_inspections", string="Inspections OK") failed_inspections = fields.Integer( - compute="_count_inspections", string="Inspections failed") + compute="_compute_count_inspections", string="Inspections failed") @api.multi def do_transfer(self): diff --git a/quality_control_stock/models/stock_production_lot.py b/quality_control_stock/models/stock_production_lot.py index 25026861c..1db874dc0 100644 --- a/quality_control_stock/models/stock_production_lot.py +++ b/quality_control_stock/models/stock_production_lot.py @@ -11,24 +11,24 @@ class StockProductionLot(models.Model): @api.multi @api.depends('qc_inspections', 'qc_inspections.state') - def _count_inspections(self): - self.ensure_one() - self.created_inspections = len(self.qc_inspections) - self.passed_inspections = len([x for x in self.qc_inspections if - x.state == 'success']) - self.failed_inspections = len([x for x in self.qc_inspections if - x.state == 'failed']) - self.done_inspections = (self.passed_inspections + - self.failed_inspections) + def _compute_count_inspections(self): + for lot in self: + lot.created_inspections = len(lot.qc_inspections) + lot.passed_inspections = \ + len([x for x in lot.qc_inspections if x.state == 'success']) + lot.failed_inspections = \ + len([x for x in lot.qc_inspections if x.state == 'failed']) + lot.done_inspections = \ + (lot.passed_inspections + lot.failed_inspections) qc_inspections = fields.One2many( comodel_name='qc.inspection', inverse_name='lot', copy=False, string='Inspections', help="Inspections related to this lot.") created_inspections = fields.Integer( - compute="_count_inspections", string="Created inspections") + compute="_compute_count_inspections", string="Created inspections") done_inspections = fields.Integer( - compute="_count_inspections", string="Done inspections") + compute="_compute_count_inspections", string="Done inspections") passed_inspections = fields.Integer( - compute="_count_inspections", string="Inspections OK") + compute="_compute_count_inspections", string="Inspections OK") failed_inspections = fields.Integer( - compute="_count_inspections", string="Inspections failed") + compute="_compute_count_inspections", string="Inspections failed") From 50afa0c5fb6fddf69ca40a334244e3faf9a4c2cd Mon Sep 17 00:00:00 2001 From: Ignacio Ales Date: Thu, 13 Sep 2018 10:57:38 +0200 Subject: [PATCH 15/18] [MIG] quality_control_stock: Migration to 11.0 --- quality_control_stock/README.rst | 7 +- quality_control_stock/__init__.py | 1 - quality_control_stock/__manifest__.py | 5 +- .../data/quality_control_stock_data.xml | 23 +++--- quality_control_stock/models/__init__.py | 1 - quality_control_stock/models/qc_inspection.py | 55 +++++++------- quality_control_stock/models/qc_trigger.py | 3 +- quality_control_stock/models/stock_picking.py | 21 +++--- .../models/stock_picking_type.py | 11 +-- .../models/stock_production_lot.py | 14 ++-- quality_control_stock/tests/__init__.py | 1 - .../tests/test_quality_control_stock.py | 72 +++++++++++-------- .../views/qc_inspection_view.xml | 34 ++++----- .../views/stock_picking_view.xml | 8 +-- .../views/stock_production_lot_view.xml | 8 +-- 15 files changed, 135 insertions(+), 129 deletions(-) diff --git a/quality_control_stock/README.rst b/quality_control_stock/README.rst index 5fbc24490..85846825c 100644 --- a/quality_control_stock/README.rst +++ b/quality_control_stock/README.rst @@ -14,13 +14,13 @@ Quality control - Stock :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fmanufacture-lightgray.png?logo=github - :target: https://github.com/OCA/manufacture/tree/10.0/quality_control_stock + :target: https://github.com/OCA/manufacture/tree/11.0/quality_control_stock :alt: OCA/manufacture .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/manufacture-10-0/manufacture-10-0-quality_control_stock + :target: https://translation.odoo-community.org/projects/manufacture-11-0/manufacture-11-0-quality_control_stock :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png - :target: https://runbot.odoo-community.org/runbot/129/10.0 + :target: https://runbot.odoo-community.org/runbot/129/11.0 :alt: Try me on Runbot |badge1| |badge2| |badge3| |badge4| |badge5| @@ -66,6 +66,7 @@ Contributors * Pedro M. Baeza * Oihane Crucelaegui * Simone Rubino +* Ignacio Ales Maintainers ~~~~~~~~~~~ diff --git a/quality_control_stock/__init__.py b/quality_control_stock/__init__.py index adca769d2..db11222a0 100644 --- a/quality_control_stock/__init__.py +++ b/quality_control_stock/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2014 Serv. Tec. Avanzados - Pedro M. Baeza # Copyright 2018 Simone Rubino - Agile Business Group # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). diff --git a/quality_control_stock/__manifest__.py b/quality_control_stock/__manifest__.py index f47f852c0..f95766f6f 100644 --- a/quality_control_stock/__manifest__.py +++ b/quality_control_stock/__manifest__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2014 Serv. Tec. Avanzados - Pedro M. Baeza # Copyright 2014 Oihane Crucelaegui - AvanzOSC # Copyright 2018 Simone Rubino - Agile Business Group @@ -6,7 +5,7 @@ { "name": "Quality control - Stock", - "version": "10.0.1.0.2", + "version": "11.0.1.0.0", "category": "Quality control", "license": "AGPL-3", "author": "OdooMRP team, " @@ -14,7 +13,7 @@ "Serv. Tecnol. Avanzados - Pedro M. Baeza, " "Agile Business Group, " "Odoo Community Association (OCA)", - "website": "https://github.com/OCA/manufacture/tree/10.0/" + "website": "https://github.com/OCA/manufacture/tree/11.0/" "quality_control_stock", "depends": [ "quality_control", diff --git a/quality_control_stock/data/quality_control_stock_data.xml b/quality_control_stock/data/quality_control_stock_data.xml index 3b3c58555..156c25b14 100644 --- a/quality_control_stock/data/quality_control_stock_data.xml +++ b/quality_control_stock/data/quality_control_stock_data.xml @@ -2,18 +2,15 @@ - - Stock Move - stock.move - + + + Stock Move + stock.move + - - Picking List - stock.picking - - - - Lot - stock.production.lot - + + Picking List + stock.picking + + diff --git a/quality_control_stock/models/__init__.py b/quality_control_stock/models/__init__.py index 87c70ccc6..634e9396b 100644 --- a/quality_control_stock/models/__init__.py +++ b/quality_control_stock/models/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from . import qc_trigger diff --git a/quality_control_stock/models/qc_inspection.py b/quality_control_stock/models/qc_inspection.py index 1e79c5abf..ac7458132 100644 --- a/quality_control_stock/models/qc_inspection.py +++ b/quality_control_stock/models/qc_inspection.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2014 Serv. Tec. Avanzados - Pedro M. Baeza # Copyright 2018 Simone Rubino - Agile Business Group # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). @@ -13,49 +12,53 @@ class QcInspection(models.Model): @api.depends('object_id') def _compute_picking(self): for inspection in self: - inspection.picking = False + inspection.picking_id = False if inspection.object_id: if inspection.object_id._name == 'stock.move': - inspection.picking = inspection.object_id.picking_id + inspection.picking_id = inspection.object_id.picking_id elif inspection.object_id._name == 'stock.picking': - inspection.picking = inspection.object_id - elif inspection.object_id._name == 'stock.pack.operation': - inspection.picking = inspection.object_id.picking_id + inspection.picking_id = inspection.object_id + elif inspection.object_id._name == 'stock.move.line': + inspection.picking_id = inspection.object_id.picking_id @api.multi @api.depends('object_id') def _compute_lot(self): for inspection in self: - inspection.lot = False + inspection.lot_id = False if inspection.object_id: - if inspection.object_id._name == 'stock.pack.operation': - inspection.lot = \ - inspection.object_id.pack_lot_ids[:1].lot_id + if inspection.object_id._name == 'stock.move.line': + inspection.lot_id = \ + inspection.object_id.lot_id elif inspection.object_id._name == 'stock.move': - inspection.lot = inspection.object_id.lot_ids[:1] + inspection.lot_id = \ + self.env['stock.move.line'].search([ + ('lot_id', '!=', False), + ('move_id', '=', inspection.object_id.id) + ])[:1].lot_id elif inspection.object_id._name == 'stock.production.lot': - inspection.lot = inspection.object_id + inspection.lot_id = inspection.object_id @api.multi @api.depends('object_id') - def _get_product(self): + def _compute_product_id(self): """Overriden for getting the product from a stock move.""" self.ensure_one() - super(QcInspection, self)._get_product() + super(QcInspection, self)._compute_product_id() if self.object_id: if self.object_id._name == 'stock.move': - self.product = self.object_id.product_id - elif self.object_id._name == 'stock.pack.operation': - self.product = self.object_id.product_id + self.product_id = self.object_id.product_id + elif self.object_id._name == 'stock.move.line': + self.product_id = self.object_id.product_id elif self.object_id._name == 'stock.production.lot': - self.product = self.object_id.product_id + self.product_id = self.object_id.product_id @api.onchange('object_id') def onchange_object_id(self): if self.object_id: if self.object_id._name == 'stock.move': self.qty = self.object_id.product_qty - elif self.object_id._name == 'stock.pack.operation': + elif self.object_id._name == 'stock.move.line': self.qty = self.object_id.product_qty @api.multi @@ -63,15 +66,15 @@ class QcInspection(models.Model): res = super(QcInspection, self)._prepare_inspection_header( object_ref, trigger_line) # Fill qty when coming from pack operations - if object_ref and object_ref._name == 'stock.pack.operation': + if object_ref and object_ref._name == 'stock.move.line': res['qty'] = object_ref.product_qty if object_ref and object_ref._name == 'stock.move': res['qty'] = object_ref.product_uom_qty return res - picking = fields.Many2one( + picking_id = fields.Many2one( comodel_name="stock.picking", compute="_compute_picking", store=True) - lot = fields.Many2one( + lot_id = fields.Many2one( comodel_name='stock.production.lot', compute="_compute_lot", store=True) @@ -79,9 +82,9 @@ class QcInspection(models.Model): class QcInspectionLine(models.Model): _inherit = 'qc.inspection.line' - picking = fields.Many2one( - comodel_name="stock.picking", related="inspection_id.picking", + picking_id = fields.Many2one( + comodel_name="stock.picking", related="inspection_id.picking_id", store=True) - lot = fields.Many2one( - comodel_name="stock.production.lot", related="inspection_id.lot", + lot_id = fields.Many2one( + comodel_name="stock.production.lot", related="inspection_id.lot_id", store=True) diff --git a/quality_control_stock/models/qc_trigger.py b/quality_control_stock/models/qc_trigger.py index 2b08d537d..942ba29fa 100644 --- a/quality_control_stock/models/qc_trigger.py +++ b/quality_control_stock/models/qc_trigger.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2014 Serv. Tec. Avanzados - Pedro M. Baeza # Copyright 2018 Simone Rubino - Agile Business Group # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). @@ -9,5 +8,5 @@ from odoo import fields, models class QcTrigger(models.Model): _inherit = 'qc.trigger' - picking_type = fields.Many2one( + picking_type_id = fields.Many2one( comodel_name="stock.picking.type", readonly=True, ondelete="cascade") diff --git a/quality_control_stock/models/stock_picking.py b/quality_control_stock/models/stock_picking.py index dcbb6cc56..ecdc5db8c 100644 --- a/quality_control_stock/models/stock_picking.py +++ b/quality_control_stock/models/stock_picking.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2014 Serv. Tec. Avanzados - Pedro M. Baeza # Copyright 2018 Simone Rubino - Agile Business Group # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). @@ -12,21 +11,21 @@ class StockPicking(models.Model): _inherit = 'stock.picking' @api.multi - @api.depends('qc_inspections', 'qc_inspections.state') + @api.depends('qc_inspections_ids', 'qc_inspections_ids.state') def _compute_count_inspections(self): for picking in self: - picking.created_inspections = len(picking.qc_inspections) + picking.created_inspections = len(picking.qc_inspections_ids) picking.passed_inspections = \ - len([x for x in picking.qc_inspections + len([x for x in picking.qc_inspections_ids if x.state == 'success']) picking.failed_inspections = \ - len([x for x in picking.qc_inspections + len([x for x in picking.qc_inspections_ids if x.state == 'failed']) picking.done_inspections = \ (picking.passed_inspections + picking.failed_inspections) - qc_inspections = fields.One2many( - comodel_name='qc.inspection', inverse_name='picking', copy=False, + qc_inspections_ids = fields.One2many( + comodel_name='qc.inspection', inverse_name='picking_id', copy=False, string='Inspections', help="Inspections related to this picking.") created_inspections = fields.Integer( compute="_compute_count_inspections", string="Created inspections") @@ -38,12 +37,12 @@ class StockPicking(models.Model): compute="_compute_count_inspections", string="Inspections failed") @api.multi - def do_transfer(self): - res = super(StockPicking, self).do_transfer() + def action_done(self): + res = super(StockPicking, self).action_done() inspection_model = self.env['qc.inspection'] - for operation in self.pack_operation_ids: + for operation in self.move_lines: qc_trigger = self.env['qc.trigger'].search( - [('picking_type', '=', self.picking_type_id.id)]) + [('picking_type_id', '=', self.picking_type_id.id)]) trigger_lines = set() for model in ['qc.trigger.product_category_line', 'qc.trigger.product_template_line', diff --git a/quality_control_stock/models/stock_picking_type.py b/quality_control_stock/models/stock_picking_type.py index 5acb3b8ff..382202b71 100644 --- a/quality_control_stock/models/stock_picking_type.py +++ b/quality_control_stock/models/stock_picking_type.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2014 Serv. Tec. Avanzados - Pedro M. Baeza # Copyright 2018 Simone Rubino - Agile Business Group # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). @@ -15,7 +14,7 @@ class StockPickingType(models.Model): qc_trigger = { 'name': self.name, 'company_id': self.warehouse_id.company_id.id, - 'picking_type': self.id, + 'picking_type_id': self.id, 'partner_selectable': True, } return self.env['qc.trigger'].sudo().create(qc_trigger) @@ -31,7 +30,9 @@ class StockPickingType(models.Model): res = super(StockPickingType, self).write(vals) if vals.get('name') or vals.get('warehouse_id'): qc_trigger_model = self.env['qc.trigger'].sudo() - qc_trigger = qc_trigger_model.search( - [('picking_type', '=', self.id)]) - qc_trigger.name = self.name + for rec in self: + qc_trigger = qc_trigger_model.search( + [('picking_type_id', '=', rec.id)]) + qc_trigger.name = rec.name + return res diff --git a/quality_control_stock/models/stock_production_lot.py b/quality_control_stock/models/stock_production_lot.py index 1db874dc0..1d74eb1e1 100644 --- a/quality_control_stock/models/stock_production_lot.py +++ b/quality_control_stock/models/stock_production_lot.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2014 Serv. Tec. Avanzados - Pedro M. Baeza # Copyright 2018 Simone Rubino - Agile Business Group # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). @@ -10,19 +9,20 @@ class StockProductionLot(models.Model): _inherit = 'stock.production.lot' @api.multi - @api.depends('qc_inspections', 'qc_inspections.state') + @api.depends('qc_inspections_ids', 'qc_inspections_ids.state') def _compute_count_inspections(self): for lot in self: - lot.created_inspections = len(lot.qc_inspections) + lot.created_inspections = len(lot.qc_inspections_ids) lot.passed_inspections = \ - len([x for x in lot.qc_inspections if x.state == 'success']) + len([x for x in lot.qc_inspections_ids + if x.state == 'success']) lot.failed_inspections = \ - len([x for x in lot.qc_inspections if x.state == 'failed']) + len([x for x in lot.qc_inspections_ids if x.state == 'failed']) lot.done_inspections = \ (lot.passed_inspections + lot.failed_inspections) - qc_inspections = fields.One2many( - comodel_name='qc.inspection', inverse_name='lot', copy=False, + qc_inspections_ids = fields.One2many( + comodel_name='qc.inspection', inverse_name='lot_id', copy=False, string='Inspections', help="Inspections related to this lot.") created_inspections = fields.Integer( compute="_compute_count_inspections", string="Created inspections") diff --git a/quality_control_stock/tests/__init__.py b/quality_control_stock/tests/__init__.py index f368a70ff..8adecedfb 100644 --- a/quality_control_stock/tests/__init__.py +++ b/quality_control_stock/tests/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from . import test_quality_control_stock diff --git a/quality_control_stock/tests/test_quality_control_stock.py b/quality_control_stock/tests/test_quality_control_stock.py index e8a6dff93..e3e8a9648 100644 --- a/quality_control_stock/tests/test_quality_control_stock.py +++ b/quality_control_stock/tests/test_quality_control_stock.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2015 Oihane Crucelaegui - AvanzOSC # Copyright 2018 Simone Rubino - Agile Business Group # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). @@ -14,7 +13,7 @@ class TestQualityControl(TransactionCase): self.inspection_model = self.env['qc.inspection'] self.qc_trigger_model = self.env['qc.trigger'] self.picking_type_model = self.env['stock.picking.type'] - self.product = self.env.ref('product.product_product_4') + self.product = self.env.ref('product.product_product_2') self.partner1 = self.env.ref('base.res_partner_2') self.partner2 = self.env.ref('base.res_partner_4') self.test = self.env.ref('quality_control.qc_test_1') @@ -29,7 +28,7 @@ class TestQualityControl(TransactionCase): 'inspection_lines': inspection_lines, }) self.trigger = self.qc_trigger_model.search( - [('picking_type', '=', self.picking_type.id)]) + [('picking_type_id', '=', self.picking_type.id)]) self.lot = self.env['stock.production.lot'].create({ 'name': 'Lot for tests', 'product_id': self.product.id, @@ -41,6 +40,7 @@ class TestQualityControl(TransactionCase): 'product_uom_qty': 2.0, 'location_id': self.picking_type.default_location_src_id.id, 'location_dest_id': self.location_dest.id, + 'quantity_done': 1.0 } self.picking1 = self.picking_model \ .with_context(default_picking_type_id=self.picking_type.id) \ @@ -52,15 +52,22 @@ class TestQualityControl(TransactionCase): }) self.picking1.action_confirm() self.picking1.force_assign() - self.picking1.do_prepare_partial() - for line in self.picking1.pack_operation_ids.filtered( + sequence = 10 + for line in self.picking1.move_lines.filtered( lambda r: r.product_id == self.product): line.write({ - 'pack_lot_ids': [(0, 0, { + 'move_line_ids': [(0, 0, { 'lot_id': self.lot.id, - 'qty': 2.0 - })] + 'product_uom_qty': 1.0, + 'qty_done': 1.0, + 'product_uom_id': line.product_uom.id, + 'product_id': line.product_id.id, + 'location_id': line.location_id.id, + 'location_dest_id': line.location_dest_id.id, + })], + 'sequence': sequence }) + sequence += 10 def test_inspection_create_for_product(self): self.product.qc_triggers = [( @@ -72,7 +79,7 @@ class TestQualityControl(TransactionCase): self.picking1.do_transfer() self.assertEqual(self.picking1.created_inspections, 1, 'Only one inspection must be created') - inspection = self.picking1.qc_inspections[:1] + inspection = self.picking1.qc_inspections_ids[:1] self.assertEqual(inspection.qty, 2.0) self.assertEqual(inspection.test, self.test, 'Wrong test picked when creating inspection.') @@ -91,7 +98,7 @@ class TestQualityControl(TransactionCase): self.picking1.do_transfer() self.assertEqual(self.picking1.created_inspections, 1, 'Only one inspection must be created') - self.assertEqual(self.picking1.qc_inspections[:1].test, self.test, + self.assertEqual(self.picking1.qc_inspections_ids[:1].test, self.test, 'Wrong test picked when creating inspection.') def test_inspection_create_for_category(self): @@ -104,7 +111,7 @@ class TestQualityControl(TransactionCase): self.picking1.do_transfer() self.assertEqual(self.picking1.created_inspections, 1, 'Only one inspection must be created') - self.assertEqual(self.picking1.qc_inspections[:1].test, self.test, + self.assertEqual(self.picking1.qc_inspections_ids[:1].test, self.test, 'Wrong test picked when creating inspection.') def test_inspection_create_for_product_partner(self): @@ -118,7 +125,7 @@ class TestQualityControl(TransactionCase): self.picking1.do_transfer() self.assertEqual(self.picking1.created_inspections, 1, 'Only one inspection must be created') - self.assertEqual(self.picking1.qc_inspections[:1].test, self.test, + self.assertEqual(self.picking1.qc_inspections_ids[:1].test, self.test, 'Wrong test picked when creating inspection.') def test_inspection_create_for_template_partner(self): @@ -132,7 +139,7 @@ class TestQualityControl(TransactionCase): self.picking1.do_transfer() self.assertEqual(self.picking1.created_inspections, 1, 'Only one inspection must be created') - self.assertEqual(self.picking1.qc_inspections[:1].test, self.test, + self.assertEqual(self.picking1.qc_inspections_ids[:1].test, self.test, 'Wrong test picked when creating inspection.') def test_inspection_create_for_category_partner(self): @@ -146,7 +153,7 @@ class TestQualityControl(TransactionCase): self.picking1.do_transfer() self.assertEqual(self.picking1.created_inspections, 1, 'Only one inspection must be created') - self.assertEqual(self.picking1.qc_inspections[:1].test, self.test, + self.assertEqual(self.picking1.qc_inspections_ids[:1].test, self.test, 'Wrong test picked when creating inspection.') def test_inspection_create_for_product_wrong_partner(self): @@ -201,11 +208,11 @@ class TestQualityControl(TransactionCase): self.picking1.do_transfer() self.assertEqual(self.picking1.created_inspections, 1, 'Only one inspection must be created') - self.assertEqual(self.picking1.qc_inspections[:1].test, self.test, + self.assertEqual(self.picking1.qc_inspections_ids[:1].test, self.test, 'Wrong test picked when creating inspection.') self.assertEqual(self.lot.created_inspections, 1, 'Only one inspection must be created') - self.assertEqual(self.lot.qc_inspections[:1].test, self.test, + self.assertEqual(self.lot.qc_inspections_ids[:1].test, self.test, 'Wrong test picked when creating inspection.') def test_picking_type(self): @@ -215,7 +222,7 @@ class TestQualityControl(TransactionCase): 'sequence_id': self.sequence.id }) trigger = self.qc_trigger_model.search( - [('picking_type', '=', picking_type.id)]) + [('picking_type_id', '=', picking_type.id)]) self.assertEqual(len(trigger), 1, 'One trigger must have been created.') self.assertEqual(trigger.name, picking_type.name, @@ -228,34 +235,37 @@ class TestQualityControl(TransactionCase): def test_qc_inspection_picking(self): self.inspection1.write({ + 'name': self.picking1.move_lines[:1]._name + "inspection", 'object_id': '%s,%d' % (self.picking1._name, self.picking1.id), }) - self.assertEquals(self.inspection1.picking, - self.picking1) + self.assertEqual(self.inspection1.picking_id, + self.picking1) def test_qc_inspection_stock_move(self): self.inspection1.write({ + 'name': self.picking1.move_lines[:1]._name + "inspection", 'object_id': '%s,%d' % (self.picking1.move_lines[:1]._name, self.picking1.move_lines[:1].id), }) self.inspection1.onchange_object_id() - self.assertEquals(self.inspection1.picking, - self.picking1) - self.assertEquals(self.inspection1.lot, - self.picking1.move_lines[:1].lot_ids[:1]) - self.assertEquals(self.inspection1.product, - self.picking1.move_lines[:1].product_id) - self.assertEquals(self.inspection1.qty, - self.picking1.move_lines[:1].product_qty) + self.assertEqual(self.inspection1.picking_id, + self.picking1) + self.assertEqual(self.inspection1.lot_id, + self.lot) + self.assertEqual(self.inspection1.product_id, + self.picking1.move_lines[:1].product_id) + self.assertEqual(self.inspection1.qty, + self.picking1.move_lines[:1].product_qty) def test_qc_inspection_lot(self): self.inspection1.write({ + 'name': self.picking1.move_lines[:1]._name + "inspection", 'object_id': '%s,%d' % (self.lot._name, self.lot.id), }) self.inspection1.onchange_object_id() - self.assertEquals(self.inspection1.lot, - self.lot) - self.assertEquals(self.inspection1.product, - self.lot.product_id) + self.assertEqual(self.inspection1.lot_id, + self.lot) + self.assertEqual(self.inspection1.product_id, + self.lot.product_id) diff --git a/quality_control_stock/views/qc_inspection_view.xml b/quality_control_stock/views/qc_inspection_view.xml index bf3a738af..e040e315b 100644 --- a/quality_control_stock/views/qc_inspection_view.xml +++ b/quality_control_stock/views/qc_inspection_view.xml @@ -7,9 +7,9 @@ qc.inspection - - - + + + @@ -19,9 +19,9 @@ qc.inspection - - - + + + @@ -31,18 +31,18 @@ qc.inspection - - - + + + + context="{'group_by': 'picking_id'}"/> + context="{'group_by': 'lot_id'}"/> @@ -52,9 +52,9 @@ qc.inspection.line - - - + + + @@ -64,9 +64,9 @@ qc.inspection.line - - - + + + Quality inspections from picking qc.inspection tree,form - [('picking', '=', active_id)] + [('picking_id', '=', active_id)] Quality inspection from picking done qc.inspection tree,form - [('picking', '=', active_id), ('state', 'not in', ['draft', 'waiting'])] + [('picking_id', '=', active_id), ('state', 'not in', ['draft', 'waiting'])] Quality inspection from picking passed qc.inspection tree,form - [('picking', '=', active_id), ('state', '=', 'success')] + [('picking_id', '=', active_id), ('state', '=', 'success')] Quality inspections from picking failed qc.inspection tree,form - [('picking', '=', active_id), ('state', '=', 'failed')] + [('picking_id', '=', active_id), ('state', '=', 'failed')] diff --git a/quality_control_stock/views/stock_production_lot_view.xml b/quality_control_stock/views/stock_production_lot_view.xml index eabd58106..2fe52a6d5 100644 --- a/quality_control_stock/views/stock_production_lot_view.xml +++ b/quality_control_stock/views/stock_production_lot_view.xml @@ -6,28 +6,28 @@ Quality inspections from lot qc.inspection tree,form - [('lot', '=', active_id)] + [('lot_id', '=', active_id)] Quality inspection from lot done qc.inspection tree,form - [('lot', '=', active_id), ('state', 'not in', ['draft', 'waiting'])] + [('lot_id', '=', active_id), ('state', 'not in', ['draft', 'waiting'])] Quality inspection from lot passed qc.inspection tree,form - [('lot', '=', active_id), ('state', '=', 'success')] + [('lot_id', '=', active_id), ('state', '=', 'success')] Quality inspections from lot failed qc.inspection tree,form - [('lot', '=', active_id), ('state', '=', 'failed')] + [('lot_id', '=', active_id), ('state', '=', 'failed')] From 712d542d91a7e65ef12c939d61e5962d1f22d10f Mon Sep 17 00:00:00 2001 From: mreficent Date: Mon, 12 Nov 2018 15:56:00 +0100 Subject: [PATCH 16/18] [FIX] stock_picking_type: assure api.multi in write --- quality_control_stock/models/stock_picking_type.py | 1 - 1 file changed, 1 deletion(-) diff --git a/quality_control_stock/models/stock_picking_type.py b/quality_control_stock/models/stock_picking_type.py index 382202b71..92aa9a35b 100644 --- a/quality_control_stock/models/stock_picking_type.py +++ b/quality_control_stock/models/stock_picking_type.py @@ -34,5 +34,4 @@ class StockPickingType(models.Model): qc_trigger = qc_trigger_model.search( [('picking_type_id', '=', rec.id)]) qc_trigger.name = rec.name - return res From cd4a02723d241b7525b4749a5914fa00e3059a91 Mon Sep 17 00:00:00 2001 From: mreficent Date: Wed, 14 Nov 2018 16:30:18 +0100 Subject: [PATCH 17/18] [FIX] quality_control_stock: singleton error --- quality_control_stock/models/stock_picking_type.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/quality_control_stock/models/stock_picking_type.py b/quality_control_stock/models/stock_picking_type.py index 92aa9a35b..131a83a01 100644 --- a/quality_control_stock/models/stock_picking_type.py +++ b/quality_control_stock/models/stock_picking_type.py @@ -31,7 +31,7 @@ class StockPickingType(models.Model): if vals.get('name') or vals.get('warehouse_id'): qc_trigger_model = self.env['qc.trigger'].sudo() for rec in self: - qc_trigger = qc_trigger_model.search( + qc_triggers = qc_trigger_model.search( [('picking_type_id', '=', rec.id)]) - qc_trigger.name = rec.name + qc_triggers.write({'name': rec.name}) return res From 76cb1fbfd797e33cda0aed84a3ea31ce3a0cb527 Mon Sep 17 00:00:00 2001 From: Jordi Ballester Alomar Date: Sun, 9 Dec 2018 17:26:34 +0100 Subject: [PATCH 18/18] [quality_control_stock][FIX] the stock user should be able to create quality control inspection without necessarily being quality control user. It is common that the person doing the picking is not going to be the same as the one doing the inspection. So when a stock user create the transfer, the system will create the necessary qc inspections, regardless if the user has permissions to process them. --- quality_control_stock/__manifest__.py | 1 + .../security/ir.model.access.csv | 8 +++++++ .../tests/test_quality_control_stock.py | 24 ++++++++++++++++++- 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 quality_control_stock/security/ir.model.access.csv diff --git a/quality_control_stock/__manifest__.py b/quality_control_stock/__manifest__.py index f95766f6f..3d60bb1c3 100644 --- a/quality_control_stock/__manifest__.py +++ b/quality_control_stock/__manifest__.py @@ -20,6 +20,7 @@ "stock", ], "data": [ + "security/ir.model.access.csv", "data/quality_control_stock_data.xml", "views/qc_inspection_view.xml", "views/stock_picking_view.xml", diff --git a/quality_control_stock/security/ir.model.access.csv b/quality_control_stock/security/ir.model.access.csv new file mode 100644 index 000000000..96a249167 --- /dev/null +++ b/quality_control_stock/security/ir.model.access.csv @@ -0,0 +1,8 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_user_qc_inspection_stock_user,qc_inspection stock user,quality_control.model_qc_inspection,stock.group_stock_user,1,1,1,0 +access_user_qc_inspection_line_stock_user,qc_inspection_line stock user,quality_control.model_qc_inspection_line,stock.group_stock_user,1,1,1,0 +access_user_qc_test_stock_user,qc_test stock_user,quality_control.model_qc_test,stock.group_stock_user,1,0,0,0 +access_user_qc_test_question_stock_user,qc_test_question stock user,quality_control.model_qc_test_question,stock.group_stock_user,1,0,0,0 +access_user_qc_test_question_value_stock_user,qc_test_question_value_stock_user,quality_control.model_qc_test_question_value,stock.group_stock_user,1,0,0,0 +access_manager_qc_trigger_stock_user,qc_trigger stock user,quality_control.model_qc_trigger,stock.group_stock_user,1,0,0,0 +access_manager_qc_trigger_product_category_line_stock_user,qc_trigger product_category line stock user,quality_control.model_qc_trigger_product_category_line,stock.group_stock_user,1,0,0,0 diff --git a/quality_control_stock/tests/test_quality_control_stock.py b/quality_control_stock/tests/test_quality_control_stock.py index e3e8a9648..88fdb091a 100644 --- a/quality_control_stock/tests/test_quality_control_stock.py +++ b/quality_control_stock/tests/test_quality_control_stock.py @@ -9,6 +9,8 @@ class TestQualityControl(TransactionCase): def setUp(self): super(TestQualityControl, self).setUp() + + self.users_model = self.env['res.users'] self.picking_model = self.env['stock.picking'] self.inspection_model = self.env['qc.inspection'] self.qc_trigger_model = self.env['qc.trigger'] @@ -33,6 +35,11 @@ class TestQualityControl(TransactionCase): 'name': 'Lot for tests', 'product_id': self.product.id, }) + self.group_stock_user = self.env.ref('stock.group_stock_user') + self.company1 = self.env.ref('base.main_company') + self.user1_id = self._create_user( + 'user_1', [self.group_stock_user], self.company1) + move_vals = { 'name': self.product.name, 'product_id': self.product.id, @@ -42,7 +49,7 @@ class TestQualityControl(TransactionCase): 'location_dest_id': self.location_dest.id, 'quantity_done': 1.0 } - self.picking1 = self.picking_model \ + self.picking1 = self.picking_model.sudo(self.user1_id) \ .with_context(default_picking_type_id=self.picking_type.id) \ .create({ 'partner_id': self.partner1.id, @@ -69,6 +76,21 @@ class TestQualityControl(TransactionCase): }) sequence += 10 + def _create_user(self, login, groups, company): + """ Create a user.""" + group_ids = [group.id for group in groups] + user = self.users_model.with_context({'no_reset_password': True}).\ + create({ + 'name': 'Sale User', + 'login': login, + 'password': 'test', + 'email': 'test@yourcompany.com', + 'company_id': company.id, + 'company_ids': [(4, company.id)], + 'groups_id': [(6, 0, group_ids)] + }) + return user.id + def test_inspection_create_for_product(self): self.product.qc_triggers = [( 0, 0, {