Blogeinträge für produktimport

How-To
Robuster Daten-Import/Export in Odoo auf Basis von connector_flow
von Thomas Rehn am

An English translation of the following text also is available.

Ein ERP-System ist in der Regel kein abgeschlossenes IT-System, sondern ist in zahlreiche Prozesse eingebunden, die Interaktion mit anderen Systemen voraussetzen. Sei es, dass Produktstammdaten eines Excel-Katalogs importiert werden sollen, dass Bestellungen an einen Logistikdienstleister per FTP übergeben werden sollen, oder, dass Kontobewegungen von einer Bank eingelesen werden sollen. Zwar können auch andere Programme auf Odoo zugreifen (zum Beispiel via RPC oder REST-API), aber eine direkt in Odoo implementierte Lösung ist für alles, was über reine Datenwandlung hinausgeht, meistens die Einfachste.
Hier setzt unser Odoo-Modul connector_flow an.
Es bietet in Odoo eine Struktur, in der wiederkehrende Aufgaben implementiert werden können und die Standardaufgaben wie FTP-Download/-Upload und CSV-Verarbeitung übernimmt. Einzelne Arbeitsschritte können getrennt implementiert und über definierte Schnittstellen zu einem Prozess zusammengefasst werden. connector_flow basiert auf dem erprobten, großartigen Connector-Framework, was einen kontrollierbaren, nachvollziehbaren und parallelisierbaren Ablauf ermöglicht.
Als Beispiel betrachten wir im Folgenden einen stark vereinfachten Import von Produktstammdaten aus einer CSV-Datei. Auf derselben technischen Grundlage haben wir für zwei unserer Kunden einen Import erstellt, der Produktdaten für etwa eine halbe Million Produkte aus einer CSV-Datei einliest.

Unseren Produkt-Import können wir in zwei Schritte aufteilen: erst lesen wir die CSV-Datei ein und pflegen dann die Produkte in Odoo. Der dazugehörige technische Prozess (Task Flow) besteht daher aus diesen zwei Tasks.

Task Flow Example


Zweistufiger Task Flow für den Produkt-Import aus CSV

Für den ersten Schritt, der Handhabung der CSV-Datei, können wir auf einen Task zurückgreifen, der schon mit dem connector_flow-Modul kommt. Dieser csv_import zerlegt eine CSV-Datei in ihre Zeilen und speichert diese jeweils einzeln als Python-Datenstruktur ab (Liste oder Dictionary), auch Chunk genannt.
Im zweiten Schritt, dem Erstellen des Produkts in Odoo, können wir dann aus einer solchem Chunk (Zeile des CSVs) ein Produkt angelegen oder aktualisieren. Zur technischen Umsetzung müssen wir zum einen diesen Task programmieren und zum anderen den Task Flow zusammensetzen.

Als Erstes kümmern wir uns um den Task zum Anlegen des Produkts. Da dieser Task von seinem Vorgänger (Lesen der CSV-Datei) ein Chunk als Eingabe bekommt, erben wir von der Klasse abstract_chunk_read_task aus dem connector_flow-Modul. Im Parameter chunk_data bekommen wir ein Dictionary, da wir das Lesen des CSVs entsprechend konfigurieren werden. Die Keys des Dictionaries entsprechen den Spaltennamen der CSV-Datei (Beispieldaten). Damit ist es nur noch eine Fingerübung das Produkt in Odoo basierend auf dem Chunk anzulegen:

class product_catalog_import(abstract_chunk_read_task):
    def read_chunk(self, config=None, chunk_data=None, async=True):
        product_data = {
            'name': chunk_data.get('Name'),
            'list_price': float(chunk_data.get('Preis VK')),
            'standard_price': float(chunk_data.get('Preis EK')),
        }
        product_image_url = chunk_data.get('Image URL')
        if product_image_url:
            url_obj = urllib2.urlopen(product_image_url)
            product_data['image'] = b64encode(url_obj.read())
        self.session.create('product.product', product_data)

