Files
erpnext_custom/README.md
T
2026-06-08 15:35:12 +02:00

5.7 KiB

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

Installation

1. App erstellen

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
cd ~/frappe-bench/apps/erpnext_custom/erpnext_custom
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

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
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