[IMP] mrp_hook+mrp_operations_extension: Adaptation to OCA

This commit is contained in:
Pedro M. Baeza
2015-11-26 19:12:34 +01:00
parent 844d86b062
commit 12db7c3041
39 changed files with 879 additions and 820 deletions

View File

@@ -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(

View File

@@ -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,

View File

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

View File

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

View File

@@ -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
}

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

81
mrp_hook/images/image.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 125 KiB

View File

@@ -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"]

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 9.0 KiB

View 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

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

View File

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

View File

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

View File

@@ -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",

View File

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

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

View File

@@ -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 ""

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 14 KiB

View File

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

View File

@@ -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" />

View File

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

View File

@@ -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,