[2ff88f42] 1. Umfassende Entitäten-Erstellung: Wir haben erfolgreich Methoden implementiert, um die Kern-SuperOffice-Entitäten per API zu erstellen:

1. Umfassende Entitäten-Erstellung: Wir haben erfolgreich Methoden implementiert, um die Kern-SuperOffice-Entitäten per API zu erstellen:
       * Firmen (`Contact`)
       * Personen (`Person`)
       * Verkäufe (`Sale`) (entspricht D365 Opportunity)
       * Projekte (`Project`) (entspricht D365 Campaign), inklusive der Verknüpfung von Personen als Projektmitglieder.
   2. Robuste UDF-Aktualisierung: Wir haben eine generische und fehlertolerante Methode (update_entity_udfs) implementiert, die benutzerdefinierte Felder (UDFs) für sowohl Contact- als
      auch Person-Entitäten aktualisieren kann. Diese Methode ruft zuerst das bestehende Objekt ab, um die Konsistenz zu gewährleisten.
   3. UDF-ID-Discovery: Durch eine iterative Inspektionsmethode haben wir erfolgreich alle internen SuperOffice-IDs für die Listenwerte deines MA Status-Feldes (Ready_to_Send, Sent_Week1,
      Sent_Week2, Bounced, Soft_Denied, Interested, Out_of_Office, Unsubscribed) ermittelt und im Connector hinterlegt.
   4. Vollständiger End-to-End Test-Workflow: Unser main.py-Skript demonstriert nun einen kompletten Ablauf, der alle diese Schritte von der Erstellung bis zur UDF-Aktualisierung umfasst.
   5. Architekturplan für Marketing Automation: Wir haben einen detaillierten "Butler-Service"-Architekturplan für die Marketing-Automatisierung entworfen, der den Connector für die
      Textgenerierung und SuperOffice für den Versand und das Status-Management nutzt.
   6. Identifikation des E-Mail-Blockers: Wir haben festgestellt, dass das Erstellen von E-Mail-Aktivitäten per API in deiner aktuellen SuperOffice-Entwicklungsumgebung aufgrund fehlender
      Lizenzierung/Konfiguration des E-Mail-Moduls blockiert ist (500 Internal Server Error).
This commit is contained in:
2026-02-10 11:06:32 +00:00
parent 7281474a4f
commit b48dc9f46f
6 changed files with 328 additions and 71 deletions

View File

@@ -8,63 +8,71 @@ from superoffice_client import SuperOfficeClient
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def discover_fields():
def get_list_items_by_prog_id(client, prog_id, entity_name):
"""Fetches and prints list items for a specific ProgId."""
logger.info(f"--- Fetching list items for {entity_name} ProgId: {prog_id} ---")
# The endpoint for user-defined lists is typically generic
list_url = client._get_url(f"v1/List/UserDefinedField/{prog_id}")
try:
list_resp = client.session.get(list_url, headers=client._get_headers())
list_resp.raise_for_status()
list_items = list_resp.json()
if list_items.get("value"):
print(" --- List Items Found ---")
for item in list_items["value"]:
print(f" ID: {item.get('Id'):<5} | Name: {item.get('Name')}")
print(" ------------------------")
return {item.get('Name'): item.get('Id') for item in list_items["value"]}
else:
print(" (No list items found or unexpected response structure)")
return None
except Exception as list_e:
logger.error(f" Failed to fetch list items for {prog_id}: {list_e}")
if hasattr(list_e, 'response') and list_e.response is not None:
logger.error(f" List fetch details: {list_e.response.text}")
return None
def get_activity_types(client):
logger.info("--- Fetching Activity Types ---")
# Common endpoint for activity types
activity_type_url = client._get_url("v1/ActivityType") # Trying direct ActivityType endpoint
try:
resp = client.session.get(activity_type_url, headers=client._get_headers())
resp.raise_for_status()
activity_types = resp.json()
if activity_types:
print(" --- Activity Types Found ---")
for atype in activity_types:
print(f" ID: {atype.get('Id'):<5} | Name: {atype.get('Name')}")
print(" ------------------------")
return {atype.get('Name'): atype.get('Id') for atype in activity_types}
else:
print(" (No activity types found or unexpected response structure)")
return None
except Exception as e:
logger.error(f" Failed to fetch activity types: {e}")
if hasattr(e, 'response') and e.response is not None:
logger.error(f" Activity type fetch details: {e.response.text}")
return None
def main():
load_dotenv(dotenv_path="../.env")
auth = AuthHandler()
client = SuperOfficeClient(auth)
# --- We know the ProgIds, so we query them directly ---
# ProgId for the "MA Status" list on the Person entity
#person_ma_status_prog_id = "SuperOffice:2" # Keep for future reference
#get_list_items_by_prog_id(client, person_ma_status_prog_id, "Person MA Status")
try:
logger.info("Fetching general Contact metadata...")
general_metadata_url = client._get_url("v1/Metadata/Contact")
resp = client.session.get(general_metadata_url, headers=client._get_headers())
resp.raise_for_status()
general_metadata = resp.json()
print("\n--- GENERAL CONTACT METADATA (partial) ---")
print(f"DisplayName: {general_metadata.get('DisplayName')}")
print(f"HasUserDefinedFields: {general_metadata.get('HasUserDefinedFields')}")
print("----------------------------------------")
logger.info("Attempting to fetch UDF metadata...")
# Get metadata for Contact (Company)
url = client._get_url("v1/Metadata/Contact/UserDefinedFields")
resp = client.session.get(url, headers=client._get_headers())
resp.raise_for_status()
fields = resp.json()
print("\n--- AVAILABLE UDF FIELDS ---")
for field in fields.get("value", []):
label = field.get('FieldLabel')
prog_id = field.get('ProgId')
field_type = field.get('FieldType')
print(f"Label: {label} -> Technical Name: {prog_id} (Type: {field_type})")
# Check if the field is a list type
if field_type in ["List", "DropDown", "UserDefinedList"]: # Common types, might need adjustment
logger.info(f" -> Fetching list items for {label} (ProgId: {prog_id})...")
# Attempt to get the list items. The actual endpoint might vary.
# Assuming a pattern like 'v1/List/UserDefinedField/{ProgId}' or 'v1/UserDefinedFieldList/{ProgId}/Items'
list_url = client._get_url(f"v1/List/UserDefinedField/{prog_id}")
try:
list_resp = client.session.get(list_url, headers=client._get_headers())
list_resp.raise_for_status()
list_items = list_resp.json()
if list_items.get("value"):
print(" --- List Items ---")
for item in list_items["value"]:
print(f" ID: {item.get('Id')}, Name: {item.get('Name')}")
else:
print(" (No list items found or unexpected response structure)")
except Exception as list_e:
logger.warning(f" Failed to fetch list items for {label}: {list_e}")
if hasattr(list_e, 'response') and list_e.response is not None:
logger.warning(f" List fetch details: {list_e.response.text}")
except Exception as e:
logger.error(f"Failed to fetch metadata: {e}")
if hasattr(e, 'response') and e.response is not None:
print(f"Details: {e.response.text}")
get_activity_types(client)
if __name__ == "__main__":
discover_fields()
main()