from functools import total_ordering from pathlib import Path from typing import List, Tuple from ee import EeException from ee.part import PartDb, load_db, save_db from ee.xml import types, bom_file_utils __all__ = ["create_order"] @total_ordering class PartInfo(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]] = [] 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 create_order(schematic_path: Path, out_path: Path, part_db_dirs: List[Path], fail_on_missing_parts: bool): sch_db = load_db(schematic_path) dbs = [(path.parent.name, load_db(path)) for path in part_db_dirs] out_parts = PartDb() infos = [PartInfo(sch) for sch in sch_db.iterparts()] for info in infos: print("Resolving {}".format(info.ref)) sch_part_numbers = info.part.referencesProp.part_number sch_supplier_part_numbers: List[types.SupplierPartNumber] = info.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 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: print("Resolved {} to {}".format(info.ref, info.available_from)) warnings = [] has_missing_parts = False for info in infos: if len(info.available_from) == 0: has_missing_parts = True warnings.append("Could not find {} in any database, part numbers: {}". format(info.ref, ", ".join([p.value for p in bom_file_utils.part_numbers(info.part)]))) for w in sorted(warnings): print(w) if has_missing_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: continue supplier, supplier_part = info.available_from[0] references = types.ReferencesList(schematic_reference=info.part.referencesProp.schematic_reference) part = types.Part(uri=supplier_part.uri, references=references) out_parts.add_entry(part, True) print("Saving {} work parts".format(out_parts.size())) save_db(out_path, out_parts)