Internal BoM: The "Quantity" column no longer includes the DNF/C status.

- This status was moved to a separated column named `Status`.
- You can join both columns if you want.
Some people pointed out that adding characters to the qty column prevents
computations applied to the CSV files.
This commit is contained in:
Salvador E. Tropea 2021-01-12 15:21:34 -03:00
parent e0ab45e95d
commit 65833dc333
6 changed files with 65 additions and 52 deletions

View File

@ -14,6 +14,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- Now the default output name applies to the DRC and ERC report names.
This provides more coherent file names.
- Internal BoM: The "Quantity" column no longer includes the DNF/C status.
This status was moved to a separated column named `Status`.
You can join both columns if you want.
## [0.9.0] - 2021-01-04

View File

@ -233,12 +233,16 @@ class ComponentGroup(object):
self.fields[ColumnList.COL_REFERENCE_L] = self.get_refs()
# Quantity
q = self.get_count()
self.fields[ColumnList.COL_GRP_QUANTITY_L] = "{n}{dnf}{dnc}".format(
n=q,
dnf=" (DNF)" if not self.is_fitted() else "",
dnc=" (DNC)" if self.is_fixed() else "")
self.fields[ColumnList.COL_GRP_QUANTITY_L] = str(q)
self.fields[ColumnList.COL_GRP_BUILD_QUANTITY_L] = str(q * self.cfg.number) if self.is_fitted() else "0"
# Group status
status = ' '
if not self.is_fitted():
status += '(DNF)'
if self.is_fixed():
status += '(DNC)'
self.fields[ColumnList.COL_STATUS_L] = status
# Component data
comp = self.components[0]
self.fields[ColumnList.COL_VALUE_L] = comp.value
self.fields[ColumnList.COL_PART_L] = comp.name

View File

@ -41,6 +41,8 @@ class ColumnList:
COL_SHEETPATH_L = COL_SHEETPATH.lower()
COL_ROW_NUMBER = 'Row'
COL_ROW_NUMBER_L = COL_ROW_NUMBER.lower()
COL_STATUS = 'Status'
COL_STATUS_L = COL_STATUS.lower()
# Default columns for groups
COL_GRP_QUANTITY = 'Quantity Per PCB'
@ -53,6 +55,7 @@ class ColumnList:
COL_GRP_QUANTITY_L: 1,
COL_GRP_BUILD_QUANTITY_L: 1,
COL_ROW_NUMBER_L: 1,
COL_STATUS_L: 1,
}
# Default columns
@ -67,6 +70,7 @@ class ColumnList:
COL_FP_LIB,
COL_GRP_QUANTITY,
COL_GRP_BUILD_QUANTITY,
COL_STATUS,
COL_DATASHEET,
COL_SHEETPATH
]

View File

