9f54bc3ab1
Phase 4.1 — Role Hierarchy:
- UserRole enum: add global_admin (platform operator) + tenant_admin
(per-tenant admin); keep legacy 'admin' for backward compat
- Role sets: ADMIN_ROLES, TENANT_ADMIN_ROLES, PM_ROLES, RLS_BYPASS_ROLES
- New auth guards: require_global_admin(), require_tenant_admin_or_above(),
require_pm_or_above(), is_admin(), is_privileged()
- Legacy require_admin / require_admin_or_pm now check both old+new roles
- Migration 049: ADD VALUE global_admin + tenant_admin with AUTOCOMMIT
workaround; backfills admin → global_admin
- Seed: new admin users created with global_admin role
Phase 4.3 — RLS bypass updated for global_admin in get_db + set_tenant_context
Phase 4.4 — Tenant Feature Flags:
- Migration 050: tenant_config JSONB on tenants table
- Tenant model: tenant_config field + get_config() accessor
- Defaults: max_concurrent_renders=3, fallback_material, invoice_prefix etc.
Phase 5.1 — Fallback Material:
- blender_render.py: replace PALETTE_LINEAR/PALETTE_HEX/_assign_palette_material
with _assign_failed_material() → SCHAEFFLER_059999_FailedMaterial (magenta)
- Unmatched parts now logged explicitly before rendering
Phase 5.2 — Remove EEVEE fallback:
- render_blender.py: EEVEE→Cycles silent retry removed; hard failure on EEVEE error
Phase 5.3 — Remove Blender version check:
- render_blender.py: deleted MIN_BLENDER_VERSION = (5, 0, 1) constant
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
185 lines
7.8 KiB
Python
185 lines
7.8 KiB
Python
"""Seed database with 7 Schaeffler product category templates."""
|
||
import asyncio
|
||
import uuid
|
||
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine, async_sessionmaker
|
||
from sqlalchemy import select
|
||
|
||
STANDARD_FIELDS = {
|
||
"0": {"label": "Ebene1", "required": True},
|
||
"1": {"label": "Ebene2", "required": True},
|
||
"2": {"label": "Baureihe", "required": True},
|
||
"3": {"label": "PIM-ID (Klasse)", "required": False},
|
||
"4": {"label": "Produkt (Baureihe)", "required": False},
|
||
"5": {"label": "[Separator]", "required": False, "skip": True},
|
||
"6": {"label": "Gewähltes Produkt", "required": True},
|
||
"7": {"label": "Name CAD-Modell", "required": True},
|
||
"8": {"label": "Gewünschte Bildnummer", "required": False},
|
||
"9": {"label": "Lagertyp", "required": False},
|
||
"10": {"label": "Medias-Rendering", "required": False},
|
||
}
|
||
|
||
TEMPLATES = [
|
||
{
|
||
"name": "Tapered Roller Bearings (TRB)",
|
||
"category_key": "TRB",
|
||
"description": "Kegelrollenlager – Tapered roller bearings",
|
||
"standard_fields": STANDARD_FIELDS,
|
||
"component_schema": {
|
||
"pairs": [
|
||
{"component_type": "Innenring / Inner ring", "required": False},
|
||
{"component_type": "Innenring / Inner ring 2", "required": False},
|
||
{"component_type": "Innenring / Inner ring 3", "required": False},
|
||
{"component_type": "Außenring / Outer ring", "required": False},
|
||
{"component_type": "Außenring / Outer ring 2", "required": False},
|
||
{"component_type": "Außenring / Outer ring 3", "required": False},
|
||
{"component_type": "Außenring / Outer ring 4", "required": False},
|
||
{"component_type": "Käfig / Cage", "required": False},
|
||
{"component_type": "Wälzkörper / Rolling Element", "required": False},
|
||
{"component_type": "Dichtungskern/Dichtungsträger", "required": False},
|
||
{"component_type": "Dichtung Außen / Dichtlippe", "required": False},
|
||
]
|
||
},
|
||
},
|
||
{
|
||
"name": "Kugellager (Ball Bearings)",
|
||
"category_key": "Kugellager",
|
||
"description": "Kugellager – Ball bearings",
|
||
"standard_fields": STANDARD_FIELDS,
|
||
"component_schema": {
|
||
"pairs": [
|
||
{"component_type": "Innenring / Inner ring", "required": False},
|
||
{"component_type": "Außenring / Outer ring", "required": False},
|
||
{"component_type": "Wälzkörper / Rolling Element", "required": True},
|
||
{"component_type": "Käfig / Cage", "required": False},
|
||
{"component_type": "Dichtungskern/Dichtungsträger", "required": False},
|
||
{"component_type": "Axial - WS", "required": False},
|
||
{"component_type": "Axial - GS", "required": False},
|
||
]
|
||
},
|
||
},
|
||
{
|
||
"name": "Gleitlager (Plain Bearings)",
|
||
"category_key": "Gleitlager",
|
||
"description": "Gleitlager – Plain / sliding bearings",
|
||
"standard_fields": STANDARD_FIELDS,
|
||
"component_schema": {
|
||
"pairs": [
|
||
{"component_type": "Innenring / Inner ring", "required": False},
|
||
{"component_type": "Außenring / Outer ring", "required": False},
|
||
{"component_type": "Gehause / Housing", "required": False},
|
||
{"component_type": "Sliding Layer", "required": False},
|
||
{"component_type": "Dichtungsträger / Sealing carrier", "required": False},
|
||
{"component_type": "Dichtlippe / Sealing lip", "required": False},
|
||
]
|
||
},
|
||
},
|
||
{
|
||
"name": "Spherical / Toroidal Roller Bearings (SRB/TORB)",
|
||
"category_key": "SRB_TORB",
|
||
"description": "Pendelrollenlager / Toroidalrollenlager – SRB and TORB bearings",
|
||
"standard_fields": STANDARD_FIELDS,
|
||
"component_schema": {
|
||
"pairs": [
|
||
{"component_type": "Innenring / Inner ring", "required": False},
|
||
{"component_type": "Außenring / Outer ring", "required": False},
|
||
{"component_type": "Käfig / Cage", "required": False},
|
||
{"component_type": "Wälzkörper / Rolling element", "required": False},
|
||
{"component_type": "Bordscheibe IR / Loose Lip IR", "required": False},
|
||
{"component_type": "Dichtungsträger / Sealing carrier", "required": False},
|
||
]
|
||
},
|
||
},
|
||
{
|
||
"name": "Cylindrical Roller Bearings (CRB)",
|
||
"category_key": "CRB",
|
||
"description": "Zylinderrollenlager – Cylindrical roller bearings",
|
||
"standard_fields": STANDARD_FIELDS,
|
||
"component_schema": {
|
||
"pairs": [
|
||
{"component_type": "Innenring", "required": False},
|
||
{"component_type": "Außenring", "required": False},
|
||
{"component_type": "Rollen", "required": False},
|
||
{"component_type": "Käfig", "required": False},
|
||
{"component_type": "Dichtung", "required": False},
|
||
{"component_type": "Halteringe", "required": False},
|
||
{"component_type": "Bordscheibe", "required": False},
|
||
]
|
||
},
|
||
},
|
||
{
|
||
"name": "Linear Guide Rails",
|
||
"category_key": "Linear_schiene",
|
||
"description": "Linearsysteme – Linear guide rail systems",
|
||
"standard_fields": STANDARD_FIELDS,
|
||
"component_schema": {
|
||
"pairs": [
|
||
{"component_type": "Rail", "required": True},
|
||
]
|
||
},
|
||
},
|
||
{
|
||
"name": "End Plates (Anschlagplatten)",
|
||
"category_key": "Anschlagplatten",
|
||
"description": "Anschlagplatten – End plates for guide rails",
|
||
"standard_fields": STANDARD_FIELDS,
|
||
"component_schema": {
|
||
"pairs": [
|
||
{"component_type": "Platte / Plate", "required": True},
|
||
{"component_type": "Schraube / Screw", "required": False},
|
||
{"component_type": "Nut BZ", "required": False},
|
||
]
|
||
},
|
||
},
|
||
]
|
||
|
||
|
||
async def seed(db_url: str, admin_email: str = "admin@schaeffler.com", admin_password: str = "Admin1234!"):
|
||
from app.models.template import Template
|
||
from app.models.user import User, UserRole
|
||
from app.utils.auth import hash_password
|
||
|
||
engine = create_async_engine(db_url, echo=False)
|
||
session_factory = async_sessionmaker(engine, expire_on_commit=False)
|
||
|
||
async with session_factory() as session:
|
||
# Seed templates
|
||
for tpl_data in TEMPLATES:
|
||
result = await session.execute(
|
||
select(Template).where(Template.category_key == tpl_data["category_key"])
|
||
)
|
||
existing = result.scalar_one_or_none()
|
||
if not existing:
|
||
tpl = Template(**tpl_data)
|
||
session.add(tpl)
|
||
print(f" + Template: {tpl_data['category_key']}")
|
||
else:
|
||
print(f" ~ Template already exists: {tpl_data['category_key']}")
|
||
|
||
# Seed admin user
|
||
result = await session.execute(select(User).where(User.email == admin_email))
|
||
if not result.scalar_one_or_none():
|
||
admin = User(
|
||
email=admin_email,
|
||
password_hash=hash_password(admin_password),
|
||
role=UserRole.global_admin,
|
||
full_name="Schaeffler Admin",
|
||
)
|
||
session.add(admin)
|
||
print(f" + Admin user: {admin_email}")
|
||
else:
|
||
print(f" ~ Admin user already exists: {admin_email}")
|
||
|
||
await session.commit()
|
||
await engine.dispose()
|
||
print("Seed complete.")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
import sys
|
||
import os
|
||
|
||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
|
||
from app.config import settings
|
||
|
||
asyncio.run(seed(settings.database_url))
|