From 1f7fc84aae04a6d2f5a8f7aae04c1e994b27c2e3 Mon Sep 17 00:00:00 2001 From: Jens Falk Date: Sun, 7 Jun 2026 13:39:51 +0200 Subject: [PATCH] ... --- README.md | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) diff --git a/README.md b/README.md index fefdfe8..0bffe88 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,135 @@ # 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 \ No newline at end of file