@ -58,16 +58,17 @@ BOM_DIR = 'BoM'
REF_COLUMN_NAME = 'References'
REF_COLUMN_NAME_R = 'Referencias'
QTY_COLUMN_NAME = 'Quantity Per PCB'
STATUS_COLUMN_NAME = 'Status'
COMP_COLUMN_NAME = 'Row'
COMP_COLUMN_NAME_R = 'Renglón'
VALUE_COLUMN_NAME = 'Value'
DATASHEET_COLUMN_NAME = 'Datasheet'
KIBOM_TEST_HEAD = [COMP_COLUMN_NAME, 'Description', 'Part', REF_COLUMN_NAME, 'Value', 'Footprint', QTY_COLUMN_NAME,
KIBOM_TEST_HEAD = [COMP_COLUMN_NAME, 'Description', 'Part', REF_COLUMN_NAME, 'Value', 'Footprint', QTY_COLUMN_NAME, 'Status',
DATASHEET_COLUMN_NAME, 'Config']
KIBOM_TEST_HEAD_TOL = [c for c in KIBOM_TEST_HEAD]
KIBOM_TEST_HEAD_TOL.insert(-1, 'Tolerance')
KIBOM_RENAME_HEAD = [COMP_COLUMN_NAME_R, REF_COLUMN_NAME_R, 'Componente', 'Valor', 'Código Digi-Key', 'Cantidad por PCB']
CONN_HEAD = [COMP_COLUMN_NAME, 'Description', 'Part', REF_COLUMN_NAME, 'Value', 'Footprint', QTY_COLUMN_NAME,
CONN_HEAD = [COMP_COLUMN_NAME, 'Description', 'Part', REF_COLUMN_NAME, 'Value', 'Footprint', QTY_COLUMN_NAME, 'Status',
DATASHEET_COLUMN_NAME]
KIBOM_TEST_COMPONENTS = ['C1', 'C2', 'C3', 'C4', 'R1', 'R2', 'R3', 'R4', 'R5', 'R7', 'R8', 'R9', 'R10']
KIBOM_TEST_COMPONENTS_ALT = ['C1-C4', 'R9-R10', 'R7', 'R8', 'R1-R5']
@ -114,10 +115,10 @@ def check_kibom_test_netlist(rows, ref_column, groups, exclude, comps, ref_sep='
logging.debug("list of components OK")
def check_dnc(rows, comp, ref, qty, datasheet=None):
def check_dnc(rows, comp, ref, status, datasheet=None):
for row in rows:
if row[ref].find(comp) != -1:
assert row[qty] == '1 (DNC)'
assert '(DNC)' in row[status]
logging.debug(comp + " is DNC OK")
if datasheet is not None:
assert row[datasheet].startswith('<a href="')
@ -220,13 +221,13 @@ def check_csv_info(r, info, stats):
assert row == len(r)
def kibom_verif(rows, header, skip_head=False, qty_name=QTY_COLUMN_NAME, ref_sep=' '):
def kibom_verif(rows, header, skip_head=False, qty_name=STATUS_COLUMN_NAME, ref_sep=' '):
if not skip_head:
assert header == KIBOM_TEST_HEAD
ref_column = header.index(REF_COLUMN_NAME)
qty_column = header.index(qty_name)
status_column = header.index(qty_name)
check_kibom_test_netlist(rows, ref_column, KIBOM_TEST_GROUPS, KIBOM_TEST_EXCLUDE, KIBOM_TEST_COMPONENTS, ref_sep)
check_dnc(rows, 'R7', ref_column, qty_column)
check_dnc(rows, 'R7', ref_column, status_column)
def kibom_setup(test, ext='csv'):
@ -314,11 +315,11 @@ def simple_html_test(ctx, rows, headers, sh_head, prj, do_title=True, do_logo=Tr
assert headers[0] == KIBOM_TEST_HEAD
# Look for reference and quantity columns
ref_column = headers[0].index(REF_COLUMN_NAME)
qty_column = headers[0].index(QTY_COLUMN_NAME)
status_column = headers[0].index(STATUS_COLUMN_NAME)
ds_column = headers[0].index(DATASHEET_COLUMN_NAME)
# Check the normal table
check_kibom_test_netlist(rows[0], ref_column, KIBOM_TEST_GROUPS, KIBOM_TEST_EXCLUDE, KIBOM_TEST_COMPONENTS)
check_dnc(rows[0], 'R7', ref_column, qty_column, ds_column)
check_dnc(rows[0], 'R7', ref_column, status_column, ds_column)
# Check the DNF table
check_kibom_test_netlist(rows[1], ref_column, 1, KIBOM_TEST_COMPONENTS, KIBOM_TEST_EXCLUDE)
ctx.clean_up()
@ -414,7 +415,7 @@ def test_int_bom_simple_xml():
# Columns get sorted by name, so we need to take care of it
for c in KIBOM_TEST_HEAD:
assert adapt_xml(c) in header, "Missing column "+c
kibom_verif(rows, header, skip_head=True, qty_name=adapt_xml(QTY_COLUMN_NAME))
kibom_verif(rows, header, skip_head=True, qty_name=adapt_xml(STATUS_COLUMN_NAME))
ctx.clean_up()
@ -426,9 +427,9 @@ def simple_xlsx_verify(ctx, prj, dnf=True):
check_head_xlsx(sh_head, KIBOM_PRJ_INFO, KIBOM_STATS)
assert header == KIBOM_TEST_HEAD
ref_column = header.index(REF_COLUMN_NAME)
qty_column = header.index(QTY_COLUMN_NAME)
status_column = header.index(STATUS_COLUMN_NAME)
check_kibom_test_netlist(rows, ref_column, KIBOM_TEST_GROUPS, KIBOM_TEST_EXCLUDE, KIBOM_TEST_COMPONENTS)
check_dnc(rows, 'R7', ref_column, qty_column)
check_dnc(rows, 'R7', ref_column, status_column)
rows, header, sh_head = ctx.load_xlsx(out, 2)
if dnf:
check_kibom_test_netlist(rows, ref_column, 1, [], KIBOM_TEST_EXCLUDE)
@ -625,9 +626,9 @@ def test_int_include_dnf():
rows, header, info = ctx.load_csv(out)
assert header == KIBOM_TEST_HEAD
ref_column = header.index(REF_COLUMN_NAME)
qty_column = header.index(QTY_COLUMN_NAME)
status_column = header.index(STATUS_COLUMN_NAME)
check_kibom_test_netlist(rows, ref_column, KIBOM_TEST_GROUPS+1, [], KIBOM_TEST_COMPONENTS+KIBOM_TEST_EXCLUDE)
check_dnc(rows, 'R7', ref_column, qty_column)
check_dnc(rows, 'R7', ref_column, status_column)
ctx.clean_up()
@ -646,9 +647,9 @@ def test_int_bom_html_generate_dnf():
assert headers[0] == KIBOM_TEST_HEAD
# Look for reference and quantity columns
ref_column = headers[0].index(REF_COLUMN_NAME)
qty_column = headers[0].index(QTY_COLUMN_NAME)
status_column = headers[0].index(STATUS_COLUMN_NAME)
check_kibom_test_netlist(rows[0], ref_column, KIBOM_TEST_GROUPS, KIBOM_TEST_EXCLUDE, KIBOM_TEST_COMPONENTS)
check_dnc(rows[0], 'R7', ref_column, qty_column)
check_dnc(rows[0], 'R7', ref_column, status_column)
ctx.clean_up()
@ -662,9 +663,9 @@ def test_int_bom_use_alt():
rows, header, info = ctx.load_csv(out)
assert header == KIBOM_TEST_HEAD
ref_column = header.index(REF_COLUMN_NAME)
qty_column = header.index(QTY_COLUMN_NAME)
status_column = header.index(STATUS_COLUMN_NAME)
check_kibom_test_netlist(rows, ref_column, KIBOM_TEST_GROUPS, KIBOM_TEST_EXCLUDE, KIBOM_TEST_COMPONENTS_ALT)
check_dnc(rows, 'R7', ref_column, qty_column)
check_dnc(rows, 'R7', ref_column, status_column)
ctx.clean_up()
@ -678,11 +679,11 @@ def test_int_bom_use_alt_2():
rows, header, info = ctx.load_csv(out)
assert header == KIBOM_TEST_HEAD
ref_column = header.index(REF_COLUMN_NAME)
qty_column = header.index(QTY_COLUMN_NAME)
status_column = header.index(STATUS_COLUMN_NAME)
# R3 without footprint won't be merged with other 10K resistors
check_kibom_test_netlist(rows, ref_column, KIBOM_TEST_GROUPS+1, KIBOM_TEST_EXCLUDE, KIBOM_TEST_COMPONENTS_ALT2,
ref_sep=';')
check_dnc(rows, 'R7', ref_column, qty_column)
check_dnc(rows, 'R7', ref_column, status_column)
ctx.clean_up()
@ -696,9 +697,9 @@ def test_int_bom_no_number_rows():
rows, header, info = ctx.load_csv(out)
assert header == KIBOM_TEST_HEAD[1:]
ref_column = header.index(REF_COLUMN_NAME)
qty_column = header.index(QTY_COLUMN_NAME)
status_column = header.index(STATUS_COLUMN_NAME)
check_kibom_test_netlist(rows, ref_column, KIBOM_TEST_GROUPS, KIBOM_TEST_EXCLUDE, KIBOM_TEST_COMPONENTS)
check_dnc(rows, 'R7', ref_column, qty_column)
check_dnc(rows, 'R7', ref_column, status_column)
ctx.clean_up()
@ -808,9 +809,9 @@ def test_int_bom_alias_csv():
rows, header, info = ctx.load_csv(out)
assert header == KIBOM_TEST_HEAD
ref_column = header.index(REF_COLUMN_NAME)
qty_column = header.index(QTY_COLUMN_NAME)
status_column = header.index(STATUS_COLUMN_NAME)
check_kibom_test_netlist(rows, ref_column, KIBOM_TEST_GROUPS, KIBOM_TEST_EXCLUDE, KIBOM_TEST_COMPONENTS)
check_dnc(rows, 'R7', ref_column, qty_column)
check_dnc(rows, 'R7', ref_column, status_column)
ctx.clean_up()
@ -824,10 +825,10 @@ def test_int_bom_alias_nm_csv():
rows, header, info = ctx.load_csv(out)
assert header == KIBOM_TEST_HEAD
ref_column = header.index(REF_COLUMN_NAME)
qty_column = header.index(QTY_COLUMN_NAME)
status_column = header.index(STATUS_COLUMN_NAME)
# R3 without footprint won't be merged with other 10K resistors
check_kibom_test_netlist(rows, ref_column, KIBOM_TEST_GROUPS+1, KIBOM_TEST_EXCLUDE, KIBOM_TEST_COMPONENTS)
check_dnc(rows, 'R7', ref_column, qty_column)
check_dnc(rows, 'R7', ref_column, status_column)
ctx.clean_up()
@ -841,10 +842,10 @@ def test_int_bom_no_group_csv():
rows, header, info = ctx.load_csv(out)
assert header == KIBOM_TEST_HEAD
ref_column = header.index(REF_COLUMN_NAME)
qty_column = header.index(QTY_COLUMN_NAME)
status_column = header.index(STATUS_COLUMN_NAME)
# R3 without footprint won't be merged with other 10K resistors
check_kibom_test_netlist(rows, ref_column, len(KIBOM_TEST_COMPONENTS), KIBOM_TEST_EXCLUDE, KIBOM_TEST_COMPONENTS)
check_dnc(rows, 'R7', ref_column, qty_column)
check_dnc(rows, 'R7', ref_column, status_column)
ctx.clean_up()
@ -859,9 +860,9 @@ def test_int_bom_repeat_csv():
rows, header, info = ctx.load_csv(out)
assert header == KIBOM_TEST_HEAD
ref_column = header.index(REF_COLUMN_NAME)
qty_column = header.index(QTY_COLUMN_NAME)
status_column = header.index(STATUS_COLUMN_NAME)
check_kibom_test_netlist(rows, ref_column, 2, ['R2'], ['U1', 'R1'])
check_dnc(rows, 'R1', ref_column, qty_column)
check_dnc(rows, 'R1', ref_column, status_column)
ctx.clean_up()
@ -875,9 +876,9 @@ def test_int_bom_collision():
rows, header, info = ctx.load_csv(out)
assert header == KIBOM_TEST_HEAD_TOL
ref_column = header.index(REF_COLUMN_NAME)
qty_column = header.index(QTY_COLUMN_NAME)
status_column = header.index(STATUS_COLUMN_NAME)
check_kibom_test_netlist(rows, ref_column, KIBOM_TEST_GROUPS, KIBOM_TEST_EXCLUDE, KIBOM_TEST_COMPONENTS)
check_dnc(rows, 'R7', ref_column, qty_column)
check_dnc(rows, 'R7', ref_column, status_column)
ctx.search_err('Field conflict')
ctx.clean_up()
@ -892,9 +893,9 @@ def test_int_bom_exclude_any():
rows, header, info = ctx.load_csv(out)
assert header == KIBOM_TEST_HEAD_TOL
ref_column = header.index(REF_COLUMN_NAME)
qty_column = header.index(QTY_COLUMN_NAME)
status_column = header.index(STATUS_COLUMN_NAME)
check_kibom_test_netlist(rows, ref_column, KIBOM_TEST_GROUPS+1, KIBOM_TEST_EXCLUDE, KIBOM_TEST_COMPONENTS+['X1'])
check_dnc(rows, 'R7', ref_column, qty_column)
check_dnc(rows, 'R7', ref_column, status_column)
ctx.search_err('Field conflict')
ctx.clean_up()
@ -909,9 +910,9 @@ def test_int_bom_include_only():
rows, header, info = ctx.load_csv(out)
assert header == KIBOM_TEST_HEAD
ref_column = header.index(REF_COLUMN_NAME)
qty_column = header.index(QTY_COLUMN_NAME)
status_column = header.index(STATUS_COLUMN_NAME)
check_kibom_test_netlist(rows, ref_column, 3, KIBOM_TEST_EXCLUDE, ['R1', 'R2', 'R3', 'R4', 'R5', 'R7', 'R8'])
check_dnc(rows, 'R7', ref_column, qty_column)
check_dnc(rows, 'R7', ref_column, status_column)
ctx.clean_up()
@ -924,9 +925,9 @@ def test_int_bom_include_only():
# rows, header, info = ctx.load_csv(out)
# assert header == KIBOM_TEST_HEAD
# ref_column = header.index(REF_COLUMN_NAME)
# qty_column = header.index(QTY_COLUMN_NAME)
# status_column = header.index(STATUS_COLUMN_NAME)
# check_kibom_test_netlist(rows, ref_column, KIBOM_TEST_GROUPS, KIBOM_TEST_EXCLUDE, KIBOM_TEST_COMPONENTS)
# check_dnc(rows, 'R7', ref_column, qty_column)
# check_dnc(rows, 'R7', ref_column, status_column)
# ctx.clean_up()
@ -962,9 +963,9 @@ def test_int_bom_simple_xlsx_2():
check_head_xlsx(sh_head, KIBOM_PRJ_INFO, KIBOM_STATS, title=None)
assert header == KIBOM_TEST_HEAD
ref_column = header.index(REF_COLUMN_NAME)
qty_column = header.index(QTY_COLUMN_NAME)
status_column = header.index(STATUS_COLUMN_NAME)
check_kibom_test_netlist(rows, ref_column, KIBOM_TEST_GROUPS, KIBOM_TEST_EXCLUDE, KIBOM_TEST_COMPONENTS)
check_dnc(rows, 'R7', ref_column, qty_column)
check_dnc(rows, 'R7', ref_column, status_column)
ctx.clean_up()
@ -986,9 +987,9 @@ def test_int_bom_simple_xlsx_4():
check_head_xlsx(sh_head, KIBOM_PRJ_INFO, KIBOM_STATS, title=None)
assert header == KIBOM_TEST_HEAD
ref_column = header.index(REF_COLUMN_NAME)
qty_column = header.index(QTY_COLUMN_NAME)
status_column = header.index(STATUS_COLUMN_NAME)
check_kibom_test_netlist(rows, ref_column, KIBOM_TEST_GROUPS, KIBOM_TEST_EXCLUDE, KIBOM_TEST_COMPONENTS)
check_dnc(rows, 'R7', ref_column, qty_column)
check_dnc(rows, 'R7', ref_column, status_column)
ctx.clean_up()
@ -1003,9 +1004,9 @@ def test_int_bom_simple_xlsx_5():
check_head_xlsx(sh_head, None, KIBOM_STATS, title=None)
assert header == KIBOM_TEST_HEAD
ref_column = header.index(REF_COLUMN_NAME)
qty_column = header.index(QTY_COLUMN_NAME)
status_column = header.index(STATUS_COLUMN_NAME)
check_kibom_test_netlist(rows, ref_column, KIBOM_TEST_GROUPS, KIBOM_TEST_EXCLUDE, KIBOM_TEST_COMPONENTS)
check_dnc(rows, 'R7', ref_column, qty_column)
check_dnc(rows, 'R7', ref_column, status_column)
ctx.clean_up()
@ -1020,9 +1021,9 @@ def test_int_bom_simple_xlsx_6():
assert len(sh_head) == 0
assert header == KIBOM_TEST_HEAD
ref_column = header.index(REF_COLUMN_NAME)
qty_column = header.index(QTY_COLUMN_NAME)
status_column = header.index(STATUS_COLUMN_NAME)
check_kibom_test_netlist(rows, ref_column, KIBOM_TEST_GROUPS, KIBOM_TEST_EXCLUDE, KIBOM_TEST_COMPONENTS)
check_dnc(rows, 'R7', ref_column, qty_column)
check_dnc(rows, 'R7', ref_column, status_column)
ctx.clean_up()

View File

@ -15,6 +15,7 @@ outputs:
- Value
- Footprint
- Quantity Per PCB
- Status
- Datasheet
- Config

View File

@ -8,6 +8,6 @@ outputs:
type: bom
dir: BoM
options:
columns: ['Row','Description','Part','References','Value','Footprint','Quantity Per PCB','Datasheet','Sheetpath']
columns: ['Row','Description','Part','References','Value','Footprint','Quantity Per PCB','Status','Datasheet','Sheetpath']
group_fields: []