# Script for populating the database with sample data. You can run it as: # # mix run priv/repo/seeds.exs # # This seeds file creates: # - Sample categories (with hierarchical subcategories) # - Storage locations (with auto-assigned AprilTag IDs) # - Sample electronic components with proper storage assignments # - Generates all AprilTag SVG files for immediate use # # Inside the script, you can read and write to any of your # repositories directly: # # ComponentsElixir.Repo.insert!(%ComponentsElixir.SomeSchema{}) # # We recommend using the bang functions (`insert!`, `update!` # and so on) as they will fail if something goes wrong. alias ComponentsElixir.{Repo, Inventory, AprilTag} alias ComponentsElixir.Inventory.{Category, Component, StorageLocation} # Clear existing data Repo.delete_all(Component) Repo.delete_all(Category) Repo.delete_all(StorageLocation) # Create categories {:ok, resistors} = Inventory.create_category(%{name: "Resistors", description: "Various types of resistors"}) {:ok, capacitors} = Inventory.create_category(%{ name: "Capacitors", description: "Electrolytic, ceramic, and film capacitors" }) {:ok, semiconductors} = Inventory.create_category(%{name: "Semiconductors", description: "ICs, transistors, diodes"}) {:ok, connectors} = Inventory.create_category(%{name: "Connectors", description: "Headers, terminals, plugs"}) # Create subcategories {:ok, _through_hole_resistors} = Inventory.create_category(%{ name: "Through-hole", description: "Traditional leaded resistors", parent_id: resistors.id }) {:ok, _smd_resistors} = Inventory.create_category(%{ name: "SMD/SMT", description: "Surface mount resistors", parent_id: resistors.id }) {:ok, _ceramic_caps} = Inventory.create_category(%{ name: "Ceramic", description: "Ceramic disc and multilayer capacitors", parent_id: capacitors.id }) {:ok, _electrolytic_caps} = Inventory.create_category(%{ name: "Electrolytic", description: "Polarized electrolytic capacitors", parent_id: capacitors.id }) # Create a DEEP category hierarchy to test fallback path (7+ levels) {:ok, deep_cat_1} = Inventory.create_category(%{ name: "Level 1", description: "Deep hierarchy test", parent_id: resistors.id }) {:ok, deep_cat_2} = Inventory.create_category(%{ name: "Level 2", description: "Deep hierarchy test", parent_id: deep_cat_1.id }) {:ok, deep_cat_3} = Inventory.create_category(%{ name: "Level 3", description: "Deep hierarchy test", parent_id: deep_cat_2.id }) {:ok, deep_cat_4} = Inventory.create_category(%{ name: "Level 4", description: "Deep hierarchy test", parent_id: deep_cat_3.id }) {:ok, deep_cat_5} = Inventory.create_category(%{ name: "Level 5", description: "Deep hierarchy test", parent_id: deep_cat_4.id }) {:ok, deep_cat_6} = Inventory.create_category(%{ name: "Level 6", description: "Deep hierarchy test", parent_id: deep_cat_5.id }) {:ok, deep_cat_7} = Inventory.create_category(%{ name: "Level 7", description: "Deep hierarchy test - triggers fallback", parent_id: deep_cat_6.id }) # Create storage locations {:ok, shelf_a} = Inventory.create_storage_location(%{name: "Shelf A", description: "Main electronics shelf"}) {:ok, _shelf_b} = Inventory.create_storage_location(%{name: "Shelf B", description: "Components overflow shelf"}) # Create drawers on Shelf A {:ok, drawer_a1} = Inventory.create_storage_location(%{ name: "Drawer 1", description: "Resistors and capacitors", parent_id: shelf_a.id }) {:ok, drawer_a2} = Inventory.create_storage_location(%{ name: "Drawer 2", description: "Semiconductors and ICs", parent_id: shelf_a.id }) # Create boxes in Drawer A1 {:ok, box_a1_1} = Inventory.create_storage_location(%{ name: "Box 1", description: "Through-hole resistors", parent_id: drawer_a1.id }) {:ok, _box_a1_2} = Inventory.create_storage_location(%{ name: "Box 2", description: "SMD resistors", parent_id: drawer_a1.id }) {:ok, box_a1_3} = Inventory.create_storage_location(%{ name: "Box 3", description: "Ceramic capacitors", parent_id: drawer_a1.id }) # Create boxes in Drawer A2 {:ok, box_a2_1} = Inventory.create_storage_location(%{ name: "Box 1", description: "Microcontrollers", parent_id: drawer_a2.id }) {:ok, _box_a2_2} = Inventory.create_storage_location(%{ name: "Box 2", description: "Transistors and diodes", parent_id: drawer_a2.id }) # Create a DEEP storage location hierarchy to test fallback path (7+ levels) {:ok, deep_loc_1} = Inventory.create_storage_location(%{ name: "Deep Level 1", description: "Deep hierarchy test", parent_id: box_a1_3.id }) {:ok, deep_loc_2} = Inventory.create_storage_location(%{ name: "Deep Level 2", description: "Deep hierarchy test", parent_id: deep_loc_1.id }) {:ok, deep_loc_3} = Inventory.create_storage_location(%{ name: "Deep Level 3", description: "Deep hierarchy test", parent_id: deep_loc_2.id }) {:ok, deep_loc_4} = Inventory.create_storage_location(%{ name: "Deep Level 4", description: "Deep hierarchy test", parent_id: deep_loc_3.id }) {:ok, deep_loc_5} = Inventory.create_storage_location(%{ name: "Deep Level 5", description: "Deep hierarchy test", parent_id: deep_loc_4.id }) {:ok, deep_loc_6} = Inventory.create_storage_location(%{ name: "Deep Level 6", description: "Deep hierarchy test", parent_id: deep_loc_5.id }) {:ok, deep_loc_7} = Inventory.create_storage_location(%{ name: "Deep Level 7", description: "Deep hierarchy test - triggers fallback", parent_id: deep_loc_6.id }) # Create sample components sample_components = [ %{ name: "1kΩ Resistor (1/4W)", description: "Carbon film resistor, 5% tolerance", keywords: "resistor carbon film 1k ohm", storage_location_id: box_a1_1.id, count: 150, category_id: resistors.id }, %{ name: "10kΩ Resistor (1/4W)", description: "Carbon film resistor, 5% tolerance", keywords: "resistor carbon film 10k ohm", storage_location_id: box_a1_1.id, count: 200, category_id: resistors.id }, %{ name: "100μF Electrolytic Capacitor", description: "25V electrolytic capacitor, radial leads", keywords: "capacitor electrolytic 100uf microfarad", storage_location_id: box_a1_3.id, count: 50, category_id: capacitors.id }, %{ name: "0.1μF Ceramic Capacitor", description: "50V ceramic disc capacitor", keywords: "capacitor ceramic 100nf nanofarad disc", storage_location_id: box_a1_3.id, count: 300, category_id: capacitors.id }, %{ name: "ATmega328P-PU", description: "8-bit AVR microcontroller, DIP-28 package", keywords: "microcontroller avr atmega328 arduino", storage_location_id: box_a2_1.id, count: 10, datasheet_url: "https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf", category_id: semiconductors.id }, %{ name: "LM358 Op-Amp", description: "Dual operational amplifier, DIP-8 package", keywords: "opamp operational amplifier lm358 dual", storage_location_id: box_a2_1.id, count: 25, category_id: semiconductors.id }, %{ name: "2N2222 NPN Transistor", description: "General purpose NPN transistor, TO-92 package", keywords: "transistor npn 2n2222 to92", storage_location_id: box_a2_1.id, count: 40, category_id: semiconductors.id }, %{ name: "2.54mm Pin Headers", description: "Male pin headers, 40 pins, break-away", keywords: "header pins male 2.54mm breakaway", storage_location_id: drawer_a2.id, count: 20, category_id: connectors.id }, %{ name: "JST-XH 2-pin Connector", description: "2-pin JST-XH connector with housing", keywords: "jst xh connector 2pin housing", storage_location_id: drawer_a2.id, count: 30, category_id: connectors.id }, %{ name: "470Ω Resistor (1/4W)", description: "Carbon film resistor, 5% tolerance, commonly used for LEDs", keywords: "resistor carbon film 470 ohm led current limiting", storage_location_id: box_a1_1.id, count: 100, category_id: resistors.id }, # Test components for deep hierarchies to ensure fallback path is exercised %{ name: "Deep Category Test Component", description: "Component in 7-level deep category hierarchy", keywords: "test deep hierarchy category fallback", storage_location_id: box_a1_1.id, count: 1, category_id: deep_cat_7.id }, %{ name: "Deep Storage Test Component", description: "Component in 7-level deep storage location hierarchy", keywords: "test deep hierarchy storage fallback", storage_location_id: deep_loc_7.id, count: 1, category_id: resistors.id } ] Enum.each(sample_components, fn component_attrs -> {:ok, _component} = Inventory.create_component(component_attrs) end) IO.puts("Seeded database with categories, storage locations, and sample components!") IO.puts("Categories: #{length(Inventory.list_categories())}") IO.puts("Storage Locations: #{length(Inventory.list_storage_locations())}") IO.puts("Components: #{length(Inventory.list_components())}") IO.puts("") IO.puts("Sample AprilTag information:") # Print AprilTag information for sample storage locations sample_locations = [ Inventory.get_storage_location!(shelf_a.id), Inventory.get_storage_location!(drawer_a1.id), Inventory.get_storage_location!(box_a1_1.id), Inventory.get_storage_location!(box_a2_1.id) ] Enum.each(sample_locations, fn location -> if location.apriltag_id do apriltag_url = AprilTag.get_apriltag_url(location) location_path = StorageLocation.full_path(location) IO.puts("#{location_path}: AprilTag ID #{location.apriltag_id}") IO.puts(" Download URL: #{apriltag_url}") else location_path = StorageLocation.full_path(location) IO.puts("#{location_path}: No AprilTag assigned") end end) # Generate all AprilTag SVGs for immediate use IO.puts("Generating AprilTag SVG files...") result = AprilTag.generate_all_apriltag_svgs() IO.puts("Generated #{result.success}/#{result.total} AprilTag SVG files") IO.puts("") IO.puts("🎉 Database seeded successfully!") IO.puts("📊 Summary:") IO.puts(" Categories: #{length(Inventory.list_categories())}") IO.puts( " Storage Locations: #{length(Inventory.list_storage_locations())} (with auto-assigned AprilTags)" ) IO.puts(" Components: #{length(Inventory.list_components())}") IO.puts("") IO.puts("🏷️ AprilTag System:") IO.puts(" - Each storage location has an auto-assigned AprilTag ID (0-586)") IO.puts(" - SVG files available at /apriltags/tag36h11_id_XXX.svg") IO.puts(" - Download AprilTags from storage location management page") IO.puts("") IO.puts("🔐 Login with password: changeme (or set AUTH_PASSWORD environment variable)") IO.puts("🌐 Visit http://localhost:4000 to start using the system!")