פרויקט סיום חלק א'
מסמך אפיון ויישום Salesforce פרויקט גמר CRM-Period

משרה חמה

מענה לדרישה:

  1. Master-Detail בין Application ל-Job + שדה עזר על Application + Roll-Up Summary על Job + שדה Formula/Checkbox להצגת הדגל.

    לפי מסמכי הפרויקט Application הוא אובייקט שמקשר בין משרה למועמד, וכולל כבר את שדות התהליך, מידת המוטיבציה ומידת ההתאמה. בנוסף, הדרישה בחלק ג' היא רק להציג דגל אדום כאשר יש לפחות 3 מועמדים מתאימים שעברו את שלב הצעת השכר והמשרה עדיין פתוחה.

    1. יצירת Formula Checkbox על Application בשם:  Qualified_For_Hot_Job
      נוסחה:

    AND (ISPICKVAL( Fit_Level__c , "High"), OR(ISPICKVAL(Application_Process__c, "Offer"),
    ISPICKVAL(Application_Process__c, "Hired")))

    1. יצירת Roll-Up Summary על  Jobבשם:  High_Fit_After_Salary_Offer_Count
      סופר כמה Qualified_For_Hot_Job = True

    2. יצירת Formula Checkbox על Jobבשם: Show_Red_Flag
      נוסחה:

    AND(ISPICKVAL(Status__c, "Open"), High_Fit_After_Salary_Offer_Count__c >= 3)

    כך הדגל נקבע אוטומטית לפי מצב המשרה ומספר המועמדויות הרלוונטיות. הדרישה למסמך אכן קושרת בין מצב המשרה הפתוחה לבין 3 מועמדים או יותר ברמת התאמה גבוהה אחרי שלב הצעת השכר.

    1. יצירת שדה Formula Text על Job בשם: Red Flag Banner
      נוסחה:

    IF(Show_Red_Flag__c, "🔴 HOT JOB – 3+ high-fit candidates after salary offer", "" )

מועמדויות למשרה:

התנאי לחיווי משרה חמה : High_Fit_After_Salary_Offer_Count  >= 3

מתחת ל-3 מועמדים אין חיווי
מתחת ל-3 מועמדים אין חיווי

התנאי לחיווי משרה חמה : High_Fit_After_Salary_Offer_Count  >= 3

חיווי משרה חמה
מ- 3 מועמדים מעלה חיווי משרה חמה

שכלול ניקוד ראיון

מענה לדרישה: 

מבוסס על 3 שדות התרשמות שקיימים באובייקט המבוססים על ערכים Low, Medium, High:

  • Tech Impression – התרשמות טכנולוגית
  • Interpersonal Impression – התרשמות HR יחסי אנוש
  • Motivation Impression – התרשמות מוטיבציה

יצירת שדה Interview Score מסוגFormula (Number,1)  שמחשב את הציון הסופי

עדכון Compact Layout  כדי שהציון יופיע בכותרת הרשומה

נוסחת השקלול המומלצת

אם שלושת הערכים הם 1–3, אז: ממוצע מינימלי = 1, ממוצע מקסימלי = 3

כדי להמיר ל־1–10 השתמשתי בנוסחה: ((Average−1)/2)∗9+1

כך: כל הציונים נמוכה → 1 |  כל הציונים גבוהה → 10 |  ערכים באמצע יקבלו ציון יחסי

גרסה יותר מקצועית עסקית, שבה לקריטריון Tech Impression יש משקל גבוה יותר, כי ברוב תהליכי הגיוס המקצועיים היכולת הטכנולוגית נחשבת קריטית יותר, אך עדיין נשמר איזון עם HR ו־Motivation.

נוסחה בשדה Interview Score

ROUND((((CASE(TEXT( Tech_Impression__c ),"Low", 1,"Medium", 2,"High", 3,1) * 0.5)

+

(CASE(TEXT( Interpersonal_Impression__c ),"Low", 1,"Medium", 2,"High", 3,1) * 0.25)

+

(CASE(TEXT( Motivation_Impression__c ),"Low", 1,"Medium", 2,"High", 3,1) * 0.25)) – 1) / 2 * 9 + 1, 1)

