91 lines
2.8 KiB
Python
91 lines
2.8 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
from collections import namedtuple
|
|
from dataclasses import dataclass
|
|
from enum import Enum
|
|
from typing import List, Optional, Union
|
|
|
|
import tabulate as tabulate_module
|
|
|
|
from wireviz.wv_utils import html_line_breaks
|
|
|
|
BOM_HASH_FIELDS = "description qty_unit amount partnumbers"
|
|
|
|
|
|
BomEntry = namedtuple("BomEntry", "category qty designators")
|
|
BomHash = namedtuple("BomHash", BOM_HASH_FIELDS)
|
|
BomHashList = namedtuple("BomHashList", BOM_HASH_FIELDS)
|
|
PartNumberInfo = namedtuple("PartNumberInfo", "pn manufacturer mpn supplier spn")
|
|
|
|
|
|
BomCategory = Enum(
|
|
"BomEntry", "CONNECTOR CABLE WIRE ADDITIONAL_INSIDE ADDITIONAL_OUTSIDE"
|
|
)
|
|
QtyMultiplierConnector = Enum(
|
|
"QtyMultiplierConnector", "PINCOUNT POPULATED CONNECTIONS"
|
|
)
|
|
QtyMultiplierCable = Enum(
|
|
"QtyMultiplierCable", "WIRECOUNT TERMINATION LENGTH TOTAL_LENGTH"
|
|
)
|
|
|
|
PART_NUMBER_HEADERS = PartNumberInfo(
|
|
pn="P/N", manufacturer=None, mpn="MPN", supplier=None, spn="SPN"
|
|
)
|
|
|
|
|
|
def partnumbers_to_list(partnumbers: PartNumberInfo) -> List[str]:
|
|
cell_contents = [
|
|
pn_info_string(PART_NUMBER_HEADERS.pn, None, partnumbers.pn),
|
|
pn_info_string(
|
|
PART_NUMBER_HEADERS.mpn, partnumbers.manufacturer, partnumbers.mpn
|
|
),
|
|
pn_info_string(PART_NUMBER_HEADERS.spn, partnumbers.supplier, partnumbers.spn),
|
|
]
|
|
if any(cell_contents):
|
|
return [html_line_breaks(cell) for cell in cell_contents]
|
|
else:
|
|
return None
|
|
|
|
|
|
def pn_info_string(
|
|
header: str, name: Optional[str], number: Optional[str]
|
|
) -> Optional[str]:
|
|
"""Return the company name and/or the part number in one single string or None otherwise."""
|
|
number = str(number).strip() if number is not None else ""
|
|
if name or number:
|
|
return f'{name if name else header}{": " + number if number else ""}'
|
|
else:
|
|
return None
|
|
|
|
|
|
def print_bom_debug(bom):
|
|
headers = "# qty unit description amount unit designators category".split(" ")
|
|
rows = []
|
|
rows.append(headers)
|
|
# fill rows
|
|
for hash, entry in bom.items():
|
|
cells = [
|
|
0,
|
|
entry["qty"],
|
|
hash.qty_unit,
|
|
hash.description,
|
|
hash.amount.number if hash.amount else None,
|
|
hash.amount.unit if hash.amount else None,
|
|
", ".join(sorted(entry["designators"])),
|
|
entry["category"],
|
|
]
|
|
rows.append(cells)
|
|
# remove empty columns
|
|
transposed = list(map(list, zip(*rows)))
|
|
transposed = [
|
|
column
|
|
for column in transposed
|
|
if any([cell is not None for cell in column[1:]])
|
|
# ^ ignore header cell in check
|
|
]
|
|
rows = list(map(list, zip(*transposed)))
|
|
# output
|
|
print()
|
|
print(tabulate_module.tabulate(rows, headers="firstrow"))
|
|
print()
|