mirror of
https://github.com/OCA/manufacture.git
synced 2025-01-28 16:37:15 +02:00
Merge pull request #227 from Eficent/9.0-add-mrp_production_unreserve
[9.0][ADD] mrp_production_unreserve
This commit is contained in:
64
mrp_production_unreserve/README.rst
Normal file
64
mrp_production_unreserve/README.rst
Normal file
@@ -0,0 +1,64 @@
|
||||
.. 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 Unreserve
|
||||
========================
|
||||
|
||||
This module backports the functionality of Manufacturing Orders (MOs) in v10
|
||||
which allows to unreserve MOs.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
To use this module, you need to:
|
||||
|
||||
#. Go to a confirmed MO with some *Products to Consume* in black font (which
|
||||
means that they are reserved).
|
||||
#. Click the new button *Unreserve*.
|
||||
|
||||
.. 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/9.0
|
||||
|
||||
Known issues / Roadmap
|
||||
======================
|
||||
|
||||
* No need to migrate this module further. The feature is out-of-the-box in v10.
|
||||
|
||||
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.
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
Images
|
||||
------
|
||||
|
||||
* Odoo Community Association: `Icon <https://github.com/OCA/maintainer-tools/blob/master/template/module/static/description/icon.svg>`_.
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
||||
* Lois Rilo Antelo <lois.rilo@eficent.com>
|
||||
|
||||
Maintainer
|
||||
----------
|
||||
|
||||
.. 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.
|
||||
4
mrp_production_unreserve/__init__.py
Normal file
4
mrp_production_unreserve/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from . import models
|
||||
20
mrp_production_unreserve/__openerp__.py
Normal file
20
mrp_production_unreserve/__openerp__.py
Normal file
@@ -0,0 +1,20 @@
|
||||
# -*- 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).
|
||||
{
|
||||
"name": "MRP Production Unreserve",
|
||||
"summary": "Allows you to unreserve Manufacturing Orders.",
|
||||
"version": "9.0.1.0.0",
|
||||
"category": "Manufacturing",
|
||||
"website": "https://github.com/OCA/manufacture",
|
||||
"author": "Eficent, "
|
||||
"Odoo Community Association (OCA)",
|
||||
"license": "AGPL-3",
|
||||
"application": False,
|
||||
"installable": True,
|
||||
"depends": ["mrp"],
|
||||
"data": [
|
||||
"views/mrp_production_view.xml",
|
||||
"data/mrp_workflow.xml",
|
||||
],
|
||||
}
|
||||
15
mrp_production_unreserve/data/mrp_workflow.xml
Normal file
15
mrp_production_unreserve/data/mrp_workflow.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<?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 id="prod_trans_unreserved" model="workflow.transition">
|
||||
<field name="act_from" ref="mrp.prod_act_ready"/>
|
||||
<field name="act_to" ref="mrp.prod_act_confirmed"/>
|
||||
<field name="signal">moves_unreserved</field>
|
||||
<field name="trigger_model" eval="False"/> <!-- Force empty -->
|
||||
<field name="trigger_expr_id" eval="False"/> <!-- Force empty -->
|
||||
<field name="condition">True</field> <!-- Force default -->
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
4
mrp_production_unreserve/models/__init__.py
Normal file
4
mrp_production_unreserve/models/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from . import mrp_production
|
||||
45
mrp_production_unreserve/models/mrp_production.py
Normal file
45
mrp_production_unreserve/models/mrp_production.py
Normal file
@@ -0,0 +1,45 @@
|
||||
# -*- 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 openerp import api, fields, models
|
||||
from openerp import workflow
|
||||
|
||||
|
||||
class MrpProduction(models.Model):
|
||||
_inherit = "mrp.production"
|
||||
|
||||
unreserve_visible = fields.Boolean(
|
||||
string='MO Unreserve Visible',
|
||||
compute='_compute_unreserve_visible',
|
||||
help='Technical field to check when we can unreserve',
|
||||
)
|
||||
|
||||
@api.depends('state', 'move_lines.reserved_quant_ids')
|
||||
def _compute_unreserve_visible(self):
|
||||
for order in self:
|
||||
if (order.state in ['done', 'cancel'] or not
|
||||
order.move_lines.mapped('reserved_quant_ids')):
|
||||
order.unreserve_visible = False
|
||||
else:
|
||||
order.unreserve_visible = True
|
||||
|
||||
@api.multi
|
||||
def button_unreserve(self):
|
||||
for production in self:
|
||||
production.move_lines.filtered(
|
||||
lambda x: x.state not in ('done', 'cancel')).do_unreserve()
|
||||
if not production.test_ready():
|
||||
workflow.trg_validate(
|
||||
self.env.uid, 'mrp.production', production.id,
|
||||
'moves_unreserved', self.env.cr)
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
def action_confirm(self):
|
||||
"""If a MO comes from 'ready' state it doesn't need to be confirmed
|
||||
again."""
|
||||
from_draft = self.filtered(lambda mo: not mo.move_lines)
|
||||
res = super(MrpProduction, from_draft).action_confirm()
|
||||
self.write({'state': 'confirmed'})
|
||||
return res
|
||||
4
mrp_production_unreserve/tests/__init__.py
Normal file
4
mrp_production_unreserve/tests/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from . import test_mrp_production_unreserve
|
||||
@@ -0,0 +1,76 @@
|
||||
# -*- 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 openerp.tests.common import TransactionCase
|
||||
|
||||
|
||||
class TestMrpProductionUnreserve(TransactionCase):
|
||||
def setUp(self, *args, **kwargs):
|
||||
super(TestMrpProductionUnreserve, self).setUp(*args, **kwargs)
|
||||
self.production_model = self.env['mrp.production']
|
||||
self.bom_model = self.env['mrp.bom']
|
||||
self.product_model = self.env['product.product']
|
||||
self.quant_model = self.env['stock.quant']
|
||||
|
||||
# Create products, BoM and MO:
|
||||
self.product = self.product_model.create({
|
||||
'name': 'Test Product',
|
||||
'type': 'product',
|
||||
})
|
||||
self.component_a = self.product_model.create({
|
||||
'name': 'Component A',
|
||||
'type': 'product',
|
||||
})
|
||||
self.component_b = self.product_model.create({
|
||||
'name': 'Component B',
|
||||
'type': 'product',
|
||||
})
|
||||
self.test_bom = self.bom_model.create({
|
||||
'product_tmpl_id': self.product.product_tmpl_id.id,
|
||||
'product_qty': 1,
|
||||
'code': 'TEST',
|
||||
'bom_line_ids': [
|
||||
(0, 0, {
|
||||
'product_id': self.component_a.id,
|
||||
'product_qty': 2,
|
||||
}),
|
||||
(0, 0, {
|
||||
'product_id': self.component_b.id,
|
||||
'product_qty': 1,
|
||||
})
|
||||
],
|
||||
})
|
||||
self.test_mo = self.production_model.create({
|
||||
'product_id': self.product.id,
|
||||
'product_qty': 5.0,
|
||||
'product_uom': self.product.uom_id.id,
|
||||
'bom_id': self.test_bom.id,
|
||||
})
|
||||
# Create Stock for components:
|
||||
wh_main = self.browse_ref('stock.warehouse0')
|
||||
stock_location_id = wh_main.lot_stock_id.id
|
||||
self.quant_model.create({
|
||||
'product_id': self.component_a.id,
|
||||
'location_id': stock_location_id,
|
||||
'qty': 10.0,
|
||||
})
|
||||
self.quant_model.create({
|
||||
'product_id': self.component_b.id,
|
||||
'location_id': stock_location_id,
|
||||
'qty': 5.0,
|
||||
})
|
||||
|
||||
def test_mo_unreserve(self):
|
||||
self.test_mo._compute_unreserve_visible()
|
||||
self.assertFalse(self.test_mo.unreserve_visible)
|
||||
self.assertFalse(self.test_mo.move_lines)
|
||||
self.test_mo.action_confirm()
|
||||
self.test_mo.action_assign()
|
||||
for l in self.test_mo.move_lines:
|
||||
self.assertEqual(l.state, 'assigned')
|
||||
self.test_mo._compute_unreserve_visible()
|
||||
self.assertTrue(self.test_mo.unreserve_visible)
|
||||
self.test_mo.button_unreserve()
|
||||
for l in self.test_mo.move_lines:
|
||||
self.assertEqual(l.state, 'confirmed')
|
||||
21
mrp_production_unreserve/views/mrp_production_view.xml
Normal file
21
mrp_production_unreserve/views/mrp_production_view.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<?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 id="mrp_production_form_view" model="ir.ui.view">
|
||||
<field name="name">mrp.production.form - mrp_production_unreserved</field>
|
||||
<field name="model">mrp.production</field>
|
||||
<field name="inherit_id"
|
||||
ref="mrp.mrp_production_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<button name="action_assign" position="after">
|
||||
<field name="unreserve_visible" invisible="1"/>
|
||||
<button name="button_unreserve" type="object"
|
||||
string="Unreserve"
|
||||
attrs="{'invisible': [('unreserve_visible', '=', False)]}"/>
|
||||
</button>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user