From 44988be6c76e1574284e40ef9302ff58680a10b7 Mon Sep 17 00:00:00 2001 From: Johan De Taeye Date: Tue, 5 Nov 2024 16:14:55 +0100 Subject: [PATCH 1/6] fixes for runs with MO level planning only --- frepple/controllers/outbound.py | 95 ++++++++++++++++++++++----------- 1 file changed, 63 insertions(+), 32 deletions(-) diff --git a/frepple/controllers/outbound.py b/frepple/controllers/outbound.py index 268d6dd..5d03739 100644 --- a/frepple/controllers/outbound.py +++ b/frepple/controllers/outbound.py @@ -1478,11 +1478,11 @@ def export_boms(self): quoteattr(location), ) else: - duration_per = (i["produce_delay"] or 0) + ( + duration = (i["produce_delay"] or 0) + ( i["days_to_prepare_mo"] or 0 ) - yield '\n' "\n" % ( + yield '\n' "\n" % ( quoteattr(operation), ( ("description=%s " % quoteattr(i["code"])) @@ -1490,8 +1490,8 @@ def export_boms(self): else "" ), ( - self.convert_float_time(duration_per) - if duration_per and duration_per > 0 + self.convert_float_time(duration) + if duration and duration > 0 else "P0D" ), self.manufacturing_lead, @@ -2060,7 +2060,12 @@ def getReservedQuantity(stock_move_id): ), due, priority, - qty - reserved_quantity if j["picking_policy"] == "one" and qty - reserved_quantity > 0 else 0.0, + ( + qty - reserved_quantity + if j["picking_policy"] == "one" + and qty - reserved_quantity > 0 + else 0.0 + ), "open" if qty - reserved_quantity > 0 else "closed", quoteattr(product["name"]), quoteattr(customer), @@ -2448,9 +2453,12 @@ def export_manufacturingorders(self): startdate = self.formatDateTime( i.date_start if i.date_start else i.date_planned_start ) - # enddate = self.formatDateTime(i.date_planned_finished) except Exception: continue + try: + enddate = self.formatDateTime(i.date_finished) + except Exception: + enddate = None qty = self.convert_qty_uom( i.qty_producing if i.qty_producing else i.product_qty, i.product_uom_id.id, @@ -2470,31 +2478,24 @@ def export_manufacturingorders(self): batch = mto_mo[0].display_name if mto_mo else i.name # Create a record for the MO - # Option 1: compute MO end date based on the start date - yield '\n' % ( + yield '\n' % ( quoteattr(i.name), quoteattr(batch), - startdate, + ( + "start" # Option 1: compute MO end date based on the start date + if self.manage_work_orders or not enddate + else "end" # Option 2: compute MO start date based on the end date + ), + (startdate if self.manage_work_orders or not enddate else enddate), qty, - "approved", # In the "approved" status, frepple can still reschedule the MO in function of material and capacity - # "confirmed", # In the "confirmed" status, frepple sees the MO as frozen and unchangeable - # "approved" if i["status"] == "confirmed" else "confirmed", # In-progress can't be rescheduled in frepple, but confirmed MOs + # In the "approved" status, frepple can still reschedule the MO in function of material and capacity + # In the "confirmed" status, frepple sees the MO as frozen and unchangeable + ( + "approved" + if self.manage_work_orders or i.state in ("confirmed", "draft") + else "confirmed" + ), ) - # Option 2: compute MO start date based on the end date - # yield '\n' % ( - # quoteattr(i["name"]), - # enddate, - # qty, - # # "approved", # In the "approved" status, frepple can still reschedule the MO in function of material and capacity - # "confirmed", # In the "confirmed" status, frepple sees the MO as frozen and unchangeable - # quoteattr(operation), - # ) - - # Collect work order info - if self.manage_work_orders: - wo_list = i.workorder_ids - else: - wo_list = [] # Collect move info if i.move_raw_ids: @@ -2502,8 +2503,8 @@ def export_manufacturingorders(self): else: mv_list = [] - if not wo_list: - # There are no workorders on the manufacturing order + if not self.manage_work_orders or not getattr(i, "workorder_ids", None): + # There are no workorders on the manufacturing order (or we don't want to see them in frepple) yield '' % ( quoteattr(operation), quoteattr(location), @@ -2543,7 +2544,37 @@ def export_manufacturingorders(self): yield '\n' % ( quoteattr(item["name"]), ) - yield "" + yield "" + # Pick up work center loading of all work orders + loads = {} + for wo in getattr(i, "workorder_ids", []): + # Get remaining duration of the WO + time_left = wo.duration_expected - wo.duration_unit + if wo.is_user_working and wo.time_ids: + # The WO is currently being worked on + for tm in wo.time_ids: + if tm.date_start and not tm.date_end: + time_left -= round( + (now - tm.date_start).total_seconds() / 60 + ) + if ( + time_left > 0 + and wo.workcenter_id.id in self.map_workcenters + and wo.state not in ("done", "cancel") + ): + loads[self.map_workcenters[wo.workcenter_id.id]] = ( + loads.get(self.map_workcenters[wo.workcenter_id.id], 0) + + time_left + ) + if loads: + yield "" + for r, q in loads.items(): + yield '' % ( + q, + quoteattr(r), + ) + yield "" + yield "" else: # Define an operation for the MO yield '' % ( @@ -2554,7 +2585,7 @@ def export_manufacturingorders(self): # Define operations for each WO idx = 10 first_wo = True - for wo in wo_list: + for wo in i.workorder_ids: suboperation = wo.display_name if len(suboperation) > 300: suboperation = suboperation[0:300] @@ -2679,7 +2710,7 @@ def export_manufacturingorders(self): # Create operationplans for each WO, starting with the last one idx = 0 - for wo in reversed(wo_list): + for wo in reversed(i.workorder_ids): idx += 1.0 suboperation = wo.display_name if len(suboperation) > 300: From e77a060f4cf4f91a19f25b55a5df2ac0a698dbc0 Mon Sep 17 00:00:00 2001 From: Johan De Taeye Date: Wed, 6 Nov 2024 09:35:52 +0100 Subject: [PATCH 2/6] bug fix: avoid unintended changes of the name of subcontracting MOs --- frepple/controllers/outbound.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frepple/controllers/outbound.py b/frepple/controllers/outbound.py index 5d03739..23f2edc 100644 --- a/frepple/controllers/outbound.py +++ b/frepple/controllers/outbound.py @@ -2430,6 +2430,7 @@ def export_manufacturingorders(self): ): # Filter out irrelevant manufacturing orders location = self.map_locations.get(i.location_dest_id.id, None) + operation = i.name if not location and i.picking_type_id: # For subcontracting MO we find the warehouse on the operation type operation_type = self.operation_types.get(i.picking_type_id.id, None) @@ -2438,7 +2439,7 @@ def export_manufacturingorders(self): if location: code = self.subcontracting_mo_po_mapping.get(i.id, None) if code: - i.name = code + operation = code item = self.product_product.get(i.product_id.id, None) if not item or not location: continue @@ -2448,7 +2449,6 @@ def export_manufacturingorders(self): # materials. # To reflect this flexibility we need a frepple operation specific # to each manufacturing order. - operation = i.name try: startdate = self.formatDateTime( i.date_start if i.date_start else i.date_planned_start From b2bb60a8cb4cd8316e88fa2c55d60177637f6622 Mon Sep 17 00:00:00 2001 From: Johan De Taeye Date: Wed, 11 Dec 2024 09:35:34 +0100 Subject: [PATCH 3/6] remove suggestion to plan the MO --- frepple/controllers/inbound.py | 1 - 1 file changed, 1 deletion(-) diff --git a/frepple/controllers/inbound.py b/frepple/controllers/inbound.py index 582d529..2b75efe 100644 --- a/frepple/controllers/inbound.py +++ b/frepple/controllers/inbound.py @@ -729,7 +729,6 @@ def run(self): mo_references[elem.get("reference")] = mo mo._create_update_move_finished() # mo.action_confirm() # confirm MO - # mo._plan_workorders() # plan MO # mo.action_assign() # reserve material create = True else: From bebe320874a15d7a70a20e072785c4e8f4851f04 Mon Sep 17 00:00:00 2001 From: Johan De Taeye Date: Wed, 11 Dec 2024 09:40:00 +0100 Subject: [PATCH 4/6] MO material reservation already included in confirmation --- frepple/controllers/inbound.py | 1 - 1 file changed, 1 deletion(-) diff --git a/frepple/controllers/inbound.py b/frepple/controllers/inbound.py index 2b75efe..6554fa0 100644 --- a/frepple/controllers/inbound.py +++ b/frepple/controllers/inbound.py @@ -729,7 +729,6 @@ def run(self): mo_references[elem.get("reference")] = mo mo._create_update_move_finished() # mo.action_confirm() # confirm MO - # mo.action_assign() # reserve material create = True else: # MO update From 40803fcfa23f15768c708612c338c09d8d7439e9 Mon Sep 17 00:00:00 2001 From: Johan De Taeye Date: Tue, 7 Jan 2025 15:32:59 +0100 Subject: [PATCH 5/6] avoid creating MO on nonexisting boms and kit boms --- frepple/controllers/inbound.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/frepple/controllers/inbound.py b/frepple/controllers/inbound.py index 6554fa0..3565b7e 100644 --- a/frepple/controllers/inbound.py +++ b/frepple/controllers/inbound.py @@ -90,6 +90,7 @@ def run(self): stck_picking_type = self.env["stock.picking.type"].with_user( self.actual_user ) + bom_type = self.env["mrp.bom"].with_user(self.actual_user) stck_picking = self.env["stock.picking"].with_user(self.actual_user) stck_move = self.env["stock.move"].with_user(self.actual_user) stck_warehouse = self.env["stock.warehouse"].with_user(self.actual_user) @@ -706,6 +707,19 @@ def run(self): remark = "frePPLe - %s" % remark else: remark = "frePPLe" + bom_id = int(elem.get("operation").rsplit(" ", 1)[1]) + try: + bom = bom_type.search( + [ + ("id", "=", bom_id), + ], + limit=1, + ) + if not bom and bom.type == "phantom": + # Avoid creating MO on a) non-existing BOMs and b) phantom/kit BOMs + continue + except Exception: + pass mo = mfg_order.with_context(context).create( { "product_qty": elem.get("quantity"), @@ -715,9 +729,7 @@ def run(self): "company_id": self.company.id, "product_uom_id": int(uom_id), "picking_type_id": picking.id, - "bom_id": int( - elem.get("operation").rsplit(" ", 1)[1] - ), + "bom_id": bom_id, "qty_producing": 0.00, # TODO no place to store the criticality # elem.get('criticality'), From a5671e25e87ad3c65ef5092c0ddaf6ec6cba8e65 Mon Sep 17 00:00:00 2001 From: wout Date: Wed, 8 Jan 2025 15:46:50 +0100 Subject: [PATCH 6/6] V18 migratie views --- frepple/__manifest__.py | 2 +- frepple/migrations/18.0.0.1/pre-migrate.py | 11 +++++++++++ frepple/views/mrp_routing_workcenter_inherit.xml | 2 +- frepple/views/mrp_secondary_workcenter.xml | 6 +++--- frepple/views/mrp_skill.xml | 8 ++++---- frepple/views/mrp_workcenter_inherit.xml | 4 ++-- frepple/views/mrp_workcenter_skill.xml | 8 ++++---- frepple/views/mrp_workorder_secondary_workcenter.xml | 8 ++++---- frepple/views/product_supplierinfo_inherit.xml | 7 +------ frepple/views/quote_views.xml | 8 ++++---- frepple/views/sale_views.xml | 4 +--- 11 files changed, 36 insertions(+), 32 deletions(-) create mode 100644 frepple/migrations/18.0.0.1/pre-migrate.py diff --git a/frepple/__manifest__.py b/frepple/__manifest__.py index 74e0c44..6eadfda 100644 --- a/frepple/__manifest__.py +++ b/frepple/__manifest__.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- { "name": "frepple", - "version": "18.0.0.0", + "version": "18.0.0.1", "category": "Manufacturing", "summary": "Advanced planning and scheduling", "author": "frePPLe", diff --git a/frepple/migrations/18.0.0.1/pre-migrate.py b/frepple/migrations/18.0.0.1/pre-migrate.py new file mode 100644 index 0000000..d905b58 --- /dev/null +++ b/frepple/migrations/18.0.0.1/pre-migrate.py @@ -0,0 +1,11 @@ +from odoo import SUPERUSER_ID, api + + +def migrate(cr, version): + """Update xml id of roles which have""" + if not version: + return + # Can not change form to list on existing database. So delete the form views before upgrading the module + env = api.Environment(cr, SUPERUSER_ID, {}) + env["ir.ui.view"].search([('arch_fs', 'ilike', 'frepple/'), ('type', '=', 'form')]).unlink() + diff --git a/frepple/views/mrp_routing_workcenter_inherit.xml b/frepple/views/mrp_routing_workcenter_inherit.xml index e736e30..b74cdc4 100644 --- a/frepple/views/mrp_routing_workcenter_inherit.xml +++ b/frepple/views/mrp_routing_workcenter_inherit.xml @@ -32,7 +32,7 @@ - + diff --git a/frepple/views/mrp_secondary_workcenter.xml b/frepple/views/mrp_secondary_workcenter.xml index 9ed03f8..0d48cf0 100644 --- a/frepple/views/mrp_secondary_workcenter.xml +++ b/frepple/views/mrp_secondary_workcenter.xml @@ -4,14 +4,14 @@ mrp.secondary.workcenter.tree mrp.secondary.workcenter -
+ - +
@@ -32,4 +32,4 @@ - \ No newline at end of file + diff --git a/frepple/views/mrp_skill.xml b/frepple/views/mrp_skill.xml index 5546442..6d32ffd 100644 --- a/frepple/views/mrp_skill.xml +++ b/frepple/views/mrp_skill.xml @@ -4,7 +4,7 @@ Skill mrp.skill ir.actions.act_window - tree,form + list,form @@ -26,10 +26,10 @@ MRP Skill List mrp.skill -
+ - +
- \ No newline at end of file + diff --git a/frepple/views/mrp_workcenter_inherit.xml b/frepple/views/mrp_workcenter_inherit.xml index 9c55e83..2d3a283 100644 --- a/frepple/views/mrp_workcenter_inherit.xml +++ b/frepple/views/mrp_workcenter_inherit.xml @@ -32,9 +32,9 @@ - + - \ No newline at end of file + diff --git a/frepple/views/mrp_workcenter_skill.xml b/frepple/views/mrp_workcenter_skill.xml index 54f1836..73945dd 100644 --- a/frepple/views/mrp_workcenter_skill.xml +++ b/frepple/views/mrp_workcenter_skill.xml @@ -4,7 +4,7 @@ Work Center Skill mrp.workcenter.skill ir.actions.act_window - tree,form + list,form @@ -26,11 +26,11 @@ MRP Work Center Skill List mrp.workcenter.skill -
+ - +
- \ No newline at end of file + diff --git a/frepple/views/mrp_workorder_secondary_workcenter.xml b/frepple/views/mrp_workorder_secondary_workcenter.xml index e0a9fd7..1460a56 100644 --- a/frepple/views/mrp_workorder_secondary_workcenter.xml +++ b/frepple/views/mrp_workorder_secondary_workcenter.xml @@ -5,11 +5,11 @@ mrp.workorder.secondary.workcenter.tree mrp.workorder.secondary.workcenter -
+ - +
@@ -18,7 +18,7 @@
- + @@ -27,4 +27,4 @@
- \ No newline at end of file + diff --git a/frepple/views/product_supplierinfo_inherit.xml b/frepple/views/product_supplierinfo_inherit.xml index c0b468b..1869ddc 100644 --- a/frepple/views/product_supplierinfo_inherit.xml +++ b/frepple/views/product_supplierinfo_inherit.xml @@ -1,7 +1,4 @@ - - - - + product.supplierinfo.inherit.tree.view @@ -14,5 +11,3 @@ - - \ No newline at end of file diff --git a/frepple/views/quote_views.xml b/frepple/views/quote_views.xml index 7ae0b3f..ec22d85 100644 --- a/frepple/views/quote_views.xml +++ b/frepple/views/quote_views.xml @@ -89,20 +89,20 @@ frepple_quote.post.view.tree frepple.quote -
+ - +
FrePPLe Quotes frepple.quote - tree,kanban,form + list,kanban,form

Make your first FrePPLe quote! @@ -113,4 +113,4 @@ - \ No newline at end of file + diff --git a/frepple/views/sale_views.xml b/frepple/views/sale_views.xml index 8d405ea..9dc2bd4 100644 --- a/frepple/views/sale_views.xml +++ b/frepple/views/sale_views.xml @@ -1,6 +1,5 @@ - sale.order.form.inherit.sale.product.configurator sale.order @@ -12,5 +11,4 @@ - - \ No newline at end of file +