mirror of
https://github.com/OCA/stock-logistics-warehouse.git
synced 2025-01-21 14:27:28 +02:00
[IMP] stock_reserve: black, isort, prettier
This commit is contained in:
committed by
Víctor Martínez
parent
03c1aa983e
commit
f7df08dc6a
@@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
#
|
#
|
||||||
# Author: Guewen Baconnier
|
# Author: Guewen Baconnier
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
#
|
#
|
||||||
# Author: Guewen Baconnier
|
# Author: Guewen Baconnier
|
||||||
@@ -19,25 +18,25 @@
|
|||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
{'name': 'Stock Reservation',
|
{
|
||||||
'summary': 'Stock reservations on products',
|
"name": "Stock Reservation",
|
||||||
'version': '10.0.1.0.0',
|
"summary": "Stock reservations on products",
|
||||||
'author': "Camptocamp,Odoo Community Association (OCA)",
|
"version": "10.0.1.0.0",
|
||||||
'category': 'Warehouse',
|
"author": "Camptocamp,Odoo Community Association (OCA)",
|
||||||
'license': 'AGPL-3',
|
"category": "Warehouse",
|
||||||
'complexity': 'normal',
|
"license": "AGPL-3",
|
||||||
'images': [],
|
"complexity": "normal",
|
||||||
'website': "http://www.camptocamp.com",
|
"images": [],
|
||||||
'depends': ['stock',
|
"website": "http://www.camptocamp.com",
|
||||||
],
|
"depends": ["stock",],
|
||||||
'demo': [],
|
"demo": [],
|
||||||
'data': ['view/stock_reserve.xml',
|
"data": [
|
||||||
'view/product.xml',
|
"view/stock_reserve.xml",
|
||||||
'data/stock_data.xml',
|
"view/product.xml",
|
||||||
'security/ir.model.access.csv',
|
"data/stock_data.xml",
|
||||||
],
|
"security/ir.model.access.csv",
|
||||||
'auto_install': False,
|
],
|
||||||
'test': ['test/stock_reserve.yml',
|
"auto_install": False,
|
||||||
],
|
"test": ["test/stock_reserve.yml",],
|
||||||
'installable': True,
|
"installable": True,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +1,29 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<odoo>
|
<odoo>
|
||||||
<data noupdate="1">
|
<data noupdate="1">
|
||||||
<record id="stock_location_reservation" model="stock.location">
|
<record id="stock_location_reservation" model="stock.location">
|
||||||
<field name="name">Reservation Stock</field>
|
<field name="name">Reservation Stock</field>
|
||||||
<field name="location_id" ref="stock.stock_location_locations"/>
|
<field name="location_id" ref="stock.stock_location_locations" />
|
||||||
</record>
|
</record>
|
||||||
|
<!-- Release the stock.reservation when the validity date has
|
||||||
|
|
||||||
<!-- Release the stock.reservation when the validity date has
|
|
||||||
passed -->
|
passed -->
|
||||||
<record forcecreate="True" id="ir_cron_release_stock_reservation" model="ir.cron">
|
<record
|
||||||
<field name="name">Release the stock reservation having a passed validity date</field>
|
forcecreate="True"
|
||||||
<field eval="True" name="active" />
|
id="ir_cron_release_stock_reservation"
|
||||||
<field name="user_id" ref="base.user_root" />
|
model="ir.cron"
|
||||||
<field name="interval_number">1</field>
|
>
|
||||||
<field name="interval_type">days</field>
|
<field
|
||||||
<field name="numbercall">-1</field>
|
name="name"
|
||||||
<field eval="False" name="doall" />
|
>Release the stock reservation having a passed validity date</field>
|
||||||
<field name="model">stock.reservation</field>
|
<field eval="True" name="active" />
|
||||||
<field name="function">release_validity_exceeded</field>
|
<field name="user_id" ref="base.user_root" />
|
||||||
<field name="args">()</field>
|
<field name="interval_number">1</field>
|
||||||
</record>
|
<field name="interval_type">days</field>
|
||||||
|
<field name="numbercall">-1</field>
|
||||||
</data>
|
<field eval="False" name="doall" />
|
||||||
|
<field name="model">stock.reservation</field>
|
||||||
|
<field name="function">release_validity_exceeded</field>
|
||||||
|
<field name="args">()</field>
|
||||||
|
</record>
|
||||||
|
</data>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Author: Leonardo Pistone
|
# Author: Leonardo Pistone
|
||||||
# Copyright 2015 Camptocamp SA
|
# Copyright 2015 Camptocamp SA
|
||||||
#
|
#
|
||||||
@@ -18,8 +17,9 @@
|
|||||||
|
|
||||||
def migrate(cr, installed_version):
|
def migrate(cr, installed_version):
|
||||||
"""Update a wrong location that is no_update in XML."""
|
"""Update a wrong location that is no_update in XML."""
|
||||||
if installed_version == '8.0.0.1':
|
if installed_version == "8.0.0.1":
|
||||||
cr.execute('''
|
cr.execute(
|
||||||
|
"""
|
||||||
UPDATE stock_location
|
UPDATE stock_location
|
||||||
SET location_id = (
|
SET location_id = (
|
||||||
SELECT res_id
|
SELECT res_id
|
||||||
@@ -39,4 +39,5 @@ def migrate(cr, installed_version):
|
|||||||
WHERE name = 'stock_location_company'
|
WHERE name = 'stock_location_company'
|
||||||
AND module = 'stock'
|
AND module = 'stock'
|
||||||
);
|
);
|
||||||
''')
|
"""
|
||||||
|
)
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
#
|
#
|
||||||
# Author: Guewen Baconnier
|
# Author: Guewen Baconnier
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
#
|
#
|
||||||
# Author: Guewen Baconnier
|
# Author: Guewen Baconnier
|
||||||
@@ -19,59 +18,62 @@
|
|||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
from odoo import models, fields, api
|
from odoo import api, fields, models
|
||||||
|
|
||||||
|
|
||||||
class ProductTemplate(models.Model):
|
class ProductTemplate(models.Model):
|
||||||
_inherit = 'product.template'
|
_inherit = "product.template"
|
||||||
|
|
||||||
reservation_count = fields.Float(
|
reservation_count = fields.Float(
|
||||||
compute='_compute_reservation_count',
|
compute="_compute_reservation_count", string="# Sales"
|
||||||
string='# Sales')
|
)
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def _compute_reservation_count(self):
|
def _compute_reservation_count(self):
|
||||||
for product in self:
|
for product in self:
|
||||||
product.reservation_count = sum(
|
product.reservation_count = sum(
|
||||||
product.product_variant_ids.mapped('reservation_count'))
|
product.product_variant_ids.mapped("reservation_count")
|
||||||
|
)
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def action_view_reservations(self):
|
def action_view_reservations(self):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
ref = 'stock_reserve.action_stock_reservation_tree'
|
ref = "stock_reserve.action_stock_reservation_tree"
|
||||||
product_ids = self.mapped('product_variant_ids.id')
|
product_ids = self.mapped("product_variant_ids.id")
|
||||||
action_dict = self.env.ref(ref).read()[0]
|
action_dict = self.env.ref(ref).read()[0]
|
||||||
action_dict['domain'] = [('product_id', 'in', product_ids)]
|
action_dict["domain"] = [("product_id", "in", product_ids)]
|
||||||
action_dict['context'] = {
|
action_dict["context"] = {
|
||||||
'search_default_draft': 1,
|
"search_default_draft": 1,
|
||||||
'search_default_reserved': 1
|
"search_default_reserved": 1,
|
||||||
}
|
}
|
||||||
return action_dict
|
return action_dict
|
||||||
|
|
||||||
|
|
||||||
class ProductProduct(models.Model):
|
class ProductProduct(models.Model):
|
||||||
_inherit = 'product.product'
|
_inherit = "product.product"
|
||||||
|
|
||||||
reservation_count = fields.Float(
|
reservation_count = fields.Float(
|
||||||
compute='_compute_reservation_count',
|
compute="_compute_reservation_count", string="# Sales"
|
||||||
string='# Sales')
|
)
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def _compute_reservation_count(self):
|
def _compute_reservation_count(self):
|
||||||
for product in self:
|
for product in self:
|
||||||
domain = [('product_id', '=', product.id),
|
domain = [
|
||||||
('state', 'in', ['draft', 'assigned'])]
|
("product_id", "=", product.id),
|
||||||
reservations = self.env['stock.reservation'].search(domain)
|
("state", "in", ["draft", "assigned"]),
|
||||||
product.reservation_count = sum(reservations.mapped('product_qty'))
|
]
|
||||||
|
reservations = self.env["stock.reservation"].search(domain)
|
||||||
|
product.reservation_count = sum(reservations.mapped("product_qty"))
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def action_view_reservations(self):
|
def action_view_reservations(self):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
ref = 'stock_reserve.action_stock_reservation_tree'
|
ref = "stock_reserve.action_stock_reservation_tree"
|
||||||
action_dict = self.env.ref(ref).read()[0]
|
action_dict = self.env.ref(ref).read()[0]
|
||||||
action_dict['domain'] = [('product_id', '=', self.id)]
|
action_dict["domain"] = [("product_id", "=", self.id)]
|
||||||
action_dict['context'] = {
|
action_dict["context"] = {
|
||||||
'search_default_draft': 1,
|
"search_default_draft": 1,
|
||||||
'search_default_reserved': 1
|
"search_default_reserved": 1,
|
||||||
}
|
}
|
||||||
return action_dict
|
return action_dict
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
#
|
#
|
||||||
# Author: Guewen Baconnier
|
# Author: Guewen Baconnier
|
||||||
@@ -19,7 +18,7 @@
|
|||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
from odoo import models, fields, api
|
from odoo import api, fields, models
|
||||||
from odoo.exceptions import except_orm
|
from odoo.exceptions import except_orm
|
||||||
from odoo.tools.translate import _
|
from odoo.tools.translate import _
|
||||||
|
|
||||||
@@ -46,18 +45,20 @@ class StockReservation(models.Model):
|
|||||||
* date_validity (once passed, the reservation will be released)
|
* date_validity (once passed, the reservation will be released)
|
||||||
* note
|
* note
|
||||||
"""
|
"""
|
||||||
_name = 'stock.reservation'
|
|
||||||
_description = 'Stock Reservation'
|
_name = "stock.reservation"
|
||||||
_inherits = {'stock.move': 'move_id'}
|
_description = "Stock Reservation"
|
||||||
|
_inherits = {"stock.move": "move_id"}
|
||||||
|
|
||||||
move_id = fields.Many2one(
|
move_id = fields.Many2one(
|
||||||
'stock.move',
|
"stock.move",
|
||||||
'Reservation Move',
|
"Reservation Move",
|
||||||
required=True,
|
required=True,
|
||||||
readonly=True,
|
readonly=True,
|
||||||
ondelete='cascade',
|
ondelete="cascade",
|
||||||
index=True)
|
index=True,
|
||||||
date_validity = fields.Date('Validity Date')
|
)
|
||||||
|
date_validity = fields.Date("Validity Date")
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def default_get(self, fields_list):
|
def default_get(self, fields_list):
|
||||||
@@ -74,14 +75,13 @@ class StockReservation(models.Model):
|
|||||||
# if there is 'location_id' field requested, ensure that
|
# if there is 'location_id' field requested, ensure that
|
||||||
# picking_type_id is also requested, because it is required
|
# picking_type_id is also requested, because it is required
|
||||||
# to compute location_id
|
# to compute location_id
|
||||||
if ('location_id' in fields_list and
|
if "location_id" in fields_list and "picking_type_id" not in fields_list:
|
||||||
'picking_type_id' not in fields_list):
|
fields_list = fields_list + ["picking_type_id"]
|
||||||
fields_list = fields_list + ['picking_type_id']
|
|
||||||
|
|
||||||
res = super(StockReservation, self).default_get(fields_list)
|
res = super(StockReservation, self).default_get(fields_list)
|
||||||
|
|
||||||
if 'product_qty' in res:
|
if "product_qty" in res:
|
||||||
del res['product_qty']
|
del res["product_qty"]
|
||||||
|
|
||||||
# At this point picking_type_id and location_id
|
# At this point picking_type_id and location_id
|
||||||
# should be computed in default way:
|
# should be computed in default way:
|
||||||
@@ -93,19 +93,20 @@ class StockReservation(models.Model):
|
|||||||
#
|
#
|
||||||
# If picking_type_id is present and location_id is not, try to find
|
# If picking_type_id is present and location_id is not, try to find
|
||||||
# default value for location_id
|
# default value for location_id
|
||||||
if not res.get('picking_type_id', None):
|
if not res.get("picking_type_id", None):
|
||||||
res['picking_type_id'] = self._default_picking_type_id()
|
res["picking_type_id"] = self._default_picking_type_id()
|
||||||
|
|
||||||
picking_type_id = res.get('picking_type_id')
|
picking_type_id = res.get("picking_type_id")
|
||||||
if picking_type_id and not res.get('location_id', False):
|
if picking_type_id and not res.get("location_id", False):
|
||||||
picking = self.env['stock.picking'].new(
|
picking = self.env["stock.picking"].new(
|
||||||
{'picking_type_id': picking_type_id})
|
{"picking_type_id": picking_type_id}
|
||||||
|
)
|
||||||
picking.onchange_picking_type()
|
picking.onchange_picking_type()
|
||||||
res['location_id'] = picking.location_id.id
|
res["location_id"] = picking.location_id.id
|
||||||
if 'location_dest_id' in fields_list:
|
if "location_dest_id" in fields_list:
|
||||||
res['location_dest_id'] = self._default_location_dest_id()
|
res["location_dest_id"] = self._default_location_dest_id()
|
||||||
if 'product_uom_qty' in fields_list:
|
if "product_uom_qty" in fields_list:
|
||||||
res['product_uom_qty'] = 1.0
|
res["product_uom_qty"] = 1.0
|
||||||
return res
|
return res
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
@@ -115,7 +116,7 @@ class StockReservation(models.Model):
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
location = self.env.ref(ref, raise_if_not_found=True)
|
location = self.env.ref(ref, raise_if_not_found=True)
|
||||||
location.check_access_rule('read')
|
location.check_access_rule("read")
|
||||||
location_id = location.id
|
location_id = location.id
|
||||||
except (except_orm, ValueError):
|
except (except_orm, ValueError):
|
||||||
location_id = False
|
location_id = False
|
||||||
@@ -123,12 +124,12 @@ class StockReservation(models.Model):
|
|||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def _default_picking_type_id(self):
|
def _default_picking_type_id(self):
|
||||||
ref = 'stock.picking_type_out'
|
ref = "stock.picking_type_out"
|
||||||
return self.env.ref(ref, raise_if_not_found=False).id
|
return self.env.ref(ref, raise_if_not_found=False).id
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def _default_location_dest_id(self):
|
def _default_location_dest_id(self):
|
||||||
ref = 'stock_reserve.stock_location_reservation'
|
ref = "stock_reserve.stock_location_reservation"
|
||||||
return self.get_location_from_ref(ref)
|
return self.get_location_from_ref(ref)
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
@@ -138,9 +139,9 @@ class StockReservation(models.Model):
|
|||||||
The reservation is done using the default UOM of the product.
|
The reservation is done using the default UOM of the product.
|
||||||
A date until which the product is reserved can be specified.
|
A date until which the product is reserved can be specified.
|
||||||
"""
|
"""
|
||||||
self.write({'date_expected': fields.Datetime.now()})
|
self.write({"date_expected": fields.Datetime.now()})
|
||||||
self.mapped('move_id').action_confirm()
|
self.mapped("move_id").action_confirm()
|
||||||
self.mapped('move_id.picking_id').action_assign()
|
self.mapped("move_id.picking_id").action_assign()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
@@ -148,16 +149,18 @@ class StockReservation(models.Model):
|
|||||||
"""
|
"""
|
||||||
Release moves from reservation
|
Release moves from reservation
|
||||||
"""
|
"""
|
||||||
self.mapped('move_id').action_cancel()
|
self.mapped("move_id").action_cancel()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def release_validity_exceeded(self, ids=None):
|
def release_validity_exceeded(self, ids=None):
|
||||||
""" Release all the reservation having an exceeded validity date """
|
""" Release all the reservation having an exceeded validity date """
|
||||||
domain = [('date_validity', '<', fields.date.today()),
|
domain = [
|
||||||
('state', '=', 'assigned')]
|
("date_validity", "<", fields.date.today()),
|
||||||
|
("state", "=", "assigned"),
|
||||||
|
]
|
||||||
if ids:
|
if ids:
|
||||||
domain.append(('id', 'in', ids))
|
domain.append(("id", "in", ids))
|
||||||
self.search(domain).release()
|
self.search(domain).release()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -167,18 +170,19 @@ class StockReservation(models.Model):
|
|||||||
self.release()
|
self.release()
|
||||||
return super(StockReservation, self).unlink()
|
return super(StockReservation, self).unlink()
|
||||||
|
|
||||||
@api.onchange('product_id')
|
@api.onchange("product_id")
|
||||||
def _onchange_product_id(self):
|
def _onchange_product_id(self):
|
||||||
""" set product_uom and name from product onchange """
|
""" set product_uom and name from product onchange """
|
||||||
# save value before reading of self.move_id as this last one erase
|
# save value before reading of self.move_id as this last one erase
|
||||||
# product_id value
|
# product_id value
|
||||||
move = self.move_id or self.env['stock.move'].new(
|
move = self.move_id or self.env["stock.move"].new(
|
||||||
{'product_id': self.product_id})
|
{"product_id": self.product_id}
|
||||||
|
)
|
||||||
move.onchange_product_id()
|
move.onchange_product_id()
|
||||||
self.name = move.name
|
self.name = move.name
|
||||||
self.product_uom = move.product_uom
|
self.product_uom = move.product_uom
|
||||||
|
|
||||||
@api.onchange('product_uom_qty')
|
@api.onchange("product_uom_qty")
|
||||||
def _onchange_quantity(self):
|
def _onchange_quantity(self):
|
||||||
""" On change of product quantity avoid negative quantities """
|
""" On change of product quantity avoid negative quantities """
|
||||||
if not self.product_id or self.product_uom_qty <= 0.0:
|
if not self.product_id or self.product_uom_qty <= 0.0:
|
||||||
@@ -187,13 +191,12 @@ class StockReservation(models.Model):
|
|||||||
@api.multi
|
@api.multi
|
||||||
def open_move(self):
|
def open_move(self):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
action = self.env.ref('stock.stock_move_action')
|
action = self.env.ref("stock.stock_move_action")
|
||||||
action_dict = action.read()[0]
|
action_dict = action.read()[0]
|
||||||
action_dict['name'] = _('Reservation Move')
|
action_dict["name"] = _("Reservation Move")
|
||||||
# open directly in the form view
|
# open directly in the form view
|
||||||
view_id = self.env.ref('stock.view_move_form').id
|
view_id = self.env.ref("stock.view_move_form").id
|
||||||
action_dict.update(
|
action_dict.update(
|
||||||
views=[(view_id, 'form')],
|
views=[(view_id, "form")], res_id=self.move_id.id,
|
||||||
res_id=self.move_id.id,
|
)
|
||||||
)
|
|
||||||
return action_dict
|
return action_dict
|
||||||
|
|||||||
@@ -1,16 +1,12 @@
|
|||||||
-
|
- I force recomputation of stock.location parent left/right
|
||||||
I force recomputation of stock.location parent left/right
|
- ? !python {model: stock.location}
|
||||||
-
|
|
||||||
!python {model: stock.location}:
|
|
||||||
# we need this because when running the tests at install time as is done on
|
# 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
|
# Travis, the hook performing this operation for the new stock reservation
|
||||||
# location is run after the test execution. This causes the stock level
|
# location is run after the test execution. This causes the stock level
|
||||||
# computation to be wrong at the time the tests are run.
|
# computation to be wrong at the time the tests are run.
|
||||||
self._parent_store_compute()
|
: self._parent_store_compute()
|
||||||
-
|
- I create a product to test the stock reservation
|
||||||
I create a product to test the stock reservation
|
- !record {model: product.product, id: product_sorbet}:
|
||||||
-
|
|
||||||
!record {model: product.product, id: product_sorbet}:
|
|
||||||
default_code: 001SORBET
|
default_code: 001SORBET
|
||||||
name: Sorbet
|
name: Sorbet
|
||||||
type: product
|
type: product
|
||||||
@@ -19,137 +15,96 @@
|
|||||||
standard_price: 70.0
|
standard_price: 70.0
|
||||||
uom_id: product.product_uom_kgm
|
uom_id: product.product_uom_kgm
|
||||||
uom_po_id: product.product_uom_kgm
|
uom_po_id: product.product_uom_kgm
|
||||||
-
|
- I create a stock orderpoint for the product
|
||||||
I create a stock orderpoint for the product
|
- !record {model: stock.warehouse.orderpoint, id: sorbet_orderpoint}:
|
||||||
-
|
|
||||||
!record {model: stock.warehouse.orderpoint, id: sorbet_orderpoint}:
|
|
||||||
warehouse_id: stock.warehouse0
|
warehouse_id: stock.warehouse0
|
||||||
location_id: stock.stock_location_stock
|
location_id: stock.stock_location_stock
|
||||||
product_id: product_sorbet
|
product_id: product_sorbet
|
||||||
product_uom: product.product_uom_kgm
|
product_uom: product.product_uom_kgm
|
||||||
product_min_qty: 4.0
|
product_min_qty: 4.0
|
||||||
product_max_qty: 15.0
|
product_max_qty: 15.0
|
||||||
-
|
- I update the current stock of the Sorbet with 10 kgm
|
||||||
I update the current stock of the Sorbet with 10 kgm
|
- !record {model: stock.change.product.qty, id: change_qty}:
|
||||||
-
|
|
||||||
!record {model: stock.change.product.qty, id: change_qty}:
|
|
||||||
new_quantity: 10
|
new_quantity: 10
|
||||||
product_id: product_sorbet
|
product_id: product_sorbet
|
||||||
-
|
- !python {model: stock.change.product.qty}: |
|
||||||
!python {model: stock.change.product.qty}: |
|
|
||||||
self.browse(ref('change_qty')).change_product_qty()
|
self.browse(ref('change_qty')).change_product_qty()
|
||||||
-
|
- I check Virtual stock of Sorbet after update stock.
|
||||||
I check Virtual stock of Sorbet after update stock.
|
- !python {model: product.product, id: product_sorbet}: |
|
||||||
-
|
|
||||||
!python {model: product.product, id: product_sorbet}: |
|
|
||||||
assert self.virtual_available == 10, "Stock is not updated."
|
assert self.virtual_available == 10, "Stock is not updated."
|
||||||
-
|
- I create a stock reservation for 6 kgm
|
||||||
I create a stock reservation for 6 kgm
|
- !record {model: stock.reservation, id: reserv_sorbet1}:
|
||||||
-
|
|
||||||
!record {model: stock.reservation, id: reserv_sorbet1}:
|
|
||||||
product_id: product_sorbet
|
product_id: product_sorbet
|
||||||
product_uom_qty: 6.0
|
product_uom_qty: 6.0
|
||||||
product_uom: product.product_uom_kgm
|
product_uom: product.product_uom_kgm
|
||||||
name: reserve 6 kg of sorbet for test
|
name: reserve 6 kg of sorbet for test
|
||||||
-
|
- I confirm the reservation
|
||||||
I confirm the reservation
|
- !python {model: stock.reservation}: |
|
||||||
-
|
|
||||||
!python {model: stock.reservation}: |
|
|
||||||
self.browse(ref('reserv_sorbet1')).reserve()
|
self.browse(ref('reserv_sorbet1')).reserve()
|
||||||
-
|
- I create a stock reservation for 500g
|
||||||
I create a stock reservation for 500g
|
- !record {model: stock.reservation, id: reserv_sorbet2}:
|
||||||
-
|
|
||||||
!record {model: stock.reservation, id: reserv_sorbet2}:
|
|
||||||
product_id: product_sorbet
|
product_id: product_sorbet
|
||||||
product_uom_qty: 500
|
product_uom_qty: 500
|
||||||
product_uom: product.product_uom_gram
|
product_uom: product.product_uom_gram
|
||||||
name: reserve 500g of sorbet for test
|
name: reserve 500g of sorbet for test
|
||||||
-
|
- I confirm the reservation
|
||||||
I confirm the reservation
|
- !python {model: stock.reservation, id: reserv_sorbet2}: |
|
||||||
-
|
|
||||||
!python {model: stock.reservation, id: reserv_sorbet2}: |
|
|
||||||
self.reserve()
|
self.reserve()
|
||||||
-
|
- I check the reserved amount of the product and the template
|
||||||
I check the reserved amount of the product and the template
|
- !python {model: product.product, id: product_sorbet}: |
|
||||||
-
|
|
||||||
!python {model: product.product, id: product_sorbet}: |
|
|
||||||
assert 6.5 == self.reservation_count
|
assert 6.5 == self.reservation_count
|
||||||
assert 6.5 == self.product_tmpl_id.reservation_count
|
assert 6.5 == self.product_tmpl_id.reservation_count
|
||||||
-
|
- Then the reservation should be assigned and have reserved a quant
|
||||||
Then the reservation should be assigned and have reserved a quant
|
- !python {model: stock.reservation, id: reserv_sorbet2}: |
|
||||||
-
|
|
||||||
!python {model: stock.reservation, id: reserv_sorbet2}: |
|
|
||||||
assert 'assigned' == self.state
|
assert 'assigned' == self.state
|
||||||
assert 1 == len(self.reserved_quant_ids)
|
assert 1 == len(self.reserved_quant_ids)
|
||||||
-
|
- I check Virtual stock of Sorbet after update reservation
|
||||||
I check Virtual stock of Sorbet after update reservation
|
- !python {model: product.product, id: product_sorbet}: |
|
||||||
-
|
|
||||||
!python {model: product.product, id: product_sorbet}: |
|
|
||||||
assert 3.5 == self.virtual_available
|
assert 3.5 == self.virtual_available
|
||||||
-
|
- I run the scheduler
|
||||||
I run the scheduler
|
- !python {model: procurement.order}: |
|
||||||
-
|
|
||||||
!python {model: procurement.order}: |
|
|
||||||
self.run_scheduler()
|
self.run_scheduler()
|
||||||
-
|
- The procurement linked to the orderpoint must be in exception (no routes configured)
|
||||||
The procurement linked to the orderpoint must be in exception (no routes configured)
|
- !python {model: stock.warehouse.orderpoint}: |
|
||||||
-
|
|
||||||
!python {model: stock.warehouse.orderpoint}: |
|
|
||||||
orderpoint = self.browse(ref('stock_reserve.sorbet_orderpoint'))
|
orderpoint = self.browse(ref('stock_reserve.sorbet_orderpoint'))
|
||||||
assert orderpoint.procurement_ids[0].state == 'exception', 'procurement must be in exception as there is no rule for procurement'
|
assert orderpoint.procurement_ids[0].state == 'exception', 'procurement must be in exception as there is no rule for procurement'
|
||||||
import math
|
import math
|
||||||
assert orderpoint.procurement_ids[0].product_qty == math.ceil(15 - 3.5), 'wrong product qty ordered'
|
assert orderpoint.procurement_ids[0].product_qty == math.ceil(15 - 3.5), 'wrong product qty ordered'
|
||||||
-
|
- I release the reservation
|
||||||
I release the reservation
|
- !python {model: stock.reservation}: |
|
||||||
-
|
|
||||||
!python {model: stock.reservation}: |
|
|
||||||
self.browse(ref('reserv_sorbet1')).release()
|
self.browse(ref('reserv_sorbet1')).release()
|
||||||
-
|
- I check Virtual stock of Sorbet after update reservation
|
||||||
I check Virtual stock of Sorbet after update reservation
|
- !python {model: product.product}: |
|
||||||
-
|
|
||||||
!python {model: product.product}: |
|
|
||||||
product = self.browse(ref('stock_reserve.product_sorbet'))
|
product = self.browse(ref('stock_reserve.product_sorbet'))
|
||||||
assert product.virtual_available == 9.5, "Stock is not updated."
|
assert product.virtual_available == 9.5, "Stock is not updated."
|
||||||
-
|
- I set the validity of the second reservation to yesterday
|
||||||
I set the validity of the second reservation to yesterday
|
- !python {model: stock.reservation}: |
|
||||||
-
|
|
||||||
!python {model: stock.reservation}: |
|
|
||||||
import datetime
|
import datetime
|
||||||
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT
|
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT
|
||||||
yesterday = datetime.date.today() - datetime.timedelta(days=1)
|
yesterday = datetime.date.today() - datetime.timedelta(days=1)
|
||||||
yesterday = yesterday.strftime(DEFAULT_SERVER_DATE_FORMAT)
|
yesterday = yesterday.strftime(DEFAULT_SERVER_DATE_FORMAT)
|
||||||
self.browse(ref('reserv_sorbet2')).write({'date_validity': yesterday})
|
self.browse(ref('reserv_sorbet2')).write({'date_validity': yesterday})
|
||||||
-
|
- I call the function releasing expired reservations
|
||||||
I call the function releasing expired reservations
|
- !python {model: stock.reservation}: |
|
||||||
-
|
|
||||||
!python {model: stock.reservation}: |
|
|
||||||
self.release_validity_exceeded()
|
self.release_validity_exceeded()
|
||||||
-
|
- I check Virtual stock of Sorbet after update reservation
|
||||||
I check Virtual stock of Sorbet after update reservation
|
- !python {model: product.product}: |
|
||||||
-
|
|
||||||
!python {model: product.product}: |
|
|
||||||
product = self.browse(ref('stock_reserve.product_sorbet'))
|
product = self.browse(ref('stock_reserve.product_sorbet'))
|
||||||
product.refresh()
|
product.refresh()
|
||||||
assert product.virtual_available == 10.0, "Stock is not updated."
|
assert product.virtual_available == 10.0, "Stock is not updated."
|
||||||
|
|
||||||
-
|
- I create a stock reservation for 3 kgm
|
||||||
I create a stock reservation for 3 kgm
|
- !record {model: stock.reservation, id: reserv_sorbet3}:
|
||||||
-
|
|
||||||
!record {model: stock.reservation, id: reserv_sorbet3}:
|
|
||||||
product_id: product_sorbet
|
product_id: product_sorbet
|
||||||
product_uom_qty: 3.0
|
product_uom_qty: 3.0
|
||||||
product_uom: product.product_uom_kgm
|
product_uom: product.product_uom_kgm
|
||||||
name: reserve 3 kg of sorbet for test (release on unlink)
|
name: reserve 3 kg of sorbet for test (release on unlink)
|
||||||
-
|
- I confirm the reservation
|
||||||
I confirm the reservation
|
- !python {model: stock.reservation}: |
|
||||||
-
|
|
||||||
!python {model: stock.reservation}: |
|
|
||||||
self.browse(ref('reserv_sorbet3')).reserve()
|
self.browse(ref('reserv_sorbet3')).reserve()
|
||||||
|
|
||||||
-
|
- I press the open_move button on reservation and test result
|
||||||
I press the open_move button on reservation and test result
|
- !python {model: stock.reservation}: |
|
||||||
-
|
|
||||||
!python {model: stock.reservation}: |
|
|
||||||
reserv = self.browse(ref('reserv_sorbet3'))
|
reserv = self.browse(ref('reserv_sorbet3'))
|
||||||
move = reserv.move_id
|
move = reserv.move_id
|
||||||
action_dict = reserv.open_move()
|
action_dict = reserv.open_move()
|
||||||
@@ -158,10 +113,8 @@
|
|||||||
assert action_dict['id'] == ref('stock.stock_move_action'), "action not correct"
|
assert action_dict['id'] == ref('stock.stock_move_action'), "action not correct"
|
||||||
assert action_dict['views'][0][0] == ref('stock.view_move_form'), "action view not correct"
|
assert action_dict['views'][0][0] == ref('stock.view_move_form'), "action view not correct"
|
||||||
|
|
||||||
-
|
- I press button 'action_view_reservations' on product variant and test result
|
||||||
I press button 'action_view_reservations' on product variant and test result
|
- !python {model: product.product}: |
|
||||||
-
|
|
||||||
!python {model: product.product}: |
|
|
||||||
product = self.browse(ref('product_sorbet'))
|
product = self.browse(ref('product_sorbet'))
|
||||||
action_dict = product.action_view_reservations()
|
action_dict = product.action_view_reservations()
|
||||||
assert action_dict['res_model'] == 'stock.reservation', "action model is not 'stock.move'"
|
assert action_dict['res_model'] == 'stock.reservation', "action model is not 'stock.move'"
|
||||||
@@ -171,10 +124,8 @@
|
|||||||
assert action_dict['context']['search_default_draft'] == 1, "wrong context"
|
assert action_dict['context']['search_default_draft'] == 1, "wrong context"
|
||||||
assert action_dict['context']['search_default_reserved'] == 1, "wrong context"
|
assert action_dict['context']['search_default_reserved'] == 1, "wrong context"
|
||||||
|
|
||||||
-
|
- I press button 'action_view_reservations' on product template and test result
|
||||||
I press button 'action_view_reservations' on product template and test result
|
- !python {model: product.template}: |
|
||||||
-
|
|
||||||
!python {model: product.template}: |
|
|
||||||
product = self.env['product.product'].browse(ref('product_sorbet'))
|
product = self.env['product.product'].browse(ref('product_sorbet'))
|
||||||
product_tmpl = product.product_tmpl_id
|
product_tmpl = product.product_tmpl_id
|
||||||
product_ids = product_tmpl.mapped('product_variant_ids.id')
|
product_ids = product_tmpl.mapped('product_variant_ids.id')
|
||||||
@@ -188,10 +139,8 @@
|
|||||||
assert action_dict['context']['search_default_draft'] == 1, "wrong context"
|
assert action_dict['context']['search_default_draft'] == 1, "wrong context"
|
||||||
assert action_dict['context']['search_default_reserved'] == 1, "wrong context"
|
assert action_dict['context']['search_default_reserved'] == 1, "wrong context"
|
||||||
|
|
||||||
-
|
- I unlink the reservation
|
||||||
I unlink the reservation
|
- !python {model: stock.reservation}: |
|
||||||
-
|
|
||||||
!python {model: stock.reservation}: |
|
|
||||||
reserv = self.browse(ref('reserv_sorbet3'))
|
reserv = self.browse(ref('reserv_sorbet3'))
|
||||||
move = reserv.move_id
|
move = reserv.move_id
|
||||||
reserv.unlink()
|
reserv.unlink()
|
||||||
|
|||||||
@@ -1,31 +1,47 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<odoo>
|
<odoo>
|
||||||
|
<record model="ir.ui.view" id="product_template_form_view_reservation_button">
|
||||||
<record model="ir.ui.view" id="product_template_form_view_reservation_button">
|
<field name="name">product.template.reservation.button</field>
|
||||||
<field name="name">product.template.reservation.button</field>
|
<field name="model">product.template</field>
|
||||||
<field name="model">product.template</field>
|
<field name="inherit_id" ref="product.product_template_only_form_view" />
|
||||||
<field name="inherit_id" ref="product.product_template_only_form_view"/>
|
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<xpath expr="//div[@name='button_box']" position="inside">
|
<xpath expr="//div[@name='button_box']" position="inside">
|
||||||
<button class="oe_inline oe_stat_button" name="action_view_reservations"
|
<button
|
||||||
type="object" attrs="{'invisible':[('type', '!=', 'product')]}" icon="fa-lock">
|
class="oe_inline oe_stat_button"
|
||||||
<field string="Stock Reservations" name="reservation_count" widget="statinfo" />
|
name="action_view_reservations"
|
||||||
</button>
|
type="object"
|
||||||
</xpath>
|
attrs="{'invisible':[('type', '!=', 'product')]}"
|
||||||
</field>
|
icon="fa-lock"
|
||||||
</record>
|
>
|
||||||
|
<field
|
||||||
<record model="ir.ui.view" id="product_product_form_view_reservation_button">
|
string="Stock Reservations"
|
||||||
<field name="name">product.template.reservation.button</field>
|
name="reservation_count"
|
||||||
<field name="model">product.product</field>
|
widget="statinfo"
|
||||||
<field name="inherit_id" ref="product.product_normal_form_view"/>
|
/>
|
||||||
<field name="arch" type="xml">
|
</button>
|
||||||
<xpath expr="//div[@name='button_box']" position="inside">
|
</xpath>
|
||||||
<button class="oe_inline oe_stat_button" name="action_view_reservations"
|
</field>
|
||||||
type="object" attrs="{'invisible':[('type', '!=', 'product')]}" icon="fa-lock">
|
</record>
|
||||||
<field string="Stock Reservations" name="reservation_count" widget="statinfo" />
|
<record model="ir.ui.view" id="product_product_form_view_reservation_button">
|
||||||
</button>
|
<field name="name">product.template.reservation.button</field>
|
||||||
</xpath>
|
<field name="model">product.product</field>
|
||||||
</field>
|
<field name="inherit_id" ref="product.product_normal_form_view" />
|
||||||
</record>
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//div[@name='button_box']" position="inside">
|
||||||
|
<button
|
||||||
|
class="oe_inline oe_stat_button"
|
||||||
|
name="action_view_reservations"
|
||||||
|
type="object"
|
||||||
|
attrs="{'invisible':[('type', '!=', 'product')]}"
|
||||||
|
icon="fa-lock"
|
||||||
|
>
|
||||||
|
<field
|
||||||
|
string="Stock Reservations"
|
||||||
|
name="reservation_count"
|
||||||
|
widget="statinfo"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -1,140 +1,192 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<odoo>
|
<odoo>
|
||||||
<record id="view_stock_reservation_form" model="ir.ui.view">
|
<record id="view_stock_reservation_form" model="ir.ui.view">
|
||||||
<field name="name">stock.reservation.form</field>
|
<field name="name">stock.reservation.form</field>
|
||||||
<field name="model">stock.reservation</field>
|
<field name="model">stock.reservation</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="Stock Reservations" version="7.0">
|
<form string="Stock Reservations" version="7.0">
|
||||||
<header>
|
<header>
|
||||||
<button name="reserve" type="object"
|
<button
|
||||||
|
name="reserve"
|
||||||
|
type="object"
|
||||||
|
string="Reserve"
|
||||||
|
class="oe_highlight"
|
||||||
|
states="draft"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
name="release"
|
||||||
|
type="object"
|
||||||
|
string="Release"
|
||||||
|
class="oe_highlight"
|
||||||
|
states="assigned,confirmed,done"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
name="open_move"
|
||||||
|
type="object"
|
||||||
|
string="View Reservation Move"
|
||||||
|
/>
|
||||||
|
<field
|
||||||
|
name="state"
|
||||||
|
widget="statusbar"
|
||||||
|
statusbar_visible="draft,assigned"
|
||||||
|
/>
|
||||||
|
</header>
|
||||||
|
<sheet>
|
||||||
|
<group>
|
||||||
|
<group name="main_grp" string="Details">
|
||||||
|
<field name="product_id" />
|
||||||
|
<label for="product_uom_qty" />
|
||||||
|
<div>
|
||||||
|
<field name="product_uom_qty" class="oe_inline" />
|
||||||
|
<field
|
||||||
|
name="product_uom"
|
||||||
|
groups="product.group_uom"
|
||||||
|
class="oe_inline"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<field name="name" />
|
||||||
|
<field name="date_validity" />
|
||||||
|
<field name="create_date" groups="base.group_no_one" />
|
||||||
|
<field
|
||||||
|
name="company_id"
|
||||||
|
groups="base.group_multi_company"
|
||||||
|
widget="selection"
|
||||||
|
/>
|
||||||
|
<field
|
||||||
|
name="restrict_partner_id"
|
||||||
|
groups="stock.group_tracking_owner"
|
||||||
|
/>
|
||||||
|
</group>
|
||||||
|
<group
|
||||||
|
name="location"
|
||||||
|
string="Locations"
|
||||||
|
groups="stock.group_locations"
|
||||||
|
>
|
||||||
|
<field name="location_id" />
|
||||||
|
<field name="location_dest_id" />
|
||||||
|
</group>
|
||||||
|
<group name="note" string="Notes">
|
||||||
|
<field name="note" nolabel="1" />
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
</sheet>
|
||||||
|
</form>
|
||||||
|
</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="arch" type="xml">
|
||||||
|
<tree
|
||||||
|
string="Stock Reservations"
|
||||||
|
version="7.0"
|
||||||
|
colors="blue:state == 'draft';grey:state == 'cancel'"
|
||||||
|
>
|
||||||
|
<field name="name" />
|
||||||
|
<field name="product_id" />
|
||||||
|
<field name="move_id" />
|
||||||
|
<field name="product_uom_qty" sum="Total" />
|
||||||
|
<field name="product_uom" />
|
||||||
|
<field name="date_validity" />
|
||||||
|
<field name="restrict_partner_id" groups="stock.group_tracking_owner" />
|
||||||
|
<field name="location_id" />
|
||||||
|
<field name="state" />
|
||||||
|
<button
|
||||||
|
name="reserve"
|
||||||
|
type="object"
|
||||||
string="Reserve"
|
string="Reserve"
|
||||||
class="oe_highlight"
|
icon="terp-locked"
|
||||||
states="draft"/>
|
states="draft"
|
||||||
<button name="release" type="object"
|
/>
|
||||||
|
<button
|
||||||
|
name="release"
|
||||||
|
type="object"
|
||||||
string="Release"
|
string="Release"
|
||||||
class="oe_highlight"
|
icon="gtk-undo"
|
||||||
states="assigned,confirmed,done"/>
|
states="assigned,confirmed,done"
|
||||||
<button name="open_move" type="object"
|
/>
|
||||||
string="View Reservation Move"/>
|
</tree>
|
||||||
<field name="state" widget="statusbar"
|
</field>
|
||||||
statusbar_visible="draft,assigned"/>
|
</record>
|
||||||
</header>
|
<record id="view_stock_reservation_search" model="ir.ui.view">
|
||||||
<sheet>
|
<field name="name">stock.reservation.search</field>
|
||||||
<group>
|
<field name="model">stock.reservation</field>
|
||||||
<group name="main_grp" string="Details">
|
<field name="arch" type="xml">
|
||||||
<field name="product_id" />
|
<search string="Stock Reservations" version="7.0">
|
||||||
<label for="product_uom_qty" />
|
<filter
|
||||||
<div>
|
name="draft"
|
||||||
<field name="product_uom_qty" class="oe_inline"/>
|
string="Draft"
|
||||||
<field name="product_uom"
|
domain="[('state', '=', 'draft')]"
|
||||||
groups="product.group_uom" class="oe_inline"/>
|
help="Not already reserved"
|
||||||
</div>
|
/>
|
||||||
<field name="name"/>
|
<filter
|
||||||
<field name="date_validity" />
|
name="reserved"
|
||||||
<field name="create_date" groups="base.group_no_one"/>
|
string="Reserved"
|
||||||
<field name="company_id"
|
domain="[('state', '=', 'assigned')]"
|
||||||
groups="base.group_multi_company"
|
help="Moves are reserved."
|
||||||
widget="selection"/>
|
/>
|
||||||
<field name="restrict_partner_id" groups="stock.group_tracking_owner"/>
|
<filter
|
||||||
</group>
|
name="cancel"
|
||||||
<group name="location" string="Locations"
|
string="Released"
|
||||||
groups="stock.group_locations">
|
domain="[('state', '=', 'cancel')]"
|
||||||
<field name="location_id"/>
|
help="Reservations have been released."
|
||||||
<field name="location_dest_id"/>
|
/>
|
||||||
</group>
|
<field name="name" />
|
||||||
<group name="note" string="Notes">
|
<field name="product_id" />
|
||||||
<field name="note" nolabel="1"/>
|
<field name="move_id" />
|
||||||
</group>
|
<field name="restrict_partner_id" groups="stock.group_tracking_owner" />
|
||||||
|
<group expand="0" string="Group By...">
|
||||||
|
<filter
|
||||||
|
string="Status"
|
||||||
|
name="groupby_state"
|
||||||
|
domain="[]"
|
||||||
|
context="{'group_by': 'state'}"
|
||||||
|
/>
|
||||||
|
<filter
|
||||||
|
string="Product"
|
||||||
|
domain="[]"
|
||||||
|
name="groupby_product"
|
||||||
|
context="{'group_by': 'product_id'}"
|
||||||
|
/>
|
||||||
|
<filter
|
||||||
|
string="Product UoM"
|
||||||
|
domain="[]"
|
||||||
|
name="groupby_product_uom"
|
||||||
|
context="{'group_by': 'product_uom'}"
|
||||||
|
/>
|
||||||
|
<filter
|
||||||
|
string="Source Location"
|
||||||
|
domain="[]"
|
||||||
|
name="groupby_location"
|
||||||
|
context="{'group_by': 'location_id'}"
|
||||||
|
/>
|
||||||
</group>
|
</group>
|
||||||
</sheet>
|
</search>
|
||||||
</form>
|
</field>
|
||||||
</field>
|
</record>
|
||||||
</record>
|
<record id="action_stock_reservation_tree" model="ir.actions.act_window">
|
||||||
|
<field name="name">Stock Reservations</field>
|
||||||
<record id="view_stock_reservation_tree" model="ir.ui.view">
|
<field name="res_model">stock.reservation</field>
|
||||||
<field name="name">stock.reservation.tree</field>
|
<field name="type">ir.actions.act_window</field>
|
||||||
<field name="model">stock.reservation</field>
|
<field name="view_id" ref="view_stock_reservation_tree" />
|
||||||
<field name="arch" type="xml">
|
<field name="search_view_id" ref="view_stock_reservation_search" />
|
||||||
<tree string="Stock Reservations" version="7.0"
|
<field name="context">{'search_default_draft': 1,
|
||||||
colors="blue:state == 'draft';grey:state == 'cancel'" >
|
|
||||||
<field name="name" />
|
|
||||||
<field name="product_id" />
|
|
||||||
<field name="move_id" />
|
|
||||||
<field name="product_uom_qty" sum="Total" />
|
|
||||||
<field name="product_uom" />
|
|
||||||
<field name="date_validity" />
|
|
||||||
<field name="restrict_partner_id" groups="stock.group_tracking_owner"/>
|
|
||||||
<field name="location_id" />
|
|
||||||
<field name="state"/>
|
|
||||||
<button name="reserve" type="object"
|
|
||||||
string="Reserve"
|
|
||||||
icon="terp-locked"
|
|
||||||
states="draft"/>
|
|
||||||
<button name="release" type="object"
|
|
||||||
string="Release"
|
|
||||||
icon="gtk-undo"
|
|
||||||
states="assigned,confirmed,done"/>
|
|
||||||
</tree>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="view_stock_reservation_search" model="ir.ui.view">
|
|
||||||
<field name="name">stock.reservation.search</field>
|
|
||||||
<field name="model">stock.reservation</field>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<search string="Stock Reservations" version="7.0">
|
|
||||||
<filter name="draft" string="Draft"
|
|
||||||
domain="[('state', '=', 'draft')]"
|
|
||||||
help="Not already reserved"/>
|
|
||||||
<filter name="reserved" string="Reserved"
|
|
||||||
domain="[('state', '=', 'assigned')]"
|
|
||||||
help="Moves are reserved."/>
|
|
||||||
<filter name="cancel" string="Released"
|
|
||||||
domain="[('state', '=', 'cancel')]"
|
|
||||||
help="Reservations have been released."/>
|
|
||||||
<field name="name" />
|
|
||||||
<field name="product_id" />
|
|
||||||
<field name="move_id" />
|
|
||||||
<field name="restrict_partner_id" groups="stock.group_tracking_owner"/>
|
|
||||||
<group expand="0" string="Group By...">
|
|
||||||
<filter string="Status"
|
|
||||||
name="groupby_state"
|
|
||||||
domain="[]" context="{'group_by': 'state'}"/>
|
|
||||||
<filter string="Product" domain="[]"
|
|
||||||
name="groupby_product"
|
|
||||||
context="{'group_by': 'product_id'}"/>
|
|
||||||
<filter string="Product UoM" domain="[]"
|
|
||||||
name="groupby_product_uom"
|
|
||||||
context="{'group_by': 'product_uom'}"/>
|
|
||||||
<filter string="Source Location" domain="[]"
|
|
||||||
name="groupby_location"
|
|
||||||
context="{'group_by': 'location_id'}"/>
|
|
||||||
</group>
|
|
||||||
</search>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="action_stock_reservation_tree" model="ir.actions.act_window">
|
|
||||||
<field name="name">Stock Reservations</field>
|
|
||||||
<field name="res_model">stock.reservation</field>
|
|
||||||
<field name="type">ir.actions.act_window</field>
|
|
||||||
<field name="view_id" ref="view_stock_reservation_tree"/>
|
|
||||||
<field name="search_view_id" ref="view_stock_reservation_search"/>
|
|
||||||
<field name="context">{'search_default_draft': 1,
|
|
||||||
'search_default_reserved': 1,
|
'search_default_reserved': 1,
|
||||||
'search_default_groupby_product': 1}</field>
|
'search_default_groupby_product': 1}</field>
|
||||||
<field name="help" type="html">
|
<field name="help" type="html">
|
||||||
<p class="oe_view_nocontent_create">
|
<p class="oe_view_nocontent_create">
|
||||||
Click to create a stock reservation.
|
Click to create a stock reservation.
|
||||||
</p><p>
|
</p>
|
||||||
|
<p>
|
||||||
This menu allow you to prepare and reserve some quantities
|
This menu allow you to prepare and reserve some quantities
|
||||||
of products.
|
of products.
|
||||||
</p>
|
</p>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
<menuitem
|
||||||
<menuitem action="action_stock_reservation_tree"
|
action="action_stock_reservation_tree"
|
||||||
id="menu_action_stock_reservation"
|
id="menu_action_stock_reservation"
|
||||||
parent="stock.menu_stock_inventory_control"
|
parent="stock.menu_stock_inventory_control"
|
||||||
sequence="30"/>
|
sequence="30"
|
||||||
|
/>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
Reference in New Issue
Block a user