שכלול ניקוד ראיון

פעולה מהירה

יצירת משרה חדשה

מענה לדרישה: יצירת Global Action

פעולה מהירה - יצירת משרה חדשה

בקשות באובייקט מועמד

מענה לדרישה:

  1. הורדה והתקנת אפליקציה
  2. הוספת הקומפוננטה בדף המועמדות למשרה.
  3. הגדרת תנאי תצוגה ל- קומפוננטה
  4. וולידציה על מנת לאכוף את האפשרות להוספת חתימה תהיה זמינה אך ורק למועמדים שעברו את שלב הצעת השכר
  5. וולידציה על מנת לאכוף קבלה למשרה אם לא קיימת חתימה של המועמד
  6. בניית FLOW תומך לאישור ועדכון הרשומה
  7. התקנת תוסף Refresher ושפעול Apex – מרענן את הרשומה ללא צורך ב- F5

1) רק כאשר תנאי הוולידציה של השדה (Formula) Allow Signature יתקיימו
OR(ISPICKVAL(Application_Process__c, "Offer"),ISPICKVAL(Application_Process__c, "Accepted"))
2) סטטוס הפעולה – Offer
3) שדה שנתקבל חתימה מהמועמד: False = Candidate Signature Received
4) שדה המציג קישור לקובץ החתימה יופיע רק לאחר חתימה ו שדה
True = Candidate Signature Received
5) כותרת " ✅ החתימה התקבלה בהצלחה" תופיע רק לאחר חתימה ו שדה
True = Candidate Signature Received

6) הוספת: Record Refresher וכתיבת Apex (AppSignatureUpdate) שמבצע Refresh לרשומה במקום (F5)

הוספת שדות:

  • שדה Candidate Signature Received  מסוג: CheckBox לחיווי שתקבלה חתימה מהמועמד
  • שדה: Candidate Signature Date מסוג: Date/Time – לתיעוד תאריך ושעת החתימה

וולידציות:

AND(ISPICKVAL( Application_Process__c , "Hired"),Candidate_Signature_Received__c = False)

וולידציה: הוספת חתימה תהיה זמינה אך ורק למועמדים שעברו את שלב הצעת השכר

מבוסס על לוגיקה של שדה Allow Signature מסוג: Formula CheckBox

OR(ISPICKVAL(Application_Process__c, "Offer"),ISPICKVAL(Application_Process__c, "Accepted"))

וולידציה חסימת שינוי לאחר קבלת חתימה

AND(PRIORVALUE(Candidate_Signature_Received__c) = TRUE, OR(ISCHANGED(Candidate_Signature_Received__c), ISCHANGED(Candidate_Signature_Date__c)))

הוספת שדות:

שדה Candidate Signature Received  מסוג: CheckBox לחיווי שתקבלה חתימה מהמועמד

שדה: Candidate Signature Date מסוג: Date/Time – לתיעוד תאריך ושעת החתימה

כתיבת APEX לריענון הרשומה במקום F5

PushTopic pt = new PushTopic();
pt.Name = 'AppSignatureUpdate';
// חשוב: השדות והאובייקט מדויקים (ל Application__c)
pt.Query = 'SELECT Id, Name, Candidate_Signature_Received__c FROM Application__c';
pt.ApiVersion = 59.0;
// הגדרות שליחה
pt.NotifyForOperationUpdate = true; // רוצים עדכון
pt.NotifyForOperationCreate = true;
pt.NotifyForFields = 'Referenced'; // התרעה רק אם השדה בשאילתה השתנה
insert pt;
System.debug('PushTopic Created: ' + pt.Name);

אוטומציה (FLOW) לעדכון :

עדכון שדות:

  • Candidate Signature Received
  • Candidate Signature Date

תהליך ה- FLOW
טריגר אובייקט Application כשיש עדכון ברשומהבדיקת CheckBox – AllowSignature

