aboutsummaryrefslogtreecommitdiff
path: root/src/ee/order/__init__.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/ee/order/__init__.py')
-rw-r--r--src/ee/order/__init__.py119
1 files changed, 64 insertions, 55 deletions
diff --git a/src/ee/order/__init__.py b/src/ee/order/__init__.py
index 1652f24..a384cb7 100644
--- a/src/ee/order/__init__.py
+++ b/src/ee/order/__init__.py
@@ -1,9 +1,9 @@
-from functools import total_ordering
-from itertools import groupby
+import os.path
from pathlib import Path
from typing import List, Tuple
from ee import EeException
+from ee.db import ObjDb
from ee.part import PartDb, load_db, save_db
from ee.project import Project, report
from ee.xml import types, bom_file_utils
@@ -11,96 +11,105 @@ from ee.xml import types, bom_file_utils
__all__ = ["create_order"]
-@total_ordering
-class PartInfo(object):
+class OrderPart(object):
def __init__(self, part: types.Part):
self.part = part
self.ref = next((ref.referenceProp for ref in bom_file_utils.schematic_references(part)), None)
- self.pn = next((p.valueProp for p in bom_file_utils.part_numbers(part)), None)
self.available_from: List[Tuple[str, types.Part]] = []
+ self.selected_supplier_and_part = None
rl = part.referencesProp = part.referencesProp or types.ReferencesList() # type: types.ReferencesList
rl.schematic_referenceProp = rl.schematic_referenceProp or []
rl.part_numberProp = rl.part_numberProp or []
rl.supplier_part_numberProp = rl.supplier_part_numberProp or []
- def __lt__(self, other: "PartInfo"):
- return self.ref == other.ref
+
+def make_report(out_file, order_parts: ObjDb[OrderPart], has_unresolved_parts):
+ parts_by_supplier = {}
+
+ for supplier, order_parts in order_parts.index("selected_part").items():
+ parts = {}
+ for op in order_parts:
+ p = op.selected_supplier_and_part[1]
+ parts[p.uriProp] = p
+ parts_by_supplier[supplier] = parts.values()
+
+ kwargs = {
+ "order_parts": order_parts,
+ "parts_by_supplier": parts_by_supplier,
+ "has_unresolved_parts": has_unresolved_parts,
+ }
+ report.save_report("ee.order", "order.rst.j2", out_file, **kwargs)
def create_order(project: Project, schematic_path: Path, out_path: Path, part_db_dirs: List[Path],
fail_on_missing_parts: bool):
- messages = []
-
sch_db = load_db(schematic_path)
dbs = [(path.parent.name, load_db(path)) for path in part_db_dirs]
- out_parts = PartDb()
+ def supplier_index(op: OrderPart):
+ return [spn.supplierProp for spn in bom_file_utils.supplier_part_numbers(op.part)]
+
+ def selected_part_index(op: OrderPart):
+ return [op.selected_supplier_and_part[0]] if op.selected_supplier_and_part else None
+
+ def available_from_index(op: OrderPart):
+ return set([s for s, s_part in op.available_from])
- infos = [PartInfo(sch) for sch in sch_db.iterparts()]
+ def supplier_part_index(op: OrderPart):
+ return set([s_part.uriProp for s, s_part in op.available_from])
- for info in infos:
- sch_part_numbers = info.part.referencesProp.part_number
- sch_supplier_part_numbers: List[types.SupplierPartNumber] = info.part.referencesProp.supplier_part_number
+ def pn_index(op: OrderPart):
+ return [pn.value for pn in bom_file_utils.part_numbers(op.part)]
+
+ order_parts: ObjDb[OrderPart] = ObjDb[OrderPart]()
+ for sch_part in sch_db.iterparts():
+ order_parts.add(OrderPart(sch_part))
+
+ for order_part in order_parts:
+ sch_part_numbers = order_part.part.referencesProp.part_number
+ sch_supplier_part_numbers: List[types.SupplierPartNumber] = order_part.part.referencesProp.supplier_part_number
for supplier, db in dbs:
for supplier_part in db.iterparts(sort=True):
- found = None
for sch_pn in sch_part_numbers:
for pn in bom_file_utils.part_numbers(supplier_part):
if sch_pn.valueProp == pn.valueProp:
- found = supplier_part
- break
- if found:
- break
-
- if found:
- info.available_from.append((supplier, found))
- break
+ order_part.available_from.append((supplier, supplier_part))
- found = None
for sch_spn in sch_supplier_part_numbers:
for spn in bom_file_utils.supplier_part_numbers(supplier_part):
if sch_spn.valueProp == spn.valueProp and sch_spn.supplierProp == spn.supplierProp:
- found = supplier_part
- break
- if found:
- break
-
- if found:
- info.available_from.append((supplier, found))
- break
-
- for info in infos:
- if len(info.available_from):
- strings = ["{} from {}".format(part.uri, s) for s, part in info.available_from]
- text = "Resolved {} to {}".format(info.ref, ", ".join(strings))
- messages.append(report.Message(object=info.ref, text=text))
-
- has_missing_parts = False
- for info in infos:
- if len(info.available_from) == 0:
- has_missing_parts = True
- text = "Could not find {} in any database, part numbers: {}". \
- format(info.ref, ", ".join([p.value for p in bom_file_utils.part_numbers(info.part)]))
- messages.append(report.Message(object=info.ref, text=text))
-
- if has_missing_parts and fail_on_missing_parts:
+ order_part.available_from.append((supplier, supplier_part))
+
+ has_unresolved_parts = False
+ for order_part in order_parts:
+ if len(order_part.available_from) == 0:
+ has_unresolved_parts = True
+ elif len(order_part.available_from) == 1:
+ order_part.selected_supplier_and_part = order_part.available_from[0]
+ else:
+ raise EeException("unimplemented: part available from multiple suppliers")
+
+ if has_unresolved_parts and fail_on_missing_parts:
raise EeException("The order has parts that can't be found from any supplier")
- for info in infos:
- if len(info.available_from) == 0:
+ order_parts.add_index("selected_part", selected_part_index)
+
+ out_file = project.report_dir / (os.path.splitext(out_path.name)[0] + ".rst")
+ make_report(out_file, order_parts, has_unresolved_parts)
+
+ out_parts = PartDb()
+ for order_part in order_parts:
+ if not order_part.selected_supplier_and_part:
continue
- supplier, supplier_part = info.available_from[0]
+ supplier, supplier_part = order_part.selected_supplier_and_part
- references = types.ReferencesList(schematic_reference=info.part.referencesProp.schematic_reference)
+ references = types.ReferencesList(schematic_reference=order_part.part.referencesProp.schematic_reference)
part = types.Part(uri=supplier_part.uri, references=references)
out_parts.add_entry(part, True)
save_db(out_path, out_parts)
- # messages
- kwargs = {"messages_by_object": groupby(messages, lambda m: m.object)}
- report.save_report("ee.order", "order.rst.j2", project.report_dir / "order.rst", **kwargs)