דלגו לתוכן

או התחילו מנקודה בטוחה: אינדקס הכלים המלא · מפת הטבלאות המרכזיות

מערכת חדשה — 14 יום חינם

סקילים — אוטומציה

עודכן 30.08.2026

שלושה סקילים למה שקורה מעצמו. שניים מהם דומים למראית עין ושונים לחלוטין במהות: טריגר רץ בשרת ואוכף; חוק טופס רץ בדפדפן ומעצב חוויה. ההבחנה הזו היא ההחלטה הראשונה בכל בקשת אוטומציה.

הסקיל איפה זה רץ האם זה אוכף
myb-p-trigger-setup שרת כן — גם על כתיבות API
myb-p-form-rules דפדפן, בטופס לא — כתיבת API עוקפת לגמרי
myb-p-sla-configuration שרת (טריגרים) + הגדרות כן — אבל רק אחרי שבנו את הטריגרים

טריגר מפוצל לשני חלקים, ולכן לשני כלים:

TRIGGER (מתי) ACTIONS (מה) — אחת או יותר
├── type: data change / scheduled ├── email
├── events: create / update ├── sms
├── criterias: תנאים ├── whatsapp-message
├── onSetFields: שדות מנוטרים ├── create-object
└── oneachupdate: חוזר? ├── update-object
├── notification
├── http (webhook)
├── server-side-code
└── ai-webhook

תמיד בסדר הזה: Set-Trigger יוצר את הראש ומחזיר את המזהה; Set-Trigger-Action נקרא פעם אחת לכל פעולה ותולה אותה עליו.

איך נראה המזהה בתשובה: לטריגר data change התשובה היא סכימת הטבלה כולה, והמזהה יושב ב‑triggers[].._id (10 תווים — מחפשים לפי name); לטריגר scheduled התשובה היא {"value":"<24-hex>"}.

הפרמטר טיפוס חובה המשמעות
tableName String הטבלה שעליה הטריגר יושב
type Enum data change · scheduled
active Boolean חובה גם ביצירה
name String שם תיאורי. בעברית — מומלץ
_id String קיים ⇒ עדכון; נעדר ⇒ יצירה
events Array ל‑data change ["create"] · ["update"] · שניהם
onSetFields Array<String> ל‑data change הטריגר נבחן רק אם אחד מהשדות האלה השתנה
criterias Array תנאי סינון במבנה F/C/T/V/P
oneachupdate Boolean false (ברירת מחדל) = פעם אחת לרשומה · true = בכל עדכון תואם
schedulerField String ל‑scheduled שדה תאריך שממנו נגזר התזמון
shcedulerHours Number ל‑scheduled כמה שעות לפני ערך התאריך. שלילי = אחרי

בעדכון — שולחים רק את מה שמשתנה, בשני הסוגים (ב‑scheduled, שינוי שם בלבד שומר את כל שאר ההגדרות).

זה הפרמטר שמונע לולאות. טריגר על Sales שכותב חזרה ל‑Sales יפעיל את עצמו — אלא אם השדה שהוא כותב אינו ברשימת השדות שהוא מאזין להם. שני שמות שדה שונים = אין לולאה.

הוא גם שיקול ביצועים: בלי onSetFields, כל עדכון בטבלה נבחן מול כל התנאים. מערך ריק [] עובד — אבל פירושו “כל שינוי בשדה כלשהו”, וזו לא הגדרה שרוצים על טבלה עמוסה.

באירוע create, בוחרים שדה שתמיד נקבע ביצירה.

JSON
{
"F": "SaleStatusId",
"FText": "סטטוס מכירה",
"C": "equalTo",
"T": "Pointer",
"V": "zrP1MSVBoq",
"P": { "targetClass": "SaleStatuses", "visibleVal": "הושלמה", "multiple": false },
"condOr": false
}

האופרטורים בסכימה: contains · startsWith · equalTo · greaterThan · lessThan · greaterThanOrEqualTo · lessThanOrEqualTo · notEqualTo · containedIn · notContainedIn.

AND ו‑OR חיים יחד: תנאים בלי condOr הם AND: כולם חייבים להתקיים. תנאים עם condOr: true מרכיבים קבוצת OR, ומספיק שאחד מהם יתקיים. condOr על תנאי בודד לא עושה כלום.

