mirror of
https://github.com/OCA/manufacture.git
synced 2025-01-28 16:37:15 +02:00
[11.0][MIG] mrp_production_request
This commit is contained in:
committed by
Chandresh Thakkar
parent
4269e2771c
commit
423183102f
@@ -1,24 +1,54 @@
|
||||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
|
||||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
|
||||
:alt: License: AGPL-3
|
||||
|
||||
======================
|
||||
MRP Production Request
|
||||
======================
|
||||
|
||||
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! This file is generated by oca-gen-addon-readme !!
|
||||
!! changes will be overwritten. !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
.. |badge1| image:: https://img.shields.io/badge/maturity-Mature-brightgreen.png
|
||||
:target: https://odoo-community.org/page/development-status
|
||||
:alt: Mature
|
||||
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
|
||||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
|
||||
:alt: License: AGPL-3
|
||||
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fmanufacture-lightgray.png?logo=github
|
||||
:target: https://github.com/OCA/manufacture/tree/11.0/mrp_production_request
|
||||
:alt: OCA/manufacture
|
||||
.. |badge4| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
|
||||
:target: https://runbot.odoo-community.org/runbot/129/11.0
|
||||
:alt: Try me on Runbot
|
||||
|
||||
|badge1| |badge2| |badge3| |badge4|
|
||||
|
||||
This module extends the functionality of Manufacturing to allow you to use
|
||||
Manufacturing Request (MR) as a previous step to Manufacturing Orders (MO).
|
||||
|
||||
Some of the benefits you can obtain are:
|
||||
|
||||
* Allow managers to review what is going to be manufactured.
|
||||
* Better control of manufacturing calendar.
|
||||
* Manage big requirements splitting them in batches.
|
||||
* Know your bottleneck component in advance and only schedule what you really
|
||||
can build.
|
||||
|
||||
**Table of contents**
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
Configuration
|
||||
=============
|
||||
|
||||
To configure this module to automatically generate Manufacturing Requests
|
||||
from procurement orders instead of directly create manufacturing orders yo
|
||||
To configure a product to automatically generate Manufacturing Requests
|
||||
from procurements instead of directly create manufacturing orders you
|
||||
need to:
|
||||
|
||||
#. Go to the products that you want them to trigger manufacturing orders.
|
||||
#. Go to the products that you want them to trigger manufacturing requests.
|
||||
#. Go to the *Inventory* tab.
|
||||
#. Check the route *manufacture* and the box *Manufacturing Request*.
|
||||
#. Check the box of a *manufacture* route and the box of
|
||||
*Manufacturing Request*.
|
||||
|
||||
Usage
|
||||
=====
|
||||
@@ -29,12 +59,12 @@ To use this module, you need to:
|
||||
#. Create a manufacturing request or open a existing one (assigned to you or
|
||||
created from a procurement).
|
||||
#. If you click on *Request approval* button the user assigned as approver
|
||||
will added to the thread.
|
||||
will be added to the thread.
|
||||
#. If you are the approver you can either click on *Approve* or *Reject*
|
||||
buttons.
|
||||
#. Rejecting a MR will cancel associated procurements and propagate this
|
||||
cancellation.
|
||||
#. Approving a MR will allow to create manufacturing orders.
|
||||
#. Rejecting a MR will cancel it and propagate this cancellation to
|
||||
destination moves.
|
||||
#. Approving a MR will allow you to create manufacturing orders.
|
||||
#. You can manually set to done a request by clicking in the button *Done*.
|
||||
|
||||
To create MOs from MRs you have to:
|
||||
@@ -43,7 +73,8 @@ To create MOs from MRs you have to:
|
||||
#. Click on the button *Create Manufacturing Order*.
|
||||
#. In the opened wizard, click on *Compute lines* so you will have a
|
||||
quantity proposed for creating a MO. This quantity is the maximum quantity
|
||||
you can produce with the current stock available in the source location.
|
||||
you can produce with the current stock available for the components needed
|
||||
in the source location.
|
||||
#. Use the proposed quantity or change it and click on *Create MO* at the
|
||||
bottom of the wizard.
|
||||
|
||||
@@ -51,49 +82,64 @@ To create MOs from MRs you have to:
|
||||
from a MR to MOs. It is in hands of the user to decide when a MR is ended and
|
||||
to set it to *Done* state.
|
||||
|
||||
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
|
||||
:alt: Try me on Runbot
|
||||
:target: https://runbot.odoo-community.org/runbot/129/10.0
|
||||
|
||||
Known issues / Roadmap
|
||||
======================
|
||||
|
||||
* Take into account workstations.
|
||||
* Take into account consumable products.
|
||||
|
||||
Changelog
|
||||
=========
|
||||
|
||||
11.0.1.0.0 (2018-09-13)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* [MIG] Migration to v11. Start of the history.
|
||||
|
||||
Bug Tracker
|
||||
===========
|
||||
|
||||
Bugs are tracked on `GitHub Issues
|
||||
<https://github.com/OCA/manufacture/issues>`_. In case of trouble, please
|
||||
check there if your issue has already been reported. If you spotted it first,
|
||||
help us smash it by providing detailed and welcomed feedback.
|
||||
Bugs are tracked on `GitHub Issues <https://github.com/OCA/manufacture/issues>`_.
|
||||
In case of trouble, please check there if your issue has already been reported.
|
||||
If you spotted it first, help us smashing it by providing a detailed and welcomed feedback.
|
||||
|
||||
Do not contact contributors directly about support or help with technical issues.
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
Images
|
||||
------
|
||||
Authors
|
||||
~~~~~~~
|
||||
|
||||
* Odoo Community Association: `Icon <https://github.com/OCA/maintainer-tools/blob/master/template/module/static/description/icon.svg>`_.
|
||||
* Eficent
|
||||
|
||||
Contributors
|
||||
------------
|
||||
~~~~~~~~~~~~
|
||||
|
||||
* Lois Rilo Antelo <lois.rilo@eficent.com>
|
||||
* Jordi Ballester <jordi.ballester@eficent.com>
|
||||
|
||||
Maintainer
|
||||
----------
|
||||
Maintainers
|
||||
~~~~~~~~~~~
|
||||
|
||||
This module is maintained by the OCA.
|
||||
|
||||
.. image:: https://odoo-community.org/logo.png
|
||||
:alt: Odoo Community Association
|
||||
:target: https://odoo-community.org
|
||||
|
||||
This module is maintained by the OCA.
|
||||
|
||||
OCA, or the Odoo Community Association, is a nonprofit organization whose
|
||||
mission is to support the collaborative development of Odoo features and
|
||||
promote its widespread use.
|
||||
|
||||
To contribute to this module, please visit https://odoo-community.org.
|
||||
.. |maintainer-lreficent| image:: https://github.com/lreficent.png?size=40px
|
||||
:target: https://github.com/lreficent
|
||||
:alt: lreficent
|
||||
|
||||
Current `maintainer <https://odoo-community.org/page/maintainer-role>`_:
|
||||
|
||||
|maintainer-lreficent|
|
||||
|
||||
This module is part of the `OCA/manufacture <https://github.com/OCA/manufacture/tree/11.0/mrp_production_request>`_ project on GitHub.
|
||||
|
||||
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
|
||||
|
||||
@@ -1,5 +1,2 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from . import models
|
||||
from . import wizards
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
{
|
||||
@@ -6,7 +5,9 @@
|
||||
"summary": "Allows you to use Manufacturing Request as a previous "
|
||||
"step to Manufacturing Orders for better manufacture "
|
||||
"planification.",
|
||||
"version": "10.0.1.1.0",
|
||||
"version": "11.0.1.0.0",
|
||||
"development_status": "Mature",
|
||||
"maintainers": ['lreficent'],
|
||||
"category": "Manufacturing",
|
||||
"website": "https://github.com/OCA/manufacture",
|
||||
"author": "Eficent,"
|
||||
@@ -22,7 +23,6 @@
|
||||
"wizards/mrp_production_request_create_mo_view.xml",
|
||||
"views/mrp_production_request_view.xml",
|
||||
"views/product_template_view.xml",
|
||||
"views/procurement_order_view.xml",
|
||||
"views/mrp_production_view.xml",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
# Copyright 2018 Eficent Business and IT Consulting Services S.L.
|
||||
# (http://www.eficent.com)
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
|
||||
def migrate(cr, version):
|
||||
"""Copy `move_dest_id` from the old procurement orders to the new field
|
||||
`move_dest_ids` in the Manufacturing Request."""
|
||||
cr.execute("""
|
||||
SELECT move_dest_id, mrp_production_request_id
|
||||
FROM procurement_order
|
||||
WHERE mrp_production_request_id is not null;""")
|
||||
for move_dest, mrp_request in cr.fetchall():
|
||||
if move_dest:
|
||||
cr.execute("""
|
||||
UPDATE stock_move
|
||||
SET created_mrp_production_request_id = %s
|
||||
WHERE id = %s
|
||||
""", (mrp_request, move_dest,))
|
||||
@@ -1,8 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from . import mrp_production_request
|
||||
from . import mrp_production
|
||||
from . import procurement
|
||||
from . import procurement_rule
|
||||
from . import product
|
||||
from . import stock_move
|
||||
from . import stock_warehouse_orderpoint
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
@@ -13,7 +12,16 @@ class MrpProduction(models.Model):
|
||||
string="Manufacturing Request", copy=False, readonly=True)
|
||||
|
||||
def _generate_finished_moves(self):
|
||||
"""`move_dest_ids` is a One2many fields in mrp.production, thus we
|
||||
cannot indicate the same destination move in several MOs (which most
|
||||
probably would be the case with MRs).
|
||||
Storing them on the MR and writing them on the finished moves as it
|
||||
would happen if they were present in the MO, is the best workaround
|
||||
without changing the standard data model."""
|
||||
move = super(MrpProduction, self)._generate_finished_moves()
|
||||
mr_proc = self.mrp_production_request_id.procurement_id
|
||||
if mr_proc and mr_proc.move_dest_id:
|
||||
move.write({"move_dest_id": mr_proc.move_dest_id.id})
|
||||
request = self.mrp_production_request_id
|
||||
if request and request.move_dest_ids:
|
||||
move.write({
|
||||
'move_dest_ids': [(4, x.id) for x in request.move_dest_ids],
|
||||
})
|
||||
return move
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2017-18 Eficent Business and IT Consulting Services S.L.
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
@@ -11,7 +10,7 @@ class MrpProductionRequest(models.Model):
|
||||
_name = "mrp.production.request"
|
||||
_description = "Manufacturing Request"
|
||||
_inherit = "mail.thread"
|
||||
_order = "id DESC"
|
||||
_order = "date_planned_start desc, id desc"
|
||||
|
||||
@api.model
|
||||
def _company_get(self):
|
||||
@@ -22,59 +21,6 @@ class MrpProductionRequest(models.Model):
|
||||
def _get_default_requested_by(self):
|
||||
return self.env.user
|
||||
|
||||
@api.multi
|
||||
def _subscribe_assigned_user(self, vals):
|
||||
self.ensure_one()
|
||||
if vals.get('assigned_to'):
|
||||
self.message_subscribe_users(user_ids=[self.assigned_to.id])
|
||||
|
||||
@api.model
|
||||
def _create_sequence(self, vals):
|
||||
if not vals.get('name') or vals.get('name') == '/':
|
||||
vals['name'] = self.env['ir.sequence'].next_by_code(
|
||||
'mrp.production.request') or '/'
|
||||
return vals
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
"""Add sequence if name is not defined and subscribe to the thread
|
||||
the user assigned to the request."""
|
||||
vals = self._create_sequence(vals)
|
||||
res = super(MrpProductionRequest, self).create(vals)
|
||||
res._subscribe_assigned_user(vals)
|
||||
return res
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
res = super(MrpProductionRequest, self).write(vals)
|
||||
for request in self:
|
||||
request._subscribe_assigned_user(vals)
|
||||
return res
|
||||
|
||||
@api.onchange('product_id')
|
||||
def _onchange_product_id(self):
|
||||
self.product_uom_id = self.product_id.uom_id
|
||||
self.bom_id = self.env['mrp.bom']._bom_find(
|
||||
product=self.product_id, company_id=self.company_id.id,
|
||||
picking_type=self.picking_type_id)
|
||||
|
||||
@api.model
|
||||
def _get_mo_valid_states(self):
|
||||
return ['draft', 'confirmed', 'ready', 'in_production', 'done']
|
||||
|
||||
@api.multi
|
||||
@api.depends('mrp_production_ids', 'mrp_production_ids.state', 'state')
|
||||
def _compute_manufactured_qty(self):
|
||||
valid_states = self._get_mo_valid_states()
|
||||
for req in self:
|
||||
done_mo = req.mrp_production_ids.filtered(
|
||||
lambda mo: mo.state in 'done').mapped('product_qty')
|
||||
req.done_qty = sum(done_mo)
|
||||
valid_mo = req.mrp_production_ids.filtered(
|
||||
lambda mo: mo.state in valid_states).mapped('product_qty')
|
||||
req.manufactured_qty = sum(valid_mo)
|
||||
req.pending_qty = max(req.product_qty - req.manufactured_qty, 0.0)
|
||||
|
||||
name = fields.Char(
|
||||
default="/", required=True,
|
||||
readonly=True, states={'draft': [('readonly', False)]})
|
||||
@@ -89,7 +35,10 @@ class MrpProductionRequest(models.Model):
|
||||
assigned_to = fields.Many2one(
|
||||
comodel_name='res.users', string='Approver',
|
||||
track_visibility='onchange',
|
||||
readonly=True, states={'draft': [('readonly', False)]})
|
||||
readonly=True, states={'draft': [('readonly', False)]},
|
||||
domain=lambda self: [('groups_id', 'in', self.env.ref(
|
||||
'mrp_production_request.'
|
||||
'group_mrp_production_request_manager').id)])
|
||||
description = fields.Text('Description')
|
||||
date_planned_start = fields.Datetime(
|
||||
'Deadline Start', copy=False, default=fields.Datetime.now,
|
||||
@@ -105,6 +54,10 @@ class MrpProductionRequest(models.Model):
|
||||
mrp_production_ids = fields.One2many(
|
||||
comodel_name="mrp.production", string="Manufacturing Orders",
|
||||
inverse_name="mrp_production_request_id", readonly=True)
|
||||
mrp_production_count = fields.Integer(
|
||||
compute="_compute_mrp_production_count",
|
||||
string="MO's Count",
|
||||
)
|
||||
state = fields.Selection(
|
||||
selection=[("draft", "Draft"),
|
||||
("to_approve", "To Be Approved"),
|
||||
@@ -117,21 +70,11 @@ class MrpProductionRequest(models.Model):
|
||||
string='Procurement Group',
|
||||
comodel_name='procurement.group',
|
||||
copy=False)
|
||||
procurement_ids = fields.One2many(
|
||||
string='Related Procurements',
|
||||
comodel_name='procurement.order',
|
||||
inverse_name='mrp_production_request_id')
|
||||
propagate = fields.Boolean(
|
||||
'Propagate cancel and split',
|
||||
help='If checked, when the previous move of the move '
|
||||
'(which was generated by a next procurement) is cancelled '
|
||||
'or split, the move generated by this move will too')
|
||||
procurement_id = fields.Many2one(
|
||||
comodel_name="procurement.order", string="Procurement Order",
|
||||
readonly=True)
|
||||
procurement_state = fields.Selection(
|
||||
related='procurement_id.state',
|
||||
store=True, readonly=True, string="Procurement State")
|
||||
product_id = fields.Many2one(
|
||||
comodel_name="product.product", string="Product", required=True,
|
||||
domain=[('type', 'in', ['product', 'consu'])],
|
||||
@@ -142,7 +85,7 @@ class MrpProductionRequest(models.Model):
|
||||
related='product_id.product_tmpl_id')
|
||||
product_qty = fields.Float(
|
||||
string="Required Quantity", required=True, track_visibility='onchange',
|
||||
digits=dp.get_precision('Product Unit of Measure'),
|
||||
digits=dp.get_precision('Product Unit of Measure'), default=1.0,
|
||||
readonly=True, states={'draft': [('readonly', False)]})
|
||||
product_uom_id = fields.Many2one(
|
||||
comodel_name='product.uom', string='Unit of Measure',
|
||||
@@ -151,16 +94,16 @@ class MrpProductionRequest(models.Model):
|
||||
category_uom_id = fields.Many2one(related="product_uom_id.category_id")
|
||||
manufactured_qty = fields.Float(
|
||||
string="Quantity in Manufacturing Orders",
|
||||
compute=_compute_manufactured_qty, store=True, readonly=True,
|
||||
compute="_compute_manufactured_qty", store=True, readonly=True,
|
||||
digits=dp.get_precision('Product Unit of Measure'),
|
||||
help="Sum of the quantities in Manufacturing Orders (in any state).")
|
||||
done_qty = fields.Float(
|
||||
string="Quantity Done", store=True, readonly=True,
|
||||
compute=_compute_manufactured_qty,
|
||||
compute="_compute_manufactured_qty",
|
||||
digits=dp.get_precision('Product Unit of Measure'),
|
||||
help="Sum of the quantities in all done Manufacturing Orders.")
|
||||
pending_qty = fields.Float(
|
||||
string="Pending Quantity", compute=_compute_manufactured_qty,
|
||||
string="Pending Quantity", compute="_compute_manufactured_qty",
|
||||
store=True, digits=dp.get_precision('Product Unit of Measure'),
|
||||
readonly=True,
|
||||
help="Quantity pending to add to Manufacturing Orders "
|
||||
@@ -191,6 +134,76 @@ class MrpProductionRequest(models.Model):
|
||||
default=lambda self: self.env['stock.picking.type'].browse(
|
||||
self.env['mrp.production']._get_default_picking_type()),
|
||||
required=True, readonly=True, states={'draft': [('readonly', False)]})
|
||||
move_dest_ids = fields.One2many(
|
||||
comodel_name='stock.move',
|
||||
inverse_name='created_mrp_production_request_id',
|
||||
string="Stock Movements of Produced Goods")
|
||||
orderpoint_id = fields.Many2one(
|
||||
comodel_name='stock.warehouse.orderpoint',
|
||||
string='Orderpoint')
|
||||
|
||||
_sql_constraints = [
|
||||
('name_uniq', 'unique(name, company_id)',
|
||||
'Reference must be unique per Company!'),
|
||||
]
|
||||
|
||||
@api.model
|
||||
def _get_mo_valid_states(self):
|
||||
return ['planned', 'confirmed', 'progress', 'done']
|
||||
|
||||
@api.multi
|
||||
@api.depends('mrp_production_ids', 'mrp_production_ids.state', 'state')
|
||||
def _compute_manufactured_qty(self):
|
||||
valid_states = self._get_mo_valid_states()
|
||||
for req in self:
|
||||
done_mo = req.mrp_production_ids.filtered(
|
||||
lambda mo: mo.state in 'done').mapped('product_qty')
|
||||
req.done_qty = sum(done_mo)
|
||||
valid_mo = req.mrp_production_ids.filtered(
|
||||
lambda mo: mo.state in valid_states).mapped('product_qty')
|
||||
req.manufactured_qty = sum(valid_mo)
|
||||
req.pending_qty = max(req.product_qty - req.manufactured_qty, 0.0)
|
||||
|
||||
@api.multi
|
||||
def _compute_mrp_production_count(self):
|
||||
for rec in self:
|
||||
rec.mrp_production_count = len(rec.mrp_production_ids)
|
||||
|
||||
@api.onchange('product_id')
|
||||
def _onchange_product_id(self):
|
||||
self.product_uom_id = self.product_id.uom_id
|
||||
self.bom_id = self.env['mrp.bom']._bom_find(
|
||||
product=self.product_id, company_id=self.company_id.id,
|
||||
picking_type=self.picking_type_id)
|
||||
|
||||
@api.multi
|
||||
def _subscribe_assigned_user(self, vals):
|
||||
self.ensure_one()
|
||||
if vals.get('assigned_to'):
|
||||
self.message_subscribe_users(user_ids=[self.assigned_to.id])
|
||||
|
||||
@api.model
|
||||
def _create_sequence(self, vals):
|
||||
if not vals.get('name') or vals.get('name') == '/':
|
||||
vals['name'] = self.env['ir.sequence'].next_by_code(
|
||||
'mrp.production.request') or '/'
|
||||
return vals
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
"""Add sequence if name is not defined and subscribe to the thread
|
||||
the user assigned to the request."""
|
||||
vals = self._create_sequence(vals)
|
||||
res = super(MrpProductionRequest, self).create(vals)
|
||||
res._subscribe_assigned_user(vals)
|
||||
return res
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
res = super(MrpProductionRequest, self).write(vals)
|
||||
for request in self:
|
||||
request._subscribe_assigned_user(vals)
|
||||
return res
|
||||
|
||||
@api.multi
|
||||
def button_to_approve(self):
|
||||
@@ -205,8 +218,6 @@ class MrpProductionRequest(models.Model):
|
||||
@api.multi
|
||||
def button_done(self):
|
||||
self.write({'state': 'done'})
|
||||
if self.mapped('procurement_id'):
|
||||
self.mapped('procurement_id').write({'state': 'done'})
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
@@ -216,11 +227,6 @@ class MrpProductionRequest(models.Model):
|
||||
raise UserError(
|
||||
_("You cannot reset a manufacturing request if the related "
|
||||
"manufacturing orders are not cancelled."))
|
||||
if any([s in ['done', 'cancel'] for s in self.mapped(
|
||||
'procurement_id.state')]):
|
||||
raise UserError(
|
||||
_("You cannot reset a manufacturing request related to "
|
||||
"done or cancelled procurement orders."))
|
||||
|
||||
@api.multi
|
||||
def button_draft(self):
|
||||
@@ -230,8 +236,7 @@ class MrpProductionRequest(models.Model):
|
||||
|
||||
@api.multi
|
||||
def _check_cancel_allowed(self):
|
||||
if any([s == 'done' for s in self.mapped(
|
||||
'procurement_id.state')]):
|
||||
if any([s == 'done' for s in self.mapped('state')]):
|
||||
raise UserError(
|
||||
_('You cannot reject a manufacturing request related to '
|
||||
'done procurement orders.'))
|
||||
@@ -240,15 +245,21 @@ class MrpProductionRequest(models.Model):
|
||||
def button_cancel(self):
|
||||
self._check_cancel_allowed()
|
||||
self.write({'state': 'cancel'})
|
||||
self.mapped('procurement_id').with_context(
|
||||
from_mrp_production_request=True).cancel()
|
||||
if not self.env.context.get('cancel_procurement'):
|
||||
procurements = self.mapped('procurement_id')
|
||||
procurements.filtered(lambda r: r.state not in (
|
||||
'cancel', 'exception') and not r.rule_id.propagate).write(
|
||||
{'state': 'exception'})
|
||||
moves = procurements.filtered(
|
||||
lambda r: r.rule_id.propagate).mapped(
|
||||
'move_dest_id')
|
||||
moves.filtered(lambda r: r.state != 'cancel').action_cancel()
|
||||
self.mapped('move_dest_ids').filtered(
|
||||
lambda r: r.state != 'cancel')._action_cancel()
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
def action_view_mrp_productions(self):
|
||||
action = self.env.ref('mrp.mrp_production_action')
|
||||
result = action.read()[0]
|
||||
result['context'] = {}
|
||||
mos = self.mapped('mrp_production_ids')
|
||||
# choose the view_mode accordingly
|
||||
if len(mos) != 1:
|
||||
result['domain'] = [('id', 'in', mos.ids)]
|
||||
elif len(mos) == 1:
|
||||
form = self.env.ref('mrp.mrp_production_form_view', False)
|
||||
result['views'] = [(form and form.id or False, 'form')]
|
||||
result['res_id'] = mos[0].id
|
||||
return result
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
|
||||
|
||||
class ProcurementOrder(models.Model):
|
||||
_inherit = "procurement.order"
|
||||
|
||||
mrp_production_request_id = fields.Many2one(
|
||||
comodel_name="mrp.production.request", string="Manufacturing Request",
|
||||
copy=False)
|
||||
|
||||
@api.multi
|
||||
def _prepare_mrp_production_request(self):
|
||||
self.ensure_one()
|
||||
data = self._prepare_mo_vals(self._get_matching_bom())
|
||||
data['procurement_id'] = self.id
|
||||
data['state'] = 'to_approve'
|
||||
return data
|
||||
|
||||
@api.multi
|
||||
def _run(self):
|
||||
self.ensure_one()
|
||||
if (self.rule_id and
|
||||
self.rule_id.action == 'manufacture' and
|
||||
self.product_id.mrp_production_request):
|
||||
if not self._get_matching_bom():
|
||||
self.message_post(
|
||||
body=_("No BoM exists for this product!"))
|
||||
return False
|
||||
if not self.mrp_production_request_id:
|
||||
request_data = self._prepare_mrp_production_request()
|
||||
req = self.env['mrp.production.request'].create(request_data)
|
||||
self.message_post(body=_(
|
||||
"Manufacturing Request created"))
|
||||
self.mrp_production_request_id = req.id
|
||||
return True
|
||||
return super(ProcurementOrder, self)._run()
|
||||
|
||||
@api.multi
|
||||
def propagate_cancels(self):
|
||||
result = super(ProcurementOrder, self).propagate_cancels()
|
||||
for procurement in self:
|
||||
mrp_production_requests = \
|
||||
self.env['mrp.production.request'].sudo().search([
|
||||
('procurement_id', '=', procurement.id)])
|
||||
if mrp_production_requests and not self.env.context.get(
|
||||
'from_mrp_production_request'):
|
||||
mrp_production_requests.sudo().button_cancel()
|
||||
for mr in mrp_production_requests:
|
||||
mr.sudo().message_post(
|
||||
body=_("Related procurement has been cancelled."))
|
||||
procurement.write({'mrp_production_request_id': None})
|
||||
return result
|
||||
80
mrp_production_request/models/procurement_rule.py
Normal file
80
mrp_production_request/models/procurement_rule.py
Normal file
@@ -0,0 +1,80 @@
|
||||
# Copyright 2018 Eficent Business and IT Consulting Services S.L.
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import api, models, _
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class ProcurementOrder(models.Model):
|
||||
_inherit = "procurement.rule"
|
||||
|
||||
@api.multi
|
||||
def _prepare_mrp_production_request(
|
||||
self, product_id, product_qty, product_uom, location_id, name,
|
||||
origin, values, bom):
|
||||
self.ensure_one()
|
||||
data = self._prepare_mo_vals(
|
||||
product_id, product_qty, product_uom, location_id, name,
|
||||
origin, values, bom)
|
||||
data['state'] = 'to_approve'
|
||||
orderpoint = values.get('orderpoint_id')
|
||||
if orderpoint:
|
||||
data['orderpoint_id'] = orderpoint.id
|
||||
return data
|
||||
|
||||
@api.multi
|
||||
def _need_production_request(self, product_id):
|
||||
return self.action == 'manufacture' \
|
||||
and product_id.mrp_production_request
|
||||
|
||||
@api.multi
|
||||
def _run_production_request(self, product_id, product_qty, product_uom,
|
||||
location_id, name, origin, values):
|
||||
"""Trying to handle this as much similar as possible to Odoo
|
||||
production orders. See `_run_manufacture` in Odoo standard."""
|
||||
request_obj = self.env['mrp.production.request']
|
||||
request_obj_sudo = request_obj.sudo().with_context(
|
||||
force_company=values['company_id'].id)
|
||||
bom = self._get_matching_bom(product_id, values)
|
||||
if not bom:
|
||||
raise UserError(_(
|
||||
'There is no Bill of Material found for the product %s. '
|
||||
'Please define a Bill of Material for this product.') % (
|
||||
product_id.display_name,))
|
||||
|
||||
# create the MR as SUPERUSER because the current user may not
|
||||
# have the rights to do it (mto product launched by a sale for example)
|
||||
request = request_obj_sudo.create(
|
||||
self._prepare_mrp_production_request(
|
||||
product_id, product_qty, product_uom, location_id, name,
|
||||
origin, values, bom))
|
||||
origin_production = values.get('move_dest_ids') and \
|
||||
values['move_dest_ids'][0].raw_material_production_id or False
|
||||
orderpoint = values.get('orderpoint_id')
|
||||
if orderpoint:
|
||||
request.message_post_with_view(
|
||||
'mail.message_origin_link',
|
||||
values={'self': request,
|
||||
'origin': orderpoint},
|
||||
subtype_id=self.env.ref('mail.mt_note').id,
|
||||
)
|
||||
if origin_production:
|
||||
request.message_post_with_view(
|
||||
'mail.message_origin_link',
|
||||
values={'self': request,
|
||||
'origin': origin_production},
|
||||
subtype_id=self.env.ref('mail.mt_note').id,
|
||||
)
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
def _run_manufacture(self, product_id, product_qty, product_uom,
|
||||
location_id, name, origin, values):
|
||||
if self._need_production_request(product_id):
|
||||
return self._run_production_request(
|
||||
product_id, product_qty, product_uom,
|
||||
location_id, name, origin, values)
|
||||
|
||||
return super()._run_manufacture(
|
||||
product_id, product_qty, product_uom, location_id, name,
|
||||
origin, values)
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import api, models
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class StockMove(models.Model):
|
||||
_inherit = "stock.move"
|
||||
|
||||
created_mrp_production_request_id = fields.Many2one(
|
||||
comodel_name='mrp.production.request',
|
||||
string='Created Production Request',
|
||||
)
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
if 'production_id' in vals:
|
||||
|
||||
19
mrp_production_request/models/stock_warehouse_orderpoint.py
Normal file
19
mrp_production_request/models/stock_warehouse_orderpoint.py
Normal file
@@ -0,0 +1,19 @@
|
||||
# Copyright 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import models
|
||||
|
||||
|
||||
class Orderpoint(models.Model):
|
||||
_inherit = "stock.warehouse.orderpoint"
|
||||
|
||||
def _quantity_in_progress(self):
|
||||
res = super(Orderpoint, self)._quantity_in_progress()
|
||||
mrp_requests = self.env['mrp.production.request'].search([
|
||||
('state', 'not in', ('done', 'cancel')),
|
||||
('orderpoint_id', 'in', self.ids),
|
||||
])
|
||||
for rec in mrp_requests:
|
||||
res[rec.orderpoint_id.id] += rec.product_uom_id._compute_quantity(
|
||||
rec.pending_qty, rec.orderpoint_id.product_uom, round=False)
|
||||
return res
|
||||
8
mrp_production_request/readme/CONFIGURE.rst
Normal file
8
mrp_production_request/readme/CONFIGURE.rst
Normal file
@@ -0,0 +1,8 @@
|
||||
To configure a product to automatically generate Manufacturing Requests
|
||||
from procurements instead of directly create manufacturing orders you
|
||||
need to:
|
||||
|
||||
#. Go to the products that you want them to trigger manufacturing requests.
|
||||
#. Go to the *Inventory* tab.
|
||||
#. Check the box of a *manufacture* route and the box of
|
||||
*Manufacturing Request*.
|
||||
2
mrp_production_request/readme/CONTRIBUTORS.rst
Normal file
2
mrp_production_request/readme/CONTRIBUTORS.rst
Normal file
@@ -0,0 +1,2 @@
|
||||
* Lois Rilo Antelo <lois.rilo@eficent.com>
|
||||
* Jordi Ballester <jordi.ballester@eficent.com>
|
||||
10
mrp_production_request/readme/DESCRIPTION.rst
Normal file
10
mrp_production_request/readme/DESCRIPTION.rst
Normal file
@@ -0,0 +1,10 @@
|
||||
This module extends the functionality of Manufacturing to allow you to use
|
||||
Manufacturing Request (MR) as a previous step to Manufacturing Orders (MO).
|
||||
|
||||
Some of the benefits you can obtain are:
|
||||
|
||||
* Allow managers to review what is going to be manufactured.
|
||||
* Better control of manufacturing calendar.
|
||||
* Manage big requirements splitting them in batches.
|
||||
* Know your bottleneck component in advance and only schedule what you really
|
||||
can build.
|
||||
4
mrp_production_request/readme/HISTORY.rst
Normal file
4
mrp_production_request/readme/HISTORY.rst
Normal file
@@ -0,0 +1,4 @@
|
||||
11.0.1.0.0 (2018-09-13)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* [MIG] Migration to v11. Start of the history.
|
||||
2
mrp_production_request/readme/ROADMAP.rst
Normal file
2
mrp_production_request/readme/ROADMAP.rst
Normal file
@@ -0,0 +1,2 @@
|
||||
* Take into account workstations.
|
||||
* Take into account consumable products.
|
||||
28
mrp_production_request/readme/USAGE.rst
Normal file
28
mrp_production_request/readme/USAGE.rst
Normal file
@@ -0,0 +1,28 @@
|
||||
To use this module, you need to:
|
||||
|
||||
#. Go to *Manufacturing > Manufacturing Requests*.
|
||||
#. Create a manufacturing request or open a existing one (assigned to you or
|
||||
created from a procurement).
|
||||
#. If you click on *Request approval* button the user assigned as approver
|
||||
will be added to the thread.
|
||||
#. If you are the approver you can either click on *Approve* or *Reject*
|
||||
buttons.
|
||||
#. Rejecting a MR will cancel it and propagate this cancellation to
|
||||
destination moves.
|
||||
#. Approving a MR will allow you to create manufacturing orders.
|
||||
#. You can manually set to done a request by clicking in the button *Done*.
|
||||
|
||||
To create MOs from MRs you have to:
|
||||
|
||||
#. Go to approved manufacturing request.
|
||||
#. Click on the button *Create Manufacturing Order*.
|
||||
#. In the opened wizard, click on *Compute lines* so you will have a
|
||||
quantity proposed for creating a MO. This quantity is the maximum quantity
|
||||
you can produce with the current stock available for the components needed
|
||||
in the source location.
|
||||
#. Use the proposed quantity or change it and click on *Create MO* at the
|
||||
bottom of the wizard.
|
||||
|
||||
**NOTE:** This module does not restrict the quantity that can be converted
|
||||
from a MR to MOs. It is in hands of the user to decide when a MR is ended and
|
||||
to set it to *Done* state.
|
||||
@@ -1,4 +1 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from . import test_mrp_production_request
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# Copyright 2017-18 Eficent Business and IT Consulting Services S.L.
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo.tests.common import TransactionCase
|
||||
@@ -14,38 +13,90 @@ class TestMrpProductionRequest(TransactionCase):
|
||||
self.request_model = self.env['mrp.production.request']
|
||||
self.wiz_model = self.env['mrp.production.request.create.mo']
|
||||
self.bom_model = self.env['mrp.bom']
|
||||
self.group_model = self.env['procurement.group']
|
||||
self.product_model = self.env['product.product']
|
||||
self.bom_model = self.env['mrp.bom']
|
||||
self.boml_model = self.env['mrp.bom.line']
|
||||
|
||||
self.warehouse = self.env.ref('stock.warehouse0')
|
||||
self.stock_loc = self.env.ref('stock.stock_location_stock')
|
||||
route_manuf = self.env.ref('mrp.route_warehouse0_manufacture')
|
||||
|
||||
# Prepare Products:
|
||||
self.product = self.env.ref('product.product_product_3')
|
||||
self.product.mrp_production_request = True
|
||||
self.product.route_ids = [(4, route_manuf.id, 0)]
|
||||
|
||||
self.test_product = self.env['product.product'].create({
|
||||
self.product_no_bom = self.product_model.create({
|
||||
'name': 'Test Product without BoM',
|
||||
'mrp_production_request': True,
|
||||
'route_ids': [(6, 0, route_manuf.ids)],
|
||||
})
|
||||
self.product_orderpoint = self.product_model.create({
|
||||
'name': 'Test Product for orderpoint',
|
||||
'mrp_production_request': True,
|
||||
'route_ids': [(6, 0, route_manuf.ids)],
|
||||
})
|
||||
product_component = self.product_model.create({
|
||||
'name': 'Test component',
|
||||
'mrp_production_request': True,
|
||||
'route_ids': [(6, 0, route_manuf.ids)],
|
||||
})
|
||||
|
||||
# Create Bill of Materials:
|
||||
self.test_bom_1 = self.bom_model.create({
|
||||
'product_id': self.product_orderpoint.id,
|
||||
'product_tmpl_id': self.product_orderpoint.product_tmpl_id.id,
|
||||
'product_uom_id': self.product_orderpoint.uom_id.id,
|
||||
'product_qty': 1.0,
|
||||
'type': 'normal',
|
||||
})
|
||||
self.boml_model.create({
|
||||
'bom_id': self.test_bom_1.id,
|
||||
'product_id': product_component.id,
|
||||
'product_qty': 1.0,
|
||||
})
|
||||
|
||||
# Create Orderpoint:
|
||||
self.orderpoint = self.env['stock.warehouse.orderpoint'].create({
|
||||
'warehouse_id': self.warehouse.id,
|
||||
'location_id': self.warehouse.lot_stock_id.id,
|
||||
'product_id': self.product_orderpoint.id,
|
||||
'product_min_qty': 10.0,
|
||||
'product_max_qty': 50.0,
|
||||
'product_uom': self.product_orderpoint.uom_id.id,
|
||||
})
|
||||
|
||||
# Create Procurement Group:
|
||||
self.test_group = self.group_model.create({
|
||||
'name': 'TEST',
|
||||
})
|
||||
|
||||
# Create User:
|
||||
self.test_user = self.env['res.users'].create({
|
||||
'name': 'John',
|
||||
'login': 'test',
|
||||
})
|
||||
|
||||
def create_procurement(self, name, product):
|
||||
def procure(self, group, product, qty=4.0,):
|
||||
values = {
|
||||
'name': name,
|
||||
'date_planned': fields.Datetime.now(),
|
||||
'product_id': product.id,
|
||||
'product_qty': 4.0,
|
||||
'product_uom': product.uom_id.id,
|
||||
'warehouse_id': self.env.ref('stock.warehouse0').id,
|
||||
'location_id': self.env.ref('stock.stock_location_stock').id,
|
||||
'route_ids': [
|
||||
(4, self.env.ref('mrp.route_warehouse0_manufacture').id, 0)],
|
||||
'group_id': group,
|
||||
}
|
||||
return self.env['procurement.order'].create(values)
|
||||
self.group_model.run(
|
||||
product, qty, product.uom_id, self.stock_loc,
|
||||
group.name, group.name, values,
|
||||
)
|
||||
return True
|
||||
|
||||
def test_manufacture_request(self):
|
||||
def test_01_manufacture_request(self):
|
||||
"""Tests manufacture request workflow."""
|
||||
proc = self.create_procurement('TEST/01', self.product)
|
||||
request = proc.mrp_production_request_id
|
||||
self.procure(self.test_group, self.product)
|
||||
request = self.request_model.search([
|
||||
('product_id', '=', self.product.id),
|
||||
('procurement_group_id', '=', self.test_group.id),
|
||||
])
|
||||
self.assertEqual(len(request), 1)
|
||||
request.button_to_approve()
|
||||
request.button_draft()
|
||||
request.button_to_approve()
|
||||
@@ -61,32 +112,7 @@ class TestMrpProductionRequest(TransactionCase):
|
||||
self.assertEqual(request.pending_qty, 0.0)
|
||||
request.button_done()
|
||||
|
||||
def test_cancellation_from_request(self):
|
||||
"""Tests propagation of cancel to procurements from manufacturing
|
||||
request and not from manufacturing order."""
|
||||
proc = self.create_procurement('TEST/02', self.product)
|
||||
request = proc.mrp_production_request_id
|
||||
wiz = self.wiz_model.with_context(active_ids=request.ids).create({})
|
||||
wiz.mo_qty = 4.0
|
||||
wiz.create_mo()
|
||||
with self.assertRaises(UserError):
|
||||
request.button_draft()
|
||||
mo = self.production_model.search([
|
||||
('mrp_production_request_id', '=', request.id)])
|
||||
mo.action_cancel()
|
||||
self.assertNotEqual(proc.state, 'cancel')
|
||||
request.button_cancel()
|
||||
self.assertEqual(proc.state, 'cancel')
|
||||
|
||||
def test_cancellation_from_proc(self):
|
||||
"""Tests cancelation from procurement."""
|
||||
proc = self.create_procurement('TEST/03', self.product)
|
||||
request = proc.mrp_production_request_id
|
||||
self.assertNotEqual(request.state, 'cancel')
|
||||
proc.cancel()
|
||||
self.assertEqual(request.state, 'cancel')
|
||||
|
||||
def test_assignation(self):
|
||||
def test_02_assignation(self):
|
||||
"""Tests assignation of manufacturing requests."""
|
||||
randon_bom_id = self.bom_model.search([], limit=1).id
|
||||
request = self.request_model.create({
|
||||
@@ -105,15 +131,27 @@ class TestMrpProductionRequest(TransactionCase):
|
||||
self.assertTrue(request.message_follower_ids,
|
||||
"Followers not added correctly.")
|
||||
|
||||
def test_raise_errors(self):
|
||||
def test_03_substract_qty_from_orderpoint(self):
|
||||
"""Quantity in Manufacturing Requests should be considered by
|
||||
orderpoints."""
|
||||
request = self.request_model.search([
|
||||
('product_id', '=', self.product_orderpoint.id),
|
||||
])
|
||||
self.assertFalse(request)
|
||||
self.env['procurement.group'].run_scheduler()
|
||||
request = self.request_model.search([
|
||||
('product_id', '=', self.product_orderpoint.id),
|
||||
])
|
||||
self.assertEqual(len(request), 1)
|
||||
# Running again the scheduler should not generate a new MR.
|
||||
self.env['procurement.group'].run_scheduler()
|
||||
request = self.request_model.search([
|
||||
('product_id', '=', self.product_orderpoint.id),
|
||||
])
|
||||
self.assertEqual(len(request), 1)
|
||||
|
||||
def test_04_raise_errors(self):
|
||||
"""Tests user errors raising properly."""
|
||||
proc_no_bom = self.create_procurement('TEST/05', self.test_product)
|
||||
self.assertEqual(proc_no_bom.state, 'exception')
|
||||
proc = self.create_procurement('TEST/05', self.product)
|
||||
request = proc.mrp_production_request_id
|
||||
request.button_to_approve()
|
||||
proc.write({'state': 'done'})
|
||||
with self.assertRaises(UserError):
|
||||
request.button_cancel()
|
||||
with self.assertRaises(UserError):
|
||||
request.button_draft()
|
||||
# No Bill of Materials:
|
||||
self.procure(self.test_group, self.product_no_bom)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2017 Eficent Business and IT Consulting Services S.L.
|
||||
<!-- Copyright 2017-18 Eficent Business and IT Consulting Services S.L.
|
||||
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl-3.0) -->
|
||||
<odoo>
|
||||
|
||||
@@ -33,6 +33,16 @@
|
||||
statusbar_visible="draft,approved,done"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button type="object" name="action_view_mrp_productions"
|
||||
class="oe_stat_button"
|
||||
icon="fa-wrench"
|
||||
attrs="{'invisible': [('mrp_production_count', '=', 0)]}">
|
||||
<field name="mrp_production_count" widget="statinfo"
|
||||
string="MOs"/>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<label string="Manufacturing Request"/>
|
||||
<h1>
|
||||
<field name="name"/>
|
||||
@@ -61,8 +71,9 @@
|
||||
<field name="requested_by"/>
|
||||
<field name="assigned_to"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="description"/>
|
||||
<group name="dates">
|
||||
<field name="date_planned_start"/>
|
||||
<field name="date_planned_finished" invisible="1"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
@@ -71,20 +82,17 @@
|
||||
</page>
|
||||
<page name="extra" string="Extra information">
|
||||
<group>
|
||||
<group>
|
||||
<field name="procurement_id"/>
|
||||
<field name="procurement_state"/>
|
||||
<field name="origin"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="location_src_id"/>
|
||||
<field name="location_dest_id"/>
|
||||
<field name="picking_type_id"/>
|
||||
<field name="date_planned_start"/>
|
||||
<field name="date_planned_finished" invisible="1"/>/>
|
||||
</group>
|
||||
</group>
|
||||
|
||||
</group>
|
||||
<group>
|
||||
<field name="origin"/>
|
||||
<field name="description"/>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
@@ -142,6 +150,10 @@
|
||||
string="Pending Qty" name="pending"
|
||||
help="Request with pending quantity"/>
|
||||
<separator/>
|
||||
<filter string="To Do" name="todo"
|
||||
domain="[('state','in',('draft', 'to_approve','approved'))]"
|
||||
help="Manufacturing Requests not done or cancelled."/>
|
||||
<separator/>
|
||||
<filter name="state_draft" string="Draft"
|
||||
domain="[('state','=','draft')]"
|
||||
help="Request is to be approved"/>
|
||||
@@ -157,11 +169,10 @@
|
||||
<filter name="state_done" string="Done"
|
||||
domain="[('state','=','done')]"
|
||||
help="Request is done"/>
|
||||
<separator/>
|
||||
<filter string="Unread Messages"
|
||||
name="message_needaction"
|
||||
domain="[('message_needaction','=',True)]"/>
|
||||
<filter domain="[('requested_by','=', uid)]"
|
||||
help="My requests"/>
|
||||
<!--Group by:-->
|
||||
<filter string="Requested by" icon="terp-personal"
|
||||
domain="[]"
|
||||
@@ -182,7 +193,7 @@
|
||||
<field name="res_model">mrp.production.request</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="context">{"search_default_pending":1}</field>
|
||||
<field name="context">{"search_default_todo":1}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to start a new manufacturing request process.
|
||||
@@ -204,22 +215,10 @@
|
||||
<record id="action_server_mrp_production_request_refresh"
|
||||
model="ir.actions.server">
|
||||
<field name="name">Refresh Quantities</field>
|
||||
<field name="condition">True</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_mrp_production_request" />
|
||||
<field name="binding_model_id" ref="model_mrp_production_request"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">self._compute_manufactured_qty(cr, uid, context.get('active_ids', []), context=context)</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.values" id="action_mrp_production_request_refresh">
|
||||
<field name="name">Compute Quantities</field>
|
||||
<field name="action_id"
|
||||
ref="action_server_mrp_production_request_refresh" />
|
||||
<field name="value" eval="'ir.actions.server,' + str(ref('action_server_mrp_production_request_refresh'))" />
|
||||
<field name="key">action</field>
|
||||
<field name="model_id" ref="model_mrp_production_request" />
|
||||
<field name="model">mrp.production.request</field>
|
||||
<field name="key2">client_action_multi</field>
|
||||
<field name="code">records._compute_manufactured_qty()</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2017 Eficent Business and IT Consulting Services S.L.
|
||||
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl-3.0) -->
|
||||
<odoo>
|
||||
|
||||
<record model="ir.ui.view" id="procurement_form_view">
|
||||
<field name="name">procurement.order.form - mrp_production_request</field>
|
||||
<field name="model">procurement.order</field>
|
||||
<field name="inherit_id" ref="procurement.procurement_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='origin']" position="after">
|
||||
<field name="mrp_production_request_id"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1,4 +1 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from . import mrp_production_request_create_mo
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2017-18 Eficent Business and IT Consulting Services S.L.
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
@@ -98,7 +97,6 @@ class MrpProductionRequestCreateMo(models.TransientModel):
|
||||
'date_planned_start': request_id.date_planned_start,
|
||||
'date_planned_finished': request_id.date_planned_finished,
|
||||
'procurement_group_id': request_id.procurement_group_id.id,
|
||||
'procurement_ids': [(6, 0, request_id.procurement_ids.ids)],
|
||||
'propagate': request_id.propagate,
|
||||
'company_id': request_id.company_id.id,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user