דלגו לתוכן

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

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

כלי טריגרים ואוטומציות

עודכן 31.08.2026

טריגר מפוצל לשני כלים: Set-Trigger יוצר את “ראש” הטריגר (על איזו טבלה, באילו אירועים, תחת אילו תנאים), ו‑Set-Trigger-Action מחבר פעולה אחת — לכמה פעולות קוראים לכלי כמה פעמים, והן נשמרות כרשימה שרצה לפי סדר ההוספה. קודם הראש, ואז הפעולות: Set-Trigger הוא שמחזיר את המזהה שהפעולות נתלות עליו.

הפרמטר טיפוס חובה המשמעות
tableName String הטבלה שרוצים את הטריגרים שלה. בלי הפרמטר — מוחזרים כל הטריגרים במערכת

התשובה היא אובייקט עם שני מערכים: triggers ו‑scheduledTriggers.

  • עם tableName — triggers הוא מערך של טריגרי data change של הטבלה, כל אחד עם _id (מזהה בסגנון Parse, 10 תווים), name, active, events, onSetFields, criterias, oneachupdate ו‑actions (לכל פעולה type, _id ושדות הפעולה).
  • בלי tableName — triggers הוא מערך של { "className": "Sales", "triggers": [ … ] }, קבוצה לכל טבלה שיש לה טריגרים.
  • scheduledTriggers — טריגרים מתוזמנים, במבנה שונה: { "_id": "<24 hex>", "className": "Sales", "app": "<appId>", "data": { "name", "active", "criterias", "actions", "schedulerField", "shcedulerHours" } }. shcedulerHours חוזר כמחרוזת ("24"), ו‑actions של טריגר מתוזמן הם ללא _id (מזהים אותם לפי אינדקס — ראו Set-Trigger-Action).
  • טבלה שאינה קיימת ⇒ Error: Class X does not exist.

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

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

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

JSON
{
"F": "SaleStatusId",
"FText": "סטטוס מכירה",
"C": "equalTo",
"T": "Pointer",
"V": "zrP1MSVBoq",
"P": { "targetClass": "SaleStatuses", "visibleVal": "הושלמה", "multiple": false },
"condOr": false
}
המפתח חובה המשמעות
F ✔ שם השדה. תומך במסלול Pointer — OwnerId._User.name
C ✔ האופרטור (enum, ראו למטה)
T ✔ טיפוס הערך — String, Number, Pointer, Boolean, Date. מחרוזת חופשית בסכימה (אין enum), ולכן שגיאת כתיב לא נתפסת
V ✔ הערך להשוואה. חובה בסכימה — בלעדיו: criterias.0.V: Invalid input: expected nonoptional. ל‑Pointer — ה‑objectId; ל‑containedIn — מערך
P ל‑Pointer { targetClass ✔, visibleVal, multiple }. targetClass נאכף בוולידציה כשיש P. multiple: true כש‑V הוא מערך
FText תווית לתצוגה בממשק
condOr true מכניס את התנאי לקבוצת ה‑OR

ה‑enum של הסכימה החיה מכיל עשרה אופרטורים בדיוק:

contains · startsWith · equalTo · greaterThan · lessThan · greaterThanOrEqualTo · lessThanOrEqualTo · notEqualTo · containedIn · notContainedIn

  • תנאים בלי condOr — כולם חייבים להתקיים (AND).
  • תנאים עם condOr: true — מרכיבים קבוצת OR אחת: מספיק שאחד מהם מתקיים.
  • תנאי OR בודד חסר משמעות; צריך לפחות שניים.
  • שילוב: כל תנאי ה‑AND חייבים להתקיים, וגם לפחות אחד מתנאי ה‑OR.
