סקילים — נתונים ואינטגרציות
שלושה סקילים למה שנכנס ומה שיוצא: נתונים שנטענים פנימה, טפסים שמזרימים רשומות מהאתר, ודוחות שמוציאים תשובות החוצה.
| הסקיל | הכיוון |
|---|---|
myb-p-data-import |
קובץ ← CRM |
myb-p-web2lead-web2table |
אתר ← 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 בכל פעם.
יצירה דו‑שלבית (לידים + מכירות):
- יצירת כל רשומות ה‑
Accountsב‑Create-Many← מקבלים objectIds - מיפוי כל objectId לנתוני המכירה המתאימה ←
Create-ManyעלSales
התשובה של Create-Many מחזירה objectIds באותו סדר של מערך הקלט — מיפוי לפי מיקום.
טריגרים בזמן ייבוא
Section titled “טריגרים בזמן ייבוא”חמש המלכודות שחוזרות
Section titled “חמש המלכודות שחוזרות”$inנקטע בשקט. בחיפוש עם$in, ערך אחד שמחזיר הרבה תוצאות “בולע” את המכסה ומפיל בשקט ערכים אחרים. תמיד לוודא שמספר הרשומות שנמצאו תואם לציפייה.- נרמול טלפונים. מספרים ישראליים מגיעים בעשרות פורמטים. תמיד לרדת לגרעין של 9 ספרות.
- חיפוש לפי שם משפחה — “כהן” יתאים להמון לקוחות לא קשורים.
- מגבלה ידועה —
Get-all-Usersמחזיר רק 100 משתמשים ראשונים. משתמש שלא שם — לא לעקוף את שכבת ההרשאות; לסמן את השורות כחסומות ולהסלים. Get-Dataמחזיר 5 שורות כברירת מחדל. תשובה קטומה נראית כמו טבלה קטנה. תמידlimitמפורש.
דוח אימות הסבה
Section titled “דוח אימות הסבה”למה זה קיים: נתונים מוסבים שהמשתמשים לא סומכים עליהם הם רוצח האימוץ מספר אחת — נציג שנתקל בכפילויות או בלקוחות חסרים בשבוע הראשון חוזר בשקט לגיליון שלו. הדוח הופך את הספירות שממילא מריצים למסמך אמון חתום, כדי שהספקות יעלו וימותו לפני עלייה לאוויר ולא אחריה.
חמישה חלקים: טבלת ספירות (שורות במקור ← יובאו ← דולגו, עם סיווג סיבה ← אימות חי ב‑Count-Data) · סיכום מיפוי בשפה עסקית · רשימת חריגים עם הכרעה לכל קבוצה · פרוטוקול דגימה שבו הלקוח בוחר 5–10 רשומות שהוא מכיר ומשווים אותן יחד מול המקור · בלוק חתימה עם “הנתונים נבדקו ואושרו להפעלה”.
נכשלה דגימה? מתקנים ← מאמתים מחדש ← מריצים את הדגימה שוב על הפריטים שנכשלו. לעולם לא אוספים חתימה על נתונים שידוע שהם שגויים “כדי לעמוד בלוח הזמנים” — לוח הזמנים שנחסך עולה באימוץ.
נתוני דמה — שיחות MyChat / WhatsApp
Section titled “נתוני דמה — שיחות MyChat / WhatsApp”לייצור שיחות 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-web2lead-web2table
Section titled “myb-p-web2lead-web2table”מייצר קוד production-ready ב‑JavaScript/jQuery, PHP, Python, C# או Node.js שמגיש טופס HTML חיצוני לאחת משתי פונקציות הענן.
| נקודת הקצה | מה נוצר | מתי |
|---|---|---|
getlead |
שורה ב‑Accounts בלבד, עם IsAccount: false (התשובה: {result: {success, leadId}}) |
הטופס לוכד איש קשר בלבד — ראו הערת השם למטה |
web2table |
שורה בכל טבלת יעד וגם Accounts אם איש הקשר חדש (התשובה: {success, accountId, Id}) |
הטופס יוצר רשומה מקושרת (מכירה, פנייה, הרשמה) |
web2case |
פנייה + Accounts (דגל AcceptWebToCaseLeads) |
קיים כנקודת קצה נפרדת |
web2sale ו‑web2contact אינם נקודות קצה (400 User function not found) — משתמשים ב‑web2table עם table: "Sales". web2case כן קיים.
הזרימה שאסור לדלג עליה
Section titled “הזרימה שאסור לדלג עליה”זה הכלל היחיד והחשוב ביותר של הסקיל: אי אפשר לייצר קוד נכון מהזיכרון. סכימת Accounts וסכימת טבלת היעד שונות בין לקוח ללקוח — שדות מותאמים, תוויות ששונו, שדות שהוסרו — ושדות Pointer דורשים objectIds חיים. המחיר של ניחוש הוא כישלון שקט: ה‑API מחזיר 200, והרשומה נוחתת בצורה שגויה.
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 | מערך JSON | למשל מערך objectIds לשדה array_*_Pointer_* |
| File / PrivateFile | לא נתמך בזרימה הזו | הבקשה נכשלת ב‑400; להתריע למשתמש |
דגל ה‑Config — ולמה MCP לא יכול לגעת בו
Section titled “דגל ה‑Config — ולמה MCP לא יכול לגעת בו”לכל נקודת קצה יש שורה משלה בטבלת 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 מטופס”לכל שדה 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 - סקילים — אוטומציה — הטריגרים שהייבוא מעיר
- עבודה בטוחה עם סוכן על מערכת חיה