הפעולות — מה כל אחת דורשת

Section titled “הפעולות — מה כל אחת דורשת”
actionType שדות החובה ב‑actionData
email template · emailAccount · emailType (fixed/field) · emailTarget · emailSubject · saveToEmailsTable
sms from · local · content · toType · to
whatsapp-message toType · to · message · from · template · WATemplateParams
notification userType · user · content (+ icon, iconColor אופציונליים)
create-object targetClass · fieldsValue[]
update-object targetClass · connection · fieldsValue[]
http url · method (GET/POST/PUT/DELETE/AUTO)
server-side-code functionName
ai-webhook webhookId · webhookName (בבלוק actionData.aiWebhook; השם התחלף בין גרסאות שרת ובחלקן הוא trigger-ai-webhook. מוודאים ב‑tools/list)

AUTO ב‑http בוחר את השיטה לפי סוג האירוע: POST ליצירה, PUT לעדכון.

connection — הכיוון של העדכון

Section titled “connection — הכיוון של העדכון”

זה הפרמטר שהכי מבלבל ב‑update-object. הערך הוא DIRECTION.FIELD_NAME:

הכיוון המשמעות
target.<Field> הרשומה המעודכנת מצביעה לרשומה שהפעילה. למשל target.SaleId כשהטריגר על Sales והשדה SaleId בטבלה המעודכנת מצביע למכירה
source.<Field> הרשומה שהפעילה מצביעה לרשומה המעודכנת. למשל source.AccountId — לעדכן את הלקוח המקושר

timeGap — חשבון תאריכים בלי קוד

Section titled “timeGap — חשבון תאריכים בלי קוד”

בתוך fieldsValue, הפרמטר timeGap מוסיף דקות לערך תאריך דינמי. שלילי מותר.

JSON
{ "field": "DueDate", "type": "dynamic", "value": "updatedAt", "timeGap": 1440 }
// יום אחרי רגע העדכון

{{{FieldName}}}שלוש סוגריים — עובד בנושא ובגוף המייל, בתוכן ה‑SMS, בתוכן ההתראה, ובכתובת ה‑URL של ה‑webhook:

  • {{{Name}}} — שדה מהרשומה שהפעילה
  • {{{AccountId.Name}}} — מעבר דרך Pointer
  • {{{SaleDate.format(date,he-IL,Asia/Jerusalem)}}} — סוג (date/timehm/datetime), locale, אזור זמן

emailTarget תומך גם הוא במעבר Pointer: "OwnerId.email" שולח לאחראי.

התבנית הטריגר הפעולה
התראה על שינוי סטטוס events: ["update"], onSetFields: ["StatusId"], קריטריון לסטטוס notification / email / sms
מייל ברוכים הבאים events: ["create"] email
משימת מעקב אוטומטית events: ["update"] + קריטריון לסטטוס סגירה create-object עם timeGap: 1440
סנכרון שדות בין טבלאות events: ["update"], onSetFields: ["<field>"] update-object עם connection
תזכורת מתוזמנת type: "scheduled", shcedulerHours: 24 sms / notification
webhook למערכת חיצונית events: ["create", "update"] http POST
  • מחיקת טריגר. MCP יכול רק לכבות (active: false). מחיקה אמיתית — Admin ← Databases ← Tables ← [הטבלה] ← Triggers, ידנית.
  • טריגר מסוג “הוספה לציר זמן” — קיים בממשק בלבד.
  • עריכת תבניות מייל — נוצרות בממשק; הטריגר רק מפנה ל‑objectId קיים.
  • יצירת חשבונות SMTPGet-SMTP-Accounts מציג את הקיימים; יצירה בממשק.
  • יצירת תבניות WhatsApp — נדרש אישור מוקדם של Meta. Send-WhatsApp-Message עם getTemplates: true מציג את המאושרות.
  • מחיקת פעולה דורשת actionData — גם עם deleteAction: true חייבים להעביר אובייקט actionData תקף לסוג הפעולה. בלעדיו: Cannot read properties of undefined. שולחים מינימום שתקף סכימתית.
  • טריגרים מתוזמנים מחזירים מזהה בפורמט אחר{"value":"69df53414167a73a568f34df"}", כלומר ObjectId של MongoDB, ולא _id בסגנון Parse. משתמשים בשדה value בתור ה‑triggerId.
  • Get-WhatsApp-Template-Params תלוי בבלוק ה‑example של מטא — הכלי לא סופר את ה‑{{N}} בגוף התבנית, אלא ממיר את בלוק ה‑example שמגיע ממטא. יש example, כל הפרמטרים חוזרים נכון, גם כשיש כמה; אין example, מוחזר אובייקט ריק לגמרי, גם לתבנית עם פרמטר יחיד. קיבלתם {} — בונים את WATemplateParams.BODY ידנית, עם ערך לכל {{N}} לפי הסדר.
  • מגבלה ידועה — שרשרת טריגרים מוגבלת ל‑3 רמות. שלושה טריגרים שלובים רצים; הרביעי נחסם ונרשם ב‑_syslogTriggers עם blocked! trigger step is to deep -3. source trigger: <id>. הסכימה מזהירה מזה במפורש.
  • useQueue קיים ב‑http, ב‑sms וב‑server-side-code. לטריגר שעלול לרוץ פעמים רבות בו‑זמנית — הפעילו אותו.

