From 12f37ac4c0fb7255fae19627fb06ecf7e6339763 Mon Sep 17 00:00:00 2001 From: seb Date: Tue, 15 Sep 2026 07:45:32 +0200 Subject: [PATCH] feat(delivery): add POST /delivery/parsePDF SSE route - Accepts multipart/form-data PDF, streams LLM extraction via SSE - Uses libllmorbiter (OpenRouterProvider) with API key from companysetting keys.openrouter - Extracts manifest basedata, notes, and line items from invoices/delivery notes - Events: status, llm_call, tool_call, usage, progress, result, error - Extends generateApiDocs.js: multipart field table + x-sse-events table support - Docs: docs/api/routes/delivery/parsePDF.md (auto-generated) --- artikeltabelle.csv | 1066 ++++++++++++++++++++++++++ docs/api/README.md | 1 + docs/api/openapi.json | 104 +++ docs/api/routes/delivery/parsePDF.md | 85 ++ package-lock.json | 401 ++++++---- package.json | 12 +- scripts/generateApiDocs.js | 31 + src/api/routes/deliveryParsePdf.js | 419 ++++++++++ 8 files changed, 1963 insertions(+), 156 deletions(-) create mode 100644 artikeltabelle.csv create mode 100644 docs/api/routes/delivery/parsePDF.md create mode 100644 src/api/routes/deliveryParsePdf.js diff --git a/artikeltabelle.csv b/artikeltabelle.csv new file mode 100644 index 0000000..9014d3b --- /dev/null +++ b/artikeltabelle.csv @@ -0,0 +1,1066 @@ +="ArtNr";"Name";Preis;USt;Pfand;"Hersteller";"Kategorie";="Barcode";"V/K" +="42000573";" Steel Pipe Screen 12mm";2,00;19;;;"Zubehör";; +="42001190";"420Strainz";0,00;19;;;"Flowers | CBN";;"V" +="42001190-1";"420Strainz 1g";11,00;19;;;"Flowers | CBN";;"K" +="42001190-2";"420Strainz 2g";21,00;19;;;"Flowers | CBN";;"K" +="42001190-3";"420Strainz 5g";50,00;19;;;"Flowers | CBN";;"K" +="42000002";"420z Leaf Blueberry";9,95;19;;;"Tabak";="4270001588593"; +="42000004";"420z Leaf Classic";9,95;19;;;"Tabak";="4270001588579"; +="42000005";"420z Leaf Lemon";9,95;19;;;"Tabak";="4270001588586"; +="42000003";"420z Leaf Rainbow";9,95;19;;;"Tabak";="4270000769634"; +="42001319";"50 Pre Roll Xtra";24,90;19;;;"Smoke | Papes";="4260748413760"; +="42001299";"Agro Perlit 4 l";5,00;19;;;"Grow | Erde";="8592542017506"; +="42001275";"Agro Perlit 8 l";8,00;19;;;"Grow | Erde";="8594200871161"; +="42001289";"Airontek Clip Fan 15W 15 cm";22,00;19;;;"Grow | Zubehör";="8595722026664"; +="42000006";"Ak420 1";7,50;19;;;"Seeds | Seedstockers";; +="42000007";"Ak420 3";15,00;19;;;"Seeds | Seedstockers";; +="42000008";"Ak420 5";22,00;19;;;"Seeds | Seedstockers";; +="42000009";"Aktivkohletasche XS Schwarz";9,90;19;;;"Zubehör";; +="42000011";"Amaretto Tarmac Auto 1";17,00;19;;;"Seeds | Seedstockers";; +="42000012";"Amaretto Tarmac Auto 3";34,00;19;;;"Seeds | Seedstockers";; +="42000013";"Amaretto Tarmac Auto 5";51,00;19;;;"Seeds | Seedstockers";; +="42000015";"American Spirit Blue";6,50;19;;;"Tabak";="4032800056860"; +="42000014";"American Spirit Gelb";6,50;19;;;"Tabak";="4032800056884"; +="42001135";"American Spirit Master Blend Orange";7,00;19;;;"Tabak";="4032800056907"; +="42000016";"American Spirit Selected Red";6,30;19;;;"Tabak";="4032800056754"; +="42001224";"Amsterdam | Glass Bowl - SG:18.8mm with Small Hole";8,00;19;;;"Bong/Glasfilter";="616695664580"; +="42001235";"Amsterdam Glass Bong- H:28cm- Ø:40mm SG:18.8mm ";35,00;19;;;"Bong/Glasfilter";="616695666508"; +="42000017";"Anheuser 0,33L";1,42;19;0,08;;"Getränke";="4100130022081"; +="42000018";"Apollo Black Cherry Auto 1";24,00;19;;;"Seeds | Seedstockers";; +="42000019";"Apollo Black Cherry Auto 3";48,00;19;;;"Seeds | Seedstockers";; +="42000020";"Apollo Black Cherry Auto 5";72,00;19;;;"Seeds | Seedstockers";; +="42001276";"Aqua Master Tools pH meter P50 PRO 2.0 ";65,00;19;;;"Grow | Messgeräte";="8721249602009"; +="42000673-1";"Aqua Panna Tuscani";1,25;19;0,15;;"Getränke";="8002270018848";"K" +="42000021";"Arizona";2,25;19;0,25;;"Getränke";; +="42001182";"Astra";0,00;19;;;"Getränke";;"V" +="42001182-2";"Astra Kiezmische";1,72;19;0,08;;"Getränke";="42278177";"K" +="42001182-1";"Astra Standard";1,72;19;0,08;;"Getränke";;"K" +="42001301";"Athena Trial Kit Liquid Blended Starter kit";95,00;19;;;"Grow | Dünger";="860011221456"; +="42000024";"Augustiner";2,02;19;0,08;;"Getränke";="4105250022003"; +="42001260";"Autopot Airdome";7,00;19;;;"Grow | AutoPot";; +="42001252";"Autopot Tray 2 Grow";87,90;19;;;"Grow | AutoPot";="5060151875488"; +="42000029";"Banana Jealousy x Guava";35,00;19;;;"Seeds | Seedstockers";; +="42000025";"BCN Power Plant Auto 1";11,50;19;;;"Seeds | Seedstockers";; +="42000026";"BCN Power Plant Auto 3";23,00;19;;;"Seeds | Seedstockers";; +="42000027";"BCN Power Plant Auto 5";34,50;19;;;"Seeds | Seedstockers";; +="42000030";"Becks ";1,52;19;0,08;;"Getränke";;"V" +="42000030-3";"Becks ICE";1,92;19;0,08;;"Getränke";="42150022";"K" +="42000030-1";"Becks 0,33l";1,52;19;0,08;;"Getränke";="41001301";"K" +="42000030-2";"Becks 0,5l";1,92;19;0,08;;"Getränke";="41001318";"K" +="42001234";"Beer Bottle Glass Bong- H:26cm- SG:14.5mm";20,00;19;;;"Bong/Glasfilter";="616695664405"; +="42001209";"Berries";0,00;19;;;"CBN_";;"V" +="42001216";"Berries";0,00;19;;;"CBD_";;"V" +="42001209-1";"Berries 1g";0,00;19;;;"CBN_";="4262557690455";"K" +="42001216-1";"Berries 1g";0,00;19;;;"CBD_";;"K" +="42001216-2";"Berries 2g";0,00;19;;;"CBD_";;"K" +="42001209-2";"Berries 2g";0,00;19;;;"CBN_";="4262557690462";"K" +="42001209-3";"Berries 5g";0,00;19;;;"CBN_";="4262557690479";"K" +="42001117";"Berries CBD";0,00;19;;;"Flowers | CBD";;"V" +="42001117-1";"Berries CBD 1g";5,00;19;;;"Flowers | CBD";="4262557690066";"K" +="42001117-2";"Berries CBD 2g";9,00;19;;;"Flowers | CBD";="4262557690073";"K" +="42001117-3";"Berries CBD 5g";22,50;19;;;"Flowers | CBD";="4262557690080";"K" +="42001246";"BIC Mini PUN";1,60;19;;;"Zubehör";; +="42001318";"BioBizz All Pack Indoor";54,90;19;;;"Grow | Dünger";; +="42001274";"Biobizz Try Pack Indoor 750 ml";20,00;19;;;"Grow | Dünger";="8718403232127"; +="42001320";"BioBizz TryPack Outdoor";15,50;19;;;"Grow | Dünger";; +="42000090";"Biodor Moschus";14,90;19;;;"Zubehör";; +="42000087";"Biodor Neutral";14,90;19;;;"Zubehör";; +="42000091";"Biodor Spray";16,90;19;;;"Zubehör";; +="42001298";"BioNova Open Top Coco Bag 12 l ";6,00;19;;;"Grow | Erde";="8595722002910"; +="42001214";"Black Caviar";0,00;19;;;"CBD_";;"V" +="42001214-1";"Black Caviar 1g";0,00;19;;;"CBD_";;"K" +="42001214-2";"Black Caviar 2g";0,00;19;;;"CBD_";;"K" +="42001118";"Black Caviar CBD";0,00;19;;;"Flowers | CBD";;"V" +="42001118-1";"Black Caviar CBD 1g";5,00;19;;;"Flowers | CBD";="4262557690035";"K" +="42001118-2";"Black Caviar CBD 2g";9,00;19;;;"Flowers | CBD";="4262557690042";"K" +="42001118-3";"Black Caviar CBD 5g";22,50;19;;;"Flowers | CBD";="4262557690059";"K" +="42001211";"Black Cherry";0,00;19;;;"CBN_";;"V" +="42001217";"Black Cherry";0,00;19;;;"CBD_";;"V" +="42001217-1";"Black Cherry 1g";0,00;19;;;"CBD_";="4262557690127";"K" +="42001211-1";"Black Cherry 1g";0,00;19;;;"CBN_";="4262557690516";"K" +="42001211-2";"Black Cherry 2g";0,00;19;;;"CBN_";="4262557690523";"K" +="42001217-2";"Black Cherry 2g";0,00;19;;;"CBD_";;"K" +="42001211-3";"Black Cherry 5g";0,00;19;;;"CBN_";="4262557691384";"K" +="42000098";"Black Rainbow Auto 1";14,50;19;;;"Seeds | Seedstockers";; +="42000099";"Black Rainbow Auto 3";29,00;19;;;"Seeds | Seedstockers";; +="42000100";"Black Rainbow Auto 5";43,50;19;;;"Seeds | Seedstockers";; +="42000101";"Blue Moby FEM 1";14,50;19;;;"Seeds | Seedstockers";; +="42000102";"Blue Moby FEM 3";29,00;19;;;"Seeds | Seedstockers";; +="42000103";"Blue Moby FEM 5";43,50;19;;;"Seeds | Seedstockers";; +="42001120";"Boarding Pass CBD";0,00;19;;;"Flowers | CBD";;"V" +="42001120-1";"Boarding Pass CBD 1g";10,00;19;;;"Flowers | CBD";="4262557690967";"K" +="42001120-2";"Boarding Pass CBD 2g";19,00;19;;;"Flowers | CBD";="4262557690974";"K" +="42001120-3";"Boarding Pass CBD 5g";45,00;19;;;"Flowers | CBD";="4262557690981";"K" +="42001106";"Boarding Pass CBN";0,00;19;;;"Flowers | CBN";;"V" +="42001106-6";"Boarding Pass CBN 10g";60,00;19;;;"Flowers | CBN";;"K" +="42001106-1";"Boarding Pass CBN 15g";82,50;19;;;"Flowers | CBN";;"K" +="42001106-9";"Boarding Pass CBN 1g";7,50;19;;;"Flowers | CBN";="4262557690882";"K" +="42001106-5";"Boarding Pass CBN 20g";105,00;19;;;"Flowers | CBN";;"K" +="42001106-4";"Boarding Pass CBN 25g";125,00;19;;;"Flowers | CBN";;"K" +="42001106-8";"Boarding Pass CBN 2g";14,00;19;;;"Flowers | CBN";="4262557690899";"K" +="42001106-2";"Boarding Pass CBN 30g";142,50;19;;;"Flowers | CBN";;"K" +="42001106-3";"Boarding Pass CBN 3g";20,00;19;;;"Flowers | CBN";;"K" +="42001106-7";"Boarding Pass CBN 5g";32,50;19;;;"Flowers | CBN";="4262557690905";"K" +="42000114";"Bong Atomic 9mm";49,90;19;;;"Bong/Glasfilter";; +="42000116";"Bong Atomic Acryl groß";24,90;19;;;"Bong/Glasfilter";; +="42000115";"Bong Atomic Acryl klein";19,90;19;;;"Bong/Glasfilter";; +="42000113";"Bong Standard";1,00;19;;;"Bong/Glasfilter";; +="42001138";"Brass Screens 5";0,50;19;;;"Bong/Glasfilter";="000420011389"; +="42001121";"Bubblegum CBD";0,00;19;;;"Flowers | CBD";;"V" +="42001121-4";"Bubblegum CBD 10g";85,00;19;;;"Flowers | CBD";;"K" +="42001121-1";"Bubblegum CBD 1g";10,00;19;;;"Flowers | CBD";="4262557690936";"K" +="42001121-2";"Bubblegum CBD 2g";19,00;19;;;"Flowers | CBD";="4262557690943";"K" +="42001121-3";"Bubblegum CBD 5g";45,00;19;;;"Flowers | CBD";="4262557690950";"K" +="42001115";"Bubblegum CBN";0,00;19;;;"Flowers | CBN";;"V" +="42001115-2";"Bubblegum CBN 1g";11,00;19;;;"Flowers | CBN";="4262557690851";"K" +="42001115-3";"Bubblegum CBN 2g";21,00;19;;;"Flowers | CBN";="4262557690868";"K" +="42001115-1";"Bubblegum CBN 5g";50,00;19;;;"Flowers | CBN";="4262557690875";"K" +="42000136";"Budweiser";2,02;19;0,08;;"Getränke";="8594403110111"; +="42000143";"Candy Dawg Auto 1";13,00;19;;;"Seeds | Seedstockers";; +="42000144";"Candy Dawg Auto 3";26,00;19;;;"Seeds | Seedstockers";; +="42000145";"Candy Dawg Auto 5";39,00;19;;;"Seeds | Seedstockers";; +="42001313";"Canna Smile Live Resin CBD";0,00;19;;;"Vapes";;"V" +="42001313-4";"Canna Smile Live Resin CBD Banana Runtz";24,90;19;;;"Vapes";="9824204201022";"K" +="42001313-3";"Canna Smile Live Resin CBD Bubba Kush";24,90;19;;;"Vapes";="9824204201015";"K" +="42001313-2";"Canna Smile Live Resin CBD Lemon Cherry Gelato";24,90;19;;;"Vapes";="9824204201039";"K" +="42001313-5";"Canna Smile Live Resin CBD London Pound Cake";24,90;19;;;"Vapes";="9824204201046";"K" +="42001313-1";"Canna Smile Live Resin CBD Super Jack";24,90;19;;;"Vapes";="9824204201053";"K" +="42001166";"Cannasseur Cooling Case";25,00;19;;;"Cannasseur";="657039784908"; +="42001165";"Cannasseur Lupe";15,00;19;;;"Cannasseur";="657039784892"; +="42000159";"Canuma Blau";5,90;19;;;"Tabak";="42477518"; +="42000160";"Canuma Grün";5,90;19;;;"Tabak";="42477495"; +="42001185";"Capri Sonne";0,00;19;;;"Getränke";;"V" +="42001185-2";"Capri Sonne Groß";1,80;19;;;"Getränke";;"K" +="42001185-3";"Capri Sonne Monster";1,20;19;;;"Getränke";;"K" +="42001185-4";"Capri Sonne Mystic";1,20;19;;;"Getränke";;"K" +="42001185-1";"Capri Sonne Orange";1,20;19;;;"Getränke";="4000177032732";"K" +="42001249";"Carlsberg 0,5l";1,92;19;0,08;;"Getränke";="5740600514143"; +="42001212";"Caviar";0,00;19;;;"CBN_";;"V" +="42001212-1";"Caviar 1g";0,00;19;;;"CBN_";="4262557690424";"K" +="42001212-2";"Caviar 2g";0,00;19;;;"CBN_";="4262557690431";"K" +="42001212-3";"Caviar 5g";0,00;19;;;"CBN_";="4262557690448";"K" +="42000140";"CBD 1:1 Silver Lime Haze Auto 1";17,00;19;;;"Seeds | Seedstockers";; +="42000141";"CBD 1:1 Silver Lime Haze Auto 3";34,00;19;;;"Seeds | Seedstockers";; +="42000142";"CBD 1:1 Silver Lime Haze Auto 5";51,00;19;;;"Seeds | Seedstockers";; +="42001149";"CBD Trim";0,00;19;;;"Flowers | CBD";;"V" +="42001149-1";"CBD Trim 20g";20,00;19;;;"Flowers | CBD";="4262557691490";"K" +="42001149-2";"CBD Trim 5g";10,00;19;;;"Flowers | CBD";="4262557691483";"K" +="42001148";"CBN Trim ";45,00;19;;;"Flowers | CBN";="4262557691506";"V" +="42001148-1";"CBN Trim 20g";45,00;19;;;"Flowers | CBN";="4262557691506";"K" +="42001314";"CCell M4";9,90;19;;;"Vapes";="6943498626670"; +="42000167";"Chocomel";5,00;19;;;"Getränke";; +="42001247";"Clipper 420 Fairytale";2,00;19;;;"Zubehör";; +="42001245";"Clipper THC Train";2,50;19;;;"Zubehör";; +="42000169";"Club Mate 0,5";2,05;19;0,15;;"Getränke";;"V" +="42000169-2";"Club Mate 0,5 Eistee";2,05;19;0,15;;"Getränke";="4029764001814";"K" +="42000169-1";"Club Mate 0,5 Original";2,05;19;0,15;;"Getränke";="4029764001807";"K" +="42000170";"Coca Cola 0,33L";2,02;19;0,08;;"Getränke";;"V" +="42000170-1";"Coca Cola 0,33L Cherry";2,02;19;0,08;;"Getränke";="54035546";"K" +="42000170-2";"Coca Cola 0,33L Original";2,02;19;0,08;;"Getränke";="87126853";"K" +="42000172";"Deckel Humidor L";18,90;19;;;"Cannasseur";; +="42000171";"Deckel Humidor M";17,90;19;;;"Cannasseur";; +="42000173";"Deckel Humidor XL";19,90;19;;;"Cannasseur";; +="42000174";"Desperados 0,33L";2,22;19;0,08;;"Getränke";; +="42001102";"Devils Milk";0,00;19;;;"Flowers | CBN";;"V" +="42001132-3";"Devils Milk 10g";45,00;19;;;"Flowers | CBD";;"K" +="42001102-3";"Devils Milk 10g";65,00;19;;;"Flowers | CBN";;"K" +="42001102-1";"Devils Milk 15g";90,00;19;;;"Flowers | CBN";;"K" +="42001132-4";"Devils Milk 15g";62,50;19;;;"Flowers | CBD";;"K" +="42001132-2";"Devils Milk 1g";6,00;19;;;"Flowers | CBD";="4262557691452";"K" +="42001102-2";"Devils Milk 1g";8,00;19;;;"Flowers | CBN";="4262557691100";"K" +="42001102-5";"Devils Milk 20g";115,00;19;;;"Flowers | CBN";;"K" +="42001132-6";"Devils Milk 20g";80,00;19;;;"Flowers | CBD";;"K" +="42001132-7";"Devils Milk 25g";95,00;19;;;"Flowers | CBD";;"K" +="42001102-6";"Devils Milk 25g";137,50;19;;;"Flowers | CBN";;"K" +="42001102-4";"Devils Milk 2g";15,00;19;;;"Flowers | CBN";="4262557691094";"K" +="42001132-5";"Devils Milk 2g";10,00;19;;;"Flowers | CBD";="4262557691469";"K" +="42001132-8";"Devils Milk 30g";105,00;19;;;"Flowers | CBD";;"K" +="42001102-8";"Devils Milk 30g";157,50;19;;;"Flowers | CBN";;"K" +="42001102-7";"Devils Milk 3g";22,50;19;;;"Flowers | CBN";;"K" +="42001102-9";"Devils Milk 5g";35,00;19;;;"Flowers | CBN";="4262557691087";"K" +="42001132-1";"Devils Milk 5g";25,00;19;;;"Flowers | CBD";="4262557691476";"K" +="42001132";"Devils Milk CBD";0,00;19;;;"Flowers | CBD";;"V" +="42000194";"Drizl Pack Auto 1";19,50;19;;;"Seeds | Seedstockers";; +="42000195";"Drizl Pack Auto 3";39,00;19;;;"Seeds | Seedstockers";; +="42000196";"Drizl Pack Auto 5";58,50;19;;;"Seeds | Seedstockers";; +="42000197";"Drizl Pack FEM 1";19,50;19;;;"Seeds | Seedstockers";; +="42000198";"Drizl Pack FEM 3";39,00;19;;;"Seeds | Seedstockers";; +="42000199";"Drizl Pack FEM 5";58,50;19;;;"Seeds | Seedstockers";; +="42001103";"Dry Sift";0,00;19;;;"Flowers | CBN";;"V" +="42001103-9";"Dry Sift 10g";85,00;19;;;"Flowers | CBN";;"K" +="42001103-8";"Dry Sift 15g";120,00;19;;;"Flowers | CBN";;"K" +="42001103-1";"Dry Sift 1g";10,00;19;;;"Flowers | CBN";="4262557691544";"K" +="42001103-6";"Dry Sift 20g";155,00;19;;;"Flowers | CBN";;"K" +="42001103-5";"Dry Sift 25g";185,00;19;;;"Flowers | CBN";;"K" +="42001103-7";"Dry Sift 2g";19,00;19;;;"Flowers | CBN";="4262557691551";"K" +="42001103-3";"Dry Sift 30g";210,00;19;;;"Flowers | CBN";;"K" +="42001103-4";"Dry Sift 3g";28,50;19;;;"Flowers | CBN";;"K" +="42001103-2";"Dry Sift 5g";45,00;19;;;"Flowers | CBN";="4262557691568";"K" +="42001266";"Drybag";0,00;19;;;"Zubehör";;"V" +="42001266-3";"Drybag Groß";4,00;19;;;"Zubehör";;"K" +="42001266-1";"Drybag Klein";2,00;19;;;"Zubehör";;"K" +="42001266-2";"Drybag Mittel";3,00;19;;;"Zubehör";;"K" +="42001186";"Effect";0,00;19;;;"Getränke";;"V" +="42001186-4";"Effect Black Acai";2,25;19;0,25;;"Getränke";="4025127090235";"K" +="42001186-1";"Effect Cocos Blaubeere";2,25;19;0,25;;"Getränke";="4025127088126";"K" +="42001186-5";"Effect Habibi Berry";2,25;19;0,25;;"Getränke";="4025127085460";"K" +="42001186-2";"Effect Original";2,25;19;0,25;;"Getränke";="4025127020997";"K" +="42001186-3";"Effect Pink Grapefruit";2,25;19;0,25;;"Getränke";="4025127085187";"K" +="42001186-6";"Effect Strawberry Apricot";2,25;19;0,25;;"Getränke";="4025127085767";"K" +="42000223";"Erdinger Weißbier";2,02;19;0,08;;"Getränke";="4002103000013"; +="42001238";"Erdinger Weißbier 0,33l";1,62;19;0,08;;"Getränke";="4002103000105"; +="42000224";"Extract Cooling Case";39,90;19;;;"Cannasseur";; +="42000225";"F.U.H Auto 1";13,00;19;;;"Seeds | Seedstockers";; +="42000226";"F.U.H Auto 3";26,00;19;;;"Seeds | Seedstockers";; +="42000227";"F.U.H Auto 5";39,00;19;;;"Seeds | Seedstockers";; +="42001310";"Fanta";0,00;19;;;"CBN_";;"V" +="42001310-1";"Fanta 1g";0,00;19;;;"CBN_";="4262557691650";"K" +="42001310-2";"Fanta 2g";0,00;19;;;"CBN_";="4262557691643";"K" +="42001310-3";"Fanta 5g";0,00;19;;;"CBN_";="4262557691636";"K" +="42001177";"Fanta Orange 0,33l";1,92;19;0,08;;"Getränke";="87126860"; +="42000228";"FastBuds 5er Mix Pack Auto";55,00;19;;;"Seeds | FastBuds";; +="42000229";"FastBuds Afghan Kush Auto 1";9,00;19;;;"Seeds | FastBuds";; +="42000230";"FastBuds Afghan Kush Auto 3";24,00;19;;;"Seeds | FastBuds";; +="42000231";"FastBuds Afghan Kush Auto 5";35,00;19;;;"Seeds | FastBuds";; +="42001097";"FastBuds Amnesia Z Auto";0,00;19;;;"Seeds | FastBuds";;"V" +="42001097-1";"FastBuds Amnesia Z Auto 1g";13,00;19;;;"Seeds | FastBuds";;"K" +="42001097-2";"FastBuds Amnesia Z Auto 3g";36,00;19;;;"Seeds | FastBuds";;"K" +="42001097-3";"FastBuds Amnesia Z Auto 5g";55,00;19;;;"Seeds | FastBuds";;"K" +="42001098";"FastBuds Apple Strudel Auto";0,00;19;;;"Seeds | FastBuds";;"V" +="42001098-1";"FastBuds Apple Strudel Auto 1g";13,00;19;;;"Seeds | FastBuds";;"K" +="42001098-2";"FastBuds Apple Strudel Auto 3g";36,00;19;;;"Seeds | FastBuds";;"K" +="42001098-3";"FastBuds Apple Strudel Auto 5g";55,00;19;;;"Seeds | FastBuds";;"K" +="42000238";"FastBuds Banana Purple Punch Auto 1";13,00;19;;;"Seeds | FastBuds";; +="42000239";"FastBuds Banana Purple Punch Auto 3";36,00;19;;;"Seeds | FastBuds";; +="42000240";"FastBuds Banana Purple Punch Auto 5";55,00;19;;;"Seeds | FastBuds";; +="42000241";"FastBuds Biscotti Gelato 1";22,00;19;;;"Seeds | FastBuds";; +="42000242";"FastBuds Biscotti Gelato 3";40,00;19;;;"Seeds | FastBuds";; +="42000243";"FastBuds Biscotti Gelato 5";65,00;19;;;"Seeds | FastBuds";; +="42000244";"FastBuds Blueberry Auto 1";9,00;19;;;"Seeds | FastBuds";; +="42000245";"FastBuds Blueberry Auto 3";24,00;19;;;"Seeds | FastBuds";; +="42000246";"FastBuds Blueberry Auto 5";35,00;19;;;"Seeds | FastBuds";; +="42000247";"FastBuds Bruce Banner Auto 1";13,00;19;;;"Seeds | FastBuds";; +="42000248";"FastBuds Bruce Banner Auto 3";36,00;19;;;"Seeds | FastBuds";; +="42000249";"FastBuds Bruce Banner Auto 5";55,00;19;;;"Seeds | FastBuds";; +="42000250";"FastBuds BubbleGum Auto 1";9,00;19;;;"Seeds | FastBuds";; +="42000251";"FastBuds BubbleGum Auto 3";24,00;19;;;"Seeds | FastBuds";; +="42000252";"FastBuds BubbleGum Auto 5";35,00;19;;;"Seeds | FastBuds";; +="42000253";"FastBuds CBD Auto 1:1 (CBD Crack) 1";9,00;19;;;"Seeds | FastBuds";; +="42000254";"FastBuds CBD Auto 1:1 (CBD Crack) 3";24,00;19;;;"Seeds | FastBuds";; +="42000255";"FastBuds CBD Auto 1:1 (CBD Crack) 5";35,00;19;;;"Seeds | FastBuds";; +="42000256";"FastBuds Cherry Cola Auto 1";13,00;19;;;"Seeds | FastBuds";; +="42000257";"FastBuds Cherry Cola Auto 3";36,00;19;;;"Seeds | FastBuds";; +="42000258";"FastBuds Cherry Cola Auto 5";55,00;19;;;"Seeds | FastBuds";; +="42000259";"FastBuds Crystal Meth Auto 1";9,00;19;;;"Seeds | FastBuds";; +="42000260";"FastBuds Crystal Meth Auto 3";24,00;19;;;"Seeds | FastBuds";; +="42000261";"FastBuds Crystal Meth Auto 5";35,00;19;;;"Seeds | FastBuds";; +="42000262";"FastBuds Forbidden Runtz Auto 1";13,00;19;;;"Seeds | FastBuds";; +="42000263";"FastBuds Forbidden Runtz Auto 3";36,00;19;;;"Seeds | FastBuds";; +="42000264";"FastBuds Forbidden Runtz Auto 5";55,00;19;;;"Seeds | FastBuds";; +="42000265";"FastBuds Frostbanger Auto 1";13,00;19;;;"Seeds | FastBuds";; +="42000266";"FastBuds Frostbanger Auto 3";36,00;19;;;"Seeds | FastBuds";; +="42000267";"FastBuds Frostbanger Auto 5";55,00;19;;;"Seeds | FastBuds";; +="42000268";"FastBuds GG4 Sherbet FF 1";13,00;19;;;"Seeds | FastBuds";; +="42000269";"FastBuds GG4 Sherbet FF 3";36,00;19;;;"Seeds | FastBuds";; +="42000270";"FastBuds GG4 Sherbet FF 5";55,00;19;;;"Seeds | FastBuds";; +="42000271";"FastBuds Gorilla Cookies FF 1";13,00;19;;;"Seeds | FastBuds";; +="42000272";"FastBuds Gorilla Cookies FF 3";36,00;19;;;"Seeds | FastBuds";; +="42000273";"FastBuds Gorilla Cookies FF 5";55,00;19;;;"Seeds | FastBuds";; +="42000274";"FastBuds Gorilla Melon Feminisiert 1";13,00;19;;;"Seeds | FastBuds";; +="42000275";"FastBuds Gorilla Melon Feminisiert 3";36,00;19;;;"Seeds | FastBuds";; +="42000276";"FastBuds Gorilla Melon Feminisiert 5";55,00;19;;;"Seeds | FastBuds";; +="42000277";"FastBuds Gorilla Z Auto 1";13,00;19;;;"Seeds | FastBuds";; +="42000278";"FastBuds Gorilla Z Auto 3";36,00;19;;;"Seeds | FastBuds";; +="42000279";"FastBuds Gorilla Z Auto 5";55,00;19;;;"Seeds | FastBuds";; +="42000280";"FastBuds Guava Auto RF3 1";16,00;19;;;"Seeds | FastBuds";; +="42000281";"FastBuds Guava Auto RF3 3";42,00;19;;;"Seeds | FastBuds";; +="42000282";"FastBuds Guava Auto RF3 5";65,00;19;;;"Seeds | FastBuds";; +="42000286";"FastBuds Lemon Cherry Cookies Auto 1";13,00;19;;;"Seeds | FastBuds";; +="42000287";"FastBuds Lemon Cherry Cookies Auto 3";36,00;19;;;"Seeds | FastBuds";; +="42000288";"FastBuds Lemon Cherry Cookies Auto 5";55,00;19;;;"Seeds | FastBuds";; +="42000289";"FastBuds Lemon Cherry Runtz 1";22,00;19;;;"Seeds | FastBuds";; +="42000290";"FastBuds Lemon Cherry Runtz 3";40,00;19;;;"Seeds | FastBuds";; +="42000291";"FastBuds Lemon Cherry Runtz 5";65,00;19;;;"Seeds | FastBuds";; +="42000292";"FastBuds Lemonpaya Feminisiert 1";13,00;19;;;"Seeds | FastBuds";; +="42000293";"FastBuds Lemonpaya Feminisiert 3";36,00;19;;;"Seeds | FastBuds";; +="42000294";"FastBuds Lemonpaya Feminisiert 5";55,00;19;;;"Seeds | FastBuds";; +="42000283";"FastBuds LSD-25 Auto 1";9,00;19;;;"Seeds | FastBuds";; +="42000284";"FastBuds LSD-25 Auto 3";24,00;19;;;"Seeds | FastBuds";; +="42000285";"FastBuds LSD-25 Auto 5";35,00;19;;;"Seeds | FastBuds";; +="42000295";"FastBuds Moby Dick Auto 1";9,00;19;;;"Seeds | FastBuds";; +="42000296";"FastBuds Moby Dick Auto 3";24,00;19;;;"Seeds | FastBuds";; +="42000297";"FastBuds Moby Dick Auto 5";35,00;19;;;"Seeds | FastBuds";; +="42000298";"FastBuds Orange President Auto 1";13,00;19;;;"Seeds | FastBuds";; +="42000299";"FastBuds Orange President Auto 3";36,00;19;;;"Seeds | FastBuds";; +="42000300";"FastBuds Orange President Auto 5";55,00;19;;;"Seeds | FastBuds";; +="42000301";"FastBuds Orange Sherbet FF 1";13,00;19;;;"Seeds | FastBuds";; +="42000302";"FastBuds Orange Sherbet FF 3";36,00;19;;;"Seeds | FastBuds";; +="42000303";"FastBuds Orange Sherbet FF 5";55,00;19;;;"Seeds | FastBuds";; +="42000304";"FastBuds Papaya Cookies Auto 1";13,00;19;;;"Seeds | FastBuds";; +="42000305";"FastBuds Papaya Cookies Auto 3";36,00;19;;;"Seeds | FastBuds";; +="42000306";"FastBuds Papaya Cookies Auto 5";55,00;19;;;"Seeds | FastBuds";; +="42000307";"FastBuds Papaya Sherbet Feminisiert 1";13,00;19;;;"Seeds | FastBuds";; +="42000308";"FastBuds Papaya Sherbet Feminisiert 3";36,00;19;;;"Seeds | FastBuds";; +="42000309";"FastBuds Papaya Sherbet Feminisiert 5";55,00;19;;;"Seeds | FastBuds";; +="42000310";"FastBuds Pound Cake Auto 1";13,00;19;;;"Seeds | FastBuds";; +="42000311";"FastBuds Pound Cake Auto 3";36,00;19;;;"Seeds | FastBuds";; +="42000312";"FastBuds Pound Cake Auto 5";55,00;19;;;"Seeds | FastBuds";; +="42000313";"FastBuds Purple Haze Auto 1";13,00;19;;;"Seeds | FastBuds";; +="42000314";"FastBuds Purple Haze Auto 3";36,00;19;;;"Seeds | FastBuds";; +="42000315";"FastBuds Purple Haze Auto 5";55,00;19;;;"Seeds | FastBuds";; +="42000316";"FastBuds Purple Lemonade Auto 1";13,00;19;;;"Seeds | FastBuds";; +="42000317";"FastBuds Purple Lemonade Auto 3";36,00;19;;;"Seeds | FastBuds";; +="42000318";"FastBuds Purple Lemonade Auto 5";55,00;19;;;"Seeds | FastBuds";; +="42000319";"FastBuds Purple Lemonade FF 1";13,00;19;;;"Seeds | FastBuds";; +="42000320";"FastBuds Purple Lemonade FF 3";36,00;19;;;"Seeds | FastBuds";; +="42000321";"FastBuds Purple Lemonade FF 5";55,00;19;;;"Seeds | FastBuds";; +="42000322";"FastBuds Smoothie Auto 1";9,00;19;;;"Seeds | FastBuds";; +="42000323";"FastBuds Smoothie Auto 3";24,00;19;;;"Seeds | FastBuds";; +="42000324";"FastBuds Smoothie Auto 5";35,00;19;;;"Seeds | FastBuds";; +="42000325";"FastBuds Sour Jealousy Auto 1";13,00;19;;;"Seeds | FastBuds";; +="42000326";"FastBuds Sour Jealousy Auto 3";36,00;19;;;"Seeds | FastBuds";; +="42000327";"FastBuds Sour Jealousy Auto 5";55,00;19;;;"Seeds | FastBuds";; +="42000328";"FastBuds Strawberry Banana Auto 1";13,00;19;;;"Seeds | FastBuds";; +="42000329";"FastBuds Strawberry Banana Auto 3";36,00;19;;;"Seeds | FastBuds";; +="42000330";"FastBuds Strawberry Banana Auto 5";55,00;19;;;"Seeds | FastBuds";; +="42000331";"FastBuds Strawberry Pie Auto 1";13,00;19;;;"Seeds | FastBuds";; +="42000332";"FastBuds Strawberry Pie Auto 3";36,00;19;;;"Seeds | FastBuds";; +="42000333";"FastBuds Strawberry Pie Auto 5";55,00;19;;;"Seeds | FastBuds";; +="42000334";"FastBuds Super Boof Auto 1";13,00;19;;;"Seeds | FastBuds";; +="42000335";"FastBuds Super Boof Auto 3";36,00;19;;;"Seeds | FastBuds";; +="42000336";"FastBuds Super Boof Auto 5";55,00;19;;;"Seeds | FastBuds";; +="42000337";"FastBuds Tropicana Cookies Auto 1";13,00;19;;;"Seeds | FastBuds";; +="42000338";"FastBuds Tropicana Cookies Auto 3";36,00;19;;;"Seeds | FastBuds";; +="42000339";"FastBuds Tropicana Cookies Auto 5";55,00;19;;;"Seeds | FastBuds";; +="42000340";"FastBuds Tropicana Cookies FF 1";13,00;19;;;"Seeds | FastBuds";; +="42000341";"FastBuds Tropicana Cookies FF 3";36,00;19;;;"Seeds | FastBuds";; +="42000342";"FastBuds Tropicana Cookies FF 5";55,00;19;;;"Seeds | FastBuds";; +="42000343";"FastBuds Wedding Cheesecake FF 1";13,00;19;;;"Seeds | FastBuds";; +="42000344";"FastBuds Wedding Cheesecake FF 3";36,00;19;;;"Seeds | FastBuds";; +="42000345";"FastBuds Wedding Cheesecake FF 5";55,00;19;;;"Seeds | FastBuds";; +="42000349";"FastBuds Ztrawberriez Auto 1";13,00;19;;;"Seeds | FastBuds";; +="42000350";"FastBuds Ztrawberriez Auto 3";36,00;19;;;"Seeds | FastBuds";; +="42000351";"FastBuds Ztrawberriez Auto 5";55,00;19;;;"Seeds | FastBuds";; +="42000346";"FastBuds Z-Up Auto 1";13,00;19;;;"Seeds | FastBuds";; +="42000347";"FastBuds Z-Up Auto 3";36,00;19;;;"Seeds | FastBuds";; +="42000348";"FastBuds Z-Up Auto 5";55,00;19;;;"Seeds | FastBuds";; +="42001180";"Feldschlößchen Radler";0,00;19;;;"Getränke";;"V" +="42001180-1";"Feldschlößchen Radler Grapefruit";1,72;19;0,08;;"Getränke";;"K" +="42001180-2";"Feldschlößchen Radler Zitrone";1,72;19;0,08;;"Getränke";="4250594205695";"K" +="42000354";"Feuerzeug BIC";1,90;19;;;"Zubehör";; +="42000356";"Feuerzeug Brenner";3,00;19;;;"Zubehör";; +="42000357";"Feuerzeug Clicker";2,50;19;;;"Zubehör";; +="42000355";"Feuerzeug Clipper";2,00;19;;;"Zubehör";; +="42000358";"Feuerzeug Feuerstein Clipper";1,00;19;;;"Zubehör";; +="42000359";"Fishy Zoap Auto 1";17,00;19;;;"Seeds | Seedstockers";; +="42000360";"Fishy Zoap Auto 3";34,00;19;;;"Seeds | Seedstockers";; +="42000361";"Fishy Zoap Auto 5";51,00;19;;;"Seeds | Seedstockers";; +="42000362";"Fishy Zoap FEM 1";17,00;19;;;"Seeds | Seedstockers";; +="42000363";"Fishy Zoap FEM 3";34,00;19;;;"Seeds | Seedstockers";; +="42000364";"Fishy Zoap FEM 5";51,00;19;;;"Seeds | Seedstockers";; +="42000373";"Forbidden Mochi Auto 1";13,00;19;;;"Seeds | Seedstockers";; +="42000374";"Forbidden Mochi Auto 3";26,00;19;;;"Seeds | Seedstockers";; +="42000375";"Forbidden Mochi Auto 5";39,00;19;;;"Seeds | Seedstockers";; +="42000376";"Fred Jaune";6,70;19;;;"Tabak";="7640119424125"; +="42000377";"Fred Rose";6,95;19;;;"Tabak";="7640119424156"; +="42000378";"Fritz 0,33";1,92;19;0,08;;"Getränke";="4260107220015"; +="42000379";"Frosty Tooth FEM 1";17,00;19;;;"Seeds | Seedstockers";; +="42000380";"Frosty Tooth FEM 3";34,00;19;;;"Seeds | Seedstockers";; +="42000381";"Frosty Tooth FEM 5";51,00;19;;;"Seeds | Seedstockers";; +="42000382";"Fuze Tea";1,85;19;0,25;;"Getränke";; +="42000394";"Gelato 41 Auto 1";17,00;19;;;"Seeds | Seedstockers";; +="42000395";"Gelato 41 Auto 3";34,00;19;;;"Seeds | Seedstockers";; +="42000396";"Gelato 41 Auto 5";51,00;19;;;"Seeds | Seedstockers";; +="42000383";"GG4 Auto 1";17,00;19;;;"Seeds | Seedstockers";; +="42000384";"GG4 Auto 3";34,00;19;;;"Seeds | Seedstockers";; +="42000385";"GG4 Auto 5";51,00;19;;;"Seeds | Seedstockers";; +="42000397";"Girl Scout Cookies Auto 1";13,00;19;;;"Seeds | Seedstockers";; +="42000398";"Girl Scout Cookies Auto 3";26,00;19;;;"Seeds | Seedstockers";; +="42000399";"Girl Scout Cookies Auto 5";39,00;19;;;"Seeds | Seedstockers";; +="42000407";"Glasfilter 10mm Herb Shuttle";7,90;19;;;"Bong/Glasfilter";; +="42000406";"Glasfilter 12mm Herb Shuttle";9,90;19;;;"Bong/Glasfilter";; +="42000408";"Glasfilter Purize 9mm";9,90;19;;;"Bong/Glasfilter";; +="42001223";"Glass Kawum- L:10cm";3,00;19;;;"Bong/Glasfilter";="616695669509"; +="42001170";"Glucks 0,33l";2,00;19;0,08;;"Getränke";;"V" +="42001170-3";"Glucks 0,33l Helles";2,00;19;;;"Getränke";="4270000189241";"K" +="42001170-2";"Glucks 0,33l Pils";2,00;19;;;"Getränke";="4270000189227";"K" +="42001170-1";"Glucks 0,33l Radler";2,00;19;;;"Getränke";="4270000189265";"K" +="42001187";"Goldberg Soda";0,00;19;;;"Getränke";;"V" +="42001187-2";"Goldberg Soda Pink Grapefruit";1,85;19;0,15;;"Getränke";="4025127088768";"K" +="42001187-3";"Goldberg Soda Tonic Water";1,85;19;0,15;;"Getränke";="4025127027972";"K" +="42001187-1";"Goldberg Soda Wild Berry";1,85;19;0,15;;"Getränke";="4025127087471";"K" +="42000410";"Gorilla Cookies Auto 1";13,00;19;;;"Seeds | Seedstockers";; +="42000411";"Gorilla Cookies Auto 3";39,00;19;;;"Seeds | Seedstockers";; +="42000412";"Gorilla Cookies Auto 5";52,00;19;;;"Seeds | Seedstockers";; +="42000424";"Gösser Radler 0,5L";1,72;19;0,08;;"Getränke";="90288104"; +="42001227";"Grace Glass | Green Palm Tree – H:27cm – :50mm – SG:18.8mm";40,00;19;;;"Bong/Glasfilter";="616695688623"; +="42000414";"Green Crack Auto 1";17,50;19;;;"Seeds | Seedstockers";; +="42000415";"Green Crack Auto 3";29,00;19;;;"Seeds | Seedstockers";; +="42000416";"Green Crack Auto 5";43,50;19;;;"Seeds | Seedstockers";; +="42000419";"Grinder Champ High";17,50;19;;;"Grinder";; +="42000417";"Grinder Plaste";3,00;19;;;"Grinder";; +="42000420";"Grinder Purize Plaste";5,00;19;;;"Grinder";; +="42000423";"Grinder RAW Rot";28,90;19;;;"Grinder";="716165304104"; +="42000422";"Grinder RAW Schwarz";35,90;19;;;"Grinder";="716165304043"; +="42000418";"Grinder Würfel";5,00;19;;;"Grinder";; +="42000421";"Grinderkarte Woodzl";5,00;19;;;"Zubehör";; +="42000425";"Happy Amsterdam Amnesia Haze";34,50;19;;;"Vapes";="4262499460031"; +="42000426";"Happy Amsterdam Cali Exoticz";34,50;19;;;"Vapes";="4262499460000"; +="42000430";"Happy Amsterdam Cherry Kush";34,50;19;;;"Vapes";="4262499460062"; +="42000434";"Happy Amsterdam Forbidden Fruit";34,50;19;;;"Vapes";="4262499460079"; +="42000432";"Happy Amsterdam Golden OG Kush";34,50;19;;;"Vapes";; +="42000427";"Happy Amsterdam Mango Safari";34,50;19;;;"Vapes";="4262499460147"; +="42000429";"Happy Amsterdam Moroccan Hash";34,50;19;;;"Vapes";="4262499460017"; +="42000431";"Happy Amsterdam Purple Punch";34,50;19;;;"Vapes";="4262499460086"; +="42000428";"Happy Amsterdam Super Lemon Haze";34,50;19;;;"Vapes";="4262499460048"; +="42000433";"Happy Amsterdam Super Silver Haze";34,50;19;;;"Vapes";="4262499460024"; +="42000436";"Heineken 0,33L";1,82;19;0,08;;"Getränke";="8712000900663"; +="42001240";"Heineken 0,4l";1,92;19;0,08;;"Getränke";="8712000039370"; +="42001151";"Homebox Ambient Q60+ 60x60x160cm";95,00;19;;;"Grow | Zelte";; +="42001152";"Homebox Ambient Q80+ 80x80x180cm";120,00;19;;;"Grow | Zelte";="4260220922025"; +="42001283";"Homebox DryNet 60 cm";10,00;19;;;"Grow | Zubehör";="4260220921127"; +="42000438";"Humidor L";59,90;19;;;"Cannasseur";; +="42000437";"Humidor M";49,90;19;;;"Cannasseur";; +="42000439";"Humidor XL";69,90;19;;;"Cannasseur";; +="42000440";"Humidor XLA";69,90;19;;;"Cannasseur";; +="42000441";"Jack Herer Auto 1";13,00;19;;;"Seeds | Seedstockers";; +="42000442";"Jack Herer Auto 3";26,00;19;;;"Seeds | Seedstockers";; +="42000443";"Jack Herer Auto 5";39,00;19;;;"Seeds | Seedstockers";; +="42000444";"Jarritos 0,33l";2,45;19;0,15;;"Getränke";; +="42000445";"Javaanese Jongens";8,50;19;;;"Tabak";="42504436"; +="42001183";"Jever";0,00;19;;;"Getränke";;"V" +="42001183-1";"Jever Fun 0,0%";1,52;19;0,08;;"Getränke";;"K" +="42001183-2";"Jever Pilsner";1,52;19;0,08;;"Getränke";;"K" +="42000452";"Jointhülse";1,00;19;;;"Zubehör";; +="42000453";"Kamala OG 1";13,00;19;;;"Seeds | FastBuds";; +="42000454";"Kamala OG 3";36,00;19;;;"Seeds | FastBuds";; +="42000455";"Kamala OG 5";55,00;19;;;"Seeds | FastBuds";; +="42001317";"King Palm Mini Funnel";4,50;19;;;"Zubehör";="810089617156"; +="42001142";"King Palm Variety Flavors";24,90;19;;;"Smoke | King Palm";="810089616739"; +="42001176";"Kräuterbraut";1,92;19;0,08;;"Getränke";;"V" +="42001176-1";"Kräuterbraut Bergkräuter";1,92;19;0,08;;"Getränke";="4002846036812";"K" +="42001176-2";"Kräuterbraut Brombeere Rosmarin";1,92;19;0,08;;"Getränke";="4002846036850";"K" +="42001176-3";"Kräuterbraut Zitrone Minze";1,92;19;0,08;;"Getränke";="4002846036836";"K" +="42001250";"Krombacher Natur Radler";1,82;19;0,08;;"Getränke";="4008287940947"; +="42001219";"Kush Mintz";0,00;19;;;"Flowers | CBN";;"V" +="42001219-1";"Kush Mintz 1g";10,00;19;;;"Flowers | CBN";="4262557691575";"K" +="42001219-2";"Kush Mintz 2g";19,00;19;;;"Flowers | CBN";="4262557691582";"K" +="42001219-3";"Kush Mintz 5g";45,00;19;;;"Flowers | CBN";="4262557691599";"K" +="42001309";"LA Coast";0,00;19;;;"CBN_";;"V" +="42001309-1";"LA Coast 1g";0,00;19;;;"CBN_";="4262557691629";"K" +="42001309-2";"LA Coast 2g";0,00;19;;;"CBN_";="4262557691612";"K" +="42001309-3";"LA Coast 5g";0,00;19;;;"CBN_";="4262557691605";"K" +="42001236";"Lichtenauer PUR 0,5l";1,45;19;0,25;;"Getränke";="4013256642074"; +="42000469";"Lipton Pfirsich";1,65;19;0,25;;"Getränke";="4062139025039"; +="42000470";"Lipton Zitrone";1,65;19;0,25;;"Getränke";="4062139025015"; +="42000472";"Lößnitz Pils";1,52;19;0,08;;"Getränke";; +="42000471";"Lupe";17,90;19;;;"Cannasseur";; +="42000474";"Mack and Crack Auto 1";19,50;19;;;"Seeds | Seedstockers";; +="42000475";"Mack and Crack Auto 3";39,00;19;;;"Seeds | Seedstockers";; +="42000476";"Mack and Crack Auto 5";58,50;19;;;"Seeds | Seedstockers";; +="42000477";"Mandarin Panties Auto 1";17,00;19;;;"Seeds | Seedstockers";; +="42000478";"Mandarin Panties Auto 3";34,00;19;;;"Seeds | Seedstockers";; +="42000479";"Mandarin Panties Auto 5";51,00;19;;;"Seeds | Seedstockers";; +="42000482";"Manitou Grün";7,00;19;;;"Tabak";="4006396103789"; +="42000481";"Manitou Orange";7,00;19;;;"Tabak";="4006396103819"; +="42001297";"Maxibright VARIDRIVE 360W LED";155,00;19;;;"Grow | Lampen";="5060403594518"; +="42001251";"Membran Kompressor";0,00;19;;;"Grow | AutoPot";;"V" +="42001251-1";"Membran Kompressor MK-0502";26,90;19;;;"Grow | AutoPot";="4250247608194";"K" +="42001251-2";"Membran Kompressor MK-9510";47,90;19;;;"Grow | AutoPot";="4250247608200";"K" +="42001122";"Milk Cookie CBD";0,00;19;;;"Flowers | CBD";;"V" +="42001122-1";"Milk Cookie CBD 1g";5,00;19;;;"Flowers | CBD";="4262557690158";"K" +="42001122-2";"Milk Cookie CBD 2g";9,00;19;;;"Flowers | CBD";="4262557690165";"K" +="42001122-3";"Milk Cookie CBD 5g";22,50;19;;;"Flowers | CBD";="4262557690172";"K" +="42001205";"Milk&Cookie";0,00;19;;;"CBN_";;"V" +="42001205-1";"Milk&Cookie 1g";0,00;19;;;"CBN_";="4262557690547";"K" +="42001205-2";"Milk&Cookie 2g";0,00;19;;;"CBN_";="4262557690554";"K" +="42001205-3";"Milk&Cookie 5g";0,00;19;;;"CBN_";="4262557690561";"K" +="42001218";"Milk/Cookie";0,00;19;;;"CBD_";;"V" +="42001218-1";"Milk/Cookie 1g";0,00;19;;;"CBD_";;"K" +="42001218-2";"Milk/Cookie 2g";0,00;19;;;"CBD_";;"K" +="42001168";"Milwaukee Ph600";25,00;19;;;"Grow | Messgeräte";="5999567670007"; +="42001179";"Mio Mio";0,00;19;;;"Getränke";;"V" +="42001179-4";"Mio Mio Banane";1,95;19;0,15;;"Getränke";="4002846034559";"K" +="42001179-2";"Mio Mio Cola";1,95;19;0,15;;"Getränke";="4002846034306";"K" +="42001179-3";"Mio Mio Lemon + Koffein";1,95;19;0,15;;"Getränke";="4002846034894";"K" +="42001179-1";"Mio Mio Mate 0,33l";1,95;19;0,15;;"Getränke";="4002846034443";"K" +="42001179-5";"Mio Mio Mate 0,5l";1,95;19;0,15;;"Getränke";="4002846034504";"K" +="42000510";"Mixery Dose";2,25;19;0,25;;"Getränke";="4002631028114"; +="42000511";"Mole";1,92;19;0,08;;"Getränke";; +="42000516";"Muza Clementine";8,95;19;;;"Tabak";="7290019822103"; +="42001136";"Muza Hemp Original";8,95;19;;;"Tabak";="7290019822097"; +="42000513";"Muza Indica";11,95;19;;;"Tabak";="7290019822004"; +="42001237";"Muza Lemon Haze";8,95;19;;;"Tabak";="7290019822639"; +="42000514";"Muza Neutral";11,95;19;;;"Tabak";="7290019822028"; +="42000512";"Muza Sativa";11,95;19;;;"Tabak";="7290019822011"; +="42000515";"Muza Super Kush";8,95;19;;;"Tabak";="7290019822493"; +="42000517";"Mystery Pack";20,00;19;;;"Flowers | CBD";; +="42000518";"Natur of Spirit Watermelon";12,00;19;;;"Tabak";; +="42001233";"NBoost | Cane Glass Bong - H:38cm -Ø:50mm - Socket:18.8mm- WT:5mm";38,00;19;;;"Bong/Glasfilter";="616695665631"; +="42001262";"Neu";0,00;19;;;"Grow | AutoPot";; +="42001267";"NV Glasfilter";0,00;19;;;"Bong/Glasfilter";;"V" +="42001267-4";"NV Glasfilter 10mm";15,90;19;;;"Bong/Glasfilter";;"K" +="42001267-1";"NV Glasfilter 7mm";12,90;19;;;"Bong/Glasfilter";;"K" +="42001267-2";"NV Glasfilter 8mm";13,90;19;;;"Bong/Glasfilter";;"K" +="42001267-3";"NV Glasfilter 9mm";14,90;19;;;"Bong/Glasfilter";;"K" +="42001178";"Oettinger";1,52;19;0,08;;"Getränke";;"V" +="42001178-1";"Oettinger Eistte Pfirsich";1,52;19;0,08;;"Getränke";="4014086011801";"K" +="42001178-2";"Oettinger Eistte Zitrone";1,52;19;0,08;;"Getränke";="4014086011818";"K" +="42001178-3";"Oettinger Fassbrause";1,52;19;0,08;;"Getränke";="4014086011573";"K" +="42001188";"Oppacher Holunderblüte";1,72;19;0,08;;"Getränke";="4043533006626"; +="42000526";"Orangina 0,33L";1,65;19;0,25;;"Getränke";; +="42000527";"Panty Punch Auto 1";19,50;19;;;"Seeds | Seedstockers";; +="42000528";"Panty Punch Auto 3";39,00;19;;;"Seeds | Seedstockers";; +="42000529";"Panty Punch Auto 5";58,50;19;;;"Seeds | Seedstockers";; +="42000530";"PaperBank";4,00;19;;;"Zubehör";; +="42001311";"Paris Lemon";0,00;19;;;"CBN_";;"V" +="42001311-1";"Paris Lemon 1g";0,00;19;;;"CBN_";="4262557691667";"K" +="42001311-2";"Paris Lemon 2g";0,00;19;;;"CBN_";="4262557691308";"K" +="42001311-3";"Paris Lemon 5g";0,00;19;;;"CBN_";="4262557691315";"K" +="42000531";"Paulaner Spezi 0,5L";1,72;19;0,08;;"Getränke";="4066600603405"; +="42001104-3";"Peach 10g";75,00;19;;;"Flowers | CBN";;"K" +="42001104-4";"Peach 15g";108,50;19;;;"Flowers | CBN";;"K" +="42001104-2";"Peach 1g";9,00;19;;;"Flowers | CBN";="4262557691117";"K" +="42001104-6";"Peach 20g";140,00;19;;;"Flowers | CBN";;"K" +="42001104-7";"Peach 25g";168,50;19;;;"Flowers | CBN";;"K" +="42001104-5";"Peach 2g";17,00;19;;;"Flowers | CBN";="4262557691124";"K" +="42001104-1";"Peach 30g";195,00;19;;;"Flowers | CBN";;"K" +="42001104-8";"Peach 3g";25,00;19;;;"Flowers | CBN";;"K" +="42001104-9";"Peach 5g";40,00;19;;;"Flowers | CBN";="4262557691131";"K" +="42001131";"Peach CBD";0,00;19;;;"Flowers | CBD";;"V" +="42001131-7";"Peach CBD 10g";55,00;19;;;"Flowers | CBD";;"K" +="42001131-6";"Peach CBD 15g";75,00;19;;;"Flowers | CBD";;"K" +="42001131-8";"Peach CBD 1g";7,50;19;;;"Flowers | CBD";="4262557691421";"K" +="42001131-5";"Peach CBD 20g";95,00;19;;;"Flowers | CBD";;"K" +="42001131-4";"Peach CBD 25g";110,00;19;;;"Flowers | CBD";;"K" +="42001131-1";"Peach CBD 2g";14,00;19;;;"Flowers | CBD";="4262557691438";"K" +="42001131-3";"Peach CBD 30g";125,00;19;;;"Flowers | CBD";;"K" +="42001131-2";"Peach CBD 5g";30,00;19;;;"Flowers | CBD";="4262557691445";"K" +="42001104";"Peach CBN";0,00;19;;;"Flowers | CBN";;"V" +="42001111";"Peach Cotton Candy";0,00;19;;;"Flowers | CBN";;"V" +="42001111-9";"Peach Cotton Candy 10g";90,00;19;;;"Flowers | CBN";;"K" +="42001111-8";"Peach Cotton Candy 15g";125,00;19;;;"Flowers | CBN";;"K" +="42001111-1";"Peach Cotton Candy 1g";11,00;19;;;"Flowers | CBN";="4262557691261";"K" +="42001111-6";"Peach Cotton Candy 20g";160,00;19;;;"Flowers | CBN";;"K" +="42001111-5";"Peach Cotton Candy 25g";194,00;19;;;"Flowers | CBN";;"K" +="42001111-7";"Peach Cotton Candy 2g";21,00;19;;;"Flowers | CBN";="4262557691278";"K" +="42001111-3";"Peach Cotton Candy 30g";225,00;19;;;"Flowers | CBN";;"K" +="42001111-4";"Peach Cotton Candy 3g";31,50;19;;;"Flowers | CBN";;"K" +="42001111-2";"Peach Cotton Candy 5g";50,00;19;;;"Flowers | CBN";="4262557691285";"K" +="42000559";"Pepe Bright Green";6,30;19;;;"Tabak";="4006396103635"; +="42000558";"Pepe Dark Green";5,90;19;;;"Tabak";="4006396068484"; +="42000560";"Pepe Fine Green";6,30;19;;;"Tabak";="4006396103666"; +="42001134";"Pepe Rich Green";6,30;19;;;"Tabak";="4006396103604"; +="42000561";"Pfeife klein/groß";5,00;19;;;"Zubehör";; +="42001141";"Pfeiffe groß mit 5 Sieben";5,00;19;;;"Bong/Glasfilter";="4031872340693"; +="42001140";"Pfeiffe klein mit 5 Sieben";5,00;19;;;"Bong/Glasfilter";="4031872340631"; +="42001101";"Piatella";0,00;19;;;"Flowers | CBN";;"V" +="42001101-3";"Piatella 10g";105,00;19;;;"Flowers | CBN";;"K" +="42001101-4";"Piatella 15g";150,00;19;;;"Flowers | CBN";;"K" +="42001101-2";"Piatella 1g";12,50;19;;;"Flowers | CBN";="4262557691056";"K" +="42001101-6";"Piatella 20g";190,00;19;;;"Flowers | CBN";;"K" +="42001101-7";"Piatella 25g";230,00;19;;;"Flowers | CBN";;"K" +="42001101-5";"Piatella 2g";24,00;19;;;"Flowers | CBN";="4262557691063";"K" +="42001101-9";"Piatella 30g";265,00;19;;;"Flowers | CBN";;"K" +="42001101-8";"Piatella 3g";36,00;19;;;"Flowers | CBN";;"K" +="42001101-1";"Piatella 5g";55,00;19;;;"Flowers | CBN";="4262557691070";"K" +="42001300";"Plagron Perlite 10 l";8,50;19;;;"Grow | Erde";="8718104121553"; +="42001189";"Pound Cake";0,00;19;;;"Flowers | CBN";;"V" +="42001189-1";"Pound Cake 1g";11,00;19;;;"Flowers | CBN";="4262557691230";"K" +="42001189-2";"Pound Cake 2g";21,00;19;;;"Flowers | CBN";="4262557691247";"K" +="42001189-3";"Pound Cake 5g";50,00;19;;;"Flowers | CBN";="4262557691254";"K" +="42001291";"Prima Klima PK-Kombo 125-1S, 125 mm, 360 m3/h";145,00;19;;;"Grow | Abluft";="8594171430466"; +="42001290";"Prima Klima PK-Kombo 125-TC, 125 mm, 400 m3/h";199,00;19;;;"Grow | Abluft";="8594171430459"; +="42001206";"Pudding";0,00;19;;;"Flowers | CBN";;"V" +="42001206-1";"Pudding 2g";0,00;19;;;"Flowers | CBN";="4262557690493";"K" +="42000594";"Pueblo Beige";6,75;19;;;"Tabak";="42487661"; +="42000595";"Pueblo Blau";6,75;19;;;"Tabak";="42487647"; +="42000597";"Pueblo Braun";6,50;19;;;"Tabak";="42464730"; +="42000596";"Pueblo Pink";6,75;19;;;"Tabak";="42487845"; +="42000655";"Pülleken 0,33";1,82;19;0,08;;"Getränke";="4005249061702"; +="42000651";"Purple Punch Auto 1";13,00;19;;;"Seeds | Seedstockers";; +="42000652";"Purple Punch Auto 3";26,00;19;;;"Seeds | Seedstockers";; +="42000653";"Purple Punch Auto 5";39,00;19;;;"Seeds | Seedstockers";; +="42001239";"Radeberger 0,33l";1,52;19;0,08;;"Getränke";="4014388001012"; +="42001288";"RAM 400 ml/h, 5 l";65,00;19;;;"Grow | Zubehör";="5034517802180"; +="42001215";"Ramen";0,00;19;;;"CBD_";;"V" +="42001215-1";"Ramen 1g";0,00;19;;;"CBD_";="4262557690004";"K" +="42001215-2";"Ramen 2g";0,00;19;;;"CBD_";;"K" +="42001184";"RedBull";0,00;19;;;"Getränke";;"V" +="42001184-2";"RedBull Cola";2,25;19;0,25;;"Getränke";;"K" +="42001184-3";"RedBull Organic Orange";2,25;19;0,25;;"Getränke";="9002490278960";"K" +="42001184-4";"RedBull Pfirsich";2,25;19;0,25;;"Getränke";="90474903";"K" +="42001184-1";"RedBull Spring Edition";2,25;19;0,25;;"Getränke";="90486883";"K" +="42000666";"RedBull Winter Edition";2,25;19;0,25;;"Getränke";; +="42000673";"S.Pellegrino 0,25L";1,25;19;0,15;;"Getränke";;"V" +="42000673-2";"S.Pellegrino 0,25L Sprudel";1,25;19;0,15;;"Getränke";="8002270011030";"K" +="42000690";"Salitos";2,22;19;0,08;;"Getränke";;"V" +="42000690-1";"Salitos Mojito";2,22;19;;;"Getränke";="4025127085354";"K" +="42000690-2";"Salitos Pink";2,22;19;;;"Getränke";="4025127085071";"K" +="42000691";"Santa Marta Haze Auto 1";13,00;19;;;"Seeds | Seedstockers";; +="42000692";"Santa Marta Haze Auto 3";26,00;19;;;"Seeds | Seedstockers";; +="42000693";"Santa Marta Haze Auto 5";39,00;19;;;"Seeds | Seedstockers";; +="42000694";"Sherbet Auto 1";13,00;19;;;"Seeds | Seedstockers";; +="42000695";"Sherbet Auto 3";39,00;19;;;"Seeds | Seedstockers";; +="42000696";"Sherbet Auto 5";52,00;19;;;"Seeds | Seedstockers";; +="42001312";"Shinys Grape";0,00;19;;;"CBN_";;"V" +="42001312-1";"Shinys Grape 1g";0,00;19;;;"CBN_";="4262557691353";"K" +="42001312-2";"Shinys Grape 2g";0,00;19;;;"CBN_";="4262557691360";"K" +="42001312-3";"Shinys Grape 5g";0,00;19;;;"CBN_";="4262557691377";"K" +="42000689";"SHS";34,90;19;;;"Cannasseur";; +="42001220";"Skruf";0,00;19;;;"Tabak";;"V" +="42001220-1";"Skruf 2";7,50;19;;;"Tabak";="4030500025216";"K" +="42001220-2";"Skruf 3";7,50;19;;;"Tabak";="4030500025247";"K" +="42001220-3";"Skruf 4";7,50;19;;;"Tabak";="4030500025278";"K" +="42001210";"Sour Diesel";0,00;19;;;"CBN_";;"V" +="42001210-1";"Sour Diesel 1g";0,00;19;;;"CBN_";="4262557690608";"K" +="42001210-2";"Sour Diesel 2g";0,00;19;;;"CBN_";="4262557690615";"K" +="42001210-3";"Sour Diesel 5g";0,00;19;;;"CBN_";="4262557690622";"K" +="42000715";"Sour Diesel Auto 1";7,50;19;;;"Seeds | Seedstockers";; +="42000716";"Sour Diesel Auto 3";23,00;19;;;"Seeds | Seedstockers";; +="42000717";"Sour Diesel Auto 5";34,50;19;;;"Seeds | Seedstockers";; +="42001124";"Sour Diesel CBD";0,00;19;;;"Flowers | CBD";;"V" +="42001124-1";"Sour Diesel CBD 1g";10,00;19;;;"Flowers | CBD";="4262557690219";"K" +="42001124-2";"Sour Diesel CBD 2g";19,00;19;;;"Flowers | CBD";="4262557690226";"K" +="42001124-3";"Sour Diesel CBD 5g";45,00;19;;;"Flowers | CBD";="4262557690233";"K" +="42000718";"Spaten 0,5l";2,02;19;0,08;;"Getränke";="4072700005315"; +="42001248";"Sprite 0,5l";2,12;19;0,08;;"Getränke";="54491182"; +="42000719";"Stardawg Auto 1";4,25;19;;;"Seeds | Seedstockers";; +="42000720";"Stardawg Auto 3";8,50;19;;;"Seeds | Seedstockers";; +="42000721";"Stardawg Auto 5";12,75;19;;;"Seeds | Seedstockers";; +="42000574";"Steel Pipe Screen 15mm";2,00;19;;;"Zubehör";="4250853502060"; +="42000572";"Steel Pipe Screen 9mm";2,00;19;;;"Zubehör";="4250853502046"; +="42000722";"Sternburg 0,5L";1,52;19;0,08;;"Getränke";="41057759"; +="42000724";"Sticky Fingers Auto 1";14,50;19;;;"Seeds | Seedstockers";; +="42000725";"Sticky Fingers Auto 3";29,00;19;;;"Seeds | Seedstockers";; +="42000726";"Sticky Fingers Auto 5";43,50;19;;;"Seeds | Seedstockers";; +="42000728";"Super Boof Auto 1";11,50;19;;;"Seeds | Seedstockers";; +="42000729";"Super Boof Auto 3";23,00;19;;;"Seeds | Seedstockers";; +="42000730";"Super Boof Auto 5";34,50;19;;;"Seeds | Seedstockers";; +="42000731";"Super Skunk Auto 1";9,50;19;;;"Seeds | Seedstockers";; +="42000732";"Super Skunk Auto 3";19,00;19;;;"Seeds | Seedstockers";; +="42000733";"Super Skunk Auto 5";28,50;19;;;"Seeds | Seedstockers";; +="42001162";"Taifun Flat Fan";28,00;19;;;"Grow | Abluft";="1400010000011"; +="42001160";"Taifun TT100 Flansch 100mm 180 m^3 ";40,00;19;;;"Grow | Abluft";="4260430860674"; +="42001161";"Taifun TT125 Flansch 125mm 280 m^3";60,00;19;;;"Grow | Abluft";="4260430860681"; +="42001213";"Tante Emma";0,00;19;;;"CBN_";;"V" +="42001130-3";"Tante Emma 10g";85,00;19;;;"Flowers | CBD";;"K" +="42001130-4";"Tante Emma 15g";123,50;19;;;"Flowers | CBD";;"K" +="42001130-2";"Tante Emma 1g";10,00;19;;;"Flowers | CBD";="4262557691391";"K" +="42001213-1";"Tante Emma 1g";0,00;19;;;"CBN_";="4262557691179";"K" +="42001130-6";"Tante Emma 20g";160,00;19;;;"Flowers | CBD";;"K" +="42001130-7";"Tante Emma 25g";194,00;19;;;"Flowers | CBD";;"K" +="42001130-5";"Tante Emma 2g";19,00;19;;;"Flowers | CBD";="4262557691407";"K" +="42001213-2";"Tante Emma 2g";0,00;19;;;"CBN_";="4262557691186";"K" +="42001130-8";"Tante Emma 30g";225,00;19;;;"Flowers | CBD";;"K" +="42001130-1";"Tante Emma 5g";45,00;19;;;"Flowers | CBD";="4262557691414";"K" +="42001213-3";"Tante Emma 5g";0,00;19;;;"CBN_";="4262557691193";"K" +="42001130";"Tante Emma CBD";0,00;19;;;"Flowers | CBD";;"V" +="42000745";"Terp&Tonic Auto 1";19,50;19;;;"Seeds | Seedstockers";; +="42000746";"Terp&Tonic Auto 3";39,00;19;;;"Seeds | Seedstockers";; +="42000747";"Terp&Tonic Auto 5";58,50;19;;;"Seeds | Seedstockers";; +="42000748";"Thunder Banana Auto 1";14,50;19;;;"Seeds | Seedstockers";; +="42000749";"Thunder Banana Auto 3";29,00;19;;;"Seeds | Seedstockers";; +="42000750";"Thunder Banana Auto 5";43,50;19;;;"Seeds | Seedstockers";; +="42000756";"Tray Elements Glas Groß";9,90;19;;;"Zubehör";; +="42000754";"Tray Elements Glas Klein";4,90;19;;;"Zubehör";; +="42000752";"Tray Liquid";9,90;19;;;"Cannasseur";; +="42000755";"Tray Purize";9,90;19;;;"Zubehör";; +="42000751";"Tray Standard";8,90;19;;;"Cannasseur";; +="42000753";"Tray Trippy";9,90;19;;;"Cannasseur";; +="42001282";"Trim Bin Harvest Cut Tray";80,00;19;;;"Grow | Zubehör";="713757640237"; +="42000758";"Triton Biscotto Lime Auto 1";17,00;19;;;"Seeds | Seedstockers";; +="42000759";"Triton Biscotto Lime Auto 3";34,00;19;;;"Seeds | Seedstockers";; +="42000760";"Triton Biscotto Lime Auto 5";51,00;19;;;"Seeds | Seedstockers";; +="42000761";"Tropical Smoothie FEM 1";19,50;19;;;"Seeds | Seedstockers";; +="42000762";"Tropical Smoothie FEM 3";39,00;19;;;"Seeds | Seedstockers";; +="42000763";"Tropical Smoothie FEM 5";58,50;19;;;"Seeds | Seedstockers";; +="42000764";"Tropical Zmoothie Auto 1";19,50;19;;;"Seeds | Seedstockers";; +="42000765";"Tropical Zmoothie Auto 3";39,00;19;;;"Seeds | Seedstockers";; +="42000766";"Tropical Zmoothie Auto 5";58,50;19;;;"Seeds | Seedstockers";; +="42000767";"Tyski 0,5l";2,02;19;0,08;;"Getränke";="5901359062013"; +="42001287";"U Gro Small Basic 11 l Kokos";5,00;19;;;"Grow | Erde";="609224329999"; +="42001302";"U Gro Small Rhiza 11 l";5,50;19;;;"Grow | Erde";="609224330315"; +="42001271";"Urban Bubble Bags 3 Stk.";35,00;19;;;"Grow | Zubehör";="8594200879716"; +="42001270";"Urban Bubble Bags 5 Stk.";65,00;19;;;"Grow | Zubehör";="8594200879709"; +="42001284";"Urban Mechanical Timer Socket";10,00;19;;;"Grow | Zubehör";="8595722026220"; +="42001099";"Vending Machine";0,00;19;;;"Flowers | CBN";;"V" +="42001099-2";"Vending Machine 10g";85,00;19;;;"Flowers | CBN";;"K" +="42001099-3";"Vending Machine 15g";120,00;19;;;"Flowers | CBN";;"K" +="42001099-1";"Vending Machine 1g";10,00;19;;;"Flowers | CBN";="4262557691162";"K" +="42001099-5";"Vending Machine 20g";155,00;19;;;"Flowers | CBN";;"K" +="42001099-6";"Vending Machine 25g";185,00;19;;;"Flowers | CBN";;"K" +="42001099-4";"Vending Machine 2g";19,00;19;;;"Flowers | CBN";="4262557691155";"K" +="42001099-8";"Vending Machine 30g";210,00;19;;;"Flowers | CBN";;"K" +="42001099-7";"Vending Machine 3g";28,50;19;;;"Flowers | CBN";;"K" +="42001099-9";"Vending Machine 5g";45,00;19;;;"Flowers | CBN";="4262557691148";"K" +="42001207";"White Melon";0,00;19;;;"Flowers | CBN";;"V" +="42001207-1";"White Melon 1g";11,00;19;;;"Flowers | CBN";="4262557691513";"K" +="42001207-2";"White Melon 2g";0,00;19;;;"Flowers | CBN";="4262557691520";"K" +="42001207-3";"White Melon 5g";0,00;19;;;"Flowers | CBN";="4262557691537";"K" +="42000777";"White Widow Auto 1";13,00;19;;;"Seeds | Seedstockers";; +="42000778";"White Widow Auto 3";26,00;19;;;"Seeds | Seedstockers";; +="42000779";"White Widow Auto 5";39,00;19;;;"Seeds | Seedstockers";; +="42001243";"Wildfire Glass Pipe";5,00;19;;;"Bong/Glasfilter";="9010210080298"; +="42000028";"Woodzl Bamboo Guard";8,00;19;;;"Zubehör";; +="42001146";"Zig Zag Slime Size 6mm";1,50;19;;;"Smoke | Tips/Filter";="3057068006984"; +="42001127";"Zushi CBD";0,00;19;;;"Flowers | CBD";;"V" +="42001127-3";"Zushi CBD 10g";85,00;19;;;"Flowers | CBD";;"K" +="42001127-4";"Zushi CBD 15g";120,00;19;;;"Flowers | CBD";;"K" +="42001127-2";"Zushi CBD 1g";10,00;19;;;"Flowers | CBD";="4262557690998";"K" +="42001127-6";"Zushi CBD 20g";155,00;19;;;"Flowers | CBD";;"K" +="42001127-7";"Zushi CBD 25g";185,00;19;;;"Flowers | CBD";;"K" +="42001127-5";"Zushi CBD 2g";19,00;19;;;"Flowers | CBD";="4262557691001";"K" +="42001127-1";"Zushi CBD 30g";210,00;19;;;"Flowers | CBD";;"K" +="42001127-8";"Zushi CBD 3g";28,50;19;;;"Flowers | CBD";;"K" +="42001127-9";"Zushi CBD 5g";45,00;19;;;"Flowers | CBD";="4262557691018";"K" +="42001181";"ZWO";1,92;19;0,08;;"Getränke";;"V" +="42001181-5";"ZWO Cola";1,92;19;0,08;;"Getränke";="4260657791485";"K" +="42001181-1";"ZWO Holunder";1,92;19;0,08;;"Getränke";="4260657791607";"K" +="42001181-2";"ZWO Honigmelone";1,92;19;0,08;;"Getränke";="4260657791621";"K" +="42001181-4";"ZWO Orange";1,92;19;0,08;;"Getränke";="4260657791584";"K" +="42001181-3";"ZWO Zitrone";1,92;19;0,08;;"Getränke";="4260657791560";"K" +="42001261";"1 Pot 15L System inkl. 47L Wasserfass";104,90;19;;"AutoPot";"Grow | AutoPot";; +="42001257";"1 Pot 8L System inkl. 47L Wasserfass";69,90;19;;"AutoPot";"Grow | AutoPot";; +="42001254";"1 Pot XL 25L System inkl. 47L Wasserfass";79,90;19;;"AutoPot";"Grow | AutoPot";; +="42001264";"2 Pot 15L System inkl. 47L Wasserfass";109,90;19;;"AutoPot";"Grow | AutoPot";; +="42001258";"2 Pot 8L System inkl. 47L Wasserfass";99,90;19;;"AutoPot";"Grow | AutoPot";; +="42001255";"2 Pot XL 25L System inkl. 47L Wasserfass";109,90;19;;"AutoPot";"Grow | AutoPot";; +="42001265";"3 Pot 15L System inkl. 47L Wasserfass";149,90;19;;"AutoPot";"Grow | AutoPot";; +="42001259";"3 Pot 8L System inkl. 47L Wasserfass";134,90;19;;"AutoPot";"Grow | AutoPot";; +="42001263";"3 Pot XL 25L System inkl. 47L Wasserfass";139,90;19;;"AutoPot";"Grow | AutoPot";; +="42000984";"AutoPot 15 Liter Topf";0,00;19;;"AutoPot";"Grow | AutoPot";; +="42000985";"AutoPot 1Pot Tray und Deckel";0,00;19;;"AutoPot";"Grow | AutoPot";; +="42000981";"AutoPot 1Pot XL Tray und Deckel";0,00;19;;"AutoPot";"Grow | AutoPot";; +="42000982";"AutoPot 25 Liter Topf für 1Pot XL";0,00;19;;"AutoPot";"Grow | AutoPot";; +="42000997";"AutoPot 2Pot System (incl. 47 Liter tank)";0,00;19;;"AutoPot";"Grow | AutoPot";; +="42001008";"AutoPot 2x 8,5Liter + 47L Tank Set ";90,00;19;;"AutoPot";"Grow | AutoPot";; +="42000995";"AutoPot 30L Tank mit 9mm Tülle und Deckel";0,00;19;;"AutoPot";"Grow | AutoPot";; +="42001010";"AutoPot 3x 15Liter + 47L Tank Set";130,00;19;;"AutoPot";"Grow | AutoPot";; +="42001009";"AutoPot 3x 8,5Liter + 47L Tank Set";120,00;19;;"AutoPot";"Grow | AutoPot";; +="42000996";"AutoPot 47L Tank mit 9mm Tülle und Deckel";29,00;19;;"AutoPot";"Grow | AutoPot";; +="42000983";"AutoPot 8,5 Liter Topf";0,00;19;;"AutoPot";"Grow | AutoPot";; +="42000990";"AutoPot 9mm Inline Absperrhahn";0,00;19;;"AutoPot";"Grow | AutoPot";; +="42000980";"AutoPot 9mm Schlauch (blau)";0,00;19;;"AutoPot";"Grow | AutoPot";; +="42000991";"AutoPot 9mm T-Kupplung";0,00;19;;"AutoPot";"Grow | AutoPot";; +="42000992";"AutoPot 9mm Tülle";0,00;19;;"AutoPot";"Grow | AutoPot";; +="42000993";"AutoPot 9mm Wasserfilter inklusive. Filtermaterial";0,00;19;;"AutoPot";"Grow | AutoPot";; +="42000989";"AutoPot AirBase quadratisch für 8,5L Topf und 15L Topf";8,90;19;;"AutoPot";"Grow | AutoPot";="5060151875457"; +="42000988";"AutoPot AirBase Rund für 20L Topf und 25L Topf";9,90;19;;"AutoPot";"Grow | AutoPot";="5060151875464"; +="42000979";"AutoPot AirDome Kit";0,00;19;;"AutoPot";"Grow | AutoPot";; +="42000987";"AutoPot Schlauchbürste – 9mm & 16mm Bürstenkopf";0,00;19;;"AutoPot";"Grow | AutoPot";; +="42000986";"AutoPot Zubehörpaket für 1Pot Modul – mit AQUAvalve5";0,00;19;;"AutoPot";"Grow | AutoPot";; +="42000994";"AutoPot Zubehörpaket für 1Pot XL – mit AQUAvalve5";0,00;19;;"AutoPot";"Grow | AutoPot";; +="42001191";"BioBizz Acti Vera";0,00;19;;"BioBizz";"Grow | Dünger";;"V" +="42001191-1";"BioBizz Acti Vera 1l";23,00;19;;"BioBizz";"Grow | Dünger";="8718403232523";"K" +="42001191-2";"BioBizz Acti Vera 250ml";9,00;19;;"BioBizz";"Grow | Dünger";="8718403232509";"K" +="42001191-3";"BioBizz Acti Vera 500ml";14,50;19;;"BioBizz";"Grow | Dünger";="8718403232516";"K" +="42001192";"BioBizz Alg A Mic";0,00;19;;"BioBizz";"Grow | Dünger";;"V" +="42001192-2";"BioBizz Alg A Mic 1l";24,00;19;;"BioBizz";"Grow | Dünger";="8718403231236";"K" +="42001192-1";"BioBizz Alg A Mic 250ml";6,50;19;;"BioBizz";"Grow | Dünger";="8718403232196";"K" +="42001192-3";"BioBizz Alg A Mic 500ml";9,50;19;;"BioBizz";"Grow | Dünger";="8718403231250";"K" +="42000042";"BioBizz AllMix 20L";12,50;19;;"BioBizz";"Grow | Erde";; +="42000043";"BioBizz AllMix 50L";15,00;19;;"BioBizz";"Grow | Erde";="8718403231595"; +="42000044";"BioBizz AllMix Peat Free 20L";13,50;19;;"BioBizz";"Grow | Erde";="8718403234763"; +="42000045";"BioBizz AllMix Peat Free 50L";21,50;19;;"BioBizz";"Grow | Erde";="8718403234749"; +="42001193";"BioBizz Bio Heaven";0,00;19;;"BioBizz";"Grow | Dünger";;"V" +="42001193-1";"BioBizz Bio Heaven 250ml";28,00;19;;"BioBizz";"Grow | Dünger";="8718403231564";"K" +="42001193-2";"BioBizz Bio Heaven 500ml";30,00;19;;"BioBizz";"Grow | Dünger";="8718403231540";"K" +="42001195";"BioBizz Bio PH Up";0,00;19;;"BioBizz";"Grow | Dünger";;"V" +="42001195-3";"BioBizz Bio PH Up 1l";20,00;19;;"BioBizz";"Grow | Dünger";="8718403232912";"K" +="42001195-1";"BioBizz Bio PH Up 250ml";7,00;19;;"BioBizz";"Grow | Dünger";="8718403232875";"K" +="42001195-2";"BioBizz Bio PH Up 500ml";12,00;19;;"BioBizz";"Grow | Dünger";="8718403232899";"K" +="42001194";"Biobizz BioBio PH Down";0,00;19;;"BioBizz";"Grow | Dünger";;"V" +="42001194-3";"Biobizz BioBio PH Down 1l";21,00;19;;"BioBizz";"Grow | Dünger";;"K" +="42001194-1";"Biobizz BioBio PH Down 250ml";7,00;19;;"BioBizz";"Grow | Dünger";="8718403232967";"K" +="42001194-2";"Biobizz BioBio PH Down 500ml";12,00;19;;"BioBizz";"Grow | Dünger";="8718403232981";"K" +="42001196";"BioBizz Bloom";0,00;19;;"BioBizz";"Grow | Dünger";;"V" +="42001196-2";"BioBizz Bloom 1l";16,70;19;;"BioBizz";"Grow | Dünger";="000420008938";"K" +="42001196-3";"BioBizz Bloom 250ml";5,00;19;;"BioBizz";"Grow | Dünger";;"K" +="42001196-1";"BioBizz Bloom 500ml";9,00;19;;"BioBizz";"Grow | Dünger";;"K" +="42001198";"BioBizz CalMag";0,00;19;;"BioBizz";"Grow | Dünger";;"V" +="42001198-2";"BioBizz CalMag 1l";20,00;19;;"BioBizz";"Grow | Dünger";="000420008945";"K" +="42001198-3";"BioBizz CalMag 250ml";7,00;19;;"BioBizz";"Grow | Dünger";="000420000536";"K" +="42001198-1";"BioBizz CalMag 500ml";12,00;19;;"BioBizz";"Grow | Dünger";="8718403233377";"K" +="42000054";"BioBizz CocoMix 50l";15,90;19;;"BioBizz";"Grow | Erde";="8718403231670"; +="42001199";"BioBizz FishMix";0,00;19;;"BioBizz";"Grow | Dünger";;"V" +="42001199-2";"BioBizz FishMix 1l";14,00;19;;"BioBizz";"Grow | Dünger";="8718403231298";"K" +="42001199-3";"BioBizz FishMix 250ml";4,50;19;;"BioBizz";"Grow | Dünger";="871403232189";"K" +="42001199-1";"BioBizz FishMix 500ml";8,00;19;;"BioBizz";"Grow | Dünger";="8718403231311";"K" +="42001197";"BioBizz Grow";0,00;19;;"BioBizz";"Grow | Dünger";;"V" +="42001197-1";"BioBizz Grow 1l";15,00;19;;"BioBizz";"Grow | Dünger";="000420008990";"K" +="42001197-2";"BioBizz Grow 250ml";4,50;19;;"BioBizz";"Grow | Dünger";;"K" +="42001197-3";"BioBizz Grow 500ml";8,00;19;;"BioBizz";"Grow | Dünger";="8718403231199";"K" +="42000057";"BioBizz Leaf Coat 500ml";14,90;19;;"BioBizz";"Grow | Dünger";="8718403231489"; +="42000058";"BioBizz Light Mix 20L";8,50;19;;"BioBizz";"Grow | Erde";="8718403231656"; +="42000059";"BioBizz Light Mix 50L";16,50;19;;"BioBizz";"Grow | Erde";="8718403231632"; +="42000872";"BioBizz Light Mix Erde 90L";25,00;19;;"BioBizz";"Grow | Erde";="8718403235180"; +="42000060";"BioBizz Light Mix Peat Free 20L";12,50;19;;"BioBizz";"Grow | Erde";="8718403234770"; +="42000061";"BioBizz Light Mix Peat Free 50L";19,50;19;;"BioBizz";"Grow | Erde";; +="42000898";"Biobizz Microbes, Pulver, 150 g";89,00;19;;"BioBizz";"Grow | Dünger";="8718403233995"; +="42000062";"BioBizz PreMix";16,90;19;;"BioBizz";"Grow | Erde";="8718403231694"; +="42001200";"BioBizz Root Juice";0,00;19;;"BioBizz";"Grow | Dünger";;"V" +="42001200-2";"BioBizz Root Juice 250ml";16,00;19;;"BioBizz";"Grow | Dünger";="8718403231373";"K" +="42001200-1";"BioBizz Root Juice 500ml";27,00;19;;"BioBizz";"Grow | Dünger";="8718403232479";"K" +="42000896";"Biobizz Starters Pack";79,00;19;;"BioBizz";"Grow | Dünger";="8718403231755"; +="42001201";"BioBizz TopMax";0,00;19;;"BioBizz";"Grow | Dünger";;"V" +="42001201-3";"BioBizz TopMax 1l";28,90;19;;"BioBizz";"Grow | Dünger";="8718403231403";"K" +="42001201-1";"BioBizz TopMax 250ml";10,90;19;;"BioBizz";"Grow | Dünger";="8718403231816";"K" +="42001201-2";"BioBizz TopMax 500ml";18,90;19;;"BioBizz";"Grow | Dünger";="8718403231427";"K" +="42000067";"BioBizz TryPack Indoor";14,90;19;;"BioBizz";"Grow | Dünger";; +="42000068";"BioBizz WurmHumus 50l";23,50;19;;"BioBizz";"Grow | Erde";="8718403231731"; +="42000089";"Biodor Citrus";14,90;19;;"BioBizz";"Zubehör";; +="42000088";"Biodor Eukalyptus";14,90;19;;"BioBizz";"Zubehör";; +="42000079";"BioTabs BacTrex 50g";24,50;19;;"BioTabs";"Grow | Dünger";="4260619880158"; +="42000081";"BioTabs Bio PK Compost Tea 2000g";52,50;19;;"BioTabs";"Grow | Dünger";; +="42000080";"BioTabs Bio PK Compost Tea 650g";18,50;19;;"BioTabs";"Grow | Dünger";; +="42000070";"BioTabs BioTabs";14,00;19;;"BioTabs";"Grow | Dünger";;"V" +="42000070-1";"BioTabs BioTabs 10 Stück";14,00;19;;"BioTabs";"Grow | Dünger";="4260619880080";"K" +="42000070-2";"BioTabs BioTabs 100 Stück";95,00;19;;"BioTabs";"Grow | Dünger";="4260619880097";"K" +="42000071";"BioTabs BoomBoom";9,00;19;;"BioTabs";"Grow | Dünger";="1357911161733"; +="42000072";"BioTabs Guerilla Box";35,00;19;;"BioTabs";"Grow | Dünger";="4260619880011"; +="42000069";"BioTabs Guerilla Juice 500ml";14,90;19;;"BioTabs";"Grow | Dünger";="4260619880172"; +="42000082";"BioTabs Mycotrex 100g";34,50;19;;"BioTabs";"Grow | Dünger";; +="42000078";"BioTabs Orgatrex 1000ml";17,00;19;;"BioTabs";"Grow | Dünger";; +="42000077";"BioTabs PK Booster flüssig";29,00;19;;"BioTabs";"Grow | Dünger";; +="42000073";"BioTabs PPP";22,50;19;;"BioTabs";"Grow | Dünger";="000420000734"; +="42000076";"BioTabs Silicium Flash 1,25kg";30,00;19;;"BioTabs";"Grow | Dünger";="4260619880257"; +="42000074";"BioTabs Starterbox";45,00;19;;"BioTabs";"Grow | Dünger";="42606619880004"; +="42000075";"BioTabs Startrex 1,5kg";21,50;19;;"BioTabs";"Grow | Dünger";="4260619880028"; +="42001232";"Boost | Beaker Glass Bong -H:44cm- Ø:50mm- Socket:18.8mm- WT:5mm";38,00;19;;"Boost";"Bong/Glasfilter";="616695665716"; +="42001229";"Boost | Bolt Glass Bong -H:38cm- Ø:50mm - SG:18.8mm- WT:5mm";40,00;19;;"Boost";"Bong/Glasfilter";="616695665747"; +="42001228";"Boost | Bouncer Glass Bong H:32cm Ø:40mm SG:14.5mm WT: 5mm ";38,00;19;;"Boost";"Bong/Glasfilter";="616695666089"; +="42001231";"Boost | Bouncer Glass Bong -H:41cm- Ø:50mm- Socket:18.8mm- WT:5mm ";45,00;19;;"Boost";"Bong/Glasfilter";="616695665709"; +="42001230";"Boost | Cane Glass Bong -H:48cm- Ø:65mm- Socket:18.8mm- WT:5mm ";59,00;19;;"Boost";"Bong/Glasfilter";="616695665686"; +="42001225";"Boost | Fumed Glass Bowl- Black- Ø:18.8mm";9,00;19;;"Boost";"Bong/Glasfilter";="616695665273"; +="42001226";"Boost | Fumed Glass Bowl-Black- Ø:14.5mm";7,50;19;;"Boost";"Bong/Glasfilter";="616695665334"; +="42000037";"Bio Terra+ 50L";21,50;19;;"Canna";"Grow | Erde";="8717524957841"; +="42000150";"Canna CalMag Agent 1L";15,50;19;;"Canna";"Grow | Dünger";="753321681907"; +="42001057";"CANNA Clay Pebbles, Tongranulat, 45 L";27,00;19;;"Canna";"Grow | Erde";="8717524959913"; +="42001204";"Canna Flush";0,00;19;;"Canna";"Grow | Dünger";;"V" +="42001204-2";"Canna Flush 1l";14,00;19;;"Canna";"Grow | Dünger";="8717524957100";"K" +="42001204-1";"Canna Flush 500ml";8,00;19;;"Canna";"Grow | Dünger";="8717524957131";"K" +="42000153";"Canna Home Grow Kit";19,50;19;;"Canna";"Grow | Dünger";; +="42000149";"Canna PK 13/14";11,00;19;;"Canna";"Grow | Dünger";="8717524951832"; +="42000146";"Canna Professionell+";17,50;19;;"Canna";"Grow | Erde";="8717524957780"; +="42000148";"Canna Rhizotonic 250ml";19,50;19;;"Canna";"Grow | Dünger";="753321685790"; +="42000147";"Canna SeedMix 25l";14,90;19;;"Canna";"Grow | Erde";="8717524957797"; +="42001203";"Canna Start";0,00;19;;"Canna";"Grow | Dünger";;"V" +="42001203-1";"Canna Start 1l";16,00;19;;"Canna";"Grow | Dünger";;"K" +="42001203-2";"Canna Start 500ml";13,00;19;;"Canna";"Grow | Dünger";="8717524957162";"K" +="42000137";"CANNA Terra Flores";14,00;19;;"Canna";"Grow | Dünger";="8717524951382"; +="42000138";"CANNA Terra Starterkit";60,00;19;;"Canna";"Grow | Dünger";="7081256839319"; +="42000139";"CANNA Terra Vega";14,00;19;;"Canna";"Grow | Dünger";="8717524951412"; +="42001202";"Canna Zym";0,00;19;;"Canna";"Grow | Dünger";;"V" +="42001202-1";"Canna Zym 1l";19,00;19;;"Canna";"Grow | Dünger";;"K" +="42001202-3";"Canna Zym 250ml";9,00;19;;"Canna";"Grow | Dünger";="8717524951917";"K" +="42001202-2";"Canna Zym 500ml";14,00;19;;"Canna";"Grow | Dünger";;"K" +="42001139";"Champ High Glass Pipe";5,00;19;;"Champ High";"Bong/Glasfilter";="3661075189327"; +="42001157";"Chikamasa Erntescheere gerade mit Feder TP-530S";24,00;19;;"Chikamasa";"Grow | Zubehör";="4967645016000"; +="42001156";"Chikamasa Erntescheere L Form mit Magnet B-500SLF";29,00;19;;"Chikamasa";"Grow | Zubehör";="4967645013535"; +="42001155";"Chikamasa Erntescheere mit Feder T-552";16,00;19;;"Chikamasa";"Grow | Zubehör";="4967645032802"; +="42000867";"COMPO GROW ORGANIC Aussaaterde 5L";6,00;19;;"Compo";"Grow | Erde";="4008398188702"; +="42001144";"DIPSE Exact 50";37,50;19;;"Dipse";"Grow | Zubehör";="4260215941628"; +="42000193";"Dipse Waage 2000g";32,50;19;;"Dipse";"Grow | Zubehör";="4260215940300"; +="42000192";"Dipse Waage 500g";30,00;19;;"Dipse";"Grow | Zubehör";; +="42000963";"Elements Cone Tips";0,50;19;;"Elements";"Smoke | Tips/Filter";="716165177234"; +="42000968";"Elements Connisseur King Size Slim Ultra Thin mit Tips ";1,75;19;;"Elements";"Smoke | Papes";="716165179894"; +="42000966";"Elements King Size Slim";0,00;19;;"Elements";"Smoke | Papes";;"V" +="42001133";"Elements King Size Slim 32 Blatt + Tips";0,00;19;;"Elements";"Smoke | Papes";;"V" +="42001133-1";"Elements King Size Slim 32 Blatt + Tips Green";1,75;19;;"Elements";"Smoke | Papes";="716165301554";"K" +="42001133-2";"Elements King Size Slim 32 Blatt + Tips Pink";1,75;19;;"Elements";"Smoke | Papes";="716165303442";"K" +="42001133-3";"Elements King Size Slim 32 Blatt + Tips Rainbow";1,75;19;;"Elements";"Smoke | Papes";="716165306238";"K" +="42000966-3";"Elements King Size Slim Green";1,00;19;;"Elements";"Smoke | Papes";="716165301523";"K" +="42000966-2";"Elements King Size Slim Pink";1,00;19;;"Elements";"Smoke | Papes";="716165301486";"K" +="42000966-1";"Elements King Size Slim Ultra Thin";1,00;19;;"Elements";"Smoke | Papes";="716165177777";"K" +="42000967";"Elements King Size Ultra Thin Rice";1,00;19;;"Elements";"Smoke | Papes";="716165177814"; +="42000964";"Elements Rainbow Tips";0,50;19;;"Elements";"Smoke | Tips/Filter";="716165307334"; +="42001089";"Elements Single Wide Rolls Papers 5m - Plastic Holder";2,50;19;;"Elements";"Smoke | Papes";="000420010894"; +="42000965";"Elements Wide Tips";0,50;19;;"Elements";"Smoke | Tips/Filter";="716165174196"; +="42001090";"G-Rollz Geschenkbox S - Reggae";39,00;19;;"G-Rollz";"Smoke | Zubehör";; +="42000978";"Gizeh Papes Extra Fine Weiß";1,30;19;;"Gizeh";"Smoke | Papes";="42237792"; +="42000977";"Gizeh Papes Fine Grün";1,30;19;;"Gizeh";"Smoke | Papes";="42227526"; +="42000959";"GIZEH Slim Filter";1,50;19;;"Gizeh";"Smoke | Tips/Filter";="4002604009256"; +="42000960";"GIZEH Slim Filter Aktivkohle";1,50;19;;"Gizeh";"Smoke | Tips/Filter";="4002604029254"; +="42000962";"GIZEH XL Slim Filter";1,50;19;;"Gizeh";"Smoke | Tips/Filter";="4002604481106"; +="42000961";"GIZEH XL Slim Filter unbleached";1,50;19;;"Gizeh";"Smoke | Tips/Filter";="4002604179256"; +="42001153";"Homebox Ambient Q100 100x100x200cm";180,00;19;;"Homebox";"Grow | Zelte";="4260220921714"; +="42001154";"HomeBox Ambient R120S 120x60x180cm";200,00;19;;"Homebox";"Grow | Zelte";; +="42000973";"King Palm 1 1/4 Papes mit Flavored Tips";0,00;19;;"King Palm";"Smoke | Papes";;"V" +="42000973-2";"King Palm 1 1/4 Papes mit Flavored Tips Grape-HD";3,50;19;;"King Palm";"Smoke | Papes";="810089613899";"K" +="42000973-1";"King Palm 1 1/4 Papes mit Flavored Tips Lemon Haze";3,50;19;;"King Palm";"Smoke | Papes";="810089614063";"K" +="42001019";"King Palm Flavored Tips";1,00;19;;"King Palm";"Smoke | King Palm";;"V" +="42001019-2";"King Palm Flavored Tips Banana Cream";1,00;19;;"King Palm";"Smoke | King Palm";="850018987066";"K" +="42001019-1";"King Palm Flavored Tips Magic Mint";1,00;19;;"King Palm";"Smoke | King Palm";="850018987073";"K" +="42001019-3";"King Palm Flavored Tips Pine Drip";1,00;19;;"King Palm";"Smoke | King Palm";="850018987493";"K" +="42001018";"King Palm Guava the Great";2,00;19;;"King Palm";"Smoke | King Palm";="850018987622"; +="42001014";"King Palm Leaf Cones 3 Natural";3,45;19;;"King Palm";"Smoke | King Palm";="810089612373"; +="42001011";"King Palm Leaf Rolls 2";2,95;19;;"King Palm";"Smoke | King Palm";;"V" +="42001011-3";"King Palm Leaf Rolls 2 Banana Cream";2,95;19;;"King Palm";"Smoke | King Palm";="850018987059";"K" +="42001011-4";"King Palm Leaf Rolls 2 Berry Terps";2,95;19;;"King Palm";"Smoke | King Palm";="854029008734";"K" +="42001011-6";"King Palm Leaf Rolls 2 Blue Grape";2,95;19;;"King Palm";"Smoke | King Palm";="810089610515";"K" +="42001011-2";"King Palm Leaf Rolls 2 Honey Mango";2,95;19;;"King Palm";"Smoke | King Palm";="810089611970";"K" +="42001011-5";"King Palm Leaf Rolls 2 Honey Orange";2,95;19;;"King Palm";"Smoke | King Palm";="810089610331";"K" +="42001011-1";"King Palm Leaf Rolls 2 Mini";2,95;19;;"King Palm";"Smoke | King Palm";="810078745167";"K" +="42001011-7";"King Palm Leaf Rolls 2 Strawberry Shortcake";2,95;19;;"King Palm";"Smoke | King Palm";="810089610904";"K" +="42001016";"King Palm Leaf Rolls 5 Grape HD";5,50;19;;"King Palm";"Smoke | King Palm";="810089616388"; +="42001017";"King Palm Leaf Rolls Variety Pack";9,00;19;;"King Palm";"Smoke | King Palm";="850018987387"; +="42001015";"King Palm Leaf Tubes Don Pomegranate";3,00;19;;"King Palm";"Smoke | King Palm";="810089613707"; +="42001021";"King Palm Mars Grinder";0,00;19;;"King Palm";"Grinder";;"V" +="42001021-3";"King Palm Mars Grinder The Arrival";25,00;19;;"King Palm";"Grinder";="850018987462";"K" +="42001021-2";"King Palm Mars Grinder The Colony";25,00;19;;"King Palm";"Grinder";="810078743996";"K" +="42001021-4";"King Palm Mars Grinder The Departure";25,00;19;;"King Palm";"Grinder";="810078743514";"K" +="42001021-5";"King Palm Mars Grinder The Gift";25,00;19;;"King Palm";"Grinder";="810078743330";"K" +="42001021-1";"King Palm Mars Grinder The Session";25,00;19;;"King Palm";"Grinder";="810078743453";"K" +="42001012";"King Palm Mini Leaf Rolls 2";1,95;19;;"King Palm";"Smoke | King Palm";;"V" +="42001012-1";"King Palm Mini Leaf Rolls 2 Cherry Charm";1,95;19;;"King Palm";"Smoke | King Palm";="810089610294";"K" +="42001012-2";"King Palm Mini Leaf Rolls 2 Perfect Pear";1,95;19;;"King Palm";"Smoke | King Palm";="810089610324";"K" +="42001013";"King Palm Wraps 2";2,95;19;;"King Palm";"Smoke | King Palm";;"V" +="42001013-2";"King Palm Wraps 2 Cherry Bomb";2,95;19;;"King Palm";"Smoke | King Palm";="850018987158";"K" +="42001013-1";"King Palm Wraps 2 Golden Mango";2,95;19;;"King Palm";"Smoke | King Palm";="810078740148";"K" +="42000955";"Medusa Filter 6mm 10 Stück";0,00;19;;"Medusa";"Smoke | Tips/Filter";;"V" +="42000955-1";"Medusa Filter 6mm 10 Stück Rosé";2,90;19;;"Medusa";"Smoke | Tips/Filter";="4262408940326";"K" +="42000955-2";"Medusa Filter 6mm 10 Stück Violet";2,90;19;;"Medusa";"Smoke | Tips/Filter";="4262408940302";"K" +="42000956";"Medusa Filter 6mm Mixed Tüte á 32";7,00;19;;"Medusa";"Smoke | Tips/Filter";="4262408941545"; +="42000957";"Medusa Filter 6mm Tüte á 100 ";0,00;19;;"Medusa";"Smoke | Tips/Filter";;"V" +="42000957-3";"Medusa Filter 6mm Tüte á 100 Mixed";18,90;19;;"Medusa";"Smoke | Tips/Filter";="4270003233545";"K" +="42000957-1";"Medusa Filter 6mm Tüte á 100 Sunset";18,90;19;;"Medusa";"Smoke | Tips/Filter";="4262408940135";"K" +="42000957-2";"Medusa Filter 6mm Tüte á 100 Vioket";18,90;19;;"Medusa";"Smoke | Tips/Filter";="4270003233569";"K" +="42000942";"Medusa Filter 6mm Tüte á 50 Stück";0,00;19;;"Medusa";"Smoke | Tips/Filter";;"V" +="42000942-3";"Medusa Filter 6mm Tüte á 50 Stück Organic";9,90;19;;"Medusa";"Smoke | Tips/Filter";="4270002129542";"K" +="42000942-2";"Medusa Filter 6mm Tüte á 50 Stück Rosé";9,90;19;;"Medusa";"Smoke | Tips/Filter";="4262408940128";"K" +="42000942-4";"Medusa Filter 6mm Tüte á 50 Stück Sunset";9,90;19;;"Medusa";"Smoke | Tips/Filter";="4262408940098";"K" +="42000942-1";"Medusa Filter 6mm Tüte á 50 Stück Violet";9,90;19;;"Medusa";"Smoke | Tips/Filter";="4270002129511";"K" +="42000871";"Milwaukee pH Messgerät pH600";25,00;19;;"Milwaukee";"Grow | Messgeräte";; +="42001159";"Neudorff Gelb Sticker 10 Stück";9,00;19;;"Neudorff";"Grow | Zubehör";; +="42001158";"Neudorff Gelbtafeln 7 Tafeln";9,00;19;;"Neudorff";"Grow | Zubehör";="4005240003220"; +="42000870";"Pflanzenjojo";1,60;19;;"Niecorol";"Grow | Zubehör";; +="42000976";"OCB Papes Double Premium";1,30;19;;"OCB";"Smoke | Papes";="30062948"; +="42000974";"OCB Papes Double Blue";1,30;19;;"OCB";"Smoke | Papes";="30034440"; +="42000975";"OCB Papes No4";1,30;19;;"OCB";"Smoke | Papes";="30004832"; +="42000958";"OCB Slim Filter Natur";1,50;19;;"OCB";"Smoke | Tips/Filter";; +="42000575";"Plagron All Mix 25L";12,00;19;;"Plagron";"Grow | Erde";; +="42000576";"Plagron All Mix 50L";19,50;19;;"Plagron";"Grow | Erde";; +="42000577";"Plagron Grow Mix 25L";13,50;19;;"Plagron";"Grow | Erde";; +="42000578";"Plagron Grow Mix 50L";17,00;19;;"Plagron";"Grow | Erde";; +="42000579";"Plagron Ligth Mix 25L";11,50;19;;"Plagron";"Grow | Erde";="8718104121362"; +="42000580";"Plagron Ligth Mix 50L";15,00;19;;"Plagron";"Grow | Erde";; +="42000582";"Plagron Pro Mix 50L";19,50;19;;"Plagron";"Grow | Erde";="8718104121300"; +="42000909";"PURIZE Aktivkohlefilter Big Size 14mm (3 Stück)";8,90;19;;"Purize";"Smoke | Tips/Filter";; +="42000910";"PURIZE Aktivkohlefilter Big Size 14mm (7 Stück)";22,90;19;;"Purize";"Smoke | Tips/Filter";="4260748413159"; +="42001078";"PURIZE Aktivkohlefilter Super Slim Size 5mm (500 Stück)";80,00;19;;"Purize";"Smoke | Tips/Filter";="4260748416501"; +="42000010";"Purize Aktivkohletasche XS Pink";9,90;19;;"Purize";"Zubehör";="4260748410745"; +="42000908";"PURIZE Aufblasbarer Jibbit Large 1,20 m";9,90;19;;"Purize";"Smoke | Zubehör";="4260748411735"; +="42000939";"PURIZE Big Size Tüte á 7 Stück";20,00;19;;"Purize";"Smoke | Tips/Filter";="4260748413159"; +="42001174";"Purize Blazy Susan 9mm Lila";9,90;19;;"Purize";"Smoke | Tips/Filter";="810134925526"; +="42001175";"Purize Blazy Susan 9mm Pink";9,90;19;;"Purize";"Smoke | Tips/Filter";="810134925519"; +="42000941";"PURIZE First Aid Kit";3,00;19;;"Purize";"Smoke | Papes";="4260748414804"; +="42000919";"PURIZE King Size Slim";0,00;19;;"Purize";"Smoke | Papes";;"V" +="42000919-6";"PURIZE King Size Slim 420 Papers";8,90;19;;"Purize";"Smoke | Papes";="4260748412992";"K" +="42000919-3";"PURIZE King Size Slim Braun";1,50;19;;"Purize";"Smoke | Papes";="4260748410103";"K" +="42000919-4";"PURIZE King Size Slim Inside Out";1,50;19;;"Purize";"Smoke | Papes";="4260748413104";"K" +="42000919-1";"PURIZE King Size Slim Pink";1,50;19;;"Purize";"Smoke | Papes";="4260748410134";"K" +="42000919-5";"PURIZE King Size Slim Plus Paper Tips";0,00;19;;"Purize";"Smoke | Papes";;"K" +="42000919-2";"PURIZE King Size Slim Rainbow Spezial";1,50;19;;"Purize";"Smoke | Papes";="4260748410011";"K" +="42000921";"PURIZE King Size Ultra Slim";1,50;19;;"Purize";"Smoke | Papes";="4260748410165"; +="42000920";"PURIZE King Size Wide";2,00;19;;"Purize";"Smoke | Papes";="4260748410301"; +="42000923";"PURIZE Long Size Slim";0,00;19;;"Purize";"Smoke | Papes";; +="42000922";"PURIZE Long Size Wide";0,00;19;;"Purize";"Smoke | Papes";; +="42001080";"PURIZE Pink Papes'n'Tips Pink";4,90;19;;"Purize";"Smoke | Papes";="4260748410400"; +="42000953";"Purize Prerolled Cones 6mm 3 Stück";2,00;19;;"Purize";"Smoke | Papes";="4260748413036"; +="42000952";"Purize Prerolled Cones 9mm 3 Stück";2,00;19;;"Purize";"Smoke | Papes";="4260748413302"; +="42000649";"Purize Pullover";59,90;19;;"Purize";"Zubehör";; +="42000645";"PURIZE Queen Size Slim";1,50;19;;"Purize";"Smoke | Papes";="4260748414750"; +="42000938";"PURIZE Regular Size Pack á 10 Stück";2,00;19;;"Purize";"Smoke | Tips/Filter";="4260748410936"; +="42000929";"PURIZE Regular Size Short Tüte á 50 Stück";8,90;19;;"Purize";"Smoke | Tips/Filter";="4260748415214"; +="42000933";"PURIZE Regular Size Tüte á 100 Stück";0,00;19;;"Purize";"Smoke | Tips/Filter";;"V" +="42000933-1";"PURIZE Regular Size Tüte á 100 Stück Lila";16,90;19;;"Purize";"Smoke | Tips/Filter";="4260748413753";"K" +="42000933-3";"PURIZE Regular Size Tüte á 100 Stück Organic";16,90;19;;"Purize";"Smoke | Tips/Filter";="4260748411353";"K" +="42000933-4";"PURIZE Regular Size Tüte á 100 Stück Pink";16,90;19;;"Purize";"Smoke | Tips/Filter";="4260748411360";"K" +="42000933-5";"PURIZE Regular Size Tüte á 100 Stück Spy";16,90;19;;"Purize";"Smoke | Tips/Filter";;"K" +="42000933-2";"PURIZE Regular Size Tüte á 100 Stück Weiß";16,90;19;;"Purize";"Smoke | Tips/Filter";="4260748410752";"K" +="42000934";"PURIZE Regular Size Tüte á 250 Stück";0,00;19;;"Purize";"Smoke | Tips/Filter";;"V" +="42000934-1";"PURIZE Regular Size Tüte á 250 Stück Allcolor";38,90;19;;"Purize";"Smoke | Tips/Filter";="4260748415740";"K" +="42000934-3";"PURIZE Regular Size Tüte á 250 Stück Organic";38,90;19;;"Purize";"Smoke | Tips/Filter";="4260748415733";"K" +="42000934-2";"PURIZE Regular Size Tüte á 250 Stück Pink";38,90;19;;"Purize";"Smoke | Tips/Filter";="4260748416839";"K" +="42000934-4";"PURIZE Regular Size Tüte á 250 Stück Weiß";38,90;19;;"Purize";"Smoke | Tips/Filter";="4260748410448";"K" +="42000930";"PURIZE Regular Size Tüte á 50 Stück";0,00;19;;"Purize";"Smoke | Tips/Filter";;"V" +="42000930-1";"PURIZE Regular Size Tüte á 50 Stück Allcolor";8,90;19;;"Purize";"Smoke | Tips/Filter";="4260748411377";"K" +="42000930-4";"PURIZE Regular Size Tüte á 50 Stück Organic";8,90;19;;"Purize";"Smoke | Tips/Filter";="4260748411384";"K" +="42000930-2";"PURIZE Regular Size Tüte á 50 Stück Pink";8,90;19;;"Purize";"Smoke | Tips/Filter";="4260748411391";"K" +="42000930-3";"PURIZE Regular Size Tüte á 50 Stück White";8,90;19;;"Purize";"Smoke | Tips/Filter";="4260748410653";"K" +="42000644";"PURIZE Roll Wide";2,50;19;;"Purize";"Smoke | Papes";="4260748414286"; +="42000648";"PURIZE Rolls Pink";2,00;19;;"Purize";"Smoke | Papes";="4260748410196"; +="42000643";"PURIZE Rools Braun";2,00;19;;"Purize";"Smoke | Papes";="4260748410226"; +="42000931";"PURIZE Slim Size Air Tüte á 50 Stück";9,00;19;;"Purize";"Smoke | Tips/Filter";="4260748415801"; +="42000936";"PURIZE Slim Size Tüte á 50 Stück";9,50;19;;"Purize";"Smoke | Tips/Filter";="4260748414422"; +="42000928";"PURIZE Super Slim Size Tüte á 111 Stück";17,90;19;;"Purize";"Smoke | Tips/Filter";="4260748417690"; +="42000940";"PURIZE Super Slim Size Tüte á 50 Stück";9,50;19;;"Purize";"Smoke | Tips/Filter";="4260748413173"; +="42000650";"Purize TShirt";35,00;19;;"Purize";"Zubehör";; +="42000932";"PURIZE Variety Bag";3,00;19;;"Purize";"Smoke | Tips/Filter";="4260748415894"; +="42000621";"PURIZE XTRA Slim 6mm Glas á 100 Filter";16,90;19;;"Purize";"Smoke | Tips/Filter";;"V" +="42000621-9";"PURIZE XTRA Slim 6mm Glas á 100 Filter Blau";16,90;19;;"Purize";"Smoke | Tips/Filter";;"K" +="42000621-8";"PURIZE XTRA Slim 6mm Glas á 100 Filter Gelb";16,90;19;;"Purize";"Smoke | Tips/Filter";;"K" +="42000621-7";"PURIZE XTRA Slim 6mm Glas á 100 Filter Grün";16,90;19;;"Purize";"Smoke | Tips/Filter";="4260748411469";"K" +="42000621-1";"PURIZE XTRA Slim 6mm Glas á 100 Filter Lila";16,90;19;;"Purize";"Smoke | Tips/Filter";="4260748412534";"K" +="42000621-6";"PURIZE XTRA Slim 6mm Glas á 100 Filter Organic";16,90;19;;"Purize";"Smoke | Tips/Filter";="4260748411513";"K" +="42000621-5";"PURIZE XTRA Slim 6mm Glas á 100 Filter Pink";16,90;19;;"Purize";"Smoke | Tips/Filter";="4260748411537";"K" +="42000621-4";"PURIZE XTRA Slim 6mm Glas á 100 Filter Rainbow";16,90;19;;"Purize";"Smoke | Tips/Filter";;"K" +="42000621-3";"PURIZE XTRA Slim 6mm Glas á 100 Filter Spy";16,90;19;;"Purize";"Smoke | Tips/Filter";;"K" +="42000621-2";"PURIZE XTRA Slim 6mm Glas á 100 Filter Weiß";16,90;19;;"Purize";"Smoke | Tips/Filter";="4260748410066";"K" +="42000935";"PURIZE Xtra Slim Size Pack á 10 Stück";0,00;19;;"Purize";"Smoke | Tips/Filter";;"V" +="42000935-1";"PURIZE Xtra Slim Size Pack á 10 Stück Rainbow";2,00;19;;"Purize";"Smoke | Tips/Filter";="4260748414446";"K" +="42000935-2";"PURIZE Xtra Slim Size Pack á 10 Stück White";2,00;19;;"Purize";"Smoke | Tips/Filter";="4260748410851";"K" +="42000926";"PURIZE Xtra Slim Size Tüte á 250 Stück";0,00;19;;"Purize";"Smoke | Tips/Filter";;"V" +="42000926-5";"PURIZE Xtra Slim Size Tüte á 250 Stück Blau";36,90;19;;"Purize";"Smoke | Tips/Filter";;"K" +="42000926-1";"PURIZE Xtra Slim Size Tüte á 250 Stück Gelb";36,90;19;;"Purize";"Smoke | Tips/Filter";="4260748412237";"K" +="42000926-4";"PURIZE Xtra Slim Size Tüte á 250 Stück Lila";36,90;19;;"Purize";"Smoke | Tips/Filter";="4260748413777";"K" +="42000926-2";"PURIZE Xtra Slim Size Tüte á 250 Stück Pink";36,90;19;;"Purize";"Smoke | Tips/Filter";="4260748412206";"K" +="42000926-3";"PURIZE Xtra Slim Size Tüte á 250 Stück Rainbow";36,90;19;;"Purize";"Smoke | Tips/Filter";="4260748412213";"K" +="42000926-6";"PURIZE Xtra Slim Size Tüte á 250 Stück Weiß";36,90;19;;"Purize";"Smoke | Tips/Filter";;"K" +="42000927";"PURIZE Xtra Slim Size Tüte á 33 Stück";5,90;19;;"Purize";"Smoke | Tips/Filter";="4260748415702";"V" +="42000927-2";"PURIZE Xtra Slim Size Tüte á 33 Stück Bunt";5,90;19;;"Purize";"Smoke | Tips/Filter";="4260748413135";"K" +="42000927-1";"PURIZE Xtra Slim Size Tüte á 33 Stück Frankreich";5,90;19;;"Purize";"Smoke | Tips/Filter";="4260748415702";"K" +="42000925";"PURIZE Xtra Slim Size Tüte á 50 Stück";0,00;19;;"Purize";"Smoke | Tips/Filter";;"V" +="42000925-5";"PURIZE Xtra Slim Size Tüte á 50 Stück Blazy Susan Pink";9,90;19;;"Purize";"Smoke | Tips/Filter";="810134925496";"K" +="42000925-6";"PURIZE Xtra Slim Size Tüte á 50 Stück Blazy Susan Purple";9,90;19;;"Purize";"Smoke | Tips/Filter";="810134925502";"K" +="42000925-1";"PURIZE Xtra Slim Size Tüte á 50 Stück Gelb";8,90;19;;"Purize";"Smoke | Tips/Filter";="4260748412299";"K" +="42000925-3";"PURIZE Xtra Slim Size Tüte á 50 Stück Grün";8,90;19;;"Purize";"Smoke | Tips/Filter";="4260748412268";"K" +="42000925-2";"PURIZE Xtra Slim Size Tüte á 50 Stück Lila";8,90;19;;"Purize";"Smoke | Tips/Filter";="4260748413807";"K" +="42000925-4";"PURIZE Xtra Slim Size Tüte á 50 Stück Organic";8,90;19;;"Purize";"Smoke | Tips/Filter";="4260748412251";"K" +="42000925-9";"PURIZE Xtra Slim Size Tüte á 50 Stück Pink";8,90;19;;"Purize";"Smoke | Tips/Filter";="4260748412275";"K" +="42000925-8";"PURIZE Xtra Slim Size Tüte á 50 Stück Rainbow";8,90;19;;"Purize";"Smoke | Tips/Filter";;"K" +="42000925-7";"PURIZE Xtra Slim Size Tüte á 50 Stück Spy";8,90;19;;"Purize";"Smoke | Tips/Filter";;"K" +="42000937";"PURIZE Xtra Slim Size Tüte á 500 Stück";68,90;19;;"Purize";"Smoke | Tips/Filter";="4260748414316"; +="42000657";"RAW Aschenbecher";12,90;19;;"RAW";"Zubehör";; +="42000662";"RAW Aschenbecher Glas";24,90;19;;"RAW";"Zubehör";; +="42001268";"RAW Black + Tips";2,00;19;;"RAW";"Smoke | Papes";="716165284888"; +="42001172";"RAW Donut Tray";14,90;19;;"RAW";"Zubehör";="716165285182"; +="42001082";"RAW Ethereal Papers King Size Slim";2,20;19;;"RAW";"Smoke | Papes";; +="42001163";"RAW Frisbee";12,00;19;;"RAW";"Zubehör";="716165295372"; +="42001169";"RAW Gold Papes";2,20;19;;"RAW";"Smoke | Papes";="716165307563"; +="42001269";"RAW Hemp Wick";1,50;19;;"RAW";"Smoke | Papes";="716165280521"; +="42000659";"RAW Kartenspiel";4,20;19;;"RAW";"Zubehör";; +="42001242";"Raw Kerze";10,90;19;;"RAW";"Zubehör";="716165298083"; +="42000943";"RAW King Size Slim";1,50;19;;"RAW";"Smoke | Papes";="716165177357"; +="42000944";"RAW King Size Slim Black";1,50;19;;"RAW";"Smoke | Papes";="716165280972"; +="42000946";"RAW King Size Slim mit Tips";2,00;19;;"RAW";"Smoke | Papes";="716165174011"; +="42000945";"RAW King Size Slim Organic";1,50;19;;"RAW";"Smoke | Papes";="716165174219"; +="42000947";"RAW King Size Slim Organic mit Tips";2,00;19;;"RAW";"Smoke | Papes";="716165177579"; +="42001137";"RAW Lil Prep Bowl";5,00;19;;"RAW";"Smoke | Zubehör";="716165308270"; +="42000660";"RAW Munchies Box";14,90;19;;"RAW";"Zubehör";; +="42000948";"RAW Rolls 3m";2,00;19;;"RAW";"Smoke | Papes";="716165177371"; +="42001091";"RAW Summer Rolling Tray Small 27,5 x 17,5 cm";7,47;19;;"RAW";"Smoke | Zubehör";="7161653038178"; +="42001171";"RAW Summer Tray";9,90;19;;"RAW";"Zubehör";="716165303817"; +="42000658";"RAW Tabakbefeuchter";1,90;19;;"RAW";"Zubehör";; +="42000656";"RAW Taschenaschenbecher";2,90;19;;"RAW";"Zubehör";="716165158370"; +="42000915";"RAW Tasse Wake up & Bake up";16,90;19;;"RAW";"Smoke | Zubehör";="716165294955"; +="42000949";"RAW Tips";0,50;19;;"RAW";"Smoke | Tips/Filter";="716165177395"; +="42000950";"RAW Tips Black";0,50;19;;"RAW";"Smoke | Tips/Filter";="716165286707"; +="42000951";"RAW Tips Wide";0,50;19;;"RAW";"Smoke | Tips/Filter";="716165177555"; +="42000869";"Sonnenerde Bio Hanferde 20L";23,00;19;;"Sonnenerde";"Grow | Erde";="9120009100202"; +="42000969";"Wirklichrich 66 Papes mit Tips";3,00;19;;"Wirklichrich";"Smoke | Papes";; +="42000972";"Woodzl 1 1/4 Natural mit Tips";1,50;19;;"Woodzl";"Smoke | Papes";="702754956458"; +="42000970";"Woodzl Natural King Size Slim";1,50;19;;"Woodzl";"Smoke | Papes";="096224945852"; +="42000971";"Woodzl Natural King Size Slim mit Tips";2,00;19;;"Woodzl";"Smoke | Papes";="702754956403"; +="42000954";"doobiewood kss + paper tips";2,00;19;;"doobiewood";"Smoke | Papes";="4260748412930"; \ No newline at end of file diff --git a/docs/api/README.md b/docs/api/README.md index 41bbaf8..3f86b96 100644 --- a/docs/api/README.md +++ b/docs/api/README.md @@ -75,6 +75,7 @@ Generated from `@openapi` annotations in [`src/api/routes/`](../../src/api/route | [`routes/customergroup/update.md`](routes/customergroup/update.md) | `PATCH /customergroup/{id}` | | [`routes/delivery/list.md`](routes/delivery/list.md) | `GET /delivery` | | [`routes/delivery/create.md`](routes/delivery/create.md) | `POST /delivery` | +| [`routes/delivery/parsePDF.md`](routes/delivery/parsePDF.md) | `POST /delivery/parsePDF` | | [`routes/delivery/delete.md`](routes/delivery/delete.md) | `DELETE /delivery/{id}` | | [`routes/delivery/get.md`](routes/delivery/get.md) | `GET /delivery/{id}` | | [`routes/delivery/update.md`](routes/delivery/update.md) | `PATCH /delivery/{id}` | diff --git a/docs/api/openapi.json b/docs/api/openapi.json index 09f0142..38683dd 100644 --- a/docs/api/openapi.json +++ b/docs/api/openapi.json @@ -4040,6 +4040,110 @@ } } }, + "/delivery/parsePDF": { + "post": { + "tags": [ + "Delivery" + ], + "summary": "Parse PDF (SSE)", + "description": "Accepts a PDF invoice or delivery note (`multipart/form-data`, field `pdf`)\nand streams extraction results as Server-Sent Events until parsing is complete.\n\nThe PDF is read via `pdftotext -layout` and fed page-by-page to an LLM\n(OpenRouter) which fills a structured manifest of header data and line items.\nThe OpenRouter API key is read from the authenticated user's company setting\n`keys.openrouter`; the endpoint returns `400` if the key is not configured.\n\nThe stream ends after the final `result` event (or an `error` event on failure).\n", + "security": [ + { + "cookieAuth": [] + } + ], + "x-markdown": "delivery/parsePDF.md", + "x-sse-events": [ + { + "name": "status", + "description": "PDF parse confirmation and LLM status messages", + "payload": "{ \"message\": \"…\" }" + }, + { + "name": "llm_call", + "description": "Fired before each LLM request", + "payload": "{ \"model\": \"…\", \"promptSize\": 0, \"messages\": 0 }" + }, + { + "name": "tool_call", + "description": "Fired when the output_manifest tool is invoked", + "payload": "{ \"name\": \"output_manifest\" }" + }, + { + "name": "usage", + "description": "Token usage after each LLM response", + "payload": "{ \"input\": 0, \"cached\": 0, \"output\": 0, \"cost\": 0 }" + }, + { + "name": "progress", + "description": "Intermediate accumulated extraction state (basedata / notes / items)", + "payload": "ManifestResult" + }, + { + "name": "result", + "description": "Final accumulated extraction — emitted just before the stream closes", + "payload": "ManifestResult" + }, + { + "name": "error", + "description": "Emitted on PDF parse or LLM failure; stream closes immediately after", + "payload": "{ \"message\": \"…\" }" + } + ], + "requestBody": { + "required": true, + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "required": [ + "pdf" + ], + "properties": { + "pdf": { + "type": "string", + "format": "binary", + "description": "PDF file to parse (max 50 MB, application/pdf)" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "`text/event-stream` — emits `status`, `llm_call`, `tool_call`, `usage`,\n`progress`, `result` (and `error` on failure). See SSE Events table below.\n\n**ManifestResult shape** (used by `progress` and `result`):\n\n```json\n{\n \"basedata\": {\n \"date\": \"2026-01-15\",\n \"kLieferant\": 42,\n \"lieferantName\": \"Muster GmbH\",\n \"manifestNr\": \"LS-2026-001\",\n \"manifestType\": \"lieferschein\"\n },\n \"notes\": [\"Pos. 3: VPE-Angabe fehlte, Standardwert 1 angenommen.\"],\n \"items\": {\n \"pagesFrom\": 1,\n \"pagesTo\": 2,\n \"items\": [\n {\n \"position\": 1,\n \"count\": 10,\n \"vpe\": 1,\n \"unit\": \"Stk.\",\n \"articleName\": \"Einhängesieb Stahl\",\n \"liefArtNr\": \"ES-100\",\n \"mwst\": \"19\",\n \"eknetto\": 450,\n \"page\": 1\n }\n ]\n }\n}\n```\n", + "content": { + "text/event-stream": { + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "No PDF uploaded or OpenRouter key not configured", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, "/delivery": { "get": { "tags": [ diff --git a/docs/api/routes/delivery/parsePDF.md b/docs/api/routes/delivery/parsePDF.md new file mode 100644 index 0000000..e0d816d --- /dev/null +++ b/docs/api/routes/delivery/parsePDF.md @@ -0,0 +1,85 @@ +# `POST /delivery/parsePDF` + +Protected. Requires a valid session cookie (`credentials: 'include'`). + +Parse PDF (SSE) + +Accepts a PDF invoice or delivery note (`multipart/form-data`, field `pdf`) +and streams extraction results as Server-Sent Events until parsing is complete. + +The PDF is read via `pdftotext -layout` and fed page-by-page to an LLM +(OpenRouter) which fills a structured manifest of header data and line items. +The OpenRouter API key is read from the authenticated user's company setting +`keys.openrouter`; the endpoint returns `400` if the key is not configured. + +The stream ends after the final `result` event (or an `error` event on failure). + + +## Body (`multipart/form-data`) + +| Field | Required | Type | Description | +|-------|----------|------|-------------| +| `pdf` | yes | file | PDF file to parse (max 50 MB, application/pdf) | + +## SSE Events + +The response is a `text/event-stream`. Events are emitted in order until the stream closes. + +| Event | Description | Payload | +|-------|-------------|---------| +| `status` | PDF parse confirmation and LLM status messages | `{ "message": "…" }` | +| `llm_call` | Fired before each LLM request | `{ "model": "…", "promptSize": 0, "messages": 0 }` | +| `tool_call` | Fired when the output_manifest tool is invoked | `{ "name": "output_manifest" }` | +| `usage` | Token usage after each LLM response | `{ "input": 0, "cached": 0, "output": 0, "cost": 0 }` | +| `progress` | Intermediate accumulated extraction state (basedata / notes / items) | `ManifestResult` | +| `result` | Final accumulated extraction — emitted just before the stream closes | `ManifestResult` | +| `error` | Emitted on PDF parse or LLM failure; stream closes immediately after | `{ "message": "…" }` | + +## Response `200` + +`text/event-stream` — emits `status`, `llm_call`, `tool_call`, `usage`, +`progress`, `result` (and `error` on failure). See SSE Events table below. + +**ManifestResult shape** (used by `progress` and `result`): + +```json +{ + "basedata": { + "date": "2026-01-15", + "kLieferant": 42, + "lieferantName": "Muster GmbH", + "manifestNr": "LS-2026-001", + "manifestType": "lieferschein" + }, + "notes": ["Pos. 3: VPE-Angabe fehlte, Standardwert 1 angenommen."], + "items": { + "pagesFrom": 1, + "pagesTo": 2, + "items": [ + { + "position": 1, + "count": 10, + "vpe": 1, + "unit": "Stk.", + "articleName": "Einhängesieb Stahl", + "liefArtNr": "ES-100", + "mwst": "19", + "eknetto": 450, + "page": 1 + } + ] + } +} +``` + + +## Errors + +| Status | Description | +|--------|-------------| +| 400 | No PDF uploaded or OpenRouter key not configured — `{"error":"…"}` | +| 401 | Unauthorized — `{"error":"…"}` | + +--- + +_Generated from `@openapi` JSDoc. Do not edit by hand — run `npm run docs:api`._ diff --git a/package-lock.json b/package-lock.json index f844f22..4c6baf4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,15 +15,17 @@ "crypto": "^1.0.1", "dotenv": "^17.4.2", "express": "^5.2.1", - "google-auth-library": "^11.0.0", + "google-auth-library": "^11.0.2", "ink": "^7.1.1", "ink-text-input": "^6.0.0", "jsonwebtoken": "^9.0.3", - "jszip": "^3.10.1", + "jszip": "^3.10.2", "libdashstore": "file:../dashdbschema", - "mssql": "^12.7.0", - "react": "^19.2.8", - "sharp": "^0.35.3" + "libllmorbiter": "file:../llmorbiter", + "mssql": "^12.7.2", + "multer": "^2.4.0", + "react": "^19.3.0", + "sharp": "^0.35.4" }, "devDependencies": { "swagger-jsdoc": "^6.3.0" @@ -48,6 +50,13 @@ "mssql": "^12.6.0" } }, + "../llmorbiter": { + "version": "0.1.0", + "license": "0BSD", + "dependencies": { + "dotenv": "^17.4.2" + } + }, "node_modules/@alcalzone/ansi-tokenize": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@alcalzone/ansi-tokenize/-/ansi-tokenize-0.3.0.tgz", @@ -381,9 +390,9 @@ } }, "node_modules/@img/sharp-darwin-arm64": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.3.tgz", - "integrity": "sha512-RMnFX7YQsMoh7lWfcM4NEHHymBX/rLuKNPVM84XE9ONPcaSCDgE7CHIHpSgPcO2xcRthgBy1HfNO319mwhIAkg==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.4.tgz", + "integrity": "sha512-Uhfl4V4lhP2nbUVF9+hyH1+luj86f1gUFeo8ALYxFoULoU+G87D43BfeMP8XHsk9boxAnCY/bf2EHwhA7MuGsA==", "cpu": [ "arm64" ], @@ -399,13 +408,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.3.2" + "@img/sharp-libvips-darwin-arm64": "1.3.3" } }, "node_modules/@img/sharp-darwin-x64": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.3.tgz", - "integrity": "sha512-Xo+5uFBtLN0BKqieTxiFzFPQAUlBbbH5iBKyRX/z1JrbnYsHTfKJnUfL8+p2TPXr1pXqao4eeL4Rl144uDpK9w==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.4.tgz", + "integrity": "sha512-hWniXY3bG5qKpkKrAwPe4y+VTPmf086YQAnkxWh7uA1YrlRouWGa0M0Mxj3ZjnXFkv7/TD1bTy9lGUK26vRvWw==", "cpu": [ "x64" ], @@ -421,20 +430,20 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.3.2" + "@img/sharp-libvips-darwin-x64": "1.3.3" } }, "node_modules/@img/sharp-freebsd-wasm32": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.3.tgz", - "integrity": "sha512-lUxcqWIj2wMQ9BrwNjngcr1gWUr5xgaGThBRqPPalIC2n67Cqj1uPh8NnA/ZhAg8hUbKl+kVHKwgUIwe6ZYPrg==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.4.tgz", + "integrity": "sha512-lIsKw/BU+kjB4eZjxrYrZmwOJYi3Ajrv66iAlBmUPyKc3HpnloevB1g3wxGD9P/5BbQ1brBGl65VRRrCvQDEqA==", "license": "Apache-2.0", "optional": true, "os": [ "freebsd" ], "dependencies": { - "@img/sharp-wasm32": "0.35.3" + "@img/sharp-wasm32": "0.35.4" }, "engines": { "node": ">=20.9.0" @@ -444,9 +453,9 @@ } }, "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.2.tgz", - "integrity": "sha512-9J6ypZFpQBj4YnePGoq/S38w6nz+vqg5WZLrLGY4YuSemdMq47GMLBPO42MzwdGwpg/agZ7xzZcFHa48xlywfg==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.3.tgz", + "integrity": "sha512-suTBPTDGrI9WodccaDdwZItTSaBYASlBk1NSfElSHrUfzu3szG6lvIF58+WiFvnfzuK8ZBFS5zE00PxqxnRiPg==", "cpu": [ "arm64" ], @@ -460,9 +469,9 @@ } }, "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.2.tgz", - "integrity": "sha512-m2pW1n6cns9VaubNwsZ+c3CRYjxNQWgJ5gPlnL1nbBcpkBvFm6SCFN5o0psFHI8w9n11NKhFkeEDns98tiqbEw==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.3.tgz", + "integrity": "sha512-FVJZ5mITMobmXIz/hPDTw0EintTW5H3WfrxwLqEqjiIihlu+hVRyGrFQ60xl0Lxn7Bt3zdpevPaQi0HEzqz9fw==", "cpu": [ "x64" ], @@ -476,9 +485,9 @@ } }, "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.2.tgz", - "integrity": "sha512-1eMLzy92I4J6rmi4mAT8yC3HxOtniyGELlzGbNMLLeqe052ahFQ0h6LFq+lh5DsDIdYViIDst08abvSbcEdLXQ==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.3.tgz", + "integrity": "sha512-3rbU4vqXXc3hY/OiXdl52xZvT0F1yEngWfvqudtPJg/KkyiaQw2DRsFrNzpmLvfavbwOq3qXn36GP8obHRULQA==", "cpu": [ "arm" ], @@ -495,9 +504,9 @@ } }, "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.2.tgz", - "integrity": "sha512-dqVSFynCox4C/J8kT16V7SIFAns0IjgLwkvYT7p8LQVmJ5OS5b6tI9IGflxTeuBS//zXeFIUbwt5dwxyZ17cnA==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.3.tgz", + "integrity": "sha512-0DaL0A6Xu6sQSQFwe4iVCrKWU2cCTItnRsYsCdxAMm9NF6twAA9BKnoqy4hqz4+azQ0JHuA26qiUKsf1XJ/v5A==", "cpu": [ "arm64" ], @@ -514,9 +523,9 @@ } }, "node_modules/@img/sharp-libvips-linux-ppc64": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.2.tgz", - "integrity": "sha512-3z0NHDxD6n5I9gc05U1eW1AyRm+Gznzq3naMrthPNqE6oYykcogW0l/jfpJdjYnuNl8R7yI9pNbE1XiUeyq0Aw==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.3.tgz", + "integrity": "sha512-cdn1OvUBwsXhbC0zSzJnNzf5MZ/mTrobawDvNXBTxe8VtqKAm0sRuEY2Evzovb/w9JMk4TvRxqt1mekSuJz64w==", "cpu": [ "ppc64" ], @@ -533,9 +542,9 @@ } }, "node_modules/@img/sharp-libvips-linux-riscv64": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.2.tgz", - "integrity": "sha512-bsb4rI+NldGOsXuej2r8OdSS8+zXDVaCWxyWrcv6kneTOlgAHtZABRzBBCwdsPiD90J4myNJuHpg6kA20ImW/w==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.3.tgz", + "integrity": "sha512-HjPVx7yKz+0lqdhDlTw1tt90wamBoxhiXpvl1XZpJLiHH4RCJ5yDTqH+VlYPv2fwFs89JFw4c1IexYOcQUi4IQ==", "cpu": [ "riscv64" ], @@ -552,9 +561,9 @@ } }, "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.2.tgz", - "integrity": "sha512-/ABshyj8gCpyIrNXnHn4LorDJ0HHm1VhXPBlxZ8zAtfVPAaSafXPGn+sUSIRiwaSBy0mmFjSjiXI5mkcwdChKQ==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.3.tgz", + "integrity": "sha512-neWLh+3yCNThxnfy3c4BbVBeGgt9aftno+XbT56iK28RgeDs3UOFWviLWlUu0bArYVYJaFDK+RRohbicUNCm8Q==", "cpu": [ "s390x" ], @@ -571,9 +580,9 @@ } }, "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.2.tgz", - "integrity": "sha512-ITPEtgffGJ0S6G9dRyw/366tJQqFRcHWPHhC+Stpg3Z8AEMrDrTr2lhdz4f/Y/HMbRh//7Z5mBzEpVdi62Oc3w==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.3.tgz", + "integrity": "sha512-4vKmvAst9nrowcqquKFAyZJUDolUaIp8uRiN0mWFguJ1IplC9/pitXtlnnlU4aa/eJw3J7i67V+pwUL+wZGdsA==", "cpu": [ "x64" ], @@ -590,9 +599,9 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.2.tgz", - "integrity": "sha512-zE9EdiUzUmg5mDT5a1rk5fYJ6GWPloTwWBYDS14naqHsL+EaMpDj1AWnpLgh3u0YCORv2Tt50wrcrpYqkP97Kw==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.3.tgz", + "integrity": "sha512-Y9kQaLMuNoB0bPYOOdcZMaseNrFpPodIWWMrx+CZyydf2xn68j9WYc6sWWRrDwNkzCQjKYfc68L7jKjGlHMibw==", "cpu": [ "arm64" ], @@ -609,9 +618,9 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.2.tgz", - "integrity": "sha512-m0lrLiUt+lBYnCFr8qV/65yMR4E/c7/wf78I5eKTdkEakFAlZ9QlzEM3QIhhAwVeUhLAHLcCq7a7Vszq/oFNZQ==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.3.tgz", + "integrity": "sha512-fj8Mv0HHfD1Rr+4I68+3agJynxDWtBFgicTbSOb9Bke6pIwzGcJ+RX/yHjmiEGFMCavY/dxvem7MyNaJF+wDiw==", "cpu": [ "x64" ], @@ -628,9 +637,9 @@ } }, "node_modules/@img/sharp-linux-arm": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.3.tgz", - "integrity": "sha512-affVWCTLooy8TSxbDx2qkzuDeaWLNVBA+P//FNBirHsXpP2fuBhk5AuboYUnrDnzoXes8GFjpTx0SBFOCRg+FA==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.4.tgz", + "integrity": "sha512-7OAS8gI0EReKGVN2HssHlM6umJgxF5VI3xN0p9FA91p/YO+ou5hiNghLdZ5BEHztwaaK5+bLKRf8x/o2L2nk9A==", "cpu": [ "arm" ], @@ -649,13 +658,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.3.2" + "@img/sharp-libvips-linux-arm": "1.3.3" } }, "node_modules/@img/sharp-linux-arm64": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.3.tgz", - "integrity": "sha512-QgKDspHPnrU+GQ55XPhGwyhC8acLVOOSyAvo1oVfFmrIXLkDNmGWzAfDZ4xK8oSA1qBQrALcHX0G5UZni/SuFQ==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.4.tgz", + "integrity": "sha512-De4jpEnAU8Hd5oT0j1G3uL4ZvTuipVMn7YC6vPaJhy6/7EwEae0SVAoBrUMYQbkLGDm85taVWwuPc1a44LTzCQ==", "cpu": [ "arm64" ], @@ -674,13 +683,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.3.2" + "@img/sharp-libvips-linux-arm64": "1.3.3" } }, "node_modules/@img/sharp-linux-ppc64": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.3.tgz", - "integrity": "sha512-sMd8rDxmpLOwv/7N44klFjOD5DUO7FLdjiXDI0hoxYaf7Ar262dQIEkosE98bps+5HPLtp/EvNqeqQtOycP/IA==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.4.tgz", + "integrity": "sha512-2oYZJeIl4kCcMGk4ouZVjnkCtFrpQFlNEtJ6GbxzhHQchwH0NH/qEb9ykmOl29dqwMq+JhFdZn+1ak2FKhI9fQ==", "cpu": [ "ppc64" ], @@ -699,13 +708,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-ppc64": "1.3.2" + "@img/sharp-libvips-linux-ppc64": "1.3.3" } }, "node_modules/@img/sharp-linux-riscv64": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.3.tgz", - "integrity": "sha512-0Eob78yjlYPfL5vMNWAW55l3R9Y6BQS/gOfe0ZcP9mEz9ohhKSt4im1hayiknXgf8AWrFqMvJcKIdmLmEe7yeQ==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.4.tgz", + "integrity": "sha512-cPbNChoRURAWdebDIHSenxRpgEdy7JkPydSnUxRm9VvKD7m0/xVaR/8Fzlu81pk5nHEvHH87UZUA7cTtwnbJSA==", "cpu": [ "riscv64" ], @@ -724,13 +733,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-riscv64": "1.3.2" + "@img/sharp-libvips-linux-riscv64": "1.3.3" } }, "node_modules/@img/sharp-linux-s390x": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.3.tgz", - "integrity": "sha512-KgAxQ0DxpNOq1rG2t5cgTgShJFGSuU7XO45cqC+1NVOuZnP6tlgZRuSYOfNupGkHID0o3cJOsw4DVeJpMovcGw==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.4.tgz", + "integrity": "sha512-RY0JFY8Fd6RonCBtHz+DvadaPkXDSI1AUn6yWL9TipqkZ1vY8w8evqdgyDFnkm4/K1ve1TvZiaePP5oSd4+WVQ==", "cpu": [ "s390x" ], @@ -749,13 +758,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.3.2" + "@img/sharp-libvips-linux-s390x": "1.3.3" } }, "node_modules/@img/sharp-linux-x64": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.3.tgz", - "integrity": "sha512-8pqvxubL2PGdhlPy6GLqzDYMUjyRmKAwKHYKixpdJYBUK7PJ0C029XdsnpFIdgRZG68fZiGdHVWcKPvtiPB4cA==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.4.tgz", + "integrity": "sha512-9qvvEAuk8k89TfWUoX2htWjbAMX8p+NxCppjpcg5k6xMsjhBQPTsoIh36h9Qde4WRuGpJeYnOjdosDn/cnv+OA==", "cpu": [ "x64" ], @@ -774,13 +783,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.3.2" + "@img/sharp-libvips-linux-x64": "1.3.3" } }, "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.3.tgz", - "integrity": "sha512-Vz0iQjzzcSX3HCbfwFfCSG/9SCIqyO0mH2sXyiHaAYfBk0cRsCWXRyQYX0ovCK/PAQBbTzQ0dsPQHh5MAFL59w==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.4.tgz", + "integrity": "sha512-KB5jxpfWQTr0nc3xdHtWChdbifHrBGsd2SM62Eyxrl8afikm+f5qGBU75SJIZBT/S1MC8XyacdlXBMSWq6OURA==", "cpu": [ "arm64" ], @@ -799,13 +808,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.3.2" + "@img/sharp-libvips-linuxmusl-arm64": "1.3.3" } }, "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.3.tgz", - "integrity": "sha512-6O1NPKcDVj9QEdg7Hx549EX8U0rp6yXQERqru6yRN7fGBn32UvIRJUlWnk+8xDCiG76hXVBbX82NZ/ZKr0euIg==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.4.tgz", + "integrity": "sha512-f+eZJZIQNEEd26RPSW+76chwOf1XtA2Y/O+5ocVyLliHkeih3e+jhLVBdNTd2rS3IbNXK8+ug93Vf5ZXtF5Lxg==", "cpu": [ "x64" ], @@ -824,17 +833,17 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.3.2" + "@img/sharp-libvips-linuxmusl-x64": "1.3.3" } }, "node_modules/@img/sharp-wasm32": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.3.tgz", - "integrity": "sha512-cZ0XkcYGpHZkqW6iCkqTcmUC0CD9DhD5d/qeZlZkfRBn6GnHniZXLUo5+9xw8Iv76YE6LQFN9YNBlKREcCG76w==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.4.tgz", + "integrity": "sha512-zQnl4Kwp7Q6NHsENtU2T/00Zi+w3AQNwz3+UaTyVBy2FpXrzXzGjndpK61onhZjRtRpQXxCTeqw19bVyXOh7jA==", "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, "dependencies": { - "@emnapi/runtime": "^1.11.1" + "@emnapi/runtime": "^1.11.3" }, "engines": { "node": ">=20.9.0" @@ -844,16 +853,16 @@ } }, "node_modules/@img/sharp-webcontainers-wasm32": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.3.tgz", - "integrity": "sha512-2rnq7bX3NzeR2T4YWgz8qiG4h3TSdMe+vN1iQXpJleSJ3SM5zQ8Fy2SyyXAWlbxpEZ2Y+Z4u1BePgJEYbSy80Q==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.4.tgz", + "integrity": "sha512-ESfNkywmCfPNyaZjxooddJQiQ+l/nTpGEOGthxiLnIHXC/CmcBixnfwUleX9mCz9ovrUUvKMap/pm8RYbzfwaA==", "cpu": [ "wasm32" ], "license": "Apache-2.0", "optional": true, "dependencies": { - "@img/sharp-wasm32": "0.35.3" + "@img/sharp-wasm32": "0.35.4" }, "engines": { "node": ">=20.9.0" @@ -863,9 +872,9 @@ } }, "node_modules/@img/sharp-win32-arm64": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.3.tgz", - "integrity": "sha512-4bPwFdMbeC4JQ8L8LOyWp6nsHcboP5fxkp6iPOXz2Vg49R42TuMs2whkJ5OAP4/Ul035qOzy0AecOF9VOscn4w==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.4.tgz", + "integrity": "sha512-iNdlBX9gLVvqe2I3uIJSIKTq6wckP/DYxZtcqxm09x5Gi24DnFBmPAWZmr60ZyYMG0xlzo6goG3670ar+RXvRw==", "cpu": [ "arm64" ], @@ -882,9 +891,9 @@ } }, "node_modules/@img/sharp-win32-ia32": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.3.tgz", - "integrity": "sha512-r53mXsBN6lFUDiST764SvgwUdHAqM4rPAiDzAmf4fLoB6X/rkfyTrLCg6+g17wJJiCmB3JYgHuUldCWUIRFSXw==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.4.tgz", + "integrity": "sha512-kqRsbaa5CS6KHlpxnN7WhE6vAAugXyZButpRdvDWetlv6Qv4N9WTcrWzF7tXfB9T7MsoadqdI8hmwLq6UlLvtw==", "cpu": [ "ia32" ], @@ -901,9 +910,9 @@ } }, "node_modules/@img/sharp-win32-x64": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.3.tgz", - "integrity": "sha512-D4y1vNeZrIIJCN+uHaWVtH86B+aCrdMYYjicy9pXHvbGZeGYLLSd3wdVuC37FxVXlU1ARsk84eKWfWMXGYEqvA==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.4.tgz", + "integrity": "sha512-XtmnYhBcrORsJ4XJngyzr/EWP0hRZLAZRFaApdKuviyqF78+ylxh2y06ZmtULAMOnObJ3ucpN0AcwSWnMowTRg==", "cpu": [ "x64" ], @@ -1085,6 +1094,12 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==", + "license": "MIT" + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -1266,6 +1281,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -1937,9 +1963,9 @@ } }, "node_modules/gaxios": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.5.tgz", - "integrity": "sha512-5FZy72Rh8LhtjmvDrKkI+lVhrsQrVKVsItxMoDm5mNQE+xR0WVIIs+jzPSJgBvKVsLi24fZhXJIsNI0bihDzFg==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.3.1.tgz", + "integrity": "sha512-kB3rzJV7d9juLZh8/56QTXCwQfxyhdOMdyYk1HdQKFtF8TJTDTZQJtixWIwXdE9Jji91mC41DUNpjleo4L4eAQ==", "license": "Apache-2.0", "dependencies": { "extend": "^3.0.2", @@ -1951,17 +1977,17 @@ } }, "node_modules/gcp-metadata": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz", - "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-9.0.3.tgz", + "integrity": "sha512-2YYnIlHaKBGT2IPg3G2M57hia9Galz15zsEOvw9T3oRf0lSn6KN6VcHQLqby7x8ksYKnjXvp3rp2KJyLCN6zfQ==", "license": "Apache-2.0", "dependencies": { - "gaxios": "^7.0.0", - "google-logging-utils": "^1.0.0", + "gaxios": "^7.1.3", + "google-logging-utils": "^2.0.0", "json-bigint": "^1.0.0" }, "engines": { - "node": ">=18" + "node": ">=22" } }, "node_modules/get-east-asian-width": { @@ -2039,16 +2065,16 @@ } }, "node_modules/google-auth-library": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-11.0.0.tgz", - "integrity": "sha512-WC5gkb2pElGhZKgGx9r799trH3ZUx90ecgIOIMmgiiHS/gzO3r4vvFoQWuKI0QmR2xU5uee2M4hDUxRZDh/x7w==", + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-11.0.2.tgz", + "integrity": "sha512-vzpgPutxrghPsnjrjpzLX2bdv8IOL719Rh0oEjGnQu8YCIbnbMuTTQ5zU9LcKvLdOPgCxBwppbvnhgW90Qna5Q==", "license": "Apache-2.0", "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", "gaxios": "^7.1.4", - "gcp-metadata": "8.1.2", - "google-logging-utils": "1.1.3", + "gcp-metadata": "^9.0.0", + "google-logging-utils": "^2.0.0", "jws": "^4.0.0" }, "engines": { @@ -2056,12 +2082,12 @@ } }, "node_modules/google-logging-utils": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz", - "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-2.0.1.tgz", + "integrity": "sha512-HMhaQghlOTvbcb3c4T5jmmOMtG3JUF1iOQMezaJXL86CDS+Tm2vHd0IeLFRAx3+ewd+bo9E1HFHoy17X5aJa9A==", "license": "Apache-2.0", "engines": { - "node": ">=14" + "node": ">=22" } }, "node_modules/gopd": { @@ -2497,9 +2523,9 @@ } }, "node_modules/jszip": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", - "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "version": "3.10.2", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.2.tgz", + "integrity": "sha512-3l+rb15IOWtUhU0H5MFqES/T6Kh7abYwjosBey/vD6hDt8zoEffkSC5Ws5SGtgVw3gBx2NEbhTeSW1+kWkpyTQ==", "license": "(MIT OR GPL-3.0-or-later)", "dependencies": { "lie": "~3.3.0", @@ -2533,6 +2559,10 @@ "resolved": "../dashdbschema", "link": true }, + "node_modules/libllmorbiter": { + "resolved": "../llmorbiter", + "link": true + }, "node_modules/lie": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", @@ -2698,9 +2728,9 @@ "license": "MIT" }, "node_modules/mssql": { - "version": "12.7.0", - "resolved": "https://registry.npmjs.org/mssql/-/mssql-12.7.0.tgz", - "integrity": "sha512-J6SJKXi1jYbhHjjooLNtPnX7+s3cq5IJ701Wgy/UW1SXRpgFlJJsYi3IPve9RVgCUkq0Cqv2aaaSJ4IXtIF3mg==", + "version": "12.7.2", + "resolved": "https://registry.npmjs.org/mssql/-/mssql-12.7.2.tgz", + "integrity": "sha512-zhpPw+WXBWLw7d7J6Y0aWgQy0EV8HKDGNSvmkAjP8bSM4H41X0fweAeKWI+bg9Ri+JHCbsf/QScjmACBFcEo8A==", "license": "MIT", "dependencies": { "@tediousjs/connection-string": "^1.0.0", @@ -2716,6 +2746,67 @@ "node": ">=18.19.0" } }, + "node_modules/multer": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/multer/-/multer-2.4.0.tgz", + "integrity": "sha512-7dqa0ZcFfzbefdTuIkzOSMvZWC0J7FLqBOjJUZvDCXShIURWKxAyTT1wHhnE5q19c7jOJf43IYYKjBmZVZmvhg==", + "license": "MIT", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.6.0", + "type-is": "^1.6.18" + }, + "engines": { + "node": ">= 10.16.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/multer/node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multer/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multer/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multer/node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/native-duplexpair": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/native-duplexpair/-/native-duplexpair-1.0.0.tgz", @@ -2978,9 +3069,9 @@ } }, "node_modules/react": { - "version": "19.2.8", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.8.tgz", - "integrity": "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==", + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.3.0.tgz", + "integrity": "sha512-E8LUcbtBWt20bbl2YoHfx4ZDBdxVTfOKtCZn9cDSJ4l6/nuoApcpIBcj47t2wZoVX8g2ZHuMHbiShgCR1T5Sog==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -3187,9 +3278,9 @@ "license": "ISC" }, "node_modules/sharp": { - "version": "0.35.3", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.3.tgz", - "integrity": "sha512-ej0zVHuZGHCiABXcNxeYhpRnPNPAcvbG8RMdBAhDAxLKkCRVSpK3Iyu7qbqw3JMzoj0REeM6f3tJLtVwl0023Q==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.4.tgz", + "integrity": "sha512-n++8XWcj+jCOr2IOl7h8LbKnGBDY4aPbmprMONBNFdn0ImXqpGVv5zliDs0V9HbmbCQLpbuo2ej9rAoOQTvMDA==", "license": "Apache-2.0", "dependencies": { "@img/colour": "^1.1.0", @@ -3203,31 +3294,31 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.35.3", - "@img/sharp-darwin-x64": "0.35.3", - "@img/sharp-freebsd-wasm32": "0.35.3", - "@img/sharp-libvips-darwin-arm64": "1.3.2", - "@img/sharp-libvips-darwin-x64": "1.3.2", - "@img/sharp-libvips-linux-arm": "1.3.2", - "@img/sharp-libvips-linux-arm64": "1.3.2", - "@img/sharp-libvips-linux-ppc64": "1.3.2", - "@img/sharp-libvips-linux-riscv64": "1.3.2", - "@img/sharp-libvips-linux-s390x": "1.3.2", - "@img/sharp-libvips-linux-x64": "1.3.2", - "@img/sharp-libvips-linuxmusl-arm64": "1.3.2", - "@img/sharp-libvips-linuxmusl-x64": "1.3.2", - "@img/sharp-linux-arm": "0.35.3", - "@img/sharp-linux-arm64": "0.35.3", - "@img/sharp-linux-ppc64": "0.35.3", - "@img/sharp-linux-riscv64": "0.35.3", - "@img/sharp-linux-s390x": "0.35.3", - "@img/sharp-linux-x64": "0.35.3", - "@img/sharp-linuxmusl-arm64": "0.35.3", - "@img/sharp-linuxmusl-x64": "0.35.3", - "@img/sharp-webcontainers-wasm32": "0.35.3", - "@img/sharp-win32-arm64": "0.35.3", - "@img/sharp-win32-ia32": "0.35.3", - "@img/sharp-win32-x64": "0.35.3" + "@img/sharp-darwin-arm64": "0.35.4", + "@img/sharp-darwin-x64": "0.35.4", + "@img/sharp-freebsd-wasm32": "0.35.4", + "@img/sharp-libvips-darwin-arm64": "1.3.3", + "@img/sharp-libvips-darwin-x64": "1.3.3", + "@img/sharp-libvips-linux-arm": "1.3.3", + "@img/sharp-libvips-linux-arm64": "1.3.3", + "@img/sharp-libvips-linux-ppc64": "1.3.3", + "@img/sharp-libvips-linux-riscv64": "1.3.3", + "@img/sharp-libvips-linux-s390x": "1.3.3", + "@img/sharp-libvips-linux-x64": "1.3.3", + "@img/sharp-libvips-linuxmusl-arm64": "1.3.3", + "@img/sharp-libvips-linuxmusl-x64": "1.3.3", + "@img/sharp-linux-arm": "0.35.4", + "@img/sharp-linux-arm64": "0.35.4", + "@img/sharp-linux-ppc64": "0.35.4", + "@img/sharp-linux-riscv64": "0.35.4", + "@img/sharp-linux-s390x": "0.35.4", + "@img/sharp-linux-x64": "0.35.4", + "@img/sharp-linuxmusl-arm64": "0.35.4", + "@img/sharp-linuxmusl-x64": "0.35.4", + "@img/sharp-webcontainers-wasm32": "0.35.4", + "@img/sharp-win32-arm64": "0.35.4", + "@img/sharp-win32-ia32": "0.35.4", + "@img/sharp-win32-x64": "0.35.4" }, "peerDependenciesMeta": { "@types/node": { @@ -3377,6 +3468,14 @@ "node": ">= 0.8" } }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", diff --git a/package.json b/package.json index 95a5953..8521b41 100644 --- a/package.json +++ b/package.json @@ -20,15 +20,17 @@ "crypto": "^1.0.1", "dotenv": "^17.4.2", "express": "^5.2.1", - "google-auth-library": "^11.0.0", + "google-auth-library": "^11.0.2", "ink": "^7.1.1", "ink-text-input": "^6.0.0", "jsonwebtoken": "^9.0.3", - "jszip": "^3.10.1", + "jszip": "^3.10.2", "libdashstore": "file:../dashdbschema", - "mssql": "^12.7.0", - "react": "^19.2.8", - "sharp": "^0.35.3" + "libllmorbiter": "file:../llmorbiter", + "multer": "^2.4.0", + "mssql": "^12.7.2", + "react": "^19.3.0", + "sharp": "^0.35.4" }, "devDependencies": { "swagger-jsdoc": "^6.3.0" diff --git a/scripts/generateApiDocs.js b/scripts/generateApiDocs.js index 120bac2..15bd332 100644 --- a/scripts/generateApiDocs.js +++ b/scripts/generateApiDocs.js @@ -156,6 +156,23 @@ function renderRequestBody(requestBody) { return lines; } + // multipart/form-data — render fields as a table when properties are present + const multipart = requestBody.content['multipart/form-data']; + if (multipart?.schema?.properties) { + const schema = multipart.schema; + const required = new Set(schema.required || []); + lines.push('## Body (`multipart/form-data`)'); + lines.push(''); + lines.push('| Field | Required | Type | Description |'); + lines.push('|-------|----------|------|-------------|'); + for (const [name, prop] of Object.entries(schema.properties)) { + const type = prop.format === 'binary' ? 'file' : (prop.type || ''); + lines.push(`| \`${name}\` | ${required.has(name) ? 'yes' : 'no'} | ${type} | ${prop.description || ''} |`); + } + lines.push(''); + return lines; + } + lines.push('## Body'); lines.push(''); for (const type of types) { @@ -257,6 +274,20 @@ function renderOperation(apiPath, method, operation) { lines.push(''); } + const sseEvents = operation['x-sse-events']; + if (Array.isArray(sseEvents) && sseEvents.length) { + lines.push('## SSE Events'); + lines.push(''); + lines.push('The response is a `text/event-stream`. Events are emitted in order until the stream closes.'); + lines.push(''); + lines.push('| Event | Description | Payload |'); + lines.push('|-------|-------------|---------|'); + for (const ev of sseEvents) { + lines.push(`| \`${ev.name}\` | ${ev.description || ''} | ${ev.payload ? `\`${ev.payload}\`` : ''} |`); + } + lines.push(''); + } + const responses = operation.responses || {}; const successCodes = Object.keys(responses) .filter((c) => c.startsWith('2')) diff --git a/src/api/routes/deliveryParsePdf.js b/src/api/routes/deliveryParsePdf.js new file mode 100644 index 0000000..0eee48f --- /dev/null +++ b/src/api/routes/deliveryParsePdf.js @@ -0,0 +1,419 @@ +'use strict'; + +import { execFileSync } from 'child_process'; +import multer from 'multer'; +import { LLMOrbiter, OpenRouterProvider, defineTool, DirectReturnError } from 'libllmorbiter'; +import * as dbCompanySetting from '../../db/companysetting.js'; + +// ─── Multer — memory storage (no temp files) ──────────────────────────────────── +const upload = multer({ + storage: multer.memoryStorage(), + limits: { fileSize: 50 * 1024 * 1024 }, // 50 MB + fileFilter: (_req, file, cb) => { + if (file.mimetype === 'application/pdf' || file.originalname?.toLowerCase().endsWith('.pdf')) { + cb(null, true); + } else { + cb(new Error('Only PDF files are accepted')); + } + }, +}); + +// ─── SSE helpers ──────────────────────────────────────────────────────────────── +function sseWrite(res, event, data) { + if (res.writableEnded) return; + res.write(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`); +} + +// ─── PDF → pages via pdftotext ────────────────────────────────────────────────── +function readPdfPages(buffer) { + // Write buffer to stdin by passing '-' as output and reading from stdin via + // execFileSync input option. pdftotext reads from '-' for stdin. + const raw = execFileSync('pdftotext', ['-layout', '-', '-'], { + input: buffer, + encoding: 'utf8', + maxBuffer: 50 * 1024 * 1024, + }); + return raw + .split('\f') + .map((p) => p.trim()) + .filter((p) => p.length > 0); +} + +// ─── Extraction prompt ────────────────────────────────────────────────────────── +const BASE_PROMPT = `Extract metadata and product line items from the provided invoice or delivery note. +Call the output_manifest tool with the extracted data. Do not answer with plain text once extraction is complete. + +Rules: +- manifestType: "rechnung" or "lieferschein". For "lieferschein", prices and taxes must be null. +- Exclude non-product lines (shipping, handling, etc.). +- Line items: Extract count, vpe (default: 1), liefArtNr, mwst (7 or 19), and eknetto per piece(euro cents). +- Match supplier against the provided list for kLieferant and lieferantName. For unknown suppliers, extract lieferantName and set kLieferant to null. +- Write notes strictly in German. +- The output_manifest tool has three strictly optional components: basedata, notes, items. Only include a component when it carries genuinely new data for this batch; omit the rest. +- Include basedata ONLY when at least one of its fields is currently null/empty and you can fill it in, or when a value actually changes. If all basedata fields are already set and unchanged, omit basedata. +- Include items ONLY when this batch contains new product line items not already present. If there are no new items, omit items. +- Include notes ONLY when there is a genuinely new noteworthy detail not already in the notes list. These notes are for a human to double-check the extraction result, so record anything ambiguous, unusual, or worth verifying (e.g. packaging interpretations, excluded lines, unavailable articles). + +VPE (Verpackungseinheit) Logic: +VPE represents the number of individually sellable units inside a bulk item. If not explicitly split for individual sale, default to 1. +- "20 Boxen á 10 Stück" -> VPE = 20. +- "10 Gläser á 100 Filter" -> VPE = 10 (we sell the 10 glasses individually). +- "100 Stück" -> VPE = 1 (sold as one bulk pack). +- We don't sell the individual filters or Pieces, but typical VPEs like Beutel, Glässer, Boxen, Hefte +- That means that in "Y Hefte á X Blatt" the VPE is NOT X but: Y +- a so called "Display" also means VPE. So "20er Display" means VPE = 20 +- eknetto is the price of one full vpe + +Unit (ME) rules: +- The unit (ME) must ALWAYS refer to the individual sellable item (e.g. Stk., Beutel, Flasche, Box, Set). It must NEVER be "VE" or "VPE". +- A packaging size like "VE100" means the bulk pack contains 100 individual items: set vpe = 100 and unit = the individual item (e.g. Stk.). +- Example: "Einhängesiebe Stahl, VE100" -> vpe = 100, unit = "Stk.", count = 1 (one bulk pack of 100 sieves).`; + +// ─── Route ─────────────────────────────────────────────────────────────────────── +/** + * @param {import('express').Application} app + * @param {string} [basePath=''] + */ +export function register(app, basePath = '') { + /** + * @openapi + * /delivery/parsePDF: + * post: + * tags: [Delivery] + * summary: Parse PDF (SSE) + * description: | + * Accepts a PDF invoice or delivery note (`multipart/form-data`, field `pdf`) + * and streams extraction results as Server-Sent Events until parsing is complete. + * + * The PDF is read via `pdftotext -layout` and fed page-by-page to an LLM + * (OpenRouter) which fills a structured manifest of header data and line items. + * The OpenRouter API key is read from the authenticated user's company setting + * `keys.openrouter`; the endpoint returns `400` if the key is not configured. + * + * The stream ends after the final `result` event (or an `error` event on failure). + * security: + * - cookieAuth: [] + * x-markdown: delivery/parsePDF.md + * x-sse-events: + * - name: status + * description: PDF parse confirmation and LLM status messages + * payload: '{ "message": "…" }' + * - name: llm_call + * description: Fired before each LLM request + * payload: '{ "model": "…", "promptSize": 0, "messages": 0 }' + * - name: tool_call + * description: Fired when the output_manifest tool is invoked + * payload: '{ "name": "output_manifest" }' + * - name: usage + * description: Token usage after each LLM response + * payload: '{ "input": 0, "cached": 0, "output": 0, "cost": 0 }' + * - name: progress + * description: Intermediate accumulated extraction state (basedata / notes / items) + * payload: ManifestResult + * - name: result + * description: Final accumulated extraction — emitted just before the stream closes + * payload: ManifestResult + * - name: error + * description: Emitted on PDF parse or LLM failure; stream closes immediately after + * payload: '{ "message": "…" }' + * requestBody: + * required: true + * content: + * multipart/form-data: + * schema: + * type: object + * required: [pdf] + * properties: + * pdf: + * type: string + * format: binary + * description: PDF file to parse (max 50 MB, application/pdf) + * responses: + * 200: + * description: | + * `text/event-stream` — emits `status`, `llm_call`, `tool_call`, `usage`, + * `progress`, `result` (and `error` on failure). See SSE Events table below. + * + * **ManifestResult shape** (used by `progress` and `result`): + * + * ```json + * { + * "basedata": { + * "date": "2026-01-15", + * "kLieferant": 42, + * "lieferantName": "Muster GmbH", + * "manifestNr": "LS-2026-001", + * "manifestType": "lieferschein" + * }, + * "notes": ["Pos. 3: VPE-Angabe fehlte, Standardwert 1 angenommen."], + * "items": { + * "pagesFrom": 1, + * "pagesTo": 2, + * "items": [ + * { + * "position": 1, + * "count": 10, + * "vpe": 1, + * "unit": "Stk.", + * "articleName": "Einhängesieb Stahl", + * "liefArtNr": "ES-100", + * "mwst": "19", + * "eknetto": 450, + * "page": 1 + * } + * ] + * } + * } + * ``` + * content: + * text/event-stream: + * schema: + * type: string + * 400: + * description: No PDF uploaded or OpenRouter key not configured + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/Error' + * 401: + * description: Unauthorized + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/Error' + */ + app.post( + `${basePath}/delivery/parsePDF`, + upload.single('pdf'), + async (req, res) => { + // ── Validate upload ────────────────────────────────────────────── + if (!req.file) { + return res.status(400).json({ error: 'A PDF file is required (field name: pdf)' }); + } + + // ── Fetch OpenRouter API key from company settings ──────────────── + let apiKey; + try { + const setting = await dbCompanySetting.getByKey(req.user.id, 'keys.openrouter'); + apiKey = setting?.value; + } catch (err) { + console.error('parsePDF: failed to read OpenRouter key:', err); + } + if (!apiKey) { + return res.status(400).json({ error: 'OpenRouter API key not configured (companysetting: keys.openrouter)' }); + } + + // ── Open SSE stream ────────────────────────────────────────────── + res.setHeader('Content-Type', 'text/event-stream'); + res.setHeader('Cache-Control', 'no-cache'); + res.setHeader('Connection', 'keep-alive'); + res.flushHeaders(); + + // ── Parse PDF ──────────────────────────────────────────────────── + let pages; + try { + pages = readPdfPages(req.file.buffer); + } catch (err) { + sseWrite(res, 'error', { message: 'Failed to parse PDF: ' + err.message }); + res.end(); + return; + } + + sseWrite(res, 'status', { message: `PDF parsed: ${pages.length} page(s)` }); + + // ── Accumulated state ──────────────────────────────────────────── + const manifestBasedata = { + date: null, + kLieferant: null, + lieferantName: null, + manifestNr: null, + manifestType: null, + }; + const manifestNotes = []; + const manifestItems = { items: [], pagesFrom: null, pagesTo: null }; + let currentPage = 0; + + // ── Tool definition ────────────────────────────────────────────── + const outputManifestTool = defineTool({ + name: 'output_manifest', + description: + 'Stores extracted invoice/delivery-note data: header metadata (basedata), notes, and product line items. Each component is strictly optional — only include the ones that carry new data.', + strict: false, + parameters: { + type: 'object', + additionalProperties: false, + required: [], + properties: { + basedata: { + anyOf: [ + { + type: 'object', + additionalProperties: false, + properties: { + date: { type: ['string', 'null'], description: 'Document date (ISO 8601)' }, + kLieferant: { type: ['number', 'null'], description: 'Lieferant ID' }, + lieferantName: { type: 'string', description: 'Lieferant name' }, + manifestNr: { type: ['string', 'null'], description: 'Lieferscheinnummer or Rechnungsnummer' }, + manifestType: { + anyOf: [ + { type: 'string', enum: ['rechnung', 'lieferschein'] }, + { type: 'null' }, + ], + description: 'Document type', + }, + }, + }, + { type: 'null' }, + ], + description: 'Header/metadata. Only include fields that are currently missing or changed.', + }, + notes: { + anyOf: [ + { type: 'array', items: { type: 'string' } }, + { type: 'null' }, + ], + description: 'New noteworthy details (in German), for a human to double-check the result.', + }, + items: { + anyOf: [ + { + type: 'object', + additionalProperties: false, + properties: { + numberOfItemsToAdd: { type: 'number', description: 'Number of NEW line items being added in this call.' }, + items: { + type: 'array', + description: 'Invoice/delivery product line items', + items: { + type: 'object', + additionalProperties: false, + required: ['position', 'count', 'vpe', 'unit', 'articleName', 'liefArtNr', 'mwst', 'eknetto'], + properties: { + position: { type: 'number', description: 'Position' }, + count: { type: 'number', description: 'Quantity (Menge)' }, + vpe: { type: 'number', description: 'Packaging unit size (VPE). Default: 1.' }, + unit: { type: 'string', description: 'Unit of the individual sellable item. NEVER "VE" or "VPE".' }, + articleName: { type: 'string', description: 'Article name' }, + liefArtNr: { type: 'string', description: 'Supplier article number' }, + mwst: { + anyOf: [{ type: 'string', enum: ['7', '19'] }, { type: 'null' }], + description: 'VAT rate; null if missing', + }, + eknetto: { type: ['number', 'null'], description: 'Net price per vpe in euro cents; null if missing' }, + }, + }, + }, + }, + }, + { type: 'null' }, + ], + description: 'New product line items.', + }, + }, + }, + invoke: async (args) => { + // Merge basedata + if (args.basedata && typeof args.basedata === 'object') { + for (const key of ['date', 'kLieferant', 'lieferantName', 'manifestNr', 'manifestType']) { + if (args.basedata[key] != null) manifestBasedata[key] = args.basedata[key]; + } + } + // Merge notes + if (Array.isArray(args.notes)) { + for (const n of args.notes) { + if (n && !manifestNotes.includes(n)) manifestNotes.push(n); + } + } + // Merge items + if (args.items && typeof args.items === 'object' && Array.isArray(args.items.items)) { + const existing = new Set(manifestItems.items.map((it) => it.position)); + for (const it of args.items.items) { + if (!existing.has(it.position)) { + manifestItems.items.push({ ...it, page: currentPage }); + existing.add(it.position); + } + } + const pages = manifestItems.items.map((it) => it.page).filter((p) => p != null); + if (pages.length) { + manifestItems.pagesFrom = Math.min(...pages); + manifestItems.pagesTo = Math.max(...pages); + } + } + + // Emit intermediate progress + sseWrite(res, 'progress', { + basedata: manifestBasedata, + notes: manifestNotes, + items: manifestItems, + }); + + throw new DirectReturnError({ + basedata: manifestBasedata, + notes: manifestNotes, + items: manifestItems, + }); + }, + }); + + // ── LLMOrbiter setup ───────────────────────────────────────────── + const model = '~openai/gpt-sol-latest'; + const provider = new OpenRouterProvider({ apiKey }); + const orbiter = new LLMOrbiter(provider, { + onStatus: (status) => sseWrite(res, 'status', { message: status }), + onLLMCall: (call) => + sseWrite(res, 'llm_call', { + model: call.model, + promptSize: call.promptSize, + messages: call.messages, + }), + onToolCall: (call) => sseWrite(res, 'tool_call', { name: call.name }), + onUsage: (usage) => + sseWrite(res, 'usage', { + input: usage.input, + cached: usage.cached, + output: usage.output, + cost: usage.cost, + }), + }); + + // ── Process all pages in one batch ─────────────────────────────── + try { + const pageContent = pages + .map((p, idx) => `--- Page ${idx + 1} of ${pages.length} ---\n${p}`) + .join('\n\n'); + + const prompt = `${BASE_PROMPT} + +You are processing all ${pages.length} page(s) of this document. + +Current manifest_basedata (fill in what is still missing): +${JSON.stringify(manifestBasedata, null, 2)} + +Current notes: +${JSON.stringify(manifestNotes, null, 2)} + +Current manifest_items: +${JSON.stringify(manifestItems, null, 2)} + +Page content: +${pageContent}`; + + currentPage = 1; + await orbiter.run({ prompt, model, tools: [outputManifestTool] }); + } catch (err) { + if (!res.writableEnded) { + sseWrite(res, 'error', { message: 'LLM processing failed: ' + err.message }); + } + } + + // ── Final result ───────────────────────────────────────────────── + sseWrite(res, 'result', { + basedata: manifestBasedata, + notes: manifestNotes, + items: manifestItems, + }); + + res.end(); + }, + ); +}