Skip to content

Commit

Permalink
Merge pull request #53 from SerpentCS/9.0-mrp_operating_unit
Browse files Browse the repository at this point in the history
9.0 mrp operating unit - migrated
  • Loading branch information
JordiBForgeFlow authored Sep 28, 2016
2 parents ae21fc8 + 876cc7e commit 5bc54f5
Show file tree
Hide file tree
Showing 11 changed files with 428 additions and 0 deletions.
68 changes: 68 additions & 0 deletions mrp_operating_unit/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
.. image:: https://img.shields.io/badge/license-LGPLv3-blue.svg
:target: https://www.gnu.org/licenses/lgpl.html
:alt: License: LGPL-3

========================
MRP with Operating Units
========================

This module introduces the following features:

* Adds Operating Unit (OU) to the Manufacturing Order created from the procurement.

* This module implements global security rules on manufacturing orders so that a user can only read manufacturing orders where the location is linked to an
operating unit that the user has access to.

Installation
============

No specific installation requirements.

Configuration
=============

No configuration is required.

Usage
=====

.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/213/9.0

Bug Tracker
===========

Bugs are tracked on `GitHub Issues
<https://github.com/OCA/operating-unit/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.

Credits
=======

Images
------

* Odoo Community Association: `Icon <https://github.com/OCA/maintainer-tools/blob/master/template/module/static/description/icon.svg>`_.

Contributors
------------

* Eficent Business and IT Consulting Services S.L. <[email protected]>
* Serpent Consulting Services Pvt. Ltd. <[email protected]>

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.
7 changes: 7 additions & 0 deletions mrp_operating_unit/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# -*- coding: utf-8 -*-
# © 2015 Eficent Business and IT Consulting Services S.L. -
# Jordi Ballester Alomar
# © 2015 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
from . import models
from . import tests
23 changes: 23 additions & 0 deletions mrp_operating_unit/__openerp__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
# © 2015 Eficent Business and IT Consulting Services S.L. -
# Jordi Ballester Alomar
# © 2015 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).

{
"name": "Operating Unit in MRP",
"version": "9.0.1.0.0",
"author": "Eficent Business and IT Consulting Services S.L., "
"Serpent Consulting Services Pvt. Ltd.,"
"Odoo Community Association (OCA)",
"website": "http://www.eficent.com",
"license": "LGPL-3",
"category": "Manufacturing",
"depends": ["mrp",
"procurement_operating_unit"],
"data": [
"security/mrp_security.xml",
"views/mrp_view.xml"
],
'installable': True,
}
8 changes: 8 additions & 0 deletions mrp_operating_unit/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# -*- coding: utf-8 -*-
# © 2015 Eficent Business and IT Consulting Services S.L. -
# Jordi Ballester Alomar
# © 2015 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).

from . import mrp
from . import procurement
46 changes: 46 additions & 0 deletions mrp_operating_unit/models/mrp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# -*- coding: utf-8 -*-
# © 2015 Eficent Business and IT Consulting Services S.L. -
# Jordi Ballester Alomar
# © 2015 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).

from openerp import api, fields, models
from openerp.tools.translate import _
from openerp.exceptions import Warning


class MrpProduction(models.Model):

_inherit = 'mrp.production'

operating_unit_id = fields.Many2one('operating.unit', 'Operating Unit',
default=lambda self:
self.env['res.users'].
operating_unit_default_get(self._uid))

@api.constrains('operating_unit_id', 'location_src_id', 'location_dest_id')
def _check_location_operating_unit(self):
for mo in self:
if (
not mo.operating_unit_id and
(mo.location_src_id.operating_unit_id or
mo.location_dest_id.operating_unit_id)
):
raise Warning(_('The Operating Unit of the Manufacturing Order\
must match with that of the Raw Materials and\
Finished Product Locations.'))
if (
mo.operating_unit_id and
mo.operating_unit_id != mo.location_src_id.operating_unit_id
):
raise Warning(_('The Operating Unit of the Manufacturing Order\
must match with that of the Raw Materials and\
Finished Product Locations.'))
if (
mo.operating_unit_id and
mo.operating_unit_id != mo.location_dest_id.operating_unit_id
):
raise Warning(_('The Operating Unit of the Manufacturing Order\
must match with that of the Raw Materials and\
Finished Product Locations.'))
return True
34 changes: 34 additions & 0 deletions mrp_operating_unit/models/procurement.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
# © 2015 Eficent Business and IT Consulting Services S.L. -
# Jordi Ballester Alomar
# © 2015 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
from openerp import api, fields, models
from openerp.tools.translate import _
from openerp.exceptions import Warning


