diff --git a/stock_reserve_sale/__init__.py b/stock_reserve_sale/__init__.py
index f2bf938cb..4341cc1b5 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 c919e6ac9..3eab77e61 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 5c9fc5067..e36320781 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 5723f473f..809bb9620 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 @@ class SaleOrder(models.Model):
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 @@ class SaleOrder(models.Model):
class SaleOrderLine(models.Model):
- _inherit = 'sale.order.line'
+ _inherit = "sale.order.line"
@api.multi
def _get_line_rule(self):
@@ -85,24 +86,29 @@ class SaleOrderLine(models.Model):
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 @@ class SaleOrderLine(models.Model):
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 @@ class SaleOrderLine(models.Model):
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 @@ class SaleOrderLine(models.Model):
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 db68449bb..097ed67d2 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 0a798c3c2..3f2552607 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 a3a81a472..a02603b49 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 e5849b04c..487344b05 100644
--- a/stock_reserve_sale/view/sale.xml
+++ b/stock_reserve_sale/view/sale.xml
@@ -1,67 +1,79 @@
-
+