JSON
"criterias": [
{ "F": "Total", "C": "greaterThan", "T": "Number", "V": 5000 },
{ "F": "SaleStatusId", "C": "equalTo", "T": "Pointer", "V": "zrP1MSVBoq",
"P": { "targetClass": "SaleStatuses", "visibleVal": "הושלמה" }, "condOr": true },
{ "F": "SaleStatusId", "C": "equalTo", "T": "Pointer", "V": "V0sVNyS45K",
"P": { "targetClass": "SaleStatuses", "visibleVal": "משא ומתן" }, "condOr": true }
]
JSON
{ "tableName": "Sales", "type": "scheduled", "active": true,
"name": "תזכורת לפני תאריך סגירה",
"schedulerField": "ClosingDate",
"shcedulerHours": 24,
"criterias": [
{ "F": "IsWon", "C": "notEqualTo", "T": "Boolean", "V": true },
{ "F": "IsLost", "C": "notEqualTo", "T": "Boolean", "V": true }
] }

התנאים נבדקים ברגע הירי, לא ברגע היצירה. הרזולוציה היא דקות ספורות, לא דקה מדויקת.

shcedulerHours המשמעות
720 30 יום לפני התאריך
24 יום לפני
1 שעה לפני
-1 שעה אחרי — זה מה שמשמש ל“בערך על התאריך”
-48 יומיים אחרי
0 בדיוק על התאריך (מתקבל; נשמר כ‑"0")

ערכי החזרה — שני פורמטים למזהה

Section titled “ערכי החזרה — שני פורמטים למזהה”
סוג הטריגר מה חוזר מהיכן לוקחים את המזהה
data change סכימת המחלקה כולה (className, fields, classLevelPermissions) עם מערך triggers מאתרים לפי name, לוקחים את _id (בסגנון Parse, למשל 9ht1ary5dW)
scheduled {"value":"69df53414167a73a568f34df"} ה‑value עצמו (בסגנון MongoDB, 24 תווים)

גם Set-Trigger-Action מחזיר שני פורמטים: ב‑data change סכימת המחלקה עם triggers; ב‑scheduled — {"ok":1,"value":{ …הטריגר המלא… }}. טבלה שאינה קיימת ⇒ Error: Table not found.

מחבר פעולה אחת. קריאה נפרדת לכל פעולה; הן נצברות לרשימה ורצות לפי סדר ההוספה.

הפרמטר טיפוס חובה המשמעות
tableName String ✔ אותה טבלה של הטריגר
triggerId String ✔ המזהה שהוחזר מ‑Set-Trigger
triggerType Enum ✔ data change / scheduled — חייב להתאים לטריגר (אי‑התאמה ⇒ Error: Scheduled trigger not found)
actionType Enum ✔ אחד מתשעת הסוגים למטה
actionData Object ליצירה/עדכון אובייקט הפעולה, ממופתח לפי סוג הפעולה. חסר ⇒ Error: Action data is required; מפתח שאינו תואם ל‑actionType ⇒ למשל Error: HTTP data is required. שדות החובה של כל סוג נאכפים בוולידציה
actionId String לעדכון/מחיקה בטריגר data change — ה‑_id של הפעולה · בטריגר scheduled — אינדקס כמחרוזת ("0", "1")
deleteAction Boolean למחיקה מוחק את הפעולה
actionType מה קורה שדות חובה ב‑actionData
email שולח מייל מחשבון SMTP לפי תבנית template, emailAccount, emailType, emailTarget, emailSubject, saveToEmailsTable
sms שולח SMS from, local, content, toType, to
whatsapp-message שולח WhatsApp בתבנית מאושרת toType, to, message, from, template, WATemplateParams
notification התראה בתוך ה‑CRM למשתמש userType, user, content
create-object יוצר רשומה חדשה בטבלה כלשהי targetClass, fieldsValue
update-object מעדכן רשומה קשורה (או את עצמה) targetClass, connection, fieldsValue
http קורא ל‑webhook עם גוף הרשומה url, method
server-side-code מריץ פונקציית צד שרת קיימת functionName
ai-webhook קורא ל‑webhook של AI מטבלת AiWebhooks webhookId, webhookName (המפתח ב‑actionData הוא aiWebhook)
JSON
{ "tableName": "Sales", "triggerId": "9ht1ary5dW", "triggerType": "data change",
"actionType": "email",
"actionData": { "email": {
"emailType": "field",
"emailTarget": "AccountId.Accounts.Email",
"emailSubject": "העסקה {{{Name}}} אושרה",
"emailAccount": "smtp12345x",
"template": "tmpl098765",
"saveToEmailsTable": true,
"fieldsValue": [
{ "field": "AccountId", "targetClass": "Accounts", "type": "Pointer",
"value": "AccountId", "visibleVal": "Account" },
{ "field": "SaleId", "targetClass": "Sales", "type": "Pointer",
"value": "current", "visibleVal": "Current Object(Sales)" }
]
} } }
  • emailType: fixed (כתובת קבועה) או field (שדה מהרשומה, כולל מסלול Pointer).
  • emailAccount הוא ה‑objectId של חשבון SMTP, מ‑Get-SMTP-Accounts. במערכת חדשה הרשימה ריקה ([]) ופעולת האימייל תיכשל. הכלי אינו מאמת את המזהים: פעולת email עם emailAccount ו‑template שאינם קיימים נשמרת בהצלחה.
  • template הוא objectId מטבלת EmailTemplate. אי אפשר ליצור תבנית מייל מ‑MCP.
  • saveToEmailsTable שומר עותק ב‑Emails, ו‑fieldsValue קובע לאילו רשומות הוא ייקשר.