Get Records – לאובייקט: Content Document Link אם הקובץ מקושר לרשומה

LinkedEntityId = {!$Record.Id}

Get Records – לאובייקט: Content Document (Beta) אם סיומת הקובץ png (זוהי סיומת הקובץ שהחתימה יוצרת)
תנאי (Decision) שכל (AND) התנאים מתקיימים
בדיקה שהקישור לרשומה (קיים) ולא ריק

{!GET_ContentDocumentLink.Id} Is Null False

בדיקה שסיומת הקובץ אכן png

{!Get_Content_Document.FileExtension} Equals png

בדיקה ששם הקובץ מתחיל ב Signature

{!Get_Content_Document.Title} Starts With Signature

Update Records

Candidate Signature Received = True
Candidate Signature Date = {!$Flow.CurrentDateTime}

אוטומציה (FLOW) לעדכון שדות:

תהליך ה- FLOW
טריגר אובייקט Application כשיש עדכון ברשומהבדיקת CheckBox – AllowSignature

Get Records – לאובייקט: Content Document Link אם הקובץ מקושר לרשומה

LinkedEntityId = {!$Record.Id}

Get Records – לאובייקט: Content Document (Beta) אם סיומת הקובץ png (זוהי סיומת הקובץ שהחתימה יוצרת)
תנאי (Decision) שכל (AND) התנאים מתקיימים
בדיקה שהקישור לרשומה (קיים) ולא ריק

{!GET_ContentDocumentLink.Id} Is Null False

בדיקה שסיומת הקובץ אכן png

{!Get_Content_Document.FileExtension} Equals png

בדיקה ששם הקובץ מתחיל ב Signature

{!Get_Content_Document.Title} Starts With Signature

Update Records

Candidate Signature Received = True
Candidate Signature Date = {!$Flow.CurrentDateTime}

אוטומציה (FLOW) לעדכון שדות:

מעקב מטלות בית - חלק 1

מענה לדרישה: 

האובייקט Assignment כולל קישור ל־Application, שדה Type מסוג Picklist, ושדה Status שבו אחת האפשרויות היא "נשלח" .
בנוסף, הדרישה כאן היא תהליך אוטומטי שמקל על המשתמש ביצירת כמה מטלות בית בבת אחת מתוך רשומת Application עצמה, ולכן הפתרון הנכון הוא Screen Flow שמופעל מכפתור/Action על רשומת המועמדות. זה מתאים לדרישה העסקית של בחירה ידנית של סוגי המטלות ואז יצירה אוטומטית של הרשומות.

השתמשתי ב-3 Checkbox נפרדים במסך:

chkDataAnalysis
chkTrailhead
chkExcel

כי כל אחד מהם מחזיר Boolean ברור: True / False

ואז אני בונה בעצמי Text Collection של סוגי המטלות שנבחרו, ועליו עושה Loop.

צעד 1 – יצירת Resources

1. recordId
Text, input

2. txtSelectedTypes
Text Collection Variable
זה האוסף שעליו נעשה Loop.

3. varAssignment
Record Variable של Assignment

4. colAssignments

Record Collection של Assignment

צעד 2 – Screen

מסך אחד עם 3 Checkbox:

  • Data analysis
  • Trailhead
  • Excel

צעד 3 – הוספת Decision

בדיקה אם נבחר Data analysis אם כן בצע Assignment של הערך Data analysis

ל- Collection של הרשומות txtSelectTypes

צעד 4 – הוספת  Decision 

בדיקה אם נבחר Trailhead אם כן בצע Assignment של הערך Trailhead

ל- Collection של הרשומות txtSelectTypes

צעד 5 – הוספת Decision 

בדיקה אם נבחר Excel אם כן בצע Assignment של הערך Excel

ל- Collection של הרשומות txtSelectedTypes

כך ה-Collection יכיל רק את הבחירות האמיתיות של המשתמש.

צעד 6 – הוספת Loop

דרך פעולה ה- Loop עובר על ה- Collection – שב- txtSelectedTypes, ובכל איטרציה מכניס את הערך למשתנה שהלולאה יוצרת: Current Item from LOOP_Assignment_Types, כך ה- Flow יוצר רשומה לכל סוג מטלה.

