[14.0][ADD] mrp_routing

This commit is contained in:
Christopher Ormaza
2021-12-14 14:34:34 -05:00
parent 192296a4b5
commit 96b57bbff2
25 changed files with 1668 additions and 0 deletions

107
mrp_routing/README.rst Normal file
View File

@@ -0,0 +1,107 @@
===========
MRP Routing
===========
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png
:target: https://odoo-community.org/page/development-status
:alt: Alpha
.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
:alt: License: LGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fmanufacture-lightgray.png?logo=github
:target: https://github.com/OCA/manufacture/tree/14.0/mrp_routing
:alt: OCA/manufacture
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/manufacture-14-0/manufacture-14-0-mrp_routing
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
:target: https://runbot.odoo-community.org/runbot/129/14.0
:alt: Try me on Runbot
|badge1| |badge2| |badge3| |badge4| |badge5|
This module adds routing concept as predefined operations,
operations should work as templates of operations on BOMs
.. IMPORTANT::
This is an alpha version, the data model and design can change at any time without warning.
Only for development or testing purpose, do not use in production.
`More details on development status <https://odoo-community.org/page/development-status>`_
**Table of contents**
.. contents::
:local:
Usage
=====
You can add Routings on Manufacture / Products / Routings
#. Create new Route
#. Add Operations
Operations its a copy of current operations on BOM,
with field "On template change?", this is Sync as default,
in this mode every change on this template is propagated
on operations related with this template
Configure BOM and and Operations Page you can select predefined route (there are two ways to configure with templates)
- You can select a predefined route,
and this action replace and populate with templates associate
- Or You can add operations and select operation
as template to help setting default data
On both configurations you can set field "On template change?" that change behavior when template related perform changes on data
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:%20mrp_routing%0Aversion:%2014.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
Credits
=======
Authors
~~~~~~~
* ForgeFlow
Contributors
~~~~~~~~~~~~
* Christopher Ormaza <chris.ormaza@forgeflow.com>
Maintainers
~~~~~~~~~~~
This module is maintained by the OCA.
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
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.
.. |maintainer-ChrisOForgeFlow| image:: https://github.com/ChrisOForgeFlow.png?size=40px
:target: https://github.com/ChrisOForgeFlow
:alt: ChrisOForgeFlow
Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
|maintainer-ChrisOForgeFlow|
This module is part of the `OCA/manufacture <https://github.com/OCA/manufacture/tree/14.0/mrp_routing>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

4
mrp_routing/__init__.py Normal file
View File

@@ -0,0 +1,4 @@
# Copyright 2021 ForgeFlow S.L.
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from . import models

View File

@@ -0,0 +1,27 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{
"name": "MRP Routing",
"version": "14.0.1.0.0",
"category": "Manufacturing",
"author": "ForgeFlow, Odoo Community Association (OCA)",
"website": "https://github.com/OCA/manufacture",
"license": "AGPL-3",
"maintainers": ["ChrisOForgeFlow"],
"development_status": "Alpha",
"depends": [
"mrp",
],
"data": [
"data/sequence_data.xml",
"security/ir.model.access.csv",
"views/mrp_bom_view.xml",
"views/mrp_routing_view.xml",
"views/mrp_routing_workcenter_view.xml",
"views/mrp_routing_workcenter_template_view.xml",
],
"demo": [
"demo/routing_data.xml",
],
"installable": True,
}

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data noupdate="1">
<record id="sequence_mrp_route" model="ir.sequence">
<field name="name">Routing</field>
<field name="code">mrp.routing</field>
<field name="prefix">RO/</field>
<field name="padding">5</field>
<field name="number_next">1</field>
<field name="number_increment">1</field>
<field name="company_id" eval="False" />
</record>
</data>
</odoo>

View File

@@ -0,0 +1,116 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data>
<record id="mrp_routing_workcenter_0" model="mrp.routing.workcenter.template">
<field name="workcenter_id" ref="mrp.mrp_workcenter_3" />
<field name="name">Manual Assembly</field>
<field name="time_cycle_manual">60</field>
<field name="sequence">5</field>
<field name="worksheet_type">pdf</field>
<field
name="worksheet"
type="base64"
file="mrp/static/img/assebly-worksheet.pdf"
/>
</record>
<record id="mrp_routing_workcenter_1" model="mrp.routing.workcenter.template">
<field name="workcenter_id" ref="mrp.mrp_workcenter_3" />
<field name="name">Long time assembly</field>
<field name="time_cycle_manual">180</field>
<field name="sequence">15</field>
<field name="worksheet_type">pdf</field>
<field
name="worksheet"
type="base64"
file="mrp/static/img/cutting-worksheet.pdf"
/>
</record>
<record id="mrp_routing_workcenter_3" model="mrp.routing.workcenter.template">
<field name="workcenter_id" ref="mrp.mrp_workcenter_3" />
<field name="name">Testing</field>
<field name="time_cycle_manual">60</field>
<field name="sequence">10</field>
<field name="worksheet_type">pdf</field>
<field
name="worksheet"
type="base64"
file="mrp/static/img/assebly-worksheet.pdf"
/>
</record>
<record id="mrp_routing_workcenter_4" model="mrp.routing.workcenter.template">
<field name="workcenter_id" ref="mrp.mrp_workcenter_1" />
<field name="name">Packing</field>
<field name="time_cycle_manual">30</field>
<field name="sequence">5</field>
<field name="worksheet_type">pdf</field>
<field
name="worksheet"
type="base64"
file="mrp/static/img/cutting-worksheet.pdf"
/>
</record>
<record id="mrp_routing_workcenter_2" model="mrp.routing.workcenter.template">
<field name="workcenter_id" ref="mrp.mrp_workcenter_2" />
<field name="time_cycle_manual">120</field>
<field name="sequence">5</field>
<field name="name">Manual Assembly</field>
<field name="worksheet_type">pdf</field>
<field
name="worksheet"
type="base64"
file="mrp/static/img/assebly-worksheet.pdf"
/>
</record>
<record id="mrp_routing_workcenter_5" model="mrp.routing.workcenter.template">
<field name="workcenter_id" ref="mrp.mrp_workcenter_3" />
<field name="time_cycle_manual">120</field>
<field name="sequence">10</field>
<field name="name">Assembly Line 1</field>
<field name="worksheet_type">pdf</field>
<field
name="worksheet"
type="base64"
file="mrp/static/img/cutting-worksheet.pdf"
/>
</record>
<record id="mrp_routing_0" model="mrp.routing">
<field name="name">Primary Assembly</field>
<field
name="operation_ids"
eval="[(6, 0, [ref('mrp_routing_workcenter_0')])]"
/>
</record>
<record id="mrp_routing_1" model="mrp.routing">
<field name="name">Secondary Assembly</field>
<field
name="operation_ids"
eval="[(6, 0, [ref('mrp_routing_workcenter_1'), ref('mrp_routing_workcenter_3'), ref('mrp_routing_workcenter_4')])]"
/>
</record>
<record id="mrp_routing_2" model="mrp.routing">
<field name="name">Manual Component's Assembly</field>
<field
name="operation_ids"
eval="[(6, 0, [ref('mrp_routing_workcenter_2')])]"
/>
</record>
<record id="mrp_routing_3" model="mrp.routing">
<field name="name">Assemble Furniture</field>
<field
name="operation_ids"
eval="[(6, 0, [ref('mrp_routing_workcenter_5')])]"
/>
</record>
</data>
</odoo>

View File

View File

@@ -0,0 +1,7 @@
# Copyright 2023 ForgeFlow S.L.
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from . import mrp_routing_workcenter_template
from . import mrp_routing
from . import mrp_bom
from . import mrp_routing_workcenter

View File

@@ -0,0 +1,38 @@
# Copyright 2023 ForgeFlow S.L.
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import api, fields, models
from .mrp_routing_workcenter_template import FIELDS_TO_SYNC
class MrpBom(models.Model):
_inherit = "mrp.bom"
routing_id = fields.Many2one(
comodel_name="mrp.routing",
string="Predefined Operations",
check_company=True,
tracking=True,
)
@api.onchange("routing_id")
def onchange_routing_id(self):
opeartion_model = self.env["mrp.routing.workcenter"]
if self.routing_id and self.routing_id.operation_ids:
new_operations = opeartion_model.browse()
for template_operation in self.routing_id.operation_ids:
operation_data = template_operation.read(
FIELDS_TO_SYNC, load="_classic_write"
)[0]
operation_data.pop("id")
if "operation_ids" in operation_data:
operation_data.pop("operation_ids")
operation_data.update(
{
"template_id": template_operation.id,
"on_template_change": "sync",
}
)
new_operations |= opeartion_model.new(operation_data)
self.operation_ids = new_operations

View File

@@ -0,0 +1,60 @@
# Copyright 2023 ForgeFlow S.L.
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import _, api, fields, models
class MrpRouting(models.Model):
_name = "mrp.routing"
_description = "Manufacturing Routing"
name = fields.Char("Routing", required=True)
active = fields.Boolean(
"Active",
default=True,
help="If the active field is set to False, "
"it will allow you to hide the routing without removing it.",
)
code = fields.Char(
"Reference", copy=False, default=lambda self: _("New"), readonly=True
)
note = fields.Text("Description")
operation_ids = fields.Many2many(
comodel_name="mrp.routing.workcenter.template", string="Operations"
)
company_id = fields.Many2one(
"res.company", "Company", default=lambda self: self.env.company
)
bom_ids = fields.One2many(
comodel_name="mrp.bom",
inverse_name="routing_id",
string="Boms",
required=False,
copy=False,
)
@api.model
def create(self, vals):
if "code" not in vals or vals["code"] == _("New"):
vals["code"] = self.env["ir.sequence"].next_by_code("mrp.routing") or _(
"New"
)
return super(MrpRouting, self).create(vals)
def write(self, values):
res = super(MrpRouting, self).write(values)
if "operation_ids" in values:
for rec in self:
for bom in rec.bom_ids:
operations_not_synced = (
rec.operation_ids - bom.operation_ids.mapped("template_id")
)
for operation in operations_not_synced:
operation.create_operation_from_template(bom)
operations_to_delete = bom.operation_ids.filtered(
lambda x: x.template_id.id not in rec.operation_ids.ids
)
if operations_to_delete:
operations_to_delete.unlink()
return res

View File

@@ -0,0 +1,35 @@
# Copyright 2023 ForgeFlow S.L.
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import api, fields, models
from .mrp_routing_workcenter_template import FIELDS_TO_SYNC
class MrpRoutingWorkcenter(models.Model):
_inherit = "mrp.routing.workcenter"
template_id = fields.Many2one(
comodel_name="mrp.routing.workcenter.template",
string="Template",
readonly=False,
)
on_template_change = fields.Selection(
string="On template change?",
selection=[
("nothing", "Do nothing"),
("sync", "Sync"),
],
required=False,
default="sync",
)
@api.onchange("template_id")
def onchange_template_id(self):
if self.template_id:
to_update_data = self.template_id.read(
FIELDS_TO_SYNC, load="_classic_wirte"
)[0]
to_update_data.pop("id")
self.update(to_update_data)

View File

@@ -0,0 +1,132 @@
# Copyright 2023 ForgeFlow S.L.
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import api, fields, models
FIELDS_TO_SYNC = [
"name",
"workcenter_id",
"sequence",
"worksheet_type",
"note",
"worksheet",
"worksheet_google_slide",
"time_mode",
"time_mode_batch",
"time_cycle_manual",
"on_template_change",
]
class MrpRoutingWorkcenterTemplate(models.Model):
_name = "mrp.routing.workcenter.template"
_description = "Template Work Center Usage"
_order = "sequence, id"
_check_company_auto = True
name = fields.Char("Operation", required=True)
workcenter_id = fields.Many2one(
"mrp.workcenter", "Work Center", required=True, check_company=True
)
sequence = fields.Integer(
"Sequence",
default=100,
help="Gives the sequence order when displaying a list of routing Work Centers.",
)
company_id = fields.Many2one(
"res.company", "Company", default=lambda self: self.env.company
)
worksheet_type = fields.Selection(
[("pdf", "PDF"), ("google_slide", "Google Slide"), ("text", "Text")],
string="Work Sheet",
default="text",
help="Defines if you want to use a PDF " "or a Google Slide as work sheet.",
)
note = fields.Text("Description", help="Text worksheet description")
worksheet = fields.Binary("PDF")
worksheet_google_slide = fields.Char(
"Google Slide",
help="Paste the url of your Google Slide. "
"Make sure the access to the document is public.",
)
time_mode = fields.Selection(
[
("auto", "Compute based on tracked time"),
("manual", "Set duration manually"),
],
string="Duration Computation",
default="manual",
)
time_mode_batch = fields.Integer("Based on", default=10)
time_cycle_manual = fields.Float(
"Manual Duration",
default=60,
help="Time in minutes:"
"- In manual mode, time used"
"- In automatic mode, "
"supposed first time when there aren't any work orders yet",
)
operation_ids = fields.One2many(
comodel_name="mrp.routing.workcenter",
inverse_name="template_id",
string="Operations",
required=False,
copy=False,
)
on_template_change = fields.Selection(
string="On template change?",
selection=[
("nothing", "Do nothing"),
("sync", "Sync"),
],
required=False,
default="sync",
)
routing_ids = fields.Many2many(comodel_name="mrp.routing", string="Routings")
def create_operation_from_template(self, bom):
operation_model = self.env["mrp.routing.workcenter"]
for operation in self:
operation_data = operation.read(FIELDS_TO_SYNC, load="_classic_write")[0]
operation_data.update(
{
"bom_id": bom.id,
"template_id": operation.id,
"on_template_change": "sync",
}
)
operation_model.create(operation_data)
@api.model_create_multi
def create(self, values):
recs = super(MrpRoutingWorkcenterTemplate, self).create(values)
for rec in self:
for bom in rec.mapped("routing_ids.bom_ids"):
rec.create_operation_from_template(bom)
return recs
def unlink(self):
for rec in self:
synced_records = rec.operation_ids.filtered(
lambda x: x.on_template_change == "sync"
)
if synced_records:
synced_records.unlink()
return super(MrpRoutingWorkcenterTemplate, self).unlink()
def write(self, values):
res = super(MrpRoutingWorkcenterTemplate, self).write(values)
current_field_changes = []
for field_name in FIELDS_TO_SYNC:
if field_name in values.keys():
current_field_changes.append(field_name)
if current_field_changes:
for rec in self.filtered(lambda x: x.operation_ids):
to_write_data = rec.read(current_field_changes)[0]
to_write = rec.operation_ids.filtered(
lambda x: x.on_template_change == "sync"
)
if to_write:
to_write.write(to_write_data)
return res

View File

@@ -0,0 +1 @@
* Christopher Ormaza <chris.ormaza@forgeflow.com>

View File

@@ -0,0 +1,2 @@
This module adds routing concept as predefined operations,
operations should work as templates of operations on BOMs

View File

@@ -0,0 +1,16 @@
You can add Routings on Manufacture / Products / Routings
#. Create new Route
#. Add Operations
Operations its a copy of current operations on BOM,
with field "On template change?", this is Sync as default,
in this mode every change on this template is propagated
on operations related with this template
Configure BOM and and Operations Page you can select predefined route (there are two ways to configure with templates)
- You can select a predefined route,
and this action replace and populate with templates associate
- Or You can add operations and select operation
as template to help setting default data
On both configurations you can set field "On template change?" that change behavior when template related perform changes on data

View File

@@ -0,0 +1,5 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_mrp_routing,mrp.routing,model_mrp_routing,mrp.group_mrp_user,1,0,0,0
access_mrp_routing_manager,mrp.routing.manager,model_mrp_routing,mrp.group_mrp_manager,1,1,1,1
access_mrp_routing_workcenter_template,mrp.routing.workcenter,model_mrp_routing_workcenter_template,mrp.group_mrp_user,1,0,0,0
access_mrp_routing_workcenter_template_manager,mrp.routing.workcenter.manager,model_mrp_routing_workcenter_template,mrp.group_mrp_manager,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_mrp_routing mrp.routing model_mrp_routing mrp.group_mrp_user 1 0 0 0
3 access_mrp_routing_manager mrp.routing.manager model_mrp_routing mrp.group_mrp_manager 1 1 1 1
4 access_mrp_routing_workcenter_template mrp.routing.workcenter model_mrp_routing_workcenter_template mrp.group_mrp_user 1 0 0 0
5 access_mrp_routing_workcenter_template_manager mrp.routing.workcenter.manager model_mrp_routing_workcenter_template mrp.group_mrp_manager 1 1 1 1

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@@ -0,0 +1,455 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils: http://docutils.sourceforge.net/" />
<title>MRP Routing</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="mrp-routing">
<h1 class="title">MRP Routing</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Alpha" src="https://img.shields.io/badge/maturity-Alpha-red.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/lgpl-3.0-standalone.html"><img alt="License: LGPL-3" src="https://img.shields.io/badge/licence-LGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/manufacture/tree/14.0/mrp_routing"><img alt="OCA/manufacture" src="https://img.shields.io/badge/github-OCA%2Fmanufacture-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/manufacture-14-0/manufacture-14-0-mrp_routing"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/129/14.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
<p>This module adds routing concept as predefined operations,
operations should work as templates of operations on BOMs</p>
<div class="admonition important">
<p class="first admonition-title">Important</p>
<p class="last">This is an alpha version, the data model and design can change at any time without warning.
Only for development or testing purpose, do not use in production.
<a class="reference external" href="https://odoo-community.org/page/development-status">More details on development status</a></p>
</div>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#usage" id="id1">Usage</a></li>
<li><a class="reference internal" href="#bug-tracker" id="id2">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="id3">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="id4">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="id5">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="id6">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="usage">
<h1><a class="toc-backref" href="#id1">Usage</a></h1>
<p>You can add Routings on Manufacture / Products / Routings</p>
<ol class="arabic simple">
<li>Create new Route</li>
<li><dl class="first docutils">
<dt>Add Operations</dt>
<dd>Operations its a copy of current operations on BOM,
with field “On template change?”, this is Sync as default,
in this mode every change on this template is propagated
on operations related with this template</dd>
</dl>
</li>
</ol>
<dl class="docutils">
<dt>Configure BOM and and Operations Page you can select predefined route (there are two ways to configure with templates)</dt>
<dd><ul class="first last simple">
<li>You can select a predefined route,
and this action replace and populate with templates associate</li>
<li>Or You can add operations and select operation
as template to help setting default data</li>
</ul>
</dd>
</dl>
<p>On both configurations you can set field “On template change?” that change behavior when template related perform changes on data</p>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#id2">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/manufacture/issues">GitHub Issues</a>.
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
<a class="reference external" href="https://github.com/OCA/manufacture/issues/new?body=module:%20mrp_routing%0Aversion:%2014.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#id3">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#id4">Authors</a></h2>
<ul class="simple">
<li>ForgeFlow</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#id5">Contributors</a></h2>
<ul class="simple">
<li>Christopher Ormaza &lt;<a class="reference external" href="mailto:chris.ormaza&#64;forgeflow.com">chris.ormaza&#64;forgeflow.com</a>&gt;</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#id6">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
<p>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.</p>
<p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainer</a>:</p>
<p><a class="reference external" href="https://github.com/ChrisOForgeFlow"><img alt="ChrisOForgeFlow" src="https://github.com/ChrisOForgeFlow.png?size=40px" /></a></p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/manufacture/tree/14.0/mrp_routing">OCA/manufacture</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1 @@
from . import test_manufacturing_routing

View File

@@ -0,0 +1,295 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo.tests.common import SavepointCase
from ..models.mrp_routing_workcenter_template import FIELDS_TO_SYNC
class TestRestrictLot(SavepointCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.product_obj = cls.env["product.product"]
cls.bom_obj = cls.env["mrp.bom"]
cls.bom_line_obj = cls.env["mrp.bom.line"]
cls.routing_obj = cls.env["mrp.routing"]
cls.workcenter_obj = cls.env["mrp.workcenter"]
cls.routing_workcenter_obj = cls.env["mrp.routing.workcenter"]
cls.routing_workcenter_template_obj = cls.env["mrp.routing.workcenter.template"]
# Create products:
cls.product_1 = cls.product_obj.create({"name": "TEST 01", "type": "product"})
cls.product_2 = cls.product_obj.create({"name": "TEST 02", "type": "product"})
cls.product_3 = cls.product_obj.create({"name": "TEST 03", "type": "product"})
cls.component_1 = cls.product_obj.create({"name": "RM 01", "type": "product"})
cls.component_2 = cls.product_obj.create({"name": "RM 02", "type": "product"})
# Create Bills of Materials:
cls.bom_1 = cls.bom_obj.create(
{"product_tmpl_id": cls.product_1.product_tmpl_id.id}
)
cls.line_1_1 = cls.bom_line_obj.create(
{
"product_id": cls.component_1.id,
"bom_id": cls.bom_1.id,
"product_qty": 2.0,
}
)
cls.line_1_2 = cls.bom_line_obj.create(
{
"product_id": cls.component_2.id,
"bom_id": cls.bom_1.id,
"product_qty": 5.0,
}
)
cls.bom_2 = cls.bom_obj.create(
{"product_tmpl_id": cls.product_1.product_tmpl_id.id}
)
cls.line_2_1 = cls.bom_line_obj.create(
{
"product_id": cls.component_1.id,
"bom_id": cls.bom_2.id,
"product_qty": 2.0,
}
)
cls.line_2_2 = cls.bom_line_obj.create(
{
"product_id": cls.component_2.id,
"bom_id": cls.bom_2.id,
"product_qty": 5.0,
}
)
cls.bom_3 = cls.bom_obj.create(
{"product_tmpl_id": cls.product_1.product_tmpl_id.id}
)
cls.line_3_1 = cls.bom_line_obj.create(
{
"product_id": cls.component_1.id,
"bom_id": cls.bom_3.id,
"product_qty": 2.0,
}
)
cls.line_3_2 = cls.bom_line_obj.create(
{
"product_id": cls.component_2.id,
"bom_id": cls.bom_3.id,
"product_qty": 5.0,
}
)
# Create Routing
cls.workcenter_1 = cls.env.ref("mrp.mrp_workcenter_1")
cls.workcenter_2 = cls.env.ref("mrp.mrp_workcenter_2")
cls.workcenter_3 = cls.env.ref("mrp.mrp_workcenter_3")
cls.operation_template_1 = cls.routing_workcenter_template_obj.create(
{
"workcenter_id": cls.workcenter_1.id,
"name": "Operation 1",
"time_cycle_manual": 60,
"sequence": 5,
"worksheet_type": "text",
"on_template_change": "sync",
}
)
cls.operation_template_2 = cls.routing_workcenter_template_obj.create(
{
"workcenter_id": cls.workcenter_2.id,
"name": "Operation 2",
"time_cycle_manual": 120,
"sequence": 10,
"worksheet_type": "text",
"on_template_change": "sync",
}
)
cls.operation_template_3 = cls.routing_workcenter_template_obj.create(
{
"workcenter_id": cls.workcenter_3.id,
"name": "Operation 3",
"time_cycle_manual": 180,
"sequence": 15,
"worksheet_type": "text",
"on_template_change": "sync",
}
)
cls.operation_template_4 = cls.routing_workcenter_template_obj.create(
{
"workcenter_id": cls.workcenter_2.id,
"name": "Operation 4",
"time_cycle_manual": 150,
"sequence": 15,
"worksheet_type": "text",
"on_template_change": "nothing",
}
)
cls.routing_1 = cls.routing_obj.create(
{
"name": "Routing 1",
"operation_ids": [
(
6,
0,
[
cls.operation_template_1.id,
cls.operation_template_2.id,
cls.operation_template_3.id,
cls.operation_template_4.id,
],
)
],
}
)
def test_01_sync_onchange_predefined_operations(self):
self.bom_1.routing_id = self.routing_1.id
self.bom_1.onchange_routing_id()
self.assertEqual(
self.bom_1.operation_ids.mapped("template_id").ids,
self.routing_1.operation_ids.ids,
)
for operation in self.bom_1.operation_ids:
for field_to_check in FIELDS_TO_SYNC:
# When is setted as predefined,
# all operations are in synced mode
if field_to_check == "on_template_change":
continue
self.assertEqual(
operation[field_to_check], operation.template_id[field_to_check]
)
def test_02_sync_templates_changes_by_bom(self):
self.bom_1.routing_id = self.routing_1.id
self.bom_1.onchange_routing_id()
self.bom_2.routing_id = self.routing_1.id
self.bom_2.onchange_routing_id()
self.operation_template_1.write(
{
"sequence": 30,
"time_cycle_manual": 100,
}
)
for operation in self.routing_workcenter_obj.search(
[("template_id", "=", self.operation_template_1.id)]
):
self.assertEqual(operation.sequence, self.operation_template_1.sequence)
self.assertEqual(
operation.time_cycle_manual, self.operation_template_1.time_cycle_manual
)
# Operation 4 is setted that not sync on changes,
# but operations was created by predefined operations
self.operation_template_4.write(
{
"name": "New Operation Name",
"time_cycle_manual": 100,
}
)
for operation in self.routing_workcenter_obj.search(
[("template_id", "=", self.operation_template_4.id)]
):
self.assertEqual(operation.name, self.operation_template_4.name)
self.assertEqual(
operation.time_cycle_manual, self.operation_template_4.time_cycle_manual
)
# On delete all operations related should be deleted
self.assertEqual(
2,
self.routing_workcenter_obj.search_count(
[("template_id", "=", self.operation_template_3.id)]
),
)
self.operation_template_3.unlink()
self.assertEqual(
0,
self.routing_workcenter_obj.search_count(
[("template_id", "=", self.operation_template_3.id)]
),
)
def test_03_sync_templates_changes_manual_creation(self):
operation_1 = self.routing_workcenter_obj.create(
{
"workcenter_id": self.workcenter_1.id,
"name": "Operation without name",
"time_cycle_manual": 150,
"sequence": 15,
"worksheet_type": "text",
"bom_id": self.bom_3.id,
}
)
operation_1.write(
{
"template_id": self.operation_template_1,
}
)
operation_1.onchange_template_id()
for field_to_check in FIELDS_TO_SYNC:
self.assertEqual(
operation_1[field_to_check], operation_1.template_id[field_to_check]
)
operation_2 = self.routing_workcenter_obj.create(
{
"workcenter_id": self.workcenter_2.id,
"name": "Operation 4",
"time_cycle_manual": 20,
"sequence": 5,
"worksheet_type": "text",
"bom_id": self.bom_3.id,
}
)
operation_2.write(
{
"template_id": self.operation_template_4,
}
)
operation_2.onchange_template_id()
self.operation_template_4.write({"name": "New Name Operation 4"})
self.assertNotEqual(operation_2.name, self.operation_template_4.name)
def test_04_sync_templates_routing_changes(self):
self.bom_1.routing_id = self.routing_1.id
self.bom_1.onchange_routing_id()
self.bom_2.routing_id = self.routing_1.id
self.bom_2.onchange_routing_id()
self.routing_1.write(
{
"operation_ids": [
(
6,
0,
[
self.operation_template_1.id,
self.operation_template_2.id,
],
)
]
}
)
self.assertNotIn(
self.operation_template_4.id,
self.bom_1.operation_ids.mapped("template_id").ids,
)
self.assertNotIn(
self.operation_template_4.id,
self.bom_2.operation_ids.mapped("template_id").ids,
)
self.routing_1.write(
{
"operation_ids": [
(
6,
0,
[
self.operation_template_1.id,
self.operation_template_2.id,
self.operation_template_4.id,
],
)
]
}
)
self.assertIn(
self.operation_template_4.id,
self.bom_1.operation_ids.mapped("template_id").ids,
)
self.assertIn(
self.operation_template_4.id,
self.bom_2.operation_ids.mapped("template_id").ids,
)

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data>
<record id="mrp_bom_form_view" model="ir.ui.view">
<field name="name">mrp.bom.form.view</field>
<field name="model">mrp.bom</field>
<field name="inherit_id" ref="mrp.mrp_bom_form_view" />
<field name="arch" type="xml">
<xpath expr="//field[@name='operation_ids']" position="before">
<label for="routing_id" />
<field name="routing_id" />
</xpath>
</field>
</record>
</data>
</odoo>

View File

@@ -0,0 +1,139 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data>
<record id="mrp_routing_form_view" model="ir.ui.view">
<field name="name">mrp.routing.form</field>
<field name="model">mrp.routing</field>
<field name="arch" type="xml">
<form string="Routing">
<sheet>
<div class="oe_button_box" name="button_box">
</div>
<widget
name="web_ribbon"
title="Archived"
bg_color="bg-danger"
attrs="{'invisible': [('active', '=', True)]}"
/>
<div class="oe_title">
<h1>
<field name="code" />
</h1>
</div>
<group>
<group>
<field name="name" />
<field name="active" invisible="1" />
</group>
<group>
<field
name="company_id"
options="{'no_create': True}"
groups="base.group_multi_company"
/>
</group>
</group>
<notebook>
<page string="Work Center Operations">
<field
name="operation_ids"
context="{'default_routing_id': id}"
/>
</page>
<page string="Notes">
<field name="note" />
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<record id="mrp_routing_tree_view" model="ir.ui.view">
<field name="name">mrp.routing.tree</field>
<field name="model">mrp.routing</field>
<field name="arch" type="xml">
<tree string="Routing">
<field name="code" />
<field name="name" />
<field name="active" invisible="1" />
<field name="company_id" groups="base.group_multi_company" />
</tree>
</field>
</record>
<record id="mrp_routing_kanban_view" model="ir.ui.view">
<field name="name">mrp.routing.kanban</field>
<field name="model">mrp.routing</field>
<field name="arch" type="xml">
<kanban class="o_kanban_mobile">
<field name="code" />
<field name="name" />
<templates>
<t t-name="kanban-box">
<div t-attf-class="oe_kanban_card oe_kanban_global_click">
<div class="o_kanban_record_top">
<div class="o_kanban_record_headings mt4">
<strong class="o_kanban_record_title"><span><t
t-esc="record.name.value"
/></span></strong>
</div>
<span class="badge badge-pill"><field
name="code"
/></span>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<record id="mrp_routing_search_view" model="ir.ui.view">
<field name="name">mrp.routing.search</field>
<field name="model">mrp.routing</field>
<field name="arch" type="xml">
<search string="Routing">
<field
name="name"
string="Routing"
filter_domain="['|', ('name', 'ilike', self), ('code', 'ilike', self)]"
/>
<filter
name="inactive"
string="Archived"
domain="[('active', '=', False)]"
/>
</search>
</field>
</record>
<record id="mrp_routing_action" model="ir.actions.act_window">
<field name="name">Routings</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">mrp.routing</field>
<field name="view_mode">tree,kanban,form</field>
<field name="view_id" ref="mrp_routing_tree_view" />
<field name="search_view_id" ref="mrp_routing_search_view" />
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a new routing
</p><p>
Routings define the successive operations that need to be
done to realize a Manufacturing Order. Each operation from
a Routing is done at a specific Work Center and has a specific duration.
</p>
</field>
</record>
<menuitem
id="menu_mrp_routing_action"
action="mrp_routing_action"
parent="mrp.menu_mrp_bom"
groups="mrp.group_mrp_routings"
sequence="50"
/>
</data>
</odoo>

View File

@@ -0,0 +1,143 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data>
<record id="mrp_routing_workcenter_template_tree_view" model="ir.ui.view">
<field name="name">mrp.routing.workcenter.template.tree</field>
<field name="model">mrp.routing.workcenter.template</field>
<field name="arch" type="xml">
<tree string="Template Routing Work Centers">
<field name="sequence" widget="handle" />
<field name="name" />
<field name="workcenter_id" />
<field name="routing_ids" widget="many2many_tags" />
</tree>
</field>
</record>
<record id="mrp_routing_workcenter_template_form_view" model="ir.ui.view">
<field name="name">mrp.routing.workcenter.template.form</field>
<field name="model">mrp.routing.workcenter.template</field>
<field name="arch" type="xml">
<form string="Template Routing Work Centers">
<sheet>
<group>
<group name="description">
<field name="name" />
<field
name="workcenter_id"
context="{'default_company_id': company_id}"
/>
<field name="sequence" groups="base.group_no_one" />
<field name="on_template_change" />
</group><group name="workorder">
<field name="time_mode" widget="radio" />
<label
for="time_mode_batch"
attrs="{'invisible': [('time_mode', '=', 'manual')]}"
/>
<div
attrs="{'invisible': [('time_mode', '=', 'manual')]}"
>
last
<field name="time_mode_batch" class="oe_inline" />
work orders
</div>
<label
for="time_cycle_manual"
attrs="{'invisible': [('time_mode', '=', 'auto')]}"
string="Default Duration"
/>
<div
attrs="{'invisible': [('time_mode', '=', 'auto')]}"
>
<field
name="time_cycle_manual"
widget="float_time"
class="oe_inline"
/> minutes
</div>
<field
name="company_id"
groups="base.group_multi_company"
/>
</group>
</group>
<notebook>
<page string="Work Sheet" name="worksheet">
<group>
<field name="worksheet_type" widget="radio" />
<field
name="worksheet"
help="Upload your PDF file."
widget="pdf_viewer"
attrs="{'invisible': [('worksheet_type', '!=', 'pdf')], 'required': [('worksheet_type', '=', 'pdf')]}"
/>
<field
name="worksheet_google_slide"
placeholder="Google Slide Link"
widget="embed_viewer"
attrs="{'invisible': [('worksheet_type', '!=', 'google_slide')], 'required': [('worksheet_type', '=', 'google_slide')]}"
/>
<field
name="note"
attrs="{'invisible': [('worksheet_type', '!=', 'text')]}"
/>
</group>
</page>
<page string="Routings" name="routings">
<field name="routing_ids" />
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<record id="mrp_routing_workcenter_template_search_view" model="ir.ui.view">
<field name="name">mrp.routing.workcenter.template.search</field>
<field name="model">mrp.routing.workcenter.template</field>
<field name="arch" type="xml">
<search string="Template Operations">
<field name="name" />
<field name="workcenter_id" />
<field name="routing_ids" />
<filter
name="group_by_workcenter"
string="Workcenter"
context="{'group_by':'workcenter_id'}"
/>
</search>
</field>
</record>
<record
id="action_mrp_routing_workcenter_template_tree_view"
model="ir.actions.act_window"
>
<field name="name">Template Operations</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">mrp.routing.workcenter.template</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="mrp_routing_workcenter_template_tree_view" />
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a new template operation
</p><p>
Template Operation can be used to make template for operations related to bill of materials.
</p>
</field>
<field name="domain">[]</field>
</record>
<menuitem
id="menu_action_mrp_routing_workcenter_template_tree_view"
action="action_mrp_routing_workcenter_template_tree_view"
parent="mrp.menu_mrp_configuration"
groups="mrp.group_mrp_routings"
sequence="100"
/>
</data>
</odoo>

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data>
<record id="mrp_routing_workcenter_tree_view" model="ir.ui.view">
<field name="name">mrp.routing.workcenter.tree</field>
<field name="model">mrp.routing.workcenter</field>
<field name="inherit_id" ref="mrp.mrp_routing_workcenter_tree_view" />
<field name="arch" type="xml">
<xpath expr="//field[@name='workcenter_id']" position="before">
<field name="template_id" force_save="1" />
<field name="on_template_change" />
<!--FIXME: Can we skip this invisible files to get correct data on onchange?-->
<field name="time_mode" invisible="1" />
<field name="time_mode_batch" invisible="1" />
<field name="time_cycle_manual" invisible="1" />
<field name="company_id" invisible="1" />
<field name="worksheet" invisible="1" />
<field name="worksheet_type" invisible="1" />
<field name="worksheet_google_slide" invisible="1" />
<field name="note" invisible="1" />
</xpath>
</field>
</record>
<record id="mrp_routing_workcenter_form_view" model="ir.ui.view">
<field name="name">mrp.routing.workcenter.form</field>
<field name="model">mrp.routing.workcenter</field>
<field name="inherit_id" ref="mrp.mrp_routing_workcenter_form_view" />
<field name="arch" type="xml">
<xpath expr="//field[@name='name']" position="before">
<field name="template_id" />
<field
name="on_template_change"
attrs="{'invisible': [('template_id', '=', False)]}"
/>
</xpath>
</field>
</record>
</data>
</odoo>

View File

@@ -0,0 +1 @@
../../../../mrp_routing

View File

@@ -0,0 +1,6 @@
import setuptools
setuptools.setup(
setup_requires=['setuptools-odoo'],
odoo_addon=True,
)