טריגרים כן יורים מכתיבות API ו‑Master KeyCreate-Data, Update-Data ו‑Create-Many כולם מפעילים אירועי create/update. כלומר בדיקה דרך MCP היא בדיקה תקפה, וממשק ו‑API מתנהגים אותו דבר.

לא ירה? יומן הטריגרים:

JSON
Get-Data({ "table": "_syslogTriggers", "order": "-createdAt", "limit": 5,
"keys": ["triggerId", "actionId", "objectIdValue", "error", "event", "createdAt"] })

שורה לכל פעולה (ועוד שורה לטריגר עצמו, עם actionId: null). השדות הקיימים: triggerId, actionId, objectIdValue, error, data, event — אין triggerName; את השם מצליבים מ‑Get-Triggers.

הסיבות החוזרות, לפי סדר: onSetFields לא כולל את השדה שהשתנה · criterias לא תואמים (objectId שגוי, T שגוי) · הטריגר כבוי · oneachupdate: false והוא כבר ירה על הרשומה הזו · עומק שרשרת חורג מ‑3 · הרשומה נכתבה עם skipTriggers: true.


חוקי טופס שולטים בהתנהגות השדות על דף כרטיס: הסתרה מותנית, חובה מותנית, נעילה, ערכים קבועים ודינמיים, נוסחאות, הודעות אזהרה, ומילוי מראש מ‑URL.

הכלי מה הוא עושה
Get-Form-Rules קורא את מערך הכללים הנוכחי של הדף. תמיד ראשון
Edit-Form-Rules מוסיף / עורך / מוחק כלל אחד. זה הכותב
Set-Form-Rules דורס את כל הכללים בטופס. מוצא אחרון בלבד
JSON
{ "pageId": "<pageId>", "action": "add",
"rule": { "name": "<שם ייחודי>", "conditions": [...], "actions": [...] } }
{ "pageId": "<pageId>", "action": "edit",
"rule": { "name": "<שם קיים>", "conditions": [...], "actions": [...] } }
{ "pageId": "<pageId>", "action": "delete",
"rule": { "name": "<שם קיים>", "conditions": [], "actions": [] } }

edit מחליף לגמרי את התנאים והפעולות של הכלל הנקוב — זה לא מיזוג. delete צריך רק את השם.

JSON
{
"name": "סיבת ביטול חובה כשהסטטוס בוטל",
"conditions": [
{ "field": "StatusId", "equesition": "equalTo",
"value": "abc1234567", "visibleVal": "בוטל", "condOr": false }
],
"actions": [
{ "field": "CancelReason", "action": "required", "value": "" }
]
}

שימו לב לאיות: equesition — כך זה בסכימה, ואין ברירה אלא לכתוב כך.

האופרטורים בסכימה של Edit-Form-Rules: equalTo · greaterThan · lessThan · greaterThanOrEqualTo · lessThanOrEqualTo · notEqualTo · containedIn · notContainedIn — וגם שני ערכי ה‑legacy equealTo ו‑empty.

שמונה הפעולות בסכימה: readonly · required · hidden · fixed-value · dynamic-value · formula-value · show-message · value-from-url.

