סקילים — נתונים ואינטגרציות
שלושה סקילים למה שנכנס ומה שיוצא.
| הסקיל | הכיוון |
|---|---|
myb-p-data-import |
קובץ ← CRM |
myb-p-public-forms |
אתר / דף ציבורי ← CRM |
myb-p-create-update-reports |
CRM ← שאלה |
myb-p-data-import
Section titled “myb-p-data-import”טעינה המונית מאקסל/CSV וייצור נתוני דמה: זיהוי לקוחות קיימים (מייל, טלפון, שם או objectId), מיפוי כותרות בעברית לשדות, פתרון ערכי lookup, הסרת כפילויות ויצירה מרוכזת.
1. קריאת הקובץ → גיליונות, כותרות, מספר שורות2. סיווג העמודות → מזהה / שדה CRM / מטא-דאטה3. פתרון lookups → objectIds למשתמשים, סטטוסים, מקורות4. התאמת רשומות → מציאת או יצירת Accounts5. הסרת כפילויות → מהמקור, לפני הכתיבה6. יצירה → Create-Many7. דיווח → נוצרו / דולגו / נכשלומיפוי כותרות בעברית
Section titled “מיפוי כותרות בעברית”הטבלה היא דוגמת מיפוי מלקוח ספציפי; שמות השדות אינם שמות מערכת. במערכת חדשה (vanilla) קיימים Accounts.LeadSourceId (← LeadSource), Accounts.LeadOwnerId, Sales.Source (String) ו‑Sales.SaleStatusId, ואילו SaleSource/SaleSourceList, C_LeadSource/C_LeadSourceList ו‑NewCoordinator אינם קיימים בה (כפי שרואים ב‑Get-Schema). בנו מיפוי מול הסכימה החיה.
| הכותרת בקובץ | הטבלה | השדה | התפקיד |
|---|---|---|---|
| מייל / אימייל | Accounts |
Email |
מזהה (חיפוש) |
| טלפון / מספר טלפון | Accounts |
PhoneNumber |
מזהה (חיפוש) |
AccountId.objectId |
Accounts |
objectId |
מזהה ישיר |
| שם | Accounts |
Name, F_name, L_name |
שדה ישיר |
| כותרת | Sales |
Name |
שדה ישיר |
| סטטוס / סטטוס מכירה | Sales |
SaleStatusId |
lookup ← SaleStatuses |
| מקור המכירה | Sales |
SaleSource |
lookup ← SaleSourceList |
| מקור הליד | Accounts |
C_LeadSource |
lookup ← C_LeadSourceList |
| אחראי מכירה / יועץ | Sales |
OwnerId |
lookup ← _User |
| מתאם | Accounts |
LeadOwnerId, NewCoordinator |
lookup ← _User |
| תאריך התקשרות הבא | Sales |
NextStepDate |
המרת תאריך |
בחירת אסטרטגיית זיהוי
Section titled “בחירת אסטרטגיית זיהוי”| המזהה בקובץ | האסטרטגיה | האמינות |
|---|---|---|
AccountId / objectId |
חיפוש ישיר עם $in |
מושלמת |
| מייל | חיפוש ב‑Accounts.Email |
גבוהה |
| טלפון | נרמול ← חיפוש regex | בינונית-גבוהה |
| שם | מוצא אחרון — חיפוש לפי L_name |
נמוכה — הרבה התאמות שווא |
| אין | יצירת Accounts חדש |
— |
ליד חדש נוצר כרשומת Accounts עם IsAccount: false ושדות ליד (LeadStatusId, C_LeadSource, LeadOwnerId, NewCoordinator).
יצירה — הפורמטים
Section titled “יצירה — הפורמטים”// Pointer{ "__type": "Pointer", "className": "SaleStatuses", "objectId": "abc1234567" }
// Date{ "__type": "Date", "iso": "2026-01-01T00:00:00.000Z" }גודל אצווה: עד ~50 רשומות בקריאה אחת; לסטים גדולים פיצול ל‑46–50.
יצירה דו‑שלבית (לידים + מכירות): Create-Many על Accounts ← objectIds ← מיפוי כל objectId לנתוני המכירה ← Create-Many על Sales. התשובה של Create-Many מחזירה objectIds באותו סדר של מערך הקלט; מיפוי לפי מיקום.
טריגרים בזמן ייבוא
Section titled “טריגרים בזמן ייבוא”חמש המלכודות שחוזרות
Section titled “חמש המלכודות שחוזרות”$inנקטע בשקט. ערך אחד שמחזיר הרבה תוצאות “בולע” את המכסה ומפיל בשקט ערכים אחרים. ודאו שמספר הרשומות שנמצאו תואם לציפייה.- נרמול טלפונים. מספרים ישראליים מגיעים בעשרות פורמטים; רדו לגרעין של 9 ספרות.
- חיפוש לפי שם משפחה — “כהן” יתאים להמון לקוחות לא קשורים.
- מגבלה ידועה —
Get-all-Usersמחזיר רק 100 משתמשים ראשונים. משתמש שאינו שם: אל תעקפו את שכבת ההרשאות; סמנו את השורות כחסומות והסלימו. Get-Dataמחזיר 5 שורות כברירת מחדל. תמידlimitמפורש.
דוח אימות הסבה
Section titled “דוח אימות הסבה”הדוח הופך את הספירות שממילא מריצים למסמך אמון חתום, בחמישה חלקים: טבלת ספירות (שורות במקור ← יובאו ← דולגו, עם סיווג סיבה ← אימות חי ב‑Count-Data) · סיכום מיפוי בשפה עסקית · רשימת חריגים עם הכרעה לכל קבוצה · פרוטוקול דגימה שבו הלקוח בוחר 5–10 רשומות שהוא מכיר ומשווים אותן יחד מול המקור · בלוק חתימה עם “הנתונים נבדקו ואושרו להפעלה”.
נכשלה דגימה? מתקנים ← מאמתים מחדש ← מריצים את הדגימה שוב על הפריטים שנכשלו. לעולם לא אוספים חתימה על נתונים שידוע שהם שגויים.
נתוני דמה — שיחות MyChat / WhatsApp
Section titled “נתוני דמה — שיחות MyChat / WhatsApp”מדריך עצמאי בסקיל: references/mychat-conversations.md. העיקר:
שלוש שכבות, מלמטה למעלה: Channels (מספר עסקי) ← Conversations (שרשור לכל טלפון לקוח) ← ConversationMessages (Create-Many). שדה סוג הערוץ הוא TypeId, לא ChannelTypeId.
כללי הודעה: Direction הוא מילולית "Incomeing"/"Outgoing" — שומרים על שגיאת הכתיב. Identity הוא טלפון הלקוח בפורמט בינלאומי בלי +. Message (עם escaping ל‑HTML) חייב להתאים ל‑Data.text.body. כל Data.id (wamid) ייחודי. חלון 24 השעות נאכף: טקסט חופשי יוצא יותר מ‑24 שעות אחרי ההודעה הנכנסת האחרונה חייב להיות template, אחרת failed עם קוד 131047.
מגבלות תצוגה נוספות: תיבת MyChat מציגה רק שיחות על ערוץ מחובר אמיתי, וערוץ סינתטי לא יופיע שם; חשפו את ההיסטוריה על כרטיס הלקוח דרך ווידג’ט Conversations מסונן לפי AccountId. createdAt לא ניתן לתיארוך לאחור; הכרונולוגיה נבנית מ‑Data.timestamp/sentAt/LastMessageAt.
myb-p-public-forms
Section titled “myb-p-public-forms”כל טופס שגולש בלי התחברות שולח למערכת, ובחירת המנגנון הנכון. הסקיל נפתח במדריך החלטה ומחזיק תיקייה לכל שיטה. החליף ב‑1.5.0 את myb-p-web2lead-web2table ואת myb-p-csat-survey.
| התיקייה | המנגנון | מתי |
|---|---|---|
native-form/ | Database form נייטיבי בדף ציבורי של אתר ה‑CRM, מול טבלת קליטה שפתוחה ליצירה בלבד; reCAPTCHA של הפלטפורמה | טופס שאתם מארחים: סקר, משוב, רישום, בקשה — בלי טלפון חובה ובלי קוד שמירה |
capture-data/ | אותו טופס במצב data-use-caputure-data → הפונקציה simbla-capture-data | הטבלה חייבת להישאר סגורה, או שצריך זיהוי כפילויות, שדות חובה וברירות מחדל בשרת — משורת Config אחת |
web2/ | קוד ל‑getlead / web2table ב‑JavaScript, PHP, Python, C# ו‑Node.js, מול הסכימה האמיתית | טופס שיושב מחוץ ל‑CRM — אתר הלקוח, וורדפרס, Wix, מערכת אחרת |
csat/ | סקר שביעות רצון בסגירת פנייה: לחיצה אחת מהמייל, השלכה על הפנייה, משימה על דירוג שלילי, דוחות | וריאנט נייטיבי בלי נתון אישי בקישור, או וריאנט web2table. המתכון המלא |
כלל האצבע: אנחנו מארחים את הטופס ← טופס נייטיבי. מישהו אחר מארח ← web2. הטבלה חייבת להישאר סגורה או צריך זיהוי כפילויות ← capture-data. כל המנגנונים נבדקו מקצה לקצה על מערכת חיה (10.2026), כולל בדיקות שליליות: קריאה אנונימית בלי טוקן נדחית, עדכון אנונימי נדחה כל עוד ה‑CLP סגור.
טריגרים: “טופס פומבי”, “סקר”, “משוב אחרי אירוע”, “טופס רישום בלי התחברות”, “חיבור טופס לאתר”, “דף נחיתה”, “סקר שביעות רצון”, “CSAT”. הסעיפים הבאים מפרטים את מסלול web2 — ההבדלים מול שני המסלולים האחרים בעמודי הטפסים.
הזרימה שאסור לדלג עליה
Section titled “הזרימה שאסור לדלג עליה”אי אפשר לייצר קוד נכון מהזיכרון. סכימת Accounts וסכימת טבלת היעד שונות בין לקוח ללקוח (שדות מותאמים, תוויות ששונו, שדות שהוסרו), ושדות Pointer דורשים objectIds חיים. המחיר של ניחוש הוא כישלון שקט: 200 מה‑API, ורשומה שנוחתת שגוי.
1. Get-Schema על Accounts → שמות וטיפוסים זמינים2. Get-Schema על טבלת היעד (web2table) → אותו דבר3. Get-Data על כל targetClass של Pointer מבוקש → מפת ערך→objectId4. Get-Data על LeadStatuses (סטטוס מותאם) → אימות ה-objectId5. אימות כל שדה שהמשתמש ביקש מול הסכימה → שדה שלא קיים — מסמנים, לא משמיטים בשקט6. רק עכשיו — ייצור קודחמש שאלות לפני הקוד
Section titled “חמש שאלות לפני הקוד”- איזו שפה / framework?
- איפה הקוד רץ — דף נחיתה ב‑WordPress/Wix/Elementor (דפדפן), או נקודת קצה בשרת (Express, Flask, Laravel, ASP.NET) שהטופס מגיש אליה קודם?
- מה קורה בהצלחה? — הפניה לדף תודה? אישור בתוך הדף? אירוע GTM? איפוס הטופס?
- יש captcha או שדות אנטי‑בוט? — reCAPTCHA, Turnstile, honeypot. הטוקנים שלהם מאומתים לפני ההעברה הלאה.
- הטופס בדומיין אחר מ‑
api.mbapps.co.il? — כמעט תמיד. Parse Cloud Functions מאפשרות CORS לנקודות הקצה האלה כברירת מחדל.
טיפוסים — שכבת הטפסים אינה Parse REST
Section titled “טיפוסים — שכבת הטפסים אינה Parse REST”| טיפוס בסכימה | מה שולחים | הערה |
|---|---|---|
| String | מחרוזת | כמו שהוא |
| Number | מספר או מספר כמחרוזת | ה‑API ממיר |
| Boolean | בוליאני אמיתי true/false |
גם "true"/"false" עובדות ברוב השדות — אבל account_IsAccount מקבל רק בוליאני אמיתי (מחרוזת → 400). המספר 1 → 400 |
| Date | מחרוזת ISO מרופדת (2026-06-01) או ISO מלא |
גם {__type:"Date"} נקלט; מה שנדחה הוא תאריך לא מרופד (2026-6-1 → 400) |
| Pointer | מחרוזת ה‑objectId בת 10 התווים | בשדות table_* אובייקט {__type:"Pointer"} או מזהה באורך שגוי נזרקים בשקט (200, שדה ריק); בשדות account_* האובייקט נקלט ואורך שגוי → 400 |
| Array | מערך של אובייקטי Pointer | מערך של אובייקטי Pointer — {"__type":"Pointer","className":…,"objectId":…} — הפורמט שה‑CRM עצמו שומר בשדה array_*_Pointer_*. מערך של מזהים חשופים נשמר גם הוא, אבל בכרטיס יוצגו צ’יפים ריקים וקריטריון containedIn בטריגר לא יתאים לו (נבדק ב‑web2table, 10.2026) |
| File | ב‑web2table: אובייקט File של קובץ שהועלה קודם | מעלים קודם את הקובץ — POST /parse/files/<name> (כותרת App ID בלבד, הגוף הוא הקובץ) — ושולחים את אובייקט ה‑File שחזר: {"__type":"File","name":…,"url":…} → 200 ושורה אחת עם הקובץ (נבדק 10.2026). אובייקט File של קובץ שלא הועלה מחזיר 400 {"code":1} אחרי כ‑5 שניות ומשאיר בצד השרת איש קשר ו‑5 שורות יעד כפולות; מחרוזת URL מחזירה 400 (code 111), אבל איש הקשר כבר נוצר. |
דגל ה‑Config
Section titled “דגל ה‑Config”לכל נקודת קצה שורה משלה בטבלת Config: AcceptWebLeads ל‑getlead, AcceptWebToTable ל‑web2table, AcceptWebToCaseLeads ל‑web2case. שורה חסרה או false ← 400 עם "AcceptWebToTable is Disabled" (לא 403), לפני שהבקשה מגיעה לזיהוי כפילויות.
| השדה | הערך |
|---|---|
Name |
"AcceptWebToTable" (String) |
Value |
{ "AcceptWebToTable": true } (Object — המפתח חוזר בתוך האובייקט) |
הפונקציה קוראת את המפתח הפנימי; ה‑Name החיצוני הוא מפתח החיפוש. בוליאני חשוף true לא יעבוד.
שורות כפולות לאותו דגל גורמות ל‑400 בלתי צפוי: הקוד לוקח query.first(), ובפועל השורה שנוצרה ראשונה מנצחת תמיד. שמרו שורה אחת לכל דגל. פירוט: דגלי Config.
מיפוי Pointer מטופס
Section titled “מיפוי Pointer מטופס”- מהסכימה — ה‑
targetClassשל ה‑Pointer (למשלLeadSourceעבורLeadSourceId). Get-Data(table: "<targetClass>", keys: ["Name"], limit: 200)— שליפת האפשרויות.- ייצור מפה סטטית
name → objectIdבקוד, עם הערה איך להרחיב. - ה‑
<select>מגיש את ה‑Name, והקוד מתרגם לפני השליחה.
טבלת lookup גדולה או משתנה תדיר? שליפה בזמן ההגשה (קריאת REST נוספת אחת). ברירת המחדל היא מפה סטטית.
myb-p-create-update-reports
Section titled “myb-p-create-update-reports”שני סוגי תצוגות, שניהם ב‑_DynamicQueries ושניהם ב‑Create-or-Update-Report:
| דוחות | שאילתות | |
|---|---|---|
| איפה | apps/mybusiness/reports |
דף ישות (apps/mybusiness/sales) |
| מה זה | תצוגה אנליטית עצמאית | פילטר שמור בתפריט הנפתח של אותו דף |
| מזוהה לפי | PageName/PageId |
+ FormName בפורמט dynamic-table-formP<number> |
חמישה סוגי דוחות
Section titled “חמישה סוגי דוחות”| הסוג | המאפיין | מתי |
|---|---|---|
| רגיל | IsAggr: false |
רשימת רשומות עם פילטרים, ייצוא |
| מצטבר | IsAggr: true |
“כמה” ו“סך הכל” — לפי חודש, לפי אחראי |
| פיבוט | IsAggr: true + PivotInfo |
פילוח דו‑ממדי (אחראי × חודש) |
| עם שדות מחושבים | עמודות נגזרות | מרווח רווח, אחוזים |
| דוח מורכב | רק SubqueriesInfo |
כמה תת‑דוחות בתצוגה אחת |
שלישיית השדות — קריטית לדוחות מצטברים
Section titled “שלישיית השדות — קריטית לדוחות מצטברים”שלושה ערכים חייבים להתיישר לכל עמודה. אחד שגוי — והדוח נכשל בשקט או זורק Group object must contain values:
| התכונה | הפורמט | דוגמה ל‑AccountId.Name |
|---|---|---|
ShowFields[i] |
נקודות, בלי שם הטבלה | "AccountId.Name" |
OptionalFields[i].field |
זהה ל‑ShowFields[i] |
"AccountId.Name" |
OptionalFields[i].aggrField |
מסלול מלא עם שם הטבלה | "AccountId.Accounts.Name" |
הטעות החוזרת: field: "AccountId" (אובייקט ה‑Pointer) במקום field: "AccountId.Name" (המחרוזת המוצגת). בשדות _User שימו לב ל‑name באות קטנה: ShowFields: "OwnerId.name" · aggrField: "OwnerId._User.name".
תמיד Get-Optional-Fields(className) קודם, ומעתיקים משם את הערכים המדויקים.
פריסת הפילטרים
Section titled “פריסת הפילטרים”GridDivider תמיד 3 (=4 בשורה) או 4 (=3 בשורה); 6 ו‑12 יוצרים פילטרים מתוחים על כל רוחב העמוד. גם בדוח עם שני פילטרים, תאים ריקים בסדר.
סדר הפילטרים (מימין לשמאל, מלמעלה למטה): חיפוש טקסט ← בחירה מרובה של Pointer (סטטוס, סוג, אחראי) ← זוגות טווח תאריכים ← צ’קבוקסים בוליאניים תמיד אחרונים (נרנדרים בפינה השמאלית‑תחתונה).
פתרון תקלות
Section titled “פתרון תקלות”Group object must contain values — קיבוץ לפי שדה שהוא NULL בחלק מהרשומות; צינור האגרגציה לא יכול לייצר מפתח קיבוץ מערך חסר. התיקון: פילטר exists על שדה הקיבוץ, כברירת מחדל:
{ "QueryElems": [ { "F": "Industry", "C": "exists", "T": "String", "FText": "תעשייה קיימת" }]}לשדה Pointer: {"F": "OwnerId", "C": "exists", "T": "Pointer", "P": {"targetClass": "_User"}}. המשתמש יכול לבטל את הפילטר מהממשק כדי לראות גם רשומות בלי הערך.
תוצאות מצטברות ריקות — לפי הסדר: (1) field תואם ל‑ShowFields? (2) aggrField כולל את שם המחלקה? (3) יש רשומות שתואמות לערכי ברירת המחדל של ה‑QueryElems?
דוח מתוזמן
Section titled “דוח מתוזמן”שאר הכללים
Section titled “שאר הכללים”- הרשאות נדרשות ביצירה —
role:<RoleName>לתפקידים, objectId למשתמש ספציפי. editPermissionsנדרש כשעובדים עם master key — objectId של משתמש תקף.FormNameנדרש לשאילתה על דף ישות — לוקחים אותו משאילתה קיימת באותו דף.- מיון יורד עם מינוס:
-createdAt. QueryElemsמסוג Pointer דורשים אובייקטPעםtargetClass(ו‑multiple: trueל‑containedIn).- טווחי תאריכים בזוגות:
greaterThanOrEqualTo+lessThanOrEqualTo.
- getlead · web2table · דגלי Config · מיפוי שדות
- כלי נתונים ב‑MCP —
Get-Data,Create-Many,Aggregate-Data - סקילים — אוטומציה — הטריגרים שהייבוא מעיר
- עבודה בטוחה עם סוכן על מערכת חיה