aboutsummaryrefslogtreecommitdiff
path: root/src/ee/order
diff options
context:
space:
mode:
Diffstat (limited to 'src/ee/order')
-rw-r--r--src/ee/order/__init__.py119
-rw-r--r--src/ee/order/templates/order.rst.j260
2 files changed, 117 insertions, 62 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)
diff --git a/src/ee/order/templates/order.rst.j2 b/src/ee/order/templates/order.rst.j2
index ea1dbdf..6616167 100644
--- a/src/ee/order/templates/order.rst.j2
+++ b/src/ee/order/templates/order.rst.j2
@@ -1,9 +1,55 @@
-Messages
-========
-{% for o, messages in messages_by_object %}
-{{ o | subsection }}
-{% for m in messages %}
-* {{ m.text }}
-{% endfor %}
+Order
+=====
+
+Has unresolved parts: {{ "yes" if has_unresolved_parts else "no" }}.
+
+Parts for Order
+===============
+{% for op in order_parts %}
+{{ op.ref | subsection }}
+{% if op.available_from|length == 0 %}
+Part not resolved.
+{% elif op.available_from|length == 1 %}
+{%- set from=op.available_from[0] %}
+{%- set part=from[1] %}
+{%- set pn=part|first_pn %}
+{%- set spn=part|first_spn %}
+Selected supplier: {{ from[0] }}{{ (", pn: " + pn.valueProp) if pn else "" }}{{ (", spn: " + spn.valueProp) if spn else "" }}.
+Part: part-{{pn.valueProp}}_
+{% else %}
+MANY
+{% endif %}
+{%- endfor %}
+
+Part details
+============
+{% for supplier, parts in parts_by_supplier.items() %}
+{{ ("From " + supplier) | subsection }}
+{% for part in parts %}
+{%- set pn=part|first_pn %}
+{%- set spn=part|first_spn %}
+{%- set title=pn.valueProp if pn else (spn.valueProp if spn else "???") %}
+{%- set links=part.linksProp.link %}
+.. _part-{{title}}:
+
+{{ title|subsubsection }}
+{#-
+
+"Facts"
+.......
+
+{% for f in part.facts.fact %}
+f={{f}}
{% endfor %}
+#}
+
+"Media"
+.......
+{% for l in links %}
+{%- if l.relationProp == "http://purl.org/ee/link-relation#documentation" %}
+* `{{ l.title }} <{{ l.url }}>`__
+{%- endif %}
+{%- endfor %}
+{% endfor %}
+{% endfor %}