Changes
This commit is contained in:
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"python-envs.defaultEnvManager": "ms-python.python:system"
|
||||||
|
}
|
||||||
@@ -42,6 +42,7 @@ from typing import Optional
|
|||||||
|
|
||||||
import requests
|
import requests
|
||||||
import openpyxl
|
import openpyxl
|
||||||
|
from openpyxl.cell.cell import MergedCell
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
@@ -595,6 +596,8 @@ def write_back(
|
|||||||
skipped = 0
|
skipped = 0
|
||||||
for row_num, mfr, mpn in table.data:
|
for row_num, mfr, mpn in table.data:
|
||||||
cell = ws.cell(row_num, cost_col)
|
cell = ws.cell(row_num, cost_col)
|
||||||
|
if isinstance(cell, MergedCell):
|
||||||
|
continue
|
||||||
existing = cell.value
|
existing = cell.value
|
||||||
if existing is not None and str(existing).strip() != "":
|
if existing is not None and str(existing).strip() != "":
|
||||||
skipped += 1
|
skipped += 1
|
||||||
@@ -620,6 +623,32 @@ def write_back(
|
|||||||
log.error(f" Save failed for {file_path.name}: {exc}")
|
log.error(f" Save failed for {file_path.name}: {exc}")
|
||||||
|
|
||||||
|
|
||||||
|
# ── Summary output ────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
OUTPUT_FILE = Path("bom_prices.xlsx")
|
||||||
|
|
||||||
|
|
||||||
|
def write_summary(parts: set[tuple[str, str]], price_lookup: dict[str, Optional[float]]) -> None:
|
||||||
|
rows = []
|
||||||
|
for mfr, mpn in sorted(parts):
|
||||||
|
price = price_lookup.get(_part_key(mfr, mpn))
|
||||||
|
rows.append({
|
||||||
|
"Manufacturer": mfr,
|
||||||
|
"MPN": mpn,
|
||||||
|
f"Unit Cost EUR @{QUANTITY}": price,
|
||||||
|
})
|
||||||
|
|
||||||
|
df = pd.DataFrame(rows)
|
||||||
|
with pd.ExcelWriter(OUTPUT_FILE, engine="openpyxl") as writer:
|
||||||
|
df.to_excel(writer, index=False, sheet_name="Prices")
|
||||||
|
ws = writer.sheets["Prices"]
|
||||||
|
for col in ws.columns:
|
||||||
|
width = max(len(str(cell.value or "")) for cell in col)
|
||||||
|
ws.column_dimensions[col[0].column_letter].width = min(width + 3, 50)
|
||||||
|
|
||||||
|
log.info(f"Summary written → {OUTPUT_FILE}")
|
||||||
|
|
||||||
|
|
||||||
# ── Main ───────────────────────────────────────────────────────────────────────
|
# ── Main ───────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
@@ -638,7 +667,7 @@ def main() -> None:
|
|||||||
else:
|
else:
|
||||||
log.warning("No API keys found. Copy .env.example → .env and fill in your keys.")
|
log.warning("No API keys found. Copy .env.example → .env and fill in your keys.")
|
||||||
|
|
||||||
file_map, parts = extract_parts(BOM_DIR)
|
_, parts = extract_parts(BOM_DIR)
|
||||||
|
|
||||||
if not parts:
|
if not parts:
|
||||||
log.error("No valid (Manufacturer, MPN) pairs found in BoM files.")
|
log.error("No valid (Manufacturer, MPN) pairs found in BoM files.")
|
||||||
@@ -655,7 +684,7 @@ def main() -> None:
|
|||||||
log.info(f" avg {tag} ({r.sources_found()}/3 sources)")
|
log.info(f" avg {tag} ({r.sources_found()}/3 sources)")
|
||||||
price_lookup[_part_key(mfr, mpn)] = r.average_eur
|
price_lookup[_part_key(mfr, mpn)] = r.average_eur
|
||||||
|
|
||||||
write_back(file_map, price_lookup)
|
write_summary(parts, price_lookup)
|
||||||
|
|
||||||
found = sum(1 for v in price_lookup.values() if v is not None)
|
found = sum(1 for v in price_lookup.values() if v is not None)
|
||||||
missing = [mpn for (_, mpn), v in
|
missing = [mpn for (_, mpn), v in
|
||||||
|
|||||||
BIN
bom_prices.xlsx
Normal file
BIN
bom_prices.xlsx
Normal file
Binary file not shown.
1340
price_cache.json
Normal file
1340
price_cache.json
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user