refactor: rebrand project to HartOMat
This commit is contained in:
@@ -1014,9 +1014,9 @@ async def get_dashboard_stats(
|
||||
if isinstance(entry, dict) and entry.get("material"):
|
||||
all_mat_names.add(entry["material"])
|
||||
|
||||
# Library materials (name starts with SCHAEFFLER_)
|
||||
# Library materials (name starts with HARTOMAT_)
|
||||
lib_count_result = await db.execute(
|
||||
select(func.count(Material.id)).where(Material.name.like("SCHAEFFLER_%"))
|
||||
select(func.count(Material.id)).where(Material.name.like("HARTOMAT_%"))
|
||||
)
|
||||
library_material_count = lib_count_result.scalar() or 0
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ async def get_material_pbr_map(db: AsyncSession = Depends(get_db)):
|
||||
}
|
||||
|
||||
# Also index by aliases so frontend can look up by raw Excel names
|
||||
# (e.g. "Steel--Stahl" → same PBR as "SCHAEFFLER_010101_Steel-Bare")
|
||||
# (e.g. "Steel--Stahl" → same PBR as "HARTOMAT_010101_Steel-Bare")
|
||||
# Bypass RLS — this is public data and aliases may have NULL tenant_id
|
||||
if pbr_map:
|
||||
await db.execute(text("SET LOCAL app.current_tenant_id = 'bypass'"))
|
||||
|
||||
@@ -23,7 +23,7 @@ class MaterialOut(BaseModel):
|
||||
name: str
|
||||
description: str | None
|
||||
source: str
|
||||
schaeffler_code: int | None = None
|
||||
hartomat_code: int | None = None
|
||||
created_by_name: str | None = None
|
||||
aliases: list[str] = []
|
||||
created_at: datetime
|
||||
@@ -42,7 +42,7 @@ class MaterialCreate(BaseModel):
|
||||
name: str
|
||||
description: str | None = None
|
||||
source: str = "manual"
|
||||
schaeffler_code: int | None = None
|
||||
hartomat_code: int | None = None
|
||||
|
||||
|
||||
class MaterialUpdate(BaseModel):
|
||||
@@ -64,7 +64,7 @@ def _to_out(mat: Material) -> MaterialOut:
|
||||
name=mat.name,
|
||||
description=mat.description,
|
||||
source=mat.source,
|
||||
schaeffler_code=mat.schaeffler_code,
|
||||
hartomat_code=mat.hartomat_code,
|
||||
created_by_name=creator_name,
|
||||
aliases=alias_names,
|
||||
created_at=mat.created_at,
|
||||
@@ -94,9 +94,9 @@ async def get_next_code(
|
||||
range_end = prefix_int + 99
|
||||
|
||||
result = await db.execute(
|
||||
select(func.max(Material.schaeffler_code)).where(
|
||||
Material.schaeffler_code >= range_start,
|
||||
Material.schaeffler_code <= range_end,
|
||||
select(func.max(Material.hartomat_code)).where(
|
||||
Material.hartomat_code >= range_start,
|
||||
Material.hartomat_code <= range_end,
|
||||
)
|
||||
)
|
||||
max_code = result.scalar_one_or_none()
|
||||
@@ -113,16 +113,16 @@ async def get_next_code(
|
||||
}
|
||||
|
||||
|
||||
@router.post("/seed-schaeffler")
|
||||
async def seed_schaeffler_materials(
|
||||
@router.post("/seed-hartomat")
|
||||
async def seed_hartomat_materials(
|
||||
user: User = Depends(require_admin_or_pm),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
"""Bulk-create the 35 standard Schaeffler materials. Skips existing by name."""
|
||||
from app.data.schaeffler_materials import SCHAEFFLER_MATERIALS
|
||||
"""Bulk-create the 35 standard HartOMat materials. Skips existing by name."""
|
||||
from app.data.hartomat_materials import HARTOMAT_MATERIALS
|
||||
|
||||
inserted = 0
|
||||
for mat_data in SCHAEFFLER_MATERIALS:
|
||||
for mat_data in HARTOMAT_MATERIALS:
|
||||
existing = await db.execute(
|
||||
select(Material).where(Material.name == mat_data["name"])
|
||||
)
|
||||
@@ -132,14 +132,14 @@ async def seed_schaeffler_materials(
|
||||
name=mat_data["name"],
|
||||
description=mat_data["description"],
|
||||
source=mat_data["source"],
|
||||
schaeffler_code=mat_data["schaeffler_code"],
|
||||
hartomat_code=mat_data["hartomat_code"],
|
||||
created_by=user.id,
|
||||
)
|
||||
db.add(mat)
|
||||
inserted += 1
|
||||
|
||||
await db.commit()
|
||||
return {"inserted": inserted, "total": len(SCHAEFFLER_MATERIALS)}
|
||||
return {"inserted": inserted, "total": len(HARTOMAT_MATERIALS)}
|
||||
|
||||
|
||||
@router.post("/seed-aliases")
|
||||
@@ -273,7 +273,7 @@ async def create_material(
|
||||
name=body.name,
|
||||
description=body.description,
|
||||
source=body.source,
|
||||
schaeffler_code=body.schaeffler_code,
|
||||
hartomat_code=body.hartomat_code,
|
||||
created_by=user.id,
|
||||
)
|
||||
db.add(mat)
|
||||
|
||||
@@ -475,8 +475,8 @@ async def scale_workers(
|
||||
compose_file = os.path.join(compose_dir, "docker-compose.yml")
|
||||
# Derive project name from compose dir on host (directory name = project name).
|
||||
# Inside the container the compose file is at /compose, but the host project
|
||||
# dir name determines the container naming prefix (e.g. "schaefflerautomat").
|
||||
compose_project = os.environ.get("COMPOSE_PROJECT_NAME", "schaefflerautomat")
|
||||
# dir name determines the container naming prefix (e.g. "hartomat").
|
||||
compose_project = os.environ.get("COMPOSE_PROJECT_NAME", "hartomat")
|
||||
|
||||
def _scale() -> subprocess.CompletedProcess:
|
||||
return subprocess.run(
|
||||
|
||||
@@ -4,9 +4,9 @@ from typing import Optional
|
||||
|
||||
class Settings(BaseSettings):
|
||||
# Database
|
||||
postgres_db: str = "schaeffler"
|
||||
postgres_user: str = "schaeffler"
|
||||
postgres_password: str = "schaeffler"
|
||||
postgres_db: str = "hartomat"
|
||||
postgres_user: str = "hartomat"
|
||||
postgres_password: str = "hartomat"
|
||||
postgres_host: str = "localhost"
|
||||
postgres_port: int = 5432
|
||||
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
"""HartOMat standard materials — single source of truth.
|
||||
|
||||
Naming convention: HARTOMAT_[TypeCode(2)][SubType(2)][Consecutive(2)]_[Name-Parts-Dashed]
|
||||
Type codes: 01=Metals, 02=Coatings, 03=Non-metals, 04=Compounds, 05=Misc
|
||||
"""
|
||||
|
||||
HARTOMAT_MATERIALS: list[dict] = [
|
||||
# --- 01 Metals ---
|
||||
{"name": "HARTOMAT_010101_Steel-Bare", "description": "Stahl / Stahl, glänzend / Stahl, konserviert", "hartomat_code": 10101, "source": "hartomat_standard"},
|
||||
{"name": "HARTOMAT_010102_Steel-Burnished", "description": "Stahl, brüniert", "hartomat_code": 10102, "source": "hartomat_standard"},
|
||||
{"name": "HARTOMAT_010103_Steel-Galvanized", "description": "Stahl, verzinkt", "hartomat_code": 10103, "source": "hartomat_standard"},
|
||||
{"name": "HARTOMAT_010104_Steel-Casted", "description": "Stahl Körnung", "hartomat_code": 10104, "source": "hartomat_standard"},
|
||||
{"name": "HARTOMAT_010105_Steel-Plate", "description": "Stahlblech", "hartomat_code": 10105, "source": "hartomat_standard"},
|
||||
{"name": "HARTOMAT_010201_Niro", "description": "Niro", "hartomat_code": 10201, "source": "hartomat_standard"},
|
||||
{"name": "HARTOMAT_010301_Tin", "description": "MU-Stahl, Zinnüberzug / MX-Stahl, Zinnüberzug", "hartomat_code": 10301, "source": "hartomat_standard"},
|
||||
{"name": "HARTOMAT_010401_Aluminium", "description": "Aluminium", "hartomat_code": 10401, "source": "hartomat_standard"},
|
||||
{"name": "HARTOMAT_010501_Brass", "description": "Messing", "hartomat_code": 10501, "source": "hartomat_standard"},
|
||||
{"name": "HARTOMAT_010601_Bronze", "description": "MU-B, Bronze", "hartomat_code": 10601, "source": "hartomat_standard"},
|
||||
# --- 02 Coatings ---
|
||||
{"name": "HARTOMAT_020101_Durotect-Blue", "description": "Stahl, Durotect CMT", "hartomat_code": 20101, "source": "hartomat_standard"},
|
||||
{"name": "HARTOMAT_020102_Durotect-Black", "description": "Stahl, Durotect M", "hartomat_code": 20102, "source": "hartomat_standard"},
|
||||
{"name": "HARTOMAT_020201_Coat-Black", "description": "", "hartomat_code": 20201, "source": "hartomat_standard"},
|
||||
# --- 03 Non-metals ---
|
||||
{"name": "HARTOMAT_030101_Elastomer-Brown", "description": "Elastomer, braun", "hartomat_code": 30101, "source": "hartomat_standard"},
|
||||
{"name": "HARTOMAT_030102_Elastomer-Green", "description": "Elastomer, grün", "hartomat_code": 30102, "source": "hartomat_standard"},
|
||||
{"name": "HARTOMAT_030103_Elastomer-Black", "description": "Elastomer, schwarz", "hartomat_code": 30103, "source": "hartomat_standard"},
|
||||
{"name": "HARTOMAT_030201_Plastic-Brown", "description": "Kunststoff, braun", "hartomat_code": 30201, "source": "hartomat_standard"},
|
||||
{"name": "HARTOMAT_030202_Plastic-Green", "description": "Kunststoff, grün", "hartomat_code": 30202, "source": "hartomat_standard"},
|
||||
{"name": "HARTOMAT_030203_Plastic-Black", "description": "Kunststoff, schwarz", "hartomat_code": 30203, "source": "hartomat_standard"},
|
||||
{"name": "HARTOMAT_030204_Plastic-Blue", "description": "Kunststoff, blau", "hartomat_code": 30204, "source": "hartomat_standard"},
|
||||
{"name": "HARTOMAT_030205_Plastic-White", "description": "Kunststoff, weiß", "hartomat_code": 30205, "source": "hartomat_standard"},
|
||||
{"name": "HARTOMAT_030301_Plastic-Clear", "description": "Kunststoff, durchsichtig", "hartomat_code": 30301, "source": "hartomat_standard"},
|
||||
{"name": "HARTOMAT_030302_Plastic-Translucent-White", "description": "", "hartomat_code": 30302, "source": "hartomat_standard"},
|
||||
{"name": "HARTOMAT_030401_TPU-Blue", "description": "TPU, blau", "hartomat_code": 30401, "source": "hartomat_standard"},
|
||||
{"name": "HARTOMAT_030501_Ceramic-Black", "description": "Keramik, schwarz", "hartomat_code": 30501, "source": "hartomat_standard"},
|
||||
# --- 04 Compounds ---
|
||||
{"name": "HARTOMAT_040101_E40", "description": "E40", "hartomat_code": 40101, "source": "hartomat_standard"},
|
||||
{"name": "HARTOMAT_040102_E50", "description": "E50", "hartomat_code": 40102, "source": "hartomat_standard"},
|
||||
{"name": "HARTOMAT_040201_Elgoglide", "description": "Elgoglide", "hartomat_code": 40201, "source": "hartomat_standard"},
|
||||
{"name": "HARTOMAT_040202_Elgotex", "description": "Elgotex, schwarz", "hartomat_code": 40202, "source": "hartomat_standard"},
|
||||
{"name": "HARTOMAT_040301_PTFE-Niro-Compound", "description": "PTFE-Compound, Niro-Verbund", "hartomat_code": 40301, "source": "hartomat_standard"},
|
||||
{"name": "HARTOMAT_040302_PTFE-Foil", "description": "PTFE-Folie", "hartomat_code": 40302, "source": "hartomat_standard"},
|
||||
{"name": "HARTOMAT_040303_PTFE-Compound-Black", "description": "PTFE-Verbund, schwarz", "hartomat_code": 40303, "source": "hartomat_standard"},
|
||||
{"name": "HARTOMAT_040304_PTFE-Compound-Orange", "description": "PTFE-Verbundwerkstoff", "hartomat_code": 40304, "source": "hartomat_standard"},
|
||||
{"name": "HARTOMAT_040305_GFK-PTFE-Compound", "description": "GFK+PTFE Verbundwerkstoff, schwarz / TPU, schwarz", "hartomat_code": 40305, "source": "hartomat_standard"},
|
||||
# --- 05 Misc ---
|
||||
{"name": "HARTOMAT_059999_FailedMaterial", "description": "", "hartomat_code": 59999, "source": "hartomat_standard"},
|
||||
]
|
||||
@@ -1,9 +1,9 @@
|
||||
"""Material alias seed data — derived from naming_scheme.xlsx Materialmapping sheet.
|
||||
|
||||
Each entry maps a SCHAEFFLER library material name to its known aliases:
|
||||
Each entry maps a HARTOMAT library material name to its known aliases:
|
||||
- German description (Col A from Materialmapping)
|
||||
- Intermediate identifier (Col B, e.g. "Steel_black_oxided--Stahl_brueniert")
|
||||
- Schaeffler code as string (e.g. "10102")
|
||||
- HartOMat code as string (e.g. "10102")
|
||||
- German variants (singular/plural, abbreviations, industry terms, DIN/EN standards)
|
||||
- English equivalents commonly used in German engineering contexts
|
||||
"""
|
||||
@@ -13,7 +13,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
# --- 01 Metals ---
|
||||
# =====================================================================
|
||||
{
|
||||
"material_name": "SCHAEFFLER_010101_Steel-Bare",
|
||||
"material_name": "HARTOMAT_010101_Steel-Bare",
|
||||
"aliases": [
|
||||
"Stahl",
|
||||
"Stahl, glänzend",
|
||||
@@ -66,7 +66,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
"material_name": "SCHAEFFLER_010102_Steel-Burnished",
|
||||
"material_name": "HARTOMAT_010102_Steel-Burnished",
|
||||
"aliases": [
|
||||
"Stahl, brüniert",
|
||||
"Steel_black_oxided--Stahl_brueniert",
|
||||
@@ -94,7 +94,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
"material_name": "SCHAEFFLER_010103_Steel-Galvanized",
|
||||
"material_name": "HARTOMAT_010103_Steel-Galvanized",
|
||||
"aliases": [
|
||||
"Stahl, verzinkt",
|
||||
"Steel_galvanized--Stahl_verzinkt",
|
||||
@@ -130,7 +130,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
"material_name": "SCHAEFFLER_010104_Steel-Casted",
|
||||
"material_name": "HARTOMAT_010104_Steel-Casted",
|
||||
"aliases": [
|
||||
"Stahl Körnung",
|
||||
"Guss",
|
||||
@@ -169,7 +169,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
"material_name": "SCHAEFFLER_010105_Steel-Plate",
|
||||
"material_name": "HARTOMAT_010105_Steel-Plate",
|
||||
"aliases": [
|
||||
"Stahlblech",
|
||||
"Steel_sheet--Stahlblech",
|
||||
@@ -204,7 +204,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
"material_name": "SCHAEFFLER_010201_Niro",
|
||||
"material_name": "HARTOMAT_010201_Niro",
|
||||
"aliases": [
|
||||
"Niro",
|
||||
"Steel_stainless--Niro",
|
||||
@@ -248,7 +248,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
"material_name": "SCHAEFFLER_010301_Tin",
|
||||
"material_name": "HARTOMAT_010301_Tin",
|
||||
"aliases": [
|
||||
"Zinnüberzug",
|
||||
"Tin--Zinn",
|
||||
@@ -278,7 +278,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
"material_name": "SCHAEFFLER_010401_Aluminium",
|
||||
"material_name": "HARTOMAT_010401_Aluminium",
|
||||
"aliases": [
|
||||
"Aluminium",
|
||||
"Aluminium--Aluminium",
|
||||
@@ -319,7 +319,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
"material_name": "SCHAEFFLER_010501_Brass",
|
||||
"material_name": "HARTOMAT_010501_Brass",
|
||||
"aliases": [
|
||||
"Messing",
|
||||
"Brass--Messing",
|
||||
@@ -351,7 +351,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
"material_name": "SCHAEFFLER_010601_Bronze",
|
||||
"material_name": "HARTOMAT_010601_Bronze",
|
||||
"aliases": [
|
||||
"MU-B; Bronze",
|
||||
"Bronze",
|
||||
@@ -393,7 +393,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
# --- 02 Coatings ---
|
||||
# =====================================================================
|
||||
{
|
||||
"material_name": "SCHAEFFLER_020101_Durotect-Blue",
|
||||
"material_name": "HARTOMAT_020101_Durotect-Blue",
|
||||
"aliases": [
|
||||
"Stahl, Durotect CMT",
|
||||
"Durotect_CMT--Durotect_CMT",
|
||||
@@ -414,7 +414,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
"material_name": "SCHAEFFLER_020102_Durotect-Black",
|
||||
"material_name": "HARTOMAT_020102_Durotect-Black",
|
||||
"aliases": [
|
||||
"Stahl, Durotect M",
|
||||
"Stahl; Durotect M",
|
||||
@@ -435,7 +435,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
"material_name": "SCHAEFFLER_020201_Coat-Black",
|
||||
"material_name": "HARTOMAT_020201_Coat-Black",
|
||||
"aliases": [
|
||||
"Stahl, schwarz",
|
||||
"Steel_coated_black--Stahl_beschichtet_schwarz",
|
||||
@@ -468,7 +468,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
# --- 03 Non-metals ---
|
||||
# =====================================================================
|
||||
{
|
||||
"material_name": "SCHAEFFLER_030101_Elastomer-Brown",
|
||||
"material_name": "HARTOMAT_030101_Elastomer-Brown",
|
||||
"aliases": [
|
||||
"Elastomer, braun",
|
||||
"Elastomer_brown--Elastomer_braun",
|
||||
@@ -493,7 +493,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
"material_name": "SCHAEFFLER_030102_Elastomer-Green",
|
||||
"material_name": "HARTOMAT_030102_Elastomer-Green",
|
||||
"aliases": [
|
||||
"Elastomer, grün",
|
||||
"Elastomer_green--Elastomer_gruen",
|
||||
@@ -518,7 +518,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
"material_name": "SCHAEFFLER_030103_Elastomer-Black",
|
||||
"material_name": "HARTOMAT_030103_Elastomer-Black",
|
||||
"aliases": [
|
||||
"Elastomer, schwarz",
|
||||
"Eslastomer_black--Elastomer_schwarz",
|
||||
@@ -557,7 +557,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
"material_name": "SCHAEFFLER_030201_Plastic-Brown",
|
||||
"material_name": "HARTOMAT_030201_Plastic-Brown",
|
||||
"aliases": [
|
||||
"Kunststoff, braun",
|
||||
"Plastic_brown--Kunststoff_braun",
|
||||
@@ -585,7 +585,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
"material_name": "SCHAEFFLER_030202_Plastic-Green",
|
||||
"material_name": "HARTOMAT_030202_Plastic-Green",
|
||||
"aliases": [
|
||||
"Kunststoff, grün",
|
||||
"Plastic_green--Kunststoff_gruen",
|
||||
@@ -612,7 +612,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
"material_name": "SCHAEFFLER_030203_Plastic-Black",
|
||||
"material_name": "HARTOMAT_030203_Plastic-Black",
|
||||
"aliases": [
|
||||
"Kunststoff, schwarz",
|
||||
"Plastic_black--Kunststoff_schwarz",
|
||||
@@ -642,7 +642,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
"material_name": "SCHAEFFLER_030204_Plastic-Blue",
|
||||
"material_name": "HARTOMAT_030204_Plastic-Blue",
|
||||
"aliases": [
|
||||
"Kunststoff, blau",
|
||||
"Plastic_blue--Kunststoff_blau",
|
||||
@@ -668,7 +668,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
"material_name": "SCHAEFFLER_030205_Plastic-White",
|
||||
"material_name": "HARTOMAT_030205_Plastic-White",
|
||||
"aliases": [
|
||||
"Kunststoff, weiß",
|
||||
"Plastic_white--Kunststoff_weiss",
|
||||
@@ -702,7 +702,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
"material_name": "SCHAEFFLER_030301_Plastic-Clear",
|
||||
"material_name": "HARTOMAT_030301_Plastic-Clear",
|
||||
"aliases": [
|
||||
"Kunststoff, durchsichtig",
|
||||
"Plastic_clear--Kunststoff_durchsichtig",
|
||||
@@ -738,7 +738,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
"material_name": "SCHAEFFLER_030302_Plastic-Translucent-White",
|
||||
"material_name": "HARTOMAT_030302_Plastic-Translucent-White",
|
||||
"aliases": [
|
||||
"Plastic_translucent_white--Kunststoff_transluzent_weiss",
|
||||
"30302",
|
||||
@@ -769,7 +769,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
"material_name": "SCHAEFFLER_030401_TPU-Blue",
|
||||
"material_name": "HARTOMAT_030401_TPU-Blue",
|
||||
"aliases": [
|
||||
"TPU, blau",
|
||||
"Elastomer_blue--Elastomer_blau",
|
||||
@@ -798,7 +798,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
"material_name": "SCHAEFFLER_030501_Ceramic-Black",
|
||||
"material_name": "HARTOMAT_030501_Ceramic-Black",
|
||||
"aliases": [
|
||||
"Keramik, schwarz",
|
||||
"Ceramics_black--Keramik_schwarz",
|
||||
@@ -834,7 +834,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
# --- 04 Compounds ---
|
||||
# =====================================================================
|
||||
{
|
||||
"material_name": "SCHAEFFLER_040101_E40",
|
||||
"material_name": "HARTOMAT_040101_E40",
|
||||
"aliases": [
|
||||
"E40",
|
||||
"E40--E40",
|
||||
@@ -851,7 +851,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
"material_name": "SCHAEFFLER_040102_E50",
|
||||
"material_name": "HARTOMAT_040102_E50",
|
||||
"aliases": [
|
||||
"E50",
|
||||
"E50--E50",
|
||||
@@ -868,7 +868,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
"material_name": "SCHAEFFLER_040201_Elgoglide",
|
||||
"material_name": "HARTOMAT_040201_Elgoglide",
|
||||
"aliases": [
|
||||
"Elgoglide",
|
||||
"Elgoglide--Elgoglide",
|
||||
@@ -886,7 +886,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
"material_name": "SCHAEFFLER_040202_Elgotex",
|
||||
"material_name": "HARTOMAT_040202_Elgotex",
|
||||
"aliases": [
|
||||
"Elgotex, schwarz",
|
||||
"Elgotex--Elgotex",
|
||||
@@ -907,7 +907,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
"material_name": "SCHAEFFLER_040301_PTFE-Niro-Compound",
|
||||
"material_name": "HARTOMAT_040301_PTFE-Niro-Compound",
|
||||
"aliases": [
|
||||
"PTFE-Compound, Niro-Verbund",
|
||||
"PTFE_compound_stainless_steel_composite--PTFE_Compound_Niro_Verbund",
|
||||
@@ -933,7 +933,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
"material_name": "SCHAEFFLER_040302_PTFE-Foil",
|
||||
"material_name": "HARTOMAT_040302_PTFE-Foil",
|
||||
"aliases": [
|
||||
"PTFE-Folie",
|
||||
"PTFE_film--PTFE_Folie",
|
||||
@@ -962,7 +962,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
"material_name": "SCHAEFFLER_040303_PTFE-Compound-Black",
|
||||
"material_name": "HARTOMAT_040303_PTFE-Compound-Black",
|
||||
"aliases": [
|
||||
"PTFE-Verbund, schwarz",
|
||||
"PTFE_compound_black--PTFE_Verbund_schwarz",
|
||||
@@ -987,7 +987,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
"material_name": "SCHAEFFLER_040304_PTFE-Compound-Orange",
|
||||
"material_name": "HARTOMAT_040304_PTFE-Compound-Orange",
|
||||
"aliases": [
|
||||
"PTFE-Verbundwerkstoff",
|
||||
"PTFE_composite_material_orange--PTFE_Verbundwerkstoff_orange",
|
||||
@@ -1014,7 +1014,7 @@ MATERIAL_ALIAS_SEEDS: list[dict] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
"material_name": "SCHAEFFLER_040305_GFK-PTFE-Compound",
|
||||
"material_name": "HARTOMAT_040305_GFK-PTFE-Compound",
|
||||
"aliases": [
|
||||
"GFK+PTFE Verbundwerkstoff, schwarz",
|
||||
"GFK_PTFE_compound--GFK_PTFE_Verbundwerkstoff",
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
"""Schaeffler standard materials — single source of truth.
|
||||
|
||||
Naming convention: SCHAEFFLER_[TypeCode(2)][SubType(2)][Consecutive(2)]_[Name-Parts-Dashed]
|
||||
Type codes: 01=Metals, 02=Coatings, 03=Non-metals, 04=Compounds, 05=Misc
|
||||
"""
|
||||
|
||||
SCHAEFFLER_MATERIALS: list[dict] = [
|
||||
# --- 01 Metals ---
|
||||
{"name": "SCHAEFFLER_010101_Steel-Bare", "description": "Stahl / Stahl, glänzend / Stahl, konserviert", "schaeffler_code": 10101, "source": "schaeffler_standard"},
|
||||
{"name": "SCHAEFFLER_010102_Steel-Burnished", "description": "Stahl, brüniert", "schaeffler_code": 10102, "source": "schaeffler_standard"},
|
||||
{"name": "SCHAEFFLER_010103_Steel-Galvanized", "description": "Stahl, verzinkt", "schaeffler_code": 10103, "source": "schaeffler_standard"},
|
||||
{"name": "SCHAEFFLER_010104_Steel-Casted", "description": "Stahl Körnung", "schaeffler_code": 10104, "source": "schaeffler_standard"},
|
||||
{"name": "SCHAEFFLER_010105_Steel-Plate", "description": "Stahlblech", "schaeffler_code": 10105, "source": "schaeffler_standard"},
|
||||
{"name": "SCHAEFFLER_010201_Niro", "description": "Niro", "schaeffler_code": 10201, "source": "schaeffler_standard"},
|
||||
{"name": "SCHAEFFLER_010301_Tin", "description": "MU-Stahl, Zinnüberzug / MX-Stahl, Zinnüberzug", "schaeffler_code": 10301, "source": "schaeffler_standard"},
|
||||
{"name": "SCHAEFFLER_010401_Aluminium", "description": "Aluminium", "schaeffler_code": 10401, "source": "schaeffler_standard"},
|
||||
{"name": "SCHAEFFLER_010501_Brass", "description": "Messing", "schaeffler_code": 10501, "source": "schaeffler_standard"},
|
||||
{"name": "SCHAEFFLER_010601_Bronze", "description": "MU-B, Bronze", "schaeffler_code": 10601, "source": "schaeffler_standard"},
|
||||
# --- 02 Coatings ---
|
||||
{"name": "SCHAEFFLER_020101_Durotect-Blue", "description": "Stahl, Durotect CMT", "schaeffler_code": 20101, "source": "schaeffler_standard"},
|
||||
{"name": "SCHAEFFLER_020102_Durotect-Black", "description": "Stahl, Durotect M", "schaeffler_code": 20102, "source": "schaeffler_standard"},
|
||||
{"name": "SCHAEFFLER_020201_Coat-Black", "description": "", "schaeffler_code": 20201, "source": "schaeffler_standard"},
|
||||
# --- 03 Non-metals ---
|
||||
{"name": "SCHAEFFLER_030101_Elastomer-Brown", "description": "Elastomer, braun", "schaeffler_code": 30101, "source": "schaeffler_standard"},
|
||||
{"name": "SCHAEFFLER_030102_Elastomer-Green", "description": "Elastomer, grün", "schaeffler_code": 30102, "source": "schaeffler_standard"},
|
||||
{"name": "SCHAEFFLER_030103_Elastomer-Black", "description": "Elastomer, schwarz", "schaeffler_code": 30103, "source": "schaeffler_standard"},
|
||||
{"name": "SCHAEFFLER_030201_Plastic-Brown", "description": "Kunststoff, braun", "schaeffler_code": 30201, "source": "schaeffler_standard"},
|
||||
{"name": "SCHAEFFLER_030202_Plastic-Green", "description": "Kunststoff, grün", "schaeffler_code": 30202, "source": "schaeffler_standard"},
|
||||
{"name": "SCHAEFFLER_030203_Plastic-Black", "description": "Kunststoff, schwarz", "schaeffler_code": 30203, "source": "schaeffler_standard"},
|
||||
{"name": "SCHAEFFLER_030204_Plastic-Blue", "description": "Kunststoff, blau", "schaeffler_code": 30204, "source": "schaeffler_standard"},
|
||||
{"name": "SCHAEFFLER_030205_Plastic-White", "description": "Kunststoff, weiß", "schaeffler_code": 30205, "source": "schaeffler_standard"},
|
||||
{"name": "SCHAEFFLER_030301_Plastic-Clear", "description": "Kunststoff, durchsichtig", "schaeffler_code": 30301, "source": "schaeffler_standard"},
|
||||
{"name": "SCHAEFFLER_030302_Plastic-Translucent-White", "description": "", "schaeffler_code": 30302, "source": "schaeffler_standard"},
|
||||
{"name": "SCHAEFFLER_030401_TPU-Blue", "description": "TPU, blau", "schaeffler_code": 30401, "source": "schaeffler_standard"},
|
||||
{"name": "SCHAEFFLER_030501_Ceramic-Black", "description": "Keramik, schwarz", "schaeffler_code": 30501, "source": "schaeffler_standard"},
|
||||
# --- 04 Compounds ---
|
||||
{"name": "SCHAEFFLER_040101_E40", "description": "E40", "schaeffler_code": 40101, "source": "schaeffler_standard"},
|
||||
{"name": "SCHAEFFLER_040102_E50", "description": "E50", "schaeffler_code": 40102, "source": "schaeffler_standard"},
|
||||
{"name": "SCHAEFFLER_040201_Elgoglide", "description": "Elgoglide", "schaeffler_code": 40201, "source": "schaeffler_standard"},
|
||||
{"name": "SCHAEFFLER_040202_Elgotex", "description": "Elgotex, schwarz", "schaeffler_code": 40202, "source": "schaeffler_standard"},
|
||||
{"name": "SCHAEFFLER_040301_PTFE-Niro-Compound", "description": "PTFE-Compound, Niro-Verbund", "schaeffler_code": 40301, "source": "schaeffler_standard"},
|
||||
{"name": "SCHAEFFLER_040302_PTFE-Foil", "description": "PTFE-Folie", "schaeffler_code": 40302, "source": "schaeffler_standard"},
|
||||
{"name": "SCHAEFFLER_040303_PTFE-Compound-Black", "description": "PTFE-Verbund, schwarz", "schaeffler_code": 40303, "source": "schaeffler_standard"},
|
||||
{"name": "SCHAEFFLER_040304_PTFE-Compound-Orange", "description": "PTFE-Verbundwerkstoff", "schaeffler_code": 40304, "source": "schaeffler_standard"},
|
||||
{"name": "SCHAEFFLER_040305_GFK-PTFE-Compound", "description": "GFK+PTFE Verbundwerkstoff, schwarz / TPU, schwarz", "schaeffler_code": 40305, "source": "schaeffler_standard"},
|
||||
# --- 05 Misc ---
|
||||
{"name": "SCHAEFFLER_059999_FailedMaterial", "description": "", "schaeffler_code": 59999, "source": "schaeffler_standard"},
|
||||
]
|
||||
@@ -17,7 +17,7 @@ class Material(Base):
|
||||
name: Mapped[str] = mapped_column(String(200), nullable=False, unique=True)
|
||||
description: Mapped[str] = mapped_column(Text, nullable=True)
|
||||
source: Mapped[str] = mapped_column(String(20), nullable=False, default="manual")
|
||||
schaeffler_code: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
||||
hartomat_code: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
||||
created_by: Mapped[uuid.UUID | None] = mapped_column(
|
||||
UUID(as_uuid=True), ForeignKey("users.id", ondelete="SET NULL"), nullable=True
|
||||
)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Material alias resolution service.
|
||||
|
||||
Used from Celery tasks (sync context) to resolve raw material names
|
||||
(from Excel / user input) to SCHAEFFLER library material names via aliases.
|
||||
(from Excel / user input) to HARTOMAT library material names via aliases.
|
||||
|
||||
Resolution chain:
|
||||
1. Alias lookup (case-insensitive) → use alias.material.name
|
||||
@@ -31,7 +31,7 @@ def _get_engine():
|
||||
|
||||
|
||||
def resolve_material_map(raw_map: dict[str, str]) -> dict[str, str]:
|
||||
"""Resolve raw material names to SCHAEFFLER library names via aliases.
|
||||
"""Resolve raw material names to HARTOMAT library names via aliases.
|
||||
|
||||
For each value in raw_map:
|
||||
1. Alias lookup (case-insensitive) → return alias.material.name
|
||||
@@ -66,7 +66,7 @@ def resolve_material_map(raw_map: dict[str, str]) -> dict[str, str]:
|
||||
raw_lower = raw_material.lower()
|
||||
|
||||
# 1. Alias lookup first — aliases explicitly map intermediate/display names
|
||||
# to the canonical SCHAEFFLER library names
|
||||
# to the canonical HARTOMAT library names
|
||||
if raw_lower in alias_lookup:
|
||||
target = alias_lookup[raw_lower]
|
||||
logger.info("resolved '%s' → '%s' (alias match)", raw_material, target)
|
||||
@@ -147,7 +147,7 @@ async def find_unmapped_materials(
|
||||
"""Find material names that have no alias or library match.
|
||||
|
||||
Returns a list of {"raw_name": str, "suggestions": [...]} for each
|
||||
unmapped name. Suggestions are the top 5 SCHAEFFLER library materials
|
||||
unmapped name. Suggestions are the top 5 HARTOMAT library materials
|
||||
by string similarity.
|
||||
"""
|
||||
if not material_names:
|
||||
@@ -159,8 +159,8 @@ async def find_unmapped_materials(
|
||||
|
||||
# Load all materials
|
||||
mat_rows = (await db.execute(select(Material))).scalars().all()
|
||||
# Library materials have a schaeffler_code
|
||||
library_mats = [m for m in mat_rows if m.schaeffler_code is not None]
|
||||
# Library materials have a hartomat_code
|
||||
library_mats = [m for m in mat_rows if m.hartomat_code is not None]
|
||||
# All material names (case-insensitive) for exact-match check
|
||||
name_lookup: dict[str, Material] = {m.name.lower(): m for m in mat_rows}
|
||||
|
||||
@@ -179,7 +179,7 @@ async def find_unmapped_materials(
|
||||
|
||||
# 2. Exact name match with a library material → mapped
|
||||
matched_mat = name_lookup.get(raw_lower)
|
||||
if matched_mat and matched_mat.schaeffler_code is not None:
|
||||
if matched_mat and matched_mat.hartomat_code is not None:
|
||||
continue
|
||||
|
||||
# Unmapped — compute suggestions from library materials
|
||||
@@ -194,7 +194,7 @@ async def find_unmapped_materials(
|
||||
{
|
||||
"id": str(m.id),
|
||||
"name": m.name,
|
||||
"schaeffler_code": str(m.schaeffler_code),
|
||||
"hartomat_code": str(m.hartomat_code),
|
||||
}
|
||||
for _, m in scored[:5]
|
||||
]
|
||||
|
||||
@@ -235,7 +235,7 @@ def send_email_notification_stub(
|
||||
from email.mime.text import MIMEText
|
||||
msg = MIMEText(body, "plain", "utf-8")
|
||||
msg["Subject"] = subject
|
||||
msg["From"] = cfg.get("smtp_from_address") or cfg.get("smtp_user", "noreply@schaeffler.com")
|
||||
msg["From"] = cfg.get("smtp_from_address") or cfg.get("smtp_user", "noreply@hartomat.com")
|
||||
msg["To"] = to_address
|
||||
port = int(cfg.get("smtp_port", "587"))
|
||||
with smtplib.SMTP(smtp_host, port) as smtp:
|
||||
|
||||
@@ -330,7 +330,7 @@ def generate_usd_master_task(self, cad_file_id: str) -> dict:
|
||||
if part_name and raw_material:
|
||||
raw_mat_map[part_name] = raw_material
|
||||
|
||||
# Resolve raw material names to SCHAEFFLER library names via aliases
|
||||
# Resolve raw material names to HARTOMAT library names via aliases
|
||||
material_map: dict[str, str] = {}
|
||||
if raw_mat_map:
|
||||
material_map = resolve_material_map(raw_mat_map)
|
||||
|
||||
@@ -244,7 +244,7 @@ def render_order_line_task(self, order_line_id: str):
|
||||
if m.get("part_name") and m.get("material")
|
||||
}
|
||||
|
||||
# Resolve raw material names to SCHAEFFLER library names via aliases
|
||||
# Resolve raw material names to HARTOMAT library names via aliases
|
||||
from app.services.material_service import resolve_material_map
|
||||
material_map = resolve_material_map(material_map)
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ _STEP_DESCRIPTIONS: dict[StepName, str] = {
|
||||
StepName.OCC_OBJECT_EXTRACT: "Extract part objects and metadata from the STEP file using cadquery/OCC",
|
||||
StepName.OCC_GLB_EXPORT: "Convert STEP geometry to glTF/GLB via cadquery",
|
||||
StepName.GLB_BBOX: "Compute bounding-box from the exported GLB for camera framing",
|
||||
StepName.MATERIAL_MAP_RESOLVE: "Resolve raw part-material names to SCHAEFFLER library materials via alias table",
|
||||
StepName.MATERIAL_MAP_RESOLVE: "Resolve raw part-material names to HARTOMAT library materials via alias table",
|
||||
StepName.AUTO_POPULATE_MATERIALS: "Auto-create Material records for any newly discovered part names",
|
||||
StepName.BLENDER_RENDER: "Render a thumbnail PNG using Blender (Cycles or EEVEE)",
|
||||
StepName.THREEJS_RENDER: "Render a thumbnail PNG using Three.js / Playwright headless browser",
|
||||
|
||||
@@ -9,7 +9,7 @@ _DEFAULT_TENANT_CONFIG = {
|
||||
"max_concurrent_renders": 3,
|
||||
"render_engines_allowed": ["cycles", "eevee"],
|
||||
"max_order_size": 500,
|
||||
"fallback_material": "SCHAEFFLER_059999_FailedMaterial",
|
||||
"fallback_material": "HARTOMAT_059999_FailedMaterial",
|
||||
"notifications_enabled": True,
|
||||
"invoice_prefix": "INV",
|
||||
# Azure AI validation (per-tenant)
|
||||
|
||||
+3
-3
@@ -41,9 +41,9 @@ async def lifespan(app: FastAPI):
|
||||
|
||||
|
||||
app = FastAPI(
|
||||
title="Schaeffler Automat API",
|
||||
title="HartOMat API",
|
||||
version="0.1.0",
|
||||
description="Media-creation pipeline for Schaeffler CAD/bearing product orders",
|
||||
description="Media-creation pipeline for HartOMat CAD/bearing product orders",
|
||||
lifespan=lifespan,
|
||||
)
|
||||
|
||||
@@ -101,7 +101,7 @@ app.include_router(chat_router, prefix="/api")
|
||||
|
||||
@app.get("/health")
|
||||
async def health():
|
||||
return {"status": "ok", "service": "schaefflerautomat-backend"}
|
||||
return {"status": "ok", "service": "hartomat-backend"}
|
||||
|
||||
|
||||
@app.websocket("/api/ws")
|
||||
|
||||
@@ -8,12 +8,12 @@ from pathlib import Path
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
VALIDATION_PROMPT = """You are a quality control expert for Schaeffler bearing product catalog images.
|
||||
VALIDATION_PROMPT = """You are a quality control expert for HartOMat bearing product catalog images.
|
||||
|
||||
Analyze this thumbnail of a bearing/mechanical component and evaluate:
|
||||
1. Is the component orientation correct for a standard product catalog? (typically isometric view, 30° elevation, 45° rotation)
|
||||
2. Are the key features visible? (rolling elements, rings, cage if present)
|
||||
3. Does it match standard Schaeffler catalog angle conventions?
|
||||
3. Does it match standard HartOMat catalog angle conventions?
|
||||
|
||||
Respond in JSON with exactly these fields:
|
||||
{
|
||||
|
||||
@@ -18,7 +18,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
# ── System prompt ────────────────────────────────────────────────────────────
|
||||
|
||||
SYSTEM_PROMPT = """You are the Schaeffler Automat AI assistant. You help users manage their automated render pipeline for Schaeffler product images.
|
||||
SYSTEM_PROMPT = """You are the HartOMat AI assistant. You help users manage their automated render pipeline for HartOMat product images.
|
||||
|
||||
You can:
|
||||
- List and search orders and products
|
||||
@@ -39,8 +39,8 @@ RULES:
|
||||
7. Respond in the same language the user writes in.
|
||||
8. Be concise — short answers are better than long ones.
|
||||
9. When the user says "beliebig", "any", "random", "irgendein" — just pick one yourself, don't ask back.
|
||||
10. Material system: Materials have SCHAEFFLER library names (e.g. SCHAEFFLER_020101_Durotect-Blue). Common names like "Durotect", "Stahl", "Bronze" are aliases that map to these library names. When the user asks for a material by a common name, use list_materials to find the correct SCHAEFFLER name, then use that for material_override.
|
||||
11. When setting material_override, always use the full SCHAEFFLER library name (e.g. SCHAEFFLER_020101_Durotect-Blue), never the alias.
|
||||
10. Material system: Materials have HARTOMAT library names (e.g. HARTOMAT_020101_Durotect-Blue). Common names like "Durotect", "Stahl", "Bronze" are aliases that map to these library names. When the user asks for a material by a common name, use list_materials to find the correct HARTOMAT name, then use that for material_override.
|
||||
11. When setting material_override, always use the full HARTOMAT library name (e.g. HARTOMAT_020101_Durotect-Blue), never the alias.
|
||||
12. When mentioning a product, ALWAYS link to it: [ProductName](/products/UUID). When mentioning an order, link to it: [OrderNumber](/orders/UUID). This makes the response navigable.
|
||||
13. Materials exist at TWO levels: (a) product_material — materials assigned to the product's CAD parts (from STEP/Excel import, e.g. "Durotect_M", "Stahl"), and (b) material_override — a single material applied to ALL parts at render time. When user asks for a product "with Durotect material", search product_material FIRST (products that naturally have Durotect parts). Only use material_override filter if they specifically say "override" or "alle Teile in".
|
||||
14. NEVER say "no renders found" when renders DO exist. If no exact match, show the closest match and explain what's different."""
|
||||
@@ -120,7 +120,7 @@ TOOLS = [
|
||||
},
|
||||
"material_override": {
|
||||
"type": "string",
|
||||
"description": "Optional SCHAEFFLER library material name to apply to all lines.",
|
||||
"description": "Optional HARTOMAT library material name to apply to all lines.",
|
||||
"default": "",
|
||||
},
|
||||
},
|
||||
@@ -176,7 +176,7 @@ TOOLS = [
|
||||
},
|
||||
"material_name": {
|
||||
"type": "string",
|
||||
"description": "SCHAEFFLER library material name, or empty string to clear.",
|
||||
"description": "HARTOMAT library material name, or empty string to clear.",
|
||||
},
|
||||
},
|
||||
"required": ["order_id", "material_name"],
|
||||
@@ -250,7 +250,7 @@ TOOLS = [
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "list_materials",
|
||||
"description": "List available SCHAEFFLER library materials with their aliases. Use this to find the correct material name for material_override. Materials have names like SCHAEFFLER_010101_Steel-Bare. Aliases map common names (Stahl, Bronze, Durotect, etc.) to these library materials. When user asks for a material by a common name, search aliases to find the correct SCHAEFFLER library material name.",
|
||||
"description": "List available HARTOMAT library materials with their aliases. Use this to find the correct material name for material_override. Materials have names like HARTOMAT_010101_Steel-Bare. Aliases map common names (Stahl, Bronze, Durotect, etc.) to these library materials. When user asks for a material by a common name, search aliases to find the correct HARTOMAT library material name.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -671,13 +671,13 @@ async def _tool_check_materials(db: AsyncSession, tenant_id: str, user_id: str =
|
||||
async def _tool_list_materials(db: AsyncSession, tenant_id: str, query: str = "") -> str:
|
||||
"""List library materials with their aliases."""
|
||||
sql = """
|
||||
SELECT m.id, m.name, m.schaeffler_code, m.description,
|
||||
SELECT m.id, m.name, m.hartomat_code, m.description,
|
||||
COALESCE(
|
||||
(SELECT json_agg(ma.alias) FROM material_aliases ma WHERE ma.material_id = m.id),
|
||||
'[]'::json
|
||||
) AS aliases
|
||||
FROM materials m
|
||||
WHERE m.schaeffler_code IS NOT NULL
|
||||
WHERE m.hartomat_code IS NOT NULL
|
||||
"""
|
||||
params: dict = {}
|
||||
if query:
|
||||
@@ -698,7 +698,7 @@ async def _tool_list_materials(db: AsyncSession, tenant_id: str, query: str = ""
|
||||
aliases = r["aliases"] if isinstance(r["aliases"], list) else []
|
||||
materials.append({
|
||||
"name": r["name"],
|
||||
"schaeffler_code": r["schaeffler_code"],
|
||||
"hartomat_code": r["hartomat_code"],
|
||||
"description": r["description"],
|
||||
"aliases": aliases[:10], # cap to avoid token bloat
|
||||
})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
"""
|
||||
Excel parser for Schaeffler CAD order lists.
|
||||
Excel parser for HartOMat CAD order lists.
|
||||
|
||||
Supports two formats:
|
||||
|
||||
@@ -294,7 +294,7 @@ def _parse_material_mapping(wb) -> list[dict]:
|
||||
|
||||
def parse_excel(file_path: str | Path) -> ParsedExcel:
|
||||
"""
|
||||
Parse a Schaeffler order list Excel file.
|
||||
Parse a HartOMat order list Excel file.
|
||||
|
||||
Returns a ParsedExcel with all data rows extracted.
|
||||
Header-driven: finds "Ebene1" in any column within first 5 rows,
|
||||
|
||||
@@ -25,9 +25,9 @@ def build_part_colors(
|
||||
"""
|
||||
Build {part_name: material_name} for Blender rendering.
|
||||
|
||||
Returns a mapping of part name → Schaeffler material name (e.g. SCHAEFFLER_010101_Steel-Bare).
|
||||
Returns a mapping of part name → HartOMat material name (e.g. HARTOMAT_010101_Steel-Bare).
|
||||
Parts with no material assignment are omitted; Blender will use the fallback material
|
||||
(SCHAEFFLER_059999_FailedMaterial) for unrecognised parts.
|
||||
(HARTOMAT_059999_FailedMaterial) for unrecognised parts.
|
||||
|
||||
Args:
|
||||
cad_parsed_objects: List of part names from cad_file.parsed_objects["objects"].
|
||||
|
||||
@@ -3,7 +3,7 @@ from celery.schedules import crontab
|
||||
from app.config import settings
|
||||
|
||||
celery_app = Celery(
|
||||
"schaefflerautomat",
|
||||
"hartomat",
|
||||
broker=settings.redis_url,
|
||||
backend=settings.redis_url,
|
||||
include=[
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""Seed database with 7 Schaeffler product category templates."""
|
||||
"""Seed database with 7 HartOMat product category templates."""
|
||||
import asyncio
|
||||
import uuid
|
||||
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine, async_sessionmaker
|
||||
@@ -133,7 +133,7 @@ TEMPLATES = [
|
||||
]
|
||||
|
||||
|
||||
async def seed(db_url: str, admin_email: str = "admin@schaeffler.com", admin_password: str = "Admin1234!"):
|
||||
async def seed(db_url: str, admin_email: str = "admin@hartomat.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
|
||||
@@ -162,7 +162,7 @@ async def seed(db_url: str, admin_email: str = "admin@schaeffler.com", admin_pas
|
||||
email=admin_email,
|
||||
password_hash=hash_password(admin_password),
|
||||
role=UserRole.global_admin,
|
||||
full_name="Schaeffler Admin",
|
||||
full_name="HartOMat Admin",
|
||||
)
|
||||
session.add(admin)
|
||||
print(f" + Admin user: {admin_email}")
|
||||
|
||||
Reference in New Issue
Block a user