From 4e3baedd477be41e672f041c8519018986b6a88a Mon Sep 17 00:00:00 2001 From: Cyril Gaudin Date: Tue, 23 Aug 2016 16:21:58 +0200 Subject: [PATCH] crm_rma_stock_location: Migration V9 --- crm_rma_stock_location/README.rst | 19 +- crm_rma_stock_location/__init__.py | 21 -- crm_rma_stock_location/__openerp__.py | 34 +-- .../demo/stock_inventory.xml | 50 +++-- .../demo/stock_location.xml | 60 +++--- crm_rma_stock_location/init_hooks.py | 38 ++-- crm_rma_stock_location/models/__init__.py | 24 --- .../models/product_product.py | 137 +++++-------- .../models/product_template.py | 71 +++---- .../models/stock_warehouse.py | 86 +++----- crm_rma_stock_location/tests/__init__.py | 20 +- .../tests/test_crm_rma_stock_location.py | 22 +- .../tests/test_make_picking_from_picking.py | 37 +--- .../tests/test_rma_stock.py | 194 ++++++++++++++++++ crm_rma_stock_location/views/crm_claim.xml | 33 ++- .../views/product_product.xml | 82 ++++---- .../views/product_template.xml | 42 ++-- .../views/stock_picking.xml | 56 +++-- .../views/stock_warehouse.xml | 28 ++- crm_rma_stock_location/wizards/__init__.py | 22 +- .../wizards/claim_make_picking.py | 26 +-- .../claim_make_picking_from_picking.py | 48 ++--- .../claim_make_picking_from_picking_view.xml | 116 +++++------ .../wizards/claim_make_picking_view.xml | 26 ++- 24 files changed, 620 insertions(+), 672 deletions(-) create mode 100644 crm_rma_stock_location/tests/test_rma_stock.py diff --git a/crm_rma_stock_location/README.rst b/crm_rma_stock_location/README.rst index d4e8a113..5c5fe154 100644 --- a/crm_rma_stock_location/README.rst +++ b/crm_rma_stock_location/README.rst @@ -50,7 +50,7 @@ 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/8.0/145 + :target: https://runbot.odoo-community.org/runbot/145/9.0 For further information, please visit: @@ -64,21 +64,26 @@ Known issues / Roadmap 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 `_. - +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. Credits ======= +Images +------ + +* Odoo Community Association: `Icon `_. + Contributors ------------ * Guewen Baconnier * Yanina Aular * Osval Reyes +* Cyril Gaudin Maintainer ---------- @@ -93,4 +98,4 @@ 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. +To contribute to this module, please visit https://odoo-community.org. diff --git a/crm_rma_stock_location/__init__.py b/crm_rma_stock_location/__init__.py index d59c3ae6..c14bd409 100644 --- a/crm_rma_stock_location/__init__.py +++ b/crm_rma_stock_location/__init__.py @@ -1,25 +1,4 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# Copyright 2015 Vauxoo -# Copyright 2014 Camptocamp SA -# Author: Guewen Baconnier, -# Osval Reyes -# -# 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 . -# -############################################################################## from . import models from . import wizards diff --git a/crm_rma_stock_location/__openerp__.py b/crm_rma_stock_location/__openerp__.py index 3f98a80b..eee04a88 100644 --- a/crm_rma_stock_location/__openerp__.py +++ b/crm_rma_stock_location/__openerp__.py @@ -1,32 +1,18 @@ # -*- coding: utf-8 -*- -############################################################################## +# Author: Guewen Baconnier, +# Emmanuel Samyn, Raphaël Valyi, Sébastien Beau, +# Joel Grand-Guillaume, +# Yanina Aular, Osval Reyes # -# Copyright 2015 Vauxoo -# Copyright 2013-2014 Camptocamp SA -# Copyright 2009-2013 Akretion, -# Author: Guewen Baconnier, -# Emmanuel Samyn, Raphaël Valyi, Sébastien Beau, -# Joel Grand-Guillaume, -# Yanina Aular, Osval Reyes -# -# 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 . -# -############################################################################## +# © 2009-2013 Akretion +# © 2014-2016 Camptocamp SA +# © 2015 Vauxoo +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + { 'name': 'RMA Stock Location', - 'version': '8.0.1.0.0', + 'version': '9.0.1.0.0', 'author': "Akretion,Vauxoo,Camptocamp,Odoo Community Association (OCA)", 'maintainer': 'Camptocamp', 'website': 'http://www.camptocamp.com,http://www.vauxoo.com', diff --git a/crm_rma_stock_location/demo/stock_inventory.xml b/crm_rma_stock_location/demo/stock_inventory.xml index 729a9d35..3769e875 100644 --- a/crm_rma_stock_location/demo/stock_inventory.xml +++ b/crm_rma_stock_location/demo/stock_inventory.xml @@ -1,28 +1,26 @@ - - - - Demo Stock Move: Customer > RMA - - 1 - 1000 - - 1 - - - - - - Demo Stock Move: RMA > Loss - - 1 - 1000 - - 1 - - - - - - + + + Demo Stock Move: Customer > RMA + + 1 + 1000 + + 1 + + + + + + Demo Stock Move: RMA > Loss + + 1 + 1000 + + 1 + + + + + diff --git a/crm_rma_stock_location/demo/stock_location.xml b/crm_rma_stock_location/demo/stock_location.xml index 19d2ded1..8f5bfdc6 100644 --- a/crm_rma_stock_location/demo/stock_location.xml +++ b/crm_rma_stock_location/demo/stock_location.xml @@ -1,37 +1,33 @@ - - + + + RMA Demo + internal + - - RMA Demo - internal - + + + - - - + + RMA - Box A + + internal + + + RMA - Box B + + internal + - - RMA - Box A - - internal - - - RMA - Box B - - internal - - - - Socket - - 70.0 - 100.0 - product - - - - - - + + Socket + + 70.0 + 100.0 + product + + + + diff --git a/crm_rma_stock_location/init_hooks.py b/crm_rma_stock_location/init_hooks.py index 9b97870c..34fa3e92 100644 --- a/crm_rma_stock_location/init_hooks.py +++ b/crm_rma_stock_location/init_hooks.py @@ -1,31 +1,17 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# Copyright 2015 Vauxoo -# Copyright 2014 Camptocamp SA -# Author: Guewen Baconnier, -# Osval Reyes -# -# 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 . -# -############################################################################## +# © 2015 Vauxoo +# © 2014-2016 Camptocamp SA +# Author: Guewen Baconnier, +# Osval Reyes +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + from openerp import SUPERUSER_ID +from openerp.api import Environment def post_init_hook(cr, registry): - stock_wh = registry['stock.warehouse'] - for wh_id in stock_wh.browse(cr, SUPERUSER_ID, - stock_wh.search(cr, SUPERUSER_ID, [])): - vals = stock_wh.create_locations_rma(cr, SUPERUSER_ID, wh_id) - stock_wh.write(cr, SUPERUSER_ID, wh_id.id, vals) + with Environment.manage(): + env = Environment(cr, SUPERUSER_ID, {}) + + warehouses = env['stock.warehouse'].search([]) + warehouses.create_locations_rma() diff --git a/crm_rma_stock_location/models/__init__.py b/crm_rma_stock_location/models/__init__.py index cbce7ada..8c3195b0 100644 --- a/crm_rma_stock_location/models/__init__.py +++ b/crm_rma_stock_location/models/__init__.py @@ -1,28 +1,4 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# Copyright 2015 Vauxoo -# Copyright 2013-2014 Camptocamp SA -# Copyright 2009-2013 Akretion, -# Author: Guewen Baconnier, -# Emmanuel Samyn, Raphaël Valyi, Sébastien Beau, -# Joel Grand-Guillaume, -# Osval Reyes -# -# 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 . -# -############################################################################## from . import product_product from . import product_template diff --git a/crm_rma_stock_location/models/product_product.py b/crm_rma_stock_location/models/product_product.py index 719606cf..04536852 100644 --- a/crm_rma_stock_location/models/product_product.py +++ b/crm_rma_stock_location/models/product_product.py @@ -1,27 +1,9 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# Author: Guewen Baconnier -# Copyright 2014 Camptocamp SA -# -# 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 . -# -############################################################################## +# © 2014-2016 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from openerp import _, api, fields, models +from openerp import api, fields, models import openerp.addons.decimal_precision as dp -from openerp.tools.float_utils import float_round from openerp.tools.safe_eval import safe_eval as eval @@ -30,16 +12,18 @@ class ProductProduct(models.Model): _inherit = 'product.product' rma_qty_available = fields.Float( - compute='_rma_product_available', + compute='_compute_rma_product_quantities', digits_compute=dp.get_precision('Product Unit of Measure'), search='_search_rma_product_quantity', - string=_('RMA Quantity On Hand')) + string='RMA Quantity On Hand' + ) rma_virtual_available = fields.Float( - compute='_rma_product_available', + compute='_compute_rma_product_quantities', digits_compute=dp.get_precision('Product Unit of Measure'), search='_search_rma_product_quantity', - string=_('RMA Forecasted Quantity')) + string='RMA Forecasted Quantity' + ) def _search_rma_product_quantity(self, operator, value): res = [] @@ -64,69 +48,48 @@ class ProductProduct(models.Model): res.append(('id', 'in', ids)) return res - @api.multi - def _rma_product_available(self): + @api.depends() + def _compute_rma_product_quantities(self): + """ Compute both rma_qty_available and rma_virtual_available values + by calling product_product._product_available with RMA locations + in context. """ - Finds the incoming and outgoing quantity of product for the RMA - locations. - """ - context = self.env.context - warehouse_id = context.get('warehouse_id') - ctx = context.copy() - location_ids = set() + warehouse_model = self.env['stock.warehouse'] + + locations = self.env['stock.location'] + + warehouse_id = self.env.context.get('warehouse_id') + if warehouse_id: + warehouse = warehouse_model.browse(warehouse_id) + if warehouse.lot_rma_id: + locations |= warehouse.lot_rma_id + + else: + warehouses = warehouse_model.search([('lot_rma_id', '!=', False)]) + locations |= warehouses.mapped('lot_rma_id') + + if locations: + result = self.with_context( + # Sorted by parent_left to avoid a little Odoo bug + # in tests environnement + # see https://github.com/odoo/odoo/pull/11996 + location=locations.sorted( + lambda l: l.parent_left + ).mapped('id'), + )._product_available() + + else: + result = {} + for product in self: - if warehouse_id and warehouse_id.lot_rma_id: - location_ids.add(warehouse_id.lot_rma_id.id) - else: - warehouse_ids = self.env['stock.warehouse'].search([]) - if not warehouse_ids: - return - for warehouse_id in warehouse_ids: - if warehouse_id.lot_rma_id: - location_ids.add(warehouse_id.lot_rma_id.id) + try: + product_qties = result[product.id] + except KeyError: + product.rma_qty_available = 0 + product.rma_virtual_available = 0 - if not location_ids: - return - ctx['location'] = list(location_ids) - - domain_products = [('product_id', 'in', [product.id])] - domain_quant, domain_move_in, domain_move_out = \ - product.with_context(ctx)._get_domain_locations() - domain_move_in += product.with_context(ctx)._get_domain_dates() + \ - [('state', 'not in', ('done', 'cancel', 'draft'))] + \ - domain_products - domain_move_out += product.with_context(ctx).\ - _get_domain_dates() + \ - [('state', 'not in', ('done', 'cancel', 'draft'))] + \ - domain_products - domain_quant += domain_products - moves_in = [] - moves_out = [] - lot_id = context.get('lot_id') - if lot_id: - domain_quant.append(('lot_id', '=', lot_id)) else: - moves_in = self.env['stock.move'].\ - with_context(ctx).read_group(domain_move_in, - ['product_id', 'product_qty'], - ['product_id']) - moves_out = self.env['stock.move'].\ - with_context(ctx).read_group(domain_move_out, - ['product_id', 'product_qty'], - ['product_id']) - quants = self.env['stock.quant'].with_context(ctx).read_group( - domain_quant, ['product_id', 'qty'], ['product_id']) - quants = dict([(item.get('product_id')[0], - item.get('qty')) for item in quants]) - moves_in = dict([(item.get('product_id')[0], - item.get('product_qty')) for item in moves_in]) - moves_out = dict([(item.get('product_id')[0], - item.get('product_qty')) for item in moves_out]) - product.rma_qty_available = \ - float_round(quants.get(product.id, 0.0), - precision_rounding=product.uom_id.rounding) - product.rma_virtual_available = \ - float_round(quants.get(product.id, 0.0) + - moves_in.get(product.id, 0.0) - - moves_out.get(product.id, 0.0), - precision_rounding=product.uom_id.rounding) + product.rma_qty_available = product_qties['qty_available'] + product.rma_virtual_available = product_qties[ + 'virtual_available' + ] diff --git a/crm_rma_stock_location/models/product_template.py b/crm_rma_stock_location/models/product_template.py index 5b922747..0de464e9 100644 --- a/crm_rma_stock_location/models/product_template.py +++ b/crm_rma_stock_location/models/product_template.py @@ -1,50 +1,41 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# Copyright 2015 Vauxoo -# Copyright 2014 Camptocamp SA -# Author: Guewen Baconnier, -# Osval Reyes -# -# 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 . -# -############################################################################## +# © 2015 Vauxoo +# © 2014 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from openerp import _, api, fields, models + +from openerp import api, fields, models import openerp.addons.decimal_precision as dp class ProductTemplate(models.Model): - _inherit = 'product.template' - rma_qty_available = fields.Float(compute='_rma_template_available', - digits_compute=dp. - get_precision('Product Unit ' - 'of Measure'), - string=_('RMA Quantity On Hand')) + rma_qty_available = fields.Float( + compute='_compute_rma_template_quantities', + digits_compute=dp.get_precision('Product Unit of Measure'), + string='RMA Quantity On Hand' + ) + rma_virtual_available = fields.Float( + compute='_compute_rma_template_quantities', + digits_compute=dp.get_precision('Product Unit of Measure'), + string='RMA Forecasted Quantity' + ) - rma_virtual_available = fields.Float(compute='_rma_template_available', - digits_compute=dp. - get_precision('Product Unit' - ' of Measure'), - string=_('RMA Forecasted Quantity')) + @api.depends('product_variant_ids.rma_qty_available', + 'product_variant_ids.rma_virtual_available') + def _compute_rma_template_quantities(self): + """ Compute rma_qty_available and rma_virtual_available + with sum of variants quantities. + """ - @api.multi - def _rma_template_available(self): - for product in self: - product.rma_qty_available = sum( - product.mapped('product_variant_ids.rma_virtual_available')) - product.rma_virtual_available = sum( - product.mapped('product_variant_ids.rma_virtual_available')) + for template in self: + qantities = template.product_variant_ids.read( + ['rma_qty_available', 'rma_virtual_available'] + ) + template.rma_qty_available = sum( + qty['rma_qty_available'] for qty in qantities + ) + template.rma_virtual_available = sum( + qty['rma_virtual_available'] for qty in qantities + ) diff --git a/crm_rma_stock_location/models/stock_warehouse.py b/crm_rma_stock_location/models/stock_warehouse.py index ab919f57..f8e415af 100644 --- a/crm_rma_stock_location/models/stock_warehouse.py +++ b/crm_rma_stock_location/models/stock_warehouse.py @@ -1,73 +1,47 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# Copyright 2013 Camptocamp -# Copyright 2009-2013 Akretion, -# Author: Emmanuel Samyn, Raphaël Valyi, Sébastien Beau, +# © 2013 Camptocamp +# © 2009-2013 Akretion, +# Author: Emmanuel Samyn, Raphaël Valyi, Sébastien Beau, # Joel Grand-Guillaume -# -# 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 . -# -############################################################################## +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from openerp import _, api, fields, models class StockWarehouse(models.Model): - _inherit = "stock.warehouse" loss_loc_id = fields.Many2one('stock.location', 'Loss Location') lot_refurbish_id = fields.Many2one('stock.location', 'Refurbish Location') - @api.model - def create_locations_rma(self, wh_id): - vals = {} + @api.multi + def create_locations_rma(self): + super(StockWarehouse, self).create_locations_rma() location_obj = self.env['stock.location'] - context_with_inactive = self.env.context.copy() - context_with_inactive['active_test'] = False - wh_loc_id = wh_id.view_location_id.id - vals_new = super(StockWarehouse, self).create_locations_rma(wh_id) + for warehouse in self: + if not warehouse.lot_refurbish_id: + location_id = location_obj.with_context( + active_test=False + ).create({ + 'name': _('Refurbish'), + 'usage': 'production', + 'location_id': warehouse.view_location_id.id, + 'company_id': warehouse.company_id.id, + 'active': True, + }) + warehouse.lot_refurbish_id = location_id - loc_vals = { - 'location_id': wh_loc_id, - 'active': True, - } - - if vals.get('company_id'): - loc_vals['company_id'] = vals.get('company_id') - - if not wh_id.lot_refurbish_id: - loc_vals.update({ - 'name': _('Refurbish'), - 'usage': 'production' - }) - location_id = location_obj.with_context(context_with_inactive).\ - create(loc_vals) - vals['lot_refurbish_id'] = location_id.id - - if not wh_id.loss_loc_id: - loc_vals.update({ - 'name': _('Loss'), - 'usage': 'inventory' - }) - location_id = location_obj.with_context(context_with_inactive).\ - create(loc_vals) - vals['loss_loc_id'] = location_id.id - - vals.update(vals_new) - return vals + if not warehouse.loss_loc_id: + location_id = location_obj.with_context( + active_test=False + ).create({ + 'name': _('Loss'), + 'usage': 'inventory', + 'location_id': warehouse.view_location_id.id, + 'company_id': warehouse.company_id.id, + 'active': True, + }) + warehouse.loss_loc_id = location_id diff --git a/crm_rma_stock_location/tests/__init__.py b/crm_rma_stock_location/tests/__init__.py index 38cc02d5..a66e8511 100644 --- a/crm_rma_stock_location/tests/__init__.py +++ b/crm_rma_stock_location/tests/__init__.py @@ -1,23 +1,5 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# Copyright 2015 Vauxoo -# Author: Yanina Aular, Osval Reyes -# -# 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 . -# -############################################################################## from . import test_crm_rma_stock_location from . import test_make_picking_from_picking +from . import test_rma_stock diff --git a/crm_rma_stock_location/tests/test_crm_rma_stock_location.py b/crm_rma_stock_location/tests/test_crm_rma_stock_location.py index f743eff3..b9255547 100644 --- a/crm_rma_stock_location/tests/test_crm_rma_stock_location.py +++ b/crm_rma_stock_location/tests/test_crm_rma_stock_location.py @@ -1,23 +1,7 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# Copyright 2015 Vauxoo -# Author: Osval Reyes -# -# 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 . -# -############################################################################## +# © 2015 Vauxoo +# Author: Osval Reyes +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from openerp.tests.common import TransactionCase diff --git a/crm_rma_stock_location/tests/test_make_picking_from_picking.py b/crm_rma_stock_location/tests/test_make_picking_from_picking.py index c39ebbe4..7623ec43 100644 --- a/crm_rma_stock_location/tests/test_make_picking_from_picking.py +++ b/crm_rma_stock_location/tests/test_make_picking_from_picking.py @@ -1,23 +1,7 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# Author: Yanina Aular -# Copyright 2015 Vauxoo -# -# 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 . -# -############################################################################## +# © 2015 Vauxoo +# Author: Yanina Aular +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from openerp.tests.common import TransactionCase @@ -71,7 +55,7 @@ class TestPickingFromPicking(TransactionCase): 'active_id': self.claim_id.id, 'warehouse_id': self.claim_id.warehouse_id.id, 'partner_id': self.claim_id.partner_id.id, - 'picking_type': self.claim_id.warehouse_id.rma_in_type_id.id, + 'picking_type': 'in', } wizard_id = self.wizardmakepicking.with_context(wiz_context).create({}) @@ -133,9 +117,10 @@ class TestPickingFromPicking(TransactionCase): } wizard_id = self.wizardmakepicking.with_context(new_context).create({}) - default_location_dest_id = eval( - 'self.claim_id.warehouse_id.' - 'rma_%s_type_id.default_location_dest_id' % picking_type_str) + default_location_dest_id = getattr( + self.claim_id.warehouse_id, + 'rma_%s_type_id' % picking_type_str + ).default_location_dest_id self.assertEquals( wizard_id.claim_line_dest_location_id, default_location_dest_id) @@ -153,7 +138,7 @@ class TestPickingFromPicking(TransactionCase): } wizard_id = self.wizardmakepicking.with_context(new_context).create({}) - default_location_dest_id = eval( - 'self.claim_id.warehouse_id.loss_loc_id') + default_location_dest_id = self.claim_id.warehouse_id.loss_loc_id self.assertEquals( - wizard_id.claim_line_dest_location_id, default_location_dest_id) + wizard_id.claim_line_dest_location_id, default_location_dest_id + ) diff --git a/crm_rma_stock_location/tests/test_rma_stock.py b/crm_rma_stock_location/tests/test_rma_stock.py new file mode 100644 index 00000000..5b6bd7a9 --- /dev/null +++ b/crm_rma_stock_location/tests/test_rma_stock.py @@ -0,0 +1,194 @@ +# -*- coding: utf-8 -*- +# © 2016 Cyril Gaudin (Camptocamp) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp.tests import TransactionCase + + +class TestRMAStock(TransactionCase): + + def setUp(self): + super(TestRMAStock, self).setUp() + self.wh_main = self.env.ref("stock.warehouse0") + + location_model = self.env['stock.location'] + self.loc_rma = location_model.create({ + 'name': 'RMA', + 'usage': 'view', + 'location_id': self.wh_main.view_location_id.id, + }) + + self.loc_box_a = location_model.create({ + 'name': 'RMA - Box A', + 'usage': 'internal', + 'location_id': self.loc_rma.id, + }) + + self.loc_box_b = location_model.create({ + 'name': 'RMA - Box B', + 'usage': 'internal', + 'location_id': self.loc_rma.id, + }) + + self.wh_main.lot_rma_id = self.loc_rma + + # Create products + self.product_socket = self.env['product.product'].create({ + 'name': 'Sockets', + }) + + self.product_shoes = self.env['product.product'].create({ + 'name': 'Shoes', + }) + + def test_rma_qty(self): + # Put 50 in box A + inventory = self.env['stock.inventory'].create({ + 'name': 'Inventory for Sockets', + 'location_id': self.loc_box_a.id, + 'filter': 'partial' + }) + inventory.prepare_inventory() + + self.env['stock.inventory.line'].create({ + 'inventory_id': inventory.id, + 'product_id': self.product_socket.id, + 'location_id': self.loc_box_a.id, + 'product_qty': 50, + }) + inventory.action_done() + + # Confirmed move for 30 in box B + self.env['stock.move'].create({ + 'name': 'Test move rma', + 'state': 'confirmed', + 'product_id': self.product_socket.id, + 'product_uom_qty': 30, + 'product_uom': self.product_socket.uom_id.id, + 'location_id': self.ref('stock.stock_location_suppliers'), + 'location_dest_id': self.loc_box_b.id, + }) + + # Should have 50 avalaible and 80 forecasted + self.assertEqual(50.0, self.product_socket.rma_qty_available) + self.assertEqual(80.0, self.product_socket.rma_virtual_available) + + # A warehouse can be specified + other_warehouse = self.env['stock.warehouse'].create({ + 'name': 'Other warehouse', + 'partner_id': self.ref('base.main_partner'), + 'code': 'WH2', + }) + + self.assertEqual( + 0.0, + self.product_socket.with_context( + warehouse_id=other_warehouse.id + ).rma_qty_available + ) + self.assertEqual( + 0.0, + self.product_socket.with_context( + warehouse_id=other_warehouse.id + ).rma_virtual_available + ) + + # Reset lot_rma_id (automatically created) + other_warehouse.lot_rma_id = False + self.product_socket.refresh() + self.assertEqual( + 0.0, + self.product_socket.with_context( + warehouse_id=other_warehouse.id + ).rma_qty_available + ) + self.assertEqual( + 0.0, + self.product_socket.with_context( + warehouse_id=other_warehouse.id + ).rma_virtual_available + ) + + def test_multi(self): + inventory = self.env['stock.inventory'].create({ + 'name': 'Inventory for Sockets', + 'location_id': self.loc_box_a.id, + 'filter': 'partial' + }) + inventory.prepare_inventory() + + # Put 20 sockets and 10 shoes in box A + self.env['stock.inventory.line'].create({ + 'inventory_id': inventory.id, + 'product_id': self.product_socket.id, + 'location_id': self.loc_box_a.id, + 'product_qty': 20, + }) + self.env['stock.inventory.line'].create({ + 'inventory_id': inventory.id, + 'product_id': self.product_shoes.id, + 'location_id': self.loc_box_a.id, + 'product_qty': 10, + }) + inventory.action_done() + + qties = self.env['product.product'].search_read( + [('id', 'in', [self.product_socket.id, self.product_shoes.id])], + ['rma_qty_available', 'rma_virtual_available'], + order='id' + ) + self.assertEqual([ + {'id': self.product_socket.id, 'rma_qty_available': 20, + 'rma_virtual_available': 20}, + {'id': self.product_shoes.id, 'rma_qty_available': 10, + 'rma_virtual_available': 10} + ], qties) + + def test_variants(self): + + self.variant_shoes = self.env['product.product'].create({ + 'product_tmpl_id': self.product_shoes.product_tmpl_id.id, + 'name': 'Variant shoes' + }) + inventory = self.env['stock.inventory'].create({ + 'name': 'Inventory for Sockets', + 'location_id': self.loc_box_a.id, + 'filter': 'partial' + }) + inventory.prepare_inventory() + + # Put 5 shoes and 4 variant shoes in box A + self.env['stock.inventory.line'].create({ + 'inventory_id': inventory.id, + 'product_id': self.product_shoes.id, + 'location_id': self.loc_box_a.id, + 'product_qty': 5, + }) + self.env['stock.inventory.line'].create({ + 'inventory_id': inventory.id, + 'product_id': self.variant_shoes.id, + 'location_id': self.loc_box_a.id, + 'product_qty': 4, + }) + inventory.action_done() + + # Confirmed move for 3 variant shoes in box B + self.env['stock.move'].create({ + 'name': 'Test move rma', + 'state': 'confirmed', + 'product_id': self.variant_shoes.id, + 'product_uom_qty': 3, + 'product_uom': self.variant_shoes.uom_id.id, + 'location_id': self.ref('stock.stock_location_suppliers'), + 'location_dest_id': self.loc_box_b.id, + }) + + self.assertEqual(5.0, self.product_shoes.rma_qty_available) + self.assertEqual(5.0, self.product_shoes.rma_virtual_available) + + self.assertEqual(4.0, self.variant_shoes.rma_qty_available) + self.assertEqual(7.0, self.variant_shoes.rma_virtual_available) + + shoes_template = self.product_shoes.product_tmpl_id + self.assertEqual(9.0, shoes_template.rma_qty_available) + self.assertEqual(12.0, shoes_template.rma_virtual_available) diff --git a/crm_rma_stock_location/views/crm_claim.xml b/crm_rma_stock_location/views/crm_claim.xml index f9a5f099..76f76ce0 100644 --- a/crm_rma_stock_location/views/crm_claim.xml +++ b/crm_rma_stock_location/views/crm_claim.xml @@ -1,19 +1,16 @@ - - - - CRM - Claim product return Form - crm.claim - - - - + + + diff --git a/crm_rma_stock_location/views/product_product.xml b/crm_rma_stock_location/views/product_product.xml index 54fc3c26..47174164 100644 --- a/crm_rma_stock_location/views/product_product.xml +++ b/crm_rma_stock_location/views/product_product.xml @@ -1,46 +1,44 @@ - - - - product.stock.tree.inherit - product.product - - - - - - - - - - + + + product.stock.tree.inherit + product.product + + + + + + + + + + - - product.product.search - product.product - - - - - - - + + product.product.search + product.product + + + + + + + - - RMA Stock - ir.actions.act_window - product.product - tree - form - - - {'search_default_rma_available': 1} - + + RMA Stock + ir.actions.act_window + product.product + tree + form + + + {'search_default_rma_available': 1} + - - - + + diff --git a/crm_rma_stock_location/views/product_template.xml b/crm_rma_stock_location/views/product_template.xml index 44fe71cb..cc7ecc45 100644 --- a/crm_rma_stock_location/views/product_template.xml +++ b/crm_rma_stock_location/views/product_template.xml @@ -1,17 +1,29 @@ - - - - - product.normal.procurement.locations.inherit - product.template - - - - - - + + + product.template.tree + product.template + + + + + - - - + + + + + product.form.view.rma + product.template + + + + + + + + + + + + diff --git a/crm_rma_stock_location/views/stock_picking.xml b/crm_rma_stock_location/views/stock_picking.xml index 6da49f08..ea1cecb3 100644 --- a/crm_rma_stock_location/views/stock_picking.xml +++ b/crm_rma_stock_location/views/stock_picking.xml @@ -1,30 +1,28 @@ - - - - - crm_claim_rma.picking_in_form - stock.picking - - - -