Um unsere Klasse product_catalog_import im Task Flow verwenden zu können, müssen wir sie noch im Odoo-Model impexp.task registrieren. Dies geschieht über gewöhnliche Odoo-Vererbung. Zum einen muss ein Bezeichner zu _get_available_tasks hinzugefügt werden, zum anderen muss eine Methode …_class erstellt werden, deren Namen dem gewählten Bezeichner entspricht.

class product_catalog_import_task(orm.Model):
    _inherit = 'impexp.task'
 
    def _get_available_tasks(self, cr, uid, context=None):
        return super(product_catalog_import_task, self) \
            ._get_available_tasks(cr, uid, context=context) \
            + [('product_catalog_import', 'Produkt Catalog Import')]
 
    _columns = {
        'task': fields.selection(_get_available_tasks, string='Task',
                                 required=True),
    }
 
    def product_catalog_import_class(self):
        return product_catalog_import

Damit können wir unseren Task Flow aufbauen. Dies ist zwar auch manuell über die Odoo-Oberfläche möglich; es empfiehlt sich aber der Übersichtlichkeit halber eine Konfiguration per XML. Dort legen wir Records jeweils für den Task Flow, die zwei Tasks und einen Übergang zwischen den beiden Tasks an. Der erste Task im Task Flow muss die Eigenschaft flow_start besitzen. Dies ist in unserem Fall der csv_import, der mit dem connector_flow-Modul kommt. Wir konfigurieren ihn noch mittels der includes_header-Eigenschaft im config-Wert so, dass er die erste Zeile der CSV-Datei als Überschrift verwendet und diese verwendet, um aus den übrigen Zeilen Dictionaries zu erstellen. Der zweite Task ist product_catalog_import gemäß dem Bezeichner, den wir oben im impexp.task-Model gewählt haben. Zum Schluss fügen wir noch einen Übergang zwischen den Tasks hinzu.

        <!-- Task flow -->
 
 
            Product Catalog Import
 
 
        <!-- Task and task transition -->
 
 
            Product catalog CSV to chunks
            csv_import
 
 
            <![CDATA[{'includes_header': True}]]>
 
 
 
            Product catalog chunks to products
            product_catalog_import

Um den Produkt-Import auszuführen, benutzen wir den Wizard unter Connector > Import/Export > Run Task. Als Task Flow wählen wir „Product Catalog Import“ aus, als File unsere CSV-Datei.

Produkt-Import ausführen

Produkt-Import ausführen

Beispiel-Daten für Produktimport

Beispiel-Daten für Produktimport

Kurze Zeit (wie kurz hängt von der Konfiguration des Connectors-Frameworks ab) nach Klick auf Run Task sind dann drei Produkte in Odoo angelegt; das vierte Produkt „Orange“ aus der Eingabedatei fehlt.

Die Beispiel-Produkte Apfel, Kiwi und Limette sind importiert

Die Beispiel-Produkte Apfel, Kiwi und Limette sind importiert

Unter Connector > Warteschlange > Arbeitsschritte sehen wir, dass eine Ausführung des zweiten Tasks fehlgeschlagen ist, weil die Bild-URL fehlerhaft ist. Um das Produkt dennoch zu importieren, können wir mit einem Klick auf den Related-Button die Rohdaten bearbeiten und beispielsweise die URL korrigieren oder entfernen. Nach dieser Datenkorrektur kann der Arbeitsschritt erneut gestartet werden, so dass schließlich auch die Orange in Odoo verfügbar ist.

Eine Zeile in der CSV-Datei enthält fehlerhafte Daten

Eine Zeile in der CSV-Datei enthält fehlerhafte Daten

Der Quellcode von connector_flow-Modul ist auf Github verfügbar. Dort findet sich auch der hier vorgestellte Beispiel-Code als connector_flow_example_product inklusive Beispiel-CSV (contrib/fruit_catalog.csv).

Falls Sie auch Interesse an Odoo/OpenERP haben oder unsere Expertise für Ihr ERP-Projekt benötigen, dann nehmen Sie mit uns Kontakt auf. Wir helfen Ihnen gerne weiter!

Sie erreichen uns unter der Telefonnummer +49 (0)4105 5615699 oder per Mail an info@initos.com.

Lesen
zurück zur Übersicht