AND הוא ברירת המחדל. OR דורש condOr: true על שני תנאים לפחות — תנאי בודד מסומן לא עושה כלום. ו‑conditions: [] פירושו שהכלל רץ תמיד — זה הניב של שיקוף שדות, אבל fixed-value תמידי בטעות דורס קלט של המשתמש בכל טעינת טופס.

הבקשה סקיצת הכלל
“שדה חובה רק כשסטטוס = X” זוג כללים: hidden כשהסטטוס notEqualTo X, ו‑required כשהוא equalTo X
“תסתיר את השדות עד שנבחר סוג” פעולות hidden (אחת לכל שדה) כל עוד שדה הסוג notEqualTo הערך המשחרר
“תנעל את הכרטיס אחרי סגירה” קבוצת OR של סטטוסי סיום (condOr: true על 2+) ← readonly לכל שדה נעול
“העתק פרטים מהלקוח לטופס” conditions: [] + dynamic-value לכל שדה ("AccountId.Email" — קפיצת Pointer אחת)
“תאריך סיום אוטומטי בסגירה” סטטוס equalTo סגור ← fixed-value בערך "today"
“חובה רק עבור סוגים מסוימים” containedIn עם מערך של objectIds ← required
“הצג אזהרה במצב רגיש” תנאי על המצב ← show-message עם טקסט ההודעה
“אחראי ברירת מחדל = המשתמש” conditions: [] + fixed-value בערך "currentUser" על ה‑Pointer ל‑_User
“קישור שממלא שדות מראש” פעולת value-from-url
הבקשה לאן היא שייכת
פעולה בשמירה / מייל / יצירת רשומה / אכיפה בשרת myb-p-trigger-setup
הוספה/הזזה של שדות, סקשנים, טאבים myb-p-page-builder
מי רשאי לקרוא או לכתוב (CLP, תפקידים) myb-p-users-roles-permissions
עמודות בטבלה, סינון, צביעת שורות myb-p-page-tables
סינון אפשרויות בדרופ‑דאון לפי שדה אחר myb-p-parent-child-fields — לא פעולת כלל, מנגנון ילידי
0. Get-Site-Pages → איתור דף הכרטיס (יחיד = טופס, רבים = רשימה, Mobile-* = נייד)
1. Get-Form-Rules(pageId) → גיבוי + ספירת בסיס
Get-Schema(tableName) → שמות וטיפוסי שדות מדויקים
Get-Data(<lookup>) → objectIds לערכי תנאי מסוג Pointer
2. ניסוח הכלל
3. הצגת תוכנית ואישור — לפני הכתיבה הראשונה
4. Edit-Form-Rules — קריאה אחת לכל כלל
5. Get-Form-Rules — קריאה חוזרת + בדיקת התנהגות בדפדפן

formId מוגדר כברירת מחדל לטופס הראשון בדף. יש בדף יותר מטופס אחד? מעבירים formId במפורש — הערך הוא ה‑id של אלמנט ה‑<form> כפי שהוא מופיע ב‑Get-Page-Content(minimal: true) (למשל P268; formId שאינו קיים מחזיר Form not found).

Set-Form-Rules — אם באמת חייבים

Section titled “Set-Form-Rules — אם באמת חייבים”

זה כותב‑מצב‑מלא. כתיבה עיוורת מוחקת כל כלל שלא כללתם:

1. backup = Get-Form-Rules(pageId) // לשמור את ה-JSON המלא בצד
2. newRules = backup.rules ± השינויים // למזג, אף פעם לא לכתוב מהזיכרון
3. Set-Form-Rules(pageId, rules: newRules)
4. Get-Form-Rules(pageId) // לוודא ששום דבר לא אבד

אימות — קריאה חוזרת אינה מספיקה

Section titled “אימות — קריאה חוזרת אינה מספיקה”

Get-Form-Rules מוכיח אחסון, לא התנהגות. הכללים רצים בדפדפן בלבד, ואין יומן שרת של הערכת כללים. לכן צריך גם בדיקת התנהגות: לפתוח את הדף, רענון קשה (Ctrl+F5) — הגדרות הכללים נטענות עם הדף — ואז להפוך את שדה התנאי ולראות את הפעולה נכנסת ויוצאת.

