דלגו לתוכן

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

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

מיפוי שדות מטופס לסכימה

עודכן 10.10.2026

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

# הצעד למה
1 שליפת סכימת Accounts לדעת אילו שדות קיימים, ובאיזה טיפוס
2 שליפת סכימת טבלת היעד (רק ב‑web2table) אותו דבר עבור השורה העסקית
3 שליפת הערכים מכל טבלת lookup שהטופס ממלא לבנות מפת ערך תצוגה → objectId
4 אימות כל שדה שהלקוח ביקש מול הסכימה לסמן חוסרים לפני כתיבת הקוד
5 הטמעת המפות בקוד ובנייה רק עכשיו

צעדים 1–3 בלתי תלויים; הריצו במקביל.

Bash
curl -sS "https://api.mbapps.co.il/parse/schemas/Accounts" \
-H "X-Parse-Application-Id: $APP_ID" \
-H "X-Parse-Master-Key: $MASTER_KEY" > accounts-schema.json
JavaScript
import { writeFile } from 'node:fs/promises';
const res = await fetch("https://api.mbapps.co.il/parse/schemas/Accounts", {
headers: {
'X-Parse-Application-Id': APP_ID,
'X-Parse-Master-Key': MASTER_KEY,
},
});
await writeFile('accounts-schema.json', await res.text());
Python
import requests
res = requests.get(
"https://api.mbapps.co.il/parse/schemas/Accounts",
headers={
"X-Parse-Application-Id": APP_ID,
"X-Parse-Master-Key": MASTER_KEY,
},
)
with open("accounts-schema.json", "w", encoding="utf-8") as f:
f.write(res.text)
PHP
<?php
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => "https://api.mbapps.co.il/parse/schemas/Accounts",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"X-Parse-Application-Id: {$APP_ID}",
"X-Parse-Master-Key: {$MASTER_KEY}",
],
]);
$response = curl_exec($ch);
curl_close($ch);
file_put_contents("accounts-schema.json", $response);
Python
# accounts_fields.py — שם שדה, טיפוס, ולאיזו טבלה מצביע כל Pointer
import json
fields = json.load(open('accounts-schema.json', encoding='utf-8'))['fields']
for name, spec in sorted(fields.items()):
print(f"{name:34}{spec['type']:12}{spec.get('targetClass', '')}")

פלט טיפוסי:

City Pointer CityList
CompanyId String
Email String
F_name String
IsAccount Boolean
LeadSourceId Pointer LeadSource
LeadStatusId Pointer LeadStatuses
Name String
PhoneNumber String
array_interests_Pointer_Interests Array

targetClass אומר מאיזו טבלה לשלוף את ערכי ה‑lookup בצעד 3.

City הוא Pointer לטבלת CityList בהתקנות רבות, כלומר objectId ולא שם עיר, ובהתקנות אחרות String חופשי. שלפו סכימה לכל טננט במקום להניח טיפוס.

JSON
// Get-Schema
{ "className": "Accounts" }
הפרמטר טיפוס חובה מה הוא עושה
className string לא שם המחלקה. בלעדיו מוחזרת הסכימה של כל הטבלאות, תשובה של עשרות KB. ה‑MCP משמיט את טבלאות המערכת החסומות (Config, _Session, _Role, SMTP ודומיהן) ולכן מחזיר כמה טבלאות פחות מ‑/parse/schemas
tablesNameOnly boolean לא true מחזיר רק את שמות הטבלאות, לאיתור השם המדויק של טבלת היעד

צעד 3 · בניית מפת ה‑Pointer

Section titled “צעד 3 · בניית מפת ה‑Pointer”

<select> שולח טקסט (“פייסבוק”), ה‑API רוצה objectId (“vOZLqOWnQf”). לטופס אין דרך מאובטחת לשאול את המערכת בזמן ריצה, לכן המפה מוטמעת בקוד כסטטית.

JSON
// Get-Data — שליפת ערכי טבלת ה-lookup
{ "table": "LeadSource", "keys": ["Name"], "limit": 200 }
הפרמטר טיפוס חובה הערה
table string ✔ שם הטבלה — כלומר ה‑targetClass מהסכימה
keys string[] לא הקרנת שדות. ["Name"] מספיק לבניית מפה
limit number לא ברירת המחדל 5. המקסימום: 2000
order string לא מיון; - בתחילת השם = יורד
skip number לא עימוד
where object לא תנאי סינון — כל מפתח הוא שם שדה, מפתחות מרובים מתחברים ב‑AND
objectId string לא 10 תווים בדיוק — לשליפת רשומה בודדת. אורך אחר נדחה בוולידציה (Too small / Too big)

מהתוצאה:

JavaScript
// נשלף פעם אחת מטבלת LeadSource — עדכנו כשמוסיפים מקור חדש במערכת
const SOURCE_MAP = {
'פייסבוק': 'vOZLqOWnQf',
'גוגל': 'fHG8Rgy8Hr',
'אתר אינטרנט': 'yOTdl4L99Q',
'המלצה': 'Qk2pLm8Zx4',
};

הטופס מציג את ערך התצוגה, הקוד שולח את המזהה:

HTML
<select name="source">
<option value="">איך הגעתם אלינו?</option>
<option>פייסבוק</option>
<option>גוגל</option>
<option>אתר אינטרנט</option>
<option>המלצה</option>
</select>
JavaScript
const data = { LeadSourceId: SOURCE_MAP[f.source] }; // objectId חשוף, או undefined

טבלת הטיפוסים של שכבת הטפסים

Section titled “טבלת הטיפוסים של שכבת הטפסים”

הטיפוסים כאן אינם הפורמט של Parse REST, ו‑snippet של Parse REST נראה נכון ומחזיר 200. שדות account_* ושדות table_* מתנהגים אחרת ב‑Pointer.

טיפוס בסכימה הצורה המומלצת מה קורה בפועל בצורות אחרות
String מחרוזת מחרוזת ריקה אינה נשמרת — השדה כלל לא נכתב לרשומה. אובייקט ({"a":1}) מפיל את הבקשה ב‑400 code 111
Number מספר או מחרוזת מספרית — השרת ממיר 1500 ו‑"1500" → 1500. "1,500" ו‑"abc" → נשמרים כ‑null
Boolean true / false בוליאני "true" / "false" כמחרוזת (אותיות קטנות בלבד) מומרים; כל מחרוזת אחרת — "True", "yes", "1" — נשמרת כ‑false. מספר (1 / 0) מפיל את הבקשה ב‑400 code 111 (expected Boolean but got Number). חריג: account_IsAccount מקבל רק בוליאני — מחרוזת "true" מפילה את הבקשה
Date מחרוזת ISO שטוחה ומרופדת: "2026-09-01" ISO מלא עובד, וגם {"__type":"Date","iso":"..."} עובד. "2026-9-1" (לא מרופד) מפיל את הבקשה ב‑400 code 111 (expected Date but got String)
Pointer — account_* מזהה חשוף באורך 10 תווים: "vOZLqOWnQf" {"__type":"Pointer",…} עובד גם הוא. אורך אחר מפיל את כל הבקשה ב‑400
Pointer — table_* מזהה חשוף באורך 10 תווים, ורק הוא אורך אחר וגם {"__type":"Pointer",…} נזרקים בשקט — 200 והשדה חסר. SaleStatusId ב‑Sales נזרק תמיד
Array (בחירה מרובה) מערך של אובייקטי Pointer: [{"__type":"Pointer","className":"Interests","objectId":"uNbbHuMGlK"}] מערך של מזהים חשופים נשמר, אבל בכרטיס יוצגו צ’יפים ריקים וקריטריון containedIn בטריגר לא יתאים לו
File / PrivateFile אובייקט File של קובץ שהועלה קודם (ב‑table_* בלבד) מעלים קודם את הקובץ — POST /parse/files/<name> (כותרת App ID בלבד, הגוף הוא הקובץ) — ושולחים את אובייקט ה‑File שחזר: {"__type":"File","name":…,"url":…} → 200 ושורה אחת עם הקובץ (נבדק 10.2026). אובייקט File של קובץ שלא הועלה מחזיר 400 {"code":1} אחרי כ‑5 שניות ומשאיר בצד השרת איש קשר ו‑5 שורות יעד כפולות; מחרוזת URL מחזירה 400 (code 111), אבל איש הקשר כבר נוצר.

מזהה Pointer תקין באורכו אך לא קיים בטבלת ה‑lookup נשמר בשתי הקבוצות, כ‑Pointer שמצביע לשום מקום.

array_<purpose>_Pointer_<TargetTable> מאוחסן כמערך של אובייקטי Pointer — כך ה‑CRM עצמו שומר אותו:

JSON
// getlead
{ "PhoneNumber": "0501234567",
"array_interests_Pointer_Interests": [{"__type":"Pointer","className":"Interests","objectId":"uNbbHuMGlK"}, {"__type":"Pointer","className":"Interests","objectId":"j17RjXmHdN"}] }

ב‑web2table מוסיפים את הקידומת של הקבוצה:

JSON
{ "account_array_interests_Pointer_Interests": ["uNbbHuMGlK", "j17RjXmHdN"],
"table_array_tags_Pointer_Tags": ["GGZUYqBjqT", "io3Z6YsMcG"] }

בטופס זה בדרך כלל <input type="checkbox"> מרובים או <select multiple>: אספו את הערכים, העבירו כל אחד דרך המפה, ושלחו את המערך.

שדה שלא מופה — משמיטים, לא מרוקנים

Section titled “שדה שלא מופה — משמיטים, לא מרוקנים”

undefined לא עובר סריאליזציה בצורה עקבית בין שפות. "" ו‑null אמנם מושמטים על ידי שכבת הטפסים עצמה, השדה אינו נכתב והבקשה מחזירה 200, אבל זו התנהגות לא מתועדת של השרת. והגבול דק: ערך לא ריק אבל שגוי בטיפוסו, "2026-9-1" בשדה Date, 1 בשדה Boolean, "abc" במקום מזהה ב‑account_*, מפיל את הבקשה כולה ב‑400.

הניקוי הוא השורה האחרונה לפני השליחה:

JavaScript
Object.keys(data).forEach((k) => { if (data[k] == null || data[k] === '') delete data[k]; });
Python
data = {k: v for k, v in data.items() if v not in (None, "")}
PHP
$data = array_filter($data, static fn ($v) => $v !== null && $v !== '');

דוגמה מלאה — מסכימה לקוד

Section titled “דוגמה מלאה — מסכימה לקוד”

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

שדות הטופס → שדות המערכת (web2table, table = "CourseRegistrations")
שם פרטי → account_F_name String
שם משפחה → account_L_name String
טלפון → phone String ✔ חובה, בלי קידומת
אימייל → email String בלי קידומת
עיר → account_City String
איך שמעת עלינו → account_LeadSourceId Pointer → LeadSource (מפה: 4 ערכים)
הסדנה → table_CourseId Pointer → Courses (מפה: 6 ערכים)
תאריך מועדף → table_StartDate Date ISO שטוח
⚠ "מספר משתתפים" שביקשתם לא קיים בסכימת CourseRegistrations.
הקרוב ביותר: ParticipantsCount (Number). לאשר לפני שממשיכים.
JavaScript
const SOURCE_MAP = { 'פייסבוק': 'vOZLqOWnQf', 'גוגל': 'fHG8Rgy8Hr', 'המלצה': 'Qk2pLm8Zx4' };
const COURSE_MAP = { 'קורס יסודות CRM': 'aB3dEf9HiJ', 'סדנת אוטומציות': 'kLm4NoP7Qr' };
function buildBody(f) {
const data = {
table: 'CourseRegistrations',
phone: f.phone,
email: f.email,
account_F_name: f.firstName,
account_L_name: f.lastName,
account_City: f.city,
account_LeadSourceId: SOURCE_MAP[f.source], // undefined אם לא נמצא → יימחק
table_CourseId: COURSE_MAP[f.course],
table_StartDate: f.startDate, // "2026-09-01"
};
Object.keys(data).forEach((k) => { if (data[k] == null || data[k] === '') delete data[k]; });
return data;
}
  • נשלפו סכימת Accounts וסכימת טבלת היעד
  • כל שדה שהלקוח ביקש אומת מול הסכימה, וכל חוסר סומן ללקוח
  • לכל Pointer נשלפה טבלת ה‑targetClass ונבנתה מפה
  • כל ערכי המפה מחרוזות באורך 10 תווים בדיוק, לא אובייקט {"__type":"Pointer"}
  • תאריכים ISO שטוח מרופד; בוליאנים true/false אמיתיים
  • ערכים ריקים מוסרים מהגוף, ו‑0/false לא נמחקים בטעות
  • המפות מתועדות בקוד עם הערה מאיזו טבלה הן נשלפו ומתי