schema.sql 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. CREATE DATABASE IF NOT EXISTS radionica3d;
  2. USE radionica3d;
  3. -- Materials table
  4. CREATE TABLE IF NOT EXISTS materials (
  5. id INT AUTO_INCREMENT PRIMARY KEY,
  6. name_en VARCHAR(100) NOT NULL,
  7. name_ru VARCHAR(100),
  8. name_me VARCHAR(100),
  9. desc_en TEXT,
  10. desc_ru TEXT,
  11. desc_me TEXT,
  12. price_per_cm3 DECIMAL(10, 2) DEFAULT 0.00,
  13. is_active BOOLEAN DEFAULT TRUE,
  14. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  15. );
  16. -- Services table
  17. CREATE TABLE IF NOT EXISTS services (
  18. id INT AUTO_INCREMENT PRIMARY KEY,
  19. name_en VARCHAR(100) NOT NULL,
  20. name_ru VARCHAR(100),
  21. name_me VARCHAR(100),
  22. desc_en TEXT,
  23. desc_ru TEXT,
  24. desc_me TEXT,
  25. tech_type VARCHAR(50), -- e.g., FDM, SLA
  26. is_active BOOLEAN DEFAULT TRUE,
  27. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  28. );
  29. -- Users table
  30. CREATE TABLE IF NOT EXISTS users (
  31. id INT AUTO_INCREMENT PRIMARY KEY,
  32. email VARCHAR(150) NOT NULL UNIQUE,
  33. password_hash VARCHAR(255) NOT NULL,
  34. first_name VARCHAR(100),
  35. last_name VARCHAR(100),
  36. phone VARCHAR(20),
  37. shipping_address TEXT,
  38. role VARCHAR(20) DEFAULT 'user', -- user, admin
  39. preferred_language VARCHAR(5) DEFAULT 'en',
  40. ip_address VARCHAR(45), -- Supports IPv6
  41. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  42. updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
  43. );
  44. -- Password reset tokens
  45. CREATE TABLE IF NOT EXISTS password_reset_tokens (
  46. id INT AUTO_INCREMENT PRIMARY KEY,
  47. user_id INT NOT NULL,
  48. token VARCHAR(255) NOT NULL UNIQUE,
  49. expires_at TIMESTAMP NOT NULL,
  50. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  51. FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
  52. );
  53. -- Orders table
  54. CREATE TABLE IF NOT EXISTS orders (
  55. id INT AUTO_INCREMENT PRIMARY KEY,
  56. user_id INT NULL,
  57. first_name VARCHAR(100) NOT NULL,
  58. last_name VARCHAR(100) NOT NULL,
  59. phone VARCHAR(20) NOT NULL,
  60. email VARCHAR(150) NOT NULL,
  61. shipping_address TEXT NOT NULL,
  62. model_link TEXT,
  63. status VARCHAR(50) DEFAULT 'pending', -- pending, processing, shipped, completed, cancelled
  64. total_price DECIMAL(10, 2) DEFAULT NULL, -- To be filled by admin later
  65. estimated_price DECIMAL(10, 2) DEFAULT NULL,
  66. material_name VARCHAR(100) NULL, -- Factual Snapshot
  67. material_price DECIMAL(10, 4) DEFAULT NULL, -- Factual Snapshot
  68. allow_portfolio BOOLEAN DEFAULT FALSE,
  69. quantity INT DEFAULT 1,
  70. notes TEXT,
  71. invoice_path TEXT NULL,
  72. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  73. updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  74. FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL
  75. );
  76. CREATE TABLE IF NOT EXISTS order_files (
  77. id INT AUTO_INCREMENT PRIMARY KEY,
  78. order_id INT NULL, -- Allowed NULL for temporary uploads
  79. filename VARCHAR(255) NOT NULL,
  80. file_path VARCHAR(512) NOT NULL,
  81. file_size INT,
  82. quantity INT DEFAULT 1,
  83. file_hash VARCHAR(64),
  84. print_time VARCHAR(50),
  85. filament_g FLOAT,
  86. preview_path VARCHAR(512),
  87. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  88. FOREIGN KEY (order_id) REFERENCES orders(id) ON DELETE CASCADE,
  89. INDEX (file_hash)
  90. );
  91. -- Order Photos table (for reports and portfolio)
  92. CREATE TABLE IF NOT EXISTS order_photos (
  93. id INT AUTO_INCREMENT PRIMARY KEY,
  94. order_id INT,
  95. file_path VARCHAR(512) NOT NULL,
  96. is_public BOOLEAN DEFAULT FALSE, -- Only if allow_portfolio on order is true
  97. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  98. FOREIGN KEY (order_id) REFERENCES orders(id) ON DELETE CASCADE
  99. );
  100. -- Blog Posts table
  101. CREATE TABLE IF NOT EXISTS posts (
  102. id INT AUTO_INCREMENT PRIMARY KEY,
  103. slug VARCHAR(255) NOT NULL UNIQUE,
  104. title_en VARCHAR(255) NOT NULL,
  105. title_me VARCHAR(255),
  106. title_ru VARCHAR(255),
  107. title_ua VARCHAR(255),
  108. excerpt_en TEXT,
  109. excerpt_me TEXT,
  110. excerpt_ru TEXT,
  111. excerpt_ua TEXT,
  112. content_en LONGTEXT,
  113. content_me LONGTEXT,
  114. content_ru LONGTEXT,
  115. content_ua LONGTEXT,
  116. category VARCHAR(50),
  117. image_url VARCHAR(512),
  118. is_published BOOLEAN DEFAULT FALSE,
  119. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  120. updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
  121. );
  122. -- Initial Data Migration
  123. INSERT INTO materials (name_en, name_ru, name_me, desc_en, desc_ru, desc_me, price_per_cm3) VALUES
  124. ('PLA Plastic', 'PLA Пластик', 'PLA Plastika', 'Biodegradable, ideal for prototypes', 'Биоразлагаемый, идеален для прототипов', 'Biorazgradiva, idealna za prototipove', 0.04),
  125. ('ABS Plastic', 'ABS Пластик', 'ABS Plastika', 'Durable, impact resistant', 'Прочный, ударостойкий', 'Izdržljiva, otporna na udarce', 0.05),
  126. ('PETG Plastic', 'PETG Пластик', 'PETG Plastika', 'High chemical resistance', 'Высокая химическая стойкость', 'Visoka hemijska otpornost', 0.06),
  127. ('Photopolymer Resin', 'Фотополимерная смола', 'Fotopolimerna smola', 'Maximum detail and surface quality', 'Максимальная детализация и качество поверхности', 'Maksimalna detaljnost i kvalitet površine', 0.12);
  128. INSERT INTO services (name_en, name_ru, name_me, desc_en, desc_ru, desc_me, tech_type) VALUES
  129. ('FDM Printing', 'FDM Печать', 'FDM Štampa', 'Fast and durable parts made from high-strength engineering plastics. Ideal for functional prototypes and industrial components.', 'Быстрые и прочные детали из высокопрочных инженерных пластиков. Идеально для функциональных прототипов и промышленных узлов.', 'Brzi i izdržljivi djelovi od visokootporne inženjerske plastike. Idealno za funkcionalne prototipove i industrijske komponente.', 'FDM'),
  130. ('SLA Printing', 'SLA Печать', 'SLA Štampa', 'Maximum detail and smooth surface for professional prototypes and high-precision models.', 'Максимальная детализация и гладкость поверхности для профессиональных прототипов и высокоточных моделей.', 'Maksimalna detaljnost i glatka površina za profesionalne prototipove i modele visoke preciznosti.', 'SLA');
  131. -- Initial Blog Posts
  132. INSERT INTO posts (slug, title_en, excerpt_en, content_en, title_ru, excerpt_ru, content_ru, title_me, excerpt_me, content_me, category, is_published) VALUES
  133. ('future-of-3d-printing', 'The Future of 3D Printing in Montenegro', 'How digital manufacturing is changing the local craft business.', '3D printing is no longer just a hobbyists toy. It is becoming a cornerstone of local manufacturing and decentralized production.\n\nIn Montenegro, we are seeing a surge in demand for custom parts that were previously impossible or too expensive to source locally. From drone parts to architectural models, the technology allows for rapid iteration and trust-based service delivery.', 'Будущее 3D-печати в Черногории', 'Как цифровое производство меняет местный ремесленный бизнес.', '3D-печать — это больше не игрушка для хобби. Она становится краеугольным камнем местного производства и децентрализованного изготовления.\n\nВ Черногории мы наблюдаем всплеск спроса на кастомные детали, которые раньше было невозможно или слишком дорого заказывать за границей. От запчастей для дронов до архитектурных моделей — технология позволяет быстро выполнять итерации и предоставлять услуги на основе доверия.', 'Budućnost 3D štampe u Crnoj Gori', 'Kako digitalna proizvodnja mijenja lokalni zanat.', '3D štampa više nije samo igračka za hobiste. Она postaje kamen temeljac lokalne proizvodnje i decentralizovane izrade.\n\nU Crnoj Gori vidimo porast potražnje za prilagođenim djelovima koje je ranije bilo nemoguće ili preskupo nabaviti lokalno. Od djelova za dronove do arhitektonskih modela, tehnologija omogućava brzu iteraciju i isporuku usluga zasnovanu na povjerenju.', 'Technology', TRUE),
  134. ('choosing-between-fdm-and-sla', 'FDM vs SLA: Which one to choose?', 'Choosing the right tech for your specific project.', 'Choosing between FDM and SLA depends on your project goals. FDM (Fused Deposition Modeling) is best for functional, durable parts made from industrial plastics.\n\nSLA (Stereolithography), on the other hand, offers unmatched detail and surface finish, making it ideal for miniatures, jewelry prototypes, and dental models. In this article, we dive deep into the pros and cons of each method.', 'FDM против SLA: что выбрать?', 'Выбор правильной технологии для вашего конкретного проекта.', 'Выбор между FDM и SLA зависит от целей вашего проекта. FDM (послойное наплавление) лучше всего подходит для функциональных, долговечных деталей из промышленных пластиков.\n\nSLA (стереолитография), с другой стороны, предлагает непревзойденную детализацию и чистоту поверхности, что делает устройство идеальным для миниатюр, прототипов ювелирных изделий и стоматологических моделей. В этой статье мы подробно рассмотрим плюсы и минусы каждого метода.', 'FDM protiv SLA: Šta odabrati?', 'Odabir prave tehnologije za vaš specifični projekat.', 'Odabir između FDM i SLA zavisi od ciljeva vašeg projekta. FDM (topljenje plastike) je najbolji za funkcionalne, izdržljive djelove napravljene od industrijske plastike.\n\nSLA (stereolitografija), s druge strane, nudi neprevaziđenu detaljnost i kvalitet površine, što ga čini idealnim za minijature, prototipove nakita i stomatološke modele. U ovom članku duboko zaranjamo u prednosti i mane svake metode.', 'Technology', TRUE);
  135. -- Default Admin User
  136. INSERT INTO users (email, password_hash, first_name, last_name, role) VALUES
  137. ('admin@radionica3d.com', '$2b$12$cXGLw0yUqlPMxnaDIxVuU.IdKeeTwTMHyuu.a/hKh6BAGwqQLNyxy', 'Admin', 'Root', 'admin');