class ProcurementOrder(models.Model):

_inherit = 'procurement.order'

@api.constrains('location_id', 'production_id')
def _check_mrp_production_operating_unit(self):
for pr in self:
if (
pr.production_id and
pr.location_id.operating_unit_id and
pr.production_id.operating_unit_id !=
pr.location_id.operating_unit_id
):
raise Warning(_('The Production Order and the Procurement\
Order must belong to the same Operating Unit.'))
return True

@api.model
def _prepare_mo_vals(self, procurement):
res = super(ProcurementOrder, self)._prepare_mo_vals(procurement)
if procurement.location_id.operating_unit_id:
res['operating_unit_id'] = \
procurement.location_id.operating_unit_id.id
return res
21 changes: 21 additions & 0 deletions mrp_operating_unit/security/mrp_security.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2015 Eficent Business and IT Consulting Services S.L.
Serpent Consulting Services Pvt. Ltd.
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl-3.0) -->
<openerp>
<data noupdate="0">

<record id="ir_rule_production_order_allowed_operating_units"
model="ir.rule">
<field name="model_id" ref="mrp.model_mrp_production"/>
<field name="domain_force">['|',('operating_unit_id','=',False),('operating_unit_id','in',[g.id for g in user.operating_unit_ids])]</field>
<field name="name">Manufacturing Orders from allowed operating units</field>
<field name="global" eval="True"/>
<field eval="0" name="perm_unlink"/>
<field eval="0" name="perm_write"/>
<field eval="1" name="perm_read"/>
<field eval="0" name="perm_create"/>
</record>

</data>
</openerp>
7 changes: 7 additions & 0 deletions mrp_operating_unit/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# -*- coding: utf-8 -*-
# © 2015 Eficent Business and IT Consulting Services S.L. -
# Jordi Ballester Alomar
# © 2015 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
from . import test_procurement
from . import test_mrp_operating_unit
92 changes: 92 additions & 0 deletions mrp_operating_unit/tests/test_mrp_operating_unit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
from openerp.tests import common


class TestMrpOperatingUnit(common.TransactionCase):

def setUp(self):
super(TestMrpOperatingUnit, self).setUp()
self.res_users_model = self.env['res.users']
self.mrp_production_model = self.env['mrp.production']
self.company = self.env.ref('base.main_company')

# Products
self.product1 = self.env.ref('product.product_product_4c')
# Stock Location
self.stock_location = self.env.ref('stock.stock_location_shop0')

# Main Operating Unit
self.ou1 = self.env.ref('operating_unit.main_operating_unit')
# Chicago Operating Unit
self.chicago = self.env.ref('stock_operating_unit.operating_unit_shop0')

# Groups
self.grp_mrp_saleman = self.env.ref('base.group_sale_salesman')

# Users
self.user1 = self._create_user('user_1',
[self.grp_mrp_saleman],
self.company,
[self.ou1, self.chicago])
self.user2 = self._create_user('user_2',
[self.grp_mrp_saleman],
self.company,
[self.chicago])

# Manufacturing Orders
self.mrp_record1 = self._create_mrp('Manufacturing Order 1', self.ou1)
self.mrp_record2 = self._create_mrp('Manufacturing Order 2',
self.chicago, self.stock_location)


def _create_user(self, login, groups, company, operating_units,
context=None):
"""Create a user."""
group_ids = [group.id for group in groups]
user = self.res_users_model.create({
'name': 'Test HR Contrac User',
'login': login,
'password': 'demo',
'email': '[email protected]',
'company_id': company.id,
'company_ids': [(4, company.id)],
'operating_unit_ids': [(4, ou.id) for ou in operating_units],
'groups_id': [(6, 0, group_ids)]
})
return user

