710 Nexar API (Octopart) » Historie » Version 1
[X] Philipp Wolak, 17.07.2023 12:37
| 1 | 1 | [X] Philipp Wolak | h1. 710 Nexar API (Octopart) |
|---|---|---|---|
| 2 | |||
| 3 | h2. Voraussetzungen: |
||
| 4 | |||
| 5 | # Erstellung eines Login's unter https://portal.nexar.com/ |
||
| 6 | # Anlage einer Application unter https://portal.nexar.com/applications/ {{collapse(Aufklappen) |
||
| 7 | !clipboard-202307171146-bhcrl.png! |
||
| 8 | }} |
||
| 9 | # Eintragung von Client-ID und Client-Secret in den dynamischen Einstellungen in Prodat {{collapse(Aufklappen) |
||
| 10 | !clipboard-202307171150-g4qoe.png! |
||
| 11 | }} |
||
| 12 | |||
| 13 | h2. Implementierte Funktionen |
||
| 14 | |||
| 15 | * Artikelinformationen in Stammdaten übernehmen |
||
| 16 | * Preise ale Lieferantenanfrage übernehmen |
||
| 17 | |||
| 18 | h2. Technische Dokumentation |
||
| 19 | |||
| 20 | * Das Datenmodell der Nexar API: https://api.nexar.com/ui/voyager |
||
| 21 | |||
| 22 | * Für die Abfrage der API wird folgendes benötigt: |
||
| 23 | ** ein Token ... Dieser wird bei jeder Anfrage aus der Client-ID und dem Client-Secret erstellt. |
||
| 24 | Dies macht die Funktion @get_token()@ in @nexarClient.py@ |
||
| 25 | ** eine Abfrage-Query ... Beispiele für Abfragen sind hier zu finden: https://support.nexar.com/support/solutions/articles/101000472564-query-templates |
||
| 26 | ** (optional Variablen ... Diese werden in der Abfrage-Query eingefügt, z.B. MPN) |
||
| 27 | * Die API wird mit der Python-Funktion @results = nexar.get_query(query, variables)@ abgefragt |
||
| 28 | |||
| 29 | h1. Integration in Prodat |
||
| 30 | |||
| 31 | * {{collapse(Tabellenstruktur) |
||
| 32 | In der Tabelle @nexar_api_call@ lässt sich die Abfrage-Query je Prodat-Form definieren |
||
| 33 | <pre><code class="sql"> |
||
| 34 | CREATE TABLE nexar_api_call ( |
||
| 35 | nex_id SERIAL PRIMARY KEY, |
||
| 36 | nex_api text NOT NULL, -- Nexar Anfrage-Query |
||
| 37 | nex_ownerform VARCHAR(100) -- Prodat Form |
||
| 38 | ); |
||
| 39 | </code></pre> |
||
| 40 | |||
| 41 | In der Tabelle @nexar_mapping@ lässt sich definieren welche Werte aus den erhaltenen Daten wo gespeichert werden sollen |
||
| 42 | <pre><code class="sql"> |
||
| 43 | CREATE TABLE nexar_mapping ( |
||
| 44 | nexm_id SERIAL PRIMARY KEY, |
||
| 45 | nexm_json_psth VARCHAR(250) NOT NULL, -- Nexar Attribut |
||
| 46 | nexm_table regclass NOT NULL, -- Zieltabelle Prodat |
||
| 47 | nexm_column VARCHAR(100) NOT NULL -- Zielfeld Prodat |
||
| 48 | ); |
||
| 49 | </code></pre> |
||
| 50 | Bsp: |
||
| 51 | !clipboard-202307171217-esdg5.png! |
||
| 52 | |||
| 53 | In der Tabelle @link_import@ werden die Informationen zu einer durchgeführten Abfrage gespeichert. |
||
| 54 | <pre><code class="sql"> |
||
| 55 | CREATE TABLE link_import ( |
||
| 56 | li_id SERIAL PRIMARY KEY, |
||
| 57 | li_connector varchar(20) NOT NULL, -- Anbindung (z.B. Nexar) |
||
| 58 | li_ownerform varchar(100), -- Prodat Form |
||
| 59 | li_ownerform_var json, -- Prodat Variablen |
||
| 60 | li_api_call text NOT NULL, -- Anfrage-Query |
||
| 61 | li_api_call_var json, -- zusätzliche Variablen |
||
| 62 | li_result json NOT NULL -- Ergebnis |
||
| 63 | ); |
||
| 64 | </code></pre> |
||
| 65 | }} |
||
| 66 | * Funktionen |
||
| 67 | ** Die Funktion @connector_import_json@ ruft für eine durchgeführte Abfrage die passende Import-Funktion auf (aktuell nur auf Nexar beschränkt) |
||
| 68 | {{collapse(SQL) |
||
| 69 | <pre><code class="sql"> |
||
| 70 | CREATE OR REPLACE FUNCTION connector_import_json( |
||
| 71 | IN _li_id integer |
||
| 72 | ) |
||
| 73 | RETURNS VOID AS $$ |
||
| 74 | DECLARE |
||
| 75 | _r record; |
||
| 76 | _ak_nr varchar; |
||
| 77 | BEGIN |
||
| 78 | |||
| 79 | SELECT * |
||
| 80 | INTO _r |
||
| 81 | FROM link_import |
||
| 82 | WHERE li_id = _li_id; |
||
| 83 | |||
| 84 | -- Nexar |
||
| 85 | IF _r.li_connector = 'Nexar' THEN |
||
| 86 | |||
| 87 | -- Artikelnummer aus den Variablen holen |
||
| 88 | _ak_nr = _r.li_ownerform_var->>'ak_nr'; |
||
| 89 | |||
| 90 | -- JSON importieren |
||
| 91 | PERFORM nexar_import_json(_r.li_result, _ak_nr); |
||
| 92 | |||
| 93 | END IF; |
||
| 94 | |||
| 95 | END $$ LANGUAGE plpgsql; |
||
| 96 | </code></pre> |
||
| 97 | }} |
||
| 98 | ** Die Funktionen @get_dynamic_json_path@ ermitteln anhand eines JSON-Paths das passende Element |
||
| 99 | {{collapse(SQL) |
||
| 100 | <pre><code class="sql"> |
||
| 101 | CREATE OR REPLACE FUNCTION get_dynamic_json_path(json_data jsonb, path_parts varchar) |
||
| 102 | RETURNS jsonb AS $$ |
||
| 103 | DECLARE |
||
| 104 | path jsonb; |
||
| 105 | current_part text; |
||
| 106 | BEGIN |
||
| 107 | path := json_data; |
||
| 108 | current_part := path_parts; |
||
| 109 | |||
| 110 | IF current_part ~ '^\\d+$' THEN |
||
| 111 | -- JSON-Array-Element |
||
| 112 | path := path -> current_part::int; |
||
| 113 | ELSEIF current_part LIKE '$%' THEN |
||
| 114 | -- JSON-Path-Query |
||
| 115 | path := jsonb_path_query(path,current_part::JSONPATH); |
||
| 116 | ELSE |
||
| 117 | -- JSON-Objekt-Eigenschaft |
||
| 118 | path := path -> current_part; |
||
| 119 | END IF; |
||
| 120 | |||
| 121 | |||
| 122 | RETURN path; |
||
| 123 | END; |
||
| 124 | $$ LANGUAGE plpgsql; |
||
| 125 | |||
| 126 | |||
| 127 | CREATE OR REPLACE FUNCTION get_dynamic_json_path(json_data jsonb, path_parts varchar[]) |
||
| 128 | RETURNS jsonb AS $$ |
||
| 129 | DECLARE |
||
| 130 | path jsonb; |
||
| 131 | current_part text; |
||
| 132 | BEGIN |
||
| 133 | path := json_data; |
||
| 134 | |||
| 135 | FOREACH current_part IN ARRAY path_parts |
||
| 136 | LOOP |
||
| 137 | IF current_part ~ '^\\d+$' THEN |
||
| 138 | -- JSON-Array-Element |
||
| 139 | path := path -> current_part::int; |
||
| 140 | ELSEIF current_part LIKE '$%' THEN |
||
| 141 | -- JSON-Path-Query |
||
| 142 | path := jsonb_path_query(path,current_part::JSONPATH); |
||
| 143 | ELSE |
||
| 144 | -- JSON-Objekt-Eigenschaft |
||
| 145 | path := path -> current_part; |
||
| 146 | END IF; |
||
| 147 | END LOOP; |
||
| 148 | |||
| 149 | RETURN path; |
||
| 150 | END; |
||
| 151 | $$ LANGUAGE plpgsql; |
||
| 152 | </code></pre> |
||
| 153 | }} |
||
| 154 | ** Die Funktion @nexar_import_json@ schreibt die Werte der Nexar API in die Prodat Datenbank |
||
| 155 | {{collapse(SQL) |
||
| 156 | <pre><code class="sql"> |
||
| 157 | CREATE OR REPLACE FUNCTION nexar_import_json( |
||
| 158 | IN _results json, |
||
| 159 | IN _ak_nr varchar, |
||
| 160 | IN _write_to_art boolean DEFAULT true, |
||
| 161 | IN _write_to_epreis boolean DEFAULT true |
||
| 162 | ) |
||
| 163 | RETURNS VOID AS $$ |
||
| 164 | DECLARE |
||
| 165 | _seller varchar; |
||
| 166 | _seller_path varchar; |
||
| 167 | _inventory varchar; |
||
| 168 | _inventory_path varchar; |
||
| 169 | _r record; |
||
| 170 | _value varchar; |
||
| 171 | _query varchar; |
||
| 172 | BEGIN |
||
| 173 | |||
| 174 | -- Artikeldaten übernehmen |
||
| 175 | IF _write_to_art THEN |
||
| 176 | |||
| 177 | -- alle definierten Felder durchlaufen und Werte schreiben |
||
| 178 | FOR _r IN ( |
||
| 179 | SELECT nexm_json_path AS path, |
||
| 180 | nexar_mapping.* |
||
| 181 | FROM nexar_mapping |
||
| 182 | WHERE nexm_table = 'art'::regclass |
||
| 183 | ) |
||
| 184 | LOOP |
||
| 185 | |||
| 186 | -- Wert für Feld aus JSON gemäß Setting-Tabelle ermitteln |
||
| 187 | SELECT get_dynamic_json_path(_results::jsonb, _r.nexm_json_path) |
||
| 188 | INTO _value; |
||
| 189 | |||
| 190 | continue when _value is null OR _value = 'null'; |
||
| 191 | |||
| 192 | -- Update Statement zusammenbauen und ausführen |
||
| 193 | _query := 'UPDATE ' || _r.nexm_table::varchar || ' SET ' || _r.nexm_column::varchar || ' = ''' || _value || ''' WHERE ak_nr = ''' || _ak_nr || ''''; |
||
| 194 | EXECUTE _query; |
||
| 195 | |||
| 196 | END LOOP; |
||
| 197 | |||
| 198 | END IF; |
||
| 199 | |||
| 200 | -- Lieferantenpreise übernehmen |
||
| 201 | IF _write_to_epreis THEN |
||
| 202 | |||
| 203 | -- alle definierten Felder durchlaufen und Werte schreiben |
||
| 204 | FOR _r IN ( |
||
| 205 | SELECT nexm_json_path AS path, |
||
| 206 | nexar_mapping.* |
||
| 207 | FROM nexar_mapping |
||
| 208 | WHERE nexm_table = 'epreis'::regclass |
||
| 209 | ) |
||
| 210 | LOOP |
||
| 211 | |||
| 212 | /* |
||
| 213 | ToDo: |
||
| 214 | 1. Lieferanten aus Adressstamm mit Nexar ID holen |
||
| 215 | 2. Loop über alle relevanten Lieferanten (evt. sinnvoll einschränken?) |
||
| 216 | 2.1 passenden Eintrag in JSON zum Lieferant finden |
||
| 217 | 2.2 INSERT/UPDATE Statement zusammenbauen und ausführen |
||
| 218 | */ |
||
| 219 | |||
| 220 | END LOOP; |
||
| 221 | |||
| 222 | END IF; |
||
| 223 | |||
| 224 | |||
| 225 | |||
| 226 | END $$ LANGUAGE plpgsql; |
||
| 227 | </code></pre> |
||
| 228 | }} |
||
| 229 | * Aufrufen lässt sich die Anbindung über den Zauberstab |