הכלל לא ירה? בסדר הזה: דף שגוי (רגיל מול Mobile-*) · formId שגוי · לא היה רענון קשה · ערך התנאי הוא תווית תצוגה במקום objectId · condOr בודד · כלל אחר פועל על אותו שדה · ציפייה שהכלל יירה על כתיבת API.

  • צד לקוח בלבדrequired/readonly/hidden הם חוויה, לא שלמות נתונים.
  • שכפול לפי דף וטופס — נפרדים בשקט.
  • אין כללים מותנים לפי תפקיד — לתנאי יש רק field/equesition/value בסכימה. התנהגות לפי קהל דורשת הגדרות תפקיד ברמת הדף, או דפים נפרדים.
  • אין סדר עדיפויות בין כללים על אותו שדה — הפעולות מצטברות (hidden בכלל אחד ו‑required בכלל אחר על אותו שדה → השדה גם מוסתר וגם חובה, בשני הסדרים — והטופס לא ניתן לשליחה). תכננו תנאים בלעדיים הדדית.
  • formula-value הוא קופסה שחורה — התחביר לא מתועד בסכימה. המהלך הבטוח היחיד הוא העתקה מכלל חי שעובד.
  • fixed-value על צ’קבוקס: הערך שמסמן הוא "checked"; "checkbox" ו‑"true" לא עושים דבר.
  • dynamic-value — קפיצת Pointer אחת בלבד: "OwnerId.email" ו‑"SubDeptId.Name" עובדים; שתי קפיצות ("SubDeptId.DeptId.Name") מחזירות את ה‑objectId של ה‑Pointer הביניים, לא את השם.

מנגנון ה‑SLA של מודול הפניות בנוי משבעה חלקים שכולם חייבים להיות מוגדרים כדי שהוא באמת יאכוף משהו. חסר אחד — והמערכת נראית מוגדרת ולא עושה כלום.

# החלק מה הוא נותן
1 מינוח (_Dictionary) תוויות בעברית לשדות ה‑SLA
2 מצבי פנייה (CaseStates + CaseStatuses.StateId) קיבוץ סטטוסים לפתוח / סגור (במערכת חדשה קיימים שני אלה בלבד; “מושהה” מוסיפים ביישום). השעון רץ רק במצב “פתוח”
3 שעות עבודה (BusinessHours) חלון שבוע העבודה + חגי ישראל + תאריכים מיוחדים
4 יעדים (SLASettings) היעד עצמו, בשעות או בימים, לפי סוג / סוג+תת‑סוג / סוג+תת‑סוג+סטטוס
5 טריגרים שממלאים את שדות ה‑SLA SLADeadline, ResponseTime, ResolutionTime
6 טבלת מעקב + ווידג’ט (CaseSLAProcess) שורה לכל סטטוס — היסטוריית השעון על כרטיס הפנייה
7 הסלמה (טריגרים מתוזמנים + דוחות) התראות לפני/אחרי חריגה, ודוחות שחושפים חריגות

הפער שחייבים להכיר לפני שמבטיחים ללקוח

Section titled “הפער שחייבים להכיר לפני שמבטיחים ללקוח”

מה שואלים את הלקוח לפני שמתחילים

Section titled “מה שואלים את הלקוח לפני שמתחילים”
  1. גרנולריות — היעד תלוי רק ב‑CaseType? ב‑CaseType + SubType? או גם בסטטוס?
  2. ימים או שעותSLADays או SLAHours. אחד לכל שורה, לא שניהם.
  3. חלון העבודה — חלון שבועי יחיד + חגי ישראל + תאריכים חריגים. מקבילים אינם נתמכים.
  4. מיפוי סטטוסים — סטטוסי “סגור”/“מושהה” ממופים ל‑CaseStates שאינם “פתוח”?
  5. מדיניות הסלמה — מי מקבל התראה ומתי (למשל שעתיים לפני היעד; בחריגה). התבנית הדיפולטיבית מתריעה ל‑OwnerId; ל“מנהל” צריך objectId ספציפי או תפקיד.
  6. עומק חישוב ימי העסקים — התבנית הפשוטה מוסיפה ימים קלנדריים. חישוב ימי עסקים אמיתי (דילוג על סופי שבוע וחגי ישראל) דורש פעולת server-side-code. מאשרים עם הלקוח שקלנדרי מספיק ל‑v1, או שמערבים מפתח.
