mirror of
https://github.com/OCA/manufacture.git
synced 2025-01-28 16:37:15 +02:00
1
mrp_production_date_planned_finished/README.rst
Normal file
1
mrp_production_date_planned_finished/README.rst
Normal file
@@ -0,0 +1 @@
|
||||
TO BE GENERATED
|
||||
1
mrp_production_date_planned_finished/__init__.py
Normal file
1
mrp_production_date_planned_finished/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import models
|
||||
16
mrp_production_date_planned_finished/__manifest__.py
Normal file
16
mrp_production_date_planned_finished/__manifest__.py
Normal file
@@ -0,0 +1,16 @@
|
||||
# Copyright 2022 Camptocamp SA (https://www.camptocamp.com).
|
||||
# @author Iván Todorovich <ivan.todorovich@camptocamp.com>
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
"name": "MRP Production Date Planned Finished",
|
||||
"summary": "Allows to plan production from the desired finish date",
|
||||
"version": "15.0.1.0.0",
|
||||
"author": "Camptocamp, Odoo Community Association (OCA)",
|
||||
"maintainers": ["ivantodorovich"],
|
||||
"website": "https://github.com/OCA/manufacture",
|
||||
"license": "AGPL-3",
|
||||
"category": "Manufacturing",
|
||||
"depends": ["mrp"],
|
||||
"data": ["views/mrp_production.xml"],
|
||||
}
|
||||
1
mrp_production_date_planned_finished/models/__init__.py
Normal file
1
mrp_production_date_planned_finished/models/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import mrp_production
|
||||
@@ -0,0 +1,26 @@
|
||||
# Copyright 2022 Camptocamp SA (https://www.camptocamp.com).
|
||||
# @author Iván Todorovich <ivan.todorovich@camptocamp.com>
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
from odoo import api, models
|
||||
|
||||
|
||||
class MrpProduction(models.Model):
|
||||
_inherit = "mrp.production"
|
||||
|
||||
@api.onchange("date_planned_finished")
|
||||
def _onchange_date_planned_finished_set_date_planned_start(self):
|
||||
if self.date_planned_finished and not self.is_planned:
|
||||
date_planned_start = self.date_planned_finished
|
||||
date_planned_start -= relativedelta(days=self.product_id.produce_delay)
|
||||
date_planned_start -= relativedelta(days=self.company_id.manufacturing_lead)
|
||||
if date_planned_start == self.date_planned_finished:
|
||||
date_planned_start -= relativedelta(hours=1)
|
||||
if self.date_planned_start != date_planned_start:
|
||||
self.date_planned_start = date_planned_start
|
||||
self.move_raw_ids = [
|
||||
(1, m.id, {"date": self.date_planned_start})
|
||||
for m in self.move_raw_ids
|
||||
]
|
||||
@@ -0,0 +1,3 @@
|
||||
* `Camptocamp <https://www.camptocamp.com>`_
|
||||
|
||||
* Iván Todorovich <ivan.todorovich@camptocamp.com>
|
||||
@@ -0,0 +1,5 @@
|
||||
Shows the Scheduled End Date on Manufacturing Orders, and allows to change the start
|
||||
date from it, through an onchange.
|
||||
|
||||
It's useful for companies wanting to plan their manufacturing orders from the target
|
||||
finish date. Usually these companies have long manufacturing times (days or weeks).
|
||||
1
mrp_production_date_planned_finished/tests/__init__.py
Normal file
1
mrp_production_date_planned_finished/tests/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import test_date_planned_finished
|
||||
@@ -0,0 +1,51 @@
|
||||
# Copyright 2022 Camptocamp SA (https://www.camptocamp.com).
|
||||
# @author Iván Todorovich <ivan.todorovich@camptocamp.com>
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
|
||||
from lxml import etree
|
||||
|
||||
from odoo.tests import Form, TransactionCase
|
||||
|
||||
|
||||
class TestDatePlannedFinished(TransactionCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
|
||||
cls.company = cls.env.ref("base.main_company")
|
||||
cls.company.manufacturing_lead = 1
|
||||
cls.product = cls.env.ref("mrp.product_product_computer_desk")
|
||||
cls.product.produce_delay = 1
|
||||
cls.product_bom = cls.env.ref("mrp.mrp_bom_desk")
|
||||
|
||||
def test_mrp_production_date_planned_finished_onchange(self):
|
||||
"""Test that date_planned_start is set when date_planned_finished is changed."""
|
||||
with Form(self.env["mrp.production"]) as mo:
|
||||
mo.product_id = self.product
|
||||
mo.bom_id = self.product_bom
|
||||
mo.product_qty = 1
|
||||
mo.date_planned_finished = "2022-10-10 10:00:00"
|
||||
self.assertEqual(mo.date_planned_start, "2022-10-08 10:00:00")
|
||||
|
||||
def test_mrp_production_date_planned_finished_decoration(self):
|
||||
"""Test that the date_planned_finished field is decorated properly
|
||||
|
||||
Its decoration has to exactly match the date_planned_start one.
|
||||
As this might change if odoo updates their code, or during migrations,
|
||||
this test case will track any mismatches and fail.
|
||||
"""
|
||||
res = self.env["mrp.production"].fields_view_get(view_type="form")
|
||||
doc = etree.XML(res["arch"])
|
||||
date_planned_start = doc.xpath("//field[@name='date_planned_start']")[0]
|
||||
date_planned_finished = doc.xpath("//field[@name='date_planned_finished']")[0]
|
||||
decoration_attrs = [
|
||||
attr
|
||||
for attr in date_planned_start.attrib.keys()
|
||||
if attr.startswith("decoration-")
|
||||
]
|
||||
for attr in decoration_attrs:
|
||||
self.assertEqual(
|
||||
date_planned_start.attrib[attr],
|
||||
date_planned_finished.attrib[attr],
|
||||
f"date_planned_finished decoration mismatch: {attr}",
|
||||
)
|
||||
@@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!--
|
||||
Copyright 2022 Camptocamp SA (https://www.camptocamp.com).
|
||||
@author Iván Todorovich <ivan.todorovich@camptocamp.com>
|
||||
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
<odoo>
|
||||
|
||||
<record id="mrp_production_form_view" model="ir.ui.view">
|
||||
<field name="model">mrp.production</field>
|
||||
<field name="inherit_id" ref="mrp.mrp_production_form_view" />
|
||||
<field name="arch" type="xml">
|
||||
<xpath
|
||||
expr="//field[@name='date_planned_start']/parent::div"
|
||||
position="after"
|
||||
>
|
||||
<field name="date_planned_finished" position="move" />
|
||||
</xpath>
|
||||
<field name="date_planned_finished" position="attributes">
|
||||
<attribute name="invisible" />
|
||||
<attribute t-translation="off" name="required">1</attribute>
|
||||
<attribute
|
||||
t-translation="off"
|
||||
name="attrs"
|
||||
>{"readonly": [("state", "in", ["close", "cancel"])]}</attribute>
|
||||
<attribute
|
||||
t-translation="off"
|
||||
name="decoration-warning"
|
||||
>state not in ('done', 'cancel') and date_planned_start < now</attribute>
|
||||
<attribute
|
||||
t-translation="off"
|
||||
name="decoration-danger"
|
||||
>state not in ('done', 'cancel') and date_planned_start < current_date</attribute>
|
||||
<attribute
|
||||
t-translation="off"
|
||||
name="decoration-bf"
|
||||
>state not in ('done', 'cancel') and (date_planned_start < current_date or date_planned_start < now)</attribute>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="mrp_production_tree_view" model="ir.ui.view">
|
||||
<field name="model">mrp.production</field>
|
||||
<field name="inherit_id" ref="mrp.mrp_production_tree_view" />
|
||||
<field name="arch" type="xml">
|
||||
<field name="date_planned_start" position="after">
|
||||
<field
|
||||
name="date_planned_finished"
|
||||
readonly="1"
|
||||
optional="show"
|
||||
widget="remaining_days"
|
||||
/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -0,0 +1 @@
|
||||
../../../../mrp_production_date_planned_finished
|
||||
6
setup/mrp_production_date_planned_finished/setup.py
Normal file
6
setup/mrp_production_date_planned_finished/setup.py
Normal file
@@ -0,0 +1,6 @@
|
||||
import setuptools
|
||||
|
||||
setuptools.setup(
|
||||
setup_requires=['setuptools-odoo'],
|
||||
odoo_addon=True,
|
||||
)
|
||||
Reference in New Issue
Block a user