JSON
{ "sms": {
"toType": "field", "to": "PhoneNumber",
"from": "0501234567", "local": "IL",
"content": "שלום {{{AccountId.Name}}}, הזמנתך על סך {{{Total}}} ₪ התקבלה.",
"useQueue": true } }

useQueue: true מומלץ בכל תרחיש שיכול לרוץ במקביל על הרבה רשומות.

JSON
{ "whatsapp-message": {
"toType": "field", "to": "PhoneNumber",
"from": "100000000000000",
"waba_id": "WABA_ID",
"message": "עדכון סטטוס",
"template": { "name": "status_update", "language": "he", "components": [] },
"WATemplateParams": { "BODY": ["{{{AccountId.Name}}}", "{{{Name}}}"] } } }

from הוא ה‑Identity של הערוץ ולא ה‑objectId שלו. ההסבר המלא וה‑workflow להוצאת components ו‑WATemplateParams: כלי הודעות.

JSON
{ "notification": {
"userType": "field", "user": "OwnerId",
"content": "<div>פנייה חדשה: <b>{{{Name}}}</b><br/>לקוח: {{{AccountId.Name}}}</div>",
"icon": "fa-bell", "iconColor": "#00a396" } }

userType: fixed (objectId של משתמש) או field (שדה Pointer ל‑_User). התוכן תומך ב‑HTML. icon הוא שם אייקון של FontAwesome גרסה 3.4 (כך לפי תיאור הסכימה), לא הגרסאות החדשות.

ההתראה נכתבת לטבלה _Notification (שדות Content, User, Icon, IconColor, Date, objectClass, objectIdValue), וה‑placeholders מוחלפים — כולל מסלול Pointer {{{OwnerId.name}}} ושלושת פורמטי התאריך: {{{Stamp.format(date,he-IL,Asia/Jerusalem)}}} ⇒ 10.9.2026, datetime ⇒ 10.9.2026, 11:30:00, timehm ⇒ 11:30. placeholder לשדה ריק מוחלף במחרוזת ריקה.

JSON
{ "create-object": {
"targetClass": "Tasks",
"fieldsValue": [
{ "field": "Name", "type": "static", "value": "לחזור ללקוח" },
{ "field": "SaleId", "type": "dynamic", "value": "currentObject", "targetClass": "Sales" },
{ "field": "AccountId", "type": "dynamic", "value": "AccountId", "targetClass": "Accounts" },
{ "field": "OwnerId", "type": "dynamic", "value": "OwnerId", "targetClass": "_User" },
{ "field": "DueDate", "type": "dynamic", "value": "updatedAt", "timeGap": 1440 }
] } }
  • ערך static אינו עובר החלפת placeholders: { "field": "Name", "type": "static", "value": "משימה עבור {{{Name}}}" } נשמר מילולית. לטקסט מהרשומה המפעילה השתמשו ב‑dynamic (שדה אחד), או בפעולת notification/email שבהן ההחלפה כן עובדת.
  • מסלול Pointer ב‑dynamic עובד: "value": "OwnerId._User.name" מעתיק את שם הבעלים.
  • הרשומה שנוצרת מקבלת createdBy/updatedBy = Master ושדה updatedByTrigger עם מזהה הטריגר.

