# erpnext_custom Custom App für NEXTErp mit zuverlässigem Sync von Custom Fields zu WooCommerce (ACF / Meta Data). ## Funktionen - Sync beliebiger Custom Fields aus ERPNext-Item nach WooCommerce - Verwendung von `meta_data` (stabiler als ACF-Block) - Manueller Sync-Button im Item-Formular ## Voraussetzungen - ERPNext Version 16 (getestet mit 16.17.x) - WooCommerce + Advanced Custom Fields (ACF) Plugin - App **woocommerce_fusion** installiert und konfiguriert - Mindestens ein **WooCommerce Server** mit gültigen API-Keys (`api_consumer_key` + `api_consumer_secret`) - Im Item muss eine **WooCommerce ID** hinterlegt sein (Produkt muss in WooCommerce bereits existieren) - DocType **WooCommerce ACF Mapping** muss angelegt sein ## Installation ### 1. App erstellen ```bash cd ~/frappe-bench bench new-app erpnext_custom ``` Bei den Fragen: - App Title: NEXTErp Custom - App Description: WooCommerce ACF Custom Fields Sync - App Publisher: Jens Falk - App Email: service@falk.plus ```bash cd ~/frappe-bench/apps/erpnext_custom/erpnext_custom ``` ```bash cat > api.py << 'EOF' import frappe import requests from frappe import _ @frappe.whitelist() def sync_custom_fields_to_woocommerce(item_code): """Sync Custom Fields via meta_data nach WooCommerce""" frappe.msgprint("Sync gestartet fuer Artikel " + str(item_code), indicator="blue", alert=1) doc = frappe.get_doc("Item", item_code) if not doc.get("woocommerce_servers"): frappe.msgprint("Kein WooCommerce Server verknuepft", indicator="red", alert=1) return False # Mappings aus DocType laden mappings = frappe.get_all("WooCommerce ACF Mapping", filters={"enabled": 1}, fields=["erp_field", "acf_field"]) field_mapping = {m.erp_field: m.acf_field for m in mappings if m.erp_field and m.acf_field} if not field_mapping: frappe.msgprint("KEIN Mapping gefunden! Bitte im DocType 'WooCommerce ACF Mapping' Eintraege anlegen.", indicator="red", alert=1) return False for wc_link in doc.woocommerce_servers: if not wc_link.get("woocommerce_id"): continue try: wc_server = frappe.get_doc("WooCommerce Server", wc_link.woocommerce_server) api_key = wc_server.get("api_consumer_key") api_secret = wc_server.get("api_consumer_secret") if not api_key or not api_secret: continue base_url = wc_server.woocommerce_server_url.rstrip("/") if not base_url.endswith("/wp-json/wc/v3"): base_url += "/wp-json/wc/v3" url = base_url + "/products/" + str(wc_link.woocommerce_id) auth = (api_key, api_secret) # Produkt holen resp = requests.get(url, auth=auth, timeout=15) product = resp.json() meta_data = product.get("meta_data", []) for erp_field, acf_field in field_mapping.items(): value = doc.get(erp_field) or "" meta_data = [m for m in meta_data if m.get("key") != acf_field] meta_data.append({"key": acf_field, "value": value}) payload = {"meta_data": meta_data} update_resp = requests.put(url, json=payload, auth=auth, timeout=15) update_resp.raise_for_status() frappe.msgprint("Custom Fields erfolgreich gesendet!", indicator="green", alert=1) except Exception as e: frappe.msgprint("Fehler: " + str(e), indicator="red", alert=1) return True EOF ``` Danach ausführen ```bash bench restart ``` ### 2. DocType anlegen DocType Name: WooCommerce ACF Mapping **Felder:** - erp_field → Data → Pflicht - acf_field → Data → Pflicht - enabled → Check → Default = 1 - description → Small Text **Title Field:** erp_field ### Client Script mit Button Custom Script → New - DocType: Item - Script Type: Client Script ```js frappe.ui.form.on('Item', { refresh: function(frm) { frm.add_custom_button('Custom Fields zu WooCommerce syncen', function() { if (!frm.doc.woocommerce_servers || frm.doc.woocommerce_servers.length === 0) { frappe.msgprint("Kein WooCommerce Server verknüpft!", "Warnung"); return; } frappe.call({ method: 'erpnext_custom.api.sync_custom_fields_to_woocommerce', args: { item_code: frm.doc.name } }); }, "WooCommerce"); } }); ``` ### Nutzung - Im Item-Dokument unter WooCommerce ACF Mapping die gewünschten Felder eintragen. - Im Artikel-Formular auf den Button "Custom Fields zu WooCommerce syncen" klicken. ## Bekannte Probleme - Der Standard-Sync der `woocommerce_fusion`-App kann bei manchen Artikeln fehlschlagen (Fehler bei WooCommerce ID Parsing). Deshalb wird aktuell ein separater manueller Button verwendet. - `frappe.msgprint` Meldungen erscheinen manchmal nicht sofort oder nicht in der Console (besser im Browser testen). - Bei neuen Artikeln muss zuerst ein Produkt in WooCommerce existieren und die WooCommerce ID im Item hinterlegt sein. - ACF-Felder werden derzeit zuverlässig nur über `meta_data` übertragen (direkter ACF-Block war instabil). - Der Sync muss manuell über den Button ausgelöst werden (kein automatischer Sync beim Speichern, um Konflikte mit woocommerce_fusion zu vermeiden). ## Zukünftige Erweiterungen - Automatischer Sync beim Speichern des Items (ohne Konflikt mit woocommerce_fusion) - Bidirektionaler Sync (WooCommerce → ERPNext) - Unterstützung für direkten ACF-Block (falls REST API stabil läuft) - Logging-DocType für Sync-Historie und Fehleranalyse - Massen-Sync Funktion für mehrere Artikel auf einmal - Unterstützung für Varianten und Attribute - Möglichkeit, einzelne Felder vom Sync auszuschließen - Bessere Fehlermeldungen und Status-Übersicht ## Version History **v0.0.1** (08.06.2026) - Initiale Version - Sync via meta_data - Manueller Sync-Button - Dynamisches Mapping über DocType