From 5c8e01111d92784d8346725262535db42f064e51 Mon Sep 17 00:00:00 2001 From: Hicham Lahlou Date: Mon, 12 Feb 2024 15:24:27 +0100 Subject: [PATCH 1/2] fix uom id that should be the product uom, not the category reference uom --- frepple/controllers/outbound.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/frepple/controllers/outbound.py b/frepple/controllers/outbound.py index e5eed10c..c7cdd2e1 100644 --- a/frepple/controllers/outbound.py +++ b/frepple/controllers/outbound.py @@ -334,7 +334,6 @@ def load_uom(self): unit of measure of the uom dimension. """ self.uom = {} - self.uom_categories = {} for i in self.generator.getData( "uom.uom", # We also need to load INactive UOMs, because there still might be records @@ -342,8 +341,6 @@ def load_uom(self): search=["|", ("active", "=", 1), ("active", "=", 0)], fields=["factor", "uom_type", "category_id", "name"], ): - if i["uom_type"] == "reference": - self.uom_categories[i["category_id"][0]] = i["id"] self.uom[i["id"]] = { "factor": i["factor"], "category": i["category_id"][0], @@ -1076,7 +1073,7 @@ def export_items(self): # max(0, tmpl["standard_price"]) or 0) # Option 2: Map the "cost" to frepple / self.convert_qty_uom(1.0, tmpl["uom_id"], i["product_tmpl_id"][0]), quoteattr(tmpl["categ_id"][1]) if tmpl["categ_id"] else '""', - self.uom_categories[self.uom[tmpl["uom_id"][0]]["category"]], + tmpl["uom_id"][0], i["id"], ) # Export suppliers for the item, if the item is allowed to be purchased From 2911dfaff021aea0e6bdeeddedef0b02b9eedfe1 Mon Sep 17 00:00:00 2001 From: Hicham Lahlou Date: Mon, 12 Feb 2024 16:17:40 +0100 Subject: [PATCH 2/2] it's black --- frepple/controllers/inbound.py | 22 +- frepple/controllers/outbound.py | 343 +++++++++++++++++++------------- 2 files changed, 213 insertions(+), 152 deletions(-) diff --git a/frepple/controllers/inbound.py b/frepple/controllers/inbound.py index fcc9e164..0015d9b1 100644 --- a/frepple/controllers/inbound.py +++ b/frepple/controllers/inbound.py @@ -345,17 +345,17 @@ def run(self): if not hasattr(self, "stock_picking_dict"): self.stock_picking_dict = {} if not self.stock_picking_dict.get((origin, destination)): - self.stock_picking_dict[ - (origin, destination) - ] = stck_picking.create( - { - "picking_type_id": picking_type_id, - "scheduled_date": date_shipping, - "location_id": location_id["id"], - "location_dest_id": location_dest_id["id"], - "move_type": "direct", - "origin": "frePPLe", - } + self.stock_picking_dict[(origin, destination)] = ( + stck_picking.create( + { + "picking_type_id": picking_type_id, + "scheduled_date": date_shipping, + "location_id": location_id["id"], + "location_dest_id": location_dest_id["id"], + "move_type": "direct", + "origin": "frePPLe", + } + ) ) sp = self.stock_picking_dict.get((origin, destination)) if not hasattr(self, "sm_dict"): diff --git a/frepple/controllers/outbound.py b/frepple/controllers/outbound.py index c7cdd2e1..367730a8 100644 --- a/frepple/controllers/outbound.py +++ b/frepple/controllers/outbound.py @@ -370,19 +370,19 @@ def load_operation_types(self): "name": i["name"], "code": i["code"], "sequence_code": i["sequence_code"], - "default_location_src_id": self.map_locations.get( - i["default_location_src_id"][0], None - ) - if i["default_location_src_id"] - else None, - "default_location_dest_id": self.map_locations.get( - i["default_location_dest_id"][0], None - ) - if i["default_location_dest_id"] - else None, - "warehouse_id": self.warehouses[i["warehouse_id"][0]] - if i["warehouse_id"] - else None, + "default_location_src_id": ( + self.map_locations.get(i["default_location_src_id"][0], None) + if i["default_location_src_id"] + else None + ), + "default_location_dest_id": ( + self.map_locations.get(i["default_location_dest_id"][0], None) + if i["default_location_dest_id"] + else None + ), + "warehouse_id": ( + self.warehouses[i["warehouse_id"][0]] if i["warehouse_id"] else None + ), } def convert_qty_uom(self, qty, uom_id, product_template_id=None): @@ -637,32 +637,42 @@ def export_calendar(self): if j.get("week_type", False) == False: # ONE-WEEK CALENDAR yield '\n' % ( - self.formatDateTime(j["date_from"], cal_tz[i]) - if not j["attendance"] - else ( - j["date_from"].strftime("%Y-%m-%dT00:00:00") - if j["date_from"] - else "2020-01-01T00:00:00" + ( + self.formatDateTime(j["date_from"], cal_tz[i]) + if not j["attendance"] + else ( + j["date_from"].strftime("%Y-%m-%dT00:00:00") + if j["date_from"] + else "2020-01-01T00:00:00" + ) ), - self.formatDateTime(j["date_to"], cal_tz[i]) - if not j["attendance"] - else ( - j["date_to"].strftime("%Y-%m-%dT00:00:00") - if j["date_to"] - else "2030-12-31T00:00:00" + ( + self.formatDateTime(j["date_to"], cal_tz[i]) + if not j["attendance"] + else ( + j["date_to"].strftime("%Y-%m-%dT00:00:00") + if j["date_to"] + else "2030-12-31T00:00:00" + ) ), "1" if j["attendance"] else "0", - (2 ** ((int(j["dayofweek"]) + 1) % 7)) - if "dayofweek" in j - else (2**7) - 1, + ( + (2 ** ((int(j["dayofweek"]) + 1) % 7)) + if "dayofweek" in j + else (2**7) - 1 + ), priority_attendance if j["attendance"] else priority_leave, # In odoo, monday = 0. In frePPLe, sunday = 0. - ("PT%dM" % round(j["hour_from"] * 60)) - if "hour_from" in j - else "PT0M", - ("PT%dM" % round(j["hour_to"] * 60)) - if "hour_to" in j - else "PT1440M", + ( + ("PT%dM" % round(j["hour_from"] * 60)) + if "hour_from" in j + else "PT0M" + ), + ( + ("PT%dM" % round(j["hour_to"] * 60)) + if "hour_to" in j + else "PT1440M" + ), ) if j["attendance"]: priority_attendance += 1 @@ -683,17 +693,23 @@ def export_calendar(self): cal_tz[i], ), "1", - (2 ** ((int(j["dayofweek"]) + 1) % 7)) - if "dayofweek" in j - else (2**7) - 1, + ( + (2 ** ((int(j["dayofweek"]) + 1) % 7)) + if "dayofweek" in j + else (2**7) - 1 + ), priority_attendance, # In odoo, monday = 0. In frePPLe, sunday = 0. - ("PT%dM" % round(j["hour_from"] * 60)) - if "hour_from" in j - else "PT0M", - ("PT%dM" % round(j["hour_to"] * 60)) - if "hour_to" in j - else "PT1440M", + ( + ("PT%dM" % round(j["hour_from"] * 60)) + if "hour_from" in j + else "PT0M" + ), + ( + ("PT%dM" % round(j["hour_to"] * 60)) + if "hour_to" in j + else "PT1440M" + ), ) priority_attendance += 1 dow = t.weekday() @@ -1155,13 +1171,18 @@ def export_items(self): v["batching_window"] or 0, v["min_qty"], max(0, v["price"]), - ' effective_end="%sT00:00:00"' - % v["date_end"].strftime("%Y-%m-%d") - if v["date_end"] - else "", - ' effective_start="%sT00:00:00"' % k[1].strftime("%Y-%m-%d") - if k[1] - else "", + ( + ' effective_end="%sT00:00:00"' + % v["date_end"].strftime("%Y-%m-%d") + if v["date_end"] + else "" + ), + ( + ' effective_start="%sT00:00:00"' + % k[1].strftime("%Y-%m-%d") + if k[1] + else "" + ), quoteattr(k[0]), ) yield "\n" @@ -1300,9 +1321,11 @@ def export_boms(self): if subcontractor: yield '\n' "\n" % ( quoteattr(operation), - ("description=%s " % quoteattr(i["code"])) - if i["code"] - else "", + ( + ("description=%s " % quoteattr(i["code"])) + if i["code"] + else "" + ), quoteattr(subcontractor["name"]), subcontractor.get("delay", 0), self.po_lead, @@ -1318,12 +1341,16 @@ def export_boms(self): yield '\n' "\n" % ( quoteattr(operation), - ("description=%s " % quoteattr(i["code"])) - if i["code"] - else "", - self.convert_float_time(duration_per) - if duration_per and duration_per > 0 - else "P0D", + ( + ("description=%s " % quoteattr(i["code"])) + if i["code"] + else "" + ), + ( + self.convert_float_time(duration_per) + if duration_per and duration_per > 0 + else "P0D" + ), self.manufacturing_lead, 100 + (i["sequence"] or 1), quoteattr(product_buf["name"]), @@ -1411,9 +1438,11 @@ def export_boms(self): if not product: continue yield '\n' % ( - "flow_fixed_end" - if j["subproduct_type"] == "fixed" - else "flow_end", + ( + "flow_fixed_end" + if j["subproduct_type"] == "fixed" + else "flow_end" + ), self.convert_qty_uom( j["product_qty"], j["product_uom"], @@ -1442,9 +1471,11 @@ def export_boms(self): quoteattr( self.map_workcenters[j["workcenter_id"][0]] ), - ("" % quoteattr(j["skill"][1])) - if j["skill"] - else "", + ( + ("" % quoteattr(j["skill"][1])) + if j["skill"] + else "" + ), ) # create a load for secondary workcenters # prepare the secondary workcenter xml string upfront @@ -1454,11 +1485,13 @@ def export_boms(self): sw_id ] yield '%s' % ( - 1 - if not secondary_workcenter["duration"] - or j["time_cycle"] == 0 - else secondary_workcenter["duration"] - / j["time_cycle"], + ( + 1 + if not secondary_workcenter["duration"] + or j["time_cycle"] == 0 + else secondary_workcenter["duration"] + / j["time_cycle"] + ), quoteattr(secondary_workcenter["search_mode"]), quoteattr( self.map_workcenters[ @@ -1466,13 +1499,15 @@ def export_boms(self): ] ), ( - "" - % quoteattr( - secondary_workcenter["skill"][1] + ( + "" + % quoteattr( + secondary_workcenter["skill"][1] + ) ) - ) - if secondary_workcenter["skill"] - else "", + if secondary_workcenter["skill"] + else "" + ), ) if exists: @@ -1484,9 +1519,11 @@ def export_boms(self): # yield '\n' % ( quoteattr(operation), - ("description=%s " % quoteattr(i["code"])) - if i["code"] - else "", + ( + ("description=%s " % quoteattr(i["code"])) + if i["code"] + else "" + ), self.manufacturing_lead, 100 + (i["sequence"] or 1), quoteattr(product_buf["name"]), @@ -1547,9 +1584,11 @@ def export_boms(self): fl[ ( j["product_id"][0], - j["operation_id"][0] - if j["operation_id"] - else None, + ( + j["operation_id"][0] + if j["operation_id"] + else None + ), ) ]["qty"] += qty else: @@ -1557,9 +1596,11 @@ def export_boms(self): fl[ ( j["product_id"][0], - j["operation_id"][0] - if j["operation_id"] - else None, + ( + j["operation_id"][0] + if j["operation_id"] + else None + ), ) ] = j @@ -1600,11 +1641,13 @@ def export_boms(self): secondary_workcenter_str += ( '%s' % ( - 1 - if not secondary_workcenter["duration"] - or step["time_cycle"] == 0 - else secondary_workcenter["duration"] - / step["time_cycle"], + ( + 1 + if not secondary_workcenter["duration"] + or step["time_cycle"] == 0 + else secondary_workcenter["duration"] + / step["time_cycle"] + ), quoteattr(secondary_workcenter["search_mode"]), quoteattr( self.map_workcenters[ @@ -1612,34 +1655,42 @@ def export_boms(self): ] ), ( - "" - % quoteattr( - secondary_workcenter["skill"][1] + ( + "" + % quoteattr( + secondary_workcenter["skill"][1] + ) ) - ) - if secondary_workcenter["skill"] - else "", + if secondary_workcenter["skill"] + else "" + ), ) ) yield "" '\n' "\n" '%s%s\n' % ( quoteattr(name), - ("description=%s " % quoteattr(i["code"])) - if i["code"] - else "", + ( + ("description=%s " % quoteattr(i["code"])) + if i["code"] + else "" + ), counter * 10, - self.convert_float_time(step["time_cycle"] / 1440.0) - if step["time_cycle"] and step["time_cycle"] > 0 - else "P0D", + ( + self.convert_float_time(step["time_cycle"] / 1440.0) + if step["time_cycle"] and step["time_cycle"] > 0 + else "P0D" + ), quoteattr(location), 1, quoteattr(step["search_mode"]), quoteattr( self.map_workcenters[step["workcenter_id"][0]] ), - ("" % quoteattr(step["skill"][1])) - if step["skill"] - else "", + ( + ("" % quoteattr(step["skill"][1])) + if step["skill"] + else "" + ), secondary_workcenter_str, ) first_flow = True @@ -1835,9 +1886,11 @@ def getReservedQuantity(stock_move_id): ) % ( quoteattr(sol_name), quoteattr(batch), - qty - reserved_quantity - if qty - reserved_quantity > 0 - else qty, + ( + qty - reserved_quantity + if qty - reserved_quantity > 0 + else qty + ), due, priority, j["picking_policy"] == "one" and qty or 0.0, @@ -2084,9 +2137,9 @@ def export_purchaseorders(self): fields=["production_id"], ): if k["production_id"]: - self.subcontracting_mo_po_mapping[ - k["production_id"][0] - ] = po_line_reference + self.subcontracting_mo_po_mapping[k["production_id"][0]] = ( + po_line_reference + ) continue item = self.product_product.get(i["product_id"][0], None) if not item: @@ -2141,24 +2194,26 @@ def export_manufacturingorders(self): search=[("state", "in", ["progress", "confirmed", "to_close"])], # Option 2: Also import draft manufacturing order from odoo (to avoid that frepple reproposes it another time) # search=[("state", "in", ["draft", "progress", "confirmed", "to_close"])], - fields=[ - "bom_id", - "date_start", - "date_planned_start", - "date_planned_finished", - "name", - "state", - "qty_producing", - "product_qty", - "product_uom_id", - "location_dest_id", - "product_id", - "move_raw_ids", - "picking_type_id", - ] - + ["workorder_ids"] - if self.manage_work_orders - else [], + fields=( + [ + "bom_id", + "date_start", + "date_planned_start", + "date_planned_finished", + "name", + "state", + "qty_producing", + "product_qty", + "product_uom_id", + "location_dest_id", + "product_id", + "move_raw_ids", + "picking_type_id", + ] + + ["workorder_ids"] + if self.manage_work_orders + else [] + ), ): # Filter out irrelevant manufacturing orders location = self.map_locations.get(i["location_dest_id"][0], None) @@ -2329,10 +2384,9 @@ def export_manufacturingorders(self): self.product_product[mv["product_id"][0]]["template"], ) if qty_flow > 0: - operation_materials[ - consumed_item["name"] - ] = operation_materials.get(consumed_item["name"], 0) + ( - -qty_flow / qty + operation_materials[consumed_item["name"]] = ( + operation_materials.get(consumed_item["name"], 0) + + (-qty_flow / qty) ) for key in operation_materials: yield '\n' % ( @@ -2450,9 +2504,12 @@ def export_manufacturingorders(self): != wo["workcenter_id"][0] ): yield '' % ( - secondary["duration"] / wo["duration_expected"] - if secondary["duration"] and wo["duration_expected"] - else 1, + ( + secondary["duration"] / wo["duration_expected"] + if secondary["duration"] + and wo["duration_expected"] + else 1 + ), quoteattr( self.map_workcenters[ secondary["workcenter_id"][0] @@ -2490,11 +2547,15 @@ def export_manufacturingorders(self): dt = now else: dt = max( - wo["date_start"] - if wo["date_start"] - else wo["date_planned_start"] - if wo["date_planned_start"] - else i["date_planned_start"], + ( + wo["date_start"] + if wo["date_start"] + else ( + wo["date_planned_start"] + if wo["date_planned_start"] + else i["date_planned_start"] + ) + ), now, ) wo_date = ' start="%s"' % self.formatDateTime(dt)