[IMP] mrp_hook+mrp_operations_extension: Adaptation to OCA
@@ -3,6 +3,7 @@
|
||||
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
from openerp import models, fields, api
|
||||
from openerp.tools import config
|
||||
|
||||
|
||||
class MrpBom(models.Model):
|
||||
@@ -24,14 +25,29 @@ class MrpBom(models.Model):
|
||||
parent = parent.parent_bom
|
||||
self.old_versions = old_version
|
||||
|
||||
def _default_active(self):
|
||||
"""Needed for preserving normal flow when testing other modules."""
|
||||
res = False
|
||||
if config['test_enable']:
|
||||
res = not bool(self.env.context.get('test_mrp_bom_version'))
|
||||
return res
|
||||
|
||||
def _default_state(self):
|
||||
"""Needed for preserving normal flow when testing other modules."""
|
||||
res = 'active'
|
||||
if (config['test_enable'] and
|
||||
self.env.context.get('test_mrp_bom_version')):
|
||||
res = 'draft'
|
||||
return res
|
||||
|
||||
active = fields.Boolean(
|
||||
string='Active', default=False, readonly=True,
|
||||
states={'draft': [('readonly', False)]})
|
||||
default=_default_active,
|
||||
readonly=True, states={'draft': [('readonly', False)]})
|
||||
historical_date = fields.Date(string='Historical Date', readonly=True)
|
||||
state = fields.Selection(
|
||||
selection=[('draft', 'Draft'), ('active', 'Active'),
|
||||
('historical', 'Historical')], string='State',
|
||||
index=True, readonly=True, default='draft', copy=False)
|
||||
index=True, readonly=True, default=_default_state, copy=False)
|
||||
product_tmpl_id = fields.Many2one(
|
||||
readonly=True, states={'draft': [('readonly', False)]})
|
||||
product_id = fields.Many2one(
|
||||
|
||||
@@ -10,7 +10,8 @@ class TestMrpBomVersion(common.TransactionCase):
|
||||
def setUp(self):
|
||||
super(TestMrpBomVersion, self).setUp()
|
||||
self.parameter_model = self.env['ir.config_parameter']
|
||||
self.bom_model = self.env['mrp.bom']
|
||||
self.bom_model = self.env['mrp.bom'].with_context(
|
||||
test_mrp_bom_version=True)
|
||||
self.company = self.env.ref('base.main_company')
|
||||
vals = {
|
||||
'company_id': self.company.id,
|
||||
|
||||
@@ -1,24 +1,35 @@
|
||||
.. 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
|
||||
|
||||
===============================
|
||||
Hooks for enabling advanced MRP
|
||||
===============================
|
||||
|
||||
Technical module that provides the proper framework infrastructure (hooks,
|
||||
fallback, etc) to enable advanced functionality in the manufacturing area,
|
||||
as https://github.com/odoo/odoo/pull/8885 hasn't been accepted for v8.
|
||||
as https://github.com/odoo/odoo/pull/8885 hasn't been accepted for v8:
|
||||
|
||||
* Hooks in *_bom_explode* method for returning dictionary for consume and
|
||||
* Hooks in *_bom_explode* method to return a dictionary for consumption and
|
||||
workcenter lines.
|
||||
* Provide product and template.
|
||||
* Provide product and template on *_bom_find*.
|
||||
|
||||
By itself it doesn't provide anything, but serves as base for others modules
|
||||
to develop its features.
|
||||
Usage
|
||||
=====
|
||||
|
||||
By itself it doesn't provide anything visible, but serves as base for others
|
||||
modules to develop its features.
|
||||
|
||||
.. 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/8.0
|
||||
|
||||
Known issues / Roadmap
|
||||
======================
|
||||
|
||||
* This module fully overwrites _bom_explode method, so any other module
|
||||
inheriting this method should take that into account.
|
||||
* On v9, this module can be removed.
|
||||
inheriting this method should take this into account.
|
||||
* On v9, this module can be removed, as the hooks have been integrated.
|
||||
|
||||
Credits
|
||||
=======
|
||||
@@ -27,3 +38,24 @@ Contributors
|
||||
------------
|
||||
|
||||
* Pedro M. Baeza <pedro.baeza@serviciosbaeza.com>
|
||||
|
||||
Images
|
||||
------
|
||||
|
||||
* Original Odoo MRP icon
|
||||
* Thanks to https://openclipart.org/detail/151441/lifting-hook
|
||||
|
||||
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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# (c) 2015 Serv. Tecnol. Avanzados - Pedro M. Baeza
|
||||
# © 2015 Serv. Tecnol. Avanzados - Pedro M. Baeza
|
||||
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
from . import models
|
||||
|
||||
@@ -5,10 +5,13 @@
|
||||
{
|
||||
"name": "MRP Hooks",
|
||||
"version": "8.0.1.0.0",
|
||||
"license": "AGPL-3",
|
||||
"category": "Hidden",
|
||||
"author": "OdooMRP team, "
|
||||
"AvanzOSC, "
|
||||
"Serv. Tecnol. Avanzados - Pedro M. Baeza",
|
||||
"Serv. Tecnol. Avanzados - Pedro M. Baeza, "
|
||||
"Antiun Ingeniería, "
|
||||
"Odoo Community Association (OCA), ",
|
||||
"website": "http://www.odoomrp.com",
|
||||
"contributors": [
|
||||
"Pedro M. Baeza <pedro.baeza@serviciosbaeza.com>",
|
||||
@@ -16,7 +19,8 @@
|
||||
"depends": [
|
||||
"mrp",
|
||||
],
|
||||
"data": [
|
||||
"images": [
|
||||
"images/image.png"
|
||||
],
|
||||
"installable": True
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ msgstr "Lista de material"
|
||||
#: code:addons/mrp_hook/models/mrp_bom.py:119
|
||||
#, python-format
|
||||
msgid "BoM \"%s\" contains a BoM line with a product recursion: \"%s\"."
|
||||
msgstr ""
|
||||
msgstr "La LdM \"%s\" contiene una línea con un producto recursivo: \"%s\"."
|
||||
|
||||
#. module: mrp_hook
|
||||
#: code:addons/mrp_hook/models/mrp_bom.py:147
|
||||
@@ -34,4 +34,6 @@ msgstr ""
|
||||
msgid ""
|
||||
"BoM \"%s\" contains a phantom BoM line but the product \"%s\" does not have "
|
||||
"any BoM defined."
|
||||
"La LdM \"%s\" contiene una línea fantasma pero el producto \"%s\" no tiene "
|
||||
"ninguna LdM definida."
|
||||
msgstr ""
|
||||
|
||||
BIN
mrp_hook/images/image.png
Normal file
|
After Width: | Height: | Size: 114 KiB |
81
mrp_hook/images/image.svg
Normal file
|
After Width: | Height: | Size: 125 KiB |
@@ -2,7 +2,7 @@
|
||||
# (c) 2015 Serv. Tecnol. Avanzados - Pedro M. Baeza
|
||||
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
from openerp import models, api, tools, _
|
||||
from openerp import api, models, tools, _
|
||||
from openerp.exceptions import Warning as UserError
|
||||
from openerp.addons.product import _common
|
||||
|
||||
@@ -66,17 +66,12 @@ class MrpBom(models.Model):
|
||||
def _bom_explode(self, cr, uid, bom, product, factor, properties=None,
|
||||
level=0, routing_id=False, previous_products=None,
|
||||
master_bom=None, context=None):
|
||||
return bom._bom_explode(
|
||||
product, factor, properties=properties, level=level,
|
||||
routing_id=routing_id, previous_products=previous_products,
|
||||
master_bom=master_bom)
|
||||
|
||||
@api.v8
|
||||
def _bom_explode(self, product, factor, properties=None, level=0,
|
||||
routing_id=False, previous_products=None,
|
||||
master_bom=None):
|
||||
""" Finds Products and Work Centers for related BoM for manufacturing
|
||||
order.
|
||||
|
||||
Verbatim copy of core method extracting the hooks already merged on
|
||||
v9 branch.
|
||||
|
||||
@param bom: BoM of particular product template.
|
||||
@param product: Select a particular variant of the BoM. If False use
|
||||
BoM without variants.
|
||||
@@ -91,6 +86,15 @@ class MrpBom(models.Model):
|
||||
@return: result: List of dictionaries containing product details.
|
||||
result2: List of dictionaries containing Work Center details.
|
||||
"""
|
||||
return bom._bom_explode(
|
||||
product, factor, properties=properties, level=level,
|
||||
routing_id=routing_id, previous_products=previous_products,
|
||||
master_bom=master_bom)
|
||||
|
||||
@api.v8
|
||||
def _bom_explode(self, product, factor, properties=None, level=0,
|
||||
routing_id=False, previous_products=None,
|
||||
master_bom=None):
|
||||
self.ensure_one()
|
||||
bom = self
|
||||
uom_obj = self.env["product.uom"]
|
||||
|
||||
BIN
mrp_hook/static/description/icon.png
Normal file
|
After Width: | Height: | Size: 8.7 KiB |
74
mrp_hook/static/description/icon.svg
Normal file
|
After Width: | Height: | Size: 9.0 KiB |
6
mrp_hook/tests/__init__.py
Normal file
@@ -0,0 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2015 Pedro M. Baeza
|
||||
# © 2015 Antiun Ingeniería
|
||||
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
from . import test_mrp_hook
|
||||
54
mrp_hook/tests/test_mrp_hook.py
Normal file
@@ -0,0 +1,54 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2015 Avanzosc
|
||||
# © 2015 Pedro M. Baeza - Antiun Ingeniería
|
||||
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
import openerp.tests.common as common
|
||||
from openerp.exceptions import Warning as UserError
|
||||
|
||||
|
||||
class TestMrpHook(common.TransactionCase):
|
||||
def setUp(self):
|
||||
super(TestMrpHook, self).setUp()
|
||||
self.product_model = self.env['product.product']
|
||||
self.product = self.product_model.create({'name': 'Test product'})
|
||||
self.raw_product = self.product_model.create({'name': 'Raw product'})
|
||||
self.bom = self.env['mrp.bom'].create(
|
||||
{
|
||||
'name': self.product.name,
|
||||
'product_id': self.product.id,
|
||||
'product_tmpl_id': self.product.product_tmpl_id.id,
|
||||
'bom_line_ids': [
|
||||
(0, 0, {'product_id': self.raw_product.id,
|
||||
'type': 'normal',
|
||||
'product_qty': 2})]
|
||||
})
|
||||
|
||||
def test_bom_explode_normal(self):
|
||||
products = self.bom._bom_explode(self.product, 1)[0]
|
||||
self.assertEqual(len(products), 1)
|
||||
self.assertEqual(products[0]['product_id'], self.raw_product.id)
|
||||
self.assertEqual(products[0]['product_qty'], 2)
|
||||
|
||||
def test_bom_explode_phantom_error(self):
|
||||
self.bom.bom_line_ids[0].type = 'phantom'
|
||||
with self.assertRaises(UserError):
|
||||
self.bom._bom_explode(self.product, 1)
|
||||
|
||||
def test_bom_explode_phantom(self):
|
||||
self.bom.bom_line_ids[0].type = 'phantom'
|
||||
raw_product_2 = self.product_model.create({'name': 'Raw product 2'})
|
||||
self.env['mrp.bom'].create(
|
||||
{
|
||||
'name': self.raw_product.name,
|
||||
'product_id': self.raw_product.id,
|
||||
'product_tmpl_id': self.raw_product.product_tmpl_id.id,
|
||||
'bom_line_ids': [
|
||||
(0, 0, {'product_id': raw_product_2.id,
|
||||
'type': 'normal',
|
||||
'product_qty': 3})]
|
||||
})
|
||||
products = self.bom._bom_explode(self.product, 1)[0]
|
||||
self.assertEqual(len(products), 1)
|
||||
self.assertEqual(products[0]['product_id'], raw_product_2.id)
|
||||
self.assertEqual(products[0]['product_qty'], 6)
|
||||
@@ -1,16 +1,104 @@
|
||||
MRP operations extension module
|
||||
===============================
|
||||
.. 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
|
||||
|
||||
==================================
|
||||
Manufacturing Operations Extension
|
||||
==================================
|
||||
|
||||
This module adds:
|
||||
|
||||
- New table to store operations to avoid typing them again.
|
||||
- Adds a relation from WorkcenterLines to BoM Lists.
|
||||
- Adds a relation from WorkcenterLines to Manufacturing Orders in Scheduled/Consumed/Finished Products.
|
||||
- Adds a relation between Routing Work Center Lines and Work Center extra Info.
|
||||
* New table to store operations to avoid typing them again.
|
||||
* Adds a relation from workcenter lines to Bill of Materials (BoM) lists.
|
||||
* Adds a relation between workcenter lines and Manufacturing Orders in
|
||||
Scheduled/Consumed/Finished products.
|
||||
* Adds a relation between workcenter lines and BoM lists.
|
||||
* Allows to set specific times per routing in addition to workcenter times.
|
||||
* Controls the availability of material in operations
|
||||
* Controls operation beginning in previous operations are not finished.
|
||||
|
||||
Controls the availability of material in operations, and controls operation
|
||||
start with respect to previous.
|
||||
Installation
|
||||
============
|
||||
|
||||
Once the module is installed, it transforms all existing routings to:
|
||||
|
||||
* Mark the last operation as the one where the production is done.
|
||||
* Create a workcenter routing line (new model for allowing more than one
|
||||
workcenter per operation) for the current selected workcenter.
|
||||
|
||||
Configuration
|
||||
=============
|
||||
|
||||
Go to *Settings > Manufacturing* and activate "Manage routings and work orders"
|
||||
for handling the features of this module.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
You can go to *Manufacturing > Configuration > Operations* to add templates
|
||||
of the operations you do on your manufacturing process defining:
|
||||
|
||||
* Possible workcenters to use.
|
||||
* Number of operators involved.
|
||||
* Extended description.
|
||||
|
||||
This operation template can then be selected when you create routing lines
|
||||
in *Manufacturing > Products > Routings* as the default initial data for that
|
||||
line.
|
||||
|
||||
In this screen, you are now allowed to put more than one possible work
|
||||
centers, and you can also select if the capacity data of the work center
|
||||
is specific for that route or the general one.
|
||||
|
||||
You can also define here in which of the lines the production is going to be
|
||||
made, in order to prevent to do it before reaching this operation. This is done
|
||||
marking the check "Produce here" in the routing line.
|
||||
|
||||
One last possibility for the routing lines is to set if you require to finish
|
||||
previous operations before allowing to start this one, which is done marking
|
||||
the check "Previous operations finished".
|
||||
|
||||
Once defined the routing, you can select the routing on your BoMs, going to
|
||||
*Manufacturing > Products > Bill of Materials*, and select for each component
|
||||
in which routing operation you are going to consume the material.
|
||||
|
||||
Finally, having all set, we can create a manufacturing order with a BoM and
|
||||
a routing selected. Clicking on "Compute Data" button on "Work Orders" or
|
||||
"Scheduled Products" tab, we will preview which work orders and products we
|
||||
will need for this manufacturing.
|
||||
|
||||
Clicking on a work order line, we can see in detail the times involved for that
|
||||
operation and the raw materials that are going to be consumed on it.
|
||||
|
||||
We can start the manufacturing process clicking on "Confirm Production" button.
|
||||
Then, we can control each operation start from the "Work Orders" tab of the
|
||||
manufacturing order, or go to *Manufacturing > Manufacturing > Work Orders*
|
||||
to see them directly. We will only be allowed to consume the materials that
|
||||
has been assigned to the corresponding work order, and to produce when the
|
||||
operation with the "Produce here" flag is set.
|
||||
|
||||
.. 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/8.0
|
||||
|
||||
Known issues
|
||||
============
|
||||
|
||||
* *hr_timesheet* is a big dependency for only catching the employee cost when
|
||||
selecting operators in the workcenter. A glue module for this operation
|
||||
would be desired.
|
||||
|
||||
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 smashing it by providing a detailed and welcomed `feedback
|
||||
<https://github.com/OCA/
|
||||
manufacture/issues/new?body=module:%20
|
||||
mrp_operations_extension%0Aversion:%20
|
||||
8.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
|
||||
|
||||
Credits
|
||||
=======
|
||||
@@ -23,3 +111,25 @@ Contributors
|
||||
* Oihane Crucelaegui <oihanecrucelaegi@avanzosc.es>
|
||||
* Pedro M. Baeza <pedro.baeza@serviciosbaeza.com>
|
||||
* Ana Juaristi <anajuaristi@avanzosc.es>
|
||||
* Rafael Blasco <rafabn@antiun.com>
|
||||
|
||||
Images
|
||||
------
|
||||
|
||||
* Original Odoo MRP icon
|
||||
* Thanks to https://openclipart.org/detail/151831/work-bench
|
||||
|
||||
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.
|
||||
|
||||
@@ -1,33 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
# For copyright and license notices, see __openerp__.py file in root directory
|
||||
##############################################################################
|
||||
# (c) 2015 Avanzosc
|
||||
# (c) 2015 Pedro M. Baeza - Antiun Ingeniería
|
||||
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
from . import models
|
||||
from . import wizard
|
||||
from openerp import api, SUPERUSER_ID
|
||||
|
||||
|
||||
def create_default_routing_workcenter_line(cr):
|
||||
with api.Environment.manage():
|
||||
env = api.Environment(cr, SUPERUSER_ID, {})
|
||||
routing_wcs = env['mrp.routing.workcenter'].search(
|
||||
[('op_wc_lines', '=', False)])
|
||||
for routing_wc in routing_wcs:
|
||||
routing_wc.op_wc_lines = [
|
||||
(0, 0, {'workcenter': routing_wc.workcenter_id,
|
||||
'default': True,
|
||||
'custom_data': False})]
|
||||
|
||||
|
||||
def post_init_hook(cr, pool):
|
||||
""" Set do_production on the last workcenter line of each routing """
|
||||
cr.execute(
|
||||
"""
|
||||
UPDATE mrp_routing_workcenter SET do_production = TRUE
|
||||
WHERE id IN (
|
||||
SELECT (
|
||||
SELECT id FROM mrp_routing_workcenter WHERE routing_id = mr.id
|
||||
ORDER BY sequence DESC, id DESC LIMIT 1)
|
||||
FROM mrp_routing mr);
|
||||
""")
|
||||
create_default_routing_workcenter_line(cr)
|
||||
from .hooks import post_init_hook
|
||||
|
||||
@@ -1,29 +1,19 @@
|
||||
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
#
|
||||
##############################################################################
|
||||
# -*- coding: utf-8 -*-
|
||||
# (c) 2014-2015 Avanzosc
|
||||
# (c) 2014-2015 Pedro M. Baeza
|
||||
# (c) 2015 Antiun Ingeniería
|
||||
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
{
|
||||
"name": "MRP Operations Extension",
|
||||
"name": "Manufacturing Operations Extension",
|
||||
"version": "8.0.2.0.0",
|
||||
"category": "Manufacturing",
|
||||
"license": "AGPL-3",
|
||||
"author": "OdooMRP team, "
|
||||
"AvanzOSC, "
|
||||
"Serv. Tecnol. Avanzados - Pedro M. Baeza",
|
||||
"Serv. Tecnol. Avanzados - Pedro M. Baeza, "
|
||||
"Antiun Ingeniería S.L., "
|
||||
"Odoo Community Association (OCA)",
|
||||
"website": "http://www.odoomrp.com",
|
||||
"contributors": [
|
||||
"Daniel Campos <danielcampos@avanzosc.es>",
|
||||
@@ -35,7 +25,6 @@
|
||||
"depends": [
|
||||
"mrp_operations",
|
||||
"mrp_hook",
|
||||
"stock",
|
||||
"hr_timesheet",
|
||||
],
|
||||
"data": [
|
||||
@@ -50,6 +39,15 @@
|
||||
"security/ir.model.access.csv",
|
||||
"security/mrp_operations_extension_security.xml",
|
||||
],
|
||||
"images": [
|
||||
'images/operation.png',
|
||||
'images/routing.png',
|
||||
'images/routing_line.png',
|
||||
'images/bom.png',
|
||||
'images/manufacturing_order.png',
|
||||
'images/work_order.png',
|
||||
'images/work_order2.png',
|
||||
],
|
||||
"demo": [
|
||||
"demo/res_partner_demo.xml",
|
||||
"demo/hr_employee_demo.xml",
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<field name="name">Work Center</field>
|
||||
<field name="object">mrp.workcenter</field>
|
||||
</record>
|
||||
<record id="req_link_mrp_workcenter" model="res.request.link">
|
||||
<record id="req_link_mrp_workcenter_line" model="res.request.link">
|
||||
<field name="name">Work Order</field>
|
||||
<field name="object">mrp.production.workcenter.line</field>
|
||||
</record>
|
||||
|
||||
31
mrp_operations_extension/hooks.py
Normal file
@@ -0,0 +1,31 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2015 Pedro M. Baeza - Antiun Ingeniería
|
||||
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
from openerp import api, SUPERUSER_ID
|
||||
|
||||
|
||||
def create_default_routing_workcenter_line(cr):
|
||||
with api.Environment.manage():
|
||||
env = api.Environment(cr, SUPERUSER_ID, {})
|
||||
routing_wcs = env['mrp.routing.workcenter'].search(
|
||||
[('op_wc_lines', '=', False)])
|
||||
for routing_wc in routing_wcs:
|
||||
routing_wc.op_wc_lines = [
|
||||
(0, 0, {'workcenter': routing_wc.workcenter_id,
|
||||
'default': True,
|
||||
'custom_data': False})]
|
||||
|
||||
|
||||
def post_init_hook(cr, pool):
|
||||
""" Set do_production on the last workcenter line of each routing """
|
||||
cr.execute(
|
||||
"""
|
||||
UPDATE mrp_routing_workcenter SET do_production = TRUE
|
||||
WHERE id IN (
|
||||
SELECT (
|
||||
SELECT id FROM mrp_routing_workcenter WHERE routing_id = mr.id
|
||||
ORDER BY sequence DESC, id DESC LIMIT 1)
|
||||
FROM mrp_routing mr);
|
||||
""")
|
||||
create_default_routing_workcenter_line(cr)
|
||||
@@ -1,553 +0,0 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * mrp_operations_extension
|
||||
#
|
||||
# Translators:
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: odoomrp-wip (8.0)\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-10-07 10:43+0000\n"
|
||||
"PO-Revision-Date: 2015-09-10 16:39+0000\n"
|
||||
"Last-Translator: <>\n"
|
||||
"Language-Team: English (United States) (http://www.transifex.com/oca/odoomrp-wip-8-0/language/en_US/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Language: en_US\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.workcenter,op_number:0
|
||||
msgid "# Operators"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.operation.workcenter,op_number:0
|
||||
#: field:mrp.routing.operation,op_number:0
|
||||
msgid "# operators"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: view:mrp.production:mrp_operations_extension.mrp_production_form_view_inh
|
||||
#: view:mrp.production.workcenter.line:mrp_operations_extension.workcenter_line_inh_form_view
|
||||
msgid "Actual Production Date"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: code:addons/mrp_operations_extension/models/mrp_production.py:36
|
||||
#, python-format
|
||||
msgid "At least one work order must have checked 'Produce here'"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: model:ir.model,name:mrp_operations_extension.model_mrp_bom
|
||||
msgid "Bill of Material"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: view:mrp.work.order.produce:mrp_operations_extension.view_mrp_product_consume_wizard
|
||||
#: view:mrp.work.order.produce:mrp_operations_extension.view_mrp_product_produce_wizard
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: view:mrp.production:mrp_operations_extension.mrp_production_operation_buttons_form_view
|
||||
msgid "Cancel Order"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.operation.workcenter,capacity_per_cycle:0
|
||||
msgid "Capacity per cycle"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: code:addons/mrp_operations_extension/models/mrp_bom.py:71
|
||||
#, python-format
|
||||
msgid "Changing Routing"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: code:addons/mrp_operations_extension/models/mrp_bom.py:72
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Changing routing will cause to change the operation in which each component "
|
||||
"will be consumed, by default it is set the first one of the routing"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: view:mrp.production:mrp_operations_extension.mrp_production_operation_buttons_form_view
|
||||
#: view:mrp.production.workcenter.line:mrp_operations_extension.workcenter_line_inh_form_view
|
||||
msgid "Check Availability"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.routing.operation,code:0
|
||||
msgid "Code"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: model:ir.actions.act_window,name:mrp_operations_extension.act_mrp_work_order_consume
|
||||
#: view:mrp.production:mrp_operations_extension.mrp_production_operation_buttons_form_view
|
||||
#: view:mrp.production.workcenter.line:mrp_operations_extension.workcenter_line_inh_form_view
|
||||
#: view:mrp.work.order.produce:mrp_operations_extension.view_mrp_product_consume_wizard
|
||||
msgid "Consume"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: view:mrp.work.order.produce:mrp_operations_extension.view_mrp_product_produce_wizard
|
||||
#: selection:mrp.work.order.produce,mode:0
|
||||
msgid "Consume & Produce"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: view:mrp.work.order.produce:mrp_operations_extension.view_mrp_product_consume_wizard
|
||||
#: view:mrp.work.order.produce:mrp_operations_extension.view_mrp_product_produce_wizard
|
||||
msgid "Consume Lines"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: selection:mrp.work.order.produce,mode:0
|
||||
msgid "Consume Only"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.bom.line,operation:0
|
||||
msgid "Consumed in"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.operation.workcenter,create_uid:0
|
||||
#: field:mrp.routing.operation,create_uid:0
|
||||
#: field:mrp.work.order.produce,create_uid:0
|
||||
msgid "Created by"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.operation.workcenter,create_date:0
|
||||
#: field:mrp.routing.operation,create_date:0
|
||||
#: field:mrp.work.order.produce,create_date:0
|
||||
msgid "Created on"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.operation.workcenter,default:0
|
||||
msgid "Default"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: view:mrp.routing.workcenter:mrp_operations_extension.mrp_routing_workcenter_tree_view_inh
|
||||
msgid "Default workcenter"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.routing.operation,description:0
|
||||
msgid "Description"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: view:mrp.production:mrp_operations_extension.mrp_production_form_view_inh
|
||||
#: view:mrp.production.workcenter.line:mrp_operations_extension.workcenter_line_inh_form_view
|
||||
msgid "Duration"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.operation.workcenter,time_efficiency:0
|
||||
msgid "Efficiency factor"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: view:mrp.production.workcenter.line:mrp_operations_extension.workcenter_line_inh_form_view
|
||||
msgid "Extra Information"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.work.order.produce,final_product:0
|
||||
msgid "Final Product to Stock"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: view:mrp.production:mrp_operations_extension.mrp_production_operation_buttons_form_view
|
||||
#: view:mrp.production.workcenter.line:mrp_operations_extension.workcenter_line_inh_form_view
|
||||
msgid "Force Reservation"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.operation.workcenter,id:0 field:mrp.routing.operation,id:0
|
||||
#: field:mrp.work.order.produce,id:0
|
||||
msgid "ID"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: help:mrp.routing.workcenter,do_production:0
|
||||
msgid ""
|
||||
"If enabled, the production and movement to stock of the final products will "
|
||||
"be done in this operation. There can be only one operation per route with "
|
||||
"this check marked."
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: view:mrp.production:mrp_operations_extension.mrp_production_form_view_inh
|
||||
#: view:mrp.production.workcenter.line:mrp_operations_extension.workcenter_line_inh_form_view
|
||||
msgid "Information"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.operation.workcenter,write_uid:0
|
||||
#: field:mrp.routing.operation,write_uid:0
|
||||
#: field:mrp.work.order.produce,write_uid:0
|
||||
msgid "Last Updated by"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.operation.workcenter,write_date:0
|
||||
#: field:mrp.routing.operation,write_date:0
|
||||
#: field:mrp.work.order.produce,write_date:0
|
||||
msgid "Last Updated on"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.work.order.produce,lot_id:0
|
||||
msgid "Lot"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: model:ir.model,name:mrp_operations_extension.model_mrp_operation_workcenter
|
||||
msgid "MRP Operation Workcenter"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: model:ir.model,name:mrp_operations_extension.model_mrp_routing_operation
|
||||
msgid "MRP Routing Operation"
|
||||
msgstr "MRP Routing Operation"
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.config.settings,group_mrp_workers:0
|
||||
msgid "Manage operators in work centers "
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: model:res.groups,name:mrp_operations_extension.group_mrp_workers
|
||||
msgid "Manufacturing Operators"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: model:ir.model,name:mrp_operations_extension.model_mrp_production
|
||||
msgid "Manufacturing Order"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: view:mrp.production:mrp_operations_extension.mrp_production_form_view_inh
|
||||
msgid "Materials"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: code:addons/mrp_operations_extension/models/mrp_production.py:170
|
||||
#, python-format
|
||||
msgid "Missing materials to start the production"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.work.order.produce,mode:0
|
||||
msgid "Mode"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.production.workcenter.line,move_lines:0
|
||||
msgid "Moves"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.routing.operation,name:0
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.routing.workcenter,operation:0
|
||||
msgid "Operation"
|
||||
msgstr "Operation"
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: model:ir.ui.menu,name:mrp_operations_extension.mrp_routing_menu
|
||||
#: view:mrp.production.workcenter.line:mrp_operations_extension.workcenter_line_future_calendar
|
||||
msgid "Operations"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.workcenter,op_avg_cost:0
|
||||
msgid "Operator average hour cost"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.operation.workcenter,op_avg_cost:0
|
||||
msgid "Operator avg. hour cost"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: view:mrp.workcenter:mrp_operations_extension.mrp_workcenter_form_view_inh
|
||||
#: field:mrp.workcenter,operators:0
|
||||
msgid "Operators"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.routing.operation,picking_type_id:0
|
||||
#: field:mrp.routing.workcenter,picking_type_id:0
|
||||
msgid "Picking Type"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: view:mrp.production:mrp_operations_extension.mrp_production_form_view_inh
|
||||
#: view:mrp.production.workcenter.line:mrp_operations_extension.workcenter_line_inh_form_view
|
||||
msgid "Planned Date"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.routing.workcenter,op_wc_lines:0
|
||||
msgid "Possible work centers for this operation"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: view:mrp.routing.workcenter:mrp_operations_extension.mrp_routing_workcenter_form_view_inh
|
||||
msgid "Possible workcenters"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.workcenter,post_op_product:0
|
||||
msgid "Post-operation costing product"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.workcenter,pre_op_product:0
|
||||
msgid "Pre-operation costing product"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.routing,previous_operations_finished:0
|
||||
#: field:mrp.routing.workcenter,previous_operations_finished:0
|
||||
msgid "Previous operations finished"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: code:addons/mrp_operations_extension/models/mrp_production.py:166
|
||||
#, python-format
|
||||
msgid "Previous operations not finished"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: model:ir.actions.act_window,name:mrp_operations_extension.act_mrp_work_order_produce
|
||||
#: view:mrp.production:mrp_operations_extension.mrp_production_operation_buttons_form_view
|
||||
#: view:mrp.production.workcenter.line:mrp_operations_extension.workcenter_line_inh_form_view
|
||||
#: view:mrp.work.order.produce:mrp_operations_extension.view_mrp_product_consume_wizard
|
||||
#: view:mrp.work.order.produce:mrp_operations_extension.view_mrp_product_produce_wizard
|
||||
msgid "Produce"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.production.workcenter.line,do_production:0
|
||||
#: field:mrp.routing.workcenter,do_production:0
|
||||
msgid "Produce here"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.work.order.produce,product_id:0
|
||||
msgid "Product"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: view:mrp.production:mrp_operations_extension.mrp_production_form_view_inh
|
||||
#: view:mrp.production.workcenter.line:mrp_operations_extension.workcenter_line_inh_form_view
|
||||
#: field:mrp.production.workcenter.line,product_line:0
|
||||
msgid "Product Lines"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: model:ir.model,name:mrp_operations_extension.model_mrp_product_produce_line
|
||||
msgid "Product Produce Consume lines"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: view:mrp.production:mrp_operations_extension.mrp_production_form_view_inh
|
||||
#: view:mrp.production.workcenter.line:mrp_operations_extension.workcenter_line_inh_form_view
|
||||
msgid "Product to Produce"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: model:ir.model,name:mrp_operations_extension.model_mrp_production_product_line
|
||||
msgid "Production Scheduled Product"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.work.order.produce,consume_lines:0
|
||||
msgid "Products Consumed"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.routing.operation,steps:0
|
||||
msgid "Relevant Steps"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: model:ir.model,name:mrp_operations_extension.model_mrp_routing
|
||||
msgid "Routing"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: model:ir.actions.act_window,name:mrp_operations_extension.mrp_routing_operation_action
|
||||
#: view:mrp.routing.operation:mrp_operations_extension.rountig_operation_form
|
||||
#: view:mrp.routing.operation:mrp_operations_extension.rountig_operation_tree
|
||||
msgid "Routing Operation"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: view:mrp.workcenter:mrp_operations_extension.mrp_workcenter_form_view_inh
|
||||
#: field:mrp.workcenter,rt_operations:0
|
||||
msgid "Routing Operations"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.production.workcenter.line,routing_wc_line:0
|
||||
msgid "Routing WC Line"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.operation.workcenter,routing_workcenter:0
|
||||
msgid "Routing workcenter"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.work.order.produce,product_qty:0
|
||||
msgid "Select Quantity"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: model:ir.model,name:mrp_operations_extension.model_stock_move
|
||||
msgid "Stock Move"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: code:addons/mrp_operations_extension/models/mrp_routing.py:55
|
||||
#, python-format
|
||||
msgid "There must be one and only one line set as default."
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: code:addons/mrp_operations_extension/models/mrp_routing.py:19
|
||||
#, python-format
|
||||
msgid ""
|
||||
"There must be one and only one operation with 'Produce here' check marked."
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.production.workcenter.line,time_start:0
|
||||
msgid "Time Start"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.production.workcenter.line,time_stop:0
|
||||
msgid "Time Stop"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.operation.workcenter,time_stop:0
|
||||
msgid "Time after prod."
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.operation.workcenter,time_start:0
|
||||
msgid "Time before prod."
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.operation.workcenter,time_cycle:0
|
||||
msgid "Time for 1 cycle (hours)"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: help:mrp.operation.workcenter,time_cycle:0
|
||||
msgid "Time in hours for doing one cycle."
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: help:mrp.operation.workcenter,time_stop:0
|
||||
msgid "Time in hours for the cleaning."
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: help:mrp.operation.workcenter,time_start:0
|
||||
msgid "Time in hours for the setup."
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: view:mrp.work.order.produce:mrp_operations_extension.view_mrp_product_consume_wizard
|
||||
#: view:mrp.work.order.produce:mrp_operations_extension.view_mrp_product_produce_wizard
|
||||
msgid "To Consume"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: view:mrp.routing.workcenter:mrp_operations_extension.mrp_routing_workcenter_tree_view_inh
|
||||
msgid "Total"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.work.order.produce,track_production:0
|
||||
msgid "Track production"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: model:ir.model,name:mrp_operations_extension.model_mrp_workcenter
|
||||
msgid "Work Center"
|
||||
msgstr "Work Center"
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: model:ir.model,name:mrp_operations_extension.model_mrp_routing_workcenter
|
||||
msgid "Work Center Usage"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: model:ir.model,name:mrp_operations_extension.model_mrp_production_workcenter_line
|
||||
#: field:mrp.production.product.line,work_order:0
|
||||
#: model:res.request.link,name:mrp_operations_extension.req_link_mrp_workcenter
|
||||
#: field:stock.move,work_order:0
|
||||
msgid "Work Order"
|
||||
msgstr "Work Order"
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.routing.operation,workcenters:0
|
||||
msgid "Work centers"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.product.produce.line,work_produce_id:0
|
||||
msgid "Work produce id"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.operation.workcenter,workcenter:0
|
||||
msgid "Workcenter"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: view:mrp.routing.operation:mrp_operations_extension.rountig_operation_form
|
||||
msgid "Workcenters"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: view:mrp.production:mrp_operations_extension.mrp_production_operation_buttons_form_view
|
||||
msgid "draft,startworking"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: view:mrp.production:mrp_operations_extension.mrp_production_operation_buttons_form_view
|
||||
msgid "oe_highlight"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: view:mrp.work.order.produce:mrp_operations_extension.view_mrp_product_consume_wizard
|
||||
#: view:mrp.work.order.produce:mrp_operations_extension.view_mrp_product_produce_wizard
|
||||
msgid "or"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: view:mrp.routing.workcenter:mrp_operations_extension.mrp_routing_workcenter_form_view_inh
|
||||
msgid "{'invisible': [('op_wc_lines', '!=', [])]}"
|
||||
msgstr ""
|
||||
@@ -227,7 +227,7 @@ msgstr "Operación de la ruta"
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.config.settings,group_mrp_workers:0
|
||||
msgid "Manage operators in work centers "
|
||||
msgid "Manage operators in work centers"
|
||||
msgstr "Gestionar operadores en los centros de trabajo"
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
@@ -280,12 +280,12 @@ msgstr "Operaciones"
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.workcenter,op_avg_cost:0
|
||||
msgid "Operator average hour cost"
|
||||
msgid "Operator average hourly cost"
|
||||
msgstr "Coste hora medio del operador"
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
#: field:mrp.operation.workcenter,op_avg_cost:0
|
||||
msgid "Operator avg. hour cost"
|
||||
msgid "Operator average hourly cost"
|
||||
msgstr "Coste hora medio operador"
|
||||
|
||||
#. module: mrp_operations_extension
|
||||
|
||||
BIN
mrp_operations_extension/images/bom.png
Normal file
|
After Width: | Height: | Size: 55 KiB |
BIN
mrp_operations_extension/images/manufacturing_order.png
Normal file
|
After Width: | Height: | Size: 71 KiB |
BIN
mrp_operations_extension/images/operation.png
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
mrp_operations_extension/images/routing.png
Normal file
|
After Width: | Height: | Size: 47 KiB |
BIN
mrp_operations_extension/images/routing_line.png
Normal file
|
After Width: | Height: | Size: 49 KiB |
BIN
mrp_operations_extension/images/work_order.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
mrp_operations_extension/images/work_order2.png
Normal file
|
After Width: | Height: | Size: 58 KiB |
@@ -2,10 +2,10 @@
|
||||
##############################################################################
|
||||
# For copyright and license notices, see __openerp__.py file in root directory
|
||||
##############################################################################
|
||||
from . import mrp_routing
|
||||
from . import mrp_production
|
||||
from . import mrp_bom
|
||||
from . import mrp_workcenter
|
||||
from . import mrp_production
|
||||
from . import mrp_routing
|
||||
from . import mrp_routing_operation
|
||||
from . import stock_move
|
||||
from . import mrp_workcenter
|
||||
from . import res_config
|
||||
from . import stock_move
|
||||
|
||||
@@ -16,12 +16,10 @@ class MrpBom(models.Model):
|
||||
cycle = int(math.ceil(factor / (wc_use.cycle_nbr or 1)))
|
||||
hour = wc_use.hour_nbr * cycle
|
||||
default_wc_line = wc_use.op_wc_lines.filtered(lambda r: r.default)
|
||||
if default_wc_line.custom_data:
|
||||
time_start = default_wc_line.time_start
|
||||
time_stop = default_wc_line.time_stop
|
||||
else:
|
||||
time_start = default_wc_line.workcenter.time_start
|
||||
time_stop = default_wc_line.workcenter.time_stop
|
||||
data_source = (default_wc_line if default_wc_line.custom_data else
|
||||
default_wc_line.workcenter)
|
||||
time_start = data_source.time_start
|
||||
time_stop = data_source.time_stop
|
||||
res.update({
|
||||
'cycle': cycle,
|
||||
'hour': hour,
|
||||
@@ -44,15 +42,16 @@ class MrpBom(models.Model):
|
||||
def onchange_routing_id(self):
|
||||
for line in self.bom_line_ids:
|
||||
line.operation = self.routing_id.workcenter_lines[:1]
|
||||
res = {}
|
||||
if self.routing_id:
|
||||
return {'warning': {
|
||||
'title': _('Changing Routing'),
|
||||
'message': _("Changing routing will cause to change the"
|
||||
" operation in which each component will be"
|
||||
" consumed, by default it is set the first"
|
||||
" one of the routing")
|
||||
}}
|
||||
return {}
|
||||
res['warning'] = {
|
||||
'title': _('Changing Routing'),
|
||||
'message': _(
|
||||
"Changing routing will cause to change the operation in "
|
||||
"which each component will be consumed, by default it is "
|
||||
"set the first one of the routing")
|
||||
}
|
||||
return res
|
||||
|
||||
|
||||
class MrpBomLine(models.Model):
|
||||
|
||||
@@ -9,31 +9,20 @@ class MrpProduction(models.Model):
|
||||
_inherit = 'mrp.production'
|
||||
|
||||
workcenter_lines = fields.One2many(readonly=False)
|
||||
date_planned = fields.Datetime(states={'draft': [('readonly', False)],
|
||||
'confirmed': [('readonly', False)],
|
||||
'ready': [('readonly', False)]})
|
||||
|
||||
def _get_minor_sequence_operation(self, operations):
|
||||
return min(operations, key=lambda x: x.sequence)
|
||||
|
||||
@api.model
|
||||
def _moves_assigned(self):
|
||||
res = super(MrpProduction, self)._moves_assigned()
|
||||
if res:
|
||||
return True
|
||||
operation = self._get_minor_sequence_operation(self.workcenter_lines)
|
||||
assigned_moves, no_assigned_products = \
|
||||
self._get_operation_moves(operation, state='assigned')
|
||||
return no_assigned_products == []
|
||||
date_planned = fields.Datetime(
|
||||
states={'draft': [('readonly', False)],
|
||||
'confirmed': [('readonly', False)],
|
||||
'ready': [('readonly', False)]})
|
||||
|
||||
@api.multi
|
||||
def action_confirm(self):
|
||||
res = super(MrpProduction, self).action_confirm()
|
||||
if (self.routing_id and
|
||||
not any([x.do_production for x in self.workcenter_lines])):
|
||||
raise exceptions.Warning(
|
||||
_("At least one work order must have checked 'Produce here'"))
|
||||
return res
|
||||
for prod in self:
|
||||
if (prod.workcenter_lines and
|
||||
not len(prod.workcenter_lines.filtered('do_production'))):
|
||||
raise exceptions.Warning(
|
||||
_("At least one work order must have checked 'Produce "
|
||||
"here'"))
|
||||
return super(MrpProduction, self).action_confirm()
|
||||
|
||||
@api.multi
|
||||
def _action_compute_lines(self, properties=None):
|
||||
@@ -68,11 +57,11 @@ class MrpProductionWorkcenterLine(models.Model):
|
||||
_inherit = 'mrp.production.workcenter.line'
|
||||
|
||||
@api.one
|
||||
def _ready_materials(self):
|
||||
def _compute_is_material_ready(self):
|
||||
self.is_material_ready = True
|
||||
if self.product_line:
|
||||
moves = self.env['stock.move'].search([('work_order', '=',
|
||||
self.id)])
|
||||
moves = self.env['stock.move'].search(
|
||||
[('work_order', '=', self.id)])
|
||||
self.is_material_ready = not any(
|
||||
x not in ('assigned', 'cancel', 'done') for x in
|
||||
moves.mapped('state'))
|
||||
@@ -95,7 +84,7 @@ class MrpProductionWorkcenterLine(models.Model):
|
||||
move_lines = fields.One2many(
|
||||
comodel_name='stock.move', inverse_name='work_order', string='Moves')
|
||||
is_material_ready = fields.Boolean(
|
||||
string='Materials Ready', compute="_ready_materials")
|
||||
string='Materials Ready', compute="_compute_is_material_ready")
|
||||
possible_workcenters = fields.Many2many(
|
||||
comodel_name="mrp.workcenter", compute="_compute_possible_workcenters")
|
||||
workcenter_id = fields.Many2one(
|
||||
@@ -109,38 +98,25 @@ class MrpProductionWorkcenterLine(models.Model):
|
||||
def force_assign(self):
|
||||
self.move_lines.force_assign()
|
||||
|
||||
@api.multi
|
||||
def _load_mo_date_planned(self, production, date_planned):
|
||||
if date_planned < production.date_planned:
|
||||
production.write({'date_planned': date_planned})
|
||||
return True
|
||||
return False
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
production_obj = self.env['mrp.production']
|
||||
dp = vals.get('date_planned', False)
|
||||
production_id = vals.get('production_id', False)
|
||||
if dp and production_id:
|
||||
production = production_obj.browse(production_id)
|
||||
self._load_mo_date_planned(production, dp)
|
||||
if vals.get('date_planned') and vals.get('production_id'):
|
||||
production = self.env['mrp.production'].browse(
|
||||
vals['production_id'])
|
||||
if vals['date_planned'] < production.date_planned:
|
||||
production.date_planned = vals['date_planned']
|
||||
return super(MrpProductionWorkcenterLine, self).create(vals)
|
||||
|
||||
@api.multi
|
||||
def write(self, vals, update=False):
|
||||
if vals.get('date_planned', False):
|
||||
dp = vals.get('date_planned')
|
||||
update = self._load_mo_date_planned(self.production_id, dp)
|
||||
res = super(MrpProductionWorkcenterLine, self).write(vals,
|
||||
update=update)
|
||||
return res
|
||||
|
||||
def check_minor_sequence_operations(self):
|
||||
self.ensure_one()
|
||||
seq = self.sequence
|
||||
res = True
|
||||
for operation in self.production_id.workcenter_lines:
|
||||
if operation.sequence < seq and operation.state != 'done':
|
||||
return False
|
||||
return True
|
||||
res = False
|
||||
break
|
||||
return res
|
||||
|
||||
def check_operation_moves_state(self, states):
|
||||
for move_line in self.move_lines:
|
||||
@@ -149,13 +125,14 @@ class MrpProductionWorkcenterLine(models.Model):
|
||||
return True
|
||||
|
||||
def action_start_working(self):
|
||||
if self.routing_wc_line.previous_operations_finished and \
|
||||
not self.check_minor_sequence_operations():
|
||||
raise exceptions.Warning(_("Previous operations not finished"))
|
||||
if not self.check_operation_moves_state(['assigned', 'cancel',
|
||||
'done']):
|
||||
raise exceptions.Warning(
|
||||
_("Missing materials to start the production"))
|
||||
if self.production_id.state in ('confirmed', 'ready'):
|
||||
self.production_id.state = 'in_production'
|
||||
for workorder in self:
|
||||
if workorder.routing_wc_line.previous_operations_finished and \
|
||||
not workorder.check_minor_sequence_operations():
|
||||
raise exceptions.Warning(_("Previous operations not finished"))
|
||||
if not workorder.check_operation_moves_state(
|
||||
['assigned', 'cancel', 'done']):
|
||||
raise exceptions.Warning(
|
||||
_("Missing materials to start the production"))
|
||||
if workorder.production_id.state in ('confirmed', 'ready'):
|
||||
workorder.production_id.state = 'in_production'
|
||||
return super(MrpProductionWorkcenterLine, self).action_start_working()
|
||||
|
||||
@@ -12,25 +12,15 @@ class MrpRouting(models.Model):
|
||||
@api.one
|
||||
@api.constrains('workcenter_lines')
|
||||
def _check_produce_operation(self):
|
||||
if not self.workcenter_lines:
|
||||
return
|
||||
num_produce = sum([x.do_production for x in self.workcenter_lines])
|
||||
if num_produce != 1:
|
||||
num_produce = len(self.workcenter_lines.filtered('do_production'))
|
||||
if num_produce != 1 and self.workcenter_lines:
|
||||
raise Warning(_("There must be one and only one operation with "
|
||||
"'Produce here' check marked."))
|
||||
|
||||
previous_operations_finished = fields.Boolean(
|
||||
string='Previous operations finished')
|
||||
|
||||
|
||||
class MrpRoutingWorkcenter(models.Model):
|
||||
_inherit = 'mrp.routing.workcenter'
|
||||
|
||||
def default_previous_operations_finished(self):
|
||||
if self.routing_id:
|
||||
self.previous_operations_finished = \
|
||||
self.routing_id.previous_operations_finished
|
||||
|
||||
operation = fields.Many2one('mrp.routing.operation', string='Operation')
|
||||
op_wc_lines = fields.One2many(
|
||||
'mrp.operation.workcenter', 'routing_workcenter',
|
||||
@@ -41,17 +31,14 @@ class MrpRoutingWorkcenter(models.Model):
|
||||
"products will be done in this operation. There can be only one "
|
||||
"operation per route with this check marked.")
|
||||
previous_operations_finished = fields.Boolean(
|
||||
string='Previous operations finished',
|
||||
default=default_previous_operations_finished)
|
||||
string='Previous operations finished')
|
||||
picking_type_id = fields.Many2one('stock.picking.type', 'Picking Type',
|
||||
domain=[('code', '=', 'outgoing')])
|
||||
|
||||
@api.constrains('op_wc_lines')
|
||||
def _check_default_op_wc_lines(self):
|
||||
if not self.op_wc_lines:
|
||||
return
|
||||
num_default = len([x for x in self.op_wc_lines if x.default])
|
||||
if num_default != 1:
|
||||
num_default = len(self.op_wc_lines.filtered('default'))
|
||||
if num_default != 1 and self.op_wc_lines:
|
||||
raise Warning(
|
||||
_('There must be one and only one line set as default.'))
|
||||
|
||||
@@ -84,16 +71,11 @@ class MrpRoutingWorkcenter(models.Model):
|
||||
@api.one
|
||||
@api.onchange('op_wc_lines')
|
||||
def onchange_lines_default(self):
|
||||
for line in self.op_wc_lines:
|
||||
if line.default:
|
||||
self.workcenter_id = line.workcenter
|
||||
if line.custom_data:
|
||||
self.cycle_nbr = line.capacity_per_cycle
|
||||
self.hour_nbr = line.time_cycle
|
||||
else:
|
||||
self.cycle_nbr = line.workcenter.capacity_per_cycle
|
||||
self.hour_nbr = line.workcenter.time_cycle
|
||||
break
|
||||
line = self.op_wc_lines.filtered('default')[:1]
|
||||
self.workcenter_id = line.workcenter
|
||||
data_source = line if line.custom_data else line.workcenter
|
||||
self.cycle_nbr = data_source.capacity_per_cycle
|
||||
self.hour_nbr = data_source.time_cycle
|
||||
|
||||
|
||||
class MrpOperationWorkcenter(models.Model):
|
||||
@@ -111,15 +93,15 @@ class MrpOperationWorkcenter(models.Model):
|
||||
'mrp.routing.workcenter', 'Routing workcenter', required=True)
|
||||
time_efficiency = fields.Float('Efficiency factor')
|
||||
capacity_per_cycle = fields.Float('Capacity per cycle')
|
||||
time_cycle = fields.Float('Time for 1 cycle (hours)',
|
||||
help="Time in hours for doing one cycle.")
|
||||
time_start = fields.Float('Time before prod.',
|
||||
help="Time in hours for the setup.")
|
||||
time_stop = fields.Float('Time after prod.',
|
||||
help="Time in hours for the cleaning.")
|
||||
time_cycle = fields.Float(
|
||||
string='Time for 1 cycle (hours)', help="Duration for one cycle.")
|
||||
time_start = fields.Float(
|
||||
string='Time before prod.', help="Duration for the setup.")
|
||||
time_stop = fields.Float(
|
||||
string='Time after prod.', help="Duartion for the cleaning.")
|
||||
op_number = fields.Integer('# operators', default='0')
|
||||
op_avg_cost = fields.Float(
|
||||
string='Operator avg. hour cost',
|
||||
string='Operator average hourly cost',
|
||||
digits=dp.get_precision('Product Price'))
|
||||
default = fields.Boolean('Default')
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
# For copyright and license notices, see __openerp__.py file in root directory
|
||||
##############################################################################
|
||||
# (c) 2015 Avanzosc
|
||||
# (c) 2015 Pedro M. Baeza - Antiun Ingeniería
|
||||
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
from openerp import models, fields, api
|
||||
from openerp.addons import decimal_precision as dp
|
||||
|
||||
@@ -11,25 +12,26 @@ class MrpWorkcenter(models.Model):
|
||||
|
||||
@api.one
|
||||
@api.onchange('operators')
|
||||
def _operators_number_avg_cost(self):
|
||||
def onchange_operators(self):
|
||||
self.op_number = len(self.operators)
|
||||
num_oper = 0
|
||||
op_avg_cost = 0.0
|
||||
for ope in self.operators:
|
||||
if (ope.employee_ids[0] and ope.employee_ids[0].product_id):
|
||||
for op in self.operators:
|
||||
if op.employee_ids[:1].product_id:
|
||||
num_oper += 1
|
||||
op_avg_cost += ope.employee_ids[0].product_id.standard_price
|
||||
op_avg_cost += op.employee_ids[:1].product_id.standard_price
|
||||
self.op_avg_cost = op_avg_cost / (num_oper or 1)
|
||||
|
||||
pre_op_product = fields.Many2one('product.product',
|
||||
string='Pre-operation costing product')
|
||||
post_op_product = fields.Many2one('product.product',
|
||||
string='Post-operation costing product')
|
||||
pre_op_product = fields.Many2one(
|
||||
'product.product', string='Pre-operation costing product')
|
||||
post_op_product = fields.Many2one(
|
||||
'product.product', string='Post-operation costing product')
|
||||
rt_operations = fields.Many2many(
|
||||
'mrp.routing.operation', 'mrp_operation_workcenter_rel', 'workcenter',
|
||||
'operation', 'Routing Operations')
|
||||
operators = fields.Many2many('res.users', 'mrp_wc_operator_rel',
|
||||
'workcenter_id', 'operator_id', 'Operators')
|
||||
operators = fields.Many2many(
|
||||
'res.users', 'mrp_wc_operator_rel', 'workcenter_id', 'operator_id',
|
||||
string='Operators')
|
||||
op_number = fields.Integer(string='# Operators')
|
||||
op_avg_cost = fields.Float(string='Operator average hour cost',
|
||||
op_avg_cost = fields.Float(string='Operator average hourly cost',
|
||||
digits=dp.get_precision('Product Price'))
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
##############################################################################
|
||||
# For copyright and license notices, see __openerp__.py file in root directory
|
||||
##############################################################################
|
||||
from openerp import models, fields
|
||||
from openerp import fields, models
|
||||
|
||||
|
||||
class MrpConfigSettings(models.TransientModel):
|
||||
_inherit = 'mrp.config.settings'
|
||||
|
||||
group_mrp_workers = fields.Boolean(
|
||||
string='Manage operators in work centers ',
|
||||
string='Manage operators in work centers',
|
||||
implied_group='mrp_operations_extension.group_mrp_workers')
|
||||
|
||||
BIN
mrp_operations_extension/static/description/icon.png
Normal file
|
After Width: | Height: | Size: 7.4 KiB |
151
mrp_operations_extension/static/description/icon.svg
Normal file
|
After Width: | Height: | Size: 14 KiB |
@@ -1,30 +1,169 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
# For copyright and license notices, see __openerp__.py file in root directory
|
||||
##############################################################################
|
||||
# © 2015 Avanzosc
|
||||
# © 2015 Pedro M. Baeza
|
||||
# © 2015 Antiun Ingeniería
|
||||
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
import openerp.tests.common as common
|
||||
from openerp import workflow
|
||||
from openerp.exceptions import ValidationError, Warning as UserError
|
||||
|
||||
|
||||
class TestMrpOperationsExtension(common.TransactionCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestMrpOperationsExtension, self).setUp()
|
||||
self.workcenter = self.env['mrp.workcenter'].create(
|
||||
{'name': 'Test work center',
|
||||
'op_number': 1,
|
||||
'capacity_per_cycle': 5,
|
||||
'time_cycle': 1.0}
|
||||
)
|
||||
self.operation = self.env['mrp.routing.operation'].create(
|
||||
{'name': 'Test operation',
|
||||
'op_number': 2,
|
||||
'workcenters': [(6, 0, self.workcenter.ids)]})
|
||||
self.routing = self.env['mrp.routing'].create(
|
||||
{'name': 'Test routing'})
|
||||
self.routing_workcenter = self.env['mrp.routing.workcenter'].create(
|
||||
{
|
||||
'name': 'Test routing line',
|
||||
'do_production': True,
|
||||
'workcenter_id': self.workcenter.id,
|
||||
'routing_id': self.routing.id,
|
||||
})
|
||||
self.operation_workcenter = (
|
||||
self.env['mrp.operation.workcenter'].create(
|
||||
{
|
||||
'workcenter': self.workcenter.id,
|
||||
'routing_workcenter': self.routing_workcenter.id,
|
||||
'default': True,
|
||||
}))
|
||||
self.production_model = self.env['mrp.production']
|
||||
self.work_order_produce_model = self.env['mrp.work.order.produce']
|
||||
self.produce_line_model = self.env['mrp.product.produce.line']
|
||||
self.production = self.production_model.browse(
|
||||
self.env.ref('mrp_operations_extension.mrp_production_opeext').id)
|
||||
self.production_case1 = self.production.copy()
|
||||
self.production = self.env.ref(
|
||||
'mrp_operations_extension.mrp_production_opeext')
|
||||
|
||||
def test_check_do_production_mrp_routing(self):
|
||||
# None of the workcenter lines have the check marked
|
||||
with self.assertRaises(ValidationError):
|
||||
self.routing.workcenter_lines = [
|
||||
(1, self.routing_workcenter.id, {'do_production': False})]
|
||||
|
||||
def test_check_do_production_mrp_routing_2(self):
|
||||
# Two workcenter lines have the check marked
|
||||
with self.assertRaises(ValidationError):
|
||||
self.routing.workcenter_lines = [(0, 0, {
|
||||
'name': 'Other test routing line',
|
||||
'do_production': True,
|
||||
'workcenter_id': self.workcenter.id,
|
||||
})]
|
||||
|
||||
def test_check_default_mrp_routing_workcenter(self):
|
||||
# None of the operation workcenters have the check marked
|
||||
with self.assertRaises(ValidationError):
|
||||
self.routing_workcenter.op_wc_lines = [
|
||||
(1, self.operation_workcenter.id, {'default': False})]
|
||||
|
||||
def test_check_default_mrp_routing_workcenter_2(self):
|
||||
# Two operation workcenters have the check marked
|
||||
with self.assertRaises(ValidationError):
|
||||
self.routing_workcenter.op_wc_lines = [(0, 0, {
|
||||
'default': True,
|
||||
'routing_workcenter': self.routing_workcenter.id,
|
||||
'workcenter': self.workcenter.id,
|
||||
})]
|
||||
|
||||
def test_onchange_operation_mrp_routing_workcenter(self):
|
||||
with self.env.do_in_onchange():
|
||||
record = self.env['mrp.routing.workcenter'].new()
|
||||
record.operation = self.operation.id
|
||||
record.onchange_operation()
|
||||
self.assertEqual(record.name, self.operation.name)
|
||||
self.assertEqual(len(record.op_wc_lines), 1)
|
||||
self.assertEqual(record.op_wc_lines[0].op_number, 2)
|
||||
|
||||
def test_onchange_workcenter_mrp_operation_workcenter(self):
|
||||
with self.env.do_in_onchange():
|
||||
record = self.env['mrp.operation.workcenter'].new()
|
||||
record.workcenter = self.workcenter.id
|
||||
record.onchange_workcenter()
|
||||
self.assertEqual(
|
||||
record.capacity_per_cycle, self.workcenter.capacity_per_cycle)
|
||||
self.assertEqual(
|
||||
record.time_efficiency, self.workcenter.time_efficiency)
|
||||
self.assertEqual(record.op_number, self.workcenter.op_number)
|
||||
|
||||
def test_onchange_operators_mrp_workcenter(self):
|
||||
user = self.env['res.users'].create({
|
||||
'name': 'Test user',
|
||||
'login': 'test',
|
||||
})
|
||||
cost_product = self.env['product.product'].create(
|
||||
{'name': 'Cost product',
|
||||
'standard_price': 15.0})
|
||||
self.env['hr.employee'].create({
|
||||
'name': 'Test employee',
|
||||
'user_id': user.id,
|
||||
'product_id': cost_product.id})
|
||||
with self.env.do_in_onchange():
|
||||
record = self.env['mrp.workcenter'].new()
|
||||
record.operators = [(6, 0, user.ids)]
|
||||
record.onchange_operators()
|
||||
self.assertEqual(record.op_number, 1)
|
||||
self.assertEqual(record.op_avg_cost, 15.0)
|
||||
|
||||
def test_onchange_routing_mrp_bom(self):
|
||||
with self.env.do_in_onchange():
|
||||
record = self.env['mrp.bom'].new()
|
||||
record.bom_line_ids = self.env['mrp.bom.line'].new()
|
||||
record.routing_id = self.routing.id
|
||||
res = record.onchange_routing_id()
|
||||
self.assertTrue(res['warning'])
|
||||
|
||||
def test_start_workorder_without_material(self):
|
||||
self.production.signal_workflow('button_confirm')
|
||||
workorder = self.production.workcenter_lines[0]
|
||||
with self.assertRaises(UserError):
|
||||
# Missing materials to start the production
|
||||
workorder.action_start_working()
|
||||
# In this case it should work
|
||||
workorder.action_assign()
|
||||
workorder.force_assign()
|
||||
workorder.action_start_working()
|
||||
|
||||
def test_start_second_workorder(self):
|
||||
self.production.signal_workflow('button_confirm')
|
||||
self.production.workcenter_lines[1].routing_wc_line.\
|
||||
previous_operations_finished = True
|
||||
with self.assertRaises(UserError):
|
||||
# Previous operations not finished
|
||||
self.production.workcenter_lines[1].action_start_working()
|
||||
|
||||
def test_create_workcenter_minor_date(self):
|
||||
date_planned = '1900-01-01 00:00:00'
|
||||
self.env['mrp.production.workcenter.line'].create(
|
||||
{'name': 'Test',
|
||||
'date_planned': date_planned,
|
||||
'workcenter_id': self.workcenter.id,
|
||||
'production_id': self.production.id})
|
||||
self.assertEqual(self.production.date_planned, date_planned)
|
||||
|
||||
def test_confirm_production_without_do_production_flag(self):
|
||||
self.production.action_compute()
|
||||
self.production.workcenter_lines.write({'do_production': False})
|
||||
with self.assertRaises(UserError):
|
||||
# At least one work order must have checked 'Produce here'
|
||||
self.production.action_confirm()
|
||||
|
||||
def test_confirm_production_operation_extension_case1(self):
|
||||
workflow.trg_validate(
|
||||
self.uid, 'mrp.production', self.production_case1.id,
|
||||
'button_confirm', self.cr)
|
||||
self.production_case1.force_production()
|
||||
for line in self.production_case1.workcenter_lines:
|
||||
workflow.trg_validate(self.uid, 'mrp.production.workcenter.line',
|
||||
line.id, 'button_start_working', self.cr)
|
||||
self.production.signal_workflow('button_confirm')
|
||||
self.assertFalse(self.production.workcenter_lines[0].is_material_ready)
|
||||
self.production.force_production()
|
||||
for line in self.production.workcenter_lines:
|
||||
self.assertTrue(line.is_material_ready)
|
||||
self.assertEqual(len(line.possible_workcenters),
|
||||
len(line.routing_wc_line.op_wc_lines))
|
||||
line.signal_workflow('button_start_working')
|
||||
self.assertEqual(
|
||||
line.state, 'startworking',
|
||||
'Error work center line not in start working state')
|
||||
@@ -44,9 +183,7 @@ class TestMrpOperationsExtension(common.TransactionCase):
|
||||
consume.with_context(active_id=line.id).do_consume()
|
||||
else:
|
||||
consume.with_context(active_id=line.id).do_consume_produce()
|
||||
workflow.trg_validate(
|
||||
self.uid, 'mrp.production.workcenter.line', line.id,
|
||||
'button_done', self.cr)
|
||||
line.signal_workflow('button_done')
|
||||
self.assertEqual(
|
||||
line.state, 'done',
|
||||
'Error work center line not in done state')
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
</group>
|
||||
<group string="Duration">
|
||||
<field name="cycle" />
|
||||
<field name="hour" />
|
||||
<field name="hour" widget="float_time"/>
|
||||
</group>
|
||||
<group string="Actual Production Date">
|
||||
<field name="date_start" />
|
||||
|
||||
@@ -5,17 +5,6 @@
|
||||
<field name="context">{'readonly_by_pass': True}</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="mrp_routing_form_view_inh_opeextension">
|
||||
<field name="name">mrp.routing.form</field>
|
||||
<field name="model">mrp.routing</field>
|
||||
<field name="inherit_id" ref="mrp.mrp_routing_form_view" />
|
||||
<field name="arch" type="xml">
|
||||
<field name="active" position="after">
|
||||
<field name="previous_operations_finished" />
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="mrp_routing_workcenter_tree_view_inh" model="ir.ui.view">
|
||||
<field name="name">mrp.routing.workcenter.tree.inh</field>
|
||||
<field name="model">mrp.routing.workcenter</field>
|
||||
|
||||
@@ -31,17 +31,6 @@ class MrpWorkOrderProduce(models.TransientModel):
|
||||
prod = self._get_product_id()
|
||||
return prod and (prod.track_all or prod.track_production) or False
|
||||
|
||||
def do_produce(self, cr, uid, ids, context=None):
|
||||
work_line = self.pool['mrp.production.workcenter.line'].browse(
|
||||
cr, uid, context.get("active_id"), context=context)
|
||||
production_id = work_line.production_id.id
|
||||
assert production_id
|
||||
data = self.browse(cr, uid, ids[0], context=context)
|
||||
self.pool['mrp.production'].action_produce(
|
||||
cr, uid, production_id, data.product_qty,
|
||||
data.mode, data, context=context)
|
||||
return {}
|
||||
|
||||
def do_consume(self, cr, uid, ids, context=None):
|
||||
work_line = self.pool['mrp.production.workcenter.line'].browse(
|
||||
cr, uid, context.get("active_id"), context=context)
|
||||
@@ -87,7 +76,7 @@ class MrpWorkOrderProduce(models.TransientModel):
|
||||
new_consume_lines.append([0, False, consume])
|
||||
return {'value': {'consume_lines': new_consume_lines}}
|
||||
|
||||
def _get_product_qty(self):
|
||||
def _default_product_qty(self):
|
||||
""" To obtain product quantity
|
||||
@param self: The object pointer.
|
||||
@param cr: A database cursor
|
||||
@@ -98,18 +87,16 @@ class MrpWorkOrderProduce(models.TransientModel):
|
||||
work_line = self.env['mrp.production.workcenter.line'].browse(
|
||||
self.env.context.get("active_id"))
|
||||
prod = work_line.production_id
|
||||
done = 0.0
|
||||
for move in prod.move_created_ids2:
|
||||
if move.product_id == prod.product_id:
|
||||
if not move.scrapped:
|
||||
done += move.product_qty
|
||||
moves = prod.move_created_ids2.filtered(
|
||||
lambda x: x.product_id == prod.product_id and not x.scrapped)
|
||||
done = sum(moves.mapped('product_qty'))
|
||||
return (prod.product_qty - done) or prod.product_qty
|
||||
|
||||
product_id = fields.Many2one('product.product',
|
||||
string='Product', default=_get_product_id)
|
||||
product_qty = fields.Float('Select Quantity',
|
||||
digits=(12, 6), required=True,
|
||||
default=_get_product_qty)
|
||||
product_id = fields.Many2one(
|
||||
'product.product', string='Product', default=_get_product_id)
|
||||
product_qty = fields.Float(
|
||||
string='Select Quantity', digits=(12, 6), required=True,
|
||||
default=_default_product_qty)
|
||||
mode = fields.Selection([('consume_produce', 'Consume & Produce'),
|
||||
('consume', 'Consume Only')],
|
||||
string='Mode', required=True,
|
||||
|
||||