From c4c80197c98e153029754d097a19af2f90d519af Mon Sep 17 00:00:00 2001
From: Guewen Baconnier
Date: Thu, 5 Sep 2013 17:35:11 +0200
Subject: [PATCH 01/26] [ADD] started stock_reserve_sale to reserve lines of
quotations
---
stock_reserve_sale/__init__.py | 23 +++
stock_reserve_sale/__openerp__.py | 65 +++++++
stock_reserve_sale/model/__init__.py | 23 +++
stock_reserve_sale/model/sale.py | 184 ++++++++++++++++++
stock_reserve_sale/model/stock_reserve.py | 50 +++++
stock_reserve_sale/test/sale_line_reserve.yml | 118 +++++++++++
stock_reserve_sale/test/sale_reserve.yml | 65 +++++++
stock_reserve_sale/view/sale.xml | 67 +++++++
stock_reserve_sale/view/stock_reserve.xml | 30 +++
stock_reserve_sale/wizard/__init__.py | 22 +++
.../wizard/sale_stock_reserve.py | 111 +++++++++++
.../wizard/sale_stock_reserve_view.xml | 44 +++++
12 files changed, 802 insertions(+)
create mode 100644 stock_reserve_sale/__init__.py
create mode 100644 stock_reserve_sale/__openerp__.py
create mode 100644 stock_reserve_sale/model/__init__.py
create mode 100644 stock_reserve_sale/model/sale.py
create mode 100644 stock_reserve_sale/model/stock_reserve.py
create mode 100644 stock_reserve_sale/test/sale_line_reserve.yml
create mode 100644 stock_reserve_sale/test/sale_reserve.yml
create mode 100644 stock_reserve_sale/view/sale.xml
create mode 100644 stock_reserve_sale/view/stock_reserve.xml
create mode 100644 stock_reserve_sale/wizard/__init__.py
create mode 100644 stock_reserve_sale/wizard/sale_stock_reserve.py
create mode 100644 stock_reserve_sale/wizard/sale_stock_reserve_view.xml
diff --git a/stock_reserve_sale/__init__.py b/stock_reserve_sale/__init__.py
new file mode 100644
index 000000000000..f2bf938cb9a9
--- /dev/null
+++ b/stock_reserve_sale/__init__.py
@@ -0,0 +1,23 @@
+# -*- 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
+from . import wizard
diff --git a/stock_reserve_sale/__openerp__.py b/stock_reserve_sale/__openerp__.py
new file mode 100644
index 000000000000..99522e98c60d
--- /dev/null
+++ b/stock_reserve_sale/__openerp__.py
@@ -0,0 +1,65 @@
+# -*- 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 Sales',
+ 'version': '0.1',
+ 'author': 'Camptocamp',
+ 'category': 'Warehouse',
+ 'license': 'AGPL-3',
+ 'complexity': 'normal',
+ 'images': [],
+ 'website': "http://www.camptocamp.com",
+ 'description': """
+Stock Reserve Sales
+===================
+
+Allows to create stock reservations for quotation lines before the
+confirmation of the quotation. The reservations might have a validity
+date and in any case they are lifted when the quotation is canceled or
+confirmed.
+
+Reservations can be done only on "make to stock" and stockable products.
+
+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.
+
+If you want to prevent sales orders to be confirmed when the stock is
+insufficient at the order date, you may want to install the
+`sale_exception_nostock` module.
+
+""",
+ 'depends': ['sale_stock',
+ 'stock_reserve',
+ ],
+ 'demo': [],
+ 'data': ['wizard/sale_stock_reserve_view.xml',
+ 'view/sale.xml',
+ 'view/stock_reserve.xml',
+ ],
+ 'auto_install': False,
+ 'test': ['test/sale_reserve.yml',
+ 'test/sale_line_reserve.yml',
+ ],
+ 'installable': True,
+ }
diff --git a/stock_reserve_sale/model/__init__.py b/stock_reserve_sale/model/__init__.py
new file mode 100644
index 000000000000..5c9fc50677a6
--- /dev/null
+++ b/stock_reserve_sale/model/__init__.py
@@ -0,0 +1,23 @@
+# -*- 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 sale
+from . import stock_reserve
diff --git a/stock_reserve_sale/model/sale.py b/stock_reserve_sale/model/sale.py
new file mode 100644
index 000000000000..71c3374eca53
--- /dev/null
+++ b/stock_reserve_sale/model/sale.py
@@ -0,0 +1,184 @@
+# -*- 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 sale_order(orm.Model):
+ _inherit = 'sale.order'
+
+ def _stock_reservation(self, cr, uid, ids, fields, args, context=None):
+ result = {}
+ for order_id in ids:
+ result[order_id] = {'has_stock_reservation': False,
+ 'is_stock_reservable': False}
+ for sale in self.browse(cr, uid, ids, context=context):
+ for line in sale.order_line:
+ if line.reservation_ids:
+ result[sale.id]['has_stock_reservation'] = True
+ if line.is_stock_reservable:
+ result[sale.id]['is_stock_reservable'] = True
+ if sale.state not in ('draft', 'sent'):
+ result[sale.id]['is_stock_reservable'] = False
+ return result
+
+ _columns = {
+ 'has_stock_reservation': fields.function(
+ _stock_reservation,
+ type='boolean',
+ readonly=True,
+ multi='stock_reservation',
+ string='Has Stock Reservations'),
+ 'is_stock_reservable': fields.function(
+ _stock_reservation,
+ type='boolean',
+ readonly=True,
+ multi='stock_reservation',
+ string='Can Have Stock Reservations'),
+ }
+
+ def release_all_stock_reservation(self, cr, uid, ids, context=None):
+ sales = self.browse(cr, uid, ids, context=context)
+ line_ids = [line.id for sale in sales for line in sale.order_line]
+ line_obj = self.pool.get('sale.order.line')
+ line_obj.release_stock_reservation(cr, uid, line_ids, context=context)
+ return True
+
+ def action_button_confirm(self, cr, uid, ids, context=None):
+ self.release_all_stock_reservation(cr, uid, ids, context=context)
+ return super(sale_order, self).action_button_confirm(
+ cr, uid, ids, context=context)
+
+ def action_cancel(self, cr, uid, ids, context=None):
+ self.release_all_stock_reservation(cr, uid, ids, context=context)
+ return super(sale_order, self).action_cancel(
+ cr, uid, ids, context=context)
+
+
+class sale_order_line(orm.Model):
+ _inherit = 'sale.order.line'
+
+ def _is_stock_reservable(self, cr, uid, ids, fields, args, context=None):
+ result = {}.fromkeys(ids, False)
+ for line in self.browse(cr, uid, ids, context=context):
+ if line.state != 'draft':
+ continue
+ if line.type == 'make_to_order':
+ continue
+ if (not line.product_id or line.product_id.type == 'service'):
+ continue
+ if not line.reservation_ids:
+ result[line.id] = True
+ return result
+
+ _columns = {
+ 'reservation_ids': fields.one2many(
+ 'stock.reservation',
+ 'sale_line_id',
+ string='Stock Reservation'),
+ 'is_stock_reservable': fields.function(
+ _is_stock_reservable,
+ type='boolean',
+ readonly=True,
+ string='Can be reserved'),
+ }
+
+ def copy_data(self, cr, uid, id, default=None, context=None):
+ if default is None:
+ default = {}
+ default['reservation_ids'] = False
+ return super(sale_order_line, self).copy_data(
+ cr, uid, id, default=default, context=context)
+
+ def release_stock_reservation(self, cr, uid, ids, context=None):
+ lines = self.browse(cr, uid, ids, context=context)
+ reserv_ids = [reserv.id for line in lines
+ for reserv in line.reservation_ids]
+ reserv_obj = self.pool.get('stock.reservation')
+ reserv_obj.release(cr, uid, reserv_ids, context=context)
+ return True
+
+ def product_id_change(self, cr, uid, ids, pricelist, product, qty=0,
+ uom=False, qty_uos=0, uos=False, name='', partner_id=False,
+ lang=False, update_tax=True, date_order=False, packaging=False, fiscal_position=False, flag=False, context=None):
+ result = super(sale_order_line, self).product_id_change(
+ cr, uid, ids, pricelist, product, qty=qty, uom=uom,
+ qty_uos=qty_uos, uos=uos, name=name, partner_id=partner_id,
+ lang=lang, update_tax=update_tax, date_order=date_order,
+ packaging=packaging, fiscal_position=fiscal_position,
+ flag=flag, context=context)
+ if not ids: # warn only if we change an existing line
+ return result
+ assert len(ids) == 1, "Expected 1 ID, got %r" % ids
+ line = self.browse(cr, uid, ids[0], context=context)
+ if qty != line.product_uom_qty and line.reservation_ids:
+ msg = _("As you changed the quantity of the line, "
+ "the quantity of the stock reservation will "
+ "be automatically adjusted to %.2f.") % qty
+ msg += "\n\n"
+ result.setdefault('warning', {})
+ if result['warning'].get('message'):
+ result['warning']['message'] += msg
+ else:
+ result['warning'] = {
+ 'title': _('Configuration Error!'),
+ 'message': msg,
+ }
+ return result
+
+ def write(self, cr, uid, ids, vals, context=None):
+ block_on_reserve = ('product_id', 'product_uom', 'product_uos',
+ 'type')
+ update_on_reserve = ('price_unit', 'product_uom_qty', 'product_uos_qty')
+ keys = set(vals.keys())
+ test_block = keys.intersection(block_on_reserve)
+ test_update = keys.intersection(update_on_reserve)
+ if test_block:
+ for line in self.browse(cr, uid, ids, context=context):
+ if not line.reservation_ids:
+ continue
+ raise orm.except_orm(
+ _('Error'),
+ _('You cannot change the product or unit of measure '
+ 'of lines with a stock reservation. '
+ 'Release the reservation '
+ 'before changing the product.'))
+ res = super(sale_order_line, self).write(cr, uid, ids, vals, context=context)
+ if test_update:
+ for line in self.browse(cr, uid, ids, context=context):
+ if not line.reservation_ids:
+ continue
+ if len(line.reservation_ids) > 1:
+ raise orm.except_orm(
+ _('Error'),
+ _('Several stock reservations are linked with the '
+ 'line. Impossible to adjust their quantity. '
+ 'Please release the reservation '
+ 'before changing the quantity.'))
+
+ line.reservation_ids[0].write(
+ {'price_unit': line.price_unit,
+ 'product_qty': line.product_uom_qty,
+ 'product_uos_qty': line.product_uos_qty,
+ }
+ )
+ return res
diff --git a/stock_reserve_sale/model/stock_reserve.py b/stock_reserve_sale/model/stock_reserve.py
new file mode 100644
index 000000000000..0ea5fb958599
--- /dev/null
+++ b/stock_reserve_sale/model/stock_reserve.py
@@ -0,0 +1,50 @@
+# -*- 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 stock_reservation(orm.Model):
+ _inherit = 'stock.reservation'
+
+ _columns = {
+ 'sale_line_id': fields.many2one(
+ 'sale.order.line',
+ string='Sale Order Line',
+ ondelete='cascade'),
+ 'sale_id': fields.related(
+ 'sale_line_id', 'order_id',
+ type='many2one',
+ relation='sale.order',
+ string='Sale Order')
+ }
+
+ def release(self, cr, uid, ids, context=None):
+ self.write(cr, uid, ids, {'sale_line_id': False}, context=context)
+ return super(stock_reservation, self).release(
+ cr, uid, ids, context=context)
+
+ def copy_data(self, cr, uid, id, default=None, context=None):
+ if default is None:
+ default = {}
+ default['sale_line_id'] = False
+ return super(stock_reservation, self).copy_data(
+ cr, uid, id, default=default, context=context)
diff --git a/stock_reserve_sale/test/sale_line_reserve.yml b/stock_reserve_sale/test/sale_line_reserve.yml
new file mode 100644
index 000000000000..2dfbee6efede
--- /dev/null
+++ b/stock_reserve_sale/test/sale_line_reserve.yml
@@ -0,0 +1,118 @@
+-
+ I create a product to test the stock reservation
+-
+ !record {model: product.product, id: product_yogurt}:
+ default_code: 001yogurt
+ name: yogurt
+ 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 yogurt with 10 kgm
+-
+ !record {model: stock.change.product.qty, id: change_qty}:
+ new_quantity: 10
+ product_id: product_yogurt
+-
+ !python {model: stock.change.product.qty}: |
+ context['active_id'] = ref('product_yogurt')
+ self.change_product_qty(cr, uid, [ref('change_qty')], context=context)
+-
+ In order to test reservation of the sales order, I create a sales order
+-
+ !record {model: sale.order, id: sale_reserve_02}:
+ partner_id: base.res_partner_2
+ payment_term: account.account_payment_term
+-
+ And I create a sales order line
+-
+ !record {model: sale.order.line, id: sale_line_reserve_02_01, view: sale.view_order_line_tree}:
+ name: Yogurt
+ product_id: product_yogurt
+ product_uom_qty: 4
+ product_uom: product.product_uom_kgm
+ order_id: sale_reserve_02
+-
+ And I create a stock reserve for this line
+-
+ !record {model: sale.stock.reserve, id: wizard_reserve_02_01}:
+ note: Reservation for the sales order line
+-
+ I call the wizard to reserve the products of the sales order
+-
+ !python {model: sale.stock.reserve}: |
+ active_id = ref('sale_line_reserve_02_01')
+ context['active_id'] = active_id
+ context['active_ids'] = [active_id]
+ context['active_model'] = 'sale.order.line'
+ self.button_reserve(cr, uid, [ref('wizard_reserve_02_01')], context=context)
+-
+ I check Virtual stock of yogurt after update reservation
+-
+ !python {model: product.product}: |
+ product = self.browse(cr, uid, ref('product_yogurt'), context=context)
+ assert product.virtual_available == 6, "Stock is not updated."
+-
+ And I create a MTO sales order line
+-
+ !record {model: sale.order.line, id: sale_line_reserve_02_02, view: sale.view_order_line_tree}:
+ order_id: sale_reserve_02
+ name: Mouse, Wireless
+ product_id: product.product_product_12
+ type: make_to_order
+ product_uom_qty: 4
+ product_uom: product.product_uom_kgm
+-
+ And I try to create a stock reserve for this MTO line
+-
+ !record {model: sale.stock.reserve, id: wizard_reserve_02_02}:
+ note: Reservation for the sales order line
+-
+ I call the wizard to reserve the products of the sales order
+-
+ !python {model: sale.stock.reserve}: |
+ active_id = ref('sale_line_reserve_02_02')
+ context['active_id'] = active_id
+ context['active_ids'] = [active_id]
+ context['active_model'] = 'sale.order.line'
+ self.button_reserve(cr, uid, [ref('wizard_reserve_02_02')], context=context)
+-
+ I should not have a stock reservation for a MTO line
+-
+ !python {model: stock.reservation}: |
+ reserv_ids = self.search(
+ cr, uid,
+ [('sale_line_id', '=', ref('sale_line_reserve_02_02'))],
+ context=context)
+ assert not reserv_ids, "No stock reservation should be created for MTO lines"
+-
+ And I change the quantity in the first line
+-
+ !record {model: sale.order.line, id: sale_line_reserve_02_01, view: sale.view_order_line_tree}:
+ product_uom_qty: 5
+-
+
+ I check Virtual stock of yogurt after change of reservations
+-
+ !python {model: product.product}: |
+ product = self.browse(cr, uid, ref('product_yogurt'), context=context)
+ assert product.virtual_available == 5, "Stock is not updated."
+-
+ I release the sales order's reservations for the first line
+-
+ !python {model: sale.order.line}: |
+ self.release_stock_reservation(cr, uid, [ref('sale_line_reserve_02_01')], context=context)
+-
+ I check Virtual stock of yogurt after release of reservations
+-
+ !python {model: product.product}: |
+ product = self.browse(cr, uid, ref('product_yogurt'), context=context)
+ assert product.virtual_available == 10, "Stock is not updated."
diff --git a/stock_reserve_sale/test/sale_reserve.yml b/stock_reserve_sale/test/sale_reserve.yml
new file mode 100644
index 000000000000..7fc9dff6d7c0
--- /dev/null
+++ b/stock_reserve_sale/test/sale_reserve.yml
@@ -0,0 +1,65 @@
+-
+ I create a product to test the stock reservation
+-
+ !record {model: product.product, id: product_gelato}:
+ default_code: 001GELATO
+ name: Gelato
+ 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 Gelato with 10 kgm
+-
+ !record {model: stock.change.product.qty, id: change_qty}:
+ new_quantity: 10
+ product_id: product_gelato
+-
+ !python {model: stock.change.product.qty}: |
+ context['active_id'] = ref('product_gelato')
+ self.change_product_qty(cr, uid, [ref('change_qty')], context=context)
+-
+ In order to test reservation of the sales order, I create a sales order
+-
+ !record {model: sale.order, id: sale_reserve_01}:
+ partner_id: base.res_partner_2
+ payment_term: account.account_payment_term
+ order_line:
+ - product_id: product_gelato
+ product_uom_qty: 4
+-
+ I call the wizard to reserve the products of the sales order
+-
+ !record {model: sale.stock.reserve, id: wizard_reserve_01}:
+ note: Reservation for the sales order
+-
+ !python {model: sale.stock.reserve}: |
+ active_id = ref('sale_reserve_01')
+ context['active_id'] = active_id
+ context['active_ids'] = [active_id]
+ context['active_model'] = 'sale.order'
+ self.button_reserve(cr, uid, [ref('wizard_reserve_01')], context=context)
+-
+ I check Virtual stock of Gelato after update reservation
+-
+ !python {model: product.product}: |
+ product = self.browse(cr, uid, ref('product_gelato'), context=context)
+ assert product.virtual_available == 6, "Stock is not updated."
+-
+ I release the sales order's reservations
+-
+ !python {model: sale.order}: |
+ self.release_all_stock_reservation(cr, uid, [ref('sale_reserve_01')], context=context)
+-
+ I check Virtual stock of Gelato after release of reservations
+-
+ !python {model: product.product}: |
+ product = self.browse(cr, uid, ref('product_gelato'), context=context)
+ assert product.virtual_available == 10, "Stock is not updated."
diff --git a/stock_reserve_sale/view/sale.xml b/stock_reserve_sale/view/sale.xml
new file mode 100644
index 000000000000..e5849b04c166
--- /dev/null
+++ b/stock_reserve_sale/view/sale.xml
@@ -0,0 +1,67 @@
+
+
+
+
+
+ sale.order.form.reserve
+ sale.order
+
+
+
+
+
+ {"reload_on_button": 1}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/stock_reserve_sale/view/stock_reserve.xml b/stock_reserve_sale/view/stock_reserve.xml
new file mode 100644
index 000000000000..71e47cb95328
--- /dev/null
+++ b/stock_reserve_sale/view/stock_reserve.xml
@@ -0,0 +1,30 @@
+
+
+
+
+ stock.reservation.form
+ stock.reservation
+
+
+
+
+
+
+
+
+
+
+
+
+ stock.reservation.tree
+ stock.reservation
+
+
+
+
+
+
+
+
+
+
diff --git a/stock_reserve_sale/wizard/__init__.py b/stock_reserve_sale/wizard/__init__.py
new file mode 100644
index 000000000000..6156962e3abb
--- /dev/null
+++ b/stock_reserve_sale/wizard/__init__.py
@@ -0,0 +1,22 @@
+# -*- 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 sale_stock_reserve
diff --git a/stock_reserve_sale/wizard/sale_stock_reserve.py b/stock_reserve_sale/wizard/sale_stock_reserve.py
new file mode 100644
index 000000000000..5499c7e418af
--- /dev/null
+++ b/stock_reserve_sale/wizard/sale_stock_reserve.py
@@ -0,0 +1,111 @@
+# -*- 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 sale_stock_reserve(orm.TransientModel):
+ _name = 'sale.stock.reserve'
+
+ _columns = {
+ 'location_id': fields.many2one(
+ 'stock.location',
+ 'Source Location',
+ required=True),
+ 'location_dest_id': fields.many2one(
+ 'stock.location',
+ 'Reservation Location',
+ required=True,
+ help="Location where the system will reserve the "
+ "products."),
+ 'date_validity': fields.date(
+ "Validity Date",
+ help="If a date is given, the reservations will be released "
+ "at the end of the validity."),
+ 'note': fields.text('Notes'),
+ }
+
+ def _default_location_id(self, cr, uid, context=None):
+ reserv_obj = self.pool.get('stock.reservation')
+ return reserv_obj._default_location_id(cr, uid, context=context)
+
+ def _default_location_dest_id(self, cr, uid, context=None):
+ reserv_obj = self.pool.get('stock.reservation')
+ return reserv_obj._default_location_dest_id(cr, uid, context=context)
+
+ _defaults = {
+ 'location_id': _default_location_id,
+ 'location_dest_id': _default_location_dest_id,
+ }
+
+ def _prepare_stock_reservation(self, cr, uid, form, line, context=None):
+ product_uos = line.product_uos.id if line.product_uos else False
+ return {'product_id': line.product_id.id,
+ 'product_uom': line.product_uom.id,
+ 'product_qty': line.product_uom_qty,
+ 'date_validity': form.date_validity,
+ 'name': "{} ({})".format(line.order_id.name, line.name),
+ 'location_id': form.location_id.id,
+ 'location_dest_id': form.location_dest_id.id,
+ 'note': form.note,
+ 'product_uos_qty': line.product_uos_qty,
+ 'product_uos': product_uos,
+ 'price_unit': line.price_unit,
+ 'sale_line_id': line.id,
+ }
+
+ def stock_reserve(self, cr, uid, ids, line_ids, context=None):
+ assert len(ids) == 1, "Expected 1 ID, got %r" % ids
+ reserv_obj = self.pool.get('stock.reservation')
+ line_obj = self.pool.get('sale.order.line')
+
+ form = self.browse(cr, uid, ids[0], context=context)
+ lines = line_obj.browse(cr, uid, line_ids, context=context)
+ for line in lines:
+ if not line.is_stock_reservable:
+ continue
+ vals = self._prepare_stock_reservation(cr, uid, form, line,
+ context=context)
+ reserv_id = reserv_obj.create(cr, uid, vals, context=context)
+ reserv_obj.reserve(cr, uid, [reserv_id], context=context)
+ return True
+
+ def button_reserve(self, cr, uid, ids, context=None):
+ assert len(ids) == 1, "Expected 1 ID, got %r" % ids
+ if context is None:
+ context = {}
+ close = {'type': 'ir.actions.act_window_close'}
+ active_model = context.get('active_model')
+ active_ids = context.get('active_ids')
+ if not (active_model and active_ids):
+ return close
+
+ line_obj = self.pool.get('sale.order.line')
+ if active_model == 'sale.order':
+ sale_obj = self.pool.get('sale.order')
+ sales = sale_obj.browse(cr, uid, active_ids, context=context)
+ line_ids = [line.id for sale in sales for line in sale.order_line]
+
+ if active_model == 'sale.order.line':
+ line_ids = active_ids
+
+ self.stock_reserve(cr, uid, ids, line_ids, context=context)
+ return close
diff --git a/stock_reserve_sale/wizard/sale_stock_reserve_view.xml b/stock_reserve_sale/wizard/sale_stock_reserve_view.xml
new file mode 100644
index 000000000000..5b3c39bcccfb
--- /dev/null
+++ b/stock_reserve_sale/wizard/sale_stock_reserve_view.xml
@@ -0,0 +1,44 @@
+
+
+
+
+
+ sale.stock.reserve.form
+ sale.stock.reserve
+
+
+
+
+
+
+ Reserve Stock for Quotation Lines
+ ir.actions.act_window
+ sale.stock.reserve
+ form
+ form
+ new
+
+
+
From a57767ec94f8f59ac860392d00ebf7cc55b8b986 Mon Sep 17 00:00:00 2001
From: Alexandre Fayolle
Date: Tue, 1 Jul 2014 15:09:45 +0200
Subject: [PATCH 02/26] mark unported module as uninstallable
---
stock_reserve_sale/__init__.py | 23 ---
stock_reserve_sale/__openerp__.py | 65 -------
stock_reserve_sale/model/__init__.py | 23 ---
stock_reserve_sale/model/sale.py | 184 ------------------
stock_reserve_sale/model/stock_reserve.py | 50 -----
stock_reserve_sale/test/sale_line_reserve.yml | 118 -----------
stock_reserve_sale/test/sale_reserve.yml | 65 -------
stock_reserve_sale/view/sale.xml | 67 -------
stock_reserve_sale/view/stock_reserve.xml | 30 ---
stock_reserve_sale/wizard/__init__.py | 22 ---
.../wizard/sale_stock_reserve.py | 111 -----------
.../wizard/sale_stock_reserve_view.xml | 44 -----
12 files changed, 802 deletions(-)
delete mode 100644 stock_reserve_sale/__init__.py
delete mode 100644 stock_reserve_sale/__openerp__.py
delete mode 100644 stock_reserve_sale/model/__init__.py
delete mode 100644 stock_reserve_sale/model/sale.py
delete mode 100644 stock_reserve_sale/model/stock_reserve.py
delete mode 100644 stock_reserve_sale/test/sale_line_reserve.yml
delete mode 100644 stock_reserve_sale/test/sale_reserve.yml
delete mode 100644 stock_reserve_sale/view/sale.xml
delete mode 100644 stock_reserve_sale/view/stock_reserve.xml
delete mode 100644 stock_reserve_sale/wizard/__init__.py
delete mode 100644 stock_reserve_sale/wizard/sale_stock_reserve.py
delete mode 100644 stock_reserve_sale/wizard/sale_stock_reserve_view.xml
diff --git a/stock_reserve_sale/__init__.py b/stock_reserve_sale/__init__.py
deleted file mode 100644
index f2bf938cb9a9..000000000000
--- a/stock_reserve_sale/__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 model
-from . import wizard
diff --git a/stock_reserve_sale/__openerp__.py b/stock_reserve_sale/__openerp__.py
deleted file mode 100644
index 99522e98c60d..000000000000
--- a/stock_reserve_sale/__openerp__.py
+++ /dev/null
@@ -1,65 +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 Sales',
- 'version': '0.1',
- 'author': 'Camptocamp',
- 'category': 'Warehouse',
- 'license': 'AGPL-3',
- 'complexity': 'normal',
- 'images': [],
- 'website': "http://www.camptocamp.com",
- 'description': """
-Stock Reserve Sales
-===================
-
-Allows to create stock reservations for quotation lines before the
-confirmation of the quotation. The reservations might have a validity
-date and in any case they are lifted when the quotation is canceled or
-confirmed.
-
-Reservations can be done only on "make to stock" and stockable products.
-
-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.
-
-If you want to prevent sales orders to be confirmed when the stock is
-insufficient at the order date, you may want to install the
-`sale_exception_nostock` module.
-
-""",
- 'depends': ['sale_stock',
- 'stock_reserve',
- ],
- 'demo': [],
- 'data': ['wizard/sale_stock_reserve_view.xml',
- 'view/sale.xml',
- 'view/stock_reserve.xml',
- ],
- 'auto_install': False,
- 'test': ['test/sale_reserve.yml',
- 'test/sale_line_reserve.yml',
- ],
- 'installable': True,
- }
diff --git a/stock_reserve_sale/model/__init__.py b/stock_reserve_sale/model/__init__.py
deleted file mode 100644
index 5c9fc50677a6..000000000000
--- a/stock_reserve_sale/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 sale
-from . import stock_reserve
diff --git a/stock_reserve_sale/model/sale.py b/stock_reserve_sale/model/sale.py
deleted file mode 100644
index 71c3374eca53..000000000000
--- a/stock_reserve_sale/model/sale.py
+++ /dev/null
@@ -1,184 +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 sale_order(orm.Model):
- _inherit = 'sale.order'
-
- def _stock_reservation(self, cr, uid, ids, fields, args, context=None):
- result = {}
- for order_id in ids:
- result[order_id] = {'has_stock_reservation': False,
- 'is_stock_reservable': False}
- for sale in self.browse(cr, uid, ids, context=context):
- for line in sale.order_line:
- if line.reservation_ids:
- result[sale.id]['has_stock_reservation'] = True
- if line.is_stock_reservable:
- result[sale.id]['is_stock_reservable'] = True
- if sale.state not in ('draft', 'sent'):
- result[sale.id]['is_stock_reservable'] = False
- return result
-
- _columns = {
- 'has_stock_reservation': fields.function(
- _stock_reservation,
- type='boolean',
- readonly=True,
- multi='stock_reservation',
- string='Has Stock Reservations'),
- 'is_stock_reservable': fields.function(
- _stock_reservation,
- type='boolean',
- readonly=True,
- multi='stock_reservation',
- string='Can Have Stock Reservations'),
- }
-
- def release_all_stock_reservation(self, cr, uid, ids, context=None):
- sales = self.browse(cr, uid, ids, context=context)
- line_ids = [line.id for sale in sales for line in sale.order_line]
- line_obj = self.pool.get('sale.order.line')
- line_obj.release_stock_reservation(cr, uid, line_ids, context=context)
- return True
-
- def action_button_confirm(self, cr, uid, ids, context=None):
- self.release_all_stock_reservation(cr, uid, ids, context=context)
- return super(sale_order, self).action_button_confirm(
- cr, uid, ids, context=context)
-
- def action_cancel(self, cr, uid, ids, context=None):
- self.release_all_stock_reservation(cr, uid, ids, context=context)
- return super(sale_order, self).action_cancel(
- cr, uid, ids, context=context)
-
-
-class sale_order_line(orm.Model):
- _inherit = 'sale.order.line'
-
- def _is_stock_reservable(self, cr, uid, ids, fields, args, context=None):
- result = {}.fromkeys(ids, False)
- for line in self.browse(cr, uid, ids, context=context):
- if line.state != 'draft':
- continue
- if line.type == 'make_to_order':
- continue
- if (not line.product_id or line.product_id.type == 'service'):
- continue
- if not line.reservation_ids:
- result[line.id] = True
- return result
-
- _columns = {
- 'reservation_ids': fields.one2many(
- 'stock.reservation',
- 'sale_line_id',
- string='Stock Reservation'),
- 'is_stock_reservable': fields.function(
- _is_stock_reservable,
- type='boolean',
- readonly=True,
- string='Can be reserved'),
- }
-
- def copy_data(self, cr, uid, id, default=None, context=None):
- if default is None:
- default = {}
- default['reservation_ids'] = False
- return super(sale_order_line, self).copy_data(
- cr, uid, id, default=default, context=context)
-
- def release_stock_reservation(self, cr, uid, ids, context=None):
- lines = self.browse(cr, uid, ids, context=context)
- reserv_ids = [reserv.id for line in lines
- for reserv in line.reservation_ids]
- reserv_obj = self.pool.get('stock.reservation')
- reserv_obj.release(cr, uid, reserv_ids, context=context)
- return True
-
- def product_id_change(self, cr, uid, ids, pricelist, product, qty=0,
- uom=False, qty_uos=0, uos=False, name='', partner_id=False,
- lang=False, update_tax=True, date_order=False, packaging=False, fiscal_position=False, flag=False, context=None):
- result = super(sale_order_line, self).product_id_change(
- cr, uid, ids, pricelist, product, qty=qty, uom=uom,
- qty_uos=qty_uos, uos=uos, name=name, partner_id=partner_id,
- lang=lang, update_tax=update_tax, date_order=date_order,
- packaging=packaging, fiscal_position=fiscal_position,
- flag=flag, context=context)
- if not ids: # warn only if we change an existing line
- return result
- assert len(ids) == 1, "Expected 1 ID, got %r" % ids
- line = self.browse(cr, uid, ids[0], context=context)
- if qty != line.product_uom_qty and line.reservation_ids:
- msg = _("As you changed the quantity of the line, "
- "the quantity of the stock reservation will "
- "be automatically adjusted to %.2f.") % qty
- msg += "\n\n"
- result.setdefault('warning', {})
- if result['warning'].get('message'):
- result['warning']['message'] += msg
- else:
- result['warning'] = {
- 'title': _('Configuration Error!'),
- 'message': msg,
- }
- return result
-
- def write(self, cr, uid, ids, vals, context=None):
- block_on_reserve = ('product_id', 'product_uom', 'product_uos',
- 'type')
- update_on_reserve = ('price_unit', 'product_uom_qty', 'product_uos_qty')
- keys = set(vals.keys())
- test_block = keys.intersection(block_on_reserve)
- test_update = keys.intersection(update_on_reserve)
- if test_block:
- for line in self.browse(cr, uid, ids, context=context):
- if not line.reservation_ids:
- continue
- raise orm.except_orm(
- _('Error'),
- _('You cannot change the product or unit of measure '
- 'of lines with a stock reservation. '
- 'Release the reservation '
- 'before changing the product.'))
- res = super(sale_order_line, self).write(cr, uid, ids, vals, context=context)
- if test_update:
- for line in self.browse(cr, uid, ids, context=context):
- if not line.reservation_ids:
- continue
- if len(line.reservation_ids) > 1:
- raise orm.except_orm(
- _('Error'),
- _('Several stock reservations are linked with the '
- 'line. Impossible to adjust their quantity. '
- 'Please release the reservation '
- 'before changing the quantity.'))
-
- line.reservation_ids[0].write(
- {'price_unit': line.price_unit,
- 'product_qty': line.product_uom_qty,
- 'product_uos_qty': line.product_uos_qty,
- }
- )
- return res
diff --git a/stock_reserve_sale/model/stock_reserve.py b/stock_reserve_sale/model/stock_reserve.py
deleted file mode 100644
index 0ea5fb958599..000000000000
--- a/stock_reserve_sale/model/stock_reserve.py
+++ /dev/null
@@ -1,50 +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 stock_reservation(orm.Model):
- _inherit = 'stock.reservation'
-
- _columns = {
- 'sale_line_id': fields.many2one(
- 'sale.order.line',
- string='Sale Order Line',
- ondelete='cascade'),
- 'sale_id': fields.related(
- 'sale_line_id', 'order_id',
- type='many2one',
- relation='sale.order',
- string='Sale Order')
- }
-
- def release(self, cr, uid, ids, context=None):
- self.write(cr, uid, ids, {'sale_line_id': False}, context=context)
- return super(stock_reservation, self).release(
- cr, uid, ids, context=context)
-
- def copy_data(self, cr, uid, id, default=None, context=None):
- if default is None:
- default = {}
- default['sale_line_id'] = False
- return super(stock_reservation, self).copy_data(
- cr, uid, id, default=default, context=context)
diff --git a/stock_reserve_sale/test/sale_line_reserve.yml b/stock_reserve_sale/test/sale_line_reserve.yml
deleted file mode 100644
index 2dfbee6efede..000000000000
--- a/stock_reserve_sale/test/sale_line_reserve.yml
+++ /dev/null
@@ -1,118 +0,0 @@
--
- I create a product to test the stock reservation
--
- !record {model: product.product, id: product_yogurt}:
- default_code: 001yogurt
- name: yogurt
- 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 yogurt with 10 kgm
--
- !record {model: stock.change.product.qty, id: change_qty}:
- new_quantity: 10
- product_id: product_yogurt
--
- !python {model: stock.change.product.qty}: |
- context['active_id'] = ref('product_yogurt')
- self.change_product_qty(cr, uid, [ref('change_qty')], context=context)
--
- In order to test reservation of the sales order, I create a sales order
--
- !record {model: sale.order, id: sale_reserve_02}:
- partner_id: base.res_partner_2
- payment_term: account.account_payment_term
--
- And I create a sales order line
--
- !record {model: sale.order.line, id: sale_line_reserve_02_01, view: sale.view_order_line_tree}:
- name: Yogurt
- product_id: product_yogurt
- product_uom_qty: 4
- product_uom: product.product_uom_kgm
- order_id: sale_reserve_02
--
- And I create a stock reserve for this line
--
- !record {model: sale.stock.reserve, id: wizard_reserve_02_01}:
- note: Reservation for the sales order line
--
- I call the wizard to reserve the products of the sales order
--
- !python {model: sale.stock.reserve}: |
- active_id = ref('sale_line_reserve_02_01')
- context['active_id'] = active_id
- context['active_ids'] = [active_id]
- context['active_model'] = 'sale.order.line'
- self.button_reserve(cr, uid, [ref('wizard_reserve_02_01')], context=context)
--
- I check Virtual stock of yogurt after update reservation
--
- !python {model: product.product}: |
- product = self.browse(cr, uid, ref('product_yogurt'), context=context)
- assert product.virtual_available == 6, "Stock is not updated."
--
- And I create a MTO sales order line
--
- !record {model: sale.order.line, id: sale_line_reserve_02_02, view: sale.view_order_line_tree}:
- order_id: sale_reserve_02
- name: Mouse, Wireless
- product_id: product.product_product_12
- type: make_to_order
- product_uom_qty: 4
- product_uom: product.product_uom_kgm
--
- And I try to create a stock reserve for this MTO line
--
- !record {model: sale.stock.reserve, id: wizard_reserve_02_02}:
- note: Reservation for the sales order line
--
- I call the wizard to reserve the products of the sales order
--
- !python {model: sale.stock.reserve}: |
- active_id = ref('sale_line_reserve_02_02')
- context['active_id'] = active_id
- context['active_ids'] = [active_id]
- context['active_model'] = 'sale.order.line'
- self.button_reserve(cr, uid, [ref('wizard_reserve_02_02')], context=context)
--
- I should not have a stock reservation for a MTO line
--
- !python {model: stock.reservation}: |
- reserv_ids = self.search(
- cr, uid,
- [('sale_line_id', '=', ref('sale_line_reserve_02_02'))],
- context=context)
- assert not reserv_ids, "No stock reservation should be created for MTO lines"
--
- And I change the quantity in the first line
--
- !record {model: sale.order.line, id: sale_line_reserve_02_01, view: sale.view_order_line_tree}:
- product_uom_qty: 5
--
-
- I check Virtual stock of yogurt after change of reservations
--
- !python {model: product.product}: |
- product = self.browse(cr, uid, ref('product_yogurt'), context=context)
- assert product.virtual_available == 5, "Stock is not updated."
--
- I release the sales order's reservations for the first line
--
- !python {model: sale.order.line}: |
- self.release_stock_reservation(cr, uid, [ref('sale_line_reserve_02_01')], context=context)
--
- I check Virtual stock of yogurt after release of reservations
--
- !python {model: product.product}: |
- product = self.browse(cr, uid, ref('product_yogurt'), context=context)
- assert product.virtual_available == 10, "Stock is not updated."
diff --git a/stock_reserve_sale/test/sale_reserve.yml b/stock_reserve_sale/test/sale_reserve.yml
deleted file mode 100644
index 7fc9dff6d7c0..000000000000
--- a/stock_reserve_sale/test/sale_reserve.yml
+++ /dev/null
@@ -1,65 +0,0 @@
--
- I create a product to test the stock reservation
--
- !record {model: product.product, id: product_gelato}:
- default_code: 001GELATO
- name: Gelato
- 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 Gelato with 10 kgm
--
- !record {model: stock.change.product.qty, id: change_qty}:
- new_quantity: 10
- product_id: product_gelato
--
- !python {model: stock.change.product.qty}: |
- context['active_id'] = ref('product_gelato')
- self.change_product_qty(cr, uid, [ref('change_qty')], context=context)
--
- In order to test reservation of the sales order, I create a sales order
--
- !record {model: sale.order, id: sale_reserve_01}:
- partner_id: base.res_partner_2
- payment_term: account.account_payment_term
- order_line:
- - product_id: product_gelato
- product_uom_qty: 4
--
- I call the wizard to reserve the products of the sales order
--
- !record {model: sale.stock.reserve, id: wizard_reserve_01}:
- note: Reservation for the sales order
--
- !python {model: sale.stock.reserve}: |
- active_id = ref('sale_reserve_01')
- context['active_id'] = active_id
- context['active_ids'] = [active_id]
- context['active_model'] = 'sale.order'
- self.button_reserve(cr, uid, [ref('wizard_reserve_01')], context=context)
--
- I check Virtual stock of Gelato after update reservation
--
- !python {model: product.product}: |
- product = self.browse(cr, uid, ref('product_gelato'), context=context)
- assert product.virtual_available == 6, "Stock is not updated."
--
- I release the sales order's reservations
--
- !python {model: sale.order}: |
- self.release_all_stock_reservation(cr, uid, [ref('sale_reserve_01')], context=context)
--
- I check Virtual stock of Gelato after release of reservations
--
- !python {model: product.product}: |
- product = self.browse(cr, uid, ref('product_gelato'), context=context)
- assert product.virtual_available == 10, "Stock is not updated."
diff --git a/stock_reserve_sale/view/sale.xml b/stock_reserve_sale/view/sale.xml
deleted file mode 100644
index e5849b04c166..000000000000
--- a/stock_reserve_sale/view/sale.xml
+++ /dev/null
@@ -1,67 +0,0 @@
-
-
-
-
-
- sale.order.form.reserve
- sale.order
-
-
-
-
-
-
-
-
- {"reload_on_button": 1}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/stock_reserve_sale/view/stock_reserve.xml b/stock_reserve_sale/view/stock_reserve.xml
deleted file mode 100644
index 71e47cb95328..000000000000
--- a/stock_reserve_sale/view/stock_reserve.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
- stock.reservation.form
- stock.reservation
-
-
-
-
-
-
-
-
-
-
-
-
- stock.reservation.tree
- stock.reservation
-
-
-
-
-
-
-
-
-
-
diff --git a/stock_reserve_sale/wizard/__init__.py b/stock_reserve_sale/wizard/__init__.py
deleted file mode 100644
index 6156962e3abb..000000000000
--- a/stock_reserve_sale/wizard/__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 sale_stock_reserve
diff --git a/stock_reserve_sale/wizard/sale_stock_reserve.py b/stock_reserve_sale/wizard/sale_stock_reserve.py
deleted file mode 100644
index 5499c7e418af..000000000000
--- a/stock_reserve_sale/wizard/sale_stock_reserve.py
+++ /dev/null
@@ -1,111 +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 sale_stock_reserve(orm.TransientModel):
- _name = 'sale.stock.reserve'
-
- _columns = {
- 'location_id': fields.many2one(
- 'stock.location',
- 'Source Location',
- required=True),
- 'location_dest_id': fields.many2one(
- 'stock.location',
- 'Reservation Location',
- required=True,
- help="Location where the system will reserve the "
- "products."),
- 'date_validity': fields.date(
- "Validity Date",
- help="If a date is given, the reservations will be released "
- "at the end of the validity."),
- 'note': fields.text('Notes'),
- }
-
- def _default_location_id(self, cr, uid, context=None):
- reserv_obj = self.pool.get('stock.reservation')
- return reserv_obj._default_location_id(cr, uid, context=context)
-
- def _default_location_dest_id(self, cr, uid, context=None):
- reserv_obj = self.pool.get('stock.reservation')
- return reserv_obj._default_location_dest_id(cr, uid, context=context)
-
- _defaults = {
- 'location_id': _default_location_id,
- 'location_dest_id': _default_location_dest_id,
- }
-
- def _prepare_stock_reservation(self, cr, uid, form, line, context=None):
- product_uos = line.product_uos.id if line.product_uos else False
- return {'product_id': line.product_id.id,
- 'product_uom': line.product_uom.id,
- 'product_qty': line.product_uom_qty,
- 'date_validity': form.date_validity,
- 'name': "{} ({})".format(line.order_id.name, line.name),
- 'location_id': form.location_id.id,
- 'location_dest_id': form.location_dest_id.id,
- 'note': form.note,
- 'product_uos_qty': line.product_uos_qty,
- 'product_uos': product_uos,
- 'price_unit': line.price_unit,
- 'sale_line_id': line.id,
- }
-
- def stock_reserve(self, cr, uid, ids, line_ids, context=None):
- assert len(ids) == 1, "Expected 1 ID, got %r" % ids
- reserv_obj = self.pool.get('stock.reservation')
- line_obj = self.pool.get('sale.order.line')
-
- form = self.browse(cr, uid, ids[0], context=context)
- lines = line_obj.browse(cr, uid, line_ids, context=context)
- for line in lines:
- if not line.is_stock_reservable:
- continue
- vals = self._prepare_stock_reservation(cr, uid, form, line,
- context=context)
- reserv_id = reserv_obj.create(cr, uid, vals, context=context)
- reserv_obj.reserve(cr, uid, [reserv_id], context=context)
- return True
-
- def button_reserve(self, cr, uid, ids, context=None):
- assert len(ids) == 1, "Expected 1 ID, got %r" % ids
- if context is None:
- context = {}
- close = {'type': 'ir.actions.act_window_close'}
- active_model = context.get('active_model')
- active_ids = context.get('active_ids')
- if not (active_model and active_ids):
- return close
-
- line_obj = self.pool.get('sale.order.line')
- if active_model == 'sale.order':
- sale_obj = self.pool.get('sale.order')
- sales = sale_obj.browse(cr, uid, active_ids, context=context)
- line_ids = [line.id for sale in sales for line in sale.order_line]
-
- if active_model == 'sale.order.line':
- line_ids = active_ids
-
- self.stock_reserve(cr, uid, ids, line_ids, context=context)
- return close
diff --git a/stock_reserve_sale/wizard/sale_stock_reserve_view.xml b/stock_reserve_sale/wizard/sale_stock_reserve_view.xml
deleted file mode 100644
index 5b3c39bcccfb..000000000000
--- a/stock_reserve_sale/wizard/sale_stock_reserve_view.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
-
-
-
- sale.stock.reserve.form
- sale.stock.reserve
-
-
-
-
-
-
- Reserve Stock for Quotation Lines
- ir.actions.act_window
- sale.stock.reserve
- form
- form
- new
-
-
-
From 53e04de686bc0b77dd3b7cd6d3faa06c91755a71 Mon Sep 17 00:00:00 2001
From: Yannick Vaucher
Date: Wed, 10 Sep 2014 10:12:05 +0200
Subject: [PATCH 03/26] reactivate module stock_reserve_sale
---
stock_reserve_sale/__init__.py | 23 ++
stock_reserve_sale/__openerp__.py | 65 +++++
stock_reserve_sale/model/__init__.py | 23 ++
stock_reserve_sale/model/sale.py | 234 ++++++++++++++++++
stock_reserve_sale/model/stock_reserve.py | 42 ++++
stock_reserve_sale/test/sale_line_reserve.yml | 129 ++++++++++
stock_reserve_sale/test/sale_reserve.yml | 64 +++++
stock_reserve_sale/view/sale.xml | 67 +++++
stock_reserve_sale/view/stock_reserve.xml | 30 +++
stock_reserve_sale/wizard/__init__.py | 22 ++
.../wizard/sale_stock_reserve.py | 103 ++++++++
.../wizard/sale_stock_reserve_view.xml | 44 ++++
12 files changed, 846 insertions(+)
create mode 100644 stock_reserve_sale/__init__.py
create mode 100644 stock_reserve_sale/__openerp__.py
create mode 100644 stock_reserve_sale/model/__init__.py
create mode 100644 stock_reserve_sale/model/sale.py
create mode 100644 stock_reserve_sale/model/stock_reserve.py
create mode 100644 stock_reserve_sale/test/sale_line_reserve.yml
create mode 100644 stock_reserve_sale/test/sale_reserve.yml
create mode 100644 stock_reserve_sale/view/sale.xml
create mode 100644 stock_reserve_sale/view/stock_reserve.xml
create mode 100644 stock_reserve_sale/wizard/__init__.py
create mode 100644 stock_reserve_sale/wizard/sale_stock_reserve.py
create mode 100644 stock_reserve_sale/wizard/sale_stock_reserve_view.xml
diff --git a/stock_reserve_sale/__init__.py b/stock_reserve_sale/__init__.py
new file mode 100644
index 000000000000..f2bf938cb9a9
--- /dev/null
+++ b/stock_reserve_sale/__init__.py
@@ -0,0 +1,23 @@
+# -*- 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
+from . import wizard
diff --git a/stock_reserve_sale/__openerp__.py b/stock_reserve_sale/__openerp__.py
new file mode 100644
index 000000000000..7d9d2b9b021c
--- /dev/null
+++ b/stock_reserve_sale/__openerp__.py
@@ -0,0 +1,65 @@
+# -*- 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 Sales',
+ 'version': '0.1',
+ 'author': 'Camptocamp',
+ 'category': 'Warehouse',
+ 'license': 'AGPL-3',
+ 'complexity': 'normal',
+ 'images': [],
+ 'website': "http://www.camptocamp.com",
+ 'description': """
+Stock Reserve Sales
+===================
+
+Allows to create stock reservations for quotation lines before the
+confirmation of the quotation. The reservations might have a validity
+date and in any case they are lifted when the quotation is canceled or
+confirmed.
+
+Reservations can be done only on "make to stock" and stockable products.
+
+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.
+
+If you want to prevent sales orders to be confirmed when the stock is
+insufficient at the order date, you may want to install the
+`sale_exception_nostock` module.
+
+""",
+ 'depends': ['sale_stock',
+ 'stock_reserve',
+ ],
+ 'demo': [],
+ 'data': ['wizard/sale_stock_reserve_view.xml',
+ 'view/sale.xml',
+ 'view/stock_reserve.xml',
+ ],
+ 'test': ['test/sale_reserve.yml',
+ 'test/sale_line_reserve.yml',
+ ],
+ 'installable': True,
+ 'auto_install': False,
+ }
diff --git a/stock_reserve_sale/model/__init__.py b/stock_reserve_sale/model/__init__.py
new file mode 100644
index 000000000000..5c9fc50677a6
--- /dev/null
+++ b/stock_reserve_sale/model/__init__.py
@@ -0,0 +1,23 @@
+# -*- 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 sale
+from . import stock_reserve
diff --git a/stock_reserve_sale/model/sale.py b/stock_reserve_sale/model/sale.py
new file mode 100644
index 000000000000..1dd688a56e67
--- /dev/null
+++ b/stock_reserve_sale/model/sale.py
@@ -0,0 +1,234 @@
+# -*- 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 import models, fields, api
+from openerp.exceptions import except_orm
+from openerp.tools.translate import _
+
+
+class SaleOrder(models.Model):
+ _inherit = 'sale.order'
+
+ @api.multi
+ @api.depends('state',
+ 'order_line.reservation_ids',
+ 'order_line.is_stock_reservable')
+ def _stock_reservation(self):
+ for sale in self:
+ has_stock_reservation = False
+ is_stock_reservable = False
+ for line in sale.order_line:
+ if line.reservation_ids:
+ has_stock_reservation = True
+ if line.is_stock_reservable:
+ is_stock_reservable = True
+ if sale.state not in ('draft', 'sent'):
+ is_stock_reservable = False
+ sale.is_stock_reservable = is_stock_reservable
+ sale.has_stock_reservation = has_stock_reservation
+
+ has_stock_reservation = fields.Boolean(
+ compute='_stock_reservation',
+ readonly=True,
+ multi='stock_reservation',
+ store=True,
+ string='Has Stock Reservations')
+ is_stock_reservable = fields.Boolean(
+ compute='_stock_reservation',
+ readonly=True,
+ multi='stock_reservation',
+ store=True,
+ string='Can Have Stock Reservations')
+
+ @api.multi
+ def release_all_stock_reservation(self):
+ line_ids = [line.id for order in self for line in order.order_line]
+ lines = self.env['sale.order.line'].browse(line_ids)
+ lines.release_stock_reservation()
+ return True
+
+ @api.multi
+ def action_button_confirm(self):
+ self.release_all_stock_reservation()
+ return super(SaleOrder, self).action_button_confirm()
+
+ @api.multi
+ def action_cancel(self):
+ self.release_all_stock_reservation()
+ return super(SaleOrder, self).action_cancel()
+
+
+class SaleOrderLine(models.Model):
+ _inherit = 'sale.order.line'
+
+ @api.multi
+ def _get_line_rule(self):
+ """ Get applicable rule for this product
+
+ Reproduce get suitable rule from procurement
+ to predict source location """
+ ProcurementRule = self.env['procurement.rule']
+ product = self.product_id
+ product_route_ids = [x.id for x in product.route_ids +
+ product.categ_id.total_route_ids]
+ rules = ProcurementRule.search([('route_id', 'in', product_route_ids)],
+ order='route_sequence, sequence',
+ limit=1)
+
+ if not rules:
+ warehouse = self.order_id.warehouse_id
+ wh_routes = warehouse.route_ids
+ wh_route_ids = [route.id for route in wh_routes]
+ domain = ['|', ('warehouse_id', '=', warehouse.id),
+ ('warehouse_id', '=', False),
+ ('route_id', 'in', wh_route_ids)]
+
+ rules = ProcurementRule.search(domain,
+ order='route_sequence, sequence')
+
+ if rules:
+ return rules[0]
+ return False
+
+ @api.multi
+ def _get_procure_method(self):
+ """ Get procure_method depending on product routes """
+ rule = self._get_line_rule()
+ if rule:
+ return rule.procure_method
+ return False
+
+ @api.multi
+ @api.depends('state',
+ 'product_id.route_ids',
+ 'product_id.type')
+ def _is_stock_reservable(self):
+ for line in self:
+ reservable = False
+ if (not (line.state != 'draft'
+ or line._get_procure_method() == 'make_to_order'
+ or not line.product_id
+ or line.product_id.type == 'service')
+ and not line.reservation_ids):
+ reservable = True
+ line.is_stock_reservable = reservable
+
+ reservation_ids = fields.One2many(
+ 'stock.reservation',
+ 'sale_line_id',
+ string='Stock Reservation',
+ copy=False)
+ is_stock_reservable = fields.Boolean(
+ compute='_is_stock_reservable',
+ readonly=True,
+ string='Can be reserved')
+
+ @api.multi
+ def release_stock_reservation(self):
+ reserv_ids = [reserv.id for line in self
+ for reserv in line.reservation_ids]
+ reservations = self.env['stock.reservation'].browse(reserv_ids)
+ reservations.release()
+ return True
+
+ def product_id_change(self, cr, uid, ids,
+ pricelist,
+ product,
+ qty=0,
+ uom=False,
+ qty_uos=0,
+ uos=False,
+ name='',
+ partner_id=False,
+ lang=False,
+ update_tax=True,
+ date_order=False,
+ packaging=False,
+ fiscal_position=False,
+ flag=False,
+ context=None):
+ result = super(SaleOrderLine, self).product_id_change(
+ cr, uid, ids, pricelist, product, qty=qty, uom=uom,
+ qty_uos=qty_uos, uos=uos, name=name, partner_id=partner_id,
+ lang=lang, update_tax=update_tax, date_order=date_order,
+ packaging=packaging, fiscal_position=fiscal_position,
+ flag=flag, context=context)
+ if not ids: # warn only if we change an existing line
+ return result
+ assert len(ids) == 1, "Expected 1 ID, got %r" % ids
+ line = self.browse(cr, uid, ids[0], context=context)
+ if qty != line.product_uom_qty and line.reservation_ids:
+ msg = _("As you changed the quantity of the line, "
+ "the quantity of the stock reservation will "
+ "be automatically adjusted to %.2f.") % qty
+ msg += "\n\n"
+ result.setdefault('warning', {})
+ if result['warning'].get('message'):
+ result['warning']['message'] += msg
+ else:
+ result['warning'] = {
+ 'title': _('Configuration Error!'),
+ 'message': msg,
+ }
+ return result
+
+ @api.multi
+ def write(self, vals):
+ block_on_reserve = ('product_id',
+ 'product_uom',
+ 'product_uos',
+ 'type')
+ update_on_reserve = ('price_unit',
+ 'product_uom_qty',
+ 'product_uos_qty')
+ keys = set(vals.keys())
+ test_block = keys.intersection(block_on_reserve)
+ test_update = keys.intersection(update_on_reserve)
+ if test_block:
+ for line in self:
+ if not line.reservation_ids:
+ continue
+ raise except_orm(
+ _('Error'),
+ _('You cannot change the product or unit of measure '
+ 'of lines with a stock reservation. '
+ 'Release the reservation '
+ 'before changing the product.'))
+ res = super(SaleOrderLine, self).write(vals)
+ if test_update:
+ for line in self:
+ if not line.reservation_ids:
+ continue
+ if len(line.reservation_ids) > 1:
+ raise except_orm(
+ _('Error'),
+ _('Several stock reservations are linked with the '
+ 'line. Impossible to adjust their quantity. '
+ 'Please release the reservation '
+ 'before changing the quantity.'))
+
+ line.reservation_ids.write(
+ {'price_unit': line.price_unit,
+ 'product_uom_qty': line.product_uom_qty,
+ 'product_uos_qty': line.product_uos_qty,
+ }
+ )
+ return res
diff --git a/stock_reserve_sale/model/stock_reserve.py b/stock_reserve_sale/model/stock_reserve.py
new file mode 100644
index 000000000000..db68449bbc3f
--- /dev/null
+++ b/stock_reserve_sale/model/stock_reserve.py
@@ -0,0 +1,42 @@
+# -*- 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 import models, fields, api
+
+
+class StockReservation(models.Model):
+ _inherit = 'stock.reservation'
+
+ sale_line_id = fields.Many2one(
+ 'sale.order.line',
+ string='Sale Order Line',
+ ondelete='cascade',
+ copy=False)
+ sale_id = fields.Many2one(
+ 'sale.order',
+ string='Sale Order',
+ related='sale_line_id.order_id')
+
+ @api.multi
+ def release(self):
+ for rec in self:
+ rec.sale_line_id = False
+ return super(StockReservation, self).release()
diff --git a/stock_reserve_sale/test/sale_line_reserve.yml b/stock_reserve_sale/test/sale_line_reserve.yml
new file mode 100644
index 000000000000..421d5da2f1c2
--- /dev/null
+++ b/stock_reserve_sale/test/sale_line_reserve.yml
@@ -0,0 +1,129 @@
+-
+ I create a product to test the stock reservation
+-
+ !record {model: product.product, id: product_yogurt}:
+ default_code: 001yogurt
+ name: yogurt
+ 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
+ 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 yogurt with 10 kgm
+-
+ !record {model: stock.change.product.qty, id: change_qty}:
+ new_quantity: 10
+ product_id: product_yogurt
+-
+ !python {model: stock.change.product.qty}: |
+ context['active_id'] = ref('product_yogurt')
+ self.change_product_qty(cr, uid, [ref('change_qty')], context=context)
+-
+ In order to test reservation of the sales order, I create a sales order
+-
+ !record {model: sale.order, id: sale_reserve_02}:
+ partner_id: base.res_partner_2
+ payment_term: account.account_payment_term
+-
+ And I create a sales order line
+-
+ !record {model: sale.order.line, id: sale_line_reserve_02_01, view: sale.view_order_line_tree}:
+ name: Yogurt
+ product_id: product_yogurt
+ product_uom_qty: 4
+ product_uom: product.product_uom_kgm
+ order_id: sale_reserve_02
+-
+ And I create a stock reserve for this line
+-
+ !record {model: sale.stock.reserve, id: wizard_reserve_02_01}:
+ note: Reservation for the sales order line
+-
+ I call the wizard to reserve the products of the sales order
+-
+ !python {model: sale.stock.reserve}: |
+ active_id = ref('sale_line_reserve_02_01')
+ context['active_id'] = active_id
+ context['active_ids'] = [active_id]
+ context['active_model'] = 'sale.order.line'
+ self.button_reserve(cr, uid, [ref('wizard_reserve_02_01')], context=context)
+-
+ I check Virtual stock of yogurt after update reservation
+-
+ !python {model: product.product}: |
+ product = self.browse(cr, uid, ref('product_yogurt'), context=context)
+ assert product.virtual_available == 6, "Stock is not updated."
+-
+ I set product_12 to MTO (doesn't work)
+-
+ !record {model: product.product, id: product.product_product_12}:
+ route_ids:
+ - stock.route_warehouse0_mto
+-
+ I set MTO for real
+-
+ !python {model: product.product}: |
+ product = self.browse(cr, uid, ref('product.product_product_12'), context=context)
+ self.write(cr, uid, ref('product.product_product_12'),
+ {'route_ids': [(6, False, [ref('stock.route_warehouse0_mto')])]}, context=context)
+-
+ And I create a MTO sales order line
+-
+ !record {model: sale.order.line, id: sale_line_reserve_02_02, view: sale.view_order_line_tree}:
+ order_id: sale_reserve_02
+ name: Mouse, Wireless
+ product_id: product.product_product_12
+ product_uom_qty: 4
+ product_uom: product.product_uom_unit
+-
+ And I try to create a stock reserve for this MTO line
+-
+ !record {model: sale.stock.reserve, id: wizard_reserve_02_02}:
+ note: Reservation for the sales order line
+-
+ I call the wizard to reserve the products of the sales order
+-
+ !python {model: sale.stock.reserve}: |
+ active_id = ref('sale_line_reserve_02_02')
+ context['active_id'] = active_id
+ context['active_ids'] = [active_id]
+ context['active_model'] = 'sale.order.line'
+ self.button_reserve(cr, uid, [ref('wizard_reserve_02_02')], context=context)
+-
+ I should not have a stock reservation for a MTO line
+-
+ !python {model: stock.reservation}: |
+ reserv_ids = self.search(
+ cr, uid,
+ [('sale_line_id', '=', ref('sale_line_reserve_02_02'))],
+ context=context)
+ assert not reserv_ids, "No stock reservation should be created for MTO lines"
+-
+ And I change the quantity in the first line
+-
+ !record {model: sale.order.line, id: sale_line_reserve_02_01, view: sale.view_order_line_tree}:
+ product_uom_qty: 5
+-
+
+ I check Virtual stock of yogurt after change of reservations
+-
+ !python {model: product.product}: |
+ product = self.browse(cr, uid, ref('product_yogurt'), context=context)
+ assert product.virtual_available == 5, "Stock is not updated."
+-
+ I release the sales order's reservations for the first line
+-
+ !python {model: sale.order.line}: |
+ self.release_stock_reservation(cr, uid, [ref('sale_line_reserve_02_01')], context=context)
+-
+ I check Virtual stock of yogurt after release of reservations
+-
+ !python {model: product.product}: |
+ product = self.browse(cr, uid, ref('product_yogurt'), context=context)
+ assert product.virtual_available == 10, "Stock is not updated."
diff --git a/stock_reserve_sale/test/sale_reserve.yml b/stock_reserve_sale/test/sale_reserve.yml
new file mode 100644
index 000000000000..2671f40e1250
--- /dev/null
+++ b/stock_reserve_sale/test/sale_reserve.yml
@@ -0,0 +1,64 @@
+-
+ I create a product to test the stock reservation
+-
+ !record {model: product.product, id: product_gelato}:
+ default_code: 001GELATO
+ name: Gelato
+ 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
+ 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 Gelato with 10 kgm
+-
+ !record {model: stock.change.product.qty, id: change_qty}:
+ new_quantity: 10
+ product_id: product_gelato
+-
+ !python {model: stock.change.product.qty}: |
+ context['active_id'] = ref('product_gelato')
+ self.change_product_qty(cr, uid, [ref('change_qty')], context=context)
+-
+ In order to test reservation of the sales order, I create a sales order
+-
+ !record {model: sale.order, id: sale_reserve_01}:
+ partner_id: base.res_partner_2
+ payment_term: account.account_payment_term
+ order_line:
+ - product_id: product_gelato
+ product_uom_qty: 4
+-
+ I call the wizard to reserve the products of the sales order
+-
+ !record {model: sale.stock.reserve, id: wizard_reserve_01}:
+ note: Reservation for the sales order
+-
+ !python {model: sale.stock.reserve}: |
+ active_id = ref('sale_reserve_01')
+ context['active_id'] = active_id
+ context['active_ids'] = [active_id]
+ context['active_model'] = 'sale.order'
+ self.button_reserve(cr, uid, [ref('wizard_reserve_01')], context=context)
+-
+ I check Virtual stock of Gelato after update reservation
+-
+ !python {model: product.product}: |
+ product = self.browse(cr, uid, ref('product_gelato'), context=context)
+ assert product.virtual_available == 6, "Stock is not updated."
+-
+ I release the sales order's reservations
+-
+ !python {model: sale.order}: |
+ self.release_all_stock_reservation(cr, uid, [ref('sale_reserve_01')], context=context)
+-
+ I check Virtual stock of Gelato after release of reservations
+-
+ !python {model: product.product}: |
+ product = self.browse(cr, uid, ref('product_gelato'), context=context)
+ assert product.virtual_available == 10, "Stock is not updated."
diff --git a/stock_reserve_sale/view/sale.xml b/stock_reserve_sale/view/sale.xml
new file mode 100644
index 000000000000..e5849b04c166
--- /dev/null
+++ b/stock_reserve_sale/view/sale.xml
@@ -0,0 +1,67 @@
+
+
+
+
+
+ sale.order.form.reserve
+ sale.order
+
+
+
+
+
+
+
+
+ {"reload_on_button": 1}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/stock_reserve_sale/view/stock_reserve.xml b/stock_reserve_sale/view/stock_reserve.xml
new file mode 100644
index 000000000000..71e47cb95328
--- /dev/null
+++ b/stock_reserve_sale/view/stock_reserve.xml
@@ -0,0 +1,30 @@
+
+
+
+
+ stock.reservation.form
+ stock.reservation
+
+
+
+
+
+
+
+
+
+
+
+
+ stock.reservation.tree
+ stock.reservation
+
+
+
+
+
+
+
+
+
+
diff --git a/stock_reserve_sale/wizard/__init__.py b/stock_reserve_sale/wizard/__init__.py
new file mode 100644
index 000000000000..6156962e3abb
--- /dev/null
+++ b/stock_reserve_sale/wizard/__init__.py
@@ -0,0 +1,22 @@
+# -*- 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 sale_stock_reserve
diff --git a/stock_reserve_sale/wizard/sale_stock_reserve.py b/stock_reserve_sale/wizard/sale_stock_reserve.py
new file mode 100644
index 000000000000..af8130f1b41e
--- /dev/null
+++ b/stock_reserve_sale/wizard/sale_stock_reserve.py
@@ -0,0 +1,103 @@
+# -*- 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 import models, fields, api
+
+
+class SaleStockReserve(models.TransientModel):
+ _name = 'sale.stock.reserve'
+
+ @api.model
+ def _default_location_id(self):
+ return self.env['stock.reservation']._default_location_id()
+
+ @api.model
+ def _default_location_dest_id(self):
+ return self.env['stock.reservation']._default_location_dest_id()
+
+ location_id = fields.Many2one(
+ 'stock.location',
+ 'Source Location',
+ required=True,
+ default=_default_location_id)
+ location_dest_id = fields.Many2one(
+ 'stock.location',
+ 'Reservation Location',
+ required=True,
+ help="Location where the system will reserve the "
+ "products.",
+ default=_default_location_dest_id)
+ date_validity = fields.Date(
+ "Validity Date",
+ help="If a date is given, the reservations will be released "
+ "at the end of the validity.")
+ note = fields.Text('Notes')
+
+
+ @api.one
+ def _prepare_stock_reservation(self, line):
+ product_uos = line.product_uos.id if line.product_uos else False
+ return {'product_id': line.product_id.id,
+ 'product_uom': line.product_uom.id,
+ 'product_uom_qty': line.product_uom_qty,
+ 'date_validity': self.date_validity,
+ 'name': "%s (%s)" % (line.order_id.name, line.name),
+ 'location_id': self.location_id.id,
+ 'location_dest_id': self.location_dest_id.id,
+ 'note': self.note,
+ 'product_uos_qty': line.product_uos_qty,
+ 'product_uos': product_uos,
+ 'price_unit': line.price_unit,
+ 'sale_line_id': line.id,
+ }
+
+ @api.multi
+ def stock_reserve(self, line_ids):
+ assert len(self.ids) == 1, "Expected 1 ID, got %r" % self.ids
+
+ lines = self.env['sale.order.line'].browse(line_ids)
+ for line in lines:
+ if not line.is_stock_reservable:
+ continue
+ vals = self._prepare_stock_reservation(line)[0]
+ reserv = self.env['stock.reservation'].create(vals)
+ reserv.reserve()
+ return True
+
+ @api.multi
+ def button_reserve(self):
+ env = self.env
+ assert len(self.ids) == 1, "Expected 1 ID, got %r" % self.ids
+ close = {'type': 'ir.actions.act_window_close'}
+ active_model = env.context.get('active_model')
+ active_ids = env.context.get('active_ids')
+ if not (active_model and active_ids):
+ return close
+
+ if active_model == 'sale.order':
+ sales = env['sale.order'].browse(active_ids)
+ line_ids = [line.id for sale in sales for line in sale.order_line]
+
+ if active_model == 'sale.order.line':
+ line_ids = active_ids
+
+ self.stock_reserve(line_ids)
+ return close
diff --git a/stock_reserve_sale/wizard/sale_stock_reserve_view.xml b/stock_reserve_sale/wizard/sale_stock_reserve_view.xml
new file mode 100644
index 000000000000..5b3c39bcccfb
--- /dev/null
+++ b/stock_reserve_sale/wizard/sale_stock_reserve_view.xml
@@ -0,0 +1,44 @@
+
+
+
+
+
+ sale.stock.reserve.form
+ sale.stock.reserve
+
+
+
+
+
+
+ Reserve Stock for Quotation Lines
+ ir.actions.act_window
+ sale.stock.reserve
+ form
+ form
+ new
+
+
+
From 052c48012fb7d33c3c4733ee198dd805431042fa Mon Sep 17 00:00:00 2001
From: Leonardo Pistone
Date: Thu, 25 Sep 2014 16:51:48 +0200
Subject: [PATCH 04/26] lint
---
stock_reserve_sale/wizard/sale_stock_reserve.py | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/stock_reserve_sale/wizard/sale_stock_reserve.py b/stock_reserve_sale/wizard/sale_stock_reserve.py
index af8130f1b41e..2fc7d1ff1c7f 100644
--- a/stock_reserve_sale/wizard/sale_stock_reserve.py
+++ b/stock_reserve_sale/wizard/sale_stock_reserve.py
@@ -51,9 +51,9 @@ def _default_location_dest_id(self):
"at the end of the validity.")
note = fields.Text('Notes')
-
- @api.one
+ @api.multi
def _prepare_stock_reservation(self, line):
+ self.ensure_one()
product_uos = line.product_uos.id if line.product_uos else False
return {'product_id': line.product_id.id,
'product_uom': line.product_uom.id,
@@ -71,13 +71,13 @@ def _prepare_stock_reservation(self, line):
@api.multi
def stock_reserve(self, line_ids):
- assert len(self.ids) == 1, "Expected 1 ID, got %r" % self.ids
+ self.ensure_one()
lines = self.env['sale.order.line'].browse(line_ids)
for line in lines:
if not line.is_stock_reservable:
continue
- vals = self._prepare_stock_reservation(line)[0]
+ vals = self._prepare_stock_reservation(line)
reserv = self.env['stock.reservation'].create(vals)
reserv.reserve()
return True
@@ -85,7 +85,7 @@ def stock_reserve(self, line_ids):
@api.multi
def button_reserve(self):
env = self.env
- assert len(self.ids) == 1, "Expected 1 ID, got %r" % self.ids
+ self.ensure_one()
close = {'type': 'ir.actions.act_window_close'}
active_model = env.context.get('active_model')
active_ids = env.context.get('active_ids')
From 4e6edb2ac80b70d10f054fdb0d3e496b2254a772 Mon Sep 17 00:00:00 2001
From: Alexandre Fayolle
Date: Mon, 16 Feb 2015 10:38:27 +0100
Subject: [PATCH 05/26] fix pep8 W503
---
stock_reserve_sale/__openerp__.py | 2 +-
stock_reserve_sale/model/sale.py | 10 +++++-----
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/stock_reserve_sale/__openerp__.py b/stock_reserve_sale/__openerp__.py
index 7d9d2b9b021c..be0ae3152b8c 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',
diff --git a/stock_reserve_sale/model/sale.py b/stock_reserve_sale/model/sale.py
index 1dd688a56e67..5723f473f5dc 100644
--- a/stock_reserve_sale/model/sale.py
+++ b/stock_reserve_sale/model/sale.py
@@ -123,11 +123,11 @@ def _get_procure_method(self):
def _is_stock_reservable(self):
for line in self:
reservable = False
- if (not (line.state != 'draft'
- or line._get_procure_method() == 'make_to_order'
- or not line.product_id
- or line.product_id.type == 'service')
- and not line.reservation_ids):
+ if (not (line.state != 'draft' or
+ line._get_procure_method() == 'make_to_order' or
+ not line.product_id or
+ line.product_id.type == 'service') and
+ not line.reservation_ids):
reservable = True
line.is_stock_reservable = reservable
From 574e2156a02478b4939fbb2ea6baa55bede4c72e Mon Sep 17 00:00:00 2001
From: Leonardo Pistone
Date: Tue, 17 Mar 2015 12:35:46 +0100
Subject: [PATCH 06/26] make stock_reserve_sale owner_aware
---
stock_reserve_sale/__openerp__.py | 13 +++++--
stock_reserve_sale/test/sale_line_reserve.yml | 16 +++------
stock_reserve_sale/test/sale_reserve.yml | 18 +++++-----
.../wizard/sale_stock_reserve.py | 35 +++++++++++++++++--
.../wizard/sale_stock_reserve_view.xml | 1 +
5 files changed, 55 insertions(+), 28 deletions(-)
diff --git a/stock_reserve_sale/__openerp__.py b/stock_reserve_sale/__openerp__.py
index be0ae3152b8c..3fa481478874 100644
--- a/stock_reserve_sale/__openerp__.py
+++ b/stock_reserve_sale/__openerp__.py
@@ -1,8 +1,8 @@
# -*- coding: utf-8 -*-
##############################################################################
#
-# Author: Guewen Baconnier
-# Copyright 2013 Camptocamp SA
+# Author: Guewen Baconnier, Leonardo Pistone
+# Copyright 2013-2015 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
@@ -20,7 +20,7 @@
##############################################################################
{'name': 'Stock Reserve Sales',
- 'version': '0.1',
+ 'version': '1.0',
'author': "Camptocamp,Odoo Community Association (OCA)",
'category': 'Warehouse',
'license': 'AGPL-3',
@@ -48,6 +48,13 @@
insufficient at the order date, you may want to install the
`sale_exception_nostock` module.
+Additionally, if the sale_owner_stock_sourcing module is installed, the owner
+specified on the sale order line will be proposed as owner of the reservation.
+If you try to make a reservation for an order whose lines have different, you
+will get a message suggesting to reserve each line individually. There is no
+module dependency: this modules is fully functional even without ownership
+management.
+
""",
'depends': ['sale_stock',
'stock_reserve',
diff --git a/stock_reserve_sale/test/sale_line_reserve.yml b/stock_reserve_sale/test/sale_line_reserve.yml
index 421d5da2f1c2..0a798c3c244a 100644
--- a/stock_reserve_sale/test/sale_line_reserve.yml
+++ b/stock_reserve_sale/test/sale_line_reserve.yml
@@ -41,18 +41,14 @@
order_id: sale_reserve_02
-
And I create a stock reserve for this line
--
- !record {model: sale.stock.reserve, id: wizard_reserve_02_01}:
- note: Reservation for the sales order line
--
- I call the wizard to reserve the products of the sales order
-
!python {model: sale.stock.reserve}: |
active_id = ref('sale_line_reserve_02_01')
context['active_id'] = active_id
context['active_ids'] = [active_id]
context['active_model'] = 'sale.order.line'
- self.button_reserve(cr, uid, [ref('wizard_reserve_02_01')], context=context)
+ wizard_id = self.create(cr, uid, {}, context=context)
+ self.button_reserve(cr, uid, [wizard_id], context=context)
-
I check Virtual stock of yogurt after update reservation
-
@@ -83,18 +79,14 @@
product_uom: product.product_uom_unit
-
And I try to create a stock reserve for this MTO line
--
- !record {model: sale.stock.reserve, id: wizard_reserve_02_02}:
- note: Reservation for the sales order line
--
- I call the wizard to reserve the products of the sales order
-
!python {model: sale.stock.reserve}: |
active_id = ref('sale_line_reserve_02_02')
context['active_id'] = active_id
context['active_ids'] = [active_id]
context['active_model'] = 'sale.order.line'
- self.button_reserve(cr, uid, [ref('wizard_reserve_02_02')], context=context)
+ wizard_id = self.create(cr, uid, {}, context=context)
+ self.button_reserve(cr, uid, [wizard_id], context=context)
-
I should not have a stock reservation for a MTO line
-
diff --git a/stock_reserve_sale/test/sale_reserve.yml b/stock_reserve_sale/test/sale_reserve.yml
index 2671f40e1250..9afc4dff9c68 100644
--- a/stock_reserve_sale/test/sale_reserve.yml
+++ b/stock_reserve_sale/test/sale_reserve.yml
@@ -35,22 +35,20 @@
product_uom_qty: 4
-
I call the wizard to reserve the products of the sales order
--
- !record {model: sale.stock.reserve, id: wizard_reserve_01}:
- note: Reservation for the sales order
-
!python {model: sale.stock.reserve}: |
active_id = ref('sale_reserve_01')
context['active_id'] = active_id
context['active_ids'] = [active_id]
context['active_model'] = 'sale.order'
- self.button_reserve(cr, uid, [ref('wizard_reserve_01')], context=context)
+ wizard_id = self.create(cr, uid, {}, context=context)
+ self.button_reserve(cr, uid, [wizard_id], context=context)
-
I check Virtual stock of Gelato after update reservation
-
- !python {model: product.product}: |
- product = self.browse(cr, uid, ref('product_gelato'), context=context)
- assert product.virtual_available == 6, "Stock is not updated."
+ !python {model: product.product, id: product_gelato}: |
+ from nose.tools import *
+ assert_almost_equal(self.virtual_available, 6.0)
-
I release the sales order's reservations
-
@@ -59,6 +57,6 @@
-
I check Virtual stock of Gelato after release of reservations
-
- !python {model: product.product}: |
- product = self.browse(cr, uid, ref('product_gelato'), context=context)
- assert product.virtual_available == 10, "Stock is not updated."
+ !python {model: product.product, id: product_gelato}: |
+ from nose.tools import *
+ assert_almost_equal(self.virtual_available, 10.0)
diff --git a/stock_reserve_sale/wizard/sale_stock_reserve.py b/stock_reserve_sale/wizard/sale_stock_reserve.py
index 2fc7d1ff1c7f..67d9fb313a39 100644
--- a/stock_reserve_sale/wizard/sale_stock_reserve.py
+++ b/stock_reserve_sale/wizard/sale_stock_reserve.py
@@ -1,8 +1,8 @@
# -*- coding: utf-8 -*-
##############################################################################
#
-# Author: Guewen Baconnier
-# Copyright 2013 Camptocamp SA
+# Author: Guewen Baconnier, Leonardo Pistone
+# Copyright 2013-2015 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
@@ -19,7 +19,7 @@
#
##############################################################################
-from openerp import models, fields, api
+from openerp import models, fields, api, exceptions
class SaleStockReserve(models.TransientModel):
@@ -33,6 +33,32 @@ def _default_location_id(self):
def _default_location_dest_id(self):
return self.env['stock.reservation']._default_location_dest_id()
+ def _default_owner(self):
+ """If sale_owner_stock_sourcing is installed, it adds an owner field
+ on sale order lines. Use it.
+
+ """
+ model = self.env[self.env.context['active_model']]
+ if model._name == 'sale.order':
+ lines = model.browse(self.env.context['active_id']).order_line
+ else:
+ lines = model.browse(self.env.context['active_ids'])
+
+ try:
+ owners = set([l.stock_owner_id for l in lines])
+ except AttributeError:
+ return self.env['res.partner']
+ # module sale_owner_stock_sourcing not installed, fine
+
+ if len(owners) == 1:
+ return owners.pop()
+ elif len(owners) > 1:
+ raise exceptions.Warning(
+ 'The lines have different owners. Please reserve them '
+ 'individually with the reserve button on each one.')
+
+ return self.env['res.partner']
+
location_id = fields.Many2one(
'stock.location',
'Source Location',
@@ -50,6 +76,8 @@ def _default_location_dest_id(self):
help="If a date is given, the reservations will be released "
"at the end of the validity.")
note = fields.Text('Notes')
+ owner_id = fields.Many2one('res.partner', 'Stock Owner',
+ default=_default_owner)
@api.multi
def _prepare_stock_reservation(self, line):
@@ -67,6 +95,7 @@ def _prepare_stock_reservation(self, line):
'product_uos': product_uos,
'price_unit': line.price_unit,
'sale_line_id': line.id,
+ 'restrict_partner_id': self.owner_id.id,
}
@api.multi
diff --git a/stock_reserve_sale/wizard/sale_stock_reserve_view.xml b/stock_reserve_sale/wizard/sale_stock_reserve_view.xml
index 5b3c39bcccfb..69b3fb4ff98a 100644
--- a/stock_reserve_sale/wizard/sale_stock_reserve_view.xml
+++ b/stock_reserve_sale/wizard/sale_stock_reserve_view.xml
@@ -16,6 +16,7 @@
+
From 82500556c3b48f297e52387205dea4691ae15767 Mon Sep 17 00:00:00 2001
From: Miku Laitinen
Date: Thu, 23 Apr 2015 20:38:38 +0300
Subject: [PATCH 07/26] Added the translation template file and Finnish
translations to stock_reserve and stock_reserve_sale.
---
stock_reserve_sale/i18n/fi.po | 211 ++++++++++++++++++
.../i18n/stock_reserve_sale.pot | 188 ++++++++++++++++
2 files changed, 399 insertions(+)
create mode 100644 stock_reserve_sale/i18n/fi.po
create mode 100644 stock_reserve_sale/i18n/stock_reserve_sale.pot
diff --git a/stock_reserve_sale/i18n/fi.po b/stock_reserve_sale/i18n/fi.po
new file mode 100644
index 000000000000..2a1ea21fc2a5
--- /dev/null
+++ b/stock_reserve_sale/i18n/fi.po
@@ -0,0 +1,211 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * stock_reserve_sale
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 8.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2015-04-23 15:55+0000\n"
+"PO-Revision-Date: 2015-04-23 20:35+0200\n"
+"Last-Translator: Miku Laitinen \n"
+"Language-Team: Avoin.Systems \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 1.5.4\n"
+"Language: Finnish\n"
+"X-Poedit-SourceCharset: UTF-8\n"
+
+#. module: stock_reserve_sale
+#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+msgid ""
+"A stock reservation will be created for the products\n"
+" of the selected quotation lines. If a validity date "
+"is specified,\n"
+" the reservation will be released once the date has "
+"passed."
+msgstr ""
+"Tuotevaraus luodaan valittujen rivien tuotteille.\n"
+"Jos vapautuspäivä on määritetty, varaus peruutetaan automaattisesti "
+"kyseisenä päivänä."
+
+#. module: stock_reserve_sale
+#: code:addons/stock_reserve_sale/model/sale.py:179
+#, python-format
+msgid ""
+"As you changed the quantity of the line, the quantity of the stock "
+"reservation will be automatically adjusted to %.2f."
+msgstr ""
+"Muuttaessasi rivin kappalemäärää, tuotevarauksen kappalemäärä päivitetään "
+"automaattisesti arvoon %.2f."
+
+#. module: stock_reserve_sale
+#: field:sale.order,is_stock_reservable:0
+msgid "Can Have Stock Reservations"
+msgstr "Voi sisältää tuotevarauksia"
+
+#. module: stock_reserve_sale
+#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+msgid "Cancel"
+msgstr "Peruuta"
+
+#. module: stock_reserve_sale
+#: code:addons/stock_reserve_sale/model/sale.py:188
+#, python-format
+msgid "Configuration Error!"
+msgstr "Konfiguraatiovirhe."
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,create_uid:0
+msgid "Created by"
+msgstr "Luonut"
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,create_date:0
+msgid "Created on"
+msgstr "Luotu"
+
+#. module: stock_reserve_sale
+#: code:addons/stock_reserve_sale/model/sale.py:210
+#: code:addons/stock_reserve_sale/model/sale.py:222
+#, python-format
+msgid "Error"
+msgstr "Virhe"
+
+#. module: stock_reserve_sale
+#: field:sale.order,has_stock_reservation:0
+msgid "Has Stock Reservations"
+msgstr "Sisältää tuotevarauksia"
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,id:0
+msgid "ID"
+msgstr "ID"
+
+#. module: stock_reserve_sale
+#: help:sale.stock.reserve,date_validity:0
+msgid ""
+"If a date is given, the reservations will be released at the end of the "
+"validity."
+msgstr ""
+"Jos vapautuspäivä on määritetty, varaukset perutaan kyseisenä päivänä "
+"automaattisesti."
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,write_uid:0
+msgid "Last Updated by"
+msgstr "Viimeksi päivittänyt"
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,write_date:0
+msgid "Last Updated on"
+msgstr "Viimeksi päivitetty"
+
+#. module: stock_reserve_sale
+#: help:sale.stock.reserve,location_dest_id:0
+msgid "Location where the system will reserve the products."
+msgstr "Sijainti, jonne tuotteet varataan."
+
+#. module: stock_reserve_sale
+#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+#: field:sale.stock.reserve,note:0
+msgid "Notes"
+msgstr "Huomautukset"
+
+#. module: stock_reserve_sale
+#: view:sale.order:stock_reserve_sale.view_order_form_reserve
+msgid "Pre-book products from stock"
+msgstr "Varaa tuotteita varastosta"
+
+#. module: stock_reserve_sale
+#: view:sale.order:stock_reserve_sale.view_order_form_reserve
+msgid "Release Reservation"
+msgstr "Peru varaus"
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,location_dest_id:0
+msgid "Reservation Location"
+msgstr "Varauspaikka"
+
+#. module: stock_reserve_sale
+#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+msgid "Reserve"
+msgstr "Varaa"
+
+#. module: stock_reserve_sale
+#: view:sale.order:stock_reserve_sale.view_order_form_reserve
+#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+msgid "Reserve Stock"
+msgstr "Varaa tuotteet"
+
+#. module: stock_reserve_sale
+#: model:ir.actions.act_window,name:stock_reserve_sale.action_sale_stock_reserve
+msgid "Reserve Stock for Quotation Lines"
+msgstr "Rivien tuotteiden varaus"
+
+#. module: stock_reserve_sale
+#: field:stock.reservation,sale_line_id:0
+msgid "Sale Order Line"
+msgstr "Myyntitilausrivi"
+
+#. module: stock_reserve_sale
+#: view:stock.reservation:stock_reserve_sale.view_stock_reservation_form
+msgid "Sales"
+msgstr "Myynti"
+
+#. module: stock_reserve_sale
+#: model:ir.model,name:stock_reserve_sale.model_sale_order
+msgid "Sales Order"
+msgstr "Myyntitilaus"
+
+#. module: stock_reserve_sale
+#: model:ir.model,name:stock_reserve_sale.model_sale_order_line
+msgid "Sales Order Line"
+msgstr "Myyntitilausrivi"
+
+#. module: stock_reserve_sale
+#: code:addons/stock_reserve_sale/model/sale.py:223
+#, python-format
+msgid ""
+"Several stock reservations are linked with the line. Impossible to adjust "
+"their quantity. Please release the reservation before changing the quantity."
+msgstr ""
+"Riviin on linkitetty useita tuotevarauksia. Kappalemäärien muokkaaminen ei "
+"ole mahdollista. Ole hyvä ja peruuta varaus ennen määrien muokkaamista."
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,location_id:0
+msgid "Source Location"
+msgstr "Lähtöpaikka"
+
+#. module: stock_reserve_sale
+#: model:ir.model,name:stock_reserve_sale.model_stock_reservation
+#: field:sale.order.line,reservation_ids:0
+msgid "Stock Reservation"
+msgstr "Tuotevaraus"
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,date_validity:0
+msgid "Validity Date"
+msgstr "Vapautuspäivä"
+
+#. module: stock_reserve_sale
+#: code:addons/stock_reserve_sale/model/sale.py:211
+#, python-format
+msgid ""
+"You cannot change the product or unit of measure of lines with a stock "
+"reservation. Release the reservation before changing the product."
+msgstr ""
+"Et voi vaihtaa tuotetta tai tuotteen yksikköä, jos rivillä on tuotevaraus. "
+"Peruuta varaus ennen tuotteen vaihtamista."
+
+#. module: stock_reserve_sale
+#: view:sale.order:stock_reserve_sale.view_order_form_reserve
+msgid "cancel all"
+msgstr "peru kaikki"
+
+#. module: stock_reserve_sale
+#: view:sale.order:stock_reserve_sale.view_order_form_reserve
+msgid "{\"reload_on_button\": 1}"
+msgstr "{\"reload_on_button\": 1}"
diff --git a/stock_reserve_sale/i18n/stock_reserve_sale.pot b/stock_reserve_sale/i18n/stock_reserve_sale.pot
new file mode 100644
index 000000000000..edbb02c40238
--- /dev/null
+++ b/stock_reserve_sale/i18n/stock_reserve_sale.pot
@@ -0,0 +1,188 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * stock_reserve_sale
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 8.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2015-04-23 15:55+0000\n"
+"PO-Revision-Date: 2015-04-23 15:55+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_reserve_sale
+#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+msgid "A stock reservation will be created for the products\n"
+" of the selected quotation lines. If a validity date is specified,\n"
+" the reservation will be released once the date has passed."
+msgstr ""
+
+#. module: stock_reserve_sale
+#: code:addons/stock_reserve_sale/model/sale.py:179
+#, python-format
+msgid "As you changed the quantity of the line, the quantity of the stock reservation will be automatically adjusted to %.2f."
+msgstr ""
+
+#. module: stock_reserve_sale
+#: field:sale.order,is_stock_reservable:0
+msgid "Can Have Stock Reservations"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+msgid "Cancel"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: code:addons/stock_reserve_sale/model/sale.py:188
+#, python-format
+msgid "Configuration Error!"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,create_uid:0
+msgid "Created by"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,create_date:0
+msgid "Created on"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: code:addons/stock_reserve_sale/model/sale.py:210
+#: code:addons/stock_reserve_sale/model/sale.py:222
+#, python-format
+msgid "Error"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: field:sale.order,has_stock_reservation:0
+msgid "Has Stock Reservations"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,id:0
+msgid "ID"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: help:sale.stock.reserve,date_validity:0
+msgid "If a date is given, the reservations will be released at the end of the validity."
+msgstr ""
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,write_uid:0
+msgid "Last Updated by"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,write_date:0
+msgid "Last Updated on"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: help:sale.stock.reserve,location_dest_id:0
+msgid "Location where the system will reserve the products."
+msgstr ""
+
+#. module: stock_reserve_sale
+#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+#: field:sale.stock.reserve,note:0
+msgid "Notes"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: view:sale.order:stock_reserve_sale.view_order_form_reserve
+msgid "Pre-book products from stock"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: view:sale.order:stock_reserve_sale.view_order_form_reserve
+msgid "Release Reservation"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,location_dest_id:0
+msgid "Reservation Location"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+msgid "Reserve"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: view:sale.order:stock_reserve_sale.view_order_form_reserve
+#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+msgid "Reserve Stock"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model:ir.actions.act_window,name:stock_reserve_sale.action_sale_stock_reserve
+msgid "Reserve Stock for Quotation Lines"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: field:stock.reservation,sale_line_id:0
+msgid "Sale Order Line"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: view:stock.reservation:stock_reserve_sale.view_stock_reservation_form
+msgid "Sales"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model:ir.model,name:stock_reserve_sale.model_sale_order
+msgid "Sales Order"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model:ir.model,name:stock_reserve_sale.model_sale_order_line
+msgid "Sales Order Line"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: code:addons/stock_reserve_sale/model/sale.py:223
+#, python-format
+msgid "Several stock reservations are linked with the line. Impossible to adjust their quantity. Please release the reservation before changing the quantity."
+msgstr ""
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,location_id:0
+msgid "Source Location"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model:ir.model,name:stock_reserve_sale.model_stock_reservation
+#: field:sale.order.line,reservation_ids:0
+msgid "Stock Reservation"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,date_validity:0
+msgid "Validity Date"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: code:addons/stock_reserve_sale/model/sale.py:211
+#, python-format
+msgid "You cannot change the product or unit of measure of lines with a stock reservation. Release the reservation before changing the product."
+msgstr ""
+
+#. module: stock_reserve_sale
+#: view:sale.order:stock_reserve_sale.view_order_form_reserve
+msgid "cancel all"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: view:sale.order:stock_reserve_sale.view_order_form_reserve
+msgid "{\"reload_on_button\": 1}"
+msgstr ""
+
From 3a55b664d928d3eb62f6b76f8aa40b64708b6af2 Mon Sep 17 00:00:00 2001
From: Alexandre MOREAU
Date: Mon, 1 Jun 2015 14:30:57 +0200
Subject: [PATCH 08/26] Add README.rst and remove description from
__openerp__.py
---
stock_reserve_sale/README.rst | 66 +++++++++++++++++++++++++++++++
stock_reserve_sale/__openerp__.py | 29 --------------
2 files changed, 66 insertions(+), 29 deletions(-)
create mode 100644 stock_reserve_sale/README.rst
diff --git a/stock_reserve_sale/README.rst b/stock_reserve_sale/README.rst
new file mode 100644
index 000000000000..abcdfe86d896
--- /dev/null
+++ b/stock_reserve_sale/README.rst
@@ -0,0 +1,66 @@
+.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
+ :alt: License: AGPL-3
+
+Stock Reserve Sale
+==================
+
+Allows to create stock reservations for quotation lines before the
+confirmation of the quotation. The reservations might have a validity
+date and in any case they are lifted when the quotation is canceled or
+confirmed.
+
+Reservations can be done only on "make to stock" and stockable products.
+
+The reserved products are subtracted 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.
+
+If you want to prevent sales orders to be confirmed when the stock is
+insufficient at the order date, you may want to install the
+`sale_exception_nostock` module.
+
+Additionally, if the sale_owner_stock_sourcing module is installed, the owner
+specified on the sale order line will be proposed as owner of the reservation.
+If you try to make a reservation for an order whose lines have different, you
+will get a message suggesting to reserve each line individually. There is no
+module dependency: this modules is fully functional even without ownership
+management.
+
+
+Bug Tracker
+===========
+
+Bugs are tracked on `GitHub Issues `_.
+In case of trouble, please check there if your issue has already been reported.
+If you spotted it first, help us smashing it by providing a detailed and welcomed feedback
+`here `_.
+
+
+Credits
+=======
+
+Contributors
+------------
+
+* Leonardo Pistone
+* Alexandre Fayolle
+* Yannick Vaucher
+* Guewen Baconnier
+
+Maintainer
+----------
+
+.. image:: https://odoo-community.org/logo.png
+ :alt: Odoo Community Association
+ :target: https://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.
+
diff --git a/stock_reserve_sale/__openerp__.py b/stock_reserve_sale/__openerp__.py
index 3fa481478874..119e00bb1337 100644
--- a/stock_reserve_sale/__openerp__.py
+++ b/stock_reserve_sale/__openerp__.py
@@ -27,35 +27,6 @@
'complexity': 'normal',
'images': [],
'website': "http://www.camptocamp.com",
- 'description': """
-Stock Reserve Sales
-===================
-
-Allows to create stock reservations for quotation lines before the
-confirmation of the quotation. The reservations might have a validity
-date and in any case they are lifted when the quotation is canceled or
-confirmed.
-
-Reservations can be done only on "make to stock" and stockable products.
-
-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.
-
-If you want to prevent sales orders to be confirmed when the stock is
-insufficient at the order date, you may want to install the
-`sale_exception_nostock` module.
-
-Additionally, if the sale_owner_stock_sourcing module is installed, the owner
-specified on the sale order line will be proposed as owner of the reservation.
-If you try to make a reservation for an order whose lines have different, you
-will get a message suggesting to reserve each line individually. There is no
-module dependency: this modules is fully functional even without ownership
-management.
-
-""",
'depends': ['sale_stock',
'stock_reserve',
],
From c85d76e04d71d9a2e737f117a1d975c7ce7771fb Mon Sep 17 00:00:00 2001
From: Miku Laitinen
Date: Sat, 25 Apr 2015 22:40:24 +0300
Subject: [PATCH 09/26] Multiple reservations can now be released at once. This
fixes issue #50.
---
stock_reserve_sale/test/sale_reserve.yml | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/stock_reserve_sale/test/sale_reserve.yml b/stock_reserve_sale/test/sale_reserve.yml
index 9afc4dff9c68..7450caad643f 100644
--- a/stock_reserve_sale/test/sale_reserve.yml
+++ b/stock_reserve_sale/test/sale_reserve.yml
@@ -33,6 +33,8 @@
order_line:
- product_id: product_gelato
product_uom_qty: 4
+ - product_id: product_gelato
+ product_uom_qty: 1
-
I call the wizard to reserve the products of the sales order
-
@@ -46,9 +48,9 @@
-
I check Virtual stock of Gelato after update reservation
-
- !python {model: product.product, id: product_gelato}: |
- from nose.tools import *
- assert_almost_equal(self.virtual_available, 6.0)
+ !python {model: product.product}: |
+ product = self.browse(cr, uid, ref('product_gelato'), context=context)
+ assert product.virtual_available == 5, "Stock is not updated after reservation."
-
I release the sales order's reservations
-
@@ -57,6 +59,6 @@
-
I check Virtual stock of Gelato after release of reservations
-
- !python {model: product.product, id: product_gelato}: |
- from nose.tools import *
- assert_almost_equal(self.virtual_available, 10.0)
+ !python {model: product.product}: |
+ product = self.browse(cr, uid, ref('product_gelato'), context=context)
+ assert product.virtual_available == 10, "Stock is not updated after releasing reservations."
From e8c2f8f1f1298d304bc5788b53650547d33303fa Mon Sep 17 00:00:00 2001
From: Ismael Calvo
Date: Thu, 30 Jul 2015 17:57:12 +0200
Subject: [PATCH 10/26] Add Spanish translation of stock reserve modules
---
stock_reserve_sale/i18n/es.po | 191 ++++++++++++++++++++++++++++++++++
1 file changed, 191 insertions(+)
create mode 100644 stock_reserve_sale/i18n/es.po
diff --git a/stock_reserve_sale/i18n/es.po b/stock_reserve_sale/i18n/es.po
new file mode 100644
index 000000000000..8cbe9f194467
--- /dev/null
+++ b/stock_reserve_sale/i18n/es.po
@@ -0,0 +1,191 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * stock_reserve_sale
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 8.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2015-04-23 15:55+0000\n"
+"PO-Revision-Date: 2015-07-30 17:30+0000\n"
+"Last-Translator: Ismael Calvo \n"
+"Language-Team: FactorLibre \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: stock_reserve_sale
+#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+msgid "A stock reservation will be created for the products\n"
+" of the selected quotation lines. If a validity date is specified,\n"
+" the reservation will be released once the date has passed."
+msgstr "
+"Se creará una reserva de existencias para los productos\n"
+" de las líneas del presupuesto seleccionado. Si se especifica "
+"una fecha de validez,\n"
+" la reserva se lanzará una vez que la fecha haya pasado."
+
+#. module: stock_reserve_sale
+#: code:addons/stock_reserve_sale/model/sale.py:179
+#, python-format
+msgid "As you changed the quantity of the line, the quantity of the stock reservation will be automatically adjusted to %.2f."
+msgstr "Como ha cambiado la cantidad de la línea, la cantidad de la reserva de existencias será ajustada automáticamente a %.2f."
+
+#. module: stock_reserve_sale
+#: field:sale.order,is_stock_reservable:0
+msgid "Can Have Stock Reservations"
+msgstr "Puede tener reservas de existencias"
+
+#. module: stock_reserve_sale
+#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+msgid "Cancel"
+msgstr "Cancelar"
+
+#. module: stock_reserve_sale
+#: code:addons/stock_reserve_sale/model/sale.py:188
+#, python-format
+msgid "Configuration Error!"
+msgstr "¡Error de configuración!"
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,create_uid:0
+msgid "Created by"
+msgstr "Creado por"
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,create_date:0
+msgid "Created on"
+msgstr "Creado el"
+
+#. module: stock_reserve_sale
+#: code:addons/stock_reserve_sale/model/sale.py:210
+#: code:addons/stock_reserve_sale/model/sale.py:222
+#, python-format
+msgid "Error"
+msgstr "Error"
+
+#. module: stock_reserve_sale
+#: field:sale.order,has_stock_reservation:0
+msgid "Has Stock Reservations"
+msgstr "Tiene reservas de existencias"
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,id:0
+msgid "ID"
+msgstr "ID"
+
+#. module: stock_reserve_sale
+#: help:sale.stock.reserve,date_validity:0
+msgid "If a date is given, the reservations will be released at the end of the validity."
+msgstr "Si se proporciona una fecha, las reservas serán lanzadas al final de esa fecha."
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,write_uid:0
+msgid "Last Updated by"
+msgstr "Actualizado por última vez por"
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,write_date:0
+msgid "Last Updated on"
+msgstr "Actualizado por última vez el"
+
+#. module: stock_reserve_sale
+#: help:sale.stock.reserve,location_dest_id:0
+msgid "Location where the system will reserve the products."
+msgstr "Ubicación donde el sistema reservará los productos."
+
+#. module: stock_reserve_sale
+#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+#: field:sale.stock.reserve,note:0
+msgid "Notes"
+msgstr "Notas"
+
+#. module: stock_reserve_sale
+#: view:sale.order:stock_reserve_sale.view_order_form_reserve
+msgid "Pre-book products from stock"
+msgstr "Pre reserva de productos de existencias"
+
+#. module: stock_reserve_sale
+#: view:sale.order:stock_reserve_sale.view_order_form_reserve
+msgid "Release Reservation"
+msgstr "Reserva de lanzamiento"
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,location_dest_id:0
+msgid "Reservation Location"
+msgstr "Ubicación de reserva"
+
+#. module: stock_reserve_sale
+#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+msgid "Reserve"
+msgstr "Reservar"
+
+#. module: stock_reserve_sale
+#: view:sale.order:stock_reserve_sale.view_order_form_reserve
+#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+msgid "Reserve Stock"
+msgstr "Reservar existencias"
+
+#. module: stock_reserve_sale
+#: model:ir.actions.act_window,name:stock_reserve_sale.action_sale_stock_reserve
+msgid "Reserve Stock for Quotation Lines"
+msgstr "Reservar existencias para las líneas de presupuesto"
+
+#. module: stock_reserve_sale
+#: field:stock.reservation,sale_line_id:0
+msgid "Sale Order Line"
+msgstr "Línea de pedido de venta"
+
+#. module: stock_reserve_sale
+#: view:stock.reservation:stock_reserve_sale.view_stock_reservation_form
+msgid "Sales"
+msgstr "Ventas"
+
+#. module: stock_reserve_sale
+#: model:ir.model,name:stock_reserve_sale.model_sale_order
+msgid "Sales Order"
+msgstr "Pedido de ventas"
+
+#. module: stock_reserve_sale
+#: model:ir.model,name:stock_reserve_sale.model_sale_order_line
+msgid "Sales Order Line"
+msgstr "Línea de pedido de ventas"
+
+#. module: stock_reserve_sale
+#: code:addons/stock_reserve_sale/model/sale.py:223
+#, python-format
+msgid "Several stock reservations are linked with the line. Impossible to adjust their quantity. Please release the reservation before changing the quantity."
+msgstr "Distintas reservas de existencias están enlazadas con la línea. Imposible ajustar su cantidad. Por favor lance la reserva antes de cambiar la cantidad"
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,location_id:0
+msgid "Source Location"
+msgstr "Ubicación origen"
+
+#. module: stock_reserve_sale
+#: model:ir.model,name:stock_reserve_sale.model_stock_reservation
+#: field:sale.order.line,reservation_ids:0
+msgid "Stock Reservation"
+msgstr "Reserva de existencias"
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,date_validity:0
+msgid "Validity Date"
+msgstr "Fecha de validez"
+
+#. module: stock_reserve_sale
+#: code:addons/stock_reserve_sale/model/sale.py:211
+#, python-format
+msgid "You cannot change the product or unit of measure of lines with a stock reservation. Release the reservation before changing the product."
+msgstr "No puede cambiar la unidad de medida de los productos de las líneas con una reserva de existencias. Lance la reserva antes de cambiar el producto."
+
+#. module: stock_reserve_sale
+#: view:sale.order:stock_reserve_sale.view_order_form_reserve
+msgid "cancel all"
+msgstr "cancelar todo"
+
+#. module: stock_reserve_sale
+#: view:sale.order:stock_reserve_sale.view_order_form_reserve
+msgid "{\"reload_on_button\": 1}"
+msgstr "{\"reload_on_button\": 1}"
From 8fc78f85e1bc286ed63f106b85a8b62f961dab71 Mon Sep 17 00:00:00 2001
From: Alexandre Fayolle
Date: Tue, 15 Sep 2015 12:50:24 +0200
Subject: [PATCH 11/26] force recomputation of stock.location hierachy
before running the tests. This fixes the failure experienced when running the
test in --init mode rather than --update mode.
---
stock_reserve_sale/test/sale_reserve.yml | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/stock_reserve_sale/test/sale_reserve.yml b/stock_reserve_sale/test/sale_reserve.yml
index 7450caad643f..a3a81a472ac0 100644
--- a/stock_reserve_sale/test/sale_reserve.yml
+++ b/stock_reserve_sale/test/sale_reserve.yml
@@ -1,3 +1,12 @@
+-
+ I force recomputation of stock.location parent left/right
+-
+ !python {model: stock.location}:
+ # we need this because when running the tests at install time as is done on
+ # Travis, the hook performing this operation for the new stock reservation
+ # location is run after the test execution. This causes the stock level
+ # computation to be wrong at the time the tests are run.
+ self._parent_store_compute(cr)
-
I create a product to test the stock reservation
-
From f6da8ba66b405d17c416a1c782311ee898847f88 Mon Sep 17 00:00:00 2001
From: OCA Transbot
Date: Mon, 5 Oct 2015 06:16:20 -0400
Subject: [PATCH 12/26] OCA Transbot updated translations from Transifex
---
stock_reserve_sale/i18n/en.po | 208 +++++++++++++++++++++++++++++++++
stock_reserve_sale/i18n/es.po | 97 +++++++++-------
stock_reserve_sale/i18n/fr.po | 209 ++++++++++++++++++++++++++++++++++
3 files changed, 474 insertions(+), 40 deletions(-)
create mode 100644 stock_reserve_sale/i18n/en.po
create mode 100644 stock_reserve_sale/i18n/fr.po
diff --git a/stock_reserve_sale/i18n/en.po b/stock_reserve_sale/i18n/en.po
new file mode 100644
index 000000000000..f8d6cee68767
--- /dev/null
+++ b/stock_reserve_sale/i18n/en.po
@@ -0,0 +1,208 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * stock_reserve_sale
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: stock-logistics-warehouse (8.0)\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2015-09-23 20:23+0000\n"
+"PO-Revision-Date: 2015-09-15 13:05+0000\n"
+"Last-Translator: OCA Transbot \n"
+"Language-Team: English (http://www.transifex.com/oca/OCA-stock-logistics-warehouse-8-0/language/en/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Language: en\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: stock_reserve_sale
+#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+msgid ""
+"A stock reservation will be created for the products\n"
+" of the selected quotation lines. If a validity date is specified,\n"
+" the reservation will be released once the date has passed."
+msgstr "A stock reservation will be created for the products\n of the selected quotation lines. If a validity date is specified,\n the reservation will be released once the date has passed."
+
+#. module: stock_reserve_sale
+#: code:addons/stock_reserve_sale/model/sale.py:179
+#, python-format
+msgid ""
+"As you changed the quantity of the line, the quantity of the stock "
+"reservation will be automatically adjusted to %.2f."
+msgstr "As you changed the quantity of the line, the quantity of the stock reservation will be automatically adjusted to %.2f."
+
+#. module: stock_reserve_sale
+#: field:sale.order,is_stock_reservable:0
+msgid "Can Have Stock Reservations"
+msgstr "Can Have Stock Reservations"
+
+#. module: stock_reserve_sale
+#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+msgid "Cancel"
+msgstr "Cancel"
+
+#. module: stock_reserve_sale
+#: code:addons/stock_reserve_sale/model/sale.py:188
+#, python-format
+msgid "Configuration Error!"
+msgstr "Configuration Error!"
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,create_uid:0
+msgid "Created by"
+msgstr "Created by"
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,create_date:0
+msgid "Created on"
+msgstr "Created on"
+
+#. module: stock_reserve_sale
+#: code:addons/stock_reserve_sale/model/sale.py:210
+#: code:addons/stock_reserve_sale/model/sale.py:222
+#, python-format
+msgid "Error"
+msgstr "Error"
+
+#. module: stock_reserve_sale
+#: field:sale.order,has_stock_reservation:0
+msgid "Has Stock Reservations"
+msgstr "Has Stock Reservations"
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,id:0
+msgid "ID"
+msgstr "ID"
+
+#. module: stock_reserve_sale
+#: help:sale.stock.reserve,date_validity:0
+msgid ""
+"If a date is given, the reservations will be released at the end of the "
+"validity."
+msgstr "If a date is given, the reservations will be released at the end of the validity."
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,write_uid:0
+msgid "Last Updated by"
+msgstr "Last Updated by"
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,write_date:0
+msgid "Last Updated on"
+msgstr "Last Updated on"
+
+#. module: stock_reserve_sale
+#: help:sale.stock.reserve,location_dest_id:0
+msgid "Location where the system will reserve the products."
+msgstr "Location where the system will reserve the products."
+
+#. module: stock_reserve_sale
+#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+#: field:sale.stock.reserve,note:0
+msgid "Notes"
+msgstr "Notes"
+
+#. module: stock_reserve_sale
+#: view:sale.order:stock_reserve_sale.view_order_form_reserve
+msgid "Pre-book products from stock"
+msgstr "Pre-book products from stock"
+
+#. module: stock_reserve_sale
+#: view:sale.order:stock_reserve_sale.view_order_form_reserve
+msgid "Release Reservation"
+msgstr "Release Reservation"
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,location_dest_id:0
+msgid "Reservation Location"
+msgstr "Reservation Location"
+
+#. module: stock_reserve_sale
+#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+msgid "Reserve"
+msgstr "Reserve"
+
+#. module: stock_reserve_sale
+#: view:sale.order:stock_reserve_sale.view_order_form_reserve
+#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+msgid "Reserve Stock"
+msgstr "Reserve Stock"
+
+#. module: stock_reserve_sale
+#: model:ir.actions.act_window,name:stock_reserve_sale.action_sale_stock_reserve
+msgid "Reserve Stock for Quotation Lines"
+msgstr "Reserve Stock for Quotation Lines"
+
+#. module: stock_reserve_sale
+#: field:stock.reservation,sale_line_id:0
+msgid "Sale Order Line"
+msgstr "Sale Order Line"
+
+#. module: stock_reserve_sale
+#: view:stock.reservation:stock_reserve_sale.view_stock_reservation_form
+msgid "Sales"
+msgstr "Sales"
+
+#. module: stock_reserve_sale
+#: model:ir.model,name:stock_reserve_sale.model_sale_order
+msgid "Sales Order"
+msgstr "Sales Order"
+
+#. module: stock_reserve_sale
+#: model:ir.model,name:stock_reserve_sale.model_sale_order_line
+msgid "Sales Order Line"
+msgstr "Sales Order Line"
+
+#. module: stock_reserve_sale
+#: code:addons/stock_reserve_sale/model/sale.py:223
+#, python-format
+msgid ""
+"Several stock reservations are linked with the line. Impossible to adjust "
+"their quantity. Please release the reservation before changing the quantity."
+msgstr "Several stock reservations are linked with the line. Impossible to adjust their quantity. Please release the reservation before changing the quantity."
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,location_id:0
+msgid "Source Location"
+msgstr "Source Location"
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,owner_id:0
+msgid "Stock Owner"
+msgstr "Stock Owner"
+
+#. module: stock_reserve_sale
+#: model:ir.model,name:stock_reserve_sale.model_stock_reservation
+#: field:sale.order.line,reservation_ids:0
+msgid "Stock Reservation"
+msgstr "Stock Reservation"
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,date_validity:0
+msgid "Validity Date"
+msgstr "Validity Date"
+
+#. module: stock_reserve_sale
+#: code:addons/stock_reserve_sale/model/sale.py:211
+#, python-format
+msgid ""
+"You cannot change the product or unit of measure of lines with a stock "
+"reservation. Release the reservation before changing the product."
+msgstr "You cannot change the product or unit of measure of lines with a stock reservation. Release the reservation before changing the product."
+
+#. module: stock_reserve_sale
+#: view:sale.order:stock_reserve_sale.view_order_form_reserve
+msgid "cancel all"
+msgstr "cancel all"
+
+#. module: stock_reserve_sale
+#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+msgid "or"
+msgstr "or"
+
+#. module: stock_reserve_sale
+#: view:sale.order:stock_reserve_sale.view_order_form_reserve
+msgid "{\"reload_on_button\": 1}"
+msgstr "{\"reload_on_button\": 1}"
diff --git a/stock_reserve_sale/i18n/es.po b/stock_reserve_sale/i18n/es.po
index 8cbe9f194467..30e87bbb5bd6 100644
--- a/stock_reserve_sale/i18n/es.po
+++ b/stock_reserve_sale/i18n/es.po
@@ -1,52 +1,53 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
-# * stock_reserve_sale
-#
+# * stock_reserve_sale
+#
+# Translators:
msgid ""
msgstr ""
-"Project-Id-Version: Odoo Server 8.0\n"
+"Project-Id-Version: stock-logistics-warehouse (8.0)\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-04-23 15:55+0000\n"
-"PO-Revision-Date: 2015-07-30 17:30+0000\n"
-"Last-Translator: Ismael Calvo \n"
-"Language-Team: FactorLibre \n"
+"POT-Creation-Date: 2015-09-23 20:23+0000\n"
+"PO-Revision-Date: 2015-09-15 13:05+0000\n"
+"Last-Translator: <>\n"
+"Language-Team: Spanish (http://www.transifex.com/oca/OCA-stock-logistics-warehouse-8-0/language/es/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
-"Plural-Forms: \n"
+"Language: es\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#. module: stock_reserve_sale
#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
-msgid "A stock reservation will be created for the products\n"
+msgid ""
+"A stock reservation will be created for the products\n"
" of the selected quotation lines. If a validity date is specified,\n"
" the reservation will be released once the date has passed."
-msgstr "
-"Se creará una reserva de existencias para los productos\n"
-" de las líneas del presupuesto seleccionado. Si se especifica "
-"una fecha de validez,\n"
-" la reserva se lanzará una vez que la fecha haya pasado."
+msgstr ""
#. module: stock_reserve_sale
#: code:addons/stock_reserve_sale/model/sale.py:179
#, python-format
-msgid "As you changed the quantity of the line, the quantity of the stock reservation will be automatically adjusted to %.2f."
-msgstr "Como ha cambiado la cantidad de la línea, la cantidad de la reserva de existencias será ajustada automáticamente a %.2f."
+msgid ""
+"As you changed the quantity of the line, the quantity of the stock "
+"reservation will be automatically adjusted to %.2f."
+msgstr ""
#. module: stock_reserve_sale
#: field:sale.order,is_stock_reservable:0
msgid "Can Have Stock Reservations"
-msgstr "Puede tener reservas de existencias"
+msgstr ""
#. module: stock_reserve_sale
#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
msgid "Cancel"
-msgstr "Cancelar"
+msgstr ""
#. module: stock_reserve_sale
#: code:addons/stock_reserve_sale/model/sale.py:188
#, python-format
msgid "Configuration Error!"
-msgstr "¡Error de configuración!"
+msgstr ""
#. module: stock_reserve_sale
#: field:sale.stock.reserve,create_uid:0
@@ -63,12 +64,12 @@ msgstr "Creado el"
#: code:addons/stock_reserve_sale/model/sale.py:222
#, python-format
msgid "Error"
-msgstr "Error"
+msgstr ""
#. module: stock_reserve_sale
#: field:sale.order,has_stock_reservation:0
msgid "Has Stock Reservations"
-msgstr "Tiene reservas de existencias"
+msgstr ""
#. module: stock_reserve_sale
#: field:sale.stock.reserve,id:0
@@ -77,8 +78,10 @@ msgstr "ID"
#. module: stock_reserve_sale
#: help:sale.stock.reserve,date_validity:0
-msgid "If a date is given, the reservations will be released at the end of the validity."
-msgstr "Si se proporciona una fecha, las reservas serán lanzadas al final de esa fecha."
+msgid ""
+"If a date is given, the reservations will be released at the end of the "
+"validity."
+msgstr ""
#. module: stock_reserve_sale
#: field:sale.stock.reserve,write_uid:0
@@ -93,7 +96,7 @@ msgstr "Actualizado por última vez el"
#. module: stock_reserve_sale
#: help:sale.stock.reserve,location_dest_id:0
msgid "Location where the system will reserve the products."
-msgstr "Ubicación donde el sistema reservará los productos."
+msgstr ""
#. module: stock_reserve_sale
#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
@@ -104,17 +107,17 @@ msgstr "Notas"
#. module: stock_reserve_sale
#: view:sale.order:stock_reserve_sale.view_order_form_reserve
msgid "Pre-book products from stock"
-msgstr "Pre reserva de productos de existencias"
+msgstr ""
#. module: stock_reserve_sale
#: view:sale.order:stock_reserve_sale.view_order_form_reserve
msgid "Release Reservation"
-msgstr "Reserva de lanzamiento"
+msgstr ""
#. module: stock_reserve_sale
#: field:sale.stock.reserve,location_dest_id:0
msgid "Reservation Location"
-msgstr "Ubicación de reserva"
+msgstr ""
#. module: stock_reserve_sale
#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
@@ -125,43 +128,50 @@ msgstr "Reservar"
#: view:sale.order:stock_reserve_sale.view_order_form_reserve
#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
msgid "Reserve Stock"
-msgstr "Reservar existencias"
+msgstr ""
#. module: stock_reserve_sale
#: model:ir.actions.act_window,name:stock_reserve_sale.action_sale_stock_reserve
msgid "Reserve Stock for Quotation Lines"
-msgstr "Reservar existencias para las líneas de presupuesto"
+msgstr ""
#. module: stock_reserve_sale
#: field:stock.reservation,sale_line_id:0
msgid "Sale Order Line"
-msgstr "Línea de pedido de venta"
+msgstr ""
#. module: stock_reserve_sale
#: view:stock.reservation:stock_reserve_sale.view_stock_reservation_form
msgid "Sales"
-msgstr "Ventas"
+msgstr ""
#. module: stock_reserve_sale
#: model:ir.model,name:stock_reserve_sale.model_sale_order
msgid "Sales Order"
-msgstr "Pedido de ventas"
+msgstr ""
#. module: stock_reserve_sale
#: model:ir.model,name:stock_reserve_sale.model_sale_order_line
msgid "Sales Order Line"
-msgstr "Línea de pedido de ventas"
+msgstr ""
#. module: stock_reserve_sale
#: code:addons/stock_reserve_sale/model/sale.py:223
#, python-format
-msgid "Several stock reservations are linked with the line. Impossible to adjust their quantity. Please release the reservation before changing the quantity."
-msgstr "Distintas reservas de existencias están enlazadas con la línea. Imposible ajustar su cantidad. Por favor lance la reserva antes de cambiar la cantidad"
+msgid ""
+"Several stock reservations are linked with the line. Impossible to adjust "
+"their quantity. Please release the reservation before changing the quantity."
+msgstr ""
#. module: stock_reserve_sale
#: field:sale.stock.reserve,location_id:0
msgid "Source Location"
-msgstr "Ubicación origen"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,owner_id:0
+msgid "Stock Owner"
+msgstr ""
#. module: stock_reserve_sale
#: model:ir.model,name:stock_reserve_sale.model_stock_reservation
@@ -177,15 +187,22 @@ msgstr "Fecha de validez"
#. module: stock_reserve_sale
#: code:addons/stock_reserve_sale/model/sale.py:211
#, python-format
-msgid "You cannot change the product or unit of measure of lines with a stock reservation. Release the reservation before changing the product."
-msgstr "No puede cambiar la unidad de medida de los productos de las líneas con una reserva de existencias. Lance la reserva antes de cambiar el producto."
+msgid ""
+"You cannot change the product or unit of measure of lines with a stock "
+"reservation. Release the reservation before changing the product."
+msgstr ""
#. module: stock_reserve_sale
#: view:sale.order:stock_reserve_sale.view_order_form_reserve
msgid "cancel all"
-msgstr "cancelar todo"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+msgid "or"
+msgstr ""
#. module: stock_reserve_sale
#: view:sale.order:stock_reserve_sale.view_order_form_reserve
msgid "{\"reload_on_button\": 1}"
-msgstr "{\"reload_on_button\": 1}"
+msgstr ""
diff --git a/stock_reserve_sale/i18n/fr.po b/stock_reserve_sale/i18n/fr.po
new file mode 100644
index 000000000000..79dfac1cc14c
--- /dev/null
+++ b/stock_reserve_sale/i18n/fr.po
@@ -0,0 +1,209 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * stock_reserve_sale
+#
+# Translators:
+# Pierre Verkest , 2015
+msgid ""
+msgstr ""
+"Project-Id-Version: stock-logistics-warehouse (8.0)\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2015-09-23 20:23+0000\n"
+"PO-Revision-Date: 2015-09-27 21:09+0000\n"
+"Last-Translator: Pierre Verkest \n"
+"Language-Team: French (http://www.transifex.com/oca/OCA-stock-logistics-warehouse-8-0/language/fr/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Language: fr\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+#. module: stock_reserve_sale
+#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+msgid ""
+"A stock reservation will be created for the products\n"
+" of the selected quotation lines. If a validity date is specified,\n"
+" the reservation will be released once the date has passed."
+msgstr "Une réservation de stock sera créée pour les produits\ndes lignes de devis sélectionnées. Si une date de validité est\nspécifiée, la réservation sera annulée une fois cette date dépassée."
+
+#. module: stock_reserve_sale
+#: code:addons/stock_reserve_sale/model/sale.py:179
+#, python-format
+msgid ""
+"As you changed the quantity of the line, the quantity of the stock "
+"reservation will be automatically adjusted to %.2f."
+msgstr "Suite au changement de quantité de la ligne, la quantité de stock réservée va être ajusté à %.2f."
+
+#. module: stock_reserve_sale
+#: field:sale.order,is_stock_reservable:0
+msgid "Can Have Stock Reservations"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+msgid "Cancel"
+msgstr "Annuler"
+
+#. module: stock_reserve_sale
+#: code:addons/stock_reserve_sale/model/sale.py:188
+#, python-format
+msgid "Configuration Error!"
+msgstr "Erreur de configuration!"
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,create_uid:0
+msgid "Created by"
+msgstr "Créé par"
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,create_date:0
+msgid "Created on"
+msgstr "Créé le"
+
+#. module: stock_reserve_sale
+#: code:addons/stock_reserve_sale/model/sale.py:210
+#: code:addons/stock_reserve_sale/model/sale.py:222
+#, python-format
+msgid "Error"
+msgstr "Erreur"
+
+#. module: stock_reserve_sale
+#: field:sale.order,has_stock_reservation:0
+msgid "Has Stock Reservations"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,id:0
+msgid "ID"
+msgstr "ID"
+
+#. module: stock_reserve_sale
+#: help:sale.stock.reserve,date_validity:0
+msgid ""
+"If a date is given, the reservations will be released at the end of the "
+"validity."
+msgstr "Si une date est donnée, la réservation sera annulée à la fin de cette date de validité."
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,write_uid:0
+msgid "Last Updated by"
+msgstr "Dernière màj par"
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,write_date:0
+msgid "Last Updated on"
+msgstr "Dernière màj le"
+
+#. module: stock_reserve_sale
+#: help:sale.stock.reserve,location_dest_id:0
+msgid "Location where the system will reserve the products."
+msgstr "Emplacement de stock où sont réservés les produits (pour le système)."
+
+#. module: stock_reserve_sale
+#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+#: field:sale.stock.reserve,note:0
+msgid "Notes"
+msgstr "Notes"
+
+#. module: stock_reserve_sale
+#: view:sale.order:stock_reserve_sale.view_order_form_reserve
+msgid "Pre-book products from stock"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: view:sale.order:stock_reserve_sale.view_order_form_reserve
+msgid "Release Reservation"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,location_dest_id:0
+msgid "Reservation Location"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+msgid "Reserve"
+msgstr "Réserver"
+
+#. module: stock_reserve_sale
+#: view:sale.order:stock_reserve_sale.view_order_form_reserve
+#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+msgid "Reserve Stock"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model:ir.actions.act_window,name:stock_reserve_sale.action_sale_stock_reserve
+msgid "Reserve Stock for Quotation Lines"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: field:stock.reservation,sale_line_id:0
+msgid "Sale Order Line"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: view:stock.reservation:stock_reserve_sale.view_stock_reservation_form
+msgid "Sales"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model:ir.model,name:stock_reserve_sale.model_sale_order
+msgid "Sales Order"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model:ir.model,name:stock_reserve_sale.model_sale_order_line
+msgid "Sales Order Line"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: code:addons/stock_reserve_sale/model/sale.py:223
+#, python-format
+msgid ""
+"Several stock reservations are linked with the line. Impossible to adjust "
+"their quantity. Please release the reservation before changing the quantity."
+msgstr ""
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,location_id:0
+msgid "Source Location"
+msgstr "Emplacement Source"
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,owner_id:0
+msgid "Stock Owner"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model:ir.model,name:stock_reserve_sale.model_stock_reservation
+#: field:sale.order.line,reservation_ids:0
+msgid "Stock Reservation"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: field:sale.stock.reserve,date_validity:0
+msgid "Validity Date"
+msgstr "Date de validité"
+
+#. module: stock_reserve_sale
+#: code:addons/stock_reserve_sale/model/sale.py:211
+#, python-format
+msgid ""
+"You cannot change the product or unit of measure of lines with a stock "
+"reservation. Release the reservation before changing the product."
+msgstr "Vous ne pouvez pas modifier le produit ou l'unité de mesure des lignes avec une réservation en stock. Veuillez annuler les réservations avant de modifier la ligne."
+
+#. module: stock_reserve_sale
+#: view:sale.order:stock_reserve_sale.view_order_form_reserve
+msgid "cancel all"
+msgstr "tout annuler"
+
+#. module: stock_reserve_sale
+#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+msgid "or"
+msgstr "ou"
+
+#. module: stock_reserve_sale
+#: view:sale.order:stock_reserve_sale.view_order_form_reserve
+msgid "{\"reload_on_button\": 1}"
+msgstr ""
From ec895a3ddaa4921be694adc45834fb9cdb838df2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Bidoul?=
Date: Fri, 9 Oct 2015 10:03:18 +0200
Subject: [PATCH 13/26] [UPD] prefix versions with 8.0
---
stock_reserve_sale/__openerp__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/stock_reserve_sale/__openerp__.py b/stock_reserve_sale/__openerp__.py
index 119e00bb1337..0a4196200789 100644
--- a/stock_reserve_sale/__openerp__.py
+++ b/stock_reserve_sale/__openerp__.py
@@ -20,7 +20,7 @@
##############################################################################
{'name': 'Stock Reserve Sales',
- 'version': '1.0',
+ 'version': '8.0.1.0.0',
'author': "Camptocamp,Odoo Community Association (OCA)",
'category': 'Warehouse',
'license': 'AGPL-3',
From 7c16b12e63d19ba26549584f09e5f4ca90f3f7e5 Mon Sep 17 00:00:00 2001
From: "Pedro M. Baeza"
Date: Wed, 14 Oct 2015 02:54:54 +0200
Subject: [PATCH 14/26] [MIG] Make modules uninstallable
---
stock_reserve_sale/__openerp__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/stock_reserve_sale/__openerp__.py b/stock_reserve_sale/__openerp__.py
index 0a4196200789..c919e6ac9a96 100644
--- a/stock_reserve_sale/__openerp__.py
+++ b/stock_reserve_sale/__openerp__.py
@@ -38,6 +38,6 @@
'test': ['test/sale_reserve.yml',
'test/sale_line_reserve.yml',
],
- 'installable': True,
+ 'installable': False,
'auto_install': False,
}
From 53dd4ce650414f2866f5b2c5e1cd24a882d5d0c1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Bidoul=20=28ACSONE=29?=
Date: Mon, 15 Aug 2016 22:15:34 +0200
Subject: [PATCH 15/26] [FIX] remove en.po that was erroneously created by
transbot
---
stock_reserve_sale/i18n/en.po | 208 ----------------------------------
1 file changed, 208 deletions(-)
delete mode 100644 stock_reserve_sale/i18n/en.po
diff --git a/stock_reserve_sale/i18n/en.po b/stock_reserve_sale/i18n/en.po
deleted file mode 100644
index f8d6cee68767..000000000000
--- a/stock_reserve_sale/i18n/en.po
+++ /dev/null
@@ -1,208 +0,0 @@
-# Translation of Odoo Server.
-# This file contains the translation of the following modules:
-# * stock_reserve_sale
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: stock-logistics-warehouse (8.0)\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-09-23 20:23+0000\n"
-"PO-Revision-Date: 2015-09-15 13:05+0000\n"
-"Last-Translator: OCA Transbot \n"
-"Language-Team: English (http://www.transifex.com/oca/OCA-stock-logistics-warehouse-8-0/language/en/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: \n"
-"Language: en\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#. module: stock_reserve_sale
-#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
-msgid ""
-"A stock reservation will be created for the products\n"
-" of the selected quotation lines. If a validity date is specified,\n"
-" the reservation will be released once the date has passed."
-msgstr "A stock reservation will be created for the products\n of the selected quotation lines. If a validity date is specified,\n the reservation will be released once the date has passed."
-
-#. module: stock_reserve_sale
-#: code:addons/stock_reserve_sale/model/sale.py:179
-#, python-format
-msgid ""
-"As you changed the quantity of the line, the quantity of the stock "
-"reservation will be automatically adjusted to %.2f."
-msgstr "As you changed the quantity of the line, the quantity of the stock reservation will be automatically adjusted to %.2f."
-
-#. module: stock_reserve_sale
-#: field:sale.order,is_stock_reservable:0
-msgid "Can Have Stock Reservations"
-msgstr "Can Have Stock Reservations"
-
-#. module: stock_reserve_sale
-#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
-msgid "Cancel"
-msgstr "Cancel"
-
-#. module: stock_reserve_sale
-#: code:addons/stock_reserve_sale/model/sale.py:188
-#, python-format
-msgid "Configuration Error!"
-msgstr "Configuration Error!"
-
-#. module: stock_reserve_sale
-#: field:sale.stock.reserve,create_uid:0
-msgid "Created by"
-msgstr "Created by"
-
-#. module: stock_reserve_sale
-#: field:sale.stock.reserve,create_date:0
-msgid "Created on"
-msgstr "Created on"
-
-#. module: stock_reserve_sale
-#: code:addons/stock_reserve_sale/model/sale.py:210
-#: code:addons/stock_reserve_sale/model/sale.py:222
-#, python-format
-msgid "Error"
-msgstr "Error"
-
-#. module: stock_reserve_sale
-#: field:sale.order,has_stock_reservation:0
-msgid "Has Stock Reservations"
-msgstr "Has Stock Reservations"
-
-#. module: stock_reserve_sale
-#: field:sale.stock.reserve,id:0
-msgid "ID"
-msgstr "ID"
-
-#. module: stock_reserve_sale
-#: help:sale.stock.reserve,date_validity:0
-msgid ""
-"If a date is given, the reservations will be released at the end of the "
-"validity."
-msgstr "If a date is given, the reservations will be released at the end of the validity."
-
-#. module: stock_reserve_sale
-#: field:sale.stock.reserve,write_uid:0
-msgid "Last Updated by"
-msgstr "Last Updated by"
-
-#. module: stock_reserve_sale
-#: field:sale.stock.reserve,write_date:0
-msgid "Last Updated on"
-msgstr "Last Updated on"
-
-#. module: stock_reserve_sale
-#: help:sale.stock.reserve,location_dest_id:0
-msgid "Location where the system will reserve the products."
-msgstr "Location where the system will reserve the products."
-
-#. module: stock_reserve_sale
-#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
-#: field:sale.stock.reserve,note:0
-msgid "Notes"
-msgstr "Notes"
-
-#. module: stock_reserve_sale
-#: view:sale.order:stock_reserve_sale.view_order_form_reserve
-msgid "Pre-book products from stock"
-msgstr "Pre-book products from stock"
-
-#. module: stock_reserve_sale
-#: view:sale.order:stock_reserve_sale.view_order_form_reserve
-msgid "Release Reservation"
-msgstr "Release Reservation"
-
-#. module: stock_reserve_sale
-#: field:sale.stock.reserve,location_dest_id:0
-msgid "Reservation Location"
-msgstr "Reservation Location"
-
-#. module: stock_reserve_sale
-#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
-msgid "Reserve"
-msgstr "Reserve"
-
-#. module: stock_reserve_sale
-#: view:sale.order:stock_reserve_sale.view_order_form_reserve
-#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
-msgid "Reserve Stock"
-msgstr "Reserve Stock"
-
-#. module: stock_reserve_sale
-#: model:ir.actions.act_window,name:stock_reserve_sale.action_sale_stock_reserve
-msgid "Reserve Stock for Quotation Lines"
-msgstr "Reserve Stock for Quotation Lines"
-
-#. module: stock_reserve_sale
-#: field:stock.reservation,sale_line_id:0
-msgid "Sale Order Line"
-msgstr "Sale Order Line"
-
-#. module: stock_reserve_sale
-#: view:stock.reservation:stock_reserve_sale.view_stock_reservation_form
-msgid "Sales"
-msgstr "Sales"
-
-#. module: stock_reserve_sale
-#: model:ir.model,name:stock_reserve_sale.model_sale_order
-msgid "Sales Order"
-msgstr "Sales Order"
-
-#. module: stock_reserve_sale
-#: model:ir.model,name:stock_reserve_sale.model_sale_order_line
-msgid "Sales Order Line"
-msgstr "Sales Order Line"
-
-#. module: stock_reserve_sale
-#: code:addons/stock_reserve_sale/model/sale.py:223
-#, python-format
-msgid ""
-"Several stock reservations are linked with the line. Impossible to adjust "
-"their quantity. Please release the reservation before changing the quantity."
-msgstr "Several stock reservations are linked with the line. Impossible to adjust their quantity. Please release the reservation before changing the quantity."
-
-#. module: stock_reserve_sale
-#: field:sale.stock.reserve,location_id:0
-msgid "Source Location"
-msgstr "Source Location"
-
-#. module: stock_reserve_sale
-#: field:sale.stock.reserve,owner_id:0
-msgid "Stock Owner"
-msgstr "Stock Owner"
-
-#. module: stock_reserve_sale
-#: model:ir.model,name:stock_reserve_sale.model_stock_reservation
-#: field:sale.order.line,reservation_ids:0
-msgid "Stock Reservation"
-msgstr "Stock Reservation"
-
-#. module: stock_reserve_sale
-#: field:sale.stock.reserve,date_validity:0
-msgid "Validity Date"
-msgstr "Validity Date"
-
-#. module: stock_reserve_sale
-#: code:addons/stock_reserve_sale/model/sale.py:211
-#, python-format
-msgid ""
-"You cannot change the product or unit of measure of lines with a stock "
-"reservation. Release the reservation before changing the product."
-msgstr "You cannot change the product or unit of measure of lines with a stock reservation. Release the reservation before changing the product."
-
-#. module: stock_reserve_sale
-#: view:sale.order:stock_reserve_sale.view_order_form_reserve
-msgid "cancel all"
-msgstr "cancel all"
-
-#. module: stock_reserve_sale
-#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
-msgid "or"
-msgstr "or"
-
-#. module: stock_reserve_sale
-#: view:sale.order:stock_reserve_sale.view_order_form_reserve
-msgid "{\"reload_on_button\": 1}"
-msgstr "{\"reload_on_button\": 1}"
From 8b2255e7dd10e41bb01e31ed9bdd735aafd01231 Mon Sep 17 00:00:00 2001
From: "Pedro M. Baeza"
Date: Thu, 6 Oct 2016 16:09:41 +0200
Subject: [PATCH 16/26] [MIG] Rename manifest files
---
stock_reserve_sale/{__openerp__.py => __manifest__.py} | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename stock_reserve_sale/{__openerp__.py => __manifest__.py} (100%)
diff --git a/stock_reserve_sale/__openerp__.py b/stock_reserve_sale/__manifest__.py
similarity index 100%
rename from stock_reserve_sale/__openerp__.py
rename to stock_reserve_sale/__manifest__.py
From d0d2841ffcd7ee982dac7842ebf59b5f1b4d6a4c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Bidoul=20=28ACSONE=29?=
Date: Fri, 15 Jun 2018 23:45:38 +0200
Subject: [PATCH 17/26] remove obsolete .pot files [ci skip]
---
.../i18n/stock_reserve_sale.pot | 188 ------------------
1 file changed, 188 deletions(-)
delete mode 100644 stock_reserve_sale/i18n/stock_reserve_sale.pot
diff --git a/stock_reserve_sale/i18n/stock_reserve_sale.pot b/stock_reserve_sale/i18n/stock_reserve_sale.pot
deleted file mode 100644
index edbb02c40238..000000000000
--- a/stock_reserve_sale/i18n/stock_reserve_sale.pot
+++ /dev/null
@@ -1,188 +0,0 @@
-# Translation of Odoo Server.
-# This file contains the translation of the following modules:
-# * stock_reserve_sale
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: Odoo Server 8.0\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-04-23 15:55+0000\n"
-"PO-Revision-Date: 2015-04-23 15:55+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_reserve_sale
-#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
-msgid "A stock reservation will be created for the products\n"
-" of the selected quotation lines. If a validity date is specified,\n"
-" the reservation will be released once the date has passed."
-msgstr ""
-
-#. module: stock_reserve_sale
-#: code:addons/stock_reserve_sale/model/sale.py:179
-#, python-format
-msgid "As you changed the quantity of the line, the quantity of the stock reservation will be automatically adjusted to %.2f."
-msgstr ""
-
-#. module: stock_reserve_sale
-#: field:sale.order,is_stock_reservable:0
-msgid "Can Have Stock Reservations"
-msgstr ""
-
-#. module: stock_reserve_sale
-#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
-msgid "Cancel"
-msgstr ""
-
-#. module: stock_reserve_sale
-#: code:addons/stock_reserve_sale/model/sale.py:188
-#, python-format
-msgid "Configuration Error!"
-msgstr ""
-
-#. module: stock_reserve_sale
-#: field:sale.stock.reserve,create_uid:0
-msgid "Created by"
-msgstr ""
-
-#. module: stock_reserve_sale
-#: field:sale.stock.reserve,create_date:0
-msgid "Created on"
-msgstr ""
-
-#. module: stock_reserve_sale
-#: code:addons/stock_reserve_sale/model/sale.py:210
-#: code:addons/stock_reserve_sale/model/sale.py:222
-#, python-format
-msgid "Error"
-msgstr ""
-
-#. module: stock_reserve_sale
-#: field:sale.order,has_stock_reservation:0
-msgid "Has Stock Reservations"
-msgstr ""
-
-#. module: stock_reserve_sale
-#: field:sale.stock.reserve,id:0
-msgid "ID"
-msgstr ""
-
-#. module: stock_reserve_sale
-#: help:sale.stock.reserve,date_validity:0
-msgid "If a date is given, the reservations will be released at the end of the validity."
-msgstr ""
-
-#. module: stock_reserve_sale
-#: field:sale.stock.reserve,write_uid:0
-msgid "Last Updated by"
-msgstr ""
-
-#. module: stock_reserve_sale
-#: field:sale.stock.reserve,write_date:0
-msgid "Last Updated on"
-msgstr ""
-
-#. module: stock_reserve_sale
-#: help:sale.stock.reserve,location_dest_id:0
-msgid "Location where the system will reserve the products."
-msgstr ""
-
-#. module: stock_reserve_sale
-#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
-#: field:sale.stock.reserve,note:0
-msgid "Notes"
-msgstr ""
-
-#. module: stock_reserve_sale
-#: view:sale.order:stock_reserve_sale.view_order_form_reserve
-msgid "Pre-book products from stock"
-msgstr ""
-
-#. module: stock_reserve_sale
-#: view:sale.order:stock_reserve_sale.view_order_form_reserve
-msgid "Release Reservation"
-msgstr ""
-
-#. module: stock_reserve_sale
-#: field:sale.stock.reserve,location_dest_id:0
-msgid "Reservation Location"
-msgstr ""
-
-#. module: stock_reserve_sale
-#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
-msgid "Reserve"
-msgstr ""
-
-#. module: stock_reserve_sale
-#: view:sale.order:stock_reserve_sale.view_order_form_reserve
-#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
-msgid "Reserve Stock"
-msgstr ""
-
-#. module: stock_reserve_sale
-#: model:ir.actions.act_window,name:stock_reserve_sale.action_sale_stock_reserve
-msgid "Reserve Stock for Quotation Lines"
-msgstr ""
-
-#. module: stock_reserve_sale
-#: field:stock.reservation,sale_line_id:0
-msgid "Sale Order Line"
-msgstr ""
-
-#. module: stock_reserve_sale
-#: view:stock.reservation:stock_reserve_sale.view_stock_reservation_form
-msgid "Sales"
-msgstr ""
-
-#. module: stock_reserve_sale
-#: model:ir.model,name:stock_reserve_sale.model_sale_order
-msgid "Sales Order"
-msgstr ""
-
-#. module: stock_reserve_sale
-#: model:ir.model,name:stock_reserve_sale.model_sale_order_line
-msgid "Sales Order Line"
-msgstr ""
-
-#. module: stock_reserve_sale
-#: code:addons/stock_reserve_sale/model/sale.py:223
-#, python-format
-msgid "Several stock reservations are linked with the line. Impossible to adjust their quantity. Please release the reservation before changing the quantity."
-msgstr ""
-
-#. module: stock_reserve_sale
-#: field:sale.stock.reserve,location_id:0
-msgid "Source Location"
-msgstr ""
-
-#. module: stock_reserve_sale
-#: model:ir.model,name:stock_reserve_sale.model_stock_reservation
-#: field:sale.order.line,reservation_ids:0
-msgid "Stock Reservation"
-msgstr ""
-
-#. module: stock_reserve_sale
-#: field:sale.stock.reserve,date_validity:0
-msgid "Validity Date"
-msgstr ""
-
-#. module: stock_reserve_sale
-#: code:addons/stock_reserve_sale/model/sale.py:211
-#, python-format
-msgid "You cannot change the product or unit of measure of lines with a stock reservation. Release the reservation before changing the product."
-msgstr ""
-
-#. module: stock_reserve_sale
-#: view:sale.order:stock_reserve_sale.view_order_form_reserve
-msgid "cancel all"
-msgstr ""
-
-#. module: stock_reserve_sale
-#: view:sale.order:stock_reserve_sale.view_order_form_reserve
-msgid "{\"reload_on_button\": 1}"
-msgstr ""
-
From 5de10debe913020108813b74ba2126a3682a0dd4 Mon Sep 17 00:00:00 2001
From: Carlos Roca
Date: Mon, 26 Jul 2021 09:34:54 +0200
Subject: [PATCH 18/26] [IMP] stock_reserve_sale: black, isort, prettier
---
stock_reserve_sale/__init__.py | 1 -
stock_reserve_sale/__manifest__.py | 43 ++--
stock_reserve_sale/model/__init__.py | 1 -
stock_reserve_sale/model/sale.py | 218 ++++++++++--------
stock_reserve_sale/model/stock_reserve.py | 16 +-
stock_reserve_sale/test/sale_line_reserve.yml | 112 ++++-----
stock_reserve_sale/test/sale_reserve.yml | 51 ++--
stock_reserve_sale/view/sale.xml | 70 +++---
stock_reserve_sale/view/stock_reserve.xml | 14 +-
stock_reserve_sale/wizard/__init__.py | 1 -
.../wizard/sale_stock_reserve.py | 97 ++++----
.../wizard/sale_stock_reserve_view.xml | 22 +-
12 files changed, 319 insertions(+), 327 deletions(-)
diff --git a/stock_reserve_sale/__init__.py b/stock_reserve_sale/__init__.py
index f2bf938cb9a9..4341cc1b5068 100644
--- a/stock_reserve_sale/__init__.py
+++ b/stock_reserve_sale/__init__.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
##############################################################################
#
# Author: Guewen Baconnier
diff --git a/stock_reserve_sale/__manifest__.py b/stock_reserve_sale/__manifest__.py
index c919e6ac9a96..3eab77e6182f 100644
--- a/stock_reserve_sale/__manifest__.py
+++ b/stock_reserve_sale/__manifest__.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
##############################################################################
#
# Author: Guewen Baconnier, Leonardo Pistone
@@ -19,25 +18,23 @@
#
##############################################################################
-{'name': 'Stock Reserve Sales',
- 'version': '8.0.1.0.0',
- 'author': "Camptocamp,Odoo Community Association (OCA)",
- 'category': 'Warehouse',
- 'license': 'AGPL-3',
- 'complexity': 'normal',
- 'images': [],
- 'website': "http://www.camptocamp.com",
- 'depends': ['sale_stock',
- 'stock_reserve',
- ],
- 'demo': [],
- 'data': ['wizard/sale_stock_reserve_view.xml',
- 'view/sale.xml',
- 'view/stock_reserve.xml',
- ],
- 'test': ['test/sale_reserve.yml',
- 'test/sale_line_reserve.yml',
- ],
- 'installable': False,
- 'auto_install': False,
- }
+{
+ "name": "Stock Reserve Sales",
+ "version": "8.0.1.0.0",
+ "author": "Camptocamp,Odoo Community Association (OCA)",
+ "category": "Warehouse",
+ "license": "AGPL-3",
+ "complexity": "normal",
+ "images": [],
+ "website": "http://www.camptocamp.com",
+ "depends": ["sale_stock", "stock_reserve",],
+ "demo": [],
+ "data": [
+ "wizard/sale_stock_reserve_view.xml",
+ "view/sale.xml",
+ "view/stock_reserve.xml",
+ ],
+ "test": ["test/sale_reserve.yml", "test/sale_line_reserve.yml",],
+ "installable": False,
+ "auto_install": False,
+}
diff --git a/stock_reserve_sale/model/__init__.py b/stock_reserve_sale/model/__init__.py
index 5c9fc50677a6..e36320781039 100644
--- a/stock_reserve_sale/model/__init__.py
+++ b/stock_reserve_sale/model/__init__.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
##############################################################################
#
# Author: Guewen Baconnier
diff --git a/stock_reserve_sale/model/sale.py b/stock_reserve_sale/model/sale.py
index 5723f473f5dc..809bb962097b 100644
--- a/stock_reserve_sale/model/sale.py
+++ b/stock_reserve_sale/model/sale.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
##############################################################################
#
# Author: Guewen Baconnier
@@ -19,18 +18,18 @@
#
##############################################################################
-from openerp import models, fields, api
+from openerp import api, fields, models
from openerp.exceptions import except_orm
from openerp.tools.translate import _
class SaleOrder(models.Model):
- _inherit = 'sale.order'
+ _inherit = "sale.order"
@api.multi
- @api.depends('state',
- 'order_line.reservation_ids',
- 'order_line.is_stock_reservable')
+ @api.depends(
+ "state", "order_line.reservation_ids", "order_line.is_stock_reservable"
+ )
def _stock_reservation(self):
for sale in self:
has_stock_reservation = False
@@ -40,28 +39,30 @@ def _stock_reservation(self):
has_stock_reservation = True
if line.is_stock_reservable:
is_stock_reservable = True
- if sale.state not in ('draft', 'sent'):
+ if sale.state not in ("draft", "sent"):
is_stock_reservable = False
sale.is_stock_reservable = is_stock_reservable
sale.has_stock_reservation = has_stock_reservation
has_stock_reservation = fields.Boolean(
- compute='_stock_reservation',
+ compute="_stock_reservation",
readonly=True,
- multi='stock_reservation',
+ multi="stock_reservation",
store=True,
- string='Has Stock Reservations')
+ string="Has Stock Reservations",
+ )
is_stock_reservable = fields.Boolean(
- compute='_stock_reservation',
+ compute="_stock_reservation",
readonly=True,
- multi='stock_reservation',
+ multi="stock_reservation",
store=True,
- string='Can Have Stock Reservations')
+ string="Can Have Stock Reservations",
+ )
@api.multi
def release_all_stock_reservation(self):
line_ids = [line.id for order in self for line in order.order_line]
- lines = self.env['sale.order.line'].browse(line_ids)
+ lines = self.env["sale.order.line"].browse(line_ids)
lines.release_stock_reservation()
return True
@@ -77,7 +78,7 @@ def action_cancel(self):
class SaleOrderLine(models.Model):
- _inherit = 'sale.order.line'
+ _inherit = "sale.order.line"
@api.multi
def _get_line_rule(self):
@@ -85,24 +86,29 @@ def _get_line_rule(self):
Reproduce get suitable rule from procurement
to predict source location """
- ProcurementRule = self.env['procurement.rule']
+ ProcurementRule = self.env["procurement.rule"]
product = self.product_id
- product_route_ids = [x.id for x in product.route_ids +
- product.categ_id.total_route_ids]
- rules = ProcurementRule.search([('route_id', 'in', product_route_ids)],
- order='route_sequence, sequence',
- limit=1)
+ product_route_ids = [
+ x.id for x in product.route_ids + product.categ_id.total_route_ids
+ ]
+ rules = ProcurementRule.search(
+ [("route_id", "in", product_route_ids)],
+ order="route_sequence, sequence",
+ limit=1,
+ )
if not rules:
warehouse = self.order_id.warehouse_id
wh_routes = warehouse.route_ids
wh_route_ids = [route.id for route in wh_routes]
- domain = ['|', ('warehouse_id', '=', warehouse.id),
- ('warehouse_id', '=', False),
- ('route_id', 'in', wh_route_ids)]
+ domain = [
+ "|",
+ ("warehouse_id", "=", warehouse.id),
+ ("warehouse_id", "=", False),
+ ("route_id", "in", wh_route_ids),
+ ]
- rules = ProcurementRule.search(domain,
- order='route_sequence, sequence')
+ rules = ProcurementRule.search(domain, order="route_sequence, sequence")
if rules:
return rules[0]
@@ -117,88 +123,105 @@ def _get_procure_method(self):
return False
@api.multi
- @api.depends('state',
- 'product_id.route_ids',
- 'product_id.type')
+ @api.depends("state", "product_id.route_ids", "product_id.type")
def _is_stock_reservable(self):
for line in self:
reservable = False
- if (not (line.state != 'draft' or
- line._get_procure_method() == 'make_to_order' or
- not line.product_id or
- line.product_id.type == 'service') and
- not line.reservation_ids):
+ if (
+ not (
+ line.state != "draft"
+ or line._get_procure_method() == "make_to_order"
+ or not line.product_id
+ or line.product_id.type == "service"
+ )
+ and not line.reservation_ids
+ ):
reservable = True
line.is_stock_reservable = reservable
reservation_ids = fields.One2many(
- 'stock.reservation',
- 'sale_line_id',
- string='Stock Reservation',
- copy=False)
+ "stock.reservation", "sale_line_id", string="Stock Reservation", copy=False
+ )
is_stock_reservable = fields.Boolean(
- compute='_is_stock_reservable',
- readonly=True,
- string='Can be reserved')
+ compute="_is_stock_reservable", readonly=True, string="Can be reserved"
+ )
@api.multi
def release_stock_reservation(self):
- reserv_ids = [reserv.id for line in self
- for reserv in line.reservation_ids]
- reservations = self.env['stock.reservation'].browse(reserv_ids)
+ reserv_ids = [reserv.id for line in self for reserv in line.reservation_ids]
+ reservations = self.env["stock.reservation"].browse(reserv_ids)
reservations.release()
return True
- def product_id_change(self, cr, uid, ids,
- pricelist,
- product,
- qty=0,
- uom=False,
- qty_uos=0,
- uos=False,
- name='',
- partner_id=False,
- lang=False,
- update_tax=True,
- date_order=False,
- packaging=False,
- fiscal_position=False,
- flag=False,
- context=None):
+ def product_id_change(
+ self,
+ cr,
+ uid,
+ ids,
+ pricelist,
+ product,
+ qty=0,
+ uom=False,
+ qty_uos=0,
+ uos=False,
+ name="",
+ partner_id=False,
+ lang=False,
+ update_tax=True,
+ date_order=False,
+ packaging=False,
+ fiscal_position=False,
+ flag=False,
+ context=None,
+ ):
result = super(SaleOrderLine, self).product_id_change(
- cr, uid, ids, pricelist, product, qty=qty, uom=uom,
- qty_uos=qty_uos, uos=uos, name=name, partner_id=partner_id,
- lang=lang, update_tax=update_tax, date_order=date_order,
- packaging=packaging, fiscal_position=fiscal_position,
- flag=flag, context=context)
+ cr,
+ uid,
+ ids,
+ pricelist,
+ product,
+ qty=qty,
+ uom=uom,
+ qty_uos=qty_uos,
+ uos=uos,
+ name=name,
+ partner_id=partner_id,
+ lang=lang,
+ update_tax=update_tax,
+ date_order=date_order,
+ packaging=packaging,
+ fiscal_position=fiscal_position,
+ flag=flag,
+ context=context,
+ )
if not ids: # warn only if we change an existing line
return result
assert len(ids) == 1, "Expected 1 ID, got %r" % ids
line = self.browse(cr, uid, ids[0], context=context)
if qty != line.product_uom_qty and line.reservation_ids:
- msg = _("As you changed the quantity of the line, "
+ msg = (
+ _(
+ "As you changed the quantity of the line, "
"the quantity of the stock reservation will "
- "be automatically adjusted to %.2f.") % qty
+ "be automatically adjusted to %.2f."
+ )
+ % qty
+ )
msg += "\n\n"
- result.setdefault('warning', {})
- if result['warning'].get('message'):
- result['warning']['message'] += msg
+ result.setdefault("warning", {})
+ if result["warning"].get("message"):
+ result["warning"]["message"] += msg
else:
- result['warning'] = {
- 'title': _('Configuration Error!'),
- 'message': msg,
+ result["warning"] = {
+ "title": _("Configuration Error!"),
+ "message": msg,
}
return result
@api.multi
def write(self, vals):
- block_on_reserve = ('product_id',
- 'product_uom',
- 'product_uos',
- 'type')
- update_on_reserve = ('price_unit',
- 'product_uom_qty',
- 'product_uos_qty')
+ block_on_reserve = ("product_id", "product_uom", "product_uos", "type")
+ update_on_reserve = ("price_unit", "product_uom_qty", "product_uos_qty")
keys = set(vals.keys())
test_block = keys.intersection(block_on_reserve)
test_update = keys.intersection(update_on_reserve)
@@ -207,11 +230,14 @@ def write(self, vals):
if not line.reservation_ids:
continue
raise except_orm(
- _('Error'),
- _('You cannot change the product or unit of measure '
- 'of lines with a stock reservation. '
- 'Release the reservation '
- 'before changing the product.'))
+ _("Error"),
+ _(
+ "You cannot change the product or unit of measure "
+ "of lines with a stock reservation. "
+ "Release the reservation "
+ "before changing the product."
+ ),
+ )
res = super(SaleOrderLine, self).write(vals)
if test_update:
for line in self:
@@ -219,16 +245,20 @@ def write(self, vals):
continue
if len(line.reservation_ids) > 1:
raise except_orm(
- _('Error'),
- _('Several stock reservations are linked with the '
- 'line. Impossible to adjust their quantity. '
- 'Please release the reservation '
- 'before changing the quantity.'))
+ _("Error"),
+ _(
+ "Several stock reservations are linked with the "
+ "line. Impossible to adjust their quantity. "
+ "Please release the reservation "
+ "before changing the quantity."
+ ),
+ )
line.reservation_ids.write(
- {'price_unit': line.price_unit,
- 'product_uom_qty': line.product_uom_qty,
- 'product_uos_qty': line.product_uos_qty,
- }
+ {
+ "price_unit": line.price_unit,
+ "product_uom_qty": line.product_uom_qty,
+ "product_uos_qty": line.product_uos_qty,
+ }
)
return res
diff --git a/stock_reserve_sale/model/stock_reserve.py b/stock_reserve_sale/model/stock_reserve.py
index db68449bbc3f..097ed67d280d 100644
--- a/stock_reserve_sale/model/stock_reserve.py
+++ b/stock_reserve_sale/model/stock_reserve.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
##############################################################################
#
# Author: Guewen Baconnier
@@ -19,21 +18,18 @@
#
##############################################################################
-from openerp import models, fields, api
+from openerp import api, fields, models
class StockReservation(models.Model):
- _inherit = 'stock.reservation'
+ _inherit = "stock.reservation"
sale_line_id = fields.Many2one(
- 'sale.order.line',
- string='Sale Order Line',
- ondelete='cascade',
- copy=False)
+ "sale.order.line", string="Sale Order Line", ondelete="cascade", copy=False
+ )
sale_id = fields.Many2one(
- 'sale.order',
- string='Sale Order',
- related='sale_line_id.order_id')
+ "sale.order", string="Sale Order", related="sale_line_id.order_id"
+ )
@api.multi
def release(self):
diff --git a/stock_reserve_sale/test/sale_line_reserve.yml b/stock_reserve_sale/test/sale_line_reserve.yml
index 0a798c3c244a..3f2552607cec 100644
--- a/stock_reserve_sale/test/sale_line_reserve.yml
+++ b/stock_reserve_sale/test/sale_line_reserve.yml
@@ -1,7 +1,5 @@
--
- I create a product to test the stock reservation
--
- !record {model: product.product, id: product_yogurt}:
+- I create a product to test the stock reservation
+- !record {model: product.product, id: product_yogurt}:
default_code: 001yogurt
name: yogurt
type: product
@@ -14,108 +12,90 @@
cost_method: average
property_stock_account_input: account.o_expense
property_stock_account_output: account.o_income
--
- I update the current stock of the yogurt with 10 kgm
--
- !record {model: stock.change.product.qty, id: change_qty}:
+- I update the current stock of the yogurt with 10 kgm
+- !record {model: stock.change.product.qty, id: change_qty}:
new_quantity: 10
product_id: product_yogurt
--
- !python {model: stock.change.product.qty}: |
+- !python {model: stock.change.product.qty}: |
context['active_id'] = ref('product_yogurt')
self.change_product_qty(cr, uid, [ref('change_qty')], context=context)
--
- In order to test reservation of the sales order, I create a sales order
--
- !record {model: sale.order, id: sale_reserve_02}:
+- In order to test reservation of the sales order, I create a sales order
+- !record {model: sale.order, id: sale_reserve_02}:
partner_id: base.res_partner_2
payment_term: account.account_payment_term
--
- And I create a sales order line
--
- !record {model: sale.order.line, id: sale_line_reserve_02_01, view: sale.view_order_line_tree}:
- name: Yogurt
+- And I create a sales order line
+- ? !record {
+ model: sale.order.line,
+ id: sale_line_reserve_02_01,
+ view: sale.view_order_line_tree,
+ }
+ : name: Yogurt
product_id: product_yogurt
product_uom_qty: 4
product_uom: product.product_uom_kgm
order_id: sale_reserve_02
--
- And I create a stock reserve for this line
--
- !python {model: sale.stock.reserve}: |
+- And I create a stock reserve for this line
+- !python {model: sale.stock.reserve}: |
active_id = ref('sale_line_reserve_02_01')
context['active_id'] = active_id
context['active_ids'] = [active_id]
context['active_model'] = 'sale.order.line'
wizard_id = self.create(cr, uid, {}, context=context)
self.button_reserve(cr, uid, [wizard_id], context=context)
--
- I check Virtual stock of yogurt after update reservation
--
- !python {model: product.product}: |
+- I check Virtual stock of yogurt after update reservation
+- !python {model: product.product}: |
product = self.browse(cr, uid, ref('product_yogurt'), context=context)
assert product.virtual_available == 6, "Stock is not updated."
--
- I set product_12 to MTO (doesn't work)
--
- !record {model: product.product, id: product.product_product_12}:
+- I set product_12 to MTO (doesn't work)
+- !record {model: product.product, id: product.product_product_12}:
route_ids:
- stock.route_warehouse0_mto
--
- I set MTO for real
--
- !python {model: product.product}: |
+- I set MTO for real
+- !python {model: product.product}: |
product = self.browse(cr, uid, ref('product.product_product_12'), context=context)
self.write(cr, uid, ref('product.product_product_12'),
{'route_ids': [(6, False, [ref('stock.route_warehouse0_mto')])]}, context=context)
--
- And I create a MTO sales order line
--
- !record {model: sale.order.line, id: sale_line_reserve_02_02, view: sale.view_order_line_tree}:
- order_id: sale_reserve_02
+- And I create a MTO sales order line
+- ? !record {
+ model: sale.order.line,
+ id: sale_line_reserve_02_02,
+ view: sale.view_order_line_tree,
+ }
+ : order_id: sale_reserve_02
name: Mouse, Wireless
product_id: product.product_product_12
product_uom_qty: 4
product_uom: product.product_uom_unit
--
- And I try to create a stock reserve for this MTO line
--
- !python {model: sale.stock.reserve}: |
+- And I try to create a stock reserve for this MTO line
+- !python {model: sale.stock.reserve}: |
active_id = ref('sale_line_reserve_02_02')
context['active_id'] = active_id
context['active_ids'] = [active_id]
context['active_model'] = 'sale.order.line'
wizard_id = self.create(cr, uid, {}, context=context)
self.button_reserve(cr, uid, [wizard_id], context=context)
--
- I should not have a stock reservation for a MTO line
--
- !python {model: stock.reservation}: |
+- I should not have a stock reservation for a MTO line
+- !python {model: stock.reservation}: |
reserv_ids = self.search(
cr, uid,
[('sale_line_id', '=', ref('sale_line_reserve_02_02'))],
context=context)
assert not reserv_ids, "No stock reservation should be created for MTO lines"
--
- And I change the quantity in the first line
--
- !record {model: sale.order.line, id: sale_line_reserve_02_01, view: sale.view_order_line_tree}:
- product_uom_qty: 5
--
-
- I check Virtual stock of yogurt after change of reservations
--
- !python {model: product.product}: |
+- And I change the quantity in the first line
+- ? !record {
+ model: sale.order.line,
+ id: sale_line_reserve_02_01,
+ view: sale.view_order_line_tree,
+ }
+ : product_uom_qty: 5
+- I check Virtual stock of yogurt after change of reservations
+- !python {model: product.product}: |
product = self.browse(cr, uid, ref('product_yogurt'), context=context)
assert product.virtual_available == 5, "Stock is not updated."
--
- I release the sales order's reservations for the first line
--
- !python {model: sale.order.line}: |
+- I release the sales order's reservations for the first line
+- !python {model: sale.order.line}: |
self.release_stock_reservation(cr, uid, [ref('sale_line_reserve_02_01')], context=context)
--
- I check Virtual stock of yogurt after release of reservations
--
- !python {model: product.product}: |
+- I check Virtual stock of yogurt after release of reservations
+- !python {model: product.product}: |
product = self.browse(cr, uid, ref('product_yogurt'), context=context)
assert product.virtual_available == 10, "Stock is not updated."
diff --git a/stock_reserve_sale/test/sale_reserve.yml b/stock_reserve_sale/test/sale_reserve.yml
index a3a81a472ac0..a02603b491d0 100644
--- a/stock_reserve_sale/test/sale_reserve.yml
+++ b/stock_reserve_sale/test/sale_reserve.yml
@@ -1,16 +1,12 @@
--
- I force recomputation of stock.location parent left/right
--
- !python {model: stock.location}:
+- I force recomputation of stock.location parent left/right
+- !python {model: stock.location}:
# we need this because when running the tests at install time as is done on
# Travis, the hook performing this operation for the new stock reservation
# location is run after the test execution. This causes the stock level
# computation to be wrong at the time the tests are run.
self._parent_store_compute(cr)
--
- I create a product to test the stock reservation
--
- !record {model: product.product, id: product_gelato}:
+- I create a product to test the stock reservation
+- !record {model: product.product, id: product_gelato}:
default_code: 001GELATO
name: Gelato
type: product
@@ -23,20 +19,15 @@
cost_method: average
property_stock_account_input: account.o_expense
property_stock_account_output: account.o_income
--
- I update the current stock of the Gelato with 10 kgm
--
- !record {model: stock.change.product.qty, id: change_qty}:
+- I update the current stock of the Gelato with 10 kgm
+- !record {model: stock.change.product.qty, id: change_qty}:
new_quantity: 10
product_id: product_gelato
--
- !python {model: stock.change.product.qty}: |
+- !python {model: stock.change.product.qty}: |
context['active_id'] = ref('product_gelato')
self.change_product_qty(cr, uid, [ref('change_qty')], context=context)
--
- In order to test reservation of the sales order, I create a sales order
--
- !record {model: sale.order, id: sale_reserve_01}:
+- In order to test reservation of the sales order, I create a sales order
+- !record {model: sale.order, id: sale_reserve_01}:
partner_id: base.res_partner_2
payment_term: account.account_payment_term
order_line:
@@ -44,30 +35,22 @@
product_uom_qty: 4
- product_id: product_gelato
product_uom_qty: 1
--
- I call the wizard to reserve the products of the sales order
--
- !python {model: sale.stock.reserve}: |
+- I call the wizard to reserve the products of the sales order
+- !python {model: sale.stock.reserve}: |
active_id = ref('sale_reserve_01')
context['active_id'] = active_id
context['active_ids'] = [active_id]
context['active_model'] = 'sale.order'
wizard_id = self.create(cr, uid, {}, context=context)
self.button_reserve(cr, uid, [wizard_id], context=context)
--
- I check Virtual stock of Gelato after update reservation
--
- !python {model: product.product}: |
+- I check Virtual stock of Gelato after update reservation
+- !python {model: product.product}: |
product = self.browse(cr, uid, ref('product_gelato'), context=context)
assert product.virtual_available == 5, "Stock is not updated after reservation."
--
- I release the sales order's reservations
--
- !python {model: sale.order}: |
+- I release the sales order's reservations
+- !python {model: sale.order}: |
self.release_all_stock_reservation(cr, uid, [ref('sale_reserve_01')], context=context)
--
- I check Virtual stock of Gelato after release of reservations
--
- !python {model: product.product}: |
+- I check Virtual stock of Gelato after release of reservations
+- !python {model: product.product}: |
product = self.browse(cr, uid, ref('product_gelato'), context=context)
assert product.virtual_available == 10, "Stock is not updated after releasing reservations."
diff --git a/stock_reserve_sale/view/sale.xml b/stock_reserve_sale/view/sale.xml
index e5849b04c166..487344b056f4 100644
--- a/stock_reserve_sale/view/sale.xml
+++ b/stock_reserve_sale/view/sale.xml
@@ -1,67 +1,79 @@
-
+
-
sale.order.form.reservesale.order
-
+
-
-
+
+ />
-
{"reload_on_button": 1}
-
-
-
-
+
+
-
+
+ ('state', '!=', 'draft')]}"
+ />
-
-
-
-
-
+
+
+
-
+
+ attrs="{'invisible': [('reservation_ids', '=', [])]}"
+ />
-
-
+
-
diff --git a/stock_reserve_sale/view/stock_reserve.xml b/stock_reserve_sale/view/stock_reserve.xml
index 71e47cb95328..9c7935a2c37f 100644
--- a/stock_reserve_sale/view/stock_reserve.xml
+++ b/stock_reserve_sale/view/stock_reserve.xml
@@ -1,30 +1,28 @@
-
+
stock.reservation.formstock.reservation
-
+
-
-
+
+
-
stock.reservation.treestock.reservation
-
+
-
+
-
diff --git a/stock_reserve_sale/wizard/__init__.py b/stock_reserve_sale/wizard/__init__.py
index 6156962e3abb..519cb0f7ab08 100644
--- a/stock_reserve_sale/wizard/__init__.py
+++ b/stock_reserve_sale/wizard/__init__.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
##############################################################################
#
# Author: Guewen Baconnier
diff --git a/stock_reserve_sale/wizard/sale_stock_reserve.py b/stock_reserve_sale/wizard/sale_stock_reserve.py
index 67d9fb313a39..b5b8884cebf9 100644
--- a/stock_reserve_sale/wizard/sale_stock_reserve.py
+++ b/stock_reserve_sale/wizard/sale_stock_reserve.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
##############################################################################
#
# Author: Guewen Baconnier, Leonardo Pistone
@@ -19,95 +18,95 @@
#
##############################################################################
-from openerp import models, fields, api, exceptions
+from openerp import api, exceptions, fields, models
class SaleStockReserve(models.TransientModel):
- _name = 'sale.stock.reserve'
+ _name = "sale.stock.reserve"
@api.model
def _default_location_id(self):
- return self.env['stock.reservation']._default_location_id()
+ return self.env["stock.reservation"]._default_location_id()
@api.model
def _default_location_dest_id(self):
- return self.env['stock.reservation']._default_location_dest_id()
+ return self.env["stock.reservation"]._default_location_dest_id()
def _default_owner(self):
"""If sale_owner_stock_sourcing is installed, it adds an owner field
on sale order lines. Use it.
"""
- model = self.env[self.env.context['active_model']]
- if model._name == 'sale.order':
- lines = model.browse(self.env.context['active_id']).order_line
+ model = self.env[self.env.context["active_model"]]
+ if model._name == "sale.order":
+ lines = model.browse(self.env.context["active_id"]).order_line
else:
- lines = model.browse(self.env.context['active_ids'])
+ lines = model.browse(self.env.context["active_ids"])
try:
- owners = set([l.stock_owner_id for l in lines])
+ owners = {l.stock_owner_id for l in lines}
except AttributeError:
- return self.env['res.partner']
+ return self.env["res.partner"]
# module sale_owner_stock_sourcing not installed, fine
if len(owners) == 1:
return owners.pop()
elif len(owners) > 1:
raise exceptions.Warning(
- 'The lines have different owners. Please reserve them '
- 'individually with the reserve button on each one.')
+ "The lines have different owners. Please reserve them "
+ "individually with the reserve button on each one."
+ )
- return self.env['res.partner']
+ return self.env["res.partner"]
location_id = fields.Many2one(
- 'stock.location',
- 'Source Location',
- required=True,
- default=_default_location_id)
+ "stock.location", "Source Location", required=True, default=_default_location_id
+ )
location_dest_id = fields.Many2one(
- 'stock.location',
- 'Reservation Location',
+ "stock.location",
+ "Reservation Location",
required=True,
- help="Location where the system will reserve the "
- "products.",
- default=_default_location_dest_id)
+ help="Location where the system will reserve the " "products.",
+ default=_default_location_dest_id,
+ )
date_validity = fields.Date(
"Validity Date",
help="If a date is given, the reservations will be released "
- "at the end of the validity.")
- note = fields.Text('Notes')
- owner_id = fields.Many2one('res.partner', 'Stock Owner',
- default=_default_owner)
+ "at the end of the validity.",
+ )
+ note = fields.Text("Notes")
+ owner_id = fields.Many2one("res.partner", "Stock Owner", default=_default_owner)
@api.multi
def _prepare_stock_reservation(self, line):
self.ensure_one()
product_uos = line.product_uos.id if line.product_uos else False
- return {'product_id': line.product_id.id,
- 'product_uom': line.product_uom.id,
- 'product_uom_qty': line.product_uom_qty,
- 'date_validity': self.date_validity,
- 'name': "%s (%s)" % (line.order_id.name, line.name),
- 'location_id': self.location_id.id,
- 'location_dest_id': self.location_dest_id.id,
- 'note': self.note,
- 'product_uos_qty': line.product_uos_qty,
- 'product_uos': product_uos,
- 'price_unit': line.price_unit,
- 'sale_line_id': line.id,
- 'restrict_partner_id': self.owner_id.id,
- }
+ return {
+ "product_id": line.product_id.id,
+ "product_uom": line.product_uom.id,
+ "product_uom_qty": line.product_uom_qty,
+ "date_validity": self.date_validity,
+ "name": "{} ({})".format(line.order_id.name, line.name),
+ "location_id": self.location_id.id,
+ "location_dest_id": self.location_dest_id.id,
+ "note": self.note,
+ "product_uos_qty": line.product_uos_qty,
+ "product_uos": product_uos,
+ "price_unit": line.price_unit,
+ "sale_line_id": line.id,
+ "restrict_partner_id": self.owner_id.id,
+ }
@api.multi
def stock_reserve(self, line_ids):
self.ensure_one()
- lines = self.env['sale.order.line'].browse(line_ids)
+ lines = self.env["sale.order.line"].browse(line_ids)
for line in lines:
if not line.is_stock_reservable:
continue
vals = self._prepare_stock_reservation(line)
- reserv = self.env['stock.reservation'].create(vals)
+ reserv = self.env["stock.reservation"].create(vals)
reserv.reserve()
return True
@@ -115,17 +114,17 @@ def stock_reserve(self, line_ids):
def button_reserve(self):
env = self.env
self.ensure_one()
- close = {'type': 'ir.actions.act_window_close'}
- active_model = env.context.get('active_model')
- active_ids = env.context.get('active_ids')
+ close = {"type": "ir.actions.act_window_close"}
+ active_model = env.context.get("active_model")
+ active_ids = env.context.get("active_ids")
if not (active_model and active_ids):
return close
- if active_model == 'sale.order':
- sales = env['sale.order'].browse(active_ids)
+ if active_model == "sale.order":
+ sales = env["sale.order"].browse(active_ids)
line_ids = [line.id for sale in sales for line in sale.order_line]
- if active_model == 'sale.order.line':
+ if active_model == "sale.order.line":
line_ids = active_ids
self.stock_reserve(line_ids)
diff --git a/stock_reserve_sale/wizard/sale_stock_reserve_view.xml b/stock_reserve_sale/wizard/sale_stock_reserve_view.xml
index 69b3fb4ff98a..2ed28a91d020 100644
--- a/stock_reserve_sale/wizard/sale_stock_reserve_view.xml
+++ b/stock_reserve_sale/wizard/sale_stock_reserve_view.xml
@@ -1,7 +1,6 @@
-
+
-
sale.stock.reserve.formsale.stock.reserve
@@ -13,26 +12,27 @@
the reservation will be released once the date has passed.
-
-
-
-
+
+
+
+
-
+
-
Reserve Stock for Quotation Linesir.actions.act_window
From ab70510ad2f4f0dabe06184e4a021c7f1a117c32 Mon Sep 17 00:00:00 2001
From: Carlos Roca
Date: Tue, 27 Jul 2021 07:11:44 +0200
Subject: [PATCH 19/26] [MIG] stock_reserve_sale: Migration to v13.0
---
stock_reserve_sale/README.rst | 72 ++-
stock_reserve_sale/__init__.py | 22 +-
stock_reserve_sale/__manifest__.py | 35 +-
stock_reserve_sale/i18n/es.po | 177 ++++---
.../i18n/stock_reserve_sale.pot | 220 +++++++++
stock_reserve_sale/model/__init__.py | 22 +-
stock_reserve_sale/model/sale.py | 207 ++++----
stock_reserve_sale/model/stock_reserve.py | 29 +-
stock_reserve_sale/readme/CONTRIBUTORS.rst | 8 +
stock_reserve_sale/readme/DESCRIPTION.rst | 23 +
stock_reserve_sale/readme/USAGE.rst | 8 +
.../static/description/index.html | 456 ++++++++++++++++++
stock_reserve_sale/test/sale_line_reserve.yml | 101 ----
stock_reserve_sale/test/sale_reserve.yml | 56 ---
stock_reserve_sale/tests/__init__.py | 1 +
.../tests/test_stock_reserve_sale.py | 138 ++++++
stock_reserve_sale/view/sale.xml | 191 +++++---
stock_reserve_sale/view/stock_reserve.xml | 48 +-
stock_reserve_sale/wizard/__init__.py | 22 +-
.../wizard/sale_stock_reserve.py | 41 +-
.../wizard/sale_stock_reserve_view.xml | 85 ++--
21 files changed, 1321 insertions(+), 641 deletions(-)
create mode 100644 stock_reserve_sale/i18n/stock_reserve_sale.pot
create mode 100644 stock_reserve_sale/readme/CONTRIBUTORS.rst
create mode 100644 stock_reserve_sale/readme/DESCRIPTION.rst
create mode 100644 stock_reserve_sale/readme/USAGE.rst
create mode 100644 stock_reserve_sale/static/description/index.html
delete mode 100644 stock_reserve_sale/test/sale_line_reserve.yml
delete mode 100644 stock_reserve_sale/test/sale_reserve.yml
create mode 100644 stock_reserve_sale/tests/__init__.py
create mode 100644 stock_reserve_sale/tests/test_stock_reserve_sale.py
diff --git a/stock_reserve_sale/README.rst b/stock_reserve_sale/README.rst
index abcdfe86d896..b7ba372fb3d2 100644
--- a/stock_reserve_sale/README.rst
+++ b/stock_reserve_sale/README.rst
@@ -1,8 +1,29 @@
-.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
+===================
+Stock Reserve Sales
+===================
+
+.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ !! This file is generated by oca-gen-addon-readme !!
+ !! changes will be overwritten. !!
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
+ :target: https://odoo-community.org/page/development-status
+ :alt: Beta
+.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
+ :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
-
-Stock Reserve Sale
-==================
+.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstock--logistics--warehouse-lightgray.png?logo=github
+ :target: https://github.com/OCA/stock-logistics-warehouse/tree/13.0/stock_reserve_sale
+ :alt: OCA/stock-logistics-warehouse
+.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
+ :target: https://translation.odoo-community.org/projects/stock-logistics-warehouse-13-0/stock-logistics-warehouse-13-0-stock_reserve_sale
+ :alt: Translate me on Weblate
+.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
+ :target: https://runbot.odoo-community.org/runbot/153/13.0
+ :alt: Try me on Runbot
+
+|badge1| |badge2| |badge3| |badge4| |badge5|
Allows to create stock reservations for quotation lines before the
confirmation of the quotation. The reservations might have a validity
@@ -28,39 +49,66 @@ will get a message suggesting to reserve each line individually. There is no
module dependency: this modules is fully functional even without ownership
management.
+**Table of contents**
+
+.. contents::
+ :local:
+
+Usage
+=====
+
+#. Create a new Sale Order
+#. Add lines to the Order
+
+Now you can reserve all the lines by clicking on *Reserve Stock* or you can reserve each
+one by pressing on the lock icon at the lines.
+
+Once they where reserved, you can release the reserves by clicking at *Cancell all*
+button or by clicking the undo icon on the lines.
Bug Tracker
===========
Bugs are tracked on `GitHub Issues `_.
In case of trouble, please check there if your issue has already been reported.
-If you spotted it first, help us smashing it by providing a detailed and welcomed feedback
-`here `_.
+If you spotted it first, help us smashing it by providing a detailed and welcomed
+`feedback `_.
+Do not contact contributors directly about support or help with technical issues.
Credits
=======
+Authors
+~~~~~~~
+
+* Camptocamp
+
Contributors
-------------
+~~~~~~~~~~~~
* Leonardo Pistone
* Alexandre Fayolle
* Yannick Vaucher
* Guewen Baconnier
-Maintainer
-----------
+* `Tecnativa `_:
+
+ * Carlos Roca
+
+Maintainers
+~~~~~~~~~~~
+
+This module is maintained by the OCA.
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://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.
+This module is part of the `OCA/stock-logistics-warehouse `_ project on GitHub.
+You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/stock_reserve_sale/__init__.py b/stock_reserve_sale/__init__.py
index 4341cc1b5068..8bf1bb6194f8 100644
--- a/stock_reserve_sale/__init__.py
+++ b/stock_reserve_sale/__init__.py
@@ -1,22 +1,4 @@
-##############################################################################
-#
-# 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 .
-#
-##############################################################################
-
+# Copyright 2013 Camptocamp SA - Guewen Baconnier
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from . import model
from . import wizard
diff --git a/stock_reserve_sale/__manifest__.py b/stock_reserve_sale/__manifest__.py
index 3eab77e6182f..fa4cccfcf0ed 100644
--- a/stock_reserve_sale/__manifest__.py
+++ b/stock_reserve_sale/__manifest__.py
@@ -1,40 +1,19 @@
-##############################################################################
-#
-# Author: Guewen Baconnier, Leonardo Pistone
-# Copyright 2013-2015 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 .
-#
-##############################################################################
-
+# Copyright 2013 Camptocamp SA - Guewen Baconnier
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
{
"name": "Stock Reserve Sales",
- "version": "8.0.1.0.0",
- "author": "Camptocamp,Odoo Community Association (OCA)",
+ "version": "13.0.1.0.0",
+ "author": "Camptocamp, Odoo Community Association (OCA)",
"category": "Warehouse",
"license": "AGPL-3",
"complexity": "normal",
- "images": [],
- "website": "http://www.camptocamp.com",
- "depends": ["sale_stock", "stock_reserve",],
- "demo": [],
+ "website": "https://github.com/stock-logistics-warehouse",
+ "depends": ["sale_stock", "stock_reserve"],
"data": [
"wizard/sale_stock_reserve_view.xml",
"view/sale.xml",
"view/stock_reserve.xml",
],
- "test": ["test/sale_reserve.yml", "test/sale_line_reserve.yml",],
- "installable": False,
+ "installable": True,
"auto_install": False,
}
diff --git a/stock_reserve_sale/i18n/es.po b/stock_reserve_sale/i18n/es.po
index 30e87bbb5bd6..3f8c5aec1ac4 100644
--- a/stock_reserve_sale/i18n/es.po
+++ b/stock_reserve_sale/i18n/es.po
@@ -1,208 +1,237 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * stock_reserve_sale
-#
+#
# Translators:
msgid ""
msgstr ""
"Project-Id-Version: stock-logistics-warehouse (8.0)\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-09-23 20:23+0000\n"
-"PO-Revision-Date: 2015-09-15 13:05+0000\n"
-"Last-Translator: <>\n"
-"Language-Team: Spanish (http://www.transifex.com/oca/OCA-stock-logistics-warehouse-8-0/language/es/)\n"
+"POT-Creation-Date: 2021-07-27 07:47+0000\n"
+"PO-Revision-Date: 2021-07-27 09:58+0200\n"
+"Last-Translator: Carlos \n"
+"Language-Team: Spanish (http://www.transifex.com/oca/OCA-stock-logistics-"
+"warehouse-8-0/language/es/)\n"
+"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: \n"
-"Language: es\n"
+"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Poedit 2.0.6\n"
#. module: stock_reserve_sale
-#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_sale_stock_reserve_form
msgid ""
"A stock reservation will be created for the products\n"
-" of the selected quotation lines. If a validity date is specified,\n"
-" the reservation will be released once the date has passed."
+" of the selected quotation lines. If a validity date is "
+"specified,\n"
+" the reservation will be released once the date has "
+"passed."
msgstr ""
+"Una reserva de stock va a ser creada para los productos\n"
+" de la orden de venta seleccionada. Si una fecha de "
+"validez está\n"
+"\t\t especificada, la reserva va a ser liberada cuando la fecha pase."
#. module: stock_reserve_sale
-#: code:addons/stock_reserve_sale/model/sale.py:179
-#, python-format
-msgid ""
-"As you changed the quantity of the line, the quantity of the stock "
-"reservation will be automatically adjusted to %.2f."
-msgstr ""
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_order__is_stock_reservable
+msgid "Can Have Stock Reservations"
+msgstr "Puede tener reservas de stock"
#. module: stock_reserve_sale
-#: field:sale.order,is_stock_reservable:0
-msgid "Can Have Stock Reservations"
-msgstr ""
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_order_line__is_stock_reservable
+msgid "Can be reserved"
+msgstr "Puede ser reservado"
#. module: stock_reserve_sale
-#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_sale_stock_reserve_form
msgid "Cancel"
-msgstr ""
+msgstr "Cancelar"
#. module: stock_reserve_sale
-#: code:addons/stock_reserve_sale/model/sale.py:188
-#, python-format
-msgid "Configuration Error!"
-msgstr ""
+#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_order_form_reserve
+msgid "Cancell all"
+msgstr "Cancelar todo"
#. module: stock_reserve_sale
-#: field:sale.stock.reserve,create_uid:0
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__create_uid
msgid "Created by"
msgstr "Creado por"
#. module: stock_reserve_sale
-#: field:sale.stock.reserve,create_date:0
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__create_date
msgid "Created on"
msgstr "Creado el"
#. module: stock_reserve_sale
-#: code:addons/stock_reserve_sale/model/sale.py:210
-#: code:addons/stock_reserve_sale/model/sale.py:222
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__display_name
+msgid "Display Name"
+msgstr "Nombre mostrado"
+
+#. module: stock_reserve_sale
+#: code:addons/stock_reserve_sale/model/sale.py:0
#, python-format
msgid "Error"
-msgstr ""
+msgstr "Error"
#. module: stock_reserve_sale
-#: field:sale.order,has_stock_reservation:0
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_order__has_stock_reservation
msgid "Has Stock Reservations"
-msgstr ""
+msgstr "Tiene reservas de stock"
#. module: stock_reserve_sale
-#: field:sale.stock.reserve,id:0
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__id
msgid "ID"
msgstr "ID"
#. module: stock_reserve_sale
-#: help:sale.stock.reserve,date_validity:0
+#: model:ir.model.fields,help:stock_reserve_sale.field_sale_stock_reserve__date_validity
msgid ""
"If a date is given, the reservations will be released at the end of the "
"validity."
msgstr ""
+"Si la fecha de validez está asignada, la reserva va a ser liberada al final "
+"de esta."
#. module: stock_reserve_sale
-#: field:sale.stock.reserve,write_uid:0
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve____last_update
+msgid "Last Modified on"
+msgstr "Última modificación el"
+
+#. module: stock_reserve_sale
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__write_uid
msgid "Last Updated by"
msgstr "Actualizado por última vez por"
#. module: stock_reserve_sale
-#: field:sale.stock.reserve,write_date:0
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__write_date
msgid "Last Updated on"
msgstr "Actualizado por última vez el"
#. module: stock_reserve_sale
-#: help:sale.stock.reserve,location_dest_id:0
+#: model:ir.model.fields,help:stock_reserve_sale.field_sale_stock_reserve__location_dest_id
msgid "Location where the system will reserve the products."
-msgstr ""
+msgstr "Localización donde el sistema va a reservar los productos."
#. module: stock_reserve_sale
-#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
-#: field:sale.stock.reserve,note:0
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__note
+#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_sale_stock_reserve_form
msgid "Notes"
msgstr "Notas"
#. module: stock_reserve_sale
-#: view:sale.order:stock_reserve_sale.view_order_form_reserve
+#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_order_form_reserve
msgid "Pre-book products from stock"
-msgstr ""
+msgstr "Pre-reservar productos en stock"
#. module: stock_reserve_sale
-#: view:sale.order:stock_reserve_sale.view_order_form_reserve
+#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_order_form_reserve
msgid "Release Reservation"
-msgstr ""
+msgstr "Liberar"
#. module: stock_reserve_sale
-#: field:sale.stock.reserve,location_dest_id:0
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__location_dest_id
msgid "Reservation Location"
-msgstr ""
+msgstr "Localización de la reserva"
#. module: stock_reserve_sale
-#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_sale_stock_reserve_form
msgid "Reserve"
msgstr "Reservar"
#. module: stock_reserve_sale
-#: view:sale.order:stock_reserve_sale.view_order_form_reserve
-#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_order_form_reserve
+#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_sale_stock_reserve_form
msgid "Reserve Stock"
-msgstr ""
+msgstr "Reservar stock"
#. module: stock_reserve_sale
#: model:ir.actions.act_window,name:stock_reserve_sale.action_sale_stock_reserve
msgid "Reserve Stock for Quotation Lines"
-msgstr ""
+msgstr "Reservar stock para las lineas del pedido"
+
+#. module: stock_reserve_sale
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_stock_reservation__sale_id
+msgid "Sale Order"
+msgstr "Pedido de venta"
#. module: stock_reserve_sale
-#: field:stock.reservation,sale_line_id:0
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_stock_reservation__sale_line_id
msgid "Sale Order Line"
-msgstr ""
+msgstr "Linea de venta"
#. module: stock_reserve_sale
-#: view:stock.reservation:stock_reserve_sale.view_stock_reservation_form
+#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_stock_reservation_form
msgid "Sales"
-msgstr ""
+msgstr "Ventas"
#. module: stock_reserve_sale
#: model:ir.model,name:stock_reserve_sale.model_sale_order
msgid "Sales Order"
-msgstr ""
+msgstr "Pedido"
#. module: stock_reserve_sale
#: model:ir.model,name:stock_reserve_sale.model_sale_order_line
msgid "Sales Order Line"
-msgstr ""
+msgstr "Líneas de pedidos de venta"
#. module: stock_reserve_sale
-#: code:addons/stock_reserve_sale/model/sale.py:223
+#: code:addons/stock_reserve_sale/model/sale.py:0
#, python-format
msgid ""
"Several stock reservations are linked with the line. Impossible to adjust "
"their quantity. Please release the reservation before changing the quantity."
msgstr ""
+"Algunas reservas de stock están asociadas a la linea. Imposible ajustar la "
+"cantidad. Por favor, libera la reserva antes de cambiar la cantidad."
#. module: stock_reserve_sale
-#: field:sale.stock.reserve,location_id:0
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__location_id
msgid "Source Location"
-msgstr ""
+msgstr "Ubicación origen"
#. module: stock_reserve_sale
-#: field:sale.stock.reserve,owner_id:0
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__owner_id
msgid "Stock Owner"
-msgstr ""
+msgstr "Propietario"
#. module: stock_reserve_sale
#: model:ir.model,name:stock_reserve_sale.model_stock_reservation
-#: field:sale.order.line,reservation_ids:0
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_order_line__reservation_ids
msgid "Stock Reservation"
msgstr "Reserva de existencias"
#. module: stock_reserve_sale
-#: field:sale.stock.reserve,date_validity:0
+#: code:addons/stock_reserve_sale/wizard/sale_stock_reserve.py:0
+#, python-format
+msgid ""
+"The lines have different owners. Please reserve them\n"
+" individually with the reserve button on each one."
+msgstr ""
+"Las lineas tienen distintos propietarios. Por favor, reservalas\n"
+" individualmente con el botón de reserva de cada una."
+
+#. module: stock_reserve_sale
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__date_validity
msgid "Validity Date"
msgstr "Fecha de validez"
#. module: stock_reserve_sale
-#: code:addons/stock_reserve_sale/model/sale.py:211
+#: code:addons/stock_reserve_sale/model/sale.py:0
#, python-format
msgid ""
"You cannot change the product or unit of measure of lines with a stock "
"reservation. Release the reservation before changing the product."
msgstr ""
+"No puedes cambiar el producto o la unidad de medida de las lineas con una "
+"reserva de stock. Libera la reserva antes de cambiar el producto."
#. module: stock_reserve_sale
-#: view:sale.order:stock_reserve_sale.view_order_form_reserve
-msgid "cancel all"
-msgstr ""
-
-#. module: stock_reserve_sale
-#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
+#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_sale_stock_reserve_form
msgid "or"
-msgstr ""
+msgstr "o"
#. module: stock_reserve_sale
-#: view:sale.order:stock_reserve_sale.view_order_form_reserve
-msgid "{\"reload_on_button\": 1}"
+#: model:ir.model,name:stock_reserve_sale.model_sale_stock_reserve
+msgid "sale.stock.reserve"
msgstr ""
diff --git a/stock_reserve_sale/i18n/stock_reserve_sale.pot b/stock_reserve_sale/i18n/stock_reserve_sale.pot
new file mode 100644
index 000000000000..c6dcbb7b8935
--- /dev/null
+++ b/stock_reserve_sale/i18n/stock_reserve_sale.pot
@@ -0,0 +1,220 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * stock_reserve_sale
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 13.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2021-07-27 07:47+0000\n"
+"PO-Revision-Date: 2021-07-27 07:47+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_reserve_sale
+#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_sale_stock_reserve_form
+msgid ""
+"A stock reservation will be created for the products\n"
+" of the selected quotation lines. If a validity date is specified,\n"
+" the reservation will be released once the date has passed."
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_order__is_stock_reservable
+msgid "Can Have Stock Reservations"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_order_line__is_stock_reservable
+msgid "Can be reserved"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_sale_stock_reserve_form
+msgid "Cancel"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_order_form_reserve
+msgid "Cancell all"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__create_uid
+msgid "Created by"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__create_date
+msgid "Created on"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__display_name
+msgid "Display Name"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: code:addons/stock_reserve_sale/model/sale.py:0
+#: code:addons/stock_reserve_sale/model/sale.py:0
+#, python-format
+msgid "Error"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_order__has_stock_reservation
+msgid "Has Stock Reservations"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__id
+msgid "ID"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model:ir.model.fields,help:stock_reserve_sale.field_sale_stock_reserve__date_validity
+msgid ""
+"If a date is given, the reservations will be released at the end of the "
+"validity."
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve____last_update
+msgid "Last Modified on"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__write_uid
+msgid "Last Updated by"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__write_date
+msgid "Last Updated on"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model:ir.model.fields,help:stock_reserve_sale.field_sale_stock_reserve__location_dest_id
+msgid "Location where the system will reserve the products."
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__note
+#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_sale_stock_reserve_form
+msgid "Notes"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_order_form_reserve
+msgid "Pre-book products from stock"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_order_form_reserve
+msgid "Release Reservation"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__location_dest_id
+msgid "Reservation Location"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_sale_stock_reserve_form
+msgid "Reserve"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_order_form_reserve
+#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_sale_stock_reserve_form
+msgid "Reserve Stock"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model:ir.actions.act_window,name:stock_reserve_sale.action_sale_stock_reserve
+msgid "Reserve Stock for Quotation Lines"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_stock_reservation__sale_id
+msgid "Sale Order"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_stock_reservation__sale_line_id
+msgid "Sale Order Line"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_stock_reservation_form
+msgid "Sales"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model:ir.model,name:stock_reserve_sale.model_sale_order
+msgid "Sales Order"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model:ir.model,name:stock_reserve_sale.model_sale_order_line
+msgid "Sales Order Line"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: code:addons/stock_reserve_sale/model/sale.py:0
+#, python-format
+msgid ""
+"Several stock reservations are linked with the line. Impossible to adjust "
+"their quantity. Please release the reservation before changing the quantity."
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__location_id
+msgid "Source Location"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__owner_id
+msgid "Stock Owner"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model:ir.model,name:stock_reserve_sale.model_stock_reservation
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_order_line__reservation_ids
+msgid "Stock Reservation"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: code:addons/stock_reserve_sale/wizard/sale_stock_reserve.py:0
+#, python-format
+msgid ""
+"The lines have different owners. Please reserve them\n"
+" individually with the reserve button on each one."
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__date_validity
+msgid "Validity Date"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: code:addons/stock_reserve_sale/model/sale.py:0
+#, python-format
+msgid ""
+"You cannot change the product or unit of measure of lines with a stock "
+"reservation. Release the reservation before changing the product."
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_sale_stock_reserve_form
+msgid "or"
+msgstr ""
+
+#. module: stock_reserve_sale
+#: model:ir.model,name:stock_reserve_sale.model_sale_stock_reserve
+msgid "sale.stock.reserve"
+msgstr ""
diff --git a/stock_reserve_sale/model/__init__.py b/stock_reserve_sale/model/__init__.py
index e36320781039..7090ccfa3bb9 100644
--- a/stock_reserve_sale/model/__init__.py
+++ b/stock_reserve_sale/model/__init__.py
@@ -1,22 +1,4 @@
-##############################################################################
-#
-# 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 .
-#
-##############################################################################
-
+# Copyright 2013 Camptocamp SA - Guewen Baconnier
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from . import sale
from . import stock_reserve
diff --git a/stock_reserve_sale/model/sale.py b/stock_reserve_sale/model/sale.py
index 809bb962097b..f7b07fe2e750 100644
--- a/stock_reserve_sale/model/sale.py
+++ b/stock_reserve_sale/model/sale.py
@@ -1,36 +1,19 @@
-##############################################################################
-#
-# 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 .
-#
-##############################################################################
+# Copyright 2013 Camptocamp SA - Guewen Baconnier
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+from odoo import api, fields, models
+from odoo.exceptions import UserError, except_orm
+from odoo.tools.translate import _
-from openerp import api, fields, models
-from openerp.exceptions import except_orm
-from openerp.tools.translate import _
+_LINE_KEYS = ["product_id", "product_uom_qty"]
class SaleOrder(models.Model):
_inherit = "sale.order"
- @api.multi
@api.depends(
"state", "order_line.reservation_ids", "order_line.is_stock_reservable"
)
- def _stock_reservation(self):
+ def _compute_stock_reservation(self):
for sale in self:
has_stock_reservation = False
is_stock_reservable = False
@@ -45,53 +28,100 @@ def _stock_reservation(self):
sale.has_stock_reservation = has_stock_reservation
has_stock_reservation = fields.Boolean(
- compute="_stock_reservation",
+ compute="_compute_stock_reservation",
readonly=True,
multi="stock_reservation",
store=True,
string="Has Stock Reservations",
)
is_stock_reservable = fields.Boolean(
- compute="_stock_reservation",
+ compute="_compute_stock_reservation",
readonly=True,
multi="stock_reservation",
store=True,
string="Can Have Stock Reservations",
)
- @api.multi
def release_all_stock_reservation(self):
line_ids = [line.id for order in self for line in order.order_line]
lines = self.env["sale.order.line"].browse(line_ids)
lines.release_stock_reservation()
return True
- @api.multi
- def action_button_confirm(self):
+ def action_confirm(self):
self.release_all_stock_reservation()
- return super(SaleOrder, self).action_button_confirm()
+ return super().action_confirm()
- @api.multi
def action_cancel(self):
self.release_all_stock_reservation()
- return super(SaleOrder, self).action_cancel()
+ return super().action_cancel()
+
+ def write(self, vals):
+ old_lines = self.mapped("order_line")
+ dict_old_lines = {}
+ for line in old_lines:
+ dict_old_lines[line.id] = {
+ "product_id": line.product_id,
+ "product_uom_qty": line.product_uom_qty,
+ }
+ res = super().write(vals)
+ for order in self:
+ body = ""
+ for line in vals.get("order_line", []):
+ if line[0] == 1 and list(set(line[2].keys()).intersection(_LINE_KEYS)):
+ body += order.get_message(dict_old_lines.get(line[1]), line[2])
+ if body != "":
+ order.message_post(body=body)
+ return res
+
+ @api.model
+ def get_message(self, old_vals, new_vals):
+ ProductProduct = self.env["product.product"]
+ body = _("
Modified Order line data
")
+ if "product_id" in new_vals:
+ old_product = old_vals["product_id"].display_name
+ new_product = ProductProduct.browse(new_vals["product_id"]).display_name
+ body += _("
Product: ")
+ body += "{} → {}
".format(old_product, new_product)
+ if "product_uom_qty" in new_vals:
+ if "product_id" not in new_vals:
+ body += _("
".format(
+ old_vals["product_uom_qty"], float(new_vals["product_uom_qty"]),
+ )
+ body += " "
+ return body
+
+ def unlink(self):
+ for order in self:
+ if order.has_stock_reservation:
+ raise UserError(
+ _(
+ "Sale Order %s has some reserved lines.\n"
+ "Please unreserve this lines before delete the order."
+ )
+ % (order.name)
+ )
+ return super().unlink()
class SaleOrderLine(models.Model):
_inherit = "sale.order.line"
- @api.multi
def _get_line_rule(self):
""" Get applicable rule for this product
Reproduce get suitable rule from procurement
to predict source location """
- ProcurementRule = self.env["procurement.rule"]
+ StockRule = self.env["stock.rule"]
product = self.product_id
product_route_ids = [
x.id for x in product.route_ids + product.categ_id.total_route_ids
]
- rules = ProcurementRule.search(
+ rules = StockRule.search(
[("route_id", "in", product_route_ids)],
order="route_sequence, sequence",
limit=1,
@@ -108,13 +138,12 @@ def _get_line_rule(self):
("route_id", "in", wh_route_ids),
]
- rules = ProcurementRule.search(domain, order="route_sequence, sequence")
+ rules = StockRule.search(domain, order="route_sequence, sequence")
if rules:
- return rules[0]
+ fields.first(rules)
return False
- @api.multi
def _get_procure_method(self):
""" Get procure_method depending on product routes """
rule = self._get_line_rule()
@@ -122,9 +151,8 @@ def _get_procure_method(self):
return rule.procure_method
return False
- @api.multi
@api.depends("state", "product_id.route_ids", "product_id.type")
- def _is_stock_reservable(self):
+ def _compute_is_stock_reservable(self):
for line in self:
reservable = False
if (
@@ -139,89 +167,30 @@ def _is_stock_reservable(self):
reservable = True
line.is_stock_reservable = reservable
+ @api.depends("order_id.state", "reservation_ids")
+ def _compute_is_readonly(self):
+ for line in self:
+ line.is_readonly = (
+ len(line.reservation_ids) > 0 or line.order_id.state != "draft"
+ )
+
reservation_ids = fields.One2many(
"stock.reservation", "sale_line_id", string="Stock Reservation", copy=False
)
is_stock_reservable = fields.Boolean(
- compute="_is_stock_reservable", readonly=True, string="Can be reserved"
+ compute="_compute_is_stock_reservable", readonly=True, string="Can be reserved"
)
+ is_readonly = fields.Boolean(compute="_compute_is_readonly", store=False)
- @api.multi
def release_stock_reservation(self):
reserv_ids = [reserv.id for line in self for reserv in line.reservation_ids]
reservations = self.env["stock.reservation"].browse(reserv_ids)
- reservations.release()
+ reservations.release_reserve()
return True
- def product_id_change(
- self,
- cr,
- uid,
- ids,
- pricelist,
- product,
- qty=0,
- uom=False,
- qty_uos=0,
- uos=False,
- name="",
- partner_id=False,
- lang=False,
- update_tax=True,
- date_order=False,
- packaging=False,
- fiscal_position=False,
- flag=False,
- context=None,
- ):
- result = super(SaleOrderLine, self).product_id_change(
- cr,
- uid,
- ids,
- pricelist,
- product,
- qty=qty,
- uom=uom,
- qty_uos=qty_uos,
- uos=uos,
- name=name,
- partner_id=partner_id,
- lang=lang,
- update_tax=update_tax,
- date_order=date_order,
- packaging=packaging,
- fiscal_position=fiscal_position,
- flag=flag,
- context=context,
- )
- if not ids: # warn only if we change an existing line
- return result
- assert len(ids) == 1, "Expected 1 ID, got %r" % ids
- line = self.browse(cr, uid, ids[0], context=context)
- if qty != line.product_uom_qty and line.reservation_ids:
- msg = (
- _(
- "As you changed the quantity of the line, "
- "the quantity of the stock reservation will "
- "be automatically adjusted to %.2f."
- )
- % qty
- )
- msg += "\n\n"
- result.setdefault("warning", {})
- if result["warning"].get("message"):
- result["warning"]["message"] += msg
- else:
- result["warning"] = {
- "title": _("Configuration Error!"),
- "message": msg,
- }
- return result
-
- @api.multi
def write(self, vals):
- block_on_reserve = ("product_id", "product_uom", "product_uos", "type")
- update_on_reserve = ("price_unit", "product_uom_qty", "product_uos_qty")
+ block_on_reserve = ("product_id", "product_uom", "type")
+ update_on_reserve = ("price_unit", "product_uom_qty")
keys = set(vals.keys())
test_block = keys.intersection(block_on_reserve)
test_update = keys.intersection(update_on_reserve)
@@ -238,7 +207,7 @@ def write(self, vals):
"before changing the product."
),
)
- res = super(SaleOrderLine, self).write(vals)
+ res = super().write(vals)
if test_update:
for line in self:
if not line.reservation_ids:
@@ -258,7 +227,19 @@ def write(self, vals):
{
"price_unit": line.price_unit,
"product_uom_qty": line.product_uom_qty,
- "product_uos_qty": line.product_uos_qty,
}
)
return res
+
+ def unlink(self):
+ for line in self:
+ if line.reservation_ids:
+ raise UserError(
+ _(
+ 'Sale order line "[%s] %s" has a related reservation.\n'
+ "Please unreserve this line before "
+ "delete the line"
+ )
+ % (line.order_id.name, line.name)
+ )
+ return super().unlink()
diff --git a/stock_reserve_sale/model/stock_reserve.py b/stock_reserve_sale/model/stock_reserve.py
index 097ed67d280d..c4c1c7378e5a 100644
--- a/stock_reserve_sale/model/stock_reserve.py
+++ b/stock_reserve_sale/model/stock_reserve.py
@@ -1,24 +1,6 @@
-##############################################################################
-#
-# 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 import api, fields, models
+# Copyright 2013 Camptocamp SA - Guewen Baconnier
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+from odoo import fields, models
class StockReservation(models.Model):
@@ -31,8 +13,7 @@ class StockReservation(models.Model):
"sale.order", string="Sale Order", related="sale_line_id.order_id"
)
- @api.multi
- def release(self):
+ def release_reserve(self):
for rec in self:
rec.sale_line_id = False
- return super(StockReservation, self).release()
+ return super().release_reserve()
diff --git a/stock_reserve_sale/readme/CONTRIBUTORS.rst b/stock_reserve_sale/readme/CONTRIBUTORS.rst
new file mode 100644
index 000000000000..9f19ab9b7e75
--- /dev/null
+++ b/stock_reserve_sale/readme/CONTRIBUTORS.rst
@@ -0,0 +1,8 @@
+* Leonardo Pistone
+* Alexandre Fayolle
+* Yannick Vaucher
+* Guewen Baconnier
+
+* `Tecnativa `_:
+
+ * Carlos Roca
diff --git a/stock_reserve_sale/readme/DESCRIPTION.rst b/stock_reserve_sale/readme/DESCRIPTION.rst
new file mode 100644
index 000000000000..cc3426fa1acc
--- /dev/null
+++ b/stock_reserve_sale/readme/DESCRIPTION.rst
@@ -0,0 +1,23 @@
+Allows to create stock reservations for quotation lines before the
+confirmation of the quotation. The reservations might have a validity
+date and in any case they are lifted when the quotation is canceled or
+confirmed.
+
+Reservations can be done only on "make to stock" and stockable products.
+
+The reserved products are subtracted 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.
+
+If you want to prevent sales orders to be confirmed when the stock is
+insufficient at the order date, you may want to install the
+`sale_exception_nostock` module.
+
+Additionally, if the sale_owner_stock_sourcing module is installed, the owner
+specified on the sale order line will be proposed as owner of the reservation.
+If you try to make a reservation for an order whose lines have different, you
+will get a message suggesting to reserve each line individually. There is no
+module dependency: this modules is fully functional even without ownership
+management.
diff --git a/stock_reserve_sale/readme/USAGE.rst b/stock_reserve_sale/readme/USAGE.rst
new file mode 100644
index 000000000000..05049fb0a1fb
--- /dev/null
+++ b/stock_reserve_sale/readme/USAGE.rst
@@ -0,0 +1,8 @@
+#. Create a new Sale Order
+#. Add lines to the Order
+
+Now you can reserve all the lines by clicking on *Reserve Stock* or you can reserve each
+one by pressing on the lock icon at the lines.
+
+Once they where reserved, you can release the reserves by clicking at *Cancell all*
+button or by clicking the undo icon on the lines.
diff --git a/stock_reserve_sale/static/description/index.html b/stock_reserve_sale/static/description/index.html
new file mode 100644
index 000000000000..0f5c78d06215
--- /dev/null
+++ b/stock_reserve_sale/static/description/index.html
@@ -0,0 +1,456 @@
+
+
+
+
+
+
+Stock Reserve Sales
+
+
+
+
+
Stock Reserve Sales
+
+
+
+
Allows to create stock reservations for quotation lines before the
+confirmation of the quotation. The reservations might have a validity
+date and in any case they are lifted when the quotation is canceled or
+confirmed.
+
Reservations can be done only on “make to stock” and stockable products.
+
The reserved products are subtracted 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.
+
If you want to prevent sales orders to be confirmed when the stock is
+insufficient at the order date, you may want to install the
+sale_exception_nostock module.
+
Additionally, if the sale_owner_stock_sourcing module is installed, the owner
+specified on the sale order line will be proposed as owner of the reservation.
+If you try to make a reservation for an order whose lines have different, you
+will get a message suggesting to reserve each line individually. There is no
+module dependency: this modules is fully functional even without ownership
+management.
Bugs are tracked on GitHub Issues.
+In case of trouble, please check there if your issue has already been reported.
+If you spotted it first, help us smashing it by providing a detailed and welcomed
+feedback.
+
Do not contact contributors directly about support or help with technical issues.
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.
+
+
diff --git a/stock_reserve_sale/test/sale_line_reserve.yml b/stock_reserve_sale/test/sale_line_reserve.yml
deleted file mode 100644
index 3f2552607cec..000000000000
--- a/stock_reserve_sale/test/sale_line_reserve.yml
+++ /dev/null
@@ -1,101 +0,0 @@
-- I create a product to test the stock reservation
-- !record {model: product.product, id: product_yogurt}:
- default_code: 001yogurt
- name: yogurt
- 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
- 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 yogurt with 10 kgm
-- !record {model: stock.change.product.qty, id: change_qty}:
- new_quantity: 10
- product_id: product_yogurt
-- !python {model: stock.change.product.qty}: |
- context['active_id'] = ref('product_yogurt')
- self.change_product_qty(cr, uid, [ref('change_qty')], context=context)
-- In order to test reservation of the sales order, I create a sales order
-- !record {model: sale.order, id: sale_reserve_02}:
- partner_id: base.res_partner_2
- payment_term: account.account_payment_term
-- And I create a sales order line
-- ? !record {
- model: sale.order.line,
- id: sale_line_reserve_02_01,
- view: sale.view_order_line_tree,
- }
- : name: Yogurt
- product_id: product_yogurt
- product_uom_qty: 4
- product_uom: product.product_uom_kgm
- order_id: sale_reserve_02
-- And I create a stock reserve for this line
-- !python {model: sale.stock.reserve}: |
- active_id = ref('sale_line_reserve_02_01')
- context['active_id'] = active_id
- context['active_ids'] = [active_id]
- context['active_model'] = 'sale.order.line'
- wizard_id = self.create(cr, uid, {}, context=context)
- self.button_reserve(cr, uid, [wizard_id], context=context)
-- I check Virtual stock of yogurt after update reservation
-- !python {model: product.product}: |
- product = self.browse(cr, uid, ref('product_yogurt'), context=context)
- assert product.virtual_available == 6, "Stock is not updated."
-- I set product_12 to MTO (doesn't work)
-- !record {model: product.product, id: product.product_product_12}:
- route_ids:
- - stock.route_warehouse0_mto
-- I set MTO for real
-- !python {model: product.product}: |
- product = self.browse(cr, uid, ref('product.product_product_12'), context=context)
- self.write(cr, uid, ref('product.product_product_12'),
- {'route_ids': [(6, False, [ref('stock.route_warehouse0_mto')])]}, context=context)
-- And I create a MTO sales order line
-- ? !record {
- model: sale.order.line,
- id: sale_line_reserve_02_02,
- view: sale.view_order_line_tree,
- }
- : order_id: sale_reserve_02
- name: Mouse, Wireless
- product_id: product.product_product_12
- product_uom_qty: 4
- product_uom: product.product_uom_unit
-- And I try to create a stock reserve for this MTO line
-- !python {model: sale.stock.reserve}: |
- active_id = ref('sale_line_reserve_02_02')
- context['active_id'] = active_id
- context['active_ids'] = [active_id]
- context['active_model'] = 'sale.order.line'
- wizard_id = self.create(cr, uid, {}, context=context)
- self.button_reserve(cr, uid, [wizard_id], context=context)
-- I should not have a stock reservation for a MTO line
-- !python {model: stock.reservation}: |
- reserv_ids = self.search(
- cr, uid,
- [('sale_line_id', '=', ref('sale_line_reserve_02_02'))],
- context=context)
- assert not reserv_ids, "No stock reservation should be created for MTO lines"
-- And I change the quantity in the first line
-- ? !record {
- model: sale.order.line,
- id: sale_line_reserve_02_01,
- view: sale.view_order_line_tree,
- }
- : product_uom_qty: 5
-- I check Virtual stock of yogurt after change of reservations
-- !python {model: product.product}: |
- product = self.browse(cr, uid, ref('product_yogurt'), context=context)
- assert product.virtual_available == 5, "Stock is not updated."
-- I release the sales order's reservations for the first line
-- !python {model: sale.order.line}: |
- self.release_stock_reservation(cr, uid, [ref('sale_line_reserve_02_01')], context=context)
-- I check Virtual stock of yogurt after release of reservations
-- !python {model: product.product}: |
- product = self.browse(cr, uid, ref('product_yogurt'), context=context)
- assert product.virtual_available == 10, "Stock is not updated."
diff --git a/stock_reserve_sale/test/sale_reserve.yml b/stock_reserve_sale/test/sale_reserve.yml
deleted file mode 100644
index a02603b491d0..000000000000
--- a/stock_reserve_sale/test/sale_reserve.yml
+++ /dev/null
@@ -1,56 +0,0 @@
-- I force recomputation of stock.location parent left/right
-- !python {model: stock.location}:
- # we need this because when running the tests at install time as is done on
- # Travis, the hook performing this operation for the new stock reservation
- # location is run after the test execution. This causes the stock level
- # computation to be wrong at the time the tests are run.
- self._parent_store_compute(cr)
-- I create a product to test the stock reservation
-- !record {model: product.product, id: product_gelato}:
- default_code: 001GELATO
- name: Gelato
- 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
- 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 Gelato with 10 kgm
-- !record {model: stock.change.product.qty, id: change_qty}:
- new_quantity: 10
- product_id: product_gelato
-- !python {model: stock.change.product.qty}: |
- context['active_id'] = ref('product_gelato')
- self.change_product_qty(cr, uid, [ref('change_qty')], context=context)
-- In order to test reservation of the sales order, I create a sales order
-- !record {model: sale.order, id: sale_reserve_01}:
- partner_id: base.res_partner_2
- payment_term: account.account_payment_term
- order_line:
- - product_id: product_gelato
- product_uom_qty: 4
- - product_id: product_gelato
- product_uom_qty: 1
-- I call the wizard to reserve the products of the sales order
-- !python {model: sale.stock.reserve}: |
- active_id = ref('sale_reserve_01')
- context['active_id'] = active_id
- context['active_ids'] = [active_id]
- context['active_model'] = 'sale.order'
- wizard_id = self.create(cr, uid, {}, context=context)
- self.button_reserve(cr, uid, [wizard_id], context=context)
-- I check Virtual stock of Gelato after update reservation
-- !python {model: product.product}: |
- product = self.browse(cr, uid, ref('product_gelato'), context=context)
- assert product.virtual_available == 5, "Stock is not updated after reservation."
-- I release the sales order's reservations
-- !python {model: sale.order}: |
- self.release_all_stock_reservation(cr, uid, [ref('sale_reserve_01')], context=context)
-- I check Virtual stock of Gelato after release of reservations
-- !python {model: product.product}: |
- product = self.browse(cr, uid, ref('product_gelato'), context=context)
- assert product.virtual_available == 10, "Stock is not updated after releasing reservations."
diff --git a/stock_reserve_sale/tests/__init__.py b/stock_reserve_sale/tests/__init__.py
new file mode 100644
index 000000000000..726598f66e20
--- /dev/null
+++ b/stock_reserve_sale/tests/__init__.py
@@ -0,0 +1 @@
+from . import test_stock_reserve_sale
diff --git a/stock_reserve_sale/tests/test_stock_reserve_sale.py b/stock_reserve_sale/tests/test_stock_reserve_sale.py
new file mode 100644
index 000000000000..cb47eacc9fc8
--- /dev/null
+++ b/stock_reserve_sale/tests/test_stock_reserve_sale.py
@@ -0,0 +1,138 @@
+# Copyright 2021 Tecnativa - Carlos Roca
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+from odoo.exceptions import UserError
+from odoo.tests import Form, common
+
+
+class TestStockReserveSale(common.SavepointCase):
+ def setUp(self):
+ super().setUp()
+ partner_form = Form(self.env["res.partner"])
+ partner_form.name = "Test partner"
+ partner_form.country_id = self.env.ref("base.es")
+ self.partner = partner_form.save()
+ warehouse_form = Form(self.env["stock.warehouse"])
+ warehouse_form.name = "Test warehouse"
+ warehouse_form.code = "TEST"
+ self.warehouse = warehouse_form.save()
+ product_form = Form(self.env["product.product"])
+ product_form.name = "Test Product 1"
+ product_form.type = "product"
+ self.product_1 = product_form.save()
+ product_form = Form(self.env["product.product"])
+ product_form.name = "Test Product 2"
+ product_form.type = "product"
+ self.product_2 = product_form.save()
+ self.env["stock.quant"].create(
+ {
+ "product_id": self.product_1.id,
+ "location_id": self.warehouse.lot_stock_id.id,
+ "quantity": 10.0,
+ }
+ )
+ self.env["stock.quant"].create(
+ {
+ "product_id": self.product_2.id,
+ "location_id": self.warehouse.lot_stock_id.id,
+ "quantity": 10.0,
+ }
+ )
+
+ def test_reserve_01_tree_reserve_release(self):
+ sale_order_form = Form(self.env["sale.order"])
+ sale_order_form.partner_id = self.partner
+ with sale_order_form.order_line.new() as order_line_form:
+ order_line_form.product_id = self.product_1
+ order_line_form.product_uom_qty = 3
+ so = sale_order_form.save()
+ wiz = Form(
+ self.env["sale.stock.reserve"].with_context(
+ active_model="sale.order.line", active_ids=so.order_line.ids
+ )
+ ).save()
+ wiz.button_reserve()
+ self.assertEquals(self.product_1.virtual_available, 7)
+ so.order_line.release_stock_reservation()
+ self.assertEquals(self.product_1.virtual_available, 10)
+
+ def test_reserve_02_all_form_reserve_release(self):
+ sale_order_form = Form(self.env["sale.order"])
+ sale_order_form.partner_id = self.partner
+ with sale_order_form.order_line.new() as order_line_form:
+ order_line_form.product_id = self.product_1
+ order_line_form.product_uom_qty = 3
+ with sale_order_form.order_line.new() as order_line_form:
+ order_line_form.product_id = self.product_2
+ order_line_form.product_uom_qty = 5
+ so = sale_order_form.save()
+ wiz = Form(
+ self.env["sale.stock.reserve"].with_context(
+ active_model="sale.order", active_id=so.id, active_ids=so.ids
+ )
+ ).save()
+ wiz.button_reserve()
+ self.assertEquals(self.product_1.virtual_available, 7)
+ self.assertEquals(self.product_2.virtual_available, 5)
+ so.release_all_stock_reservation()
+ self.assertEquals(self.product_1.virtual_available, 10)
+ self.assertEquals(self.product_2.virtual_available, 10)
+
+ def test_reserve_03_confirm_order_release(self):
+ sale_order_form = Form(self.env["sale.order"])
+ sale_order_form.partner_id = self.partner
+ with sale_order_form.order_line.new() as order_line_form:
+ order_line_form.product_id = self.product_1
+ order_line_form.product_uom_qty = 3
+ so = sale_order_form.save()
+ wiz = Form(
+ self.env["sale.stock.reserve"].with_context(
+ active_model="sale.order.line", active_ids=so.order_line.ids
+ )
+ ).save()
+ wiz.button_reserve()
+ self.assertEquals(self.product_1.virtual_available, 7)
+ so.action_confirm()
+ cancelled_reservation = self.env["stock.reservation"].search(
+ [("product_id", "=", self.product_1.id), ("state", "=", "cancel")]
+ )
+ self.assertEquals(len(cancelled_reservation), 1)
+ self.assertEquals(self.product_1.virtual_available, 7)
+
+ def test_reserve_04_cancel_order_release(self):
+ sale_order_form = Form(self.env["sale.order"])
+ sale_order_form.partner_id = self.partner
+ with sale_order_form.order_line.new() as order_line_form:
+ order_line_form.product_id = self.product_1
+ order_line_form.product_uom_qty = 3
+ so = sale_order_form.save()
+ wiz = Form(
+ self.env["sale.stock.reserve"].with_context(
+ active_model="sale.order.line", active_ids=so.order_line.ids
+ )
+ ).save()
+ wiz.button_reserve()
+ self.assertEquals(self.product_1.virtual_available, 7)
+ so.action_cancel()
+ cancelled_reservation = self.env["stock.reservation"].search(
+ [("product_id", "=", self.product_1.id), ("state", "=", "cancel")]
+ )
+ self.assertEquals(len(cancelled_reservation), 1)
+ self.assertEquals(self.product_1.virtual_available, 10)
+
+ def test_reserve_05_unlink_order(self):
+ sale_order_form = Form(self.env["sale.order"])
+ sale_order_form.partner_id = self.partner
+ with sale_order_form.order_line.new() as order_line_form:
+ order_line_form.product_id = self.product_1
+ order_line_form.product_uom_qty = 3
+ so = sale_order_form.save()
+ wiz = Form(
+ self.env["sale.stock.reserve"].with_context(
+ active_model="sale.order.line", active_ids=so.order_line.ids
+ )
+ ).save()
+ wiz.button_reserve()
+ with self.assertRaises(UserError):
+ so.unlink()
+ with self.assertRaises(UserError):
+ so.order_line.unlink()
diff --git a/stock_reserve_sale/view/sale.xml b/stock_reserve_sale/view/sale.xml
index 487344b056f4..2ded550dcdde 100644
--- a/stock_reserve_sale/view/sale.xml
+++ b/stock_reserve_sale/view/sale.xml
@@ -1,79 +1,122 @@
-
-
-
- sale.order.form.reserve
- sale.order
-
-
-
-
-
-
-
- {"reload_on_button": 1}
-
-
-
-
-
-
-
-
-
-
+
+
+ sale.order.form.reserve
+ sale.order
+
+
+
+
+
+
+
+ {"reload_on_button": 1}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
-
-
-
+
+
+
+
+
+ {'readonly': [('is_readonly', '=', True)]}
+
+
+ {'readonly': [('is_readonly', '=', True)]}
+
+
+
+
+
+ {'readonly': [('is_readonly', '=', True)]}
+
+
+ {'readonly': [('is_readonly', '=', True)]}
+
+
+
+
diff --git a/stock_reserve_sale/view/stock_reserve.xml b/stock_reserve_sale/view/stock_reserve.xml
index 9c7935a2c37f..976e73e8ed02 100644
--- a/stock_reserve_sale/view/stock_reserve.xml
+++ b/stock_reserve_sale/view/stock_reserve.xml
@@ -1,28 +1,26 @@
-
-
-
- stock.reservation.form
- stock.reservation
-
-
-
-
-
-
-
-
-
-
-
- stock.reservation.tree
- stock.reservation
-
-
-
+
+
+ stock.reservation.form
+ stock.reservation
+
+
+
+
-
+
+
+
+
+
+
+ stock.reservation.tree
+ stock.reservation
+
+
+
+
-
-
-
+
+
+
diff --git a/stock_reserve_sale/wizard/__init__.py b/stock_reserve_sale/wizard/__init__.py
index 519cb0f7ab08..f52589b977a9 100644
--- a/stock_reserve_sale/wizard/__init__.py
+++ b/stock_reserve_sale/wizard/__init__.py
@@ -1,21 +1,3 @@
-##############################################################################
-#
-# 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 .
-#
-##############################################################################
-
+# Copyright 2013 Camptocamp SA - Guewen Baconnier
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from . import sale_stock_reserve
diff --git a/stock_reserve_sale/wizard/sale_stock_reserve.py b/stock_reserve_sale/wizard/sale_stock_reserve.py
index b5b8884cebf9..90454f79d8e8 100644
--- a/stock_reserve_sale/wizard/sale_stock_reserve.py
+++ b/stock_reserve_sale/wizard/sale_stock_reserve.py
@@ -1,32 +1,17 @@
-##############################################################################
-#
-# Author: Guewen Baconnier, Leonardo Pistone
-# Copyright 2013-2015 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 import api, exceptions, fields, models
+# Copyright 2013 Camptocamp SA - Guewen Baconnier
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+from odoo import _, api, exceptions, fields, models
class SaleStockReserve(models.TransientModel):
_name = "sale.stock.reserve"
+ _description = "Sale Stock Reserve"
@api.model
def _default_location_id(self):
- return self.env["stock.reservation"]._default_location_id()
+ return self.env["stock.reservation"].get_location_from_ref(
+ "stock.stock_location_stock"
+ )
@api.model
def _default_location_dest_id(self):
@@ -53,8 +38,10 @@ def _default_owner(self):
return owners.pop()
elif len(owners) > 1:
raise exceptions.Warning(
- "The lines have different owners. Please reserve them "
- "individually with the reserve button on each one."
+ _(
+ """The lines have different owners. Please reserve them
+ individually with the reserve button on each one."""
+ )
)
return self.env["res.partner"]
@@ -77,10 +64,8 @@ def _default_owner(self):
note = fields.Text("Notes")
owner_id = fields.Many2one("res.partner", "Stock Owner", default=_default_owner)
- @api.multi
def _prepare_stock_reservation(self, line):
self.ensure_one()
- product_uos = line.product_uos.id if line.product_uos else False
return {
"product_id": line.product_id.id,
"product_uom": line.product_uom.id,
@@ -90,14 +75,11 @@ def _prepare_stock_reservation(self, line):
"location_id": self.location_id.id,
"location_dest_id": self.location_dest_id.id,
"note": self.note,
- "product_uos_qty": line.product_uos_qty,
- "product_uos": product_uos,
"price_unit": line.price_unit,
"sale_line_id": line.id,
"restrict_partner_id": self.owner_id.id,
}
- @api.multi
def stock_reserve(self, line_ids):
self.ensure_one()
@@ -110,7 +92,6 @@ def stock_reserve(self, line_ids):
reserv.reserve()
return True
- @api.multi
def button_reserve(self):
env = self.env
self.ensure_one()
diff --git a/stock_reserve_sale/wizard/sale_stock_reserve_view.xml b/stock_reserve_sale/wizard/sale_stock_reserve_view.xml
index 2ed28a91d020..0f338d8584e5 100644
--- a/stock_reserve_sale/wizard/sale_stock_reserve_view.xml
+++ b/stock_reserve_sale/wizard/sale_stock_reserve_view.xml
@@ -1,45 +1,42 @@
-
-
-
- sale.stock.reserve.form
- sale.stock.reserve
-
-
-
-
-
- Reserve Stock for Quotation Lines
- ir.actions.act_window
- sale.stock.reserve
- form
- form
- new
-
-
-
+
+
+ sale.stock.reserve.form
+ sale.stock.reserve
+
+
+
+
+
+ Reserve Stock for Quotation Lines
+ ir.actions.act_window
+ sale.stock.reserve
+ form
+ new
+
+
From e265f3ec1e07bc5e18e0cdf042cd833f83bbcac9 Mon Sep 17 00:00:00 2001
From: oca-travis
Date: Fri, 20 Aug 2021 06:47:55 +0000
Subject: [PATCH 20/26] [UPD] Update stock_reserve_sale.pot
---
.../i18n/stock_reserve_sale.pot | 57 ++++++++++++++++---
1 file changed, 50 insertions(+), 7 deletions(-)
diff --git a/stock_reserve_sale/i18n/stock_reserve_sale.pot b/stock_reserve_sale/i18n/stock_reserve_sale.pot
index c6dcbb7b8935..bca4db38ad3b 100644
--- a/stock_reserve_sale/i18n/stock_reserve_sale.pot
+++ b/stock_reserve_sale/i18n/stock_reserve_sale.pot
@@ -6,8 +6,6 @@ msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 13.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2021-07-27 07:47+0000\n"
-"PO-Revision-Date: 2021-07-27 07:47+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
@@ -15,6 +13,30 @@ msgstr ""
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
+#. module: stock_reserve_sale
+#: code:addons/stock_reserve_sale/model/sale.py:0
+#, python-format
+msgid "