ffe508b7f3
FastAPI + SQLite behind a single-page frontend, deployed as a container on mainserver behind Caddy. One flexible parts table plus key/value specs so components, filament, fasteners and tooling share a schema. Categories and locations are nestable trees whose filters and sidebar counts both roll up through descendants. Category spec templates pre-fill the properties worth recording for each kind of part, which is what makes manual entry tolerable. Every quantity change is logged. Search is FTS5 with prefix matching across names, MPNs, spec values, tags, category and location. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
97 lines
4.9 KiB
Python
97 lines
4.9 KiB
Python
"""Starter categories and their spec templates.
|
|
|
|
Seeded once, on an empty database. A category's template is only a suggestion —
|
|
the add form pre-fills those keys, and you can delete any of them or add your
|
|
own. Nothing here constrains what a part may hold.
|
|
"""
|
|
|
|
import json
|
|
|
|
# (name, unit, [spec keys...], [children...])
|
|
TREE = [
|
|
("Electronics", "pcs", [], [
|
|
("Resistors", "pcs", ["Resistance", "Tolerance", "Power", "Package", "Type"]),
|
|
("Capacitors", "pcs", ["Capacitance", "Voltage", "Dielectric", "Tolerance", "Package"]),
|
|
("Inductors", "pcs", ["Inductance", "Current", "Package"]),
|
|
("Diodes", "pcs", ["Type", "Forward Voltage", "Current", "Package"]),
|
|
("LEDs", "pcs", ["Colour", "Package", "Forward Voltage", "Current", "Wavelength"]),
|
|
("Transistors", "pcs", ["Type", "Voltage", "Current", "Package"]),
|
|
("ICs", "pcs", ["Function", "Package", "Pins", "Voltage"]),
|
|
("Voltage Regulators", "pcs", ["Output Voltage", "Current", "Type", "Package"]),
|
|
("Crystals & Oscillators", "pcs", ["Frequency", "Load Capacitance", "Package"]),
|
|
("Connectors", "pcs", ["Type", "Pitch", "Positions", "Gender", "Mount"]),
|
|
("Headers & Jumpers", "pcs", ["Pitch", "Positions", "Rows", "Orientation"]),
|
|
("Switches & Buttons", "pcs", ["Type", "Poles", "Rating", "Mount"]),
|
|
("Relays", "pcs", ["Coil Voltage", "Contact Rating", "Type"]),
|
|
("Sensors", "pcs", ["Measures", "Interface", "Voltage", "Range"]),
|
|
("Modules & Breakouts", "pcs", ["Function", "Interface", "Voltage"]),
|
|
("Dev Boards", "pcs", ["MCU", "Voltage", "Flash", "RAM", "Connectivity"]),
|
|
("Displays", "pcs", ["Type", "Size", "Resolution", "Interface", "Voltage"]),
|
|
("Motors & Actuators", "pcs", ["Type", "Voltage", "Torque", "Shaft"]),
|
|
("Wire & Cable", "m", ["Gauge", "Conductors", "Insulation", "Colour"]),
|
|
("PCBs & Protoboard", "pcs", ["Size", "Layers", "Type"]),
|
|
("Batteries & Power", "pcs", ["Chemistry", "Voltage", "Capacity", "Form Factor"]),
|
|
]),
|
|
("3D Printing", "pcs", [], [
|
|
("Filament", "g", ["Material", "Colour", "Diameter", "Brand", "Spool Weight", "Print Temp", "Bed Temp"]),
|
|
("Resin", "ml", ["Type", "Colour", "Brand", "Cure Time"]),
|
|
("Nozzles", "pcs", ["Diameter", "Material", "Thread", "Fits"]),
|
|
("Printer Spares", "pcs", ["Fits", "Function"]),
|
|
("Build Surfaces", "pcs", ["Size", "Type", "Fits"]),
|
|
]),
|
|
("Mechanical", "pcs", [], [
|
|
("Fasteners", "pcs", ["Thread", "Length", "Head", "Drive", "Material", "Finish"]),
|
|
("Nuts & Washers", "pcs", ["Thread", "Type", "Material"]),
|
|
("Standoffs & Spacers", "pcs", ["Thread", "Length", "Material", "Type"]),
|
|
("Bearings", "pcs", ["Bore", "Outer Diameter", "Width", "Type"]),
|
|
("Belts & Pulleys", "pcs", ["Profile", "Teeth", "Width", "Bore"]),
|
|
("Linear Motion", "pcs", ["Diameter", "Length", "Type"]),
|
|
("Springs & Magnets", "pcs", ["Size", "Type", "Strength"]),
|
|
("Extrusion & Stock", "mm", ["Profile", "Material", "Length"]),
|
|
]),
|
|
("Materials", "pcs", [], [
|
|
("Sheet & Plate", "pcs", ["Material", "Thickness", "Size"]),
|
|
("Adhesives & Tape", "pcs", ["Type", "Width", "Use"]),
|
|
("Finishing", "pcs", ["Type", "Colour", "Volume"]),
|
|
]),
|
|
("Tools", "pcs", [], [
|
|
("Hand Tools", "pcs", ["Type", "Size", "Brand"]),
|
|
("Power Tools", "pcs", ["Type", "Voltage", "Brand"]),
|
|
("Bits & Blades", "pcs", ["Type", "Size", "Fits"]),
|
|
("Measurement", "pcs", ["Type", "Range", "Resolution", "Brand"]),
|
|
("Soldering", "pcs", ["Type", "Diameter", "Alloy", "Flux"]),
|
|
]),
|
|
("Consumables", "pcs", [], [
|
|
("Cleaning", "pcs", ["Type", "Volume"]),
|
|
("Safety & PPE", "pcs", ["Type", "Size"]),
|
|
]),
|
|
("Uncategorised", "pcs", [], []),
|
|
]
|
|
|
|
LOCATIONS = ["Workshop", "Storage"]
|
|
|
|
|
|
def seed(conn):
|
|
if conn.execute("SELECT 1 FROM categories LIMIT 1").fetchone():
|
|
return
|
|
|
|
def add(name, unit, specs, parent_id, order):
|
|
template = json.dumps([{"key": k} for k in specs])
|
|
cur = conn.execute(
|
|
"INSERT INTO categories(name, parent_id, unit, spec_template, sort_order) VALUES (?,?,?,?,?)",
|
|
(name, parent_id, unit, template, order),
|
|
)
|
|
return cur.lastrowid
|
|
|
|
for i, (name, unit, specs, children) in enumerate(TREE):
|
|
parent = add(name, unit, specs, None, i)
|
|
for j, (cname, cunit, cspecs) in enumerate(children):
|
|
add(cname, cunit, cspecs, parent, j)
|
|
|
|
for i, name in enumerate(LOCATIONS):
|
|
conn.execute(
|
|
"INSERT INTO locations(name, parent_id, sort_order) VALUES (?, NULL, ?)",
|
|
(name, i),
|
|
)
|
|
conn.commit()
|