Import-helvetet
18 000 produkter. Det låter hanterbart tills du börjar fundera på hur de ska in i systemet. Varje produkt har egenskaper: material, dimension, färg, längd. Varje kombination av egenskaper skapar en variant. En produkt med tre storlekar och fyra färger ger tolv varianter. Multiplicera det med 18 000 basprodukter och du förstår varför jag sov dåligt i december.
CSV-parsning och datastruktur
Datan kom från leverantörer i olika format. Vissa skickade Excel, andra CSV, några PDF (ja, PDF). Steg ett var att normalisera allt till en gemensam struktur. Python med pandas blev mitt verktyg. Varje leverantörs data fick ett eget parser-script som transformerade deras format till vårt interna format.
Vår produktstruktur i Odoo bygger på product.template (basprodukten) och product.product (varianten). En polykarbonatskiva finns som en template. Varje specifik dimension – 500x500mm, 1000x1000mm, 2000x1000mm – är en variant under den templaten.
Varianter: dynamic, aldrig always
Det här var den dyraste lärdomen i hela projektet. Odoo har två lägen för variantskapande: ”always” och ”dynamic”. Med ”always” skapar Odoo automatiskt alla möjliga kombinationer av attribut. Låter bra, eller hur?
Nej. Om du har en produkt med fyra attribut och varje attribut har tio värden får du 10 x 10 x 10 x 10 = 10 000 varianter. Per produkt. Med 18 000 produkter pratar vi om hundratals miljoner poster i databasen. PostgreSQL hade inte tyckt det var kul.
Med ”dynamic” skapas varianter bara när de faktiskt behövs – när en kund väljer en specifik kombination i webbshopen. Det minskar databasbelastningen dramatiskt och gör systemet användbart vid 150 000 varianter istället för att krascha vid 10 miljoner.
Prissättningsformeln
Varje produkt har tre prisnivåer: inköpspris (vad vi betalar leverantören), standardpris (vår kostnad med marginal) och listpris (vad kunden ser). Formeln:
standard_price = ceil(inpris / 0.9) # 10% marginal
list_price = ceil(standard_price / 0.6) # 40% marginal
Exempel: om vi köper in ett material för 100 kr blir standard_price 112 kr och list_price 187 kr. Ceil-funktionen rundar alltid uppåt för att undvika ören-priser.
En detalj som tog timmar att lösa: standard_price i Odoo 18 sparas som JSONB i databasen. Inte som ett vanligt decimalfält. Formatet är {”1”: värde} där ”1” är företags-ID:t. Det är viktigt att veta om du skriver direkt mot databasen via scripts istället för ORM:en.
Importprocessen
Själva importen körde jag via Python-scripts som anropade Odoo’s XML-RPC API. Det är långsammare än direkta SQL-inserts men säkrare – Odoo’s ORM hanterar all validering, beräkning av computed fields och uppdatering av index.
En fullständig import av alla 18 000 produkter tar ungefär fyra timmar via RPC. Det låter mycket men det är en engångsoperation. Inkrementella uppdateringar – nya produkter eller prisändringar – tar minuter.
Viktig detalj: kör alltid RPC-anrop mot localhost (127.0.0.1:8074), inte mot den publika URL:en. Nginx blockerar XML-RPC av säkerhetsskäl i min setup.
Attributbaserad filtrering
Med produkterna på plats behövde webbshopen filtrering. Kunder vill kunna filtrera på material (polykarbonat, PTFE, POM), dimension, färg och tekniska egenskaper. Odoo har grundläggande attributfiltrering men den är byggd för kläder och elektronik, inte för industriplast.
Jag byggde ett eget filtreringssystem i arc_industrial_core som använder format-baserade profiler. Varje produktkategori har en filterprofil som definierar vilka attribut som är relevanta. Skivor filtreras på tjocklek och storlek. Stänger på diameter och längd. Rör på ytter- och innerdiameter.
Systemet kör raw SQL mot PostgreSQL för prestanda. En filtrerad sökning i 150 000 varianter returnerar resultat på under 100 millisekunder. Odoos inbyggda ORM hade inte klarat den prestandan.
Leverantörspriser
Varje produkt kan ha priser från flera leverantörer. Leverantör A säljer polykarbonat billigare men PTFE dyrare än leverantör B. Odoo hanterar leverantörspriser via seller_ids på produkten, men att importera dem i bulk krävde ytterligare scripts.
Prisuppdateringar kommer regelbundet. Jag har ett n8n-workflow som tar emot prisupdateringar från leverantörer (CSV via e-post), parsar dem och uppdaterar Odoo via RPC. Hela kedjan är automatiserad.
Lärdomar från importprojektet
Tre saker jag önskar att jag visste innan jag började:
Ett: testa med 100 produkter först. Inte 18 000. Hitta felen tidigt när det är snabbt att köra om.
Två: validera data innan import. Tomma fält, felaktiga datatyper och duplicerade SKU:er skapar kaos som är svårt att städa upp efteråt.
Tre: ha en rollback-plan. Jag tog en databasdump innan varje stor import. Det räddade mig minst tre gånger.
Idag har vi 18 000 produkter med korrekta priser, attribut och teknisk data i Odoo. Importen är inte den roligaste delen av projektet, men den är fundamentet som allt annat bygger på.
Vad tycker du?
Jag vill gärna höra dina tankar. Kommentera nedan eller nå mig på LinkedIn.

