landvex: IOL v3 + Identify API + Neo4j-graf + byggpipeline
- FastAPI Identify API (port 8081) - Neo4j propertygraf (64 noder, 80 kanter) - Ingest-pipeline (Python) - Byggscript + integrationstester - Docker Compose setup
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
subjekt,predikat,objekt,niva,beskrivning
|
||||
LVX-ELN-0101,matas_fran,LVX-ELN-0103,klass,Nätstation/transformator
|
||||
LVX-ELN-0101,ansluts_med,LVX-TRP-0101,klass,Matar bl.a. belysningsnät
|
||||
LVX-ELN-0102,star_pa,LVX-TRP-0203,klass,
|
||||
LVX-ELN-0103,ansluts_med,LVX-ELN-0101,klass,Matar kabelskåpen i LV-nätet
|
||||
LVX-ELN-0104,matas_fran,LVX-ELN-0103,klass,Nätanslutning via station eller kabelskåp beroende på effekt
|
||||
LVX-ELN-0104,matas_fran,LVX-ELN-0101,klass,Nätanslutning via station eller kabelskåp beroende på effekt
|
||||
LVX-ELN-0201,matas_fran,LVX-ELN-0101,klass,Servis via kabelskåpsnätet
|
||||
LVX-ELN-0201,variant_av,LVX-ELN-0101,klass,Mätarutförande av skåpfamiljen (CDCM)
|
||||
LVX-PRK-0101,star_pa,LVX-TRP-0203,klass,
|
||||
LVX-PRK-0102,star_pa,LVX-TRP-0203,klass,
|
||||
LVX-PRK-0103,star_pa,LVX-TRP-0203,klass,
|
||||
LVX-TEL-0101,ansluts_med,LVX-TEL-0201,klass,
|
||||
LVX-TEL-0102,star_pa,LVX-TRP-0203,klass,
|
||||
LVX-TEL-0201,ansluts_med,LVX-TEL-0101,klass,Kanalisationen matar skåpen
|
||||
LVX-TRP-0101,monteras_pa,LVX-TRP-0203,klass,Fotplatta bultas mot prefabricerat eller platsgjutet fundament
|
||||
LVX-TRP-0101,matas_fran,LVX-ELN-0101,klass,Belysningsnätets kabelskåp
|
||||
LVX-TRP-0102,monteras_pa,LVX-TRP-0101,klass,Topp- eller armmontage på belysningsstolpe
|
||||
LVX-TRP-0102,ansluts_med,LVX-TRP-0204,klass,Fotocell eller smart nod i standardiserad sockel
|
||||
LVX-TRP-0103,monteras_pa,LVX-TRP-0201,klass,portalvariant → LVX-TRP-0205
|
||||
LVX-TRP-0104,ansluts_med,LVX-TRP-0105,klass,Styrs av trafiksignalskåpets styrapparat
|
||||
LVX-TRP-0104,monteras_pa,LVX-TRP-0202,klass,
|
||||
LVX-TRP-0105,ansluts_med,LVX-TRP-0104,klass,Styr signalhuvudena
|
||||
LVX-TRP-0105,matas_fran,LVX-ELN-0101,klass,
|
||||
LVX-TRP-0107,star_pa,LVX-TRP-0203,klass,
|
||||
LVX-TRP-0108,ansluts_med,LVX-ELN-0101,klass,Belysning/realtidsskylt matas från nätet
|
||||
LVX-TRP-0201,star_pa,LVX-TRP-0203,klass,
|
||||
LVX-TRP-0202,star_pa,LVX-TRP-0203,klass,
|
||||
LVX-TRP-0202,ansluts_med,LVX-TRP-0104,klass,Bär signalhuvudena
|
||||
LVX-TRP-0204,monteras_pa,LVX-TRP-0102,klass,
|
||||
LVX-TRP-0205,star_pa,LVX-TRP-0203,klass,
|
||||
LVX-TRP-0205,ansluts_med,LVX-TRP-0103,klass,Bär vägmärken/vägvisning
|
||||
LVX-TRP-0207,star_pa,LVX-TRP-0203,klass,Eller direkt nedslagen
|
||||
LVX-TRP-0208,forvaxlas_med,LVX-TRP-0107,klass,
|
||||
LVX-TRP-0209,star_pa,LVX-TRP-0203,klass,Fundamentrad
|
||||
LVX-TRP-0210,del_av,LVX-TRP-0107,klass,Avslutar räckeslinjen
|
||||
LVX-VAT-0101,monteras_pa,LVX-VAT-0201,klass,
|
||||
LVX-VAT-0101,del_av,LVX-VAT-0202,klass,Betäckningen är brunnens synliga toppkomponent
|
||||
LVX-VAT-0101,forvaxlas_med,LVX-VAT-0102,klass,"Dagvattengaller — liknande placering, annan funktion"
|
||||
LVX-VAT-0102,del_av,LVX-VAT-0203,klass,
|
||||
LVX-VAT-0102,forvaxlas_med,LVX-VAT-0101,klass,
|
||||
LVX-VAT-0201,ansluts_med,LVX-VAT-0101,klass,Ram + lock bildar betäckningen
|
||||
LVX-VAT-0201,monteras_pa,LVX-VAT-0202,klass,
|
||||
LVX-VAT-0202,ansluts_med,LVX-VAT-0201,klass,Kröns av ram + betäckning
|
||||
LVX-VAT-0203,ansluts_med,LVX-VAT-0102,klass,Gallret är intaget
|
||||
LVX-VAT-0204,forvaxlas_med,LVX-VAT-0101,klass,
|
||||
LVX-P-0000001,tillhor_klass,LVX-TRP-0102,modell,
|
||||
LVX-P-0000001,ersatts_av,LVX-P-0000002,modell,
|
||||
LVX-P-0000002,tillhor_klass,LVX-TRP-0102,modell,
|
||||
LVX-P-0000002,ersatter,LVX-P-0000001,modell,
|
||||
LVX-P-0000002,ersatts_av,LVX-P-0000003,modell,
|
||||
LVX-P-0000003,tillhor_klass,LVX-TRP-0102,modell,
|
||||
LVX-P-0000003,ersatter,LVX-P-0000002,modell,
|
||||
LVX-P-0000004,tillhor_klass,LVX-TRP-0102,modell,
|
||||
LVX-P-0000005,tillhor_klass,LVX-TRP-0102,modell,
|
||||
LVX-P-0000005,ersatts_av,LVX-P-0000006,modell,
|
||||
LVX-P-0000006,tillhor_klass,LVX-TRP-0102,modell,
|
||||
LVX-P-0000006,ersatter,LVX-P-0000005,modell,
|
||||
LVX-P-0000007,tillhor_klass,LVX-TRP-0102,modell,
|
||||
LVX-P-0000008,tillhor_klass,LVX-TRP-0103,modell,
|
||||
LVX-P-0000009,tillhor_klass,LVX-TRP-0103,modell,
|
||||
LVX-P-0000010,tillhor_klass,LVX-VAT-0101,modell,
|
||||
LVX-P-0000011,tillhor_klass,LVX-VAT-0101,modell,
|
||||
LVX-P-0000012,tillhor_klass,LVX-ELN-0101,modell,
|
||||
LVX-P-0000013,tillhor_klass,LVX-VAT-0103,modell,
|
||||
LVX-P-0000014,tillhor_klass,LVX-VAT-0103,modell,
|
||||
LVX-P-0000015,tillhor_klass,LVX-VAT-0103,modell,
|
||||
LVX-P-0000016,tillhor_klass,LVX-VAT-0103,modell,
|
||||
LVX-P-0000017,tillhor_klass,LVX-VAT-0103,modell,
|
||||
LVX-P-0000018,tillhor_klass,LVX-VAT-0101,modell,
|
||||
LVX-P-0000019,tillhor_klass,LVX-VAT-0101,modell,
|
||||
LVX-P-0000020,tillhor_klass,LVX-TRP-0107,modell,
|
||||
LVX-P-0000021,tillhor_klass,LVX-TRP-0210,modell,
|
||||
LVX-P-0000022,tillhor_klass,LVX-TRP-0105,modell,
|
||||
LVX-P-0000023,tillhor_klass,LVX-ELN-0104,modell,
|
||||
LVX-P-0000024,tillhor_klass,LVX-ELN-0104,modell,
|
||||
LVX-P-0000025,tillhor_klass,LVX-ELN-0104,modell,
|
||||
LVX-P-0000025,ersatts_av,LVX-P-0000026,modell,
|
||||
LVX-P-0000026,tillhor_klass,LVX-ELN-0104,modell,
|
||||
LVX-P-0000026,ersatter,LVX-P-0000025,modell,
|
||||
LVX-P-0000027,tillhor_klass,LVX-VAT-0201,modell,
|
||||
|
@@ -0,0 +1,36 @@
|
||||
// Landvex IOL — ladda grafen i Neo4j
|
||||
// Kör: cat db/load_graph.cypher | cypher-shell -u neo4j -p landvex2024
|
||||
|
||||
CREATE CONSTRAINT lvx_id_unique IF NOT EXISTS
|
||||
FOR (n:Objekt) REQUIRE n.lvx_id IS UNIQUE;
|
||||
|
||||
:auto LOAD CSV WITH HEADERS FROM 'file:///noder.csv' AS row
|
||||
CALL {
|
||||
WITH row
|
||||
CREATE (o:Objekt {
|
||||
lvx_id: row.lvx_id,
|
||||
posttyp: row.posttyp,
|
||||
namn_sv: row.namn_sv,
|
||||
namn_en: row.namn_en,
|
||||
doman: row.doman,
|
||||
tier: toInteger(row.tier),
|
||||
verifieringsniva: row.verifieringsniva,
|
||||
konfidens: toFloat(row.konfidens)
|
||||
})
|
||||
} IN TRANSACTIONS OF 1000 ROWS;
|
||||
|
||||
:auto LOAD CSV WITH HEADERS FROM 'file:///kanter.csv' AS row
|
||||
CALL {
|
||||
WITH row
|
||||
MATCH (a:Objekt {lvx_id: row.subjekt})
|
||||
MATCH (b:Objekt {lvx_id: row.objekt})
|
||||
CREATE (a)-[r:RELATION {
|
||||
predikat: row.predikat,
|
||||
niva: row.niva,
|
||||
beskrivning: row.beskrivning
|
||||
}]->(b)
|
||||
} IN TRANSACTIONS OF 1000 ROWS;
|
||||
|
||||
// Index för snabb sökning
|
||||
CREATE TEXT INDEX objekt_namn IF NOT EXISTS
|
||||
FOR (o:Objekt) ON (o.namn_sv, o.namn_en);
|
||||
@@ -0,0 +1,99 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Ladda Landvex IOL in i Neo4j.
|
||||
Använder neo4j-driver (pip install neo4j).
|
||||
"""
|
||||
import json
|
||||
import csv
|
||||
from pathlib import Path
|
||||
from neo4j import GraphDatabase
|
||||
|
||||
URI = "bolt://localhost:7687"
|
||||
AUTH = ("neo4j", "quixzoom_neo4j_2026")
|
||||
DATA_DIR = Path(__file__).parent.parent / "10-data"
|
||||
DB_DIR = Path(__file__).parent
|
||||
|
||||
class Neo4jLoader:
|
||||
def __init__(self):
|
||||
self.driver = GraphDatabase.driver(URI, auth=AUTH)
|
||||
|
||||
def close(self):
|
||||
self.driver.close()
|
||||
|
||||
def load_noder(self, poster):
|
||||
with self.driver.session() as session:
|
||||
session.run("CREATE CONSTRAINT lvx_id_unique IF NOT EXISTS FOR (n:Objekt) REQUIRE n.lvx_id IS UNIQUE")
|
||||
for p in poster:
|
||||
prov = p.get("proveniens", {})
|
||||
session.run("""
|
||||
MERGE (o:Objekt {lvx_id: $lvx_id})
|
||||
SET o.posttyp = $posttyp,
|
||||
o.namn_sv = $namn_sv,
|
||||
o.namn_en = $namn_en,
|
||||
o.doman = $doman,
|
||||
o.tier = $tier,
|
||||
o.verifieringsniva = $verifieringsniva,
|
||||
o.konfidens = $konfidens
|
||||
""", {
|
||||
"lvx_id": p["lvx_id"],
|
||||
"posttyp": p.get("posttyp", ""),
|
||||
"namn_sv": p.get("namn", {}).get("sv", ""),
|
||||
"namn_en": p.get("namn", {}).get("en", ""),
|
||||
"doman": p.get("doman", ""),
|
||||
"tier": p.get("tier", 0),
|
||||
"verifieringsniva": prov.get("verifieringsniva", "obekraftad"),
|
||||
"konfidens": prov.get("konfidens", 0),
|
||||
})
|
||||
print(f"Laddade {len(poster)} noder")
|
||||
|
||||
def load_kanter(self, kanter):
|
||||
with self.driver.session() as session:
|
||||
count = 0
|
||||
for k in kanter:
|
||||
if k.get("objekt_typ") != "lvx":
|
||||
continue
|
||||
session.run("""
|
||||
MATCH (a:Objekt {lvx_id: $subjekt})
|
||||
MATCH (b:Objekt {lvx_id: $objekt})
|
||||
MERGE (a)-[r:RELATION {predikat: $predikat}]->(b)
|
||||
SET r.niva = $niva,
|
||||
r.beskrivning = $beskrivning
|
||||
""", {
|
||||
"subjekt": k["subjekt"],
|
||||
"objekt": k["objekt"],
|
||||
"predikat": k["predikat"],
|
||||
"niva": k.get("niva", ""),
|
||||
"beskrivning": k.get("beskrivning", ""),
|
||||
})
|
||||
count += 1
|
||||
print(f"Laddade {count} kanter")
|
||||
|
||||
def create_index(self):
|
||||
with self.driver.session() as session:
|
||||
session.run("CREATE TEXT INDEX objekt_namn_sv IF NOT EXISTS FOR (o:Objekt) ON (o.namn_sv)")
|
||||
session.run("CREATE TEXT INDEX objekt_namn_en IF NOT EXISTS FOR (o:Objekt) ON (o.namn_en)")
|
||||
print("Index skapade")
|
||||
|
||||
def main():
|
||||
poster = []
|
||||
for fn in ("lvx-klassposter-master-v3.json", "lvx-produktmodeller-vag2.json",
|
||||
"lvx-produktmodeller-vag3.json", "lvx-produktmodeller-auto.json"):
|
||||
fp = DATA_DIR / fn
|
||||
if not fp.exists(): continue
|
||||
with open(fp, encoding="utf-8") as f:
|
||||
poster.extend(json.load(f).get("poster", []))
|
||||
|
||||
with open(DATA_DIR / "lvx-graf-kanter-v3.json", encoding="utf-8") as f:
|
||||
kanter = json.load(f)["kanter"]
|
||||
|
||||
loader = Neo4jLoader()
|
||||
try:
|
||||
loader.load_noder(poster)
|
||||
loader.load_kanter(kanter)
|
||||
loader.create_index()
|
||||
print("✅ Graf laddad i Neo4j")
|
||||
finally:
|
||||
loader.close()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,65 @@
|
||||
lvx_id,posttyp,namn_sv,namn_en,doman,tier,verifieringsniva,konfidens
|
||||
LVX-ELN-0101,objektklass,"Kabelskåp, lågspänning",LV distribution cabinet,ELN,1,kallbelagd,0.75
|
||||
LVX-ELN-0102,objektklass,Elstolpe,Utility pole,ELN,1,kallbelagd,0.8
|
||||
LVX-ELN-0103,objektklass,Nätstation/transformatorstation,Distribution substation / padmount transformer,ELN,1,kallbelagd,0.75
|
||||
LVX-ELN-0104,objektklass,Laddstation,EV charging station,ELN,1,kallbelagd,0.8
|
||||
LVX-ELN-0201,objektklass,Mätarskåp,Meter cabinet,ELN,2,kallbelagd,0.7
|
||||
LVX-PRK-0101,objektklass,Pollare,Bollard,PRK,1,kallbelagd,0.75
|
||||
LVX-PRK-0102,objektklass,Papperskorg,Litter bin,PRK,1,kallbelagd,0.7
|
||||
LVX-PRK-0103,objektklass,Cykelställ,Cycle stand,PRK,1,kallbelagd,0.75
|
||||
LVX-PRK-0201,objektklass,Parkbänk,Public bench,PRK,2,obekraftad,0.6
|
||||
LVX-TEL-0101,objektklass,Telekomskåp (fiber/koppar),Telecom street cabinet,TEL,1,kallbelagd,0.72
|
||||
LVX-TEL-0102,objektklass,Mobilmast/antennplats,Cell tower / antenna site,TEL,1,kallbelagd,0.78
|
||||
LVX-TEL-0201,objektklass,Kabelbrunn/kanalisation,Cable chamber / handhole,TEL,2,kallbelagd,0.78
|
||||
LVX-TRP-0101,objektklass,Belysningsstolpe,Lighting column,TRP,1,kallbelagd,0.78
|
||||
LVX-TRP-0102,objektklass,Vägbelysningsarmatur,Road lighting luminaire,TRP,1,kallbelagd,0.8
|
||||
LVX-TRP-0103,objektklass,Vägmärke,Road sign,TRP,1,kallbelagd,0.82
|
||||
LVX-TRP-0104,objektklass,"Trafiksignal, signalhuvud",Traffic signal head,TRP,1,kallbelagd,0.75
|
||||
LVX-TRP-0105,objektklass,Trafiksignalskåp/styrapparat,Traffic signal controller cabinet,TRP,1,kallbelagd,0.78
|
||||
LVX-TRP-0106,objektklass,Vägmarkering,Road marking,TRP,1,kallbelagd,0.75
|
||||
LVX-TRP-0107,objektklass,Vägräcke,Road safety barrier,TRP,1,kallbelagd,0.78
|
||||
LVX-TRP-0108,objektklass,Hållplatsväderskydd,Bus shelter,TRP,1,kallbelagd,0.72
|
||||
LVX-TRP-0201,objektklass,Skyltstolpe,Sign post,TRP,2,kallbelagd,0.78
|
||||
LVX-TRP-0202,objektklass,Signalstolpe & mastarm,Signal pole & mast arm,TRP,2,kallbelagd,0.72
|
||||
LVX-TRP-0203,objektklass,Fundament (stolpe/mast/skåp),Foundation,TRP,2,kallbelagd,0.72
|
||||
LVX-TRP-0204,objektklass,Styrnod belysning (NEMA/Zhaga),Lighting control node,TRP,2,kallbelagd,0.75
|
||||
LVX-TRP-0205,objektklass,Vägportal/skyltbrygga,Sign gantry,TRP,2,kallbelagd,0.72
|
||||
LVX-TRP-0206,objektklass,Kantsten,Kerb/curb,TRP,2,kallbelagd,0.75
|
||||
LVX-TRP-0207,objektklass,Reflexstolpe/kantstolpe,Delineator post,TRP,2,kallbelagd,0.75
|
||||
LVX-TRP-0208,objektklass,Broräcke,Bridge parapet,TRP,2,kallbelagd,0.72
|
||||
LVX-TRP-0209,objektklass,Bullerskydd,Noise barrier,TRP,2,kallbelagd,0.75
|
||||
LVX-TRP-0210,objektklass,Räckesterminal/ändavslut,Guardrail end terminal,TRP,2,kallbelagd,0.75
|
||||
LVX-VAT-0101,objektklass,Brunnsbetäckning,Manhole cover,VAT,1,kallbelagd,0.82
|
||||
LVX-VAT-0102,objektklass,Dagvattengaller,Gully grating,VAT,1,kallbelagd,0.78
|
||||
LVX-VAT-0103,objektklass,Brandpost/hydrant,Fire hydrant,VAT,1,kallbelagd,0.8
|
||||
LVX-VAT-0201,objektklass,Betäckningsram,Cover frame,VAT,2,kallbelagd,0.75
|
||||
LVX-VAT-0202,objektklass,Nedstigningsbrunn,Manhole/chamber,VAT,2,kallbelagd,0.72
|
||||
LVX-VAT-0203,objektklass,Dagvattenbrunn,Gully/catch basin,VAT,2,kallbelagd,0.72
|
||||
LVX-VAT-0204,objektklass,Ventil-/spindelbetäckning,Valve surface box,VAT,2,obekraftad,0.6
|
||||
LVX-P-0000001,produktmodell,GE Evolve LED Medium Cobrahead (ERMC),GE Evolve LED Medium Cobrahead (ERMC),TRP,,kallbelagd,0.75
|
||||
LVX-P-0000002,produktmodell,GE Evolve LED Scalable Cobrahead (ERS1–ERS4),GE Evolve LED Scalable Cobrahead (ERS1–ERS4),TRP,,kallbelagd,0.8
|
||||
LVX-P-0000003,produktmodell,GE Evolve LED Roadway ERL-serien (ERL1/ERLH/ERL2),GE Evolve LED Roadway ERL series,TRP,,kallbelagd,0.8
|
||||
LVX-P-0000004,produktmodell,AEL Autobahn-serien (ATB Micro/ATB0/ATB2 + ATBL/M/S/X),AEL Autobahn series,TRP,,kallbelagd,0.8
|
||||
LVX-P-0000005,produktmodell,Schréder Ampera (Mini/Midi/Maxi),Schréder Ampera,TRP,,kallbelagd,0.78
|
||||
LVX-P-0000006,produktmodell,Schréder Ampera EVO,Schréder Ampera EVO,TRP,,kallbelagd,0.78
|
||||
LVX-P-0000007,produktmodell,Philips Luma gen2 (BGP701),Philips Luma gen2 (BGP701),TRP,,kallbelagd,0.8
|
||||
LVX-P-0000008,produktmodell,"3M Diamond Grade DG3, serie 4000",3M Diamond Grade DG3 Series 4000,TRP,,kallbelagd,0.8
|
||||
LVX-P-0000009,produktmodell,"3M High Intensity Prismatic (HIP), serie 3930",3M High Intensity Prismatic Series 3930,TRP,,kallbelagd,0.7
|
||||
LVX-P-0000010,produktmodell,Saint-Gobain PAM PAMREX,Saint-Gobain PAM PAMREX,VAT,,kallbelagd,0.8
|
||||
LVX-P-0000011,produktmodell,Neenah R-1640/R-1642-serien,Neenah R-1640/R-1642 series,VAT,,kallbelagd,0.78
|
||||
LVX-P-0000012,produktmodell,ABB Kabeldon CDC-serien,ABB Kabeldon CDC series,ELN,,kallbelagd,0.78
|
||||
LVX-P-0000013,produktmodell,Mueller Super Centurion,Mueller Super Centurion,VAT,,kallbelagd,0.7
|
||||
LVX-P-0000014,produktmodell,M&H Valve Style 929,M&H Valve Style 929,VAT,,kallbelagd,0.72
|
||||
LVX-P-0000015,produktmodell,American AVK Series 27,American AVK Series 27,VAT,,kallbelagd,0.7
|
||||
LVX-P-0000016,produktmodell,American-Darling B-84-B (AMERICAN Flow Control),American-Darling B-84-B,VAT,,kallbelagd,0.82
|
||||
LVX-P-0000017,produktmodell,Waterous Pacer (AMERICAN Flow Control),Waterous Pacer,VAT,,kallbelagd,0.68
|
||||
LVX-P-0000018,produktmodell,Ulefos gatugjutgods (t.ex. A6-betäckning),Ulefos street castings,VAT,,kallbelagd,0.75
|
||||
LVX-P-0000019,produktmodell,EJ ERGO / ERGO XL,EJ ERGO / ERGO XL access assembly,VAT,,kallbelagd,0.78
|
||||
LVX-P-0000020,produktmodell,MGS — Midwest Guardrail System (generiskt),Midwest Guardrail System (MGS),TRP,,kallbelagd,0.8
|
||||
LVX-P-0000021,produktmodell,Valtir SoftStop-terminal,Valtir SoftStop end terminal,TRP,,kallbelagd,0.78
|
||||
LVX-P-0000022,produktmodell,Econolite Blue Series NEMA-skåp,Econolite Blue Series NEMA cabinets,TRP,,kallbelagd,0.72
|
||||
LVX-P-0000023,produktmodell,Kempower Satellite (distribuerat system),Kempower Satellite charging system,ELN,,kallbelagd,0.8
|
||||
LVX-P-0000024,produktmodell,Alpitronic Hypercharger (HYC-serien),Alpitronic Hypercharger HYC series,ELN,,kallbelagd,0.8
|
||||
LVX-P-0000025,produktmodell,Tesla Supercharger V3,Tesla Supercharger V3,ELN,,kallbelagd,0.75
|
||||
LVX-P-0000026,produktmodell,Tesla Supercharger V4,Tesla Supercharger V4,ELN,,kallbelagd,0.8
|
||||
LVX-P-0000027,produktmodell,EJ SELFLEVEL betäckningsram,EJ SELFLEVEL access frame,VAT,,kallbelagd,0.72
|
||||
|
Reference in New Issue
Block a user