# השלב קובץ הייחוס בסקיל
1 אימות תנאים מקדימים — CaseTypes/CaseSubTypes/CaseStatuses/CaseStates מלאים, וכל סטטוס עם StateId prerequisites.md
2 תרגומי _Dictionary לכל השדות dictionary-setup.md
3 שורת BusinessHours יחידה business-hours.md
4 שורה אחת ב‑SLASettings לכל כלל sla-settings.md
5 שלושת טריגרי המילוי sla-triggers.md
6 טבלת CaseSLAProcess + שני טריגרים + ווידג’ט על הכרטיס case-sla-process-table.md
7 שני טריגרים מתוזמנים — אזהרה וחריגה escalation-triggers.md
8 שלושת הדוחות הסטנדרטיים sla-reports.md
9 אימות על פנייה אמיתית verify-and-troubleshoot.md

שלושת הדוחות: דוח SLA — כללי (כל הפניות עם כל השדות) · חריגות פניות פתוחות (IsClosed = false, ממוין לפי SLADeadline עולה) · חריגות פניות סגורות (IsClosed = true, ממוין לפי ResolutionTime יורד).

איך יודעים אם פנייה עמדה ב‑SLA

Section titled “איך יודעים אם פנייה עמדה ב‑SLA”
התנאי על שורת הפנייה המשמעות
ResponseTime קיים ו‑ResponseTime <= SLADeadline עמדה — המענה הראשון הגיע לפני היעד
ResponseTime קיים ו‑ResponseTime > SLADeadline חריגה — המענה הגיע, באיחור
ResponseTime ריק, SLADeadline < now, IsClosed = false בחריגה כרגע
ResponseTime ריק ו‑SLADeadline >= now בתוך התקציב

התצוגה לפי סטטוס מגיעה מ‑CaseSLAProcess: לכל שורה יש StatusEnteredAt, StatusExitedAt, DeadlineForStatus ודגל IsBreached — כלומר היסטוריית ההעברות המלאה, עם יעדים.

Get-Data(table: "SLASettings", limit: 100)
Get-Data(table: "BusinessHours", limit: 5)
Get-Data(table: "CaseStates", limit: 20)
Get-Data(table: "CaseStatuses", keys: ["Name", "StateId"], limit: 50)
Get-Triggers(tableName: "Cases")
Get-Schema(className: "CaseSLAProcess")
Get-Reports()
Count-Data(table: "Cases", where: { "SLADeadline": { "$exists": true } })
Count-Data(table: "CaseSLAProcess")

התרחיש החוזר: ללקוח “יש SLA” כי דפי הניהול קיימים ול‑SLASettings יש שורות — אבל Count-Data על פניות עם SLADeadline מחזיר 0. פירושו שהטריגרים חסרים: מישהו הניח שהמנוע מחובר.

הבקשה התשובה
“טבלת היסטוריית SLA על כרטיס הפנייה” CaseSLAProcess — שלב 6
“SLA של 4 שעות לפניות VIP” שורה ב‑SLASettings עם SLAHours = 4 ו‑CaseTypeId תואם + ודאו שטריגר שלב 5 מכסה את הסוג
“SLA לא ירוץ בסופי שבוע וחגים” זה ב‑BusinessHours — אבל הטריגר הפשוט createdAt + N ימים לא מתייעץ איתו. דילוג על סופי שבוע דורש server-side-code
“הפנייה סגורה אבל ה‑SLADeadline עדיין מוצג כחורג” SLADeadline הוא ערך מחושב סטטי — הוא לא “מתנקה” בסגירה. הדוחות מסננים לפי IsClosed
“התראות למנהל במקום לאחראי” בטריגרי שלב 7, userType מ‑field/OwnerId ל‑fixed/<objectId של המנהל>
  • המנוע לא רץ מעצמו — קונפיגורציה לבדה לא מחשבת דבר.
  • קלנדרי מול ימי עסקים — התבנית הפשוטה מוסיפה ימים קלנדריים.
  • קדימות גרנולריות — כללים עם יותר Pointers ספציפיים יותר. קדימות מלאה דורשת server-side-code; הטריגר הפשוט עם timeGap משתמש בערך קבוע אחד.
  • חלון שעות עבודה אחד בלבד. אל תנסו למדל שתי משמרות כשתי שורות.
  • לא לקבוע גם SLAHours וגם SLADays באותה שורה.