diff --git a/stock_reserve_sale/__openerp__.py b/stock_reserve_sale/__openerp__.py
index be0ae3152..3fa481478 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 @@ 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',
diff --git a/stock_reserve_sale/test/sale_line_reserve.yml b/stock_reserve_sale/test/sale_line_reserve.yml
index 421d5da2f..0a798c3c2 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 2671f40e1..9afc4dff9 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 2fc7d1ff1..67d9fb313 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 @@ class SaleStockReserve(models.TransientModel):
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 @@ class SaleStockReserve(models.TransientModel):
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 @@ class SaleStockReserve(models.TransientModel):
'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 5b3c39bcc..69b3fb4ff 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 @@
+