צעד 7 – הוספת Assignment בתוך הנתיב For each

כך יווצר אובייקט חדש להשמה (Assignment) לכל רשומה / איטרציה שהלולאה רצה

צעד 8 – הוספת Assignment

כדי הכניס את הרשומה שבנינו אל האוסף colAssignments

צעד 9 – Create Records 

ליצירת הרשומות בפעולה אחת

צעד 10 – Display Screen 

על מנת להציג למשתמש שהרשומות נוצרו בהצלחה !

‫מעקב ‬‫מטלות‬ ‫בית‬ ‫‪-‬‬ ‫חלק‬ ‫‪1‬‬

מעקב מטלות בית - חלק 2

מענה לדרישה: 

הפתרון הנכון לדעתי הוא Record-Triggered Flow על אובייקט Assignment:

  • יופעל After Save
  • יופעל כאשר נוצרת מטלה בסטטוס נשלח
  • יכיל 3 Scheduled Paths:
    • אחרי 3 ימים → מייל תזכורת למועמד
    • אחרי 7 ימים → מייל תזכורת לבעלי המשרה
    • אחרי 14 ימים → אם עדיין "נשלח", שינוי סטטוס ל־"לא הושלמה"

זה הפתרון הנכון כי:

  • הכול יושב על הרשומה שצריכה להימדד בזמן
  • אין צורך בלולאות
  • אין צורך ב־Scheduled Flow שרץ על כל המערכת
  • כל מטלה מנהלת לעצמה את הלו"ז האוטומטי שלה
FLOW מתוזמן לאחר יצירת מטלה

צעד 1 – הגדרת Start

Object – Assignment

Trigger the Flow When – A record is created

Condition Requirements – All Conditions Are Met (AND)

תנאי: Status__c Equals Sent

Optimize the Flow For – Actions and Related Records

כלומר: After Save

למה זו ההגדרה הנכונה

כי אנחנו רוצים:

  • לשלוח מיילים
  • לעדכן רשומה בעתיד
  • להשתמש ב־Scheduled Paths

כל אלה דורשים After Save.

צעד 2 – יצירת 3 Scheduled Paths

After 7 Days, After 3 Days, After 14 Days
בכולם ההגדרה Assignment__c: Created Date 
Days After
השוני היחידי הוא בהגדרת ה- Offset Number – בהתאמה ל PATH

צעד 3 – ענף  של 3 ימים הוספת Decision

בדיקה שהסטטוס עדיין במצב Sent כיוון שייתכן כי בינתיים המטלה הושלמה וכשיגיע ה Scheduled Path יגיע בזמן שלו, ואנו לא רוצם לשלוח מייל מיותר.

צעד 4 – ענף  של 3 ימים הוספת רכיב Action – Send Email, למועמד

שליחת מייל למועמד
הממוען: {!Candidate.Email)

נושא: תזכורת להשלמת מטלת הבית {Assignment.Type!}

גוף המייל:  שלום {Candidate Name!},
זוהי תזכורת להשלמת מטלת הבית שנשלחה אליך לפני 3 ימים.
נשמח להשלמתה בהקדם.

צעד 5 – ענף  של 7 ימים הוספת Decision

בדיקה שהסטטוס עדיין במצב Sent כיוון שייתכן כי בינתיים המטלה הושלמה וכשיגיע ה Scheduled Path יגיע בזמן שלו, ואנו לא רוצם לשלוח מייל מיותר.

צעד 6 – ענף  של 7 ימים הוספת רכיב Action – Send Email לבעלים של המשרה (Job.Owner)

שליחת מייל למועמד
הממוען: {!Owner.Email)

נושא: מטלת הבית  {Assignment.Type!} עדיין לא הושלמה

גוף המייל:  שלום {Owner Name!},
מטלת הבית של המועמד (Candidate.Name) עדיין בסטטוס "נשלח" לאחר 7 ימים.
מומלץ לבדוק האם נדרש מעקב מול המועמד.

