[IMP] stock_reserve_sale: black, isort, prettier

This commit is contained in:
Carlos Roca
2021-07-26 09:34:54 +02:00
parent f4fa79e5c3
commit 9a0b7879cc
12 changed files with 319 additions and 327 deletions

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Author: Guewen Baconnier

View File

@@ -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,
}

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Author: Guewen Baconnier

View File

@@ -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

View File

@@ -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):

View File

@@ -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."

View File

@@ -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."

View File

@@ -1,67 +1,79 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8" ?>
<openerp>
<data noupdate="0">
<record id="view_order_form_reserve" model="ir.ui.view">
<field name="name">sale.order.form.reserve</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale_stock.view_order_form_inherit"/>
<field name="inherit_id" ref="sale_stock.view_order_form_inherit" />
<field name="arch" type="xml">
<button name="action_quotation_send" position="before">
<field name="is_stock_reservable" invisible="1"/>
<button name="%(action_sale_stock_reserve)d"
<field name="is_stock_reservable" invisible="1" />
<button
name="%(action_sale_stock_reserve)d"
type="action"
string="Reserve Stock"
help="Pre-book products from stock"
attrs="{'invisible': [('is_stock_reservable', '=', False)]}"
/>
/>
</button>
<field name="order_line" position="attributes">
<attribute name="options">{"reload_on_button": 1}</attribute>
</field>
<xpath expr="//field[@name='order_line']/form//field[@name='state']" position="before">
<field name="reservation_ids" invisible="1"/>
<button name="%(action_sale_stock_reserve)d"
<xpath
expr="//field[@name='order_line']/form//field[@name='state']"
position="before"
>
<field name="reservation_ids" invisible="1" />
<button
name="%(action_sale_stock_reserve)d"
type="action"
string="Reserve Stock"
attrs="{'invisible': ['|', ('reservation_ids', '!=', []),
('state', '!=', 'draft')]}" />
<button name="release_stock_reservation"
('state', '!=', 'draft')]}"
/>
<button
name="release_stock_reservation"
type="object"
string="Release Reservation"
attrs="{'invisible': ['|', ('reservation_ids', '=', []),
('state', '!=', 'draft')]}" />
('state', '!=', 'draft')]}"
/>
</xpath>
<xpath expr="//field[@name='order_line']/tree/field[@name='price_subtotal']" position="after">
<field name="reservation_ids" invisible="1"/>
<field name="is_stock_reservable" invisible="1"/>
<button name="%(action_sale_stock_reserve)d"
<xpath
expr="//field[@name='order_line']/tree/field[@name='price_subtotal']"
position="after"
>
<field name="reservation_ids" invisible="1" />
<field name="is_stock_reservable" invisible="1" />
<button
name="%(action_sale_stock_reserve)d"
type="action"
string="Reserve Stock"
icon="terp-locked"
attrs="{'invisible': [('is_stock_reservable', '=', False)]}" />
<button name="release_stock_reservation"
attrs="{'invisible': [('is_stock_reservable', '=', False)]}"
/>
<button
name="release_stock_reservation"
type="object"
string="Release Reservation"
icon="gtk-undo"
attrs="{'invisible': [('reservation_ids', '=', [])]}" />
attrs="{'invisible': [('reservation_ids', '=', [])]}"
/>
</xpath>
<field name="invoiced" position="before">
<label for="has_stock_reservation"/>
<label for="has_stock_reservation" />
<div>
<field name="has_stock_reservation"/>
<button name="release_all_stock_reservation"
<field name="has_stock_reservation" />
<button
name="release_all_stock_reservation"
string="cancel all"
type="object" class="oe_link"
attrs="{'invisible': [('has_stock_reservation', '=', False)]}"/>
type="object"
class="oe_link"
attrs="{'invisible': [('has_stock_reservation', '=', False)]}"
/>
</div>
</field>
</field>
</record>
</data>
</openerp>

View File

@@ -1,30 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8" ?>
<openerp>
<data noupdate="0">
<record id="view_stock_reservation_form" model="ir.ui.view">
<field name="name">stock.reservation.form</field>
<field name="model">stock.reservation</field>
<field name="inherit_id" ref="stock_reserve.view_stock_reservation_form"/>
<field name="inherit_id" ref="stock_reserve.view_stock_reservation_form" />
<field name="arch" type="xml">
<group name="location" position="after">
<group name="sale" string="Sales">
<field name="sale_id"/>
<field name="sale_line_id"/>
<field name="sale_id" />
<field name="sale_line_id" />
</group>
</group>
</field>
</record>
<record id="view_stock_reservation_tree" model="ir.ui.view">
<field name="name">stock.reservation.tree</field>
<field name="model">stock.reservation</field>
<field name="inherit_id" ref="stock_reserve.view_stock_reservation_tree"/>
<field name="inherit_id" ref="stock_reserve.view_stock_reservation_tree" />
<field name="arch" type="xml">
<field name="move_id" position="before">
<field name="sale_id"/>
<field name="sale_id" />
</field>
</field>
</record>
</data>
</openerp>

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Author: Guewen Baconnier

View File

@@ -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 @@ class SaleStockReserve(models.TransientModel):
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)

View File

@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8" ?>
<openerp>
<data noupdate="0">
<record id="view_sale_stock_reserve_form" model="ir.ui.view">
<field name="name">sale.stock.reserve.form</field>
<field name="model">sale.stock.reserve</field>
@@ -13,26 +12,27 @@
the reservation will be released once the date has passed.
</p>
<group>
<field name="location_id"/>
<field name="location_dest_id"/>
<field name="date_validity"/>
<field name="owner_id" groups="stock.group_tracking_owner"/>
<field name="location_id" />
<field name="location_dest_id" />
<field name="date_validity" />
<field name="owner_id" groups="stock.group_tracking_owner" />
</group>
<group name="note" string="Notes">
<field name="note" nolabel="1"/>
<field name="note" nolabel="1" />
</group>
<footer>
<button string="Reserve"
<button
string="Reserve"
name="button_reserve"
type="object"
class="oe_highlight" />
class="oe_highlight"
/>
or
<button special="cancel" class="oe_link" string="Cancel"/>
<button special="cancel" class="oe_link" string="Cancel" />
</footer>
</form>
</field>
</record>
<record id="action_sale_stock_reserve" model="ir.actions.act_window">
<field name="name">Reserve Stock for Quotation Lines</field>
<field name="type">ir.actions.act_window</field>