def _create_mrp(self, name, operating_unit, stock_location=False):
new_line = self.mrp_production_model.new()
res = new_line.product_id_change(product_id=self.product1.id)
if res.get('value') and res.get('value').get('bom_id'):
bom_id = res.get('value').get('bom_id')
if res.get('value') and res.get('value').get('product_uom'):
product_uom = res.get('value').get('product_uom')
if operating_unit is self.ou1:
mrp = self.mrp_production_model.create({
'name': name,
'product_id': self.product1.id,
'bom_id': bom_id,
'product_qty': '10.0',
'product_uom': product_uom,
'operating_unit_id': operating_unit.id,
})
else:
mrp = self.mrp_production_model.create({
'name': name,
'product_id': self.product1.id,
'bom_id': bom_id,
'product_qty': '10.0',
'product_uom': product_uom,
'operating_unit_id': operating_unit.id,
'location_src_id': stock_location.id,
'location_dest_id': stock_location.id
})
return mrp

def test_mrp_ou(self):
record = self.mrp_production_model.sudo(self.user2.id).search(
[('id', '=', self.mrp_record1.id),
('operating_unit_id', '=',
self.ou1.id)])
self.assertEqual(record.ids, [], 'User 2 should not have access to '
'OU : %s' % self.ou1.name)
76 changes: 76 additions & 0 deletions mrp_operating_unit/tests/test_procurement.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# -*- coding: utf-8 -*-
# © 2015 Eficent Business and IT Consulting Services S.L. -
# Jordi Ballester Alomar
# © 2015 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
from openerp.tests import common


class TestProcurement(common.TransactionCase):

def setUp(self):
super(TestProcurement, self).setUp()
self.res_users_model = self.env['res.users']
self.procurement_order_model = self.env['procurement.order']
self.procurement_rule_model = self.env['procurement.rule']
self.bom_model = self.env['mrp.bom']
self.warehouse = self.env.ref('stock.warehouse0')

# Main Operating Unit
self.ou1 = self.env.ref('operating_unit.main_operating_unit')
# B2C Operating Unit
self.b2c = self.env.ref('operating_unit.b2c_operating_unit')

# Products
self.product1 = self.env.ref('product.product_product_9')

self.rule = self._create_procurement_rule()
self.mrp_bom_method = self._create_bom()
self.procurement_order = self._create_procurement_order()


def _create_procurement_rule(self):
rule = self.procurement_rule_model.create({
'name': 'Procurement rule',
'action': 'manufacture'
})
return rule

def _create_bom(self):
bom = self.bom_model.create({
'product_tmpl_id': self.product1.product_tmpl_id.id,
'product_id': self.product1.id,
'product_qty': '1',
'type': 'normal',
'product_efficiency': '1.00',
})
return bom

def _create_procurement_order(self):
# On change for warehouse_id
new_line = self.procurement_order_model.new()
res = new_line.change_warehouse_id(self.warehouse.id)
if res.get('value') and res.get('value').get('location_id'):
location_id = res.get('value').get('location_id')
# On change for product_id
new_line = self.procurement_order_model.new()
res = new_line.onchange_product_id(self.product1.id)
if res.get('value') and res.get('value').get('product_uom'):
product_uom = res.get('value').get('product_uom')
order = self.procurement_order_model.create({
'product_id': self.product1.id,
'product_uom': product_uom,
'product_qty': '10',
'name': 'Procurement Order',
'warehouse_id': self.warehouse.id,
'bom_id': self.mrp_bom_method.id,
'rule_id': self.rule.id,
'location_id': location_id,
})
return order

def test_security(self):
self.assertEqual(self.procurement_order.location_id.operating_unit_id,
self.procurement_order.production_id.operating_unit_id,
'The Operating Unit in Procurement Order Location'
'does not match to Manufacturing Order OU.')
Loading

0 comments on commit 5bc54f5

Please sign in to comment.