צעד 7 – ענף  של 14 ימים הוספת Decision

בדיקה שהסטטוס עדיין במצב Sent

לאחריו Update Record
וביצוע עדכון לרשומה ל-
Status= Not Completed

ניהול קבלה למשרה

הפתרון שלי מבוסס על: 

תהליך אוטומטי על מועמדות למשרה (Application):
כאשר מועמד התקבל למשרה, צריך:

  1. לשנות את סטטוס המשרה ל-סגורה
  2. לשלוח מייל למועמד שהתקבל
  3. לכל שאר המועמדויות של אותה משרה שלא התקבלו, לשנות סטטוס ל-נדחה
  4. ליצור Task כדי ליצור קשר עם אותם מועמדים ולעדכן אותם טלפונית

למה הפתרון הנכון כאן הוא Flow על Application

לפי מודל הנתונים בפרויקט:

  • המשרה מנוהלת באובייקט Job
  • המועמדות מנוהלת באובייקט Application
  • ה-Application הוא זה שמחבר בין מועמד למשרה, וגם בו נשמר שלב התהליך/ההחלטה

לכן, האירוע שמפעיל את האוטומציה צריך להיות:
כאשר Application משנה סטטוס ל-"התקבל".

זה עדיף על Flow על Job, כי ההחלטה על קבלה מתקבלת ברמת המועמדות, לא ברמת המשרה

פלואו  Record-Triggered Flow על האובייקט Application:

הטריגר

כאשר רשומת מועמדות מתעדכנת ו-Application Process = Hired

מה ה-Flow יעשה

  • יעדכן את המשרה המקושרת ל-Closed
  • ישלח מייל למועמד שהתקבל
  • ישלוף את כל שאר המועמדויות של אותה משרה
  • יעדכן אותן ל-Rejected
  • ייצור Task לכל אחת מהן

שלב 1 — יצירת Flow חדש

הגדרות טריגר

Trigger the Flow When: A record is updated

Condition Requirements:

Application Process Equals Hired
When to Run the Flow for Updated Records:

Only when a record is updated to meet the condition requirements

Optimize the Flow for:
Actions and Related Records

הסיבות לבחירה הנ"ל
כי אנחנו גם:

  • מעדכנים רשומות קשורות
  • יוצרים Tasks
  • שולחים מייל

כל אלה מחייבים After Save Flow.

שלב 2 — הוספת Get Records למשרה של המועמדות

הבאתה המשרה כ-Get Records.
זה נותן Flow יציב וברור יותר, וגם מקל על המשך הבנייה.

מה עושים

הוסף אלמנט: Get Records

Object Job

Filter : Id Equals {!$Record.Job__c}

בהמשך אשתמש:

  • לעדכן את סטטוס המשרה
  • להשתמש בשם המשרה במייל

שלב 3 — עדכון המשרה Closed"

הוסף אלמנט: Update Records

How to Find Records to Update
Use the IDs and all field values from a record or record collection

Record: {!Get_Related_Job}

Set Field Values: Status = Closed

על פי הדרישה אומרת במפורש:
אם מועמד התקבל למשרה — סטטוס המשרה צריך להשתנות לסגורה

שלב 4 — יצירת תבניות טקסט למייל הזכייה

כדי שהמייל ייראה טוב ומקצועי, השתמשתי ב-Text Template.

ב-Manager > New Resource > Text Template

Subject API/Label: TT_Accepted_Subject

תוכן:
התקבלת למשרה {!Get_Related_Job.Name}
 

Body API/Label: TT_Accepted_Body

שלום {!$Record.Candidate__r.Name},בשמחה רבה אנו מודיעים לך שהתקבלת למשרה {!Get_Related_Job.Name}.

פרטי המשרה:
שם המשרה: {!Get_Related_Job.Name}
תיאור: {!Get_Related_Job.Description__c}
טווח שכר: {!Get_Related_Job.Salary_Range__c}

מאחלים לך הצלחה רבה בהמשך הדרך!

