diff --git a/stock_reserve/__init__.py b/stock_reserve/__init__.py deleted file mode 100644 index 643bee7ab..000000000 --- a/stock_reserve/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# Author: Guewen Baconnier -# Copyright 2013 Camptocamp SA -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -from . import model diff --git a/stock_reserve/__openerp__.py b/stock_reserve/__openerp__.py deleted file mode 100644 index 61684f3c8..000000000 --- a/stock_reserve/__openerp__.py +++ /dev/null @@ -1,58 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# Author: Guewen Baconnier -# Copyright 2013 Camptocamp SA -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -{'name': 'Stock Reserve', - 'version': '0.1', - 'author': 'Camptocamp', - 'category': 'Warehouse', - 'license': 'AGPL-3', - 'complexity': 'normal', - 'images': [], - 'website': "http://www.camptocamp.com", - 'description': """ -Stock Reserve -============= - -Allows to create stock reservations on products. - -Each reservation can have a validity date, once passed, the reservation -is automatically lifted. - -The reserved products are substracted from the virtual stock. It means -that if you reserved a quantity of products which bring the virtual -stock below the minimum, the orderpoint will be triggered and new -purchase orders will be generated. It also implies that the max may be -exceeded if the reservations are canceled. - -""", - 'depends': ['stock', - ], - 'demo': [], - 'data': ['view/stock_reserve.xml', - 'view/product.xml', - 'data/stock_data.xml', - 'security/ir.model.access.csv', - ], - 'auto_install': False, - 'test': ['test/stock_reserve.yml', - ], - 'installable': True, - } diff --git a/stock_reserve/data/stock_data.xml b/stock_reserve/data/stock_data.xml deleted file mode 100644 index be6e44224..000000000 --- a/stock_reserve/data/stock_data.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - Reservation Stock - - - - - - - Release the stock reservation having a passed validity date - - - 1 - days - -1 - - stock.reservation - release_validity_exceeded - () - - - - diff --git a/stock_reserve/model/__init__.py b/stock_reserve/model/__init__.py deleted file mode 100644 index 9adf1d54b..000000000 --- a/stock_reserve/model/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# Author: Guewen Baconnier -# Copyright 2013 Camptocamp SA -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -from . import stock_reserve -from . import product diff --git a/stock_reserve/model/product.py b/stock_reserve/model/product.py deleted file mode 100644 index 45b7f28aa..000000000 --- a/stock_reserve/model/product.py +++ /dev/null @@ -1,40 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# Author: Guewen Baconnier -# Copyright 2013 Camptocamp SA -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -from openerp.osv import orm, fields - - -class product_product(orm.Model): - _inherit = 'product.product' - - def open_stock_reservation(self, cr, uid, ids, context=None): - assert len(ids) == 1, "Expected 1 ID, got %r" % ids - mod_obj = self.pool.get('ir.model.data') - act_obj = self.pool.get('ir.actions.act_window') - get_ref = mod_obj.get_object_reference - __, action_id = get_ref(cr, uid, 'stock_reserve', - 'action_stock_reservation') - action = act_obj.read(cr, uid, action_id, context=context) - action['context'] = {'search_default_draft': 1, - 'search_default_reserved': 1, - 'default_product_id': ids[0], - 'search_default_product_id': ids[0]} - return action diff --git a/stock_reserve/model/stock_reserve.py b/stock_reserve/model/stock_reserve.py deleted file mode 100644 index 6466ac233..000000000 --- a/stock_reserve/model/stock_reserve.py +++ /dev/null @@ -1,177 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# Author: Guewen Baconnier -# Copyright 2013 Camptocamp SA -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -from openerp.osv import orm, fields -from openerp.tools.translate import _ - - -class stock_reservation(orm.Model): - """ Allow to reserve products. - - The fields mandatory for the creation of a reservation are: - - * product_id - * product_qty - * product_uom - * name - - The following fields are required but have default values that you may - want to override: - - * company_id - * location_id - * dest_location_id - - Optionally, you may be interested to define: - - * date_validity (once passed, the reservation will be released) - * note - """ - _name = 'stock.reservation' - _description = 'Stock Reservation' - _inherits = {'stock.move': 'move_id'} - - _columns = { - 'move_id': fields.many2one('stock.move', - 'Reservation Move', - required=True, - readonly=True, - ondelete='cascade', - select=1), - 'date_validity': fields.date('Validity Date'), - } - - def get_location_from_ref(self, cr, uid, ref, context=None): - """ Get a location from a xmlid if allowed - :param ref: tuple (module, xmlid) - """ - location_obj = self.pool.get('stock.location') - data_obj = self.pool.get('ir.model.data') - get_ref = data_obj.get_object_reference - try: - __, location_id = get_ref(cr, uid, *ref) - location_obj.check_access_rule(cr, uid, [location_id], - 'read', context=context) - except (orm.except_orm, ValueError): - location_id = False - return location_id - - def _default_location_id(self, cr, uid, context=None): - if context is None: - context = {} - move_obj = self.pool.get('stock.move') - context['picking_type'] = 'internal' - return move_obj._default_location_source(cr, uid, context=context) - - def _default_location_dest_id(self, cr, uid, context=None): - ref = ('stock_reserve', 'stock_location_reservation') - return self.get_location_from_ref(cr, uid, ref, context=context) - - _defaults = { - 'type': 'internal', - 'location_id': _default_location_id, - 'location_dest_id': _default_location_dest_id, - 'product_qty': 1.0, - } - - def reserve(self, cr, uid, ids, context=None): - """ Confirm a reservation - - The reservation is done using the default UOM of the product. - A date until which the product is reserved can be specified. - """ - move_obj = self.pool.get('stock.move') - reservations = self.browse(cr, uid, ids, context=context) - move_ids = [reserv.move_id.id for reserv in reservations] - move_obj.write(cr, uid, move_ids, - {'date_expected': fields.datetime.now()}, - context=context) - move_obj.action_confirm(cr, uid, move_ids, context=context) - move_obj.force_assign(cr, uid, move_ids, context=context) - return True - - def release(self, cr, uid, ids, context=None): - if isinstance(ids, (int, long)): - ids = [ids] - reservations = self.read(cr, uid, ids, ['move_id'], - context=context, load='_classic_write') - move_obj = self.pool.get('stock.move') - move_ids = [reserv['move_id'] for reserv in reservations] - move_obj.action_cancel(cr, uid, move_ids, context=context) - return True - - def release_validity_exceeded(self, cr, uid, ids=None, context=None): - """ Release all the reservation having an exceeded validity date """ - domain = [('date_validity', '<', fields.date.today()), - ('state', '=', 'assigned')] - if ids: - domain.append(('id', 'in', ids)) - reserv_ids = self.search(cr, uid, domain, context=context) - self.release(cr, uid, reserv_ids, context=context) - return True - - def unlink(self, cr, uid, ids, context=None): - """ Release the reservation before the unlink """ - self.release(cr, uid, ids, context=context) - return super(stock_reservation, self).unlink(cr, uid, ids, - context=context) - - def onchange_product_id(self, cr, uid, ids, product_id=False, context=None): - move_obj = self.pool.get('stock.move') - if ids: - reserv = self.read(cr, uid, ids, ['move_id'], context=context, - load='_classic_write') - move_ids = [rv['move_id'] for rv in reserv] - else: - move_ids = [] - result = move_obj.onchange_product_id( - cr, uid, move_ids, prod_id=product_id, loc_id=False, - loc_dest_id=False, partner_id=False) - if result.get('value'): - vals = result['value'] - # only keep the existing fields on the view - keep = ('product_uom', 'name') - result['value'] = dict((key, value) for key, value in - result['value'].iteritems() if - key in keep) - return result - - def onchange_quantity(self, cr, uid, ids, product_id, product_qty, context=None): - """ On change of product quantity avoid negative quantities """ - if not product_id or product_qty <= 0.0: - return {'value': {'product_qty': 0.0}} - return {} - - def open_move(self, cr, uid, ids, context=None): - assert len(ids) == 1, "1 ID expected, got %r" % ids - reserv = self.read(cr, uid, ids[0], ['move_id'], context=context, - load='_classic_write') - mod_obj = self.pool.get('ir.model.data') - act_obj = self.pool.get('ir.actions.act_window') - get_ref = mod_obj.get_object_reference - __, action_id = get_ref(cr, uid, 'stock', 'action_move_form2') - action = act_obj.read(cr, uid, action_id, context=context) - action['name'] = _('Reservation Move') - # open directly in the form view - __, view_id = get_ref(cr, uid, 'stock', 'view_move_form') - action['views'] = [(view_id, 'form')] - action['res_id'] = reserv['move_id'] - return action diff --git a/stock_reserve/security/ir.model.access.csv b/stock_reserve/security/ir.model.access.csv deleted file mode 100644 index c48a8eefa..000000000 --- a/stock_reserve/security/ir.model.access.csv +++ /dev/null @@ -1,3 +0,0 @@ -id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -access_stock_reservation_manager,stock.reservation manager,model_stock_reservation,stock.group_stock_manager,1,1,1,1 -access_stock_reservation_user,stock.reservation user,model_stock_reservation,stock.group_stock_user,1,1,1,0 diff --git a/stock_reserve/test/stock_reserve.yml b/stock_reserve/test/stock_reserve.yml deleted file mode 100644 index 5cd92e29f..000000000 --- a/stock_reserve/test/stock_reserve.yml +++ /dev/null @@ -1,63 +0,0 @@ -- - I create a product to test the stock reservation -- - !record {model: product.product, id: product_sorbet}: - default_code: 001SORBET - name: Sorbet - type: product - categ_id: product.product_category_1 - list_price: 100.0 - standard_price: 70.0 - uom_id: product.product_uom_kgm - uom_po_id: product.product_uom_kgm - procure_method: make_to_stock - valuation: real_time - cost_method: average - property_stock_account_input: account.o_expense - property_stock_account_output: account.o_income -- - I update the current stock of the Sorbet with 10 kgm -- - !record {model: stock.change.product.qty, id: change_qty}: - new_quantity: 10 - product_id: product_sorbet -- - !python {model: stock.change.product.qty}: | - context['active_id'] = ref('stock_reserve.product_sorbet') - self.change_product_qty(cr, uid, [ref('change_qty')], context=context) -- - I check Virtual stock of Sorbet after update stock. -- - !python {model: product.product}: | - product = self.browse(cr, uid, ref('stock_reserve.product_sorbet'), context=context) - assert product.virtual_available == 10, "Stock is not updated." -- - I create a stock reservation for 5 kgm -- - !record {model: stock.reservation, id: reserv_sorbet1}: - product_id: product_sorbet - product_qty: 5.0 - product_uom: product.product_uom_kgm - name: reserve 5 kgm of sorbet for test -- - I confirm the reservation -- - !python {model: stock.reservation}: | - self.reserve(cr, uid, [ref('reserv_sorbet1')], context=context) -- - I check Virtual stock of Sorbet after update reservation -- - !python {model: product.product}: | - product = self.browse(cr, uid, ref('stock_reserve.product_sorbet'), context=context) - assert product.virtual_available == 5, "Stock is not updated." -- - I release the reservation -- - !python {model: stock.reservation}: | - self.release(cr, uid, [ref('reserv_sorbet1')], context=context) -- - I check Virtual stock of Sorbet after update reservation -- - !python {model: product.product}: | - product = self.browse(cr, uid, ref('stock_reserve.product_sorbet'), context=context) - assert product.virtual_available == 10, "Stock is not updated." diff --git a/stock_reserve/view/product.xml b/stock_reserve/view/product.xml deleted file mode 100644 index 9ff624dc1..000000000 --- a/stock_reserve/view/product.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - product.product.form.reserve - product.product - - - -