update-object — סמנטיקת ה‑connection

Section titled “update-object — סמנטיקת ה‑connection”

הפרמטר שקובע איזו רשומה מתעדכנת. הצורה היא כיוון.שם-שדה:

הערך המשמעות דוגמה
source.<PointerField> הרשומה המפעילה מצביעה אל רשומת היעד טריגר על Sales שמעדכן את הלקוח: source.AccountId
target.<PointerField> רשומות היעד מצביעות אל הרשומה המפעילה. מעדכן את כולן טריגר על Sales שמעדכן את כל שורות המכירה: target.SaleId
current.objectId הרשומה המפעילה עצמה חותמת זמן על אותה מכירה
JSON
{ "update-object": {
"targetClass": "Sales",
"connection": "current.objectId",
"fieldsValue": [
{ "field": "OwnerSetDate", "type": "dynamic", "value": "updatedAt" }
] } }

fieldsValue תומך גם במסלולים חוצי‑טבלה: {"field":"AccountId","type":"dynamic","value":"SaleId.Sales.AccountId","targetClass":"Accounts"} מעתיק את הלקוח מהמכירה האב.

JSON
{ "http": {
"url": "https://hooks.example.com/mb?sale={{{objectId}}}&name={{{Name}}}",
"method": "POST",
"useQueue": true,
"headers": [ { "name": "Content-Type", "value": "application/json" } ] } }

method יכול להיות GET, POST, PUT, DELETE או AUTO; לפי תיאור הסכימה AUTO בוחר POST באירוע יצירה ו‑PUT באירוע עדכון. גוף הבקשה הוא ה‑JSON המלא של הרשומה, אוטומטית; ה‑placeholders פועלים בתוך ה‑URL (?name={{{Name}}}&oid={{{objectId}}} יוצא כ‑?name=FIRE%20many-a&oid=1q3vkAuGl7, וה‑URL שנקרא בפועל נרשם ב‑_syslogTriggers בשדה error כשהיעד מחזיר שגיאה).

webhook שמצביע אל ה‑API של הפלטפורמה עצמה (api.mbapps.co.il) מנותב לכתובת פנימית ונכשל ב‑403 unauthorized. לכתיבה חזרה למערכת השתמשו ב‑create-object / update-object.

JSON
{ "server-side-code": { "functionName": "calculateCommission", "useQueue": true } }

מריץ פונקציה שכבר קיימת במערכת, עם הרשומה כהקשר. MCP לא יכול ליצור פונקציה; ראו פונקציות צד שרת.

JSON
{ "aiWebhook": { "webhookId": "aiwh012345", "webhookName": "Lead Scoring" } }

שני השדות חובה, ושניהם מגיעים מטבלת AiWebhooks (Get-Data עליה).

ערכים דינמיים ב‑fieldsValue

Section titled “ערכים דינמיים ב‑fieldsValue”
type value
static ערך קבוע. ל‑Pointer — objectId (הוסיפו targetClass ו‑visibleVal). המילה currentUser = המשתמש שגרם לשינוי
dynamic שם שדה מהרשומה המפעילה. מסלול Pointer: AccountId.Accounts.Name

ערכים דינמיים מיוחדים: currentObject (Pointer לרשומה המפעילה), updatedAt, createdAt, updatedBy.

שדה תאריך מקבל ערך דינמי בלבד.

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

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

מצורף לערך תאריך דינמי:

JSON
{ "field": "DueDate", "type": "dynamic", "value": "updatedAt", "timeGap": 1440 }
דקות משך
60 שעה
1440 יום
2880 יומיים
10080 שבוע
43200 30 יום
-1440 יום אחורה

