Restructure and simplify BOM creation

This commit is contained in:
Daniel Rojas 2020-06-14 17:46:21 +02:00
parent 93be0cba49
commit d97d1e1f41

View File

@ -254,125 +254,52 @@ class Harness:
d.render(filename=filename, directory=directory, view=view, cleanup=cleanup) d.render(filename=filename, directory=directory, view=view, cleanup=cleanup)
d.save(filename='{}.gv'.format(filename), directory=directory) d.save(filename='{}.gv'.format(filename), directory=directory)
# bom output # bom output
# connectors bom_list = self.bom_list()
_con = self.bom_connectors() with open('{}.bom.tsv'.format(filename),'w') as file:
header_con = ['Type','Subtype','Pin count','Qty','Designators'] file.write(tuplelist2tsv(bom_list))
bom_con = tuplelist2tsv(_con, header_con)
# cables
_cbl, _cut = self.bom_cables_and_cutlist()
header_cbl = ['Gauge','Gauge unit','Wire count','Shield','Total length','Designators']
bom_cbl = tuplelist2tsv(_cbl, header_cbl)
# cutlist
header_cut = ['Gauge','Gauge unit','Wire count','Shield','Length','Qty','Designators']
bom_cut = tuplelist2tsv(_cut, header_cut)
if gen_bom:
with open('{}.connectors.bom.tsv'.format(filename),'w') as file:
file.write(bom_con)
with open('{}.cables.bom.tsv'.format(filename),'w') as file:
file.write(bom_cbl)
with open('{}.cutlist.bom.tsv'.format(filename),'w') as file:
file.write(bom_cut)
# HTML documentation
with open('{}.html'.format(filename),'w') as file:
file.write('<html><body>')
file.write('<h1>Diagram</h1>')
with open('{}.svg'.format(filename),'r') as svg:
for l in svg:
file.write(l)
file.write('<h1>BOM</h1>') def bom(self):
listy = flatten2d(self.bom_connectors())
file.write('<h2>Connectors</h2>')
file.write('<table border="1">')
file.write('<tr>')
for item in header_con:
file.write('<th>{}</th>'.format(item))
file.write('</tr>')
for row in listy:
file.write('<tr>')
for item in row:
file.write('<td>{}</td>'.format(item))
file.write('</tr>')
file.write('</table>')
bom_cbl, bom_cut = self.bom_cables_and_cutlist()
file.write('<h2>Cables</h2>')
listy = flatten2d(bom_cbl)
file.write('<table border="1">')
file.write('<tr>')
for item in header_cbl:
file.write('<th>{}</th>'.format(item))
file.write('</tr>')
for row in listy:
file.write('<tr>')
for item in row:
file.write('<td>{}</td>'.format(item))
file.write('</tr>')
file.write('</table>')
file.write('<h2>Cutlist</h2>')
listy = flatten2d(bom_cut)
file.write('<table border="1">')
file.write('<tr>')
for item in header_cut:
file.write('<th>{}</th>'.format(item))
file.write('</tr>')
for row in listy:
file.write('<tr>')
for item in row:
file.write('<td>{}</td>'.format(item))
file.write('</tr>')
file.write('</table>')
file.write('</body></html>')
def bom_connectors(self):
bom = [] bom = []
types = Counter([v.type for v in self.connectors.values()]) # connectors
for type in types.keys(): types = Counter([(v.type, v.subtype, v.pincount) for v in self.connectors.values()])
subtypes = Counter([v.subtype for v in self.connectors.values() if v.type == type]) for type in types:
for subtype in subtypes.keys(): items = {k: v for k, v in self.connectors.items() if (v.type, v.subtype, v.pincount) == type}
pincounts = Counter([v.pincount for v in self.connectors.values() if v.type == type and designators = list(items.keys())
v.subtype == subtype]) shared = next(iter(items.values()))
for pincount in pincounts.keys(): name = '{}, {}, {} pins'.format(shared.type, shared.subtype, shared.pincount)
designators = [k for k,v in self.connectors.items() if v.type == type and item = {'item': name, 'qty': len(designators), 'unit': '', 'designators': designators}
v.subtype == subtype and bom.append(item)
v.pincount == pincount] # cables
qty = pincounts[pincount] # TODO: handle bundles separately
bom.append([type, subtype, pincount, qty, designators]) types = Counter([(v.gauge, v.gauge_unit, v.wirecount, v.shield) for v in self.cables.values()])
for type in types:
# stuff = [(k, v.length) for k,v in self.cables.items() if (v.gauge, v.gauge_unit, v.wirecount, v.shield) == type]
items = {k: v for k, v in self.cables.items() if (v.gauge, v.gauge_unit, v.wirecount, v.shield) == type}
designators = list(items.keys())
shared = next(iter(items.values()))
total_length = sum(i.length for i in items.values())
name = 'Cable {} x{}'.format(shared.wirecount,
' {} {}'.format(shared.gauge, shared.gauge_unit) if shared.gauge else '',
' shielded' if shared.shield else '')
item = {'item': name, 'qty': round(total_length, 3), 'unit': 'm', 'designators': designators}
bom.append(item)
return bom return bom
def bom_cables_and_cutlist(self): def bom_list(self):
bom_cbl = [] bom = self.bom()
bom_cut = [] # get all keys (https://stackoverflow.com/a/11399555)
gauges_and_units = Counter([v.gauge_and_unit for v in self.cables.values()]) # and remove duplicates (https://stackoverflow.com/a/7961425)
for gauge_and_unit in gauges_and_units.keys(): # keys = list(dict.fromkeys([k for d in bom for k in d.keys()]))
wirecounts_and_shields = Counter([v.wirecount_and_shield for v in self.cables.values() if v.gauge_and_unit == gauge_and_unit]) keys = ['item', 'qty', 'unit', 'designators']
for wirecount_and_shield in wirecounts_and_shields.keys(): bom_list = []
gauge = gauge_and_unit[0] bom_list.append(k.capitalize() for k in keys)
gauge_unit = gauge_and_unit[1] for item in bom:
wirecount = wirecount_and_shield[0] item_list = [item.get(key, '') for key in keys] # fill missing values with blanks
shield = wirecount_and_shield[1] for i, subitem in enumerate(item_list):
all_lengths = [v.length for v in self.cables.values() if v.gauge_and_unit == gauge_and_unit and if isinstance(subitem, List): # convert any lists into comma separated strings
v.wirecount_and_shield == wirecount_and_shield] item_list[i] = ', '.join(subitem)
len_total = round(sum(all_lengths),3) # rounding to avoid float problems bom_list.append(item_list)
qty = len(all_lengths) # number of cables that will be cut from this bom item (may be different lengths) return bom_list
designators = [k for k,v in self.cables.items() if v.gauge_and_unit == gauge_and_unit and
v.wirecount_and_shield == wirecount_and_shield]
bom_cbl.append([gauge, gauge_unit, wirecount, shield, len_total, designators])
unique_lengths = Counter([v.length for v in self.cables.values() if v.gauge_and_unit == gauge_and_unit and
v.wirecount_and_shield == wirecount_and_shield])
for length in unique_lengths:
qty = unique_lengths[length]
designators = [k for k,v in self.cables.items() if v.gauge_and_unit == gauge_and_unit and
v.wirecount_and_shield == wirecount_and_shield and
v.length == length]
bom_cut.append([gauge, gauge_unit, wirecount, shield, length, qty, designators])
return (bom_cbl, bom_cut)
@dataclass @dataclass
class Connector: class Connector: