דלגו לתוכן

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

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

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

עודכן 30.08.2026

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

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

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

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

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

  • עם tableNametriggers הוא מערך של טריגרי data change של הטבלה, כל אחד עם _id (מזהה בסגנון Parse, 10 תווים), name, active, events, onSetFields, criterias, oneachupdate ו‑actions (לכל פעולה type, _id ושדות הפעולה).
  • בלי tableNametriggers הוא מערך של { "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. בעדכון שולחים רק את מה שמשתנה — נבדק בשני הסוגים: ב‑data change שינוי שם בלבד שמר events, onSetFields, criterias ו‑actions (23.08.2026), וב‑scheduled שינוי שם בלבד שמר את schedulerField, shcedulerHours, criterias והפעולות (אומת 2026-08-25 17:34). מול שרת מלפני 25.08.2026 זה לא נכון ל‑scheduled — ראו הערת ההיסטוריה למטה.

הפרמטר טיפוס חובה המשמעות
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 כמה שעות לפני ערך התאריך. שלילי = אחרי

onSetFields — לא קישוט, אלא בלם

Section titled “onSetFields — לא קישוט, אלא בלם”

זה הפרמטר שמונע לולאות. טריגר על 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 }
]

תרגום: סכום מעל 5,000 וגם סטטוס אחד מהשניים.

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 מקבל את המזהה הזה, וגם מתייחס לפעולות עצמן בשני אופנים שונים לפי סוג הטריגר. גם 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 שאינם קיימים נשמרת בהצלחה (mcp-data-16).
  • 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 שלו. זו התקלה מספר 1 באינטגרציות WhatsApp — ההסבר המלא בכלי הודעות, וגם ה‑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, datetime10.9.2026, 11:30:00, timehm11: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 }
] } }

שלוש תוצאות מדידה על create-object:

  • ערך 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 כשהיעד מחזיר שגיאה). העברת ה‑headers והמתודה בפועל לא אומתו — הן דורשות שרת מקבל חיצוני.

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

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

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

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

שני השדות חובה, ושניהם מגיעים מטבלת AiWebhooks (Get-Data עליה). זו הפעולה היחידה שבה המפתח ב‑actionData (aiWebhook) שונה מ‑actionType (ai-webhook). כך בסכימה החיה ב‑30.08.2026, אחרי שבין 25.08 ל‑28.08 שני הערכים היו trigger-ai-webhook. ודאו את הערך ב‑tools/list לפני שימוש. זכרו גם: webhookId אינו מאומת, ו‑AiWebhooks אינה קיימת במערכת חדשה.

ערכים דינמיים ב‑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 — כך אפשר לראות בדיעבד באיזו רמה נוצרה כל רשומה.

שתי השלכות מעשיות:

  1. אל תתכננו לוגיקה שנשענת על שרשרת ארוכה. מעבר לשלוש רמות — עברו ל‑server-side-code שעושה הכול בפעולה אחת.
  2. בטעינה המונית זה מתפוצץ מוקדם יותר, כי כל שורה מתחילה שרשרת משלה. ראו skipTriggers בכלי נתונים.

השמירה מלולאות היא onSetFields: ודאו שהשדה שהפעולה כותבת אינו ברשימת השדות שהטריגר מאזין להם.

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

בפועל זה בסדר: טריגר מכובה לא רץ (נבדק: אחרי active: false יצירת רשומה תואמת לא הפעילה את הפעולות) ולא עולה כלום, והוא משמר את ההיסטוריה של מה שהיה. שימו לב רק שטריגר מכובה עדיין מופיע ב‑Get-Triggers עם active: false, ולכן ספירה נאיבית של “כמה אוטומציות יש כאן” תיתן מספר מנופח. ובטריגר מתוזמן — כיבוי בעדכון חלקי בטוח מאז גרסת השרת של 25.08.2026 (אומת 2026-08-25 17:34); בשרת ישן יותר הוא דרס את הגדרת הטריגר (mcp-a-01, נסגר) — שם שלחו את כל השדות.

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

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-Triggersactive, events, criterias מול הערכים בפועל, onSetFields מול השדה שבאמת השתנה, ו‑oneachupdate (אם false והטריגר כבר ירה על הרשומה — הוא לא יירה שוב).
התסמין הסיבה הסבירה
לא רץ אף פעם לא פעיל · תנאי לא תואם (מזהה/טיפוס שגוי) · השדה שהשתנה אינו ב‑onSetFields · נכתב עם skipTriggers
רץ פעם אחת ולא שוב oneachupdate: false
מייל לא יצא objectId שגוי של חשבון SMTP או של תבנית
WhatsApp לא יצא from הוא objectId במקום Identity · התבנית אינה APPROVED
מתוזמן לא יורה schedulerField ריק או בעבר · בשרת מלפני 25.08.2026: הטריגר עודכן חלקית ואיבד את schedulerField/shcedulerHours (mcp-a-01, נסגר)
עדכון עצמי לא קורה, בלי שגיאה connection הוא target.objectId/source.objectId במקום current.objectId
הבעלים ברשומה שנוצרה הוא "currentUser" הטריגר רץ מ‑MCP/API (mcp-a-02)

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