דקות לוח שנה, לא שעות עבודה. SLA שמדבר בימי עסקים אינו ניתן לביטוי ב‑timeGap; הוא דורש server-side-code.

JSON
{ "tableName": "Sales", "triggerId": "9ht1ary5dW", "triggerType": "data change",
"actionType": "http", "actionId": "abc123", "deleteAction": true,
"actionData": { "http": { "url": "https://example.com", "method": "POST" } } }

שרשרת טריגרים ותקרת שלוש הרמות

Section titled “שרשרת טריגרים ותקרת שלוש הרמות”

פעולה שכותבת נתונים יכולה להפעיל טריגר אחר. עומק השרשרת מוגבל לשלוש רמות: שלושה טריגרים רצים בזה אחר זה, והרביעי לא רץ ונרשם ב‑_syslogTriggers עם {"message":"blocked! trigger step is to deep -3. source trigger: <id הטריגר הראשון>"} (בשרשרת של חמש טבלאות נוצרות רשומות בארבע הראשונות, החמישית נשארת ריקה).

T1 (יצירה) → טריגר 1 → T2 → טריגר 2 → T3 → טריגר 3 → T4 → טריגר 4 ✗ נחסם (T5 לא נוצרת)

הרשומות שנוצרות בשרשרת נושאות setObjectTriggerStep (1, 2, 3) ו‑updatedByTrigger, כך שאפשר לראות בדיעבד באיזו רמה נוצרה כל רשומה. מעבר לשלוש רמות עברו ל‑server-side-code שעושה הכול בפעולה אחת. בטעינה המונית זה מתפוצץ מוקדם יותר, כי כל שורה מתחילה שרשרת משלה; ראו skipTriggers בכלי נתונים.

Set-Trigger עם active: false הוא הכיבוי. מחיקה אמיתית אפשרית רק בממשק — Databases ← Tables ← הטבלה ← Triggers.

טריגר מכובה עדיין מופיע ב‑Get-Triggers עם active: false, ולכן ספירה נאיבית של “כמה אוטומציות יש כאן” תיתן מספר מנופח. גם בטריגר מתוזמן הכיבוי בעדכון חלקי בטוח: השרת ממזג ושומר את שאר ההגדרות והפעולות.

כשהאוטומציה לא רצה — סדר הבדיקות

Section titled “כשהאוטומציה לא רצה — סדר הבדיקות”
  1. הרשומה — Get-Data עליה. זו באמת הרשומה שמדובר בה?
  2. _Timeline — מה קרה בפועל, מתי, ועל ידי מי. user.objectId === "Master" פירושו שינוי מטריגר/API.
  3. _syslogTriggers — שגיאות ורישומי ריצה. כל ריצה רושמת שורת {"status":"trigger run","actions":[…]} ושורה לכל פעולה (actionId, error, data); הערכים ב‑data/error חוזרים ב‑REST כ‑HTML‑escaped (&#34;). היעדר רשומות אינו הוכחה שהטריגר לא רץ; לא כל סביבה מתחזקת את הטבלה הזו.
  4. Get-Triggers — active, events, criterias, onSetFields ו‑oneachupdate מול הערכים בפועל.
התסמין הסיבה הסבירה
לא רץ אף פעם לא פעיל · תנאי לא תואם (מזהה/טיפוס שגוי) · השדה שהשתנה אינו ב‑onSetFields · נכתב עם skipTriggers
רץ פעם אחת ולא שוב oneachupdate: false
מייל לא יצא objectId שגוי של חשבון SMTP או של תבנית
WhatsApp לא יצא from הוא objectId במקום Identity · התבנית אינה APPROVED
מתוזמן לא יורה schedulerField ריק או בעבר · shcedulerHours לא מתאים לחלון שציפיתם לו
עדכון עצמי לא קורה, בלי שגיאה connection הוא target.objectId/source.objectId במקום current.objectId
הבעלים ברשומה שנוצרה הוא "currentUser" הטריגר רץ מ‑MCP/API

היכן מחפשים כל יומן: יומנים וראיות.