diff options
Diffstat (limited to 'src/ee/digikey')
-rw-r--r-- | src/ee/digikey/bom.py | 72 |
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) |