בברכה,
צוות הגיוס

 Get Records שלב 5 – הוספת

Get Records :הוספת

Object Candidate

Filter: Id Equals {!$Record.Candidate__c}

שלב 6 — שליחת המייל למועמד שהתקבל

הוסף אלמנט: Action
>Send Email

Configuration:

Recipient Address List = Get_Candidate.Email__c

Subject = TT_Accepted_Subject

Body = TT_Accepted_Body

שלב 7 — שליפת כל שאר המועמדויות של אותה משרה

הוסף: Get Records

Object Application

Filters

  1. Job__c Equals {!$Record.Job__c}
  2. Id Not Equals {!$Record.Id}
  3. Application_Process__c Not Equals Rejected

שלב 8 — יצירת משתנים Collection לעדכונים ולמשימות

Record Collection Variable עבור Applications

  • Resource Type: Variable
  • API Name: varApplicationsToReject
  • Data Type: Record
  • Object: Application
  • Allow multiple values: Checked

Record Collection Variable עבור Tasks

  • Resource Type: Variable
  • API Name: varTasksToCreate
  • Data Type: Record
  • Object: Task
  • Allow multiple values: Checked

שלב 9 – לולאה על שאר המועמדויות

הוסף: Loop

Collection Variable

Get Other Applications

שלב 10 — בתוך הלולאה: הכנת המועמדות לעדכון ל"Rejected"

בתוך הלולאה nבצע שתי פעולות:

  1. הכנת רשומת ה-Application לעדכון
  2. הכנת Task

10.1 Assignment לעדכון ה-Application

הוסף Assignment

פעולות

על ה-Current Item from Loop:

  • Application_Process__c = Rejected

ואז:

  • Add Current Item to varApplicationsToReject

שלב 11 — בתוך הלולאה: הכנת Task

יצירת משתנה נוסף:
Variable

  • API Name: varSingleTask
  • Data Type: Record
  • Object: Task
  • Available for multiple values: לא מסומן

אחר הוספת Assignment

שדות ל-Task

  • Subject = ליצור קשר עם מועמד שלא התקבל
  • Status = Not Started
  • Priority = Normal
  • WhatId = {!Loop_Other_Applications.Id}
    אם המערכת מאפשרת לקשר ל-Application
  • OwnerId = {!Loop_Other_Applications.OwnerId}
    זה הפתרון הכי בטוח בפרויקט כזה
  • Description = ליצור קשר עם המועמד ולעדכן כי המשרה אוישה על ידי מועמד אחר.

אחר כך:

  • Add varSingleTask to varTasksToCreate

שלב 12 — אחרי הלולאה: עדכון מרוכז של כל המועמדויות

הוספת: Update Records
Record or Record Collection varApplicationsToReject

 

כך כל שאר המועמדויות של אותה משרה יעברו ל-Rejected.

שלב 13 — אחרי הלולאה: יצירת כל המשימות

הוסף: Create Records

How Many Records to Create

Multiple

Record Collection

varTasksToCreate

כדי לייצר משימה לכל מועמד שלא התקבל

סדר האלמנטים המלא ב-Flow

כך ה-Flow צריך להיראות:

Start
Get Related Job
Get Candidate (אם צריך)
Close Job
Send Acceptance Email
Get Other Applications
Loop Other Applications
Prepare Rejected Application
Prepare Rejection Task
→ חזרה ללולאה
Reject Other Applications
Create Follow Up Tasks


למה זה פתרון טוב גם עסקית וגם טכנית

  1. טריגר נכון — ההחלטה מתקבלת ברמת Application
  2. סגירת Job אוטומטית — מונעת המשך טיפול מיותר במשרה
  3. מייל למועמד שהתקבל — משרת חוויית מועמד
  4. דחייה אוטומטית לאחרים — שומרת על דאטה נקי
  5. Task למעקב אישי — עונה בדיוק לדרישה של פנייה אישית למועמדים שלא התקבלו
  6. Bulk-safe — בגלל שימוש ב-collections במקום פעולות DML בתוך הלולאה