From 54dcb7fc18a1df170f32a6a4aa2b0db5f1c03673 Mon Sep 17 00:00:00 2001 From: Guillem Barba Date: Wed, 25 Apr 2012 17:15:22 +0200 Subject: [PATCH] [ADD] nan_prodlot_quality_control_production: new module (with Tests) --- __init__.py | 32 +++ __openerp__.py | 60 +++++ prodlot_quality_control_production_demo.xml | 248 ++++++++++++++++++++ quality_control_data.xml | 8 + stock.py | 95 ++++++++ test/prodlot_qc_production_w_1_test.yml | 109 +++++++++ test/prodlot_qc_production_w_2_tests.yml | 140 +++++++++++ test/prodlot_qc_production_wo_tests.yml | 95 ++++++++ 8 files changed, 787 insertions(+) create mode 100644 __init__.py create mode 100644 __openerp__.py create mode 100644 prodlot_quality_control_production_demo.xml create mode 100644 quality_control_data.xml create mode 100644 stock.py create mode 100644 test/prodlot_qc_production_w_1_test.yml create mode 100644 test/prodlot_qc_production_w_2_tests.yml create mode 100644 test/prodlot_qc_production_wo_tests.yml diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..f5108dd --- /dev/null +++ b/__init__.py @@ -0,0 +1,32 @@ +############################################################################## +# +# Copyright (c) 2010-2012 NaN Projectes de Programari Lliure, S.L. +# All Rights Reserved. +# http://www.NaN-tic.com +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## + +import stock + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/__openerp__.py b/__openerp__.py new file mode 100644 index 0000000..12ec2e7 --- /dev/null +++ b/__openerp__.py @@ -0,0 +1,60 @@ +############################################################################## +# +# Copyright (c) 2010-2012 NaN Projectes de Programari Lliure, S.L. +# All Rights Reserved. +# http://www.NaN-tic.com +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## + +{ + "name": "Production Lot Quality Control - Production", + "version": "1.0", + "author": "NaN Projectes de Programari Lliure S.L.", + "category": "Generic Modules/Quality Control", + "website": "http://www.nan-tic.com", + "description": """ + This module adds quality control to Production Lots on production (in + produced Lots). + """, + "depends": [ + 'nan_prodlot_quality_control', + 'mrp', + ], + "init_xml": [], + "update_xml": [ + 'quality_control_data.xml', + ], + "demo_xml": [ + 'prodlot_quality_control_production_demo.xml', + ], + "test": [ + 'test/prodlot_qc_production_wo_tests.yml', + 'test/prodlot_qc_production_w_1_test.yml', + 'test/prodlot_qc_production_w_2_tests.yml', + ], + "active": False, + "installable": True, +} + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/prodlot_quality_control_production_demo.xml b/prodlot_quality_control_production_demo.xml new file mode 100644 index 0000000..81f60a4 --- /dev/null +++ b/prodlot_quality_control_production_demo.xml @@ -0,0 +1,248 @@ + + + + + + Yes + + + + + No + + + + + + Simple Proof 2 + qualitative + + + + + + + Generic Template for Produced Lots + generic + + + + + + + + + qualitative + + + + + + Specific Template for Produced Lots + related + + + + + + + + + qualitative + + + + + + + + + Product without Quality Control for Produced Lots + product + + make_to_stock + produce + standard + + + + + + Product with One QC Test for Produced Lots + product + + make_to_stock + produce + standard + + + + + + + + generic + + + + + Product with Two QC Test for Produced Lots + product + + make_to_stock + produce + standard + + + + + + + + generic + + + + + + + related + + + + + + + + Component 1 + consu + + make_to_stock + buy + standard + + + + + Component 2 + consu + + make_to_stock + buy + standard + + + + + + + + + Product without Quality Control + + + + normal + + + + + + + + Component 1 + + + + normal + + + + + + + + Component 2 + + + + normal + + + + + + + + Product with One QC Test + + + + normal + + + + + + + + Component 1 + + + + normal + + + + + + + + Component 2 + + + + normal + + + + + + + + Product with Two QC Test + + + + normal + + + + + + + + Component 1 + + + + normal + + + + + + + + Component 2 + + + + normal + + + + + + + diff --git a/quality_control_data.xml b/quality_control_data.xml new file mode 100644 index 0000000..9e885cd --- /dev/null +++ b/quality_control_data.xml @@ -0,0 +1,8 @@ + + + + + Production + + + diff --git a/stock.py b/stock.py new file mode 100644 index 0000000..54b5787 --- /dev/null +++ b/stock.py @@ -0,0 +1,95 @@ +############################################################################## +# +# Copyright (c) 2010-2012 NaN Projectes de Programari Lliure, S.L. +# All Rights Reserved. +# http://www.NaN-tic.com +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## + +from osv import osv + + +class stock_move(osv.osv): + _inherit = 'stock.move' + + # stock.move + def create(self, cr, uid, vals, context=None): + if context is None: + context = {} + + move_id = super(stock_move, self).create(cr, uid, vals, context) + + if 'production' in context.get('no_create_trigger_test', []): + return move_id + + production_trigger_id = self.pool.get('qc.trigger').search(cr, uid, [ + ('name', '=', 'Production'), + ], context=context) + if not production_trigger_id: + return move_id + + move = self.browse(cr, uid, move_id, context) + if not move.production_id or not move.prodlot_id: + return move_id + + self.pool.get('stock.production.lot').create_qc_test_triggers(cr, uid, + move.prodlot_id, production_trigger_id[0], True, context) + return move_id + + # stock.move + def write(self, cr, uid, ids, vals, context=None): + if context is None: + context = {} + + prodlot_proxy = self.pool.get('stock.production.lot') + + res = super(stock_move, self).write(cr, uid, ids, vals, context) + # we will try to create 'test triggers' only when Lot and/or Production + # is setted to Stock Move + if not 'prodlot_id' in vals and not 'production_id' in vals: + return res + if 'production' in context.get('no_create_trigger_test', []): + return res + production_trigger_id = self.pool.get('qc.trigger').search(cr, uid, [ + ('name', '=', 'Production'), + ], context=context) + if not production_trigger_id: + return res + + production_trigger_id = production_trigger_id[0] + for move in self.browse(cr, uid, ids, context): + if not move.production_id or not move.prodlot_id: + continue + for test_trigger in move.prodlot_id.qc_test_trigger_ids: + if test_trigger.trigger_id.id == production_trigger_id: + break + else: + # If it comes here, the previous 'FOR' has not break => + # no test trigger for 'input_trigger_id' + prodlot_proxy.create_qc_test_triggers(cr, uid, move.prodlot_id, + production_trigger_id, True, context) + return res +stock_move() + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/test/prodlot_qc_production_w_1_test.yml b/test/prodlot_qc_production_w_1_test.yml new file mode 100644 index 0000000..3feca0a --- /dev/null +++ b/test/prodlot_qc_production_w_1_test.yml @@ -0,0 +1,109 @@ +- + ------ Prodlot Quality Control on Production with 1 Test ------ +- + In order to test functionality of set Quality Control Tests to Production + Lots in Production... + +- + I create the Production Order for Product with 1 Test Trigger +- + !record {model: mrp.production, id: production_w_1test}: + product_id: product_w_1qctest0 + product_uom: product.product_uom_unit + product_qty: 1.0 + bom_id: mrp_bom_product_w_1qctest + location_src_id: stock.stock_location_stock + location_dest_id: stock.stock_location_stock + +- + I will Confirm the production +- + !workflow {model: mrp.production, action: button_confirm, ref: production_w_1test} + +- + I will force de availability of Picking lines +- + !function {model: stock.picking, name: force_assign}: + - eval: "[obj(ref('production_w_1test')).picking_id.id]" + model: mrp.production + +- + Checking the internal Picking is in 'done' state +- + !python {model: mrp.production}: | + production = self.browse(cr, uid, ref('production_w_1test'), context) + picking = production.picking_id + assert picking.state == 'done', "The picking of Production is not in " \ + "the expected 'Done' state! It's state is '%s'" % picking.state + +- + Checking the Production is in 'ready' state +- + !assert {model: mrp.production, id: production_w_1test, string: The production with 1 QC Test is not in the expected 'Ready' state!}: + - state == 'ready' + +- + I will Start the production +- + !workflow {model: mrp.production, action: button_produce, ref: production_w_1test} + +- + I will finalize the Production using the function 'action_produce' like + User's wizard +- + !function {model: mrp.production, name: action_produce}: + - eval: "ref('production_w_1test')" + - 1.0 + - 'consume_produce' + +- + Checking the Production is in 'Done' state +- + !assert {model: mrp.production, id: production_w_1test, string: The production is not in the expected 'Done' state!}: + - state == 'done' + +- + Checking the 'Created Moves' of Production with 1 QC Test has + assigned Production lot and they are Inactive and in 'Pending Test' state +- + !assert {model: mrp.production, id: production_w_1test, string: The produced Lot with a Quality Test is, unexpectly, not in 'Pending Test' state or is 'Active'!}: + - len(move_created_ids2) == 1 + - move_created_ids2[0].prodlot_id.state == 'pending_test' + - move_created_ids2[0].prodlot_id.active == False + +- + Filling up the current Quality Test with valid data and I will confirm and + aprove it +- + !python {model: mrp.production}: | + import netsvc + + test_line_proxy = self.pool.get('qc.test.line') + wf_service = netsvc.LocalService("workflow") + + production = self.browse(cr, uid, ref('production_w_1test'), context) + curr_test = production.move_created_ids2[0].prodlot_id.current_qc_test_id + test_line_proxy.write(cr, uid, [ + curr_test.test_line_ids[0].id, + ], { + 'actual_value_ql': ref('qc_posible_value_yes0'), + }, context) + + wf_service.trg_validate(uid, 'qc.test', curr_test.id, + 'confirm', cr) + wf_service.trg_validate(uid, 'qc.test', curr_test.id, + 'approve', cr) + +- + Checking the produced Production Lot is in 'Valid' state and is active +- + !assert {model: mrp.production, id: production_w_1test, string: The produced Lot with a Quality Test is, unexpectly, not in 'Valid' state or is not 'Active'!}: + - move_created_ids2[0].prodlot_id.state == 'valid' + - move_created_ids2[0].prodlot_id.active == True + +- + ------ Prodlot Quality Control on Production with 1 Test END OK ------ +- + !python {model: stock.picking}: | + print "THE END" + diff --git a/test/prodlot_qc_production_w_2_tests.yml b/test/prodlot_qc_production_w_2_tests.yml new file mode 100644 index 0000000..8487eb5 --- /dev/null +++ b/test/prodlot_qc_production_w_2_tests.yml @@ -0,0 +1,140 @@ +- + ------ Prodlot Quality Control on Production with 1 Test ------ +- + In order to test functionality of set Quality Control Tests to Production + Lots in Production... + +- + I create the Production Order for Product with 2 Test Trigger +- + !record {model: mrp.production, id: production_w_2tests}: + product_id: product_w_2qctest0 + product_uom: product.product_uom_unit + product_qty: 1.0 + bom_id: mrp_bom_product_w_2qctest + location_src_id: stock.stock_location_stock + location_dest_id: stock.stock_location_stock + +- + I will Confirm the production +- + !workflow {model: mrp.production, action: button_confirm, ref: production_w_2tests} + +- + I will force de availability of Picking lines +- + !function {model: stock.picking, name: force_assign}: + - eval: "[obj(ref('production_w_2tests')).picking_id.id]" + model: mrp.production + +- + Checking the internal Picking is in 'done' state +- + !python {model: mrp.production}: | + production = self.browse(cr, uid, ref('production_w_2tests'), context) + picking = production.picking_id + assert picking.state == 'done', "The picking of Production is not in " \ + "the expected 'Done' state! It's state is '%s'" % picking.state + +- + Checking the Production is in 'ready' state +- + !assert {model: mrp.production, id: production_w_2tests, string: The production with 2 QC Test is not in the expected 'Ready' state!}: + - state == 'ready' + +- + I will Start the production +- + !workflow {model: mrp.production, action: button_produce, ref: production_w_2tests} + +- + I will finalize the Production using the function 'action_produce' like + User's wizard +- + !function {model: mrp.production, name: action_produce}: + - eval: "ref('production_w_2tests')" + - 1.0 + - 'consume_produce' + +- + Checking the Production is in 'Done' state +- + !assert {model: mrp.production, id: production_w_2tests, string: The production is not in the expected 'Done' state!}: + - state == 'done' + +- + Checking the 'Created Moves' of Production with 2 QC Test has + assigned Production lot and they are Inactive and in 'Pending Test' state +- + !assert {model: mrp.production, id: production_w_2tests, string: The produced Lot with two Quality Test is, unexpectly, not in 'Pending Test' state or is 'Active'!}: + - len(move_created_ids2) == 1 + - move_created_ids2[0].prodlot_id.state == 'pending_test' + - move_created_ids2[0].prodlot_id.active == False + +- + Filling up the current Quality Test with valid data and I will confirm and + aprove it +- + !python {model: mrp.production}: | + import netsvc + + test_line_proxy = self.pool.get('qc.test.line') + wf_service = netsvc.LocalService("workflow") + + production = self.browse(cr, uid, ref('production_w_2tests'), context) + curr_test = production.move_created_ids2[0].prodlot_id.current_qc_test_id + test_line_proxy.write(cr, uid, [ + curr_test.test_line_ids[0].id, + ], { + 'actual_value_ql': ref('qc_posible_value_yes0'), + }, context) + + wf_service.trg_validate(uid, 'qc.test', curr_test.id, + 'confirm', cr) + wf_service.trg_validate(uid, 'qc.test', curr_test.id, + 'approve', cr) + +- + Checking the produced Production Lot remains in 'Pending Test' state and is + inactive +- + !assert {model: mrp.production, id: production_w_2tests, string: The produced Lot with a Quality Test is, unexpectly, not in 'Pending Test' state or is 'Active'!}: + - move_created_ids2[0].prodlot_id.state == 'pending_test' + - move_created_ids2[0].prodlot_id.active == False + +- + Filling up the current Quality Test with valid data and I will confirm and + aprove it +- + !python {model: mrp.production}: | + import netsvc + + test_line_proxy = self.pool.get('qc.test.line') + wf_service = netsvc.LocalService("workflow") + + production = self.browse(cr, uid, ref('production_w_2tests'), context) + curr_test = production.move_created_ids2[0].prodlot_id.current_qc_test_id + test_line_proxy.write(cr, uid, [ + curr_test.test_line_ids[0].id, + ], { + 'actual_value_ql': ref('qc_posible_value_yes0'), + }, context) + + wf_service.trg_validate(uid, 'qc.test', curr_test.id, + 'confirm', cr) + wf_service.trg_validate(uid, 'qc.test', curr_test.id, + 'approve', cr) + +- + Checking the produced Production Lot remains in 'Valid' state and is active +- + !assert {model: mrp.production, id: production_w_2tests, string: The produced Lot with a Quality Test is, unexpectly, not in 'Valid' state or is not 'Active'!}: + - move_created_ids2[0].prodlot_id.state == 'valid' + - move_created_ids2[0].prodlot_id.active == True + +- + ------ Prodlot Quality Control on Production with 1 Test END OK ------ +- + !python {model: stock.picking}: | + print "THE END" + diff --git a/test/prodlot_qc_production_wo_tests.yml b/test/prodlot_qc_production_wo_tests.yml new file mode 100644 index 0000000..6b7dbd7 --- /dev/null +++ b/test/prodlot_qc_production_wo_tests.yml @@ -0,0 +1,95 @@ +- + ------ Prodlot Quality Control on Production without Tests ------ +- + In order to test functionality of set Quality Control Tests to Production + Lots in Production... + +- + I create the Production Order for Product without Quality Control +- + !record {model: mrp.production, id: production_wo_qc}: + product_id: product_wo_qc0 + product_uom: product.product_uom_unit + product_qty: 1.0 + bom_id: mrp_bom_product_wo_qc + location_src_id: stock.stock_location_stock + location_dest_id: stock.stock_location_stock + +- + I will Confirm the production +- + !workflow {model: mrp.production, action: button_confirm, ref: production_wo_qc} + +- + Checking the Production is in 'Confirmed' state +- + !assert {model: mrp.production, id: production_wo_qc, string: The production without Quality Control is not in the expected 'Confirmed' state!}: + - state == 'confirmed' + +- + I will force de availability of Picking lines +- + !function {model: stock.picking, name: force_assign}: + - eval: "[obj(ref('production_wo_qc')).picking_id.id]" + model: mrp.production + +- + Checking the internal Picking is in 'done' state +- + !python {model: mrp.production}: | + production = self.browse(cr, uid, ref('production_wo_qc'), context) + picking = production.picking_id + assert picking.state == 'done', "The picking of Production is not in " \ + "the expected 'Done' state! It's state is '%s'" % picking.state + +- + Checking the Production is in 'ready' state +- + !assert {model: mrp.production, id: production_wo_qc, string: The production without Quality Control is not in the expected 'Ready' state!}: + - state == 'ready' + +- + I will Start the production +- + !workflow {model: mrp.production, action: button_produce, ref: production_wo_qc} + +- + I will finalize the Production using the function 'action_produce' like + User's wizard +- + !function {model: mrp.production, name: action_produce}: + - eval: "ref('production_wo_qc')" + - 1.0 + - 'consume_produce' + +- + Checking the Production is in 'Done' state +- + !assert {model: mrp.production, id: production_wo_qc, string: The production is not in the expected 'Done' state!}: + - state == 'done' + +- + Checking the 'Created Moves' of Production without Quality Control has + assigned Production lot and they are Active and in 'Valid' state +- + !python {model: mrp.production}: | + production = self.browse(cr, uid, ref('production_wo_qc'), context) + for created_move in production.move_created_ids2: + assert created_move.prodlot_id, "The Created Move %s doesn't have " \ + "Production Lot (%s)" % (created_move.name, + str(created_move.prodlot_id)) + + assert created_move.prodlot_id.active, \ + "The Lot of Created Move %s is not active" % created_move.name + + assert created_move.prodlot_id.state == 'valid', \ + "The Lot of Created Move %s is not in the expected 'Valid' " \ + "state: %s" % (created_move.name, created_move.state) + +- + ------ Prodlot Quality Control on Production without Tests END OK ------ +- + !python {model: stock.picking}: | + print "THE END" + + \ No newline at end of file