From b4c8ebd37edac6de31dd895a9d1b30992247ed80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Faure-Lacroix?= Date: Sat, 28 Feb 2015 16:44:51 +0300 Subject: [PATCH 01/22] [#66647] Init --- stock_available_reserved_quantity/__init__.py | 0 .../__openerp__.py | 46 +++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 stock_available_reserved_quantity/__init__.py create mode 100644 stock_available_reserved_quantity/__openerp__.py diff --git a/stock_available_reserved_quantity/__init__.py b/stock_available_reserved_quantity/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/stock_available_reserved_quantity/__openerp__.py b/stock_available_reserved_quantity/__openerp__.py new file mode 100644 index 000000000000..360b8253fe41 --- /dev/null +++ b/stock_available_reserved_quantity/__openerp__.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- + +{ + 'name': 'Stock available reserved quantity', + 'version': '1.0', + 'author': 'Savoir-faire Linux', + 'category': 'Warehouse', + 'depends': [ + 'stock' + ], + 'description': """\ +Stock available reserved quantity +================================= + +Configuration +============= + +Usage +===== + +Credits +======= + +Contributors +------------ + +* Loïc Faure-Lacroix + +Maintainer +---------- + +.. image:: http://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: http://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.""", + 'license': 'AGPL-3', + 'data': [ + ] +} From 1c0285ea505f72349dc53ee507a22242218db7ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Faure-Lacroix?= Date: Sun, 1 Mar 2015 12:25:16 +0300 Subject: [PATCH 02/22] [#66647] Added stock recount --- .../models/__init__.py | 1 + .../models/stock_production_lot.py | 52 +++++++++++++++++++ .../views/stock_production_lot.xml | 25 +++++++++ 3 files changed, 78 insertions(+) create mode 100644 stock_available_reserved_quantity/models/__init__.py create mode 100644 stock_available_reserved_quantity/models/stock_production_lot.py create mode 100644 stock_available_reserved_quantity/views/stock_production_lot.xml diff --git a/stock_available_reserved_quantity/models/__init__.py b/stock_available_reserved_quantity/models/__init__.py new file mode 100644 index 000000000000..dd885b7bed84 --- /dev/null +++ b/stock_available_reserved_quantity/models/__init__.py @@ -0,0 +1 @@ +from . import stock_production_lot diff --git a/stock_available_reserved_quantity/models/stock_production_lot.py b/stock_available_reserved_quantity/models/stock_production_lot.py new file mode 100644 index 000000000000..2a3ee368b514 --- /dev/null +++ b/stock_available_reserved_quantity/models/stock_production_lot.py @@ -0,0 +1,52 @@ +from openerp.osv import orm, fields +import openerp.addons.decimal_precision as dp + +def get_stock_proxy(self, cr, uid, ids, field_name, arg, context=None): + return self._get_stock(cr, uid, ids, field_name, arg, context=context) + +def stock_search_proxy(self, cr, uid, obj, name, args, context=None): + return self._stock_search(cr, uid, obj, name, args, context=context) + +class StockProductionLot(orm.Model): + + def _validate_retained_stock(self, cr, uid, ids, context=None): + for lot in self.browse(cr, uid, ids, context=context): + if lot.retained_stock < 0: + return False + + return True + + _inherit = "stock.production.lot" + + _columns = { + 'stock_available': fields.function( + get_stock_proxy, + fnct_search=stock_search_proxy, + type="float", + string="Available", + select=True, + help="Current quantity of products with this Serial Number " + "available in company warehouses", + digits_compute=dp.get_precision('Product Unit of Measure') + ), + 'retained_stock': fields.float(string='Retained stock'), + } + + _constraints = [ + ( + _validate_retained_stock, + 'Retained stock cannot be negative', + ['retained_stock'], + ), + ] + + def _get_stock(self, cr, uid, ids, field_name, arg, context=None): + + base_func = super(StockProductionLot, self)._get_stock + res = base_func(cr, uid, ids, field_name, arg, context=context) + ids = res.keys() + + for prod_lot in self.browse(cr, uid, ids): + res[prod_lot.id] -= prod_lot.retained_stock + + return res diff --git a/stock_available_reserved_quantity/views/stock_production_lot.xml b/stock_available_reserved_quantity/views/stock_production_lot.xml new file mode 100644 index 000000000000..4817240ef16c --- /dev/null +++ b/stock_available_reserved_quantity/views/stock_production_lot.xml @@ -0,0 +1,25 @@ + + + + + + stock.production.lot.form + stock.production.lot + + + + + + + + + + + + + + + + From 8186c142244a153e388e68e62ed83bd5474996d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Faure-Lacroix?= Date: Sun, 1 Mar 2015 12:27:20 +0300 Subject: [PATCH 03/22] [#66647] Added report which control the stock availability and search methods --- stock_available_reserved_quantity/__init__.py | 2 + .../__openerp__.py | 1 + .../models/stock_production_lot.py | 27 ---------- .../report/__init__.py | 1 + .../report/report_stock.py | 49 +++++++++++++++++++ 5 files changed, 53 insertions(+), 27 deletions(-) create mode 100644 stock_available_reserved_quantity/report/__init__.py create mode 100644 stock_available_reserved_quantity/report/report_stock.py diff --git a/stock_available_reserved_quantity/__init__.py b/stock_available_reserved_quantity/__init__.py index e69de29bb2d1..bf588bc8b803 100644 --- a/stock_available_reserved_quantity/__init__.py +++ b/stock_available_reserved_quantity/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import report diff --git a/stock_available_reserved_quantity/__openerp__.py b/stock_available_reserved_quantity/__openerp__.py index 360b8253fe41..e8e717917823 100644 --- a/stock_available_reserved_quantity/__openerp__.py +++ b/stock_available_reserved_quantity/__openerp__.py @@ -42,5 +42,6 @@ To contribute to this module, please visit http://odoo-community.org.""", 'license': 'AGPL-3', 'data': [ + "views/stock_production_lot.xml", ] } diff --git a/stock_available_reserved_quantity/models/stock_production_lot.py b/stock_available_reserved_quantity/models/stock_production_lot.py index 2a3ee368b514..0ada8ade9d8b 100644 --- a/stock_available_reserved_quantity/models/stock_production_lot.py +++ b/stock_available_reserved_quantity/models/stock_production_lot.py @@ -1,12 +1,6 @@ from openerp.osv import orm, fields import openerp.addons.decimal_precision as dp -def get_stock_proxy(self, cr, uid, ids, field_name, arg, context=None): - return self._get_stock(cr, uid, ids, field_name, arg, context=context) - -def stock_search_proxy(self, cr, uid, obj, name, args, context=None): - return self._stock_search(cr, uid, obj, name, args, context=context) - class StockProductionLot(orm.Model): def _validate_retained_stock(self, cr, uid, ids, context=None): @@ -19,16 +13,6 @@ def _validate_retained_stock(self, cr, uid, ids, context=None): _inherit = "stock.production.lot" _columns = { - 'stock_available': fields.function( - get_stock_proxy, - fnct_search=stock_search_proxy, - type="float", - string="Available", - select=True, - help="Current quantity of products with this Serial Number " - "available in company warehouses", - digits_compute=dp.get_precision('Product Unit of Measure') - ), 'retained_stock': fields.float(string='Retained stock'), } @@ -39,14 +23,3 @@ def _validate_retained_stock(self, cr, uid, ids, context=None): ['retained_stock'], ), ] - - def _get_stock(self, cr, uid, ids, field_name, arg, context=None): - - base_func = super(StockProductionLot, self)._get_stock - res = base_func(cr, uid, ids, field_name, arg, context=context) - ids = res.keys() - - for prod_lot in self.browse(cr, uid, ids): - res[prod_lot.id] -= prod_lot.retained_stock - - return res diff --git a/stock_available_reserved_quantity/report/__init__.py b/stock_available_reserved_quantity/report/__init__.py new file mode 100644 index 000000000000..445fac624598 --- /dev/null +++ b/stock_available_reserved_quantity/report/__init__.py @@ -0,0 +1 @@ +from . import report_stock diff --git a/stock_available_reserved_quantity/report/report_stock.py b/stock_available_reserved_quantity/report/report_stock.py new file mode 100644 index 000000000000..fad99774373f --- /dev/null +++ b/stock_available_reserved_quantity/report/report_stock.py @@ -0,0 +1,49 @@ +from openerp.osv import fields, osv +from openerp.tools.sql import drop_view_if_exists + +class stock_report_prodlots(osv.osv): + _inherit = "stock.report.prodlots" + + def init(self, cr): + print "***" * 1000 + drop_view_if_exists(cr, 'stock_report_prodlots') + cr.execute(""" + create or replace view stock_report_prodlots as ( + select max(id) as id, + location_id, + product_id, + prodlot_id, + sum(qty) as qty + from ( + select -max(sm.id) as id, + sm.location_id, + sm.product_id, + sm.prodlot_id, + -sum(sm.product_qty /uo.factor) + coalesce(lot.retained_stock, 0)as qty + from stock_move as sm + left join stock_location sl + on (sl.id = sm.location_id) + left join product_uom uo + on (uo.id=sm.product_uom) + left join stock_production_lot lot + on (lot.id=sm.prodlot_id) + where state = 'done' + group by sm.location_id, sm.product_id, sm.product_uom, sm.prodlot_id, lot.retained_stock + union all + select max(sm.id) as id, + sm.location_dest_id as location_id, + sm.product_id, + sm.prodlot_id, + sum(sm.product_qty /uo.factor) - coalesce(lot.retained_stock, 0) as qty + from stock_move as sm + left join stock_location sl + on (sl.id = sm.location_dest_id) + left join product_uom uo + on (uo.id=sm.product_uom) + left join stock_production_lot lot + on (lot.id=sm.prodlot_id) + where state = 'done' + group by sm.location_dest_id, sm.product_id, sm.product_uom, sm.prodlot_id, lot.retained_stock + ) as report + group by location_id, product_id, prodlot_id + )""") From 6c69b66009722177a04b3b8b5a28e43bbcfa82b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Faure-Lacroix?= Date: Sun, 1 Mar 2015 15:11:26 +0300 Subject: [PATCH 04/22] [#66647] Fix PEP8 errors --- .../models/stock_production_lot.py | 4 ++-- .../report/report_stock.py | 16 +++++++++++----- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/stock_available_reserved_quantity/models/stock_production_lot.py b/stock_available_reserved_quantity/models/stock_production_lot.py index 0ada8ade9d8b..b00cd43e4930 100644 --- a/stock_available_reserved_quantity/models/stock_production_lot.py +++ b/stock_available_reserved_quantity/models/stock_production_lot.py @@ -1,9 +1,9 @@ from openerp.osv import orm, fields -import openerp.addons.decimal_precision as dp + class StockProductionLot(orm.Model): - def _validate_retained_stock(self, cr, uid, ids, context=None): + def _validate_retained_stock(self, cr, uid, ids, context=None): for lot in self.browse(cr, uid, ids, context=context): if lot.retained_stock < 0: return False diff --git a/stock_available_reserved_quantity/report/report_stock.py b/stock_available_reserved_quantity/report/report_stock.py index fad99774373f..b33c39def350 100644 --- a/stock_available_reserved_quantity/report/report_stock.py +++ b/stock_available_reserved_quantity/report/report_stock.py @@ -1,11 +1,11 @@ from openerp.osv import fields, osv from openerp.tools.sql import drop_view_if_exists + class stock_report_prodlots(osv.osv): _inherit = "stock.report.prodlots" def init(self, cr): - print "***" * 1000 drop_view_if_exists(cr, 'stock_report_prodlots') cr.execute(""" create or replace view stock_report_prodlots as ( @@ -19,7 +19,8 @@ def init(self, cr): sm.location_id, sm.product_id, sm.prodlot_id, - -sum(sm.product_qty /uo.factor) + coalesce(lot.retained_stock, 0)as qty + -sum(sm.product_qty /uo.factor) + + coalesce(lot.retained_stock, 0) as qty from stock_move as sm left join stock_location sl on (sl.id = sm.location_id) @@ -28,13 +29,16 @@ def init(self, cr): left join stock_production_lot lot on (lot.id=sm.prodlot_id) where state = 'done' - group by sm.location_id, sm.product_id, sm.product_uom, sm.prodlot_id, lot.retained_stock + group by sm.location_id, sm.product_id, + sm.product_uom, sm.prodlot_id, + lot.retained_stock union all select max(sm.id) as id, sm.location_dest_id as location_id, sm.product_id, sm.prodlot_id, - sum(sm.product_qty /uo.factor) - coalesce(lot.retained_stock, 0) as qty + sum(sm.product_qty /uo.factor) - + coalesce(lot.retained_stock, 0) as qty from stock_move as sm left join stock_location sl on (sl.id = sm.location_dest_id) @@ -43,7 +47,9 @@ def init(self, cr): left join stock_production_lot lot on (lot.id=sm.prodlot_id) where state = 'done' - group by sm.location_dest_id, sm.product_id, sm.product_uom, sm.prodlot_id, lot.retained_stock + group by sm.location_dest_id, sm.product_id, + sm.product_uom, sm.prodlot_id, + lot.retained_stock ) as report group by location_id, product_id, prodlot_id )""") From 0aa87fb226d2da0e34e3d45bd67df55cb3c884f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Faure-Lacroix?= Date: Sun, 1 Mar 2015 15:21:10 +0300 Subject: [PATCH 05/22] [#66647] Added copyright --- stock_available_reserved_quantity/__init__.py | 21 ++++++++++ .../__openerp__.py | 21 +++++++++- .../models/__init__.py | 21 ++++++++++ .../report/__init__.py | 21 ++++++++++ .../report/report_stock.py | 39 +++++++++++++++++++ 5 files changed, 122 insertions(+), 1 deletion(-) diff --git a/stock_available_reserved_quantity/__init__.py b/stock_available_reserved_quantity/__init__.py index bf588bc8b803..8f592663a602 100644 --- a/stock_available_reserved_quantity/__init__.py +++ b/stock_available_reserved_quantity/__init__.py @@ -1,2 +1,23 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module copyright (C) 2015 - Present Savoir-faire Linux +# (). +# +# 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 report diff --git a/stock_available_reserved_quantity/__openerp__.py b/stock_available_reserved_quantity/__openerp__.py index e8e717917823..3ba847919dc7 100644 --- a/stock_available_reserved_quantity/__openerp__.py +++ b/stock_available_reserved_quantity/__openerp__.py @@ -1,5 +1,24 @@ # -*- coding: utf-8 -*- - +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module copyright (C) 2015 - Present Savoir-faire Linux +# (). +# +# 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': 'Stock available reserved quantity', 'version': '1.0', diff --git a/stock_available_reserved_quantity/models/__init__.py b/stock_available_reserved_quantity/models/__init__.py index dd885b7bed84..3a1352b43e9d 100644 --- a/stock_available_reserved_quantity/models/__init__.py +++ b/stock_available_reserved_quantity/models/__init__.py @@ -1 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module copyright (C) 2015 - Present Savoir-faire Linux +# (). +# +# 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 stock_production_lot diff --git a/stock_available_reserved_quantity/report/__init__.py b/stock_available_reserved_quantity/report/__init__.py index 445fac624598..db0e83432d18 100644 --- a/stock_available_reserved_quantity/report/__init__.py +++ b/stock_available_reserved_quantity/report/__init__.py @@ -1 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module copyright (C) 2015 - Present Savoir-faire Linux +# (). +# +# 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 report_stock diff --git a/stock_available_reserved_quantity/report/report_stock.py b/stock_available_reserved_quantity/report/report_stock.py index b33c39def350..2e54300ea47b 100644 --- a/stock_available_reserved_quantity/report/report_stock.py +++ b/stock_available_reserved_quantity/report/report_stock.py @@ -1,11 +1,50 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module copyright (C) 2015 - Present Savoir-faire Linux +# (). +# +# 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 openerp.osv import fields, osv from openerp.tools.sql import drop_view_if_exists class stock_report_prodlots(osv.osv): + + """ + Override the stock.report.prodlots. + + We have to substract and add the retained value on stock_move + that have a prodlot assigned to it. The prodlot objects should + have a retained_stock value which is used to calculate a fake + quantity of product. + """ + _inherit = "stock.report.prodlots" def init(self, cr): + """ + Delete and replace the previous view by this one. + + This view is an extension of the view in the module + stock of odoo. + + file: odoo/addons/stock/report/report_stock.py + """ drop_view_if_exists(cr, 'stock_report_prodlots') cr.execute(""" create or replace view stock_report_prodlots as ( From c952e2f4f64be6fe48697ab5eef62e8e646bed18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Faure-Lacroix?= Date: Sun, 1 Mar 2015 15:21:33 +0300 Subject: [PATCH 06/22] [#66647] Added doctstrings --- .../models/stock_production_lot.py | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/stock_available_reserved_quantity/models/stock_production_lot.py b/stock_available_reserved_quantity/models/stock_production_lot.py index b00cd43e4930..37b81123801d 100644 --- a/stock_available_reserved_quantity/models/stock_production_lot.py +++ b/stock_available_reserved_quantity/models/stock_production_lot.py @@ -1,9 +1,44 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module copyright (C) 2015 - Present Savoir-faire Linux +# (). +# +# 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 openerp.osv import orm, fields class StockProductionLot(orm.Model): + """ + Extend the stock.production.lot model. + + We add the retained_stock field to our model. It will be used to + recaculate the available quantity of products. The available quantity + of products is calculated inside a view. + + The view is named "stock.report.prodlots" the extended view is located + in the report folder. The stock and search function for available quantity + depends on this view. For that reason, only the view as to be rewritten + to take in account the retained_stock field. + """ + def _validate_retained_stock(self, cr, uid, ids, context=None): + """Check that the retained stock is a positive number.""" for lot in self.browse(cr, uid, ids, context=context): if lot.retained_stock < 0: return False From e758e3c34f970e76ec29a320eaa8b1941c571699 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Faure-Lacroix?= Date: Mon, 2 Mar 2015 14:28:48 +0300 Subject: [PATCH 07/22] [#66647] Fix pep8 errors and use orm.Model instead of osv.osv --- stock_available_reserved_quantity/report/report_stock.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stock_available_reserved_quantity/report/report_stock.py b/stock_available_reserved_quantity/report/report_stock.py index 2e54300ea47b..fbe03d5e0d7e 100644 --- a/stock_available_reserved_quantity/report/report_stock.py +++ b/stock_available_reserved_quantity/report/report_stock.py @@ -19,11 +19,11 @@ # along with this program. If not, see . # ############################################################################## -from openerp.osv import fields, osv +from openerp.osv import orm from openerp.tools.sql import drop_view_if_exists -class stock_report_prodlots(osv.osv): +class stock_report_prodlots(orm.Model): """ Override the stock.report.prodlots. From 9721da6077c95db156bdff44d895499cc4a5c2f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Faure-Lacroix?= Date: Fri, 6 Mar 2015 23:42:06 +0300 Subject: [PATCH 08/22] [#66647] Fix SQL view --- .../report/report_stock.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/stock_available_reserved_quantity/report/report_stock.py b/stock_available_reserved_quantity/report/report_stock.py index fbe03d5e0d7e..00ab9ba48b5e 100644 --- a/stock_available_reserved_quantity/report/report_stock.py +++ b/stock_available_reserved_quantity/report/report_stock.py @@ -52,14 +52,14 @@ def init(self, cr): location_id, product_id, prodlot_id, - sum(qty) as qty + sum(qty) - retained_stock as qty from ( select -max(sm.id) as id, sm.location_id, sm.product_id, sm.prodlot_id, - -sum(sm.product_qty /uo.factor) + - coalesce(lot.retained_stock, 0) as qty + -sum(sm.product_qty /uo.factor) as qty, + coalesce(lot.retained_stock, 0) as retained_stock from stock_move as sm left join stock_location sl on (sl.id = sm.location_id) @@ -76,8 +76,8 @@ def init(self, cr): sm.location_dest_id as location_id, sm.product_id, sm.prodlot_id, - sum(sm.product_qty /uo.factor) - - coalesce(lot.retained_stock, 0) as qty + sum(sm.product_qty /uo.factor) as qty, + coalesce(lot.retained_stock, 0) as retained_stock from stock_move as sm left join stock_location sl on (sl.id = sm.location_dest_id) @@ -90,5 +90,5 @@ def init(self, cr): sm.product_uom, sm.prodlot_id, lot.retained_stock ) as report - group by location_id, product_id, prodlot_id + group by location_id, product_id, prodlot_id, retained_stock )""") From 24dd66dd0d83e51ce535b20d295901136f9d0f54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Faure-Lacroix?= Date: Fri, 6 Mar 2015 23:45:25 +0300 Subject: [PATCH 09/22] [#66647] Add unit of measure on retained stock --- .../models/stock_production_lot.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/stock_available_reserved_quantity/models/stock_production_lot.py b/stock_available_reserved_quantity/models/stock_production_lot.py index 37b81123801d..a994e60b84e5 100644 --- a/stock_available_reserved_quantity/models/stock_production_lot.py +++ b/stock_available_reserved_quantity/models/stock_production_lot.py @@ -20,6 +20,7 @@ # ############################################################################## from openerp.osv import orm, fields +import openerp.addons.decimal_precision as dp class StockProductionLot(orm.Model): @@ -48,7 +49,10 @@ def _validate_retained_stock(self, cr, uid, ids, context=None): _inherit = "stock.production.lot" _columns = { - 'retained_stock': fields.float(string='Retained stock'), + 'retained_stock': fields.float( + string='Retained stock', + digits_compute=dp.get_precision('Product Unit of Measure') + ), } _constraints = [ From 26a604d2e8c271976839c39b15382a04b8968250 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Faure-Lacroix?= Date: Sat, 7 Mar 2015 13:03:18 +0300 Subject: [PATCH 10/22] [#66647] Added translation --- stock_available_reserved_quantity/i18n/fr.po | 37 +++++++++++++++++++ .../i18n/stock_available_reserved_quantity.po | 37 +++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 stock_available_reserved_quantity/i18n/fr.po create mode 100644 stock_available_reserved_quantity/i18n/stock_available_reserved_quantity.po diff --git a/stock_available_reserved_quantity/i18n/fr.po b/stock_available_reserved_quantity/i18n/fr.po new file mode 100644 index 000000000000..2ab0673bf0d9 --- /dev/null +++ b/stock_available_reserved_quantity/i18n/fr.po @@ -0,0 +1,37 @@ +# Translation of OpenERP Server. +# This file contains the translation of the following modules: +# * stock_available_reserved_quantity +# +msgid "" +msgstr "" +"Project-Id-Version: OpenERP Server 7.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-03-07 09:26+0000\n" +"PO-Revision-Date: 2015-03-07 09: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: nplurals=2; plural=(n > 1);" + +#. module: stock_available_reserved_quantity +#: field:stock.production.lot,retained_stock:0 +msgid "Retained stock" +msgstr "Quantité Retenue" + +#. module: stock_available_reserved_quantity +#: model:ir.model,name:stock_available_reserved_quantity.model_stock_report_prodlots +msgid "Stock report by serial number" +msgstr "Rapport de stock par numéro de série" + +#. module: stock_available_reserved_quantity +#: model:ir.model,name:stock_available_reserved_quantity.model_stock_production_lot +msgid "Serial Number" +msgstr "Numéro de série" + +#. module: stock_available_reserved_quantity +#: constraint:stock.production.lot:0 +msgid "Retained stock cannot be negative" +msgstr "La quantité retenue ne peut pas être négative." + diff --git a/stock_available_reserved_quantity/i18n/stock_available_reserved_quantity.po b/stock_available_reserved_quantity/i18n/stock_available_reserved_quantity.po new file mode 100644 index 000000000000..ac85ea508790 --- /dev/null +++ b/stock_available_reserved_quantity/i18n/stock_available_reserved_quantity.po @@ -0,0 +1,37 @@ +# Translation of OpenERP Server. +# This file contains the translation of the following modules: +# * stock_available_reserved_quantity +# +msgid "" +msgstr "" +"Project-Id-Version: OpenERP Server 7.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-03-07 09:26+0000\n" +"PO-Revision-Date: 2015-03-07 09: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: stock_available_reserved_quantity +#: field:stock.production.lot,retained_stock:0 +msgid "Retained stock" +msgstr "" + +#. module: stock_available_reserved_quantity +#: model:ir.model,name:stock_available_reserved_quantity.model_stock_report_prodlots +msgid "Stock report by serial number" +msgstr "" + +#. module: stock_available_reserved_quantity +#: model:ir.model,name:stock_available_reserved_quantity.model_stock_production_lot +msgid "Serial Number" +msgstr "" + +#. module: stock_available_reserved_quantity +#: constraint:stock.production.lot:0 +msgid "Retained stock cannot be negative" +msgstr "" + From 3e0adc82eb6fb9ab0bd2c858f07fcf8907bd911a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Faure-Lacroix?= Date: Wed, 11 Mar 2015 12:53:53 +0300 Subject: [PATCH 11/22] [#66647] Added tests --- .../tests/__init__.py | 26 +++++ .../tests/test_retained_stock.py | 106 ++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 stock_available_reserved_quantity/tests/__init__.py create mode 100644 stock_available_reserved_quantity/tests/test_retained_stock.py diff --git a/stock_available_reserved_quantity/tests/__init__.py b/stock_available_reserved_quantity/tests/__init__.py new file mode 100644 index 000000000000..95cc56540c36 --- /dev/null +++ b/stock_available_reserved_quantity/tests/__init__.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module copyright (C) 2015 - Present Savoir-faire Linux +# (). +# +# 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_retained_stock + +checks = [ + test_retained_stock, +] diff --git a/stock_available_reserved_quantity/tests/test_retained_stock.py b/stock_available_reserved_quantity/tests/test_retained_stock.py new file mode 100644 index 000000000000..f453ba26ed0d --- /dev/null +++ b/stock_available_reserved_quantity/tests/test_retained_stock.py @@ -0,0 +1,106 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module copyright (C) 2015 - Present Savoir-faire Linux +# (). +# +# 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 openerp.tests import common +from openerp.osv.orm import except_orm + + +class TestRetainedStock(common.TransactionCase): + + def setUp(self): + super(TestRetainedStock, self).setUp() + + self.prodlot_model = self.registry('stock.production.lot') + self.stock_move_model = self.registry('stock.move') + self.location_model = self.registry("stock.location") + + def create_lot(self, vals): + return self.prodlot_model.create(self.cr, self.uid, vals) + + def create_move(self, vals): + return self.stock_move_model.create(self.cr, self.uid, vals) + + def create_location(self, vals): + return self.location_model.create(self.cr, self.uid, vals) + + def test_retained_stock_constraint(self): + lot_id = self.create_lot({ + "name": "Monitors", + "product_id": self.ref("product.product_product_6"), + "retained_stock": 10 + }) + + self.assertNotEqual(lot_id, 0) + + lot_id = self.create_lot({ + "name": "Monitors", + "product_id": self.ref("product.product_product_6"), + "retained_stock": 0 + }) + + self.assertNotEqual(lot_id, 0) + + with self.assertRaises(except_orm): + self.create_lot({ + "name": "Monitors 2", + "product_id": self.ref("product.product_product_6"), + "retained_stock": -1 + }) + + def test_retained_stock_calculated(self): + from_location_id = self.create_location({ + "name": "StockSupplier", + "usage": "inventory", + }) + + location_id = self.create_location({ + "name": "Stock", + "usage": "internal", + }) + + lot_id = self.create_lot({ + "name": "Monitors", + "product_id": self.ref("product.product_product_6"), + "retained_stock": 10, + "location_id": location_id, + }) + + self.create_move({ + "name": "move_name", + "product_id": self.ref("product.product_product_6"), + "product_uom": self.ref("product.product_uom_kgm"), + "product_qty": 50, + "location_id": from_location_id, + "location_dest_id": location_id, + "prodlot_id": lot_id, + "state": "done", + }) + + prodlot = self.prodlot_model.browse(self.cr, self.uid, lot_id) + self.assertEqual(prodlot.stock_available, 40) + + prodlot.write({"retained_stock": 40}) + prodlot.refresh() + self.assertEqual(prodlot.stock_available, 10) + + prodlot.write({"retained_stock": 0}) + prodlot.refresh() + self.assertEqual(prodlot.stock_available, 50) From d971613b95f02f54c8fcf07f23a43de1a4208c4d Mon Sep 17 00:00:00 2001 From: Alexandre Fayolle Date: Mon, 2 Mar 2015 17:28:33 +0100 Subject: [PATCH 12/22] Add OCA as author of OCA addons In order to get visibility on https://www.odoo.com/apps the OCA board has decided to add the OCA as author of all the addons maintained as part of the association. --- stock_available_immediately/__openerp__.py | 2 +- stock_location_ownership/__openerp__.py | 2 +- stock_location_search_stock/__openerp__.py | 2 +- stock_lot_valuation/__openerp__.py | 2 +- stock_optional_valuation/__openerp__.py | 2 +- stock_orderpoint_generator/__openerp__.py | 2 +- stock_reord_rule/__openerp__.py | 2 +- stock_reserve/__openerp__.py | 2 +- stock_reserve_sale/__openerp__.py | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/stock_available_immediately/__openerp__.py b/stock_available_immediately/__openerp__.py index 08383b4f9cbb..e2cb8bf9a154 100644 --- a/stock_available_immediately/__openerp__.py +++ b/stock_available_immediately/__openerp__.py @@ -24,7 +24,7 @@ "name": "Ignore planned receptions in quantity available to promise", "version": "2.0", "depends": ["stock_available"], - "author": "Camptocamp", + "author": "Camptocamp,Odoo Community Association (OCA)", "license": "AGPL-3", "description": u""" Ignore planned receptions in quantity available to promise diff --git a/stock_location_ownership/__openerp__.py b/stock_location_ownership/__openerp__.py index bcd2582c085c..91de5d27fed9 100644 --- a/stock_location_ownership/__openerp__.py +++ b/stock_location_ownership/__openerp__.py @@ -21,7 +21,7 @@ {'name': 'Stock Location Ownership', 'version': '0.1', - 'author': 'Camptocamp', + 'author': "Camptocamp,Odoo Community Association (OCA)", 'category': 'Warehouse', 'license': 'AGPL-3', 'complexity': 'normal', diff --git a/stock_location_search_stock/__openerp__.py b/stock_location_search_stock/__openerp__.py index acdf895117f5..61bb65a0428a 100644 --- a/stock_location_search_stock/__openerp__.py +++ b/stock_location_search_stock/__openerp__.py @@ -21,7 +21,7 @@ {'name': 'Stock Location Search Stock Quantities', 'version': '1.0', - 'author': 'Camptocamp', + 'author': "Camptocamp,Odoo Community Association (OCA)", 'maintainer': 'Camptocamp', 'license': 'AGPL-3', 'category': 'Warehouse Management', diff --git a/stock_lot_valuation/__openerp__.py b/stock_lot_valuation/__openerp__.py index 84c91935b395..65120bc87ba2 100644 --- a/stock_lot_valuation/__openerp__.py +++ b/stock_lot_valuation/__openerp__.py @@ -34,7 +34,7 @@ As for products, lots have 'cost' and 'costing method' fields. Also, a 'Change Standard Price' wizard is available. """, - 'author': 'Agile Business Group', + 'author': "Agile Business Group,Odoo Community Association (OCA)", 'website': 'http://www.agilebg.com', 'license': 'AGPL-3', "depends": ['stock'], diff --git a/stock_optional_valuation/__openerp__.py b/stock_optional_valuation/__openerp__.py index 0338df4a5ee1..223a7eba5001 100644 --- a/stock_optional_valuation/__openerp__.py +++ b/stock_optional_valuation/__openerp__.py @@ -26,7 +26,7 @@ You can choose which stock moves have to generate inventory valuation accounting entries, by specifying it in the location form. """, - 'author': 'Agile Business Group', + 'author': "Agile Business Group,Odoo Community Association (OCA)", 'website': 'http://www.agilebg.com', 'license': 'AGPL-3', "depends": ['stock'], diff --git a/stock_orderpoint_generator/__openerp__.py b/stock_orderpoint_generator/__openerp__.py index 1436036fc741..1a084746628d 100644 --- a/stock_orderpoint_generator/__openerp__.py +++ b/stock_orderpoint_generator/__openerp__.py @@ -22,7 +22,7 @@ {'name': 'Order point generator', 'summary': 'Mass configuration of stock order points', 'version': '1.0', - 'author': 'Camptocamp', + 'author': "Camptocamp,Odoo Community Association (OCA)", 'category': 'Warehouse', 'license': 'AGPL-3', 'complexity': 'easy', diff --git a/stock_reord_rule/__openerp__.py b/stock_reord_rule/__openerp__.py index 977e46f1ea9e..36eaabeb3ce8 100644 --- a/stock_reord_rule/__openerp__.py +++ b/stock_reord_rule/__openerp__.py @@ -46,7 +46,7 @@ This module doesn't need purchase module to work, but it's useful with that module.""", - 'author': 'Sergio Corato', + 'author': "Sergio Corato,Odoo Community Association (OCA)", 'website': 'http://www.icstools.it', 'depends': ['procurement', 'sale', diff --git a/stock_reserve/__openerp__.py b/stock_reserve/__openerp__.py index 61684f3c87ba..cd26446f5c2a 100644 --- a/stock_reserve/__openerp__.py +++ b/stock_reserve/__openerp__.py @@ -21,7 +21,7 @@ {'name': 'Stock Reserve', 'version': '0.1', - 'author': 'Camptocamp', + 'author': "Camptocamp,Odoo Community Association (OCA)", 'category': 'Warehouse', 'license': 'AGPL-3', 'complexity': 'normal', diff --git a/stock_reserve_sale/__openerp__.py b/stock_reserve_sale/__openerp__.py index 99522e98c60d..19126250fd93 100644 --- a/stock_reserve_sale/__openerp__.py +++ b/stock_reserve_sale/__openerp__.py @@ -21,7 +21,7 @@ {'name': 'Stock Reserve Sales', 'version': '0.1', - 'author': 'Camptocamp', + 'author': "Camptocamp,Odoo Community Association (OCA)", 'category': 'Warehouse', 'license': 'AGPL-3', 'complexity': 'normal', From 7596a0ba3f1a136224d77dcbeb0b14a6736ba772 Mon Sep 17 00:00:00 2001 From: Alexandre Fayolle Date: Fri, 27 Mar 2015 16:21:15 +0100 Subject: [PATCH 13/22] don't use travis container-based infrastructure --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index a14d7c6c2f87..e75bbd42fcbc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,4 @@ +sudo: required language: python python: From 5137b3bc6e9d891a988c18eb936ed4c50383642f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Faure-Lacroix?= Date: Thu, 16 Apr 2015 00:35:48 +0300 Subject: [PATCH 14/22] Add a warning message when there is not enough stock for a split --- quantity_warn_on_lot/__init__.py | 3 + quantity_warn_on_lot/__openerp__.py | 45 +++++ quantity_warn_on_lot/models/__init__.py | 2 + .../models/stock_move_split.py | 168 ++++++++++++++++++ .../views/stock_move_split.xml | 25 +++ 5 files changed, 243 insertions(+) create mode 100644 quantity_warn_on_lot/__init__.py create mode 100644 quantity_warn_on_lot/__openerp__.py create mode 100644 quantity_warn_on_lot/models/__init__.py create mode 100644 quantity_warn_on_lot/models/stock_move_split.py create mode 100644 quantity_warn_on_lot/views/stock_move_split.xml diff --git a/quantity_warn_on_lot/__init__.py b/quantity_warn_on_lot/__init__.py new file mode 100644 index 000000000000..cde864bae21a --- /dev/null +++ b/quantity_warn_on_lot/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import models diff --git a/quantity_warn_on_lot/__openerp__.py b/quantity_warn_on_lot/__openerp__.py new file mode 100644 index 000000000000..33fbdb190411 --- /dev/null +++ b/quantity_warn_on_lot/__openerp__.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module copyright (C) 2015 - present Savoir-faire Linux +# (). +# +# 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': 'Quantity warn on lot', + 'version': '0.1', + 'author': 'Savoir-faire Linux', + 'maintainer': 'Savoir-faire Linux', + 'website': 'http://www.savoirfairelinux.com', + 'license': 'AGPL-3', + 'category': 'Others', + 'summary': 'Warnings for invalid lot quantities', + 'description': """ +Add a warning message when user is trying to book a stock move with a lot number having not enough quantity available. +""", + 'depends': [ + 'stock', + ], + 'external_dependencies': { + 'python': [], + }, + 'data': [ + 'views/stock_move_split.xml', + ], + 'installable': True, + 'application': True, +} diff --git a/quantity_warn_on_lot/models/__init__.py b/quantity_warn_on_lot/models/__init__.py new file mode 100644 index 000000000000..023a0aab94fc --- /dev/null +++ b/quantity_warn_on_lot/models/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +from . import stock_move_split diff --git a/quantity_warn_on_lot/models/stock_move_split.py b/quantity_warn_on_lot/models/stock_move_split.py new file mode 100644 index 000000000000..80a91d91832e --- /dev/null +++ b/quantity_warn_on_lot/models/stock_move_split.py @@ -0,0 +1,168 @@ +# -*- coding: utf-8 -*- + +from openerp.osv import orm + + +class InvalidAmountException(Exception): + + """ + InvalidAmountException is raised when there is not enough products. + + It contains the product_id, prodlot_id and the actual quantity of + products after a successful update. + """ + + def __init__(self, product_id, prodlot_id, quantity): + """ + Create the InvalidAmountException object. + + :params product_id: The product in question + :params prodlot_id: The prodlot in question + :params quantity: The quantity of products available + """ + self.product_id = product_id + self.prodlot_id = prodlot_id + self.quantity = quantity + + +class StockMoveSplit(orm.TransientModel): + + """StockMoveSplit override to handle the amount of available products.""" + + _inherit = 'stock.move.split' + + def get_confirm_view_id(self, cr, uid, context=None): + """Get the default view id for the confirm view.""" + ir_model_data = self.pool.get('ir.model.data') + view_ref = ir_model_data.get_object_reference( + cr, uid, 'quantity_warn_on_lot', 'view_confirm_split' + ) + return view_ref and view_ref[1] or False + + def restore_split(self, cr, uid, ids, context=None): + """Restore the split to where we were before the warning.""" + res = { + 'type': 'ir.actions.act_window', + 'res_model': 'stock.move.split', + 'res_id': ids[0], + 'view_type': 'form', + 'view_mode': 'form', + 'target': 'new', + 'nodestroy': True, + 'context': context, + } + + return res + + def continue_split(self, cr, uid, ids, context=None): + """Continue splitting without and silence the warning.""" + if context is None: + context = {} + + # Adding continue_split to the context will silence + # the check for amount_quantity + context['continue_split'] = True + + return self.split_lot(cr, uid, ids, context=context) + + def fields_view_get( + self, cr, uid, + view_id=None, view_type='form', + context=None, toolbar=False, + submenu=False + ): + """Override the confirm_view and add a custom message.""" + base_func = super(StockMoveSplit, self).fields_view_get + ret = base_func(cr, uid, view_id, view_type, context=context) + + view_confirm_id = self.get_confirm_view_id(cr, uid, context) + + if view_confirm_id == view_id: + # Edit only the confirm window + message = context.get('warning_message', '') + # Simple and dirty replace {message} by our text + ret['arch'] = ret['arch'].replace('{message}', message) + + return ret + + def split_lot(self, cr, uid, ids, context=None): + """ + Override the split_lot method and handle errors. + + In case the available quantity is below 0, the split + method will raise an InvalidAmountException. This method + catch this error and instead open a new view that requires + confirmation to continue the split or keep editing. + + Before returning this method, we have to rollback changes to + be certain that none of the change made before raising the + error will get saved to the database. + """ + base_func = super(StockMoveSplit, self).split_lot + + try: + res = base_func(cr, uid, ids, context=context) + except InvalidAmountException as exc: + # Prevent changes to be saved + cr.rollback() + + view_id = self.get_confirm_view_id(cr, uid, context) + + message = ( + "La quantité restante de %(product_name)s du lot " + "%(lot_number)s du produit n'est pas suffisante. " + "La quantité restante dans ce numéro de lot est " + "%(quantity)d du numéro de lot en question. " + "Merci de corriger votre bon de livraison." + ).decode('utf-8') + + format_dict = { + "product_name": exc.product_id.name, + "lot_number": exc.prodlot_id.name, + "quantity": exc.quantity, + } + + context['warning_message'] = message % format_dict + + # Call the window + res = { + 'type': 'ir.actions.act_window', + 'view_id': view_id, + 'res_model': 'stock.move.split', + 'res_id': ids[0], + 'view_type': 'form', + 'view_mode': 'form', + 'target': 'new', + 'nodestroy': True, + 'context': context, + } + + return res + + def split(self, cr, uid, ids, move_ids, context=None): + """Check for the available stock quantity to be over 0.""" + if context is None: + context = {} + + base_func = super(StockMoveSplit, self).split + res = base_func(cr, uid, ids, move_ids, context) + + for data in self.browse(cr, uid, ids, context=context): + for move in data.line_exist_ids: + sum_in_draft = [ + m.product_qty + for m in move.prodlot_id.move_ids + if m.state == 'draft' and m.id not in move_ids + ] + + quantity_rest = ( + move.prodlot_id.stock_available - sum(sum_in_draft) + ) + + if quantity_rest < 0 and not context.get('continue_split'): + raise InvalidAmountException( + move.prodlot_id.product_id, + move.prodlot_id, quantity_rest + ) + + return res diff --git a/quantity_warn_on_lot/views/stock_move_split.xml b/quantity_warn_on_lot/views/stock_move_split.xml new file mode 100644 index 000000000000..6a9c75738497 --- /dev/null +++ b/quantity_warn_on_lot/views/stock_move_split.xml @@ -0,0 +1,25 @@ + + + + + Confirm split + stock.move.split + 1000 + +
+
+

Confirm move split

+
+

+ {message} +

+
+
+
+
+
+ +
+
From c8c7702504524d35519901f83244cf8bb5f5cf25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Faure-Lacroix?= Date: Thu, 16 Apr 2015 01:16:43 +0300 Subject: [PATCH 15/22] Added French translation --- quantity_warn_on_lot/i18n/fr.po | 47 ++++++++++++++++++ .../i18n/quantity_warn_on_lot.pot | 48 +++++++++++++++++++ .../models/stock_move_split.py | 31 +++++++++--- 3 files changed, 119 insertions(+), 7 deletions(-) create mode 100644 quantity_warn_on_lot/i18n/fr.po create mode 100644 quantity_warn_on_lot/i18n/quantity_warn_on_lot.pot diff --git a/quantity_warn_on_lot/i18n/fr.po b/quantity_warn_on_lot/i18n/fr.po new file mode 100644 index 000000000000..363e65a21da8 --- /dev/null +++ b/quantity_warn_on_lot/i18n/fr.po @@ -0,0 +1,47 @@ +# Translation of OpenERP Server. +# This file contains the translation of the following modules: +# * quantity_warn_on_lot +# +msgid "" +msgstr "" +"Project-Id-Version: OpenERP Server 7.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-04-15 22:11+0000\n" +"PO-Revision-Date: 2015-04-15 22:11+0000\n" +"Last-Translator: Loïc Faure-Lacroix\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: quantity_warn_on_lot +#: view:stock.move.split:0 +msgid "{message}" +msgstr "" + +#. module: quantity_warn_on_lot +#: view:stock.move.split:0 +msgid "Continue" +msgstr "Laisser tel quel" + +#. module: quantity_warn_on_lot +#: code:addons/quantity_warn_on_lot/models/stock_move_split.py:133 +#, python-format +msgid "The remaining amount of %(product_name)s in the lot %(lot_number)s isn't enough.The remaining amount of products in this lot number is %(quantity)d.Please correct your sale order" +msgstr "La quantité restante de %(product_name)s du lot %(lot_number)s n'est pas suffisante. La quantité restante dans ce numéro de lot est %(quantity)d. Merci de corriger votre bon de livraison." + +#. module: quantity_warn_on_lot +#: view:stock.move.split:0 +msgid "Confirm move split" +msgstr "Confirmez la division du mouvement" + +#. module: quantity_warn_on_lot +#: model:ir.model,name:quantity_warn_on_lot.model_stock_move_split +msgid "Split in Serial Numbers" +msgstr "Divisé en numéros de séries" + +#. module: quantity_warn_on_lot +#: view:stock.move.split:0 +msgid "Correct" +msgstr "Modifier" diff --git a/quantity_warn_on_lot/i18n/quantity_warn_on_lot.pot b/quantity_warn_on_lot/i18n/quantity_warn_on_lot.pot new file mode 100644 index 000000000000..49d7f92207a3 --- /dev/null +++ b/quantity_warn_on_lot/i18n/quantity_warn_on_lot.pot @@ -0,0 +1,48 @@ +# Translation of OpenERP Server. +# This file contains the translation of the following modules: +# * quantity_warn_on_lot +# +msgid "" +msgstr "" +"Project-Id-Version: OpenERP Server 7.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-04-15 22:11+0000\n" +"PO-Revision-Date: 2015-04-15 22:11+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: quantity_warn_on_lot +#: view:stock.move.split:0 +msgid "{message}" +msgstr "" + +#. module: quantity_warn_on_lot +#: view:stock.move.split:0 +msgid "Continue" +msgstr "" + +#. module: quantity_warn_on_lot +#: code:addons/quantity_warn_on_lot/models/stock_move_split.py:133 +#, python-format +msgid "The remaining amount of %(product_name)s in the lot %(lot_number)s of the product isn't enough.The remaining amount of products in this lot number is %(quantity)d.Please correct your sale order" +msgstr "" + +#. module: quantity_warn_on_lot +#: view:stock.move.split:0 +msgid "Confirm move split" +msgstr "" + +#. module: quantity_warn_on_lot +#: model:ir.model,name:quantity_warn_on_lot.model_stock_move_split +msgid "Split in Serial Numbers" +msgstr "" + +#. module: quantity_warn_on_lot +#: view:stock.move.split:0 +msgid "Correct" +msgstr "" + diff --git a/quantity_warn_on_lot/models/stock_move_split.py b/quantity_warn_on_lot/models/stock_move_split.py index 80a91d91832e..f25c13031ba4 100644 --- a/quantity_warn_on_lot/models/stock_move_split.py +++ b/quantity_warn_on_lot/models/stock_move_split.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- from openerp.osv import orm +from openerp.tools.translate import _ class InvalidAmountException(Exception): @@ -52,6 +53,14 @@ def restore_split(self, cr, uid, ids, context=None): 'context': context, } + active_id = context.get('active_id') + move = self.pool['stock.move'].browse(cr, uid, active_id) + picking = move.picking_id + + picking.message_post( + "Pressed correct button in the confirmation window" + ) + return res def continue_split(self, cr, uid, ids, context=None): @@ -63,6 +72,14 @@ def continue_split(self, cr, uid, ids, context=None): # the check for amount_quantity context['continue_split'] = True + active_id = context.get('active_id') + move = self.pool['stock.move'].browse(cr, uid, active_id) + picking = move.picking_id + + picking.message_post( + "Pressed continue button in the confirmation window" + ) + return self.split_lot(cr, uid, ids, context=context) def fields_view_get( @@ -108,13 +125,13 @@ def split_lot(self, cr, uid, ids, context=None): view_id = self.get_confirm_view_id(cr, uid, context) - message = ( - "La quantité restante de %(product_name)s du lot " - "%(lot_number)s du produit n'est pas suffisante. " - "La quantité restante dans ce numéro de lot est " - "%(quantity)d du numéro de lot en question. " - "Merci de corriger votre bon de livraison." - ).decode('utf-8') + message = _( + "The remaining amount of %(product_name)s in the lot " + "%(lot_number)s of the product isn't enough." + "The remaining amount of products in this lot number is " + "%(quantity)d." + "Please correct your sale order" + ) format_dict = { "product_name": exc.product_id.name, From dd80cb50c9b19d18d74f727c9921f761e8a9acba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Faure-Lacroix?= Date: Thu, 16 Apr 2015 01:19:43 +0300 Subject: [PATCH 16/22] Fix move count and added more translatable text --- quantity_warn_on_lot/i18n/fr.po | 12 ++++++++++++ quantity_warn_on_lot/i18n/quantity_warn_on_lot.pot | 12 ++++++++++++ quantity_warn_on_lot/models/stock_move_split.py | 6 +++--- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/quantity_warn_on_lot/i18n/fr.po b/quantity_warn_on_lot/i18n/fr.po index 363e65a21da8..6952d685e8fd 100644 --- a/quantity_warn_on_lot/i18n/fr.po +++ b/quantity_warn_on_lot/i18n/fr.po @@ -25,6 +25,18 @@ msgstr "" msgid "Continue" msgstr "Laisser tel quel" +#. module: quantity_warn_on_lot +#: code:addons/quantity_warn_on_lot/models/stock_move_split.py:80 +#, python-format +msgid "Pressed continue button in the confirmation window" +msgstr "A cliqué sur le bouton 'laisser tel quel' dans la fenêtre de confirmation." + +#. module: quantity_warn_on_lot +#: code:addons/quantity_warn_on_lot/models/stock_move_split.py:61 +#, python-format +msgid "Pressed correct button in the confirmation window" +msgstr "A cliqué sur le bouton 'modifier' dans la fenêtre de confirmations." + #. module: quantity_warn_on_lot #: code:addons/quantity_warn_on_lot/models/stock_move_split.py:133 #, python-format diff --git a/quantity_warn_on_lot/i18n/quantity_warn_on_lot.pot b/quantity_warn_on_lot/i18n/quantity_warn_on_lot.pot index 49d7f92207a3..e329a9cd6ced 100644 --- a/quantity_warn_on_lot/i18n/quantity_warn_on_lot.pot +++ b/quantity_warn_on_lot/i18n/quantity_warn_on_lot.pot @@ -25,6 +25,18 @@ msgstr "" msgid "Continue" msgstr "" +#. module: quantity_warn_on_lot +#: code:addons/quantity_warn_on_lot/models/stock_move_split.py:80 +#, python-format +msgid "Pressed continue button in the confirmation window" +msgstr "" + +#. module: quantity_warn_on_lot +#: code:addons/quantity_warn_on_lot/models/stock_move_split.py:61 +#, python-format +msgid "Pressed correct button in the confirmation window" +msgstr "" + #. module: quantity_warn_on_lot #: code:addons/quantity_warn_on_lot/models/stock_move_split.py:133 #, python-format diff --git a/quantity_warn_on_lot/models/stock_move_split.py b/quantity_warn_on_lot/models/stock_move_split.py index f25c13031ba4..3c00f6481a26 100644 --- a/quantity_warn_on_lot/models/stock_move_split.py +++ b/quantity_warn_on_lot/models/stock_move_split.py @@ -58,7 +58,7 @@ def restore_split(self, cr, uid, ids, context=None): picking = move.picking_id picking.message_post( - "Pressed correct button in the confirmation window" + _("Pressed correct button in the confirmation window") ) return res @@ -77,7 +77,7 @@ def continue_split(self, cr, uid, ids, context=None): picking = move.picking_id picking.message_post( - "Pressed continue button in the confirmation window" + _("Pressed continue button in the confirmation window") ) return self.split_lot(cr, uid, ids, context=context) @@ -169,7 +169,7 @@ def split(self, cr, uid, ids, move_ids, context=None): sum_in_draft = [ m.product_qty for m in move.prodlot_id.move_ids - if m.state == 'draft' and m.id not in move_ids + if m.state == 'draft' ] quantity_rest = ( From 9195d17073207c887da27e57203e965ba824b325 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Faure-Lacroix?= Date: Wed, 22 Apr 2015 19:47:47 +0300 Subject: [PATCH 17/22] Fix pep8 error --- quantity_warn_on_lot/__openerp__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/quantity_warn_on_lot/__openerp__.py b/quantity_warn_on_lot/__openerp__.py index 33fbdb190411..4fd54ae44863 100644 --- a/quantity_warn_on_lot/__openerp__.py +++ b/quantity_warn_on_lot/__openerp__.py @@ -29,7 +29,8 @@ 'category': 'Others', 'summary': 'Warnings for invalid lot quantities', 'description': """ -Add a warning message when user is trying to book a stock move with a lot number having not enough quantity available. +Add a warning message when user is trying to book a stock move with a lot +number having not enough quantity available. """, 'depends': [ 'stock', @@ -41,5 +42,5 @@ 'views/stock_move_split.xml', ], 'installable': True, - 'application': True, + 'application': False, } From f95a89565bc95b1eaee6e9b1c28a2195cff5402e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Faure-Lacroix?= Date: Wed, 22 Apr 2015 19:48:44 +0300 Subject: [PATCH 18/22] Added copyrights --- quantity_warn_on_lot/models/__init__.py | 20 +++++++++++++++++++ .../models/stock_move_split.py | 20 +++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/quantity_warn_on_lot/models/__init__.py b/quantity_warn_on_lot/models/__init__.py index 023a0aab94fc..0b372baf1ab3 100644 --- a/quantity_warn_on_lot/models/__init__.py +++ b/quantity_warn_on_lot/models/__init__.py @@ -1,2 +1,22 @@ # -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module copyright (C) 2015 - present Savoir-faire Linux +# (). +# +# 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 stock_move_split diff --git a/quantity_warn_on_lot/models/stock_move_split.py b/quantity_warn_on_lot/models/stock_move_split.py index 3c00f6481a26..b301c2c6f4f3 100644 --- a/quantity_warn_on_lot/models/stock_move_split.py +++ b/quantity_warn_on_lot/models/stock_move_split.py @@ -1,4 +1,24 @@ # -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module copyright (C) 2015 - present Savoir-faire Linux +# (). +# +# 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 openerp.osv import orm from openerp.tools.translate import _ From fda31b9d8abf34f96b1b26fd93fef650fcf04766 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Faure-Lacroix?= Date: Wed, 22 Apr 2015 22:05:57 +0300 Subject: [PATCH 19/22] Catch value error in case view isn't yet loaded --- quantity_warn_on_lot/models/stock_move_split.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/quantity_warn_on_lot/models/stock_move_split.py b/quantity_warn_on_lot/models/stock_move_split.py index b301c2c6f4f3..1874c9e2cfff 100644 --- a/quantity_warn_on_lot/models/stock_move_split.py +++ b/quantity_warn_on_lot/models/stock_move_split.py @@ -19,10 +19,13 @@ # along with this program. If not, see . # ############################################################################## +import logging from openerp.osv import orm from openerp.tools.translate import _ +_logger = logging.getLogger(__name__) + class InvalidAmountException(Exception): @@ -55,9 +58,15 @@ class StockMoveSplit(orm.TransientModel): def get_confirm_view_id(self, cr, uid, context=None): """Get the default view id for the confirm view.""" ir_model_data = self.pool.get('ir.model.data') - view_ref = ir_model_data.get_object_reference( - cr, uid, 'quantity_warn_on_lot', 'view_confirm_split' - ) + + try: + view_ref = ir_model_data.get_object_reference( + cr, uid, 'quantity_warn_on_lot', 'view_confirm_split' + ) + except ValueError as exc: + _logger.debug(exc) + view_ref = None + return view_ref and view_ref[1] or False def restore_split(self, cr, uid, ids, context=None): From 35f1a8e6bb25ff6e641a7524468fa22fdef78aea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Faure-Lacroix?= Date: Thu, 23 Apr 2015 23:43:44 +0300 Subject: [PATCH 20/22] Add copyrights --- quantity_warn_on_lot/__init__.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/quantity_warn_on_lot/__init__.py b/quantity_warn_on_lot/__init__.py index cde864bae21a..4d6e147beda8 100644 --- a/quantity_warn_on_lot/__init__.py +++ b/quantity_warn_on_lot/__init__.py @@ -1,3 +1,22 @@ # -*- coding: utf-8 -*- - +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module copyright (C) 2015 - present Savoir-faire Linux +# (). +# +# 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 0f43908beb7b0df0be0adb166b89fce19cb18366 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Faure-Lacroix?= Date: Thu, 23 Apr 2015 23:45:13 +0300 Subject: [PATCH 21/22] Adding xml version --- quantity_warn_on_lot/views/stock_move_split.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/quantity_warn_on_lot/views/stock_move_split.xml b/quantity_warn_on_lot/views/stock_move_split.xml index 6a9c75738497..bcf558661a52 100644 --- a/quantity_warn_on_lot/views/stock_move_split.xml +++ b/quantity_warn_on_lot/views/stock_move_split.xml @@ -1,3 +1,4 @@ + From 9798b451081673ce6eca6c95740c72bcb5e48123 Mon Sep 17 00:00:00 2001 From: EL HADJI DEM Date: Fri, 8 May 2015 16:43:20 -0400 Subject: [PATCH 22/22] [UPD] Remove view and clean the model No need adding the view and just overriding one method in the StockMoveSplit class --- quantity_warn_on_lot/__openerp__.py | 1 - .../models/stock_move_split.py | 197 +++--------------- .../views/stock_move_split.xml | 26 --- 3 files changed, 27 insertions(+), 197 deletions(-) delete mode 100644 quantity_warn_on_lot/views/stock_move_split.xml diff --git a/quantity_warn_on_lot/__openerp__.py b/quantity_warn_on_lot/__openerp__.py index 4fd54ae44863..4329cc2f114b 100644 --- a/quantity_warn_on_lot/__openerp__.py +++ b/quantity_warn_on_lot/__openerp__.py @@ -39,7 +39,6 @@ 'python': [], }, 'data': [ - 'views/stock_move_split.xml', ], 'installable': True, 'application': False, diff --git a/quantity_warn_on_lot/models/stock_move_split.py b/quantity_warn_on_lot/models/stock_move_split.py index 1874c9e2cfff..3fa97abe6025 100644 --- a/quantity_warn_on_lot/models/stock_move_split.py +++ b/quantity_warn_on_lot/models/stock_move_split.py @@ -27,188 +27,45 @@ _logger = logging.getLogger(__name__) -class InvalidAmountException(Exception): - - """ - InvalidAmountException is raised when there is not enough products. - - It contains the product_id, prodlot_id and the actual quantity of - products after a successful update. - """ - - def __init__(self, product_id, prodlot_id, quantity): - """ - Create the InvalidAmountException object. - - :params product_id: The product in question - :params prodlot_id: The prodlot in question - :params quantity: The quantity of products available - """ - self.product_id = product_id - self.prodlot_id = prodlot_id - self.quantity = quantity - - class StockMoveSplit(orm.TransientModel): """StockMoveSplit override to handle the amount of available products.""" _inherit = 'stock.move.split' - def get_confirm_view_id(self, cr, uid, context=None): - """Get the default view id for the confirm view.""" - ir_model_data = self.pool.get('ir.model.data') - - try: - view_ref = ir_model_data.get_object_reference( - cr, uid, 'quantity_warn_on_lot', 'view_confirm_split' - ) - except ValueError as exc: - _logger.debug(exc) - view_ref = None - - return view_ref and view_ref[1] or False - - def restore_split(self, cr, uid, ids, context=None): - """Restore the split to where we were before the warning.""" - res = { - 'type': 'ir.actions.act_window', - 'res_model': 'stock.move.split', - 'res_id': ids[0], - 'view_type': 'form', - 'view_mode': 'form', - 'target': 'new', - 'nodestroy': True, - 'context': context, - } - - active_id = context.get('active_id') - move = self.pool['stock.move'].browse(cr, uid, active_id) - picking = move.picking_id - - picking.message_post( - _("Pressed correct button in the confirmation window") - ) - - return res - - def continue_split(self, cr, uid, ids, context=None): - """Continue splitting without and silence the warning.""" - if context is None: - context = {} - - # Adding continue_split to the context will silence - # the check for amount_quantity - context['continue_split'] = True - - active_id = context.get('active_id') - move = self.pool['stock.move'].browse(cr, uid, active_id) - picking = move.picking_id - - picking.message_post( - _("Pressed continue button in the confirmation window") - ) - - return self.split_lot(cr, uid, ids, context=context) - - def fields_view_get( - self, cr, uid, - view_id=None, view_type='form', - context=None, toolbar=False, - submenu=False - ): - """Override the confirm_view and add a custom message.""" - base_func = super(StockMoveSplit, self).fields_view_get - ret = base_func(cr, uid, view_id, view_type, context=context) - - view_confirm_id = self.get_confirm_view_id(cr, uid, context) - - if view_confirm_id == view_id: - # Edit only the confirm window - message = context.get('warning_message', '') - # Simple and dirty replace {message} by our text - ret['arch'] = ret['arch'].replace('{message}', message) - - return ret - - def split_lot(self, cr, uid, ids, context=None): - """ - Override the split_lot method and handle errors. - - In case the available quantity is below 0, the split - method will raise an InvalidAmountException. This method - catch this error and instead open a new view that requires - confirmation to continue the split or keep editing. + def split(self, cr, uid, ids, move_ids, context=None): + """ To split stock moves into serial numbers - Before returning this method, we have to rollback changes to - be certain that none of the change made before raising the - error will get saved to the database. + :param move_ids: the ID or list of IDs of stock move we want to split """ - base_func = super(StockMoveSplit, self).split_lot - - try: - res = base_func(cr, uid, ids, context=context) - except InvalidAmountException as exc: - # Prevent changes to be saved - cr.rollback() - - view_id = self.get_confirm_view_id(cr, uid, context) - - message = _( - "The remaining amount of %(product_name)s in the lot " - "%(lot_number)s of the product isn't enough." - "The remaining amount of products in this lot number is " - "%(quantity)d." - "Please correct your sale order" - ) - - format_dict = { - "product_name": exc.product_id.name, - "lot_number": exc.prodlot_id.name, - "quantity": exc.quantity, - } - - context['warning_message'] = message % format_dict - - # Call the window - res = { - 'type': 'ir.actions.act_window', - 'view_id': view_id, - 'res_model': 'stock.move.split', - 'res_id': ids[0], - 'view_type': 'form', - 'view_mode': 'form', - 'target': 'new', - 'nodestroy': True, - 'context': context, - } - - return res - - def split(self, cr, uid, ids, move_ids, context=None): - """Check for the available stock quantity to be over 0.""" if context is None: context = {} - base_func = super(StockMoveSplit, self).split res = base_func(cr, uid, ids, move_ids, context) - + move_obj = self.pool.get('stock.move') + uom_obj = self.pool.get('product.uom') for data in self.browse(cr, uid, ids, context=context): - for move in data.line_exist_ids: - sum_in_draft = [ - m.product_qty - for m in move.prodlot_id.move_ids - if m.state == 'draft' - ] - - quantity_rest = ( - move.prodlot_id.stock_available - sum(sum_in_draft) - ) - - if quantity_rest < 0 and not context.get('continue_split'): - raise InvalidAmountException( - move.prodlot_id.product_id, - move.prodlot_id, quantity_rest - ) + for move in move_obj.browse(cr, uid, move_ids, context=context): + product_uom = move.product_uom + if data.use_exist: + lines = [l for l in data.line_exist_ids if l] + else: + lines = [l for l in data.line_ids if l] + total_move_qty = 0.0 + for line in lines: + quantity = line.quantity + total_move_qty += quantity + amount_actual = uom_obj._compute_qty_obj( + cr, uid, move.product_uom, + line.prodlot_id.stock_available, + product_uom, context=context) + if (data.location_id.usage == 'internal') and \ + (quantity > (amount_actual or 0.0)): + raise orm.except_orm( + _('Insufficient Stock for Serial Number !'), + _('You are moving %.2f %s but only %.2f %s ' + 'available for this serial number.') % + (total_move_qty, move.product_uom.name, + amount_actual, move.product_uom.name)) return res diff --git a/quantity_warn_on_lot/views/stock_move_split.xml b/quantity_warn_on_lot/views/stock_move_split.xml deleted file mode 100644 index bcf558661a52..000000000000 --- a/quantity_warn_on_lot/views/stock_move_split.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - Confirm split - stock.move.split - 1000 - -
-
-

Confirm move split

-
-

- {message} -

- -
-
-
- -
-