זיהוי כפילויות — מה קורה בשרת
“מה קורה אם אותו אדם ממלא את הטופס פעמיים?” — זו השאלה שהלקוח שואל בכל פרויקט, ובדרך כלל הוא מצפה לתשובה “המערכת תזהה ותמזג”. היא לא ממזגת. היא מזהה, מסמנת, ויוצרת שורה חדשה.
העמוד הזה מפרט בדיוק מה רץ בצד השרת, כדי שתוכלו לענות ללקוח לפני העלייה לאוויר ולא אחריה.
איך נראית הבדיקה
Section titled “איך נראית הבדיקה”הבדיקה זהה בנקודות הקצה הקיימות (web2table ו‑web2case — שתיהן אומתו מול אותו איש קשר), ורצה אחרי בדיקת דגל ה‑Config ולפני יצירת הרשומה: דגל כבוי + טלפון קיים מחזיר … is Disabled, לא התאמה.
1 · נרמול הטלפון
Section titled “1 · נרמול הטלפון”השרת מסיר מהמספר כל תו שאינו ספרה, וממיר קידומת בינלאומית לצורה המקומית — 972… הופך ל‑0….
| מה הגולש הקליד | הצורה המנורמלת |
|---|---|
050-123-4567 |
0501234567 |
+972 50 1234567 |
0501234567 |
972501234567 |
0501234567 |
שלושת הפורמטים בטבלה, וגם "050 200 0001" עם רווחים, נבדקו בפועל — כולם איתרו את אותו איש קשר.
2 · סריקה של חמישה פורמטים שמורים
Section titled “2 · סריקה של חמישה פורמטים שמורים”הנרמול לא מספיק, כי הנתונים במערכת עצמה שמורים בפורמטים מעורבים — ייבוא ישן, הקלדה ידנית, אינטגרציה שכתבה בפורמט בינלאומי. לכן השרת לא מחפש ערך אחד; הוא בונה מהמספר המנורמל שאילתה על חמישה פורמטים שמורים — בדיוק אלה, ולא אחרים:
Accounts.PhoneNumber ∈ { 0501234567 ← 05XXXXXXXX 972501234567 ← 9725XXXXXXX +972501234567 ← +9725XXXXXXX 050-1234567 ← 05X-XXXXXXX +972-50-1234567 ← +972-5X-XXXXXXX}ובאותה צורה לקידומות של קווי נייח (02…, 03…, 04…, 08…, 09…) — אומת: 039990001, 97239990001, +97239990001, 03-9990001 ו‑+972-3-9990001 כולם אותרו מקלט 039990001. חמשת הפורמטים הסלולריים אומתו גם מקלט מנורמל וגם מקלט זהה לפורמט השמור.
3 · OR מול האימייל
Section titled “3 · OR מול האימייל”כל הווריאציות למעלה מחוברות ב‑OR להשוואת שוויון על Accounts.Email. כלומר: התאמה בטלפון או התאמה באימייל = כפילות. אומת: טלפון חדש לגמרי עם אימייל של איש קשר קיים — מחזיר את ה‑accountId הקיים.
// המבנה הלוגי של השאילתה (המחשה){ "$or": [ { "PhoneNumber": "0501234567" }, { "PhoneNumber": "+972501234567" }, { "PhoneNumber": "050-1234567" }, { "Email": "israel@example.co.il" }] }4 · ב‑web2table — שלושה מפתחות נוספים
Section titled “4 · ב‑web2table — שלושה מפתחות נוספים”web2table מרחיב את אותה בדיקה:
| המפתח בבקשה | מול איזה שדה | הערה |
|---|---|---|
phone |
PhoneNumber |
מפתח חובה |
phone2 |
טלפון משני | מזין את החיפוש, אבל אינו נשמר — אין שדה טלפון משני בתבנית vanilla |
email |
Email |
|
email2 |
אימייל משני | מזין את החיפוש, אבל אינו נשמר — אין שדה אימייל משני בתבנית vanilla |
idnum |
CompanyId |
ח.פ. / ת.ז. — התאמה מדויקת, בלי נרמול |
חמשת המפתחות נבדקו אחד־אחד מול איש קשר קיים: כל אחד מהם, לבדו, איתר אותו. אימות ה‑idnum כלל גם את היעדר הנרמול — "123-456-780" לא התאים ל‑"123456780", והמחרוזת נשמרה ב‑CompanyId כפי שנשלחה.
כפילות לא חוסמת יצירה
Section titled “כפילות לא חוסמת יצירה”זו הנקודה שהכי חשוב להסביר ללקוח מראש.
ב‑getlead — תמיד נוצרת שורה חדשה
Section titled “ב‑getlead — תמיד נוצרת שורה חדשה”אומת בפועל (24.08.2026): שליחה חוזרת של אותו טלפון ל‑getlead יצרה שורת ליד שנייה שסומנה בסטטוס “ליד כפול” (QYvLV9xHE1 בתבנית), בעוד הליד הראשון קיבל “ליד חדש” (e9TwcETDGq).
| התוצאה | מה קורה |
|---|---|
| נמצאה התאמה | נוצרת שורת ליד חדשה, ומסומנת בסטטוס “ליד כפול” |
| לא נמצאה | נוצרת שורת ליד חדשה עם ה‑LeadStatusId שנשלח בבקשה, ואם לא נשלח — עם סטטוס “ליד חדש” |
אין מיזוג ואין עדכון של הליד הקיים. הרציונל: שתי פניות הן שני אירועים עסקיים, גם אם מדובר באותו אדם — והשדה שמבדיל ביניהן הוא הסטטוס.
ב‑web2table — איש קשר קיים מקושר, לא משוכפל
Section titled “ב‑web2table — איש קשר קיים מקושר, לא משוכפל”כאן ההתנהגות הפוכה, וזו בדיוק הסיבה שיש שתי נקודות קצה:
| התוצאה | מה קורה ל‑Accounts |
מה קורה לטבלת היעד |
|---|---|---|
| נמצא איש קשר | לא נוצרת שורה חדשה, וגם לא מתעדכן דבר | נוצרת שורה חדשה, מקושרת אליו דרך AccountId |
| לא נמצא | נוצר איש קשר חדש עם הערכים מ‑account_* ומ‑DefaultValues.Account |
נוצרת שורה חדשה, מקושרת אליו |
IsFirst — השדה שנראה אמין ואינו
Section titled “IsFirst — השדה שנראה אמין ואינו”בכל שורה שנוצרת בטבלת היעד השרת ממלא IsFirst. הרבה דוחות “לידים חדשים מול לקוחות חוזרים” נשענים עליו — ולכן חשוב לדעת מתי הוא נכון:
| מצב הבקשה | איש הקשר | IsFirst |
|---|---|---|
| כל בקשה | חדש | true |
נשלח isExistsAccountCheck: true |
קיים | false |
לא נשלח isExistsAccountCheck |
קיים | true ← לא נכון עסקית |
אותו דגל משפיע גם על שדה ה‑Name שהשרת ממלא בשורה החדשה כשלא נשלח Name בבקשה:
| המצב | ערך Name שנקבע |
|---|---|
Name נשלח בבקשה |
הערך שנשלח |
| איש קשר חדש | "פניה ראשונה" |
איש קשר קיים + isExistsAccountCheck |
"פניה חוזרת" |
הפלטפורמה עצמה לא אוכפת ייחודיות
Section titled “הפלטפורמה עצמה לא אוכפת ייחודיות”זו עובדה שקובעת ארכיטקטורה בכל אינטגרציה, לא רק בטפסים: אין אילוץ ייחודיות על PhoneNumber או על Email בטבלת Accounts. שום דבר לא ימנע מכם ליצור עשר רשומות עם אותו טלפון.
לכן:
- בטפסים — זיהוי הכפילויות של
getlead/web2tableהוא מה שמחליף את האילוץ החסר. זו סיבה טובה להשתמש בנקודות הקצה האלה ולא לכתוב יצירה ישירה. - ב‑REST API — האחריות עליכם: find‑before‑create בכל זרימה שיוצרת אנשי קשר.
# find-before-create ב-REST — בדיקה לפני יצירה. צד שרת בלבד.curl -sS -G "https://api.mbapps.co.il/parse/classes/Accounts" \ -H "X-Parse-Application-Id: $APP_ID" -H "X-Parse-Master-Key: $MASTER_KEY" \ --data-urlencode 'where={"PhoneNumber":"0501234567"}' \ --data-urlencode 'limit=5'# 0 תוצאות → ליצור · 1 → לעדכן · יותר מאחת → כפילות קיימת, דורשת החלטה אנושית// find-before-create ב-REST — בדיקה לפני יצירה. צד שרת בלבד.const params = new URLSearchParams({ where: JSON.stringify({ PhoneNumber: '0501234567' }), limit: '5',});const res = await fetch(`https://api.mbapps.co.il/parse/classes/Accounts?${params}`, { headers: { 'X-Parse-Application-Id': APP_ID, 'X-Parse-Master-Key': MASTER_KEY, },});// 0 תוצאות → ליצור · 1 → לעדכן · יותר מאחת → כפילות קיימת, דורשת החלטה אנושית# find-before-create ב-REST — בדיקה לפני יצירה. צד שרת בלבד.import jsonimport requests
res = requests.get( "https://api.mbapps.co.il/parse/classes/Accounts", headers={ "X-Parse-Application-Id": APP_ID, "X-Parse-Master-Key": MASTER_KEY, }, params={"where": json.dumps({"PhoneNumber": "0501234567"}), "limit": 5},)# 0 תוצאות → ליצור · 1 → לעדכן · יותר מאחת → כפילות קיימת, דורשת החלטה אנושית<?php// find-before-create ב-REST — בדיקה לפני יצירה. צד שרת בלבד.$query = http_build_query([ "where" => json_encode(["PhoneNumber" => "0501234567"]), "limit" => 5,]);$ch = curl_init();curl_setopt_array($ch, [ CURLOPT_URL => "https://api.mbapps.co.il/parse/classes/Accounts?{$query}", CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "X-Parse-Application-Id: {$APP_ID}", "X-Parse-Master-Key: {$MASTER_KEY}", ],]);$response = curl_exec($ch);curl_close($ch);// 0 תוצאות → ליצור · 1 → לעדכן · יותר מאחת → כפילות קיימת, דורשת החלטה אנושיתשתי רשומות Accounts עם אותו טלפון ואותו אימייל נוצרו בבדיקה זו אחר זו, שתיהן ב‑201 — אין שום אילוץ שמונע זאת.
מה להגיד ללקוח
Section titled “מה להגיד ללקוח”שלוש משפטים שחוסכים שיחה שלמה אחרי העלייה לאוויר:
- “אותו אדם שממלא פעמיים ייצור שתי רשומות.” ב‑
getlead— שני לידים, השני מסומן ככפול. ב‑web2table— איש קשר אחד ושתי רשומות עסקיות. - “המערכת מסמנת, אתם מחליטים.” מיזוג לידים כפולים הוא תהליך עסקי — אפשר לבנות אותו כטריגר או כתצוגת עבודה על סטטוס “ליד כפול”, אבל הוא לא קורה מעצמו.
- “פרטים של לקוח חוזר לא מתעדכנים מהטופס.” אם זה נדרש — זה פיתוח נפרד, לא הגדרה.
- getlead · web2table
- אבחון תקלות — “איש קשר הוכפל” ו“איש קשר קיים לא התעדכן”
- מיפוי שדות — איך שולפים את
LeadStatusesובונים מפה