aboutsummaryrefslogtreecommitdiff
path: root/src/ee/digikey
diff options
context:
space:
mode:
Diffstat (limited to 'src/ee/digikey')
-rw-r--r--src/ee/digikey/bom.py72
1 files changed, 72 insertions, 0 deletions
diff --git a/src/ee/digikey/bom.py b/src/ee/digikey/bom.py
new file mode 100644
index 0000000..36b0143
--- /dev/null
+++ b/src/ee/digikey/bom.py
@@ -0,0 +1,72 @@
+import csv
+from pathlib import Path
+from typing import List, MutableMapping, Optional
+
+from ee.db import ObjDb
+from ee.digikey import DigikeyStore
+from ee.logging import log
+from ee.part import Part, load_db
+from ee.part.bom import load_bom, check_bom, join_refs
+
+__all__ = ["create_bom"]
+
+
+class BomLine(object):
+ def __init__(self, uri, part: Part):
+ self.uri = uri
+ self.part = part
+ self.refs = []
+
+ def add_ref(self, ref):
+ self.refs.append(ref)
+
+ @classmethod
+ def header(cls) -> List[str]:
+ return ["Quantity", "Digi-Key Part Number", "Customer Reference"]
+
+ def to_rows(self) -> List[str]:
+ return [str(len(self.refs)), self.part.get_exactly_one_spn().valueProp, join_refs(self.refs)]
+
+
+def gen_bom(allow_incomplete, bom_parts: ObjDb[Part], supplier_parts: ObjDb[Part]) -> Optional[List[List[str]]]:
+ lines: MutableMapping[str, BomLine] = {}
+
+ uri_idx = supplier_parts.index("uri")
+
+ for part in bom_parts.values:
+ pr_obj = part.get_only_part_reference()
+
+ if allow_incomplete and pr_obj is None:
+ log.debug("Skipping part without part reference: {}".format(part.printable_reference))
+ continue
+ elif pr_obj is None:
+ log.warn("Unresolved part: {}".format(part.printable_reference))
+ return
+
+ part_uri = pr_obj.part_uriProp
+
+ if part_uri not in lines:
+ lines[part_uri] = line = BomLine(part_uri, uri_idx.get_single(part_uri))
+ else:
+ line = lines[part_uri]
+
+ line.add_ref(part.get_exactly_one_schematic_reference().referenceProp)
+
+ return sorted(line.to_rows() for line in lines.values())
+
+
+def create_bom(bom_path: Path, part_files: List[Path], out_path: Path, store_code, allow_incomplete):
+ store = DigikeyStore.from_store_code(store_code)
+
+ bom_parts, supplier_parts = load_bom(bom_path, part_files)
+ check_bom(bom_parts, supplier_parts)
+
+ bom = gen_bom(allow_incomplete, bom_parts, supplier_parts)
+
+ if bom is None:
+ return
+
+ with out_path.open("w") as f:
+ w = csv.writer(f)
+ w.writerow(BomLine.header())
+ w.writerows(bom)