# erpnext_custom Custom App für NEXTErp mit WooCommerce ACF Sync (Advanced Custom Fields). ## Funktionen - Übertragung beliebiger Custom Fields aus dem ERPNext-Item nach WooCommerce (ACF) - Dynamisches Mapping über das DocType `WooCommerce ACF Mapping` - Funktioniert mit mehreren WooCommerce Servern ## Installation (empfohlener Weg) ### 1. App auf dem Server erstellen ```bash cd ~/frappe-bench bench new-app erpnext_custom ``` Bei den Fragen folgendes eingeben: App Title: NEXTErp Custom App Description: WooCommerce ACF Custom Fields Sync App Publisher: Jens Falk App Email: service@falk.plus (oder deine Email) Branch Name: main oder einfach Enter drücken cd ~/frappe-bench/apps/erpnext_custom/erpnext_custom # Hier die aktuelle api.py einfügen (z.B. per cat > api.py << 'EOF' ...) cat > api.py << 'EOF' import frappe import requests from frappe import _ @frappe.whitelist() def sync_custom_fields_to_woocommerce(item_code): """Sync Custom Fields vom Item nach WooCommerce ACF (dynamisch aus DocType)""" if not item_code: frappe.throw(_("Kein Item Code angegeben")) try: doc = frappe.get_doc("Item", item_code) except Exception: frappe.throw(_("Item {0} nicht gefunden").format(item_code)) if not doc.get("woocommerce_servers"): frappe.msgprint(_("Item hat keine verknüpften WooCommerce Server"), indicator="orange") return False # Dynamisches Mapping aus dem DocType "WooCommerce ACF Mapping" field_mapping = {} mappings = frappe.get_all("WooCommerce ACF Mapping", filters={"enabled": 1}, fields=["erp_field", "acf_field"]) for m in mappings: if m.erp_field and m.acf_field: field_mapping[m.erp_field] = m.acf_field if not field_mapping: frappe.msgprint(_("Keine aktivierten Mappings im DocType 'WooCommerce ACF Mapping' gefunden."), indicator="orange") return False success_count = 0 errors = [] for wc_link in doc.woocommerce_servers: if not wc_link.enable_sync or not wc_link.woocommerce_id: continue try: wc_server = frappe.get_doc("WooCommerce Server", wc_link.woocommerce_server) if not wc_server.api_key or not wc_server.api_secret: errors.append("WooCommerce Server {} hat keine Zugangsdaten".format(wc_link.woocommerce_server)) 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 = "{}/products/{}".format(base_url, wc_link.woocommerce_id) auth = (wc_server.api_key, wc_server.api_secret) resp = requests.get(url, auth=auth, timeout=15) resp.raise_for_status() product = resp.json() acf_data = product.get("acf", {}) updated_fields = 0 for erp_field, acf_field in field_mapping.items(): value = doc.get(erp_field) if value is not None: acf_data[acf_field] = value updated_fields += 1 if updated_fields == 0: continue payload = {"acf": acf_data} update_resp = requests.put(url, json=payload, auth=auth, timeout=15) update_resp.raise_for_status() success_count += 1 except Exception as e: error_msg = "Fehler für Item {} / WC-ID {}: {}".format(item_code, wc_link.woocommerce_id, str(e)) errors.append(error_msg) frappe.log_error(error_msg, "WooCommerce ACF Sync") if success_count > 0: msg = "Custom Fields für {} WooCommerce-Produkt(e) erfolgreich synchronisiert".format(success_count) if errors: msg += " ({} Fehler)".format(len(errors)) frappe.msgprint(msg, alert=True, indicator="green") return True else: if errors: frappe.msgprint("Fehler beim Sync:\n" + "\n".join(errors[:3]), indicator="red") else: frappe.msgprint("Keine Felder wurden synchronisiert.", indicator="orange") return False EOF ### Installation abschließen ```bash bench --site erp.berchmans.de install-app erpnext_custom --force bench --site erp.berchmans.de migrate bench restart Weiterer Schritt (nach Installation) Danach das DocType WooCommerce ACF Mapping anlegen