Merge pull request #227 from Eficent/9.0-add-mrp_production_unreserve

[9.0][ADD] mrp_production_unreserve
This commit is contained in:
Lois Rilo
2018-05-18 16:43:44 +02:00
committed by GitHub
9 changed files with 253 additions and 0 deletions

View 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.

View File

@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from . import models

View 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",
],
}

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

View File

@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from . import mrp_production

View 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

View 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

View File

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

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