MichaelWelsch commited on
Commit
016c9c4
·
verified ·
1 Parent(s): 54720f8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +115 -28
app.py CHANGED
@@ -384,71 +384,157 @@ def normalize_wholix_dropdown(val):
384
  return {"keys": [s], "values": [s]}
385
  return None
386
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
387
  def map_to_wholix_record(lead: dict, draft: dict, tag_text: str = "AI") -> dict:
388
- """
389
- JS mapToWholixContactsPayload → Python
390
- """
391
  p = (lead or {}).get("person") or {}
392
  c = (lead or {}).get("company") or {}
393
  m = (lead or {}).get("messages") or {}
394
  ctx = (lead or {}).get("context") or {}
395
 
396
- email = str(p.get("email") or "").strip()
 
397
  if not email:
398
  e = ValueError("E-Mail-Adresse fehlt – Wholix benötigt 'email' als Pflichtfeld.")
399
  e.name = "ValidationError"
400
  raise e
401
 
 
402
  depts_raw = p.get("departments")
403
  if isinstance(depts_raw, list):
404
- departments = ", ".join([str(x) for x in depts_raw if str(x).strip()]) or None
 
405
  else:
406
- departments = (str(depts_raw) if depts_raw is not None else None)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
407
 
408
- company_url = (
409
- str(c.get("url") or c.get("website") or c.get("domain") or "").strip()
410
- or str(ctx.get("url") or "").strip()
411
- or None
 
 
 
 
412
  )
413
 
414
- mail = m.get("email") if isinstance(m, dict) else {}
415
- mail_body = (mail.get("body") or "").strip() if isinstance(mail, dict) else ""
416
- mail_subject = (mail.get("subject") or "").strip() if isinstance(mail, dict) else ""
417
- followup1 = m.get("followup1")
418
- followup2 = m.get("followup2")
419
 
420
- street_parts = [c.get("street_name"), c.get("street_number")]
421
- street = " ".join([str(x).strip() for x in street_parts if str(x or "").strip()]) or ""
422
- street = street or None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
423
 
424
  payload = {
 
425
  "firstname": p.get("first_name") or None,
426
  "lastname": p.get("last_name") or None,
427
  "email": email,
428
- "adress": street, # (sic)
429
- "city": c.get("city") or None,
430
- "postcode": c.get("zip_code") or None,
431
  "phonenumber": p.get("phone") or None,
432
  "job_title": p.get("job_title") or None,
433
- "departments": departments,
434
  "linkedin_url": p.get("linkedin_url") or None,
435
 
436
- "company_name": c.get("name") or None,
437
- "company_url": company_url,
 
438
 
439
- "message_mail": mail_body or None,
440
- "message_mail_subject": mail_subject or None,
 
441
  "message_followup1": followup1 or None,
442
  "message_followup2": followup2 or None,
443
 
444
- "exclude_hash": (lead.get("exclude_hash") or None),
 
445
 
 
446
  "status_field": { "keys": ["Kontakt aufgenommen"], "values": ["Kontakt aufgenommen"] },
447
- "tags": { "keys": [str(tag_text).strip("[]") or "AI"], "values": [str(tag_text).strip("[]") or "AI"] },
448
  }
449
 
450
  normalized = filter_wholix_contact_fields(payload)
451
 
 
452
  if "status_field" in normalized:
453
  fixed = normalize_wholix_dropdown(normalized["status_field"])
454
  if fixed: normalized["status_field"] = fixed
@@ -461,6 +547,7 @@ def map_to_wholix_record(lead: dict, draft: dict, tag_text: str = "AI") -> dict:
461
 
462
  return normalized
463
 
 
464
  def wholix_store_contact(token: str, record: dict, module: str = "Contacts") -> dict:
465
  """
466
  JS wholixStoreContact exakt nachgebildet (mit Fallbacks)
 
384
  return {"keys": [s], "values": [s]}
385
  return None
386
 
387
+ def _first_non_empty(*vals):
388
+ for v in vals:
389
+ if isinstance(v, str) and v.strip():
390
+ return v.strip()
391
+ if v not in (None, "", [], {}):
392
+ return v
393
+ return None
394
+
395
+ def _from_ci(d: dict, *keys, default=None):
396
+ if not isinstance(d, dict):
397
+ return default
398
+ for k in keys:
399
+ if k in d and str(d[k]).strip() != "":
400
+ return d[k]
401
+ for dk in d.keys():
402
+ if dk.lower() == k.lower() and str(d[dk]).strip() != "":
403
+ return d[dk]
404
+ return default
405
+
406
+ def _join_nonempty(parts, sep=" "):
407
+ return sep.join([str(x).strip() for x in parts if str(x or "").strip()])
408
+
409
  def map_to_wholix_record(lead: dict, draft: dict, tag_text: str = "AI") -> dict:
 
 
 
410
  p = (lead or {}).get("person") or {}
411
  c = (lead or {}).get("company") or {}
412
  m = (lead or {}).get("messages") or {}
413
  ctx = (lead or {}).get("context") or {}
414
 
415
+ # --- Email (REQUIRED) ---
416
+ email = str(_first_non_empty(p.get("email"), _from_ci(p, "mail", "email_address")) or "").strip()
417
  if not email:
418
  e = ValueError("E-Mail-Adresse fehlt – Wholix benötigt 'email' als Pflichtfeld.")
419
  e.name = "ValidationError"
420
  raise e
421
 
422
+ # --- Departments as TEXT + we’ll mirror into tags dropdown later ---
423
  depts_raw = p.get("departments")
424
  if isinstance(depts_raw, list):
425
+ departments_txt = ", ".join([str(x).strip() for x in depts_raw if str(x).strip()]) or None
426
+ depts_list_for_tags = [str(x).strip() for x in depts_raw if str(x).strip()]
427
  else:
428
+ departments_txt = str(depts_raw).strip() if depts_raw not in (None, "", []) else None
429
+ depts_list_for_tags = [departments_txt] if departments_txt else []
430
+
431
+ # --- Company URL with wide fallbacks ---
432
+ company_url = _first_non_empty(
433
+ c.get("url"),
434
+ c.get("website"),
435
+ c.get("domain"),
436
+ c.get("homepage_url"),
437
+ c.get("website_url"),
438
+ c.get("url_normalized"),
439
+ ctx.get("url"),
440
+ (lead or {}).get("homepage_url"),
441
+ )
442
+
443
+ # --- Message fields: PULL FROM 'draft' (fix) ---
444
+ draft = draft or {}
445
+ draft_email = draft.get("email") if isinstance(draft, dict) else {}
446
+ # tolerate shapes like {'email': {'subject','body','to'}} + followups at root
447
+ msg_subject = _first_non_empty(
448
+ _from_ci(draft_email, "subject", "email_subject"),
449
+ _from_ci(draft, "subject", "email_subject", "Betreff"),
450
+ _from_ci(m, "message_mail_subject"), # legacy
451
+ )
452
+ msg_body = _first_non_empty(
453
+ _from_ci(draft_email, "body", "text", "content"),
454
+ _from_ci(draft, "body", "Text", "content", "email_body"),
455
+ _from_ci(m, "message_mail"), # legacy
456
+ )
457
+ followup1 = _first_non_empty(
458
+ _from_ci(draft, "followup1", "FollowUp1", "LinkedIn", "linkedin", "li"),
459
+ _from_ci(m, "followup1", "message_followup1"),
460
+ )
461
+ followup2 = _first_non_empty(
462
+ _from_ci(draft, "followup2", "FollowUp2", "Facebook", "facebook", "fb"),
463
+ _from_ci(m, "followup2", "message_followup2"),
464
+ )
465
 
466
+ # --- Address with wide fallbacks ---
467
+ street = _first_non_empty(
468
+ _join_nonempty([c.get("street_name"), c.get("street_number")]),
469
+ c.get("address"),
470
+ c.get("address1"),
471
+ c.get("address_line1"),
472
+ c.get("street"),
473
+ c.get("street_address"),
474
  )
475
 
476
+ city = _first_non_empty(
477
+ c.get("city"),
478
+ c.get("town"),
479
+ c.get("locality"),
480
+ )
481
 
482
+ postcode = _first_non_empty(
483
+ c.get("zip_code"),
484
+ c.get("postal_code"),
485
+ c.get("postcode"),
486
+ c.get("zip"),
487
+ )
488
+
489
+ # --- exclude_hash with fallbacks ---
490
+ exclude_hash = _first_non_empty(
491
+ lead.get("exclude_hash"),
492
+ c.get("exclude_hash"),
493
+ p.get("exclude_hash"),
494
+ lead.get("combined_id"),
495
+ )
496
+
497
+ # --- Build tags dropdown: keep existing tag_text and add departments (if any) ---
498
+ tag_items = [str(tag_text).strip("[]")] if str(tag_text).strip("[]") else []
499
+ for d in depts_list_for_tags:
500
+ if d and d not in tag_items:
501
+ tag_items.append(d)
502
+ tags_dropdown = {"keys": tag_items, "values": tag_items} if tag_items else None
503
 
504
  payload = {
505
+ # Person
506
  "firstname": p.get("first_name") or None,
507
  "lastname": p.get("last_name") or None,
508
  "email": email,
509
+ "adress": street or None, # (sic) exact key
510
+ "city": city or None,
511
+ "postcode": postcode or None,
512
  "phonenumber": p.get("phone") or None,
513
  "job_title": p.get("job_title") or None,
514
+ "departments": departments_txt, # text field, as before
515
  "linkedin_url": p.get("linkedin_url") or None,
516
 
517
+ # Company
518
+ "company_name": c.get("name") or c.get("company_name") or None,
519
+ "company_url": company_url or None,
520
 
521
+ # Message (now from 'draft')
522
+ "message_mail": msg_body or None,
523
+ "message_mail_subject": msg_subject or None,
524
  "message_followup1": followup1 or None,
525
  "message_followup2": followup2 or None,
526
 
527
+ # Other
528
+ "exclude_hash": exclude_hash or None,
529
 
530
+ # Dropdowns
531
  "status_field": { "keys": ["Kontakt aufgenommen"], "values": ["Kontakt aufgenommen"] },
532
+ "tags": tags_dropdown,
533
  }
534
 
535
  normalized = filter_wholix_contact_fields(payload)
536
 
537
+ # Normalize dropdowns (status/tags). Departments stays text.
538
  if "status_field" in normalized:
539
  fixed = normalize_wholix_dropdown(normalized["status_field"])
540
  if fixed: normalized["status_field"] = fixed
 
547
 
548
  return normalized
549
 
550
+
551
  def wholix_store_contact(token: str, record: dict, module: str = "Contacts") -> dict:
552
  """
553
  JS wholixStoreContact exakt nachgebildet (mit Fallbacks)