mirror of
https://github.com/OCA/stock-logistics-warehouse.git
synced 2025-01-21 14:27:28 +02:00
[IMP] stock_request: Add stock request order
This commit is contained in:
@@ -71,6 +71,7 @@ Contributors
|
||||
------------
|
||||
|
||||
* Jordi Ballester (EFICENT) <jordi.ballester@eficent.com>.
|
||||
* Enric Tobella <etobella@creublanca.es>
|
||||
|
||||
Maintainer
|
||||
----------
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
{
|
||||
"name": "Stock Request",
|
||||
"summary": "Internal request for stock",
|
||||
"version": "11.0.1.0.0",
|
||||
"version": "11.0.2.0.0",
|
||||
"license": "LGPL-3",
|
||||
"website": "https://github.com/stock-logistics-warehouse",
|
||||
"author": "Eficent, "
|
||||
@@ -20,7 +20,10 @@
|
||||
"views/stock_request_allocation_views.xml",
|
||||
"views/stock_move_views.xml",
|
||||
"views/stock_picking_views.xml",
|
||||
"data/stock_request_sequence_data.xml"
|
||||
"views/stock_request_order_views.xml",
|
||||
"views/res_config_settings_views.xml",
|
||||
"views/stock_request_menu.xml",
|
||||
"data/stock_request_sequence_data.xml",
|
||||
],
|
||||
"installable": True,
|
||||
}
|
||||
|
||||
@@ -10,5 +10,13 @@
|
||||
<field name="company_id" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record id="seq_stock_request_order" model="ir.sequence">
|
||||
<field name="name">Stock Request Order</field>
|
||||
<field name="code">stock.request.order</field>
|
||||
<field name="prefix">SRO/</field>
|
||||
<field name="padding">5</field>
|
||||
<field name="company_id" eval="False"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
|
||||
from . import stock_request
|
||||
from . import stock_request_allocation
|
||||
from . import stock_request_order
|
||||
from . import stock_move
|
||||
from . import stock_picking
|
||||
from . import procurement_rule
|
||||
from . import stock_move_line
|
||||
from . import res_config_settings
|
||||
|
||||
14
stock_request/models/res_config_settings.py
Normal file
14
stock_request/models/res_config_settings.py
Normal file
@@ -0,0 +1,14 @@
|
||||
# Copyright 2018 Creu Blanca
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class ResConfigSettings(models.TransientModel):
|
||||
_inherit = 'res.config.settings'
|
||||
|
||||
group_stock_request_order = fields.Boolean(
|
||||
implied_group='stock_request.group_stock_request_order')
|
||||
|
||||
module_stock_request_purchase = fields.Boolean(
|
||||
string='Stock requests for purchase')
|
||||
@@ -36,8 +36,9 @@ class StockRequest(models.Model):
|
||||
|
||||
@api.depends('product_id', 'product_uom_id', 'product_uom_qty')
|
||||
def _compute_product_qty(self):
|
||||
self.product_qty = self.product_uom_id._compute_quantity(
|
||||
self.product_uom_qty, self.product_id.uom_id)
|
||||
for rec in self:
|
||||
rec.product_qty = rec.product_uom_id._compute_quantity(
|
||||
rec.product_uom_qty, rec.product_id.uom_id)
|
||||
|
||||
name = fields.Char(
|
||||
'Name', copy=False, required=True, readonly=True,
|
||||
@@ -138,12 +139,24 @@ class StockRequest(models.Model):
|
||||
route_id = fields.Many2one('stock.location.route', string='Route',
|
||||
readonly=True,
|
||||
states={'draft': [('readonly', False)]},
|
||||
domain="[('id', 'in', route_ids)]",
|
||||
ondelete='restrict')
|
||||
|
||||
route_ids = fields.Many2many(
|
||||
'stock.location.route', string='Route',
|
||||
compute='_compute_route_ids',
|
||||
readonly=True,
|
||||
)
|
||||
|
||||
allocation_ids = fields.One2many(comodel_name='stock.request.allocation',
|
||||
inverse_name='stock_request_id',
|
||||
string='Stock Request Allocation')
|
||||
|
||||
order_id = fields.Many2one(
|
||||
'stock.request.order',
|
||||
readonly=True,
|
||||
)
|
||||
|
||||
_sql_constraints = [
|
||||
('name_uniq', 'unique(name, company_id)',
|
||||
'Stock Request name must be unique'),
|
||||
@@ -177,6 +190,21 @@ class StockRequest(models.Model):
|
||||
request.product_id.uom_id._compute_quantity(
|
||||
open_qty, request.product_uom_id)
|
||||
|
||||
@api.depends('product_id', 'warehouse_id', 'location_id')
|
||||
def _compute_route_ids(self):
|
||||
for record in self:
|
||||
routes = self.env['stock.location.route']
|
||||
if record.product_id:
|
||||
routes += record.product_id.mapped(
|
||||
'route_ids') | record.product_id.mapped(
|
||||
'categ_id').mapped('total_route_ids')
|
||||
if record.warehouse_id:
|
||||
routes |= self.env['stock.location.route'].search(
|
||||
[('warehouse_ids', 'in', record.warehouse_id.ids)])
|
||||
parents = record.get_parents().ids
|
||||
record.route_ids = routes.filtered(lambda r: any(
|
||||
p.location_id.id in parents for p in r.pull_ids))
|
||||
|
||||
def get_parents(self):
|
||||
location = self.location_id.sudo()
|
||||
result = location
|
||||
@@ -196,26 +224,65 @@ class StockRequest(models.Model):
|
||||
'same category than the default unit '
|
||||
'of measure of the product'))
|
||||
|
||||
def _get_valid_routes(self):
|
||||
routes = self.env['stock.location.route']
|
||||
if self.product_id:
|
||||
routes += self.product_id.mapped(
|
||||
'route_ids') | self.product_id.mapped(
|
||||
'categ_id').mapped('total_route_ids')
|
||||
if self.warehouse_id:
|
||||
routes |= self.env['stock.location.route'].search(
|
||||
[('warehouse_ids', 'in', self.warehouse_id.ids)])
|
||||
parents = self.get_parents().ids
|
||||
routes = routes.filtered(lambda r: any(
|
||||
p.location_id.id in parents for p in r.pull_ids))
|
||||
return routes
|
||||
@api.constrains('order_id', 'requested_by')
|
||||
def check_order_requested_by(self):
|
||||
if self.order_id and self.order_id.requested_by != self.requested_by:
|
||||
raise ValidationError(_(
|
||||
'Requested by must be equal to the order'
|
||||
))
|
||||
|
||||
@api.constrains('order_id', 'warehouse_id')
|
||||
def check_order_warehouse_id(self):
|
||||
if self.order_id and self.order_id.warehouse_id != self.warehouse_id:
|
||||
raise ValidationError(_(
|
||||
'Warehouse must be equal to the order'
|
||||
))
|
||||
|
||||
@api.constrains('order_id', 'location_id')
|
||||
def check_order_location(self):
|
||||
if self.order_id and self.order_id.location_id != self.location_id:
|
||||
raise ValidationError(_(
|
||||
'Location must be equal to the order'
|
||||
))
|
||||
|
||||
@api.constrains('order_id', 'procurement_group_id')
|
||||
def check_order_procurement_group(self):
|
||||
if (
|
||||
self.order_id and
|
||||
self.order_id.procurement_group_id != self.procurement_group_id
|
||||
):
|
||||
raise ValidationError(_(
|
||||
'Procurement group must be equal to the order'
|
||||
))
|
||||
|
||||
@api.constrains('order_id', 'company_id')
|
||||
def check_order_company(self):
|
||||
if self.order_id and self.order_id.company_id != self.company_id:
|
||||
raise ValidationError(_(
|
||||
'Company must be equal to the order'
|
||||
))
|
||||
|
||||
@api.constrains('order_id', 'expected_date')
|
||||
def check_order_expected_date(self):
|
||||
if self.order_id and self.order_id.expected_date != self.expected_date:
|
||||
raise ValidationError(_(
|
||||
'Expected date must be equal to the order'
|
||||
))
|
||||
|
||||
@api.constrains('order_id', 'picking_policy')
|
||||
def check_order_picking_policy(self):
|
||||
if (
|
||||
self.order_id and
|
||||
self.order_id.picking_policy != self.picking_policy
|
||||
):
|
||||
raise ValidationError(_(
|
||||
'The picking policy must be equal to the order'
|
||||
))
|
||||
|
||||
@api.onchange('warehouse_id')
|
||||
def onchange_warehouse_id(self):
|
||||
""" Finds location id for changed warehouse. """
|
||||
res = {'domain': {}}
|
||||
routes = self._get_valid_routes()
|
||||
res['domain']['route_id'] = [('id', 'in', routes.ids)]
|
||||
if self.warehouse_id:
|
||||
# search with sudo because the user may not have permissions
|
||||
loc_wh = self.location_id.sudo().get_warehouse()
|
||||
@@ -228,8 +295,6 @@ class StockRequest(models.Model):
|
||||
@api.onchange('location_id')
|
||||
def onchange_location_id(self):
|
||||
res = {'domain': {}}
|
||||
routes = self._get_valid_routes()
|
||||
res['domain']['route_id'] = [('id', 'in', routes.ids)]
|
||||
if self.location_id:
|
||||
loc_wh = self.location_id.get_warehouse()
|
||||
if self.warehouse_id != loc_wh:
|
||||
@@ -254,8 +319,6 @@ class StockRequest(models.Model):
|
||||
@api.onchange('product_id')
|
||||
def onchange_product_id(self):
|
||||
res = {'domain': {}}
|
||||
routes = self._get_valid_routes()
|
||||
res['domain']['route_id'] = [('id', 'in', routes.ids)]
|
||||
if self.product_id:
|
||||
self.product_uom_id = self.product_id.uom_id.id
|
||||
res['domain']['product_uom_id'] = [
|
||||
@@ -285,6 +348,8 @@ class StockRequest(models.Model):
|
||||
|
||||
def action_done(self):
|
||||
self.state = 'done'
|
||||
if self.order_id:
|
||||
self.order_id.check_done()
|
||||
return True
|
||||
|
||||
def check_done(self):
|
||||
@@ -373,3 +438,9 @@ class StockRequest(models.Model):
|
||||
(self.env.ref('stock.view_picking_form').id, 'form')]
|
||||
action['res_id'] = pickings.id
|
||||
return action
|
||||
|
||||
@api.multi
|
||||
def unlink(self):
|
||||
if self.filtered(lambda r: r.state != 'draft'):
|
||||
raise UserError(_('Only requests on draft state can be unlinked'))
|
||||
return super(StockRequest, self).unlink()
|
||||
|
||||
249
stock_request/models/stock_request_order.py
Normal file
249
stock_request/models/stock_request_order.py
Normal file
@@ -0,0 +1,249 @@
|
||||
# Copyright 2018 Creu Blanca
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
REQUEST_STATES = [
|
||||
('draft', 'Draft'),
|
||||
('open', 'In progress'),
|
||||
('done', 'Done'),
|
||||
('cancel', 'Cancelled')]
|
||||
|
||||
|
||||
class StockRequestOrder(models.Model):
|
||||
_name = 'stock.request.order'
|
||||
_description = 'Stock Request Order'
|
||||
_inherit = ['mail.thread', 'mail.activity.mixin']
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields):
|
||||
res = super().default_get(fields)
|
||||
warehouse = None
|
||||
if 'warehouse_id' not in res and res.get('company_id'):
|
||||
warehouse = self.env['stock.warehouse'].search(
|
||||
[('company_id', '=', res['company_id'])], limit=1)
|
||||
if warehouse:
|
||||
res['warehouse_id'] = warehouse.id
|
||||
res['location_id'] = warehouse.lot_stock_id.id
|
||||
return res
|
||||
|
||||
def _get_default_requested_by(self):
|
||||
return self.env['res.users'].browse(self.env.uid)
|
||||
|
||||
name = fields.Char(
|
||||
'Name', copy=False, required=True, readonly=True,
|
||||
states={'draft': [('readonly', False)]},
|
||||
default=lambda self: self.env['ir.sequence'].next_by_code(
|
||||
'stock.request.order'))
|
||||
state = fields.Selection(selection=REQUEST_STATES, string='Status',
|
||||
copy=False, default='draft', index=True,
|
||||
readonly=True, track_visibility='onchange',
|
||||
)
|
||||
requested_by = fields.Many2one(
|
||||
'res.users', 'Requested by', required=True,
|
||||
track_visibility='onchange',
|
||||
default=lambda s: s._get_default_requested_by(),
|
||||
)
|
||||
warehouse_id = fields.Many2one(
|
||||
'stock.warehouse', 'Warehouse', readonly=True,
|
||||
ondelete="cascade", required=True,
|
||||
states={'draft': [('readonly', False)]})
|
||||
location_id = fields.Many2one(
|
||||
'stock.location', 'Location', readonly=True,
|
||||
domain=[('usage', 'in', ['internal', 'transit'])],
|
||||
ondelete="cascade", required=True,
|
||||
states={'draft': [('readonly', False)]},
|
||||
)
|
||||
procurement_group_id = fields.Many2one(
|
||||
'procurement.group', 'Procurement Group', readonly=True,
|
||||
states={'draft': [('readonly', False)]},
|
||||
help="Moves created through this stock request will be put in this "
|
||||
"procurement group. If none is given, the moves generated by "
|
||||
"procurement rules will be grouped into one big picking.",
|
||||
)
|
||||
company_id = fields.Many2one(
|
||||
'res.company', 'Company', required=True, readonly=True,
|
||||
states={'draft': [('readonly', False)]},
|
||||
default=lambda self: self.env['res.company']._company_default_get(
|
||||
'stock.request.order'),
|
||||
)
|
||||
expected_date = fields.Datetime(
|
||||
'Expected date', default=fields.Datetime.now, index=True,
|
||||
required=True, readonly=True,
|
||||
states={'draft': [('readonly', False)]},
|
||||
help="Date when you expect to receive the goods.",
|
||||
)
|
||||
picking_policy = fields.Selection([
|
||||
('direct', 'Receive each product when available'),
|
||||
('one', 'Receive all products at once')],
|
||||
string='Shipping Policy', required=True, readonly=True,
|
||||
states={'draft': [('readonly', False)]},
|
||||
default='direct',
|
||||
)
|
||||
move_ids = fields.One2many(comodel_name='stock.move',
|
||||
compute='_compute_move_ids',
|
||||
string='Stock Moves', readonly=True,
|
||||
)
|
||||
picking_ids = fields.One2many('stock.picking',
|
||||
compute='_compute_picking_ids',
|
||||
string='Pickings', readonly=True,
|
||||
)
|
||||
picking_count = fields.Integer(string='Delivery Orders',
|
||||
compute='_compute_picking_ids',
|
||||
readonly=True,
|
||||
)
|
||||
stock_request_ids = fields.One2many(
|
||||
'stock.request',
|
||||
inverse_name='order_id',
|
||||
)
|
||||
stock_request_count = fields.Integer(
|
||||
string='Stock requests',
|
||||
compute='_compute_stock_request_count',
|
||||
readonly=True,
|
||||
)
|
||||
|
||||
_sql_constraints = [
|
||||
('name_uniq', 'unique(name, company_id)',
|
||||
'Stock Request name must be unique'),
|
||||
]
|
||||
|
||||
@api.depends('stock_request_ids.allocation_ids')
|
||||
def _compute_picking_ids(self):
|
||||
for record in self:
|
||||
record.picking_ids = record.stock_request_ids.mapped('picking_ids')
|
||||
record.picking_count = len(record.picking_ids)
|
||||
|
||||
@api.depends('stock_request_ids')
|
||||
def _compute_move_ids(self):
|
||||
for record in self:
|
||||
record.move_ids = record.stock_request_ids.mapped('move_ids')
|
||||
|
||||
@api.depends('stock_request_ids')
|
||||
def _compute_stock_request_count(self):
|
||||
for record in self:
|
||||
record.stock_request_count = len(record.stock_request_ids)
|
||||
|
||||
@api.onchange('requested_by')
|
||||
def onchange_requested_by(self):
|
||||
self.change_childs()
|
||||
|
||||
@api.onchange('expected_date')
|
||||
def onchange_expected_date(self):
|
||||
self.change_childs()
|
||||
|
||||
@api.onchange('picking_policy')
|
||||
def onchange_picking_policy(self):
|
||||
self.change_childs()
|
||||
|
||||
@api.onchange('location_id')
|
||||
def onchange_location_id(self):
|
||||
if self.location_id:
|
||||
loc_wh = self.location_id.sudo().get_warehouse()
|
||||
if loc_wh and self.warehouse_id != loc_wh:
|
||||
self.warehouse_id = loc_wh
|
||||
self.with_context(
|
||||
no_change_childs=True).onchange_warehouse_id()
|
||||
self.change_childs()
|
||||
|
||||
@api.onchange('warehouse_id')
|
||||
def onchange_warehouse_id(self):
|
||||
if self.warehouse_id:
|
||||
# search with sudo because the user may not have permissions
|
||||
loc_wh = self.location_id.sudo().get_warehouse()
|
||||
if self.warehouse_id != loc_wh:
|
||||
self.location_id = self.warehouse_id.sudo().lot_stock_id
|
||||
self.with_context(no_change_childs=True).onchange_location_id()
|
||||
if self.warehouse_id.sudo().company_id != self.company_id:
|
||||
self.company_id = self.warehouse_id.company_id
|
||||
self.with_context(no_change_childs=True).onchange_company_id()
|
||||
self.change_childs()
|
||||
|
||||
@api.onchange('procurement_group_id')
|
||||
def onchange_procurement_group_id(self):
|
||||
self.change_childs()
|
||||
|
||||
@api.onchange('company_id')
|
||||
def onchange_company_id(self):
|
||||
if self.company_id and (
|
||||
not self.warehouse_id or
|
||||
self.warehouse_id.sudo().company_id != self.company_id
|
||||
):
|
||||
self.warehouse_id = self.env['stock.warehouse'].search(
|
||||
[('company_id', '=', self.company_id.id)], limit=1)
|
||||
self.with_context(no_change_childs=True).onchange_warehouse_id()
|
||||
self.change_childs()
|
||||
return {
|
||||
'domain': {
|
||||
'warehouse_id': [('company_id', '=', self.company_id.id)]}}
|
||||
|
||||
def change_childs(self):
|
||||
if not self._context.get('no_change_childs', False):
|
||||
for line in self.stock_request_ids:
|
||||
line.warehouse_id = self.warehouse_id
|
||||
line.location_id = self.location_id
|
||||
line.company_id = self.company_id
|
||||
line.picking_policy = self.picking_policy
|
||||
line.expected_date = self.expected_date
|
||||
line.requested_by = self.requested_by
|
||||
line.procurement_group_id = self.procurement_group_id
|
||||
|
||||
@api.multi
|
||||
def action_confirm(self):
|
||||
for line in self.stock_request_ids:
|
||||
line.action_confirm()
|
||||
self.state = 'open'
|
||||
return True
|
||||
|
||||
def action_draft(self):
|
||||
for line in self.stock_request_ids:
|
||||
line.action_draft()
|
||||
self.state = 'draft'
|
||||
return True
|
||||
|
||||
def action_cancel(self):
|
||||
for line in self.stock_request_ids:
|
||||
line.action_cancel()
|
||||
self.state = 'cancel'
|
||||
return True
|
||||
|
||||
def action_done(self):
|
||||
self.state = 'done'
|
||||
return True
|
||||
|
||||
def check_done(self):
|
||||
if not self.stock_request_ids.filtered(lambda r: r.state != 'done'):
|
||||
self.action_done()
|
||||
return
|
||||
|
||||
@api.multi
|
||||
def action_view_transfer(self):
|
||||
action = self.env.ref('stock.action_picking_tree_all').read()[0]
|
||||
|
||||
pickings = self.mapped('picking_ids')
|
||||
if len(pickings) > 1:
|
||||
action['domain'] = [('id', 'in', pickings.ids)]
|
||||
elif pickings:
|
||||
action['views'] = [
|
||||
(self.env.ref('stock.view_picking_form').id, 'form')]
|
||||
action['res_id'] = pickings.id
|
||||
return action
|
||||
|
||||
@api.multi
|
||||
def action_view_stock_requests(self):
|
||||
action = self.env.ref(
|
||||
'stock_request.action_stock_request_form').read()[0]
|
||||
if len(self.stock_request_ids) > 1:
|
||||
action['domain'] = [('order_id', 'in', self.ids)]
|
||||
elif self.stock_request_ids:
|
||||
action['views'] = [
|
||||
(self.env.ref(
|
||||
'stock_request.view_stock_request_form').id, 'form')]
|
||||
action['res_id'] = self.stock_request_ids.id
|
||||
return action
|
||||
|
||||
@api.multi
|
||||
def unlink(self):
|
||||
if self.filtered(lambda r: r.state != 'draft'):
|
||||
raise UserError(_('Only orders on draft state can be unlinked'))
|
||||
return super().unlink()
|
||||
@@ -5,9 +5,9 @@ access_stock_request_stock_user,stock.request stock user,model_stock_request,sto
|
||||
access_stock_request_allocation_user,stock request allocation user,model_stock_request_allocation,group_stock_request_user,1,1,1,1
|
||||
access_stock_request_allocation_manager,stock request allocation manager,model_stock_request_allocation,group_stock_request_manager,1,1,1,1
|
||||
access_stock_request_allocation_stock_user,stock.request.allocation stock user,model_stock_request_allocation,stock.group_stock_user,1,0,0,0
|
||||
access_stock_request_manager,stock request manager,model_stock_request,group_stock_request_manager,1,1,1,1
|
||||
access_stock_warehouse_user,stock.warehouse.user,stock.model_stock_warehouse,group_stock_request_user,1,0,0,0
|
||||
access_stock_location_user,stock.location.user,stock.model_stock_location,group_stock_request_user,1,0,0,0
|
||||
access_stock_location_request_manager,stock.location request manager,stock.model_stock_location,group_stock_request_manager,1,0,0,0
|
||||
access_procurement_rule_request_manager,procurement_rule request_manager,stock.model_procurement_rule,group_stock_request_manager,1,0,0,0
|
||||
access_procurement_rule,procurement.rule.flow,stock.model_procurement_rule,group_stock_request_user,1,0,0,0
|
||||
access_stock_request_order_user,stock request user,model_stock_request_order,stock_request.group_stock_request_user,1,1,1,0
|
||||
access_stock_request_order_manager,stock request manager,model_stock_request_order,stock_request.group_stock_request_manager,1,1,1,1
|
||||
|
||||
|
@@ -21,6 +21,11 @@
|
||||
<field name="category_id" ref="module_category_stock_request"/>
|
||||
</record>
|
||||
|
||||
<record id="group_stock_request_order" model="res.groups">
|
||||
<field name="name">Stock Request Order</field>
|
||||
<field name="category_id" ref="base.module_category_hidden"/>
|
||||
</record>
|
||||
|
||||
<record id="stock.group_stock_user" model="res.groups">
|
||||
<field name="implied_ids"
|
||||
eval="[(4, ref('group_stock_request_user'))]"/>
|
||||
@@ -67,6 +72,46 @@
|
||||
<field name="perm_create" eval="True"/>
|
||||
<field name="perm_unlink" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule" id="stock_request_order_picking_rule">
|
||||
<field name="name">stock_request_order multi-company</field>
|
||||
<field name="model_id" ref="model_stock_request_order"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||
</record>
|
||||
|
||||
<record id="stock_request_order_followers_rule" model="ir.rule">
|
||||
<field name="name">Follow Stock Request Order</field>
|
||||
<field name="model_id" ref="model_stock_request_order"/>
|
||||
<field name="groups" eval="[(6,0, [ref('stock_request.group_stock_request_user')])]"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_unlink" eval="False"/>
|
||||
<field name="domain_force">['|',('requested_by','=',user.id),
|
||||
('message_partner_ids', 'in', [user.partner_id.id])]</field>
|
||||
</record>
|
||||
|
||||
<record id="stock_request_order_rule" model="ir.rule">
|
||||
<field name="name">Stock Request Order User</field>
|
||||
<field name="model_id" ref="model_stock_request_order"/>
|
||||
<field name="groups" eval="[(6,0, [ref('stock_request.group_stock_request_user')])]"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
<field name="perm_create" eval="True"/>
|
||||
<field name="perm_unlink" eval="True"/>
|
||||
<field name="domain_force">[('requested_by','=',user.id)]</field>
|
||||
</record>
|
||||
|
||||
<record id="stock_request_order_manager_rule" model="ir.rule">
|
||||
<field name="name">Stock Request Manager</field>
|
||||
<field name="model_id" ref="model_stock_request_order"/>
|
||||
<field name="groups" eval="[(6,0, [ref('stock_request.group_stock_request_manager')])]"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
<field name="perm_create" eval="True"/>
|
||||
<field name="perm_unlink" eval="True"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 7.3 KiB |
@@ -2,11 +2,10 @@
|
||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl-3.0).
|
||||
|
||||
from odoo.tests import common
|
||||
from odoo import exceptions
|
||||
from odoo import fields, exceptions
|
||||
|
||||
|
||||
class TestStockRequest(common.TransactionCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestStockRequest, self).setUp()
|
||||
|
||||
@@ -92,7 +91,6 @@ class TestStockRequest(common.TransactionCase):
|
||||
})
|
||||
|
||||
def test_defaults(self):
|
||||
|
||||
vals = {
|
||||
'product_id': self.product.id,
|
||||
'product_uom_id': self.product.uom_id.id,
|
||||
@@ -111,6 +109,80 @@ class TestStockRequest(common.TransactionCase):
|
||||
self.assertEqual(
|
||||
stock_request.location_id, self.warehouse.lot_stock_id)
|
||||
|
||||
def test_defaults_order(self):
|
||||
vals = {}
|
||||
order = self.env['stock.request.order'].sudo(
|
||||
self.stock_request_user.id).with_context(
|
||||
company_id=self.main_company.id).create(vals)
|
||||
|
||||
self.assertEqual(
|
||||
order.requested_by, self.stock_request_user)
|
||||
|
||||
self.assertEqual(
|
||||
order.warehouse_id, self.warehouse)
|
||||
|
||||
self.assertEqual(
|
||||
order.location_id, self.warehouse.lot_stock_id)
|
||||
|
||||
def test_onchanges_order(self):
|
||||
vals = {
|
||||
'company_id': self.main_company.id,
|
||||
'warehouse_id': self.warehouse.id,
|
||||
'location_id': self.warehouse.lot_stock_id.id,
|
||||
'stock_request_ids': [(0, 0, {
|
||||
'product_id': self.product.id,
|
||||
'product_uom_id': self.product.uom_id.id,
|
||||
'product_uom_qty': 5.0,
|
||||
'company_id': self.main_company.id,
|
||||
'warehouse_id': self.warehouse.id,
|
||||
'location_id': self.warehouse.lot_stock_id.id,
|
||||
})]
|
||||
}
|
||||
order = self.env['stock.request.order'].sudo(
|
||||
self.stock_request_user).new(vals)
|
||||
self.stock_request_user.company_id = self.company_2
|
||||
order.company_id = self.company_2
|
||||
|
||||
order.onchange_company_id()
|
||||
|
||||
stock_request = order.stock_request_ids
|
||||
self.assertEqual(order.warehouse_id, self.wh2)
|
||||
self.assertEqual(order.location_id, self.wh2.lot_stock_id)
|
||||
self.assertEqual(order.warehouse_id, stock_request.warehouse_id)
|
||||
|
||||
procurement_group = self.env['procurement.group'].create({
|
||||
'name': 'TEST'
|
||||
})
|
||||
order.procurement_group_id = procurement_group
|
||||
order.onchange_procurement_group_id()
|
||||
self.assertEqual(
|
||||
order.procurement_group_id,
|
||||
order.stock_request_ids.procurement_group_id)
|
||||
|
||||
order.procurement_group_id = procurement_group
|
||||
order.onchange_procurement_group_id()
|
||||
self.assertEqual(
|
||||
order.procurement_group_id,
|
||||
order.stock_request_ids.procurement_group_id)
|
||||
order.picking_policy = 'one'
|
||||
|
||||
order.onchange_picking_policy()
|
||||
self.assertEqual(
|
||||
order.picking_policy,
|
||||
order.stock_request_ids.picking_policy)
|
||||
|
||||
order.expected_date = fields.Date.today()
|
||||
order.onchange_expected_date()
|
||||
self.assertEqual(
|
||||
order.expected_date,
|
||||
order.stock_request_ids.expected_date)
|
||||
|
||||
order.requested_by = self.stock_request_manager
|
||||
order.onchange_requested_by()
|
||||
self.assertEqual(
|
||||
order.requested_by,
|
||||
order.stock_request_ids.requested_by)
|
||||
|
||||
def test_onchanges(self):
|
||||
self.product.route_ids = [(6, 0, self.route.ids)]
|
||||
vals = {
|
||||
@@ -123,11 +195,8 @@ class TestStockRequest(common.TransactionCase):
|
||||
stock_request.product_id = self.product
|
||||
vals = stock_request.default_get(['warehouse_id', 'company_id'])
|
||||
stock_request.update(vals)
|
||||
res = stock_request.onchange_product_id()
|
||||
self.assertTrue(res['domain']['route_id'])
|
||||
routes = self.env['stock.location.route'].search(
|
||||
res['domain']['route_id'])
|
||||
self.assertIn(self.route.id, routes.ids)
|
||||
stock_request.onchange_product_id()
|
||||
self.assertIn(self.route.id, stock_request.route_ids.ids)
|
||||
|
||||
self.stock_request_user.company_id = self.company_2
|
||||
stock_request.company_id = self.company_2
|
||||
@@ -162,11 +231,12 @@ class TestStockRequest(common.TransactionCase):
|
||||
|
||||
# Test onchange_warehouse_id
|
||||
wh2_2 = self.env['stock.warehouse'].with_context(
|
||||
company_id=self.company_2.id).create({
|
||||
'name': 'C2_2',
|
||||
'code': 'C2_2',
|
||||
'company_id': self.company_2.id
|
||||
})
|
||||
company_id=self.company_2.id
|
||||
).create({
|
||||
'name': 'C2_2',
|
||||
'code': 'C2_2',
|
||||
'company_id': self.company_2.id
|
||||
})
|
||||
stock_request.warehouse_id = wh2_2
|
||||
stock_request.onchange_warehouse_id()
|
||||
|
||||
@@ -181,6 +251,146 @@ class TestStockRequest(common.TransactionCase):
|
||||
self.assertEqual(
|
||||
stock_request.location_id, self.warehouse.lot_stock_id)
|
||||
|
||||
def test_stock_request_order_validations_01(self):
|
||||
vals = {
|
||||
'company_id': self.main_company.id,
|
||||
'warehouse_id': self.wh2.id,
|
||||
'location_id': self.warehouse.lot_stock_id.id,
|
||||
'stock_request_ids': [(0, 0, {
|
||||
'product_id': self.product.id,
|
||||
'product_uom_id': self.product.uom_id.id,
|
||||
'product_uom_qty': 5.0,
|
||||
'company_id': self.main_company.id,
|
||||
'warehouse_id': self.warehouse.id,
|
||||
'location_id': self.warehouse.lot_stock_id.id,
|
||||
})]
|
||||
}
|
||||
# Select a UoM that is incompatible with the product's UoM
|
||||
with self.assertRaises(exceptions.ValidationError):
|
||||
self.env['stock.request.order'].sudo(
|
||||
self.stock_request_user).create(vals)
|
||||
|
||||
def test_stock_request_order_validations_02(self):
|
||||
vals = {
|
||||
'company_id': self.main_company.id,
|
||||
'warehouse_id': self.warehouse.id,
|
||||
'location_id': self.wh2.lot_stock_id.id,
|
||||
'stock_request_ids': [(0, 0, {
|
||||
'product_id': self.product.id,
|
||||
'product_uom_id': self.product.uom_id.id,
|
||||
'product_uom_qty': 5.0,
|
||||
'company_id': self.main_company.id,
|
||||
'warehouse_id': self.warehouse.id,
|
||||
'location_id': self.warehouse.lot_stock_id.id,
|
||||
})]
|
||||
}
|
||||
# Select a UoM that is incompatible with the product's UoM
|
||||
with self.assertRaises(exceptions.ValidationError):
|
||||
self.env['stock.request.order'].sudo(
|
||||
self.stock_request_user).create(vals)
|
||||
|
||||
def test_stock_request_order_validations_03(self):
|
||||
vals = {
|
||||
'company_id': self.main_company.id,
|
||||
'warehouse_id': self.warehouse.id,
|
||||
'location_id': self.warehouse.lot_stock_id.id,
|
||||
'requested_by': self.stock_request_user.id,
|
||||
'stock_request_ids': [(0, 0, {
|
||||
'product_id': self.product.id,
|
||||
'product_uom_id': self.product.uom_id.id,
|
||||
'product_uom_qty': 5.0,
|
||||
'requested_by': self.stock_request_manager.id,
|
||||
'company_id': self.main_company.id,
|
||||
'warehouse_id': self.warehouse.id,
|
||||
'location_id': self.warehouse.lot_stock_id.id,
|
||||
})]
|
||||
}
|
||||
# Select a UoM that is incompatible with the product's UoM
|
||||
with self.assertRaises(exceptions.ValidationError):
|
||||
self.env['stock.request.order'].sudo(
|
||||
self.stock_request_user).create(vals)
|
||||
|
||||
def test_stock_request_order_validations_04(self):
|
||||
procurement_group = self.env['procurement.group'].create({
|
||||
'name': 'Procurement',
|
||||
})
|
||||
vals = {
|
||||
'company_id': self.main_company.id,
|
||||
'warehouse_id': self.warehouse.id,
|
||||
'location_id': self.warehouse.lot_stock_id.id,
|
||||
'procurement_group_id': procurement_group.id,
|
||||
'stock_request_ids': [(0, 0, {
|
||||
'product_id': self.product.id,
|
||||
'product_uom_id': self.product.uom_id.id,
|
||||
'product_uom_qty': 5.0,
|
||||
'company_id': self.main_company.id,
|
||||
'warehouse_id': self.warehouse.id,
|
||||
'location_id': self.warehouse.lot_stock_id.id,
|
||||
})]
|
||||
}
|
||||
# Select a UoM that is incompatible with the product's UoM
|
||||
with self.assertRaises(exceptions.ValidationError):
|
||||
self.env['stock.request.order'].sudo(
|
||||
self.stock_request_user).create(vals)
|
||||
|
||||
def test_stock_request_order_validations_05(self):
|
||||
vals = {
|
||||
'company_id': self.main_company.id,
|
||||
'warehouse_id': self.warehouse.id,
|
||||
'location_id': self.warehouse.lot_stock_id.id,
|
||||
'expected_date': fields.Date.today(),
|
||||
'stock_request_ids': [(0, 0, {
|
||||
'product_id': self.product.id,
|
||||
'product_uom_id': self.product.uom_id.id,
|
||||
'product_uom_qty': 5.0,
|
||||
'company_id': self.main_company.id,
|
||||
'warehouse_id': self.warehouse.id,
|
||||
'location_id': self.warehouse.lot_stock_id.id,
|
||||
})]
|
||||
}
|
||||
# Select a UoM that is incompatible with the product's UoM
|
||||
with self.assertRaises(exceptions.ValidationError):
|
||||
self.env['stock.request.order'].sudo(
|
||||
self.stock_request_user).create(vals)
|
||||
|
||||
def test_stock_request_order_validations_06(self):
|
||||
vals = {
|
||||
'company_id': self.company_2.id,
|
||||
'warehouse_id': self.warehouse.id,
|
||||
'location_id': self.warehouse.lot_stock_id.id,
|
||||
'stock_request_ids': [(0, 0, {
|
||||
'product_id': self.product.id,
|
||||
'product_uom_id': self.product.uom_id.id,
|
||||
'product_uom_qty': 5.0,
|
||||
'company_id': self.main_company.id,
|
||||
'warehouse_id': self.warehouse.id,
|
||||
'location_id': self.warehouse.lot_stock_id.id,
|
||||
})]
|
||||
}
|
||||
# Select a UoM that is incompatible with the product's UoM
|
||||
with self.assertRaises(exceptions.ValidationError):
|
||||
self.env['stock.request.order'].sudo().create(vals)
|
||||
|
||||
def test_stock_request_order_validations_07(self):
|
||||
vals = {
|
||||
'company_id': self.main_company.id,
|
||||
'warehouse_id': self.warehouse.id,
|
||||
'location_id': self.warehouse.lot_stock_id.id,
|
||||
'picking_policy': 'one',
|
||||
'stock_request_ids': [(0, 0, {
|
||||
'product_id': self.product.id,
|
||||
'product_uom_id': self.product.uom_id.id,
|
||||
'product_uom_qty': 5.0,
|
||||
'company_id': self.main_company.id,
|
||||
'warehouse_id': self.warehouse.id,
|
||||
'location_id': self.warehouse.lot_stock_id.id,
|
||||
})]
|
||||
}
|
||||
# Select a UoM that is incompatible with the product's UoM
|
||||
with self.assertRaises(exceptions.ValidationError):
|
||||
self.env['stock.request.order'].sudo(
|
||||
self.stock_request_user).create(vals)
|
||||
|
||||
def test_stock_request_validations_01(self):
|
||||
vals = {
|
||||
'product_id': self.product.id,
|
||||
@@ -213,22 +423,32 @@ class TestStockRequest(common.TransactionCase):
|
||||
stock_request.action_confirm()
|
||||
|
||||
def test_create_request_01(self):
|
||||
|
||||
vals = {
|
||||
'product_id': self.product.id,
|
||||
'product_uom_id': self.product.uom_id.id,
|
||||
'product_uom_qty': 5.0,
|
||||
'company_id': self.main_company.id,
|
||||
'warehouse_id': self.warehouse.id,
|
||||
'location_id': self.warehouse.lot_stock_id.id,
|
||||
'stock_request_ids': [(0, 0, {
|
||||
'product_id': self.product.id,
|
||||
'product_uom_id': self.product.uom_id.id,
|
||||
'product_uom_qty': 5.0,
|
||||
'company_id': self.main_company.id,
|
||||
'warehouse_id': self.warehouse.id,
|
||||
'location_id': self.warehouse.lot_stock_id.id,
|
||||
})]
|
||||
}
|
||||
|
||||
stock_request = self.stock_request.sudo(
|
||||
order = self.env['stock.request.order'].sudo(
|
||||
self.stock_request_user).create(vals)
|
||||
|
||||
stock_request = order.stock_request_ids
|
||||
|
||||
self.product.route_ids = [(6, 0, self.route.ids)]
|
||||
stock_request.action_confirm()
|
||||
order.action_confirm()
|
||||
self.assertEqual(order.state, 'open')
|
||||
self.assertEqual(stock_request.state, 'open')
|
||||
|
||||
self.assertEqual(len(order.sudo().picking_ids), 1)
|
||||
self.assertEqual(len(order.sudo().move_ids), 1)
|
||||
self.assertEqual(len(stock_request.sudo().picking_ids), 1)
|
||||
self.assertEqual(len(stock_request.sudo().move_ids), 1)
|
||||
self.assertEqual(stock_request.sudo().move_ids[0].location_dest_id,
|
||||
@@ -250,6 +470,7 @@ class TestStockRequest(common.TransactionCase):
|
||||
self.assertEqual(stock_request.qty_in_progress, 0.0)
|
||||
self.assertEqual(stock_request.qty_done,
|
||||
stock_request.product_uom_qty)
|
||||
self.assertEqual(order.state, 'done')
|
||||
self.assertEqual(stock_request.state, 'done')
|
||||
|
||||
def test_create_request_02(self):
|
||||
@@ -330,19 +551,27 @@ class TestStockRequest(common.TransactionCase):
|
||||
|
||||
def test_cancel_request(self):
|
||||
vals = {
|
||||
'product_id': self.product.id,
|
||||
'product_uom_id': self.product.uom_id.id,
|
||||
'product_uom_qty': 5.0,
|
||||
'company_id': self.main_company.id,
|
||||
'warehouse_id': self.warehouse.id,
|
||||
'location_id': self.warehouse.lot_stock_id.id,
|
||||
'stock_request_ids': [(0, 0, {
|
||||
'product_id': self.product.id,
|
||||
'product_uom_id': self.product.uom_id.id,
|
||||
'product_uom_qty': 5.0,
|
||||
'company_id': self.main_company.id,
|
||||
'warehouse_id': self.warehouse.id,
|
||||
'location_id': self.warehouse.lot_stock_id.id,
|
||||
})]
|
||||
}
|
||||
|
||||
stock_request = self.stock_request.sudo(
|
||||
order = self.env['stock.request.order'].sudo(
|
||||
self.stock_request_user).create(vals)
|
||||
|
||||
self.product.route_ids = [(6, 0, self.route.ids)]
|
||||
stock_request.action_confirm()
|
||||
order.action_confirm()
|
||||
stock_request = order.stock_request_ids
|
||||
self.assertEqual(len(order.sudo().picking_ids), 1)
|
||||
self.assertEqual(len(order.sudo().move_ids), 1)
|
||||
self.assertEqual(len(stock_request.sudo().picking_ids), 1)
|
||||
self.assertEqual(len(stock_request.sudo().move_ids), 1)
|
||||
self.assertEqual(stock_request.sudo().move_ids[0].location_dest_id,
|
||||
@@ -358,37 +587,56 @@ class TestStockRequest(common.TransactionCase):
|
||||
self.assertEqual(stock_request.qty_in_progress, 5.0)
|
||||
self.assertEqual(stock_request.qty_done, 0.0)
|
||||
picking.action_assign()
|
||||
stock_request.action_cancel()
|
||||
order.action_cancel()
|
||||
|
||||
self.assertEqual(stock_request.qty_in_progress, 0.0)
|
||||
self.assertEqual(stock_request.qty_done, 0.0)
|
||||
self.assertEqual(len(stock_request.sudo().picking_ids), 0)
|
||||
|
||||
# Set the request back to draft
|
||||
stock_request.action_draft()
|
||||
|
||||
order.action_draft()
|
||||
self.assertEqual(order.state, 'draft')
|
||||
self.assertEqual(stock_request.state, 'draft')
|
||||
|
||||
# Re-confirm. We expect new pickings to be created
|
||||
stock_request.action_confirm()
|
||||
order.action_confirm()
|
||||
self.assertEqual(len(stock_request.sudo().picking_ids), 1)
|
||||
self.assertEqual(len(stock_request.sudo().move_ids), 2)
|
||||
|
||||
def test_view_actions(self):
|
||||
vals = {
|
||||
'product_id': self.product.id,
|
||||
'product_uom_id': self.product.uom_id.id,
|
||||
'product_uom_qty': 5.0,
|
||||
'company_id': self.main_company.id,
|
||||
'warehouse_id': self.warehouse.id,
|
||||
'location_id': self.warehouse.lot_stock_id.id,
|
||||
'stock_request_ids': [(0, 0, {
|
||||
'product_id': self.product.id,
|
||||
'product_uom_id': self.product.uom_id.id,
|
||||
'product_uom_qty': 5.0,
|
||||
'company_id': self.main_company.id,
|
||||
'warehouse_id': self.warehouse.id,
|
||||
'location_id': self.warehouse.lot_stock_id.id,
|
||||
})]
|
||||
}
|
||||
|
||||
stock_request = self.stock_request.sudo().create(vals)
|
||||
order = self.env['stock.request.order'].sudo().create(vals)
|
||||
self.product.route_ids = [(6, 0, self.route.ids)]
|
||||
stock_request.action_confirm()
|
||||
action = stock_request.action_view_transfer()
|
||||
|
||||
order.action_confirm()
|
||||
stock_request = order.stock_request_ids
|
||||
self.assertTrue(stock_request.picking_ids)
|
||||
self.assertTrue(order.picking_ids)
|
||||
|
||||
action = order.action_view_transfer()
|
||||
self.assertEqual('domain' in action.keys(), True)
|
||||
self.assertEqual('views' in action.keys(), True)
|
||||
self.assertEqual(action['res_id'], order.picking_ids[0].id)
|
||||
|
||||
action = order.action_view_stock_requests()
|
||||
self.assertEqual('domain' in action.keys(), True)
|
||||
self.assertEqual('views' in action.keys(), True)
|
||||
self.assertEqual(action['res_id'], stock_request[0].id)
|
||||
|
||||
action = stock_request.action_view_transfer()
|
||||
self.assertEqual('domain' in action.keys(), True)
|
||||
self.assertEqual('views' in action.keys(), True)
|
||||
self.assertEqual(action['res_id'], stock_request.picking_ids[0].id)
|
||||
|
||||
60
stock_request/views/res_config_settings_views.xml
Normal file
60
stock_request/views/res_config_settings_views.xml
Normal file
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<!--
|
||||
Copyright 2018 Creu Blanca
|
||||
License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
<record id="res_config_settings_view_form" model="ir.ui.view">
|
||||
<field name="name">res.config.settings.view.form.inherit.medical</field>
|
||||
<field name="model">res.config.settings</field>
|
||||
<field name="inherit_id" ref="base.res_config_settings_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[hasclass('settings')]" position="inside">
|
||||
<div class="app_settings_block"
|
||||
data-string="Stock Request" data-key="stock_request"
|
||||
groups="stock_request.group_stock_request_manager">
|
||||
<div class="row mt16 o_settings_container" id="stock_request">
|
||||
<div class="col-xs-12 col-md-6 o_setting_box">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="group_stock_request_order"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label string="Enable orders"
|
||||
for="group_stock_request_order"/>
|
||||
<div class="text-muted">
|
||||
Activates Stock Request Orders
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-6 o_setting_box">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="module_stock_request_purchase"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label string="Enable Stock Requests for Purchases"
|
||||
for="module_stock_request_purchase"/>
|
||||
<div class="text-muted">
|
||||
Use Purchases with Stock Requests
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_stock_request_config" model="ir.actions.act_window">
|
||||
<field name="name">Settings</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">res.config.settings</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">inline</field>
|
||||
<field name="context">{'module' : 'stock_request'}</field>
|
||||
</record>
|
||||
|
||||
|
||||
</odoo>
|
||||
27
stock_request/views/stock_request_menu.xml
Normal file
27
stock_request/views/stock_request_menu.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
<menuitem
|
||||
id="menu_stock_request_root"
|
||||
name="Stock Requests"
|
||||
groups="stock_request.group_stock_request_user,stock_request.group_stock_request_manager"
|
||||
sequence="100"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_stock_request"
|
||||
action="action_stock_request_form"
|
||||
name="Stock Requests" parent="menu_stock_request_root"
|
||||
sequence="20"/>
|
||||
|
||||
<menuitem id="stock_request_order_menu"
|
||||
name="Stock Requests orders"
|
||||
parent="menu_stock_request_root"
|
||||
action="stock_request_order_action"
|
||||
groups="group_stock_request_order"
|
||||
sequence="10"/>
|
||||
|
||||
<menuitem id="menu_stock_request_config" name="Settings"
|
||||
parent="menu_stock_request_root"
|
||||
sequence="99" action="action_stock_request_config"
|
||||
groups="base.group_system"/>
|
||||
|
||||
</odoo>
|
||||
137
stock_request/views/stock_request_order_views.xml
Normal file
137
stock_request/views/stock_request_order_views.xml
Normal file
@@ -0,0 +1,137 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
|
||||
<record model="ir.ui.view" id="stock_request_order_tree">
|
||||
<field name="name">stock.request.order.tree</field>
|
||||
<field name="model">stock.request.order</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Stock requests">
|
||||
<field name="name"/>
|
||||
<field name="warehouse_id"
|
||||
groups="stock.group_stock_multi_locations"/>
|
||||
<field name="location_id"
|
||||
groups="stock.group_stock_multi_locations"/>
|
||||
<field name="state"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="stock_request_order_form">
|
||||
<field name="name">stock.request.order.form</field>
|
||||
<field name="model">stock.request.order</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Stock request">
|
||||
<header>
|
||||
<button name="action_confirm"
|
||||
string="Confirm" type="object"
|
||||
attrs="{'invisible': [('state', 'not in', ['draft'])]}"/>
|
||||
<button name="action_cancel" states="draft,open"
|
||||
type="object" string="Cancel"/>
|
||||
<button name="action_draft" states="cancel" type="object"
|
||||
string="Set to Draft"/>
|
||||
<field name="state" widget="statusbar"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<field name="picking_ids" invisible="1"/>
|
||||
<button type="object"
|
||||
name="action_view_transfer"
|
||||
class="oe_stat_button"
|
||||
icon="fa-truck"
|
||||
attrs="{'invisible': [('picking_count', '=', 0)]}"
|
||||
groups="stock.group_stock_user">
|
||||
<field name="picking_count" widget="statinfo"
|
||||
string="Transfers"/>
|
||||
</button>
|
||||
<button type="object"
|
||||
name="action_view_stock_requests"
|
||||
class="oe_stat_button"
|
||||
icon="fa-chain"
|
||||
attrs="{'invisible': [('state', '=', 'draft')]}"
|
||||
groups="stock.group_stock_user"
|
||||
>
|
||||
<field name="stock_request_count" widget="statinfo"
|
||||
string="Stock requests"/>
|
||||
</button>
|
||||
</div>
|
||||
<div class="oe_title">
|
||||
<label string="Stock Request"/>
|
||||
<h1>
|
||||
<field name="name" readonly="1"/>
|
||||
</h1>
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="expected_date"/>
|
||||
<field name="picking_policy"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="warehouse_id" widget="selection"
|
||||
groups="stock.group_stock_multi_locations"/>
|
||||
<field name="location_id"
|
||||
groups="stock.group_stock_multi_locations"/>
|
||||
<field name="procurement_group_id"
|
||||
groups="stock.group_adv_location"/>
|
||||
<field name="company_id"
|
||||
groups="base.group_multi_company"
|
||||
options="{'no_create': True}"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page name="items" string="Items">
|
||||
<field name="stock_request_ids" context="{
|
||||
'default_expected_date':expected_date,
|
||||
'default_picking_policy': picking_policy,
|
||||
'default_warehouse_id': warehouse_id,
|
||||
'default_location_id': location_id,
|
||||
'default_procurement_group_id': procurement_group_id,
|
||||
'default_company_id': company_id,
|
||||
'default_state': state,
|
||||
}" attrs="{'readonly': [('state', '!=', 'draft')]}">
|
||||
<tree editable="bottom">
|
||||
<field name="name" readonly="1"/>
|
||||
<field name="product_id"/>
|
||||
<field name="product_uom_id"
|
||||
options="{'no_open': True, 'no_create': True}"
|
||||
groups="product.group_uom"/>
|
||||
<field name="route_id"
|
||||
options="{'no_create': True}"
|
||||
groups="stock.group_stock_multi_locations"/>
|
||||
<field name="route_ids" invisible="1"/>
|
||||
<field name="product_uom_qty"/>
|
||||
<field name="qty_in_progress"/>
|
||||
<field name="qty_done"/>
|
||||
<field name="expected_date" invisible="1"/>
|
||||
<field name="picking_policy"
|
||||
invisible="1"/>
|
||||
<field name="warehouse_id" invisible="1"/>
|
||||
<field name="location_id" invisible="1"/>
|
||||
<field name="procurement_group_id"
|
||||
invisible="1"/>
|
||||
<field name="company_id" invisible="1"/>
|
||||
<field name="state"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids"
|
||||
widget="mail_followers"/>
|
||||
<field name="activity_ids" widget="mail_activity"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window"
|
||||
id="stock_request_order_action">
|
||||
<field name="name">Stock request orders</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">stock.request.order</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -82,6 +82,7 @@
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="order_id" readonly="1"/>
|
||||
<field name="product_id"/>
|
||||
<field name="expected_date"/>
|
||||
<field name="picking_policy"/>
|
||||
@@ -93,6 +94,7 @@
|
||||
<field name="location_id" groups="stock.group_stock_multi_locations"/>
|
||||
<field name="route_id"
|
||||
options="{'no_create': True}" groups="stock.group_stock_multi_locations"/>
|
||||
<field name="route_ids" invisible="1"/>
|
||||
<field name="procurement_group_id"
|
||||
groups="stock.group_adv_location"/>
|
||||
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
|
||||
@@ -128,16 +130,4 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
id="menu_stock_request_root"
|
||||
name="Stock Requests"
|
||||
groups="stock_request.group_stock_request_user,stock_request.group_stock_request_manager"
|
||||
sequence="100"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_stock_request"
|
||||
action="action_stock_request_form"
|
||||
name="Stock Requests" parent="menu_stock_request_root"
|
||||
sequence="10"/>
|
||||
|
||||
</odoo>
|
||||
|
||||
Reference in New Issue
Block a user