openerp-community-reviewer team mailing list archive
-
openerp-community-reviewer team
-
Mailing list archive
-
Message #04742
[Merge] lp:~numerigraphe-team/stock-logistic-warehouse/7.0-inventory-date-constraint into lp:stock-logistic-warehouse
Loïc Bellier - Numérigraphe has proposed merging lp:~numerigraphe-team/stock-logistic-warehouse/7.0-inventory-date-constraint into lp:stock-logistic-warehouse.
Requested reviews:
Stock and Logistic Core Editors (stock-logistic-core-editors)
For more details, see:
https://code.launchpad.net/~numerigraphe-team/stock-logistic-warehouse/7.0-inventory-date-constraint/+merge/210632
This proposal blocks the stock moves if move date is before the latest inventory date.
--
https://code.launchpad.net/~numerigraphe-team/stock-logistic-warehouse/7.0-inventory-date-constraint/+merge/210632
Your team Stock and Logistic Core Editors is requested to review the proposed merge of lp:~numerigraphe-team/stock-logistic-warehouse/7.0-inventory-date-constraint into lp:stock-logistic-warehouse.
=== added directory 'stock_inventory_date_constraint'
=== added file 'stock_inventory_date_constraint/__init__.py'
--- stock_inventory_date_constraint/__init__.py 1970-01-01 00:00:00 +0000
+++ stock_inventory_date_constraint/__init__.py 2014-03-12 15:28:57 +0000
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# This module is copyright (C) 2011 Numérigraphe SARL. All Rights Reserved.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import stock
=== added file 'stock_inventory_date_constraint/__openerp__.py'
--- stock_inventory_date_constraint/__openerp__.py 1970-01-01 00:00:00 +0000
+++ stock_inventory_date_constraint/__openerp__.py 2014-03-12 15:28:57 +0000
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# This module is copyright (C) 2011 Numérigraphe SARL. All Rights Reserved.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+{
+ "name": "Refuse stock move happening before the date of any inventory done",
+ "version": "1.0",
+ "depends": ["stock"],
+ "author": u"Numérigraphe",
+ "category": "Stock / Inventory",
+ "description": """
+ The goal of the module is to refuse stock move happening before the date of any inventory done
+ for a product/lot/location.
+
+ This module corrects the following bug / feature (#588154):
+ "I setup a physical inventory with date 2010/05/19. Stock is 5 for product x
+ When I have an internal move for 1 piece of product x with date 2010/05/01,
+ the current calculated stock at 2010/06/01 is 4 which seems to me incorrect as the current stock
+ should reflect the physical inventory on 2010/05/19 and be 5."
+ url : https://bugs.launchpad.net/openobject-addons/+bug/588154
+ """,
+ "test": ["test/stock_inventory_date.yml"],
+ "demo": ["stock_demo.xml"]
+}
=== added directory 'stock_inventory_date_constraint/i18n'
=== added file 'stock_inventory_date_constraint/i18n/fr.po'
--- stock_inventory_date_constraint/i18n/fr.po 1970-01-01 00:00:00 +0000
+++ stock_inventory_date_constraint/i18n/fr.po 2014-03-12 15:28:57 +0000
@@ -0,0 +1,109 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * stock_inventory_date_constraint
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 6.0.4\n"
+"Report-Msgid-Bugs-To: support@xxxxxxxxxxx\n"
+"POT-Creation-Date: 2013-09-25 13:34+0000\n"
+"PO-Revision-Date: 2013-09-25 13:34+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_inventory_date_constraint
+#: code:addons/stock_inventory_date_constraint/stock.py:85
+#: code:addons/stock_inventory_date_constraint/stock.py:135
+#, python-format
+msgid "- %s (ID %d)"
+msgstr "- %s (Id. %d)"
+
+#. module: stock_inventory_date_constraint
+#: constraint:stock.move:0
+msgid "A Physical Inventory is being conducted at this location"
+msgstr "Un inventaire est déjà en cours à cet emplacement"
+
+#. module: stock_inventory_date_constraint
+#: constraint:stock.inventory:0
+msgid "Error! You can not create recursive inventories."
+msgstr "Erreur! Vous ne pouvez pas créer un inventaire récursif."
+
+#. module: stock_inventory_date_constraint
+#: constraint:stock.inventory.line:0
+msgid "Error: duplicates lines"
+msgstr "Erreur: lignes en double"
+
+#. module: stock_inventory_date_constraint
+#: model:ir.model,name:stock_inventory_date_constraint.model_stock_inventory
+msgid "Gestion des stocks"
+msgstr "Gestion des stocks"
+
+#. module: stock_inventory_date_constraint
+#: model:ir.model,name:stock_inventory_date_constraint.model_stock_inventory_line
+msgid "Ligne d'inventaire"
+msgstr "Ligne d'inventaire"
+
+#. module: stock_inventory_date_constraint
+#: model:ir.model,name:stock_inventory_date_constraint.model_stock_move
+msgid "Mouvement de stock"
+msgstr "Mouvement de stock"
+
+#. module: stock_inventory_date_constraint
+#: constraint:stock.move:0
+msgid "One or more lots are awaiting quality control and cannot be moved."
+msgstr "Un ou plusieurs lots sont en attente de contrôle qualité, et ne peuvent pas être déplacés."
+
+#. module: stock_inventory_date_constraint
+#: constraint:stock.inventory:0
+msgid "Other Physical inventories are being conducted using the same Locations."
+msgstr "Erreur: certains emplacements sont déjà dans un autre inventaire."
+
+#. module: stock_inventory_date_constraint
+#: code:addons/stock_inventory_date_constraint/stock.py:89
+#: code:addons/stock_inventory_date_constraint/stock.py:139
+#, python-format
+msgid "The changes cannot be made because they conflict the following Stock Inventories:\n"
+""
+msgstr "Les changements demandés sont impossibles car ils sont en conflit avec les inventaires suivants :\n"
+""
+
+#. module: stock_inventory_date_constraint
+#: code:addons/stock_inventory_date_constraint/stock.py:164
+#, python-format
+msgid "The following lines are duplicates and will be deleted :\n"
+"%s"
+msgstr "Les lignes suivantes sont en double et seront effacées :\n"
+"%s"
+
+#. module: stock_inventory_date_constraint
+#: code:addons/stock_inventory_date_constraint/stock.py:163
+#, python-format
+msgid "Warning : duplicates lines"
+msgstr "Attention : lignes en double"
+
+#. module: stock_inventory_date_constraint
+#: code:addons/stock_inventory_date_constraint/stock.py:88
+#: code:addons/stock_inventory_date_constraint/stock.py:138
+#, python-format
+msgid "Wrong Stock Moves"
+msgstr "Mouvements de stock incorrects"
+
+#. module: stock_inventory_date_constraint
+#: constraint:stock.move:0
+msgid "You must assign a production lot for this product"
+msgstr "Vous devez affecter un lot de fabrication à ce produit."
+
+#. module: stock_inventory_date_constraint
+#: constraint:stock.inventory.line:0
+msgid "You must not create same inventory line Product, Location, Lot on the same date"
+msgstr "Vous ne pouvez pas créer plusieurs lignes d'inventaires pour le même produit, lot, emplacement à la même date"
+
+#. module: stock_inventory_date_constraint
+#: constraint:stock.move:0
+msgid "You try to assign a lot which is not from the same product"
+msgstr "Vous essayez d'affecter un lot qui n'est pas pour ce produit."
+
=== added file 'stock_inventory_date_constraint/stock.py'
--- stock_inventory_date_constraint/stock.py 1970-01-01 00:00:00 +0000
+++ stock_inventory_date_constraint/stock.py 2014-03-12 15:28:57 +0000
@@ -0,0 +1,170 @@
+# encoding: utf-8
+##############################################################################
+#
+# This module is copyright (C) 2011 Numérigraphe SARL. All Rights Reserved.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import osv, orm
+from openerp.tools.translate import _
+
+
+class StockInventoryCancelable(osv.osv):
+ """Make inventories cancelable despite the constraint on stock move dates"""
+ _inherit = "stock.inventory"
+
+ def action_cancel_inventory(self, cr, uid, ids, context=None):
+ """Inject a context key to not block the deletion of stock moves"""
+ if context is None:
+ context = {}
+ else:
+ context = context.copy()
+ context['ignore_inventories'] = ids
+ return super(StockInventoryCancelable, self).action_cancel_inventory(
+ cr, uid, ids, context=context)
+
+
+class StockMoveConstraint(osv.osv):
+
+ _inherit = 'stock.move'
+
+ def _past_inventories(self, cr, uid, product_ids, prodlot_ids, location_ids, limit_date, context=None):
+ """Search for inventories already finished after a given date"""
+ # Search for inventory lines with the given location / prodlot / product
+ if context is None:
+ context = {}
+ sil_obj = self.pool.get('stock.inventory.line')
+ sil_ids = sil_obj.search(cr, uid, [('product_id', 'in', product_ids),
+ ('prod_lot_id', 'in', prodlot_ids),
+ ('location_id', 'in', location_ids),
+ ('inventory_id', 'not in', context.get('ignore_inventories', []))],
+ context=context)
+ if not sil_ids:
+ return []
+ # Search for inventories dates after the move containing those lines
+ inventory_ids = [i['inventory_id'][0]
+ for i in sil_obj.read(cr, uid,
+ sil_ids, ['inventory_id'],
+ context=context)]
+ return self.pool.get('stock.inventory').search(
+ cr, uid, [('id', 'in', inventory_ids),
+ ('state', '=', 'done'),
+ ('date', '>=', limit_date)], context=context)
+
+ def create(self, cr, uid, vals, context=None):
+ """Make sure the Stock Move being created doesn't make a finished inventory wrong"""
+ # Take default values into account
+ old_vals = vals
+ vals = self.default_get(cr, uid,
+ ['product_id', 'prodlot_id', 'location_id',
+ 'location_dest_id', 'date'],
+ context=context)
+ vals.update(old_vals)
+
+ if vals.get('state') == 'done':
+ inv_ids = self._past_inventories(cr, uid, [vals.get('product_id')],
+ [vals.get('prodlot_id')],
+ [vals.get('location_id'),
+ vals.get('location_dest_id')],
+ vals.get('date'), context=context)
+ if inv_ids:
+ # Make a message string with the names of the Inventories
+ inventories = self.pool.get("stock.inventory").browse(cr, uid, inv_ids, context=context)
+ tab_inventories = {i.id: i.name for i in inventories}
+ msg = "\n".join([_("- %s (ID %d)") % (name, i)
+ for (i, name) in tab_inventories.iteritems()])
+ raise orm.except_orm(
+ _('Wrong Stock Moves'),
+ _('The changes cannot be made because they conflict the following Stock Inventories:\n') + msg)
+ return super(StockMoveConstraint, self).create(cr, uid, vals, context=context)
+
+ def write(self, cr, uid, ids, vals, context=None):
+ """Make sure the changes being made to the Stock Moves don't make a finished inventory wrong"""
+ # XXX: the logic here is not 100% proven and may still allow some corner cases
+ # The difficulty is that inventories can be changed by doing or undoing a move,
+ # changing it's date, product, prodlot etc.
+ inv_ids = []
+ # Nothing to do if we change no value that can affect past inventories
+ if ('state' not in vals
+ and 'date' not in vals
+ and 'locatation_id' not in vals
+ and 'locatation_dest_id' not in vals
+ and 'prodlot_id' not in vals
+ and 'product_id' not in vals):
+ return super(StockMoveConstraint, self).write(cr, uid, ids, vals, context=context)
+
+ if not isinstance(ids, list):
+ ids = [ids]
+ for move in self.browse(cr, uid, ids, context=context):
+ # Decide the limit date of the inventories that could be made wrong, depending on how the Stock Move is being changed
+ new_state = vals.get('state', move.state)
+ if move.state == 'done':
+ if new_state == 'done':
+ # Get the earliest date from the new and the old date
+ limit_date = min(move.date, vals['date'])
+ else:
+ limit_date = move.date
+ else:
+ if new_state == 'done':
+ limit_date = vals.get('date', move.date)
+ else:
+ continue
+
+ # Search for inventories conflicting the change
+ inv_ids.extend(self._past_inventories(cr, uid,
+ [vals.get('product_id'), move.product_id.id],
+ [vals.get('prodlot_id'), move.prodlot_id.id],
+ [vals.get('location_id'), move.location_id.id,
+ vals.get('location_dest_id'), move.location_dest_id.id],
+ limit_date, context=context))
+
+ if inv_ids:
+ # Make a message string with the names of the Inventories
+ inventories = self.pool.get("stock.inventory").browse(cr, uid, inv_ids, context=context)
+ tab_inventories = {i.id: i.name for i in inventories}
+ msg = "\n".join([_("- %s (ID %d)") % (name, i)
+ for (i, name) in tab_inventories.iteritems()])
+ raise orm.except_orm(
+ _('Wrong Stock Moves'),
+ _('The changes cannot be made because they conflict the following Stock Inventories:\n') + msg)
+ return super(StockMoveConstraint, self).write(cr, uid, ids, vals, context=context)
+
+
+class stock_inventory_line(osv.osv):
+ """ Check if the new line will not be a duplicate line.
+ Look for location_id, product_id and prod_lot_id.
+ """
+ _inherit = 'stock.inventory.line'
+
+ def _check_duplicates_line(self, cr, uid, ids, context=None):
+ """ Check for duplicates lines """
+ message = ''
+ for line in self.browse(cr, uid, ids, context=context):
+ duplicates_count = self.search(cr, uid, [('location_id', '=', line.location_id.id),
+ ('product_id', '=', line.product_id.id),
+ ('prod_lot_id', '=', line.prod_lot_id.id),
+ ('inventory_id', '=', line.inventory_id.id)
+ ], context=context, count=True)
+ if duplicates_count > 1:
+ message = '%s - %s - %s\n' % (line.location_id.name, line.prod_lot_id.name, line.product_id.name)
+
+ if message:
+ raise osv.except_osv(_('Warning : duplicates lines'),
+ _('The following lines are duplicates and will be deleted :\n%s') % message)
+ return True
+
+ _constraints = [(_check_duplicates_line, 'Error: duplicates lines',
+ ['location_id', 'product_id', 'prod_lot_id']), ]
=== added file 'stock_inventory_date_constraint/stock_demo.xml'
--- stock_inventory_date_constraint/stock_demo.xml 1970-01-01 00:00:00 +0000
+++ stock_inventory_date_constraint/stock_demo.xml 2014-03-12 15:28:57 +0000
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data noupdate="0">
+
+ <!-- Record a production lot we can use in the tests. -->
+ <record id="lot_test0" model="stock.production.lot">
+ <field name="product_id" ref="product.product_product_10" />
+ </record>
+
+ <!-- Record inventories we can use in the tests. -->
+ <!-- We need them in the demo data because test data is rolled back
+ whenever an exception is raised. -->
+
+ <!-- Record an inventory to make sure the next one will have stock moves posted. -->
+ <record id="stock_inventory_init" model="stock.inventory">
+ <field name="name">Initial Stock situation for testing the date constraint</field>
+ <field name="state">draft</field>
+ <field name="date">2025-01-01 12:05:27</field>
+ </record>
+ <record id="stock_inventory_line" model="stock.inventory.line">
+ <field name="inventory_id" ref="stock_inventory_init" />
+ <field name="product_id" ref="product.product_product_10" />
+ <field name="prod_lot_id" ref="lot_test0"/>
+ <field name="product_uom" ref="product.product_uom_unit" />
+ <field name="product_qty">27.0</field>
+ <field name="location_id" ref="stock.stock_location_components" />
+ </record>
+ <function model="stock.inventory" name="action_confirm">
+ <function
+ eval="[[('id', '=', ref('stock_inventory_init'))]]"
+ model="stock.inventory" name="search" />
+ </function>
+ <function model="stock.inventory" name="action_done">
+ <function
+ eval="[[('id', '=', ref('stock_inventory_init'))]]"
+ model="stock.inventory" name="search" />
+ </function>
+
+ <!-- The next inventory is dated in the distant future because we want
+ to test it against stock moves made before, but stock.move.action_done forces
+ the move date to today. -->
+ <record id="stock_inventory_physical0" model="stock.inventory">
+ <field name="name">Stock situation in 2099 for testing the date constraint</field>
+ <field name="date">2099-01-01 12:05:27</field>
+ <field name="state">draft</field>
+ </record>
+ <record id="stock_inventory_line_0" model="stock.inventory.line">
+ <field name="inventory_id" ref="stock_inventory_physical0" />
+ <field name="product_id" ref="product.product_product_10" />
+ <field name="prod_lot_id" ref="lot_test0"/>
+ <field name="product_uom" ref="product.product_uom_unit" />
+ <field name="product_qty">10.0</field>
+ <field name="location_id" ref="stock.stock_location_components" />
+ </record>
+ <function model="stock.inventory" name="action_confirm">
+ <function
+ eval="[[('id', '=', ref('stock_inventory_physical0'))]]"
+ model="stock.inventory" name="search" />
+ </function>
+ <function model="stock.inventory" name="action_done">
+ <function
+ eval="[[('id', '=', ref('stock_inventory_physical0'))]]"
+ model="stock.inventory" name="search" />
+ </function>
+ </data>
+</openerp>
=== added directory 'stock_inventory_date_constraint/test'
=== added file 'stock_inventory_date_constraint/test/stock_inventory_date.yml'
--- stock_inventory_date_constraint/test/stock_inventory_date.yml 1970-01-01 00:00:00 +0000
+++ stock_inventory_date_constraint/test/stock_inventory_date.yml 2014-03-12 15:28:57 +0000
@@ -0,0 +1,133 @@
+-
+ In this file, I check that a stock move with an effective date before an inventory does not modify
+ the available quantity of a product.
+ First I'll check that the quantity in stock is 10.0 after the inventory
+-
+ !python {model: product.product}: |
+ ctx = {'location': [ref('stock.stock_location_components')], 'to_date': '2099-01-01 13:10:34'}
+ products = self.read(cr, uid, [ref('product.product_product_10')], ['qty_available'], context=ctx)
+ assert products[0]['qty_available'] == 10.0, "Quantity is not equal to 10.0 before stock move : %s" % products[0]['qty_available']
+-
+ To check that inventories are not made wrong by stock moves dated ealier,
+ I'll try to create a stock move dated before the inventory, directly in 'done' state.
+ Either this must fail, or we must check that the quantity is still correct.
+-
+ !python {model: stock.move}: |
+ from osv import orm
+
+ try:
+ move_id = self.create(cr, uid, {'product_id': ref('product.product_product_10'),
+ 'location_id': ref('stock.stock_location_14'),
+ 'location_dest_id': ref('stock.stock_location_components'),
+ 'product_qty': 17.0,
+ 'prodlot_id': ref('lot_test0'),
+ 'product_uom': ref('product.product_uom_unit'),
+ 'name': 'Product of test',
+ 'state': 'done'})
+ # I check the available quantity
+ product_obj = self.pool.get('product.product')
+ ctx = {'location': [ref('stock.stock_location_components')], 'to_date': '2099-01-01 15:10:34'}
+ products = product_obj.read(cr, uid, [ref('product.product_product_10')], ['qty_available'], context=ctx)
+ assert products[0]['qty_available'] == 10.0, "Quantity is not equal to 10 after stock move : %s" % products[0]['qty_available']
+ except orm.except_orm as e:
+ log("Good ! the stock move creation action has failed : %s" % e)
+-
+ To check that confirming a draft move before an inventory does not make the inventory wrong,
+ I create another Stock Move dated today, in 'draft' state.
+-
+ !record {model: stock.move, id: draft_stock_move}:
+ name: Test draft stock move before inventory date
+ location_id: stock.stock_location_components
+ location_dest_id: stock.stock_location_7
+ product_id: product.product_product_10
+ prodlot_id : lot_test0
+ product_qty: 3.0
+ product_uom: product.product_uom_unit
+ state: draft
+-
+ I confirm the Stock Move.
+-
+ !python {model: stock.move}: |
+ self.action_confirm(cr, uid, [ref('draft_stock_move')])
+-
+ I finish the Stock Move.
+ Either this must fail or we must check that the quantity is still correct.
+-
+ !python {model: stock.move}: |
+ from osv import orm
+ try:
+ self.action_done(cr, uid, [ref('draft_stock_move')])
+ # I check the available quantity
+ products = self.pool.get('product.product').read(
+ cr, uid, [ref('product.product_product_10')], ['qty_available'],
+ context={'location': [ref('stock.stock_location_components')],
+ 'to_date': '2099-01-01 15:10:34'})
+ assert products[0]['qty_available'] == 10.0, "Quantity is not equal to 10 after stock move : %s" % products[0]['qty_available']
+ except orm.except_orm as e:
+ log("Good ! The Stock Move could not be 'done' : %s" % e)
+-
+ To check that confirmed Stock Moves can be canceled even before the inventory,
+ I create yet another Stock Move dated today, in 'draft' state.
+-
+ !record {model: stock.move, id: draft_stock_move2}:
+ name: 2nd Test draft stock move before inventory date
+ location_id: stock.stock_location_components
+ location_dest_id: stock.stock_location_7
+ product_id: product.product_product_10
+ prodlot_id : lot_test0
+ product_qty: 3.0
+ product_uom: product.product_uom_unit
+ state: draft
+-
+ I confirm the Stock Move.
+-
+ !python {model: stock.move}: |
+ self.action_confirm(cr, uid, [ref('draft_stock_move2')])
+-
+ I cancel the Stock Move.
+-
+ !python {model: stock.move}: |
+ self.action_cancel(cr, uid, [ref('draft_stock_move2')])
+-
+ To check that stock moves are allowed after the inventory and not inhibited,
+ I create a Stock Move in 'done' state after the inventory.
+-
+ !record {model: stock.move, id: draft_stock_move}:
+ name: Test draft stock move before inventory date
+ date: '2099-06-02 09:53:28'
+ location_id: stock.stock_location_14
+ location_dest_id: stock.stock_location_components
+ product_id: product.product_product_10
+ prodlot_id : lot_test0
+ product_qty: 10.0
+ product_uom: product.product_uom_unit
+ state: done
+-
+ I check the quantity for product is equal to 20.0 after the inventory.
+-
+ !python {model: product.product}: |
+ products = self.read(cr, uid, [ref('product.product_product_10')],['qty_available'],
+ context={'location': [ref('stock.stock_location_components')],
+ 'to_date': '2099-12-31 19:10:34'})
+ assert products[0]['qty_available'] == 20.0, "Quantity is not equal to 20.0 : %s" % products[0]['qty_available']
+-
+ I try to cancel the first inventory.
+ Either this must fail or we must check that the quantity is still correct.
+-
+ !python {model: stock.inventory}: |
+ from osv import orm
+ try:
+ self.action_cancel_inventory(cr, uid, [ref('stock_inventory_init')])
+ # I check the available quantity
+ products = self.pool.get('product.product').read(
+ cr, uid, [ref('product.product_product_10')], ['qty_available'],
+ context={'location': [ref('stock.stock_location_components')],
+ 'to_date': '2099-12-31 19:10:34'})
+ assert products[0]['qty_available'] == 20.0, "Quantity is not equal to 20 after canceling the inventory : %s" % products[0]['qty_available']
+ except orm.except_orm as e:
+ log("Good ! The Inventory could not be canceled : %s" % e)
+-
+ I check that the last inventory can be canceled
+-
+ !python {model: stock.inventory}: |
+ self.action_cancel_inventory(cr, uid, [ref('stock_inventory_physical0')])
Follow ups