שתף דרך


הגדרת סוכן הוצאות (תצוגה מקדימה)

חשוב

  • ‏‫‏‫זוהי תכונת Preview של מוכנות לסביבת ייצור.‬‬
  • תכונות Preview של מוכנות לסביבת ייצור כפופות לתנאי שימוש משלימים.

חל על Dynamics 365 Project Operations בשילוב עם ERP ו- Dynamics 365 Project Operations לייצור

סוכן ההוצאות מאחד בין יכולות מ- Microsoft Dynamics 365 Project Operations, יישומי פיננסים ותפעול, Microsoft Copilot Studio, ‏Power Automate ו- Dataverse כדי להפוך זרימות עבודה של עיבוד הוצאות לאוטומטיות באמצעות בינה מלאכותית. תכונה זו עוזרת לחסוך זמן ולהפחית את המאמץ הידתי בכך שהיא מאפשרת למערכת לעבד קבלות וליצור שורות הוצאות ודוחות הוצאות עבור משתמשים. היא משתמשת במחברים של Microsoft Power Platform לשילוב עם Outlook,‏ Microsoft Teams, לוחות שנה של משתמשים והסביבה של יישומי פיננסים ותפעול באמצעות ישויות Dataverse וירטואליות.

סוכן ההוצאות כולל זרימות מרובות, כשלוש מתוכן משמשות המתאמי ליבה:

  • עיבוד הודעות דואר אלקטרוני – זרימה זו סורקת תיקיית תיבת דואר שתצורתה נקבעה מדי שעה ומאחסן את הקבצים המצורפים כקבלות לא מצורפות ב- Dynamics 365 Finance.
  • חילוץ מזהי קבלה – זרימה זו אוספת קבלות לא משויכות ומפעילה את הסוכן לחלץ פרטי קבלה וליצור קו הוצאות לא מצורף.
  • דוח הוצאות בתהליך – זרימה זו ממירה שורות הוצאות לא פריטים קשורים ומפיקה דוחות הוצאות, בהתבסס על דוחות הקבוצה לפי תצורה שאתה מגדיר ביישום עבור כל ישות משפטית.

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

הסוכן מסתמך על כמה מחברים של Microsoft Power Platform. הפניה למחברים אלה מתבצעת אוטומטית בזרימות Power Automate המסופקות.

  • Outlook ‏(Office 365) – מחבר זה ניגש לתיבת הדואר המשותפת כדי לחלץ קבלות.
  • Dataverse (ישויות וירטואליות) – מחבר זה משתלב עם יישומי פיננסים ותפעול באמצעות ישויות וירטואליות.
  • Microsoft Copilot Studio – מחבר זה מפעיל מודלים של בינה מלאכותית כדי לחלץ פרטי קבלה.
  • Microsoft Teams – מחבר זה שולח כרטיסים מסתגלים עבור אינטראקציות משתמש (אם שילוב Teams זמין).
  • משתמשי Microsoft 365 – מחבר זה מאחזר את פרטי לוח השנה של המשתמש (אופציונלי, אם ניתוח הקבלות מודע להקשר).

דרישות מוקדמות

  1. סביבת כספים ותפעול: דרושה לך גירסה 10.0.44 לפחות (10.0.2263.167 ואילך) או 10.0.45 (10.0.2345.102 ואילך) של סביבת הכספים והפעולות כדי להתקין את הסוכן.
  2. תפקידים נדרשים כדי להגדיר את המשתמש סוכן הוצאות: כדי להשלים את השלבים במאמר זה, עליך להיות מנהל המערכת של הארגון ויש לך את התפקידים הבאים כדי להגדיר את המשתמש סוכן הוצאות להתקנת סוכן הוצאות.
מערכת תפקיד הערות
מרכז הניהול של Power Platform מנהל מערכת
  1. מעבר אל מרכז הניהול של Power Platform
  2. עוברים אל ניהול בחלונית הימנית. בוחרים סביבות ולאחר מכן בוחרים סביבה.
  3. בקטע גישה>משתמשים, בוחרים להציג הכול.
  4. בחרו משתמש ולאחר מכן בחרו ניהול תפקידים והוסיפו את התפקיד.
Finance and Operations מנהל מערכת
  1. פתחו את כתובת ה- URL של פיננסים ותפעול עבור הסביבה.
  2. עברו אל מודול>ניהולמערכת>משתמשים ובחרו משתמש.
  3. בחרו הוסף תפקיד – מנהל מערכת.
Microsoft 365 מנהל Exchange ומנהל משתמשים
  1. עברו אל מרכז הניהול של Microsoft 365.
  2. עברו אל משתמשים>משתמשים פעילים> ובחרו את המשתמש.
  3. בחרו נהל תפקידים ולאחר מכן, מתוך תפקידים , בחרו באפשרות מנהל Exchange.
  4. שמור את השינויים.
  5. בצעו את אותם השלבים כדי להוסיף את התפקיד מנהל משתמש.
מרכז הניהול של Teams מנהל Teams נדרש אם רוצים להפוך שילוב של Microsoft Teams לזמין

שלבים להגדרה של סוכן ההוצאות

כדי להתקין ולהגדיר את סוכן הוצאות, בצע את הפעולות הבאות:

  1. התקן את Copilot עבור יישומי פיננסים ותפעול.
  2. הפכו את תכונות הסוכן לזמינות בסביבה שלכם.
  3. צרו משתמש הוצאות לביצוע הסוכן.
  4. הגדירו תיבת דואר משותפת.
  5. הגדירו את סוכן ההוצאות.
  6. הפכו את סוכן ההוצאות לזמין ב- Microsoft Teams (אופציונלי - אם אתם זקוקים לשילוב של Microsoft Teams)

הסעיפים הבאים מתארים כל שלב בפירוט.

שלב 1: התקנת Copilot עבור יישומי פיננסים ותפעול

סוכן ההוצאות זמין כחלק מהחבילה Copilot ליישומי פיננסים ותפעול. לאחר התקנת חבילה זו בסביבה שלך, תקבל באופן אוטומטי את כל הנכסים הנדרשים, כולל הסוכן, משתני הסביבה ותזרימי Power Automate.

כדי להתקין את היישום הנדרש, בצע את הפעולות הבאות:

  1. עברו אל מרכז הניהול של Power Platform בדפדפן.
  2. מתוך רשימת הסביבות, בחרו את שם הסביבה שבו רוצים להתקין את האפליקציה.
  3. בדף הפרטים של הסביבה (NOT מהניווט הימני), עבור אל המקטע משאבים ובחר יישומי Dynamics 365.
  4. חפשו את Copilot ליישומי פיננסים ותפעול ברשימת האפליקציות של Dynamics 365. אם הוא כבר מותקן ויש עדכון זמין, בחרו בלחצן עדכון.
  5. אם האפליקציה אינה מופיעה תחת אפליקציות Dynamics 365, בחרו התקן אפליקציה , בחרו Copilot ליישומי פיננסים ותפעול ופעלו בהתאם להנחיות כדי להשלים את ההתקנה.

הערה

קבלו מידע נוסף על האופן שבו ניתן להפוך את Copilot לזמין בסביבה בקטע הפעלת יכולות של ‏Copilot ביישומי פיננסים ותפעול.

טיפ

כדי לבדוק אם החבילה הותקנה בהצלחה, בצע את הפעולות הבאות:

  1. עברו אל Power Apps Maker Portal > בחרו את הסביבה שלכם > בחרו 'פתרונות' > עיינו בהיסטוריה > חפשו ובחרו msdyn_ExpenseAI > פרטים.
  2. בדוק את השדה 'תוצאה '.
    1. אם התוצאה מציגה 'הצלחה', החבילה הותקנה כראוי.
    2. אם התוצאה אינה מציגה 'הצלחה', ההתקנה נכשלה.
  3. אם ההתקנה נכשלת, מחק msdyn_FnOCopilotAnchor (עיין בסעיף הסרת ההתקנה) והתקן שוב את Copilot עבור יישומי כספים ופעולות.

שלב 2: הפכו את תכונות הסוכן לזמינות בסביבה שלכם

לאחר התקנת חבילת האפליקציות של Copilot עבור כספים ופעולות, הפעל את סוכן ההוצאות מתוך סביבת Dataverse וכספים ותפעול.

הפיכת התכונה לזמינה ב- Dataverse

הפעל את דגל התכונה Copilot במרכז הניהול של Power Platform. כדי להפעיל את דגל התכונה Copilot, בצע את הפעולות הבאות:

  1. עבור אל מרכז הניהול של Power Platform.
  2. בחרו סביבות> בחרו את הסביבה שלכם >הגדרות>מוצר> בחרו תכונות.
  3. ודאו שדגל התכונה Copilot מופעל.

הפיכת תכונה לזמינה בסביבת פיננסים ותפעול

כדי להפעיל את הסוכן באפליקציות הכספים והפעולות, בצע את הפעולות הבאות:

  1. היכנסו לסביבת פיננסים ותפעול.
  2. עברו אל ניהול תכונות והפעילו את תכונת דף הבית המודרני וניהול סוכנים.
  3. כדי לקבוע את התצורה של סוכן הוצאות (ההגדרה היא לכל ישות משפטית), עברו אל ניהול הוצאות>הגדרה>כללי>פרמטרי ניהול הוצאות.
  4. בכרטיסיה סוכן ישות הוצאות , קבעו את תצורת הפרמטרים כפי שמוצג בטבלה הבאה.
פרמטרים ערך הערות
הפיכת סוכן ההוצאות לזמין עבור ישות משפטית נוכחית ‏‏כן העבירו את הלחצן הדו-מצבי לכן כדי להפוך את הסוכן לזמין עבור הישות המשפטית הנוכחית.
תדירות מדי יום או מדי שבוע קבעו את התצורה של התדירות ליצירת דוחות הוצאות באופן אוטומטי בארגון.
קיבוץ דוחות לפי נסיעה או פרוייקט קבעו את התצורה להוצאות קבוצתיות בהתבסס על פרוייקט או טיול.

שלב 3: יצירת משתמש של סוכן הוצאות לשימוש על ידי הסוכן

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

יצירת משתמש סוכן הוצאות במזהה Entra של Microsoft

  1. היכנס אל פורטל Azure.
  2. משירותי Azure הזמינים, בחרו מזהה Microsoft Entra.
  3. בקטע מזהה Microsoft Entra, צרו משתמש חדש.
  4. בחרו הוסף>משתמש>צור משתמש חדש והזינו את הפרטים הבאים.
    • שם ראשי של משתמש
    • בחרו את התחום הנכון
    • שם תצוגה
    • סיסמה
    • סימון החשבון כמופעל
  5. כדי להציג את הפרטים ולהשלים את תהליך יצירת המשתמש, בחרו סקירה + יצירה ובחרו צור.
  6. בדף המשתמש (ניהול > משתמשים), בחרו משתמש ואת דף פרטי התצוגה.
  7. בחרו ערוך מאפיינים, נווטו אל הכרטיסיה הגדרות ומלאו את מיקום השימוש המתאים.

הערה

בהתאם למדיניות הארגון, ייתכן שתידרשו לשנות את הסיסמה ולהגדיר אימות רב-גורמי (MFA). בצעו את השלבים כפי שאתם עושים בדרך כלל עבור שינוי סיסמה והגדרת MFA.

הקצו את הרישיונות הדרושים למשתמש של סוכן הוצאות

כדי להתקין בהצלחה את סוכן הוצאות, הקצה את הרשיונות הבאים למשתמש סוכן הוצאות:

  • רישיון Dynamics 365 Teams Members
  • Microsoft 365 Business Basic או כל רישיון המכסה את Microsoft Teams ו- Outlook (לדוגמה, Office 365 E5 עם Teams)
  • Power Apps Premium

כדי להקצות רשיונות, בצע את הפעולות הבאות:

  1. היכנסו למרכז הניהול של Microsoft 365 עם משתמש בעל גישה להקצאת רישיונות שהוא משתמש בעל מנהל רישיונות ואילך.
  2. בחרו חיוב>רישיונות>רישיון Dynamics 365 Teams Members.
  3. בחרו +הקצה רשיונות.
  4. חפשו את משתמש סוכן ההוצאות שנוצר בשלב הקודם.
  5. בחרו 'הקצה' כדי להשלים את הקצאת הרישיון.
  6. בצעו גם את שלבים 2 עד 5 עבור הרישיונות האחרים – Microsoft 365 Business Basic ו- Power Apps Premium.

הערה

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

הוספת המשתמש לסביבת Power Platform

כדי להוסיף את המשתמש לסביבת Power Platform, בצע את הפעולות הבאות:

  1. יש להתחבר אל מרכז הניהול של Power Platform ולבחור את הסביבה המתאימה.

    טיפ

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

  2. עברו אל גישה > משתמשים > להציג הכול.

  3. בחרו הוסף משתמש, הזינו את המשתמש הסוכן החדש שנוצר ובחרו הוסף.

  4. בדף ניהול תפקידי אבטחה , הוסף את התפקידים הבאים.

    • תפקיד סוכן AI להוצאות
    • מנהל התצורה של סוכן פיננסים ותפעול
    • אחראי על התאמה אישית של המערכת
  5. כדי לאשר את הקצאות התפקידים, בחרו שמור.

תפקידים אלה מספקים גישה לרכיבים Dataverse ו- Power Automate שהסוכן צריך כדי לפעול.

טיפ

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

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

הקצו את התפקיד הנדרש בסביבות הפיננסים והתפעול

כדי להקצות את התפקיד ExpenseAgentRole בסביבות הכספים והפעולות, בצע שלבים אלה:

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

הערה

ExpenseAgentRole זמין בגירסת יישומי פיננסים ותפעול מ- 10.0.44 (10.0.2263.81) ו- 10.0.45 (10.0.2345.6) וב- Copilot עבור יישומי פיננסים ותפעול גירסה 1.0.3121.1

הקצאת גישה לגישה לתיבת הדואר המשותפת

למשתמש הסוכן חייבת להיות הרשאת Mail.Read.Shared Microsoft Graph. הרשאה זו מאפשרת לסוכן לקרוא קבלות מתיבת הדואר המשותפת שתצורתה נקבעה במהלך ביצוע זרימה.

כדי להקצות גישה לגישה לתיבת הדואר המשותפת, בצע את הפעולות הבאות:

  1. עבור אל Microsoft Graph Explorer והיכנס באמצעות משתמש הסוכן שנוצר.
  2. בחרו את סמל המשתמש בפינה השמאלית העליונה > בחרו באפשרות הסכמה להרשאות.
  3. בחרו את התפריט הנפתח עבור דואר> חפשו Mail.Read.Shared> בחרו הסכמה ובחרו קבל.

סיכום של התפקידים הנדרשים עבור משתמש הסוכן שנוצר

סביבה תפקידים הערות
Dataverse
  • תפקיד סוכן AI להוצאות
  • מנהל התצורה של סוכן פיננסים ותפעול
  • אחראי על התאמה אישית של המערכת
  • התפקידים שהוזכרו מאפשרים לסוכן לקיים אינטראקציה עם זרימות Power Automate, משתני סביבה וישויות וירטואליות המחוברות ל- Dynamics 365 Finance
    Finance and Operations
  • ExpenseAgentRole
  • משתמש מערכת
  • תפקיד זה נדרש כדי שהסוכן ייצור וינהל ישויות הוצאות בסביבה של יישומי פיננסים ותפעול.

    הערה: ExpenseAgentRole זמין בגירסת יישומי הכספים והפעולות מ- 10.0.44 (10.0.2263.81) ו- 10.0.45 (10.0.2345.6) וב- Copilot ליישומי פיננסים ותפעול גירסה 1.0.3121.1
    גישה לתיבת דואר משותפת באמצעות בודק Graph Mail.Read.Shared הרשאת Microsoft Graph שמאפשרת לסוכן לקרוא קבלות מתיבת הדואר המשותפת שתצורתה נקבעה במהלך ביצוע זרימה

    שלב 4: הגדרת תיבת הדואר המשותפת

    סוכן ההוצאות משתמש בתיבת דואר משותפת כדי לקבל ולעבד הודעות דואר אלקטרוני של קבלה. משתמש בעל תפקיד מנהל Exchange צריך ליצור ולהגדיר תיבת דואר זו במרכז הניהול של Microsoft 365.

    כדי ליצור את תיבת הדואר המשותפת ולהגדיר אותה, בצע את הפעולות הבאות:

    1. היכנסו אל מרכז הניהול של Microsoft 365 באמצעות חשבון מנהל מערכת של Exchange.

    2. בחלונית הימנית, בחרו Teams & קבוצות>תיבות דואר משותפות.

      טיפ

      ייתכן שיהיה עליך לבחור הצג הכל כדי להרחיב את הרשימה המלאה.

    3. בחר הוסף תיבת דואר משותפת.

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

    5. בחר שמור שינויים.

    6. בקטע השלבים הבאים, בחרו הוסף חברים לתיבת דואר משותפת זו. (ייתכן שיחלפו מספר דקות עד שהנהלת החברים תהיה זמינה).

    7. בחרו הוספת חברים

    8. בחרו את המשתמש הסוכן שנוצר וכל אדם אחר שאמור לנטר את תיבת הדואר ובחרו הוסף.

    9. בחר סגור.

    הערה

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

    שלב 5: הגדרת סוכן ההוצאות

    יש שתי אפשרויות להגדרת סוכן ההוצאות:

    • אפשרות א': שימוש בקובץ Script של PowerShell (מומלץ)
    • אפשרות ב': ביצוע הגדרה ידנית ב- Power Apps (ללא PowerShell)

    חשוב

    לפני שתמשיך בהתקנת סוכן ההוצאות, ודא שהסוכן הוקצה בהצלחה ב- Microsoft Copilot Studio.

    כדי לוודא שהסוכן הוקצה בהצלחה, בצע את הפעולות הבאות:

    1. היכנסו אל Microsoft Copilot Studio ובחרו את הסביבה שלכם.
    2. עברו אל סוכנים וחפשו ExpenseAgent-Line ‏(Preview).
    3. ודא שלחצן פרסם זמין.
    4. אם אפשרות זו זמינה, המשיכו בהתקנה. אם האפשרות אינה זמינה, המתינו עד להקצאת הסוכן.
    5. חזרו על שלבים אלה כדי לוודא שסוכן ישות הוצאות (Preview) זמין.

    טיפ

    אם הקצאת משאבים לאפליקציה 'כספים ופעולות של Copilot' נמשכת יותר מ- 5-6 שעות, הסר את התקנת האפליקציה והתקן אותה מחדש כדי לפתור עיכובים אפשריים בהגדרה. לקבלת מידע נוסף, עיין בסעיף הסרת ההתקנה של סוכן הוצאות בסוף מאמר זה.

    הגדרה ידנית של הסוכן כרוכה ביצירה וקישור של חיבורים, הפעלת זרימות Power Automate ופרסום הפתרון. תהליך זה עשוי לצרוך זמן והוא נתון לשגיאות. כדי להפוך את ההגדרה לאוטומטית, השתמש בקובץ Script של PowerShell לאחר עדכון הפרמטרים הנדרשים.

    קובץ ה- Script של PowerShell הופך את המשימות הבאות לאוטומטיות:

    • עדכון משתני הסביבה הנדרשים.
    • מקשר חיבורי Microsoft Power Platform עם הפניות לחיבורי פתרונות.
    • הפיכת כל תזרימי Power Automate שסוכן הזמן וההוצאות דורש לזמינים.
    • מפרסם את סוכני Copilot.
    • מפרסם את הפתרון Dataverse.

    לפני הפעלת קובץ ה- Script, יש ליצור חיבורים מכיוון שעליכם לספק את מזהה החיבור עבור כל מחבר install.ps1 הקובץ. כדי ליצור חיבורים אלה, בצע שלבים אלה באמצעות משתמש הסוכן שנוצר.

    1. היכנס לפורטל יוצר היישומים של Power Apps באמצעות המשתמש הסוכן החדש שנוצר ובחר את הסביבה שלך.
    2. בחלונית הימנית, בחרו עוד ובחרו חיבורים.
    3. בחר חיבור חדש וחפש באמצעות שם החיבור מהטבלה הבאה (לדוגמה, Office 365 Outlook).
    4. בחרו את המחבר המתאים מהרשימה וצרו אותו.
    5. לאחר יצירת החיבור, שימו לב למשתמש שבו נוצר החיבור. באופן אידיאלי, זה אמור להיות מזהה משתמש הסוכן שנוצר. עדכן מזהה משתמש זה בקובץ ההתקנה שתיצור בשלב הבא.
    6. חזרו על שלבים 3 ו- 4 עבור כל אחד מהחיבורים הנדרשים הנותרים המפורטים בטבלה הבאה.
    שם החיבור תבניות כתובת URL של חיבור
    Office 365 Outlook https://make.powerapps.com/environments/environmentID/connections
    / shared_office365/connectionID/details
    משתמשי Office 365 https://make.powerapps.com/environments/environmentID/connections
    / shared_office365users/connectionID/details
    צוותי מיקרוסופט https://make.powerapps.com/environments/environmentID/connections
    / shared_teams/connectionID/details
    Microsoft Dataverse https://make.powerapps.com/environments/environmentID/connections
    / shared_commondataserviceforapps/connectionID/details
    ‏Microsoft Copilot Studio (‏Preview) https://make.powerapps.com/environments/environmentID/connections
    / shared_microsoftcopilotstudio/connectionID/details

    מידע הדרוש ליצירת קובץ ההתקנה

    כדי ליצור את קובץ ההתקנה - install.ps1, יש לקבל את המידע הבא זמין. (באפשרותך להפנות לטבלה הבאה לעיון.)

    פרמטר פרטים נוספים
    מזהה סביבת Dataverse הזינו את מזהה הסביבה שמתקבל ממרכז הניהול של Power Platform.
    ערך לדוגמה: xxxx-xxxx-xxxx-xxxxxxxxxx
    כתובת URL של סביבת Dataverse הזינו את כתובת ה- URL של הסביבה ממרכז הניהול של Power Platform.
    הערה: ודאו שיש https:// בהתחלה ללא קו נטוי '/' בסוף.
    ערך לדוגמה: https://org123.crm.contoso.com
    כתובת URL של מופע פיננסים ותפעול הזינו את פרטי סביבת הפיננסים והתפעול בתבנית הבאה.
    ערך לדוגמה: https://org123.contoso.com
    הערה: ודאו שיש https:// בהתחלה וללא קו נטוי '/' בסוף.
    OutlookFolderPath הזינו את נתיב התיקיה שנוצר בתיבת הדואר המשותפת. אם לא נוצרת תיקיה אחרת, היא מוגדרת כתיבת דואר נכנס כברירת מחדל.
    ערך לדוגמה: תיבת דואר נכנס
    כשם עבודה מומלצת, צור תיקיה נפרדת לניהול הוצאות
    מזהה כתובת תיבת דואר הזן את כתובת הדואר של תיבת הדואר המשותפת החדשה שנוצרה
    ערך לדוגמה: expenseagent@contoso.com
    שם חיבור של Microsoft Dataverse
    שם חיבור של Microsoft Copilot Studio
    שם החיבור של Microsoft Office Outlook
    שם החיבור של משתמשי Microsoft Office 365
    שם חיבור של Microsoft Teams
    הקלט לכל שמות החיבור הוא זהה והוא כתובת הדואר האלקטרוני של המשתמש של הסוכן שנוצר.

    ערך לדוגמה: createdexpenseagentuser@contoso.com

    יצירת קובץ ה- Script של ההתקנה

    צור קובץ Script של התקנה על-ידי העתקת הקוד הבא. הוסף את משתני הסביבה הדרושים ל- Script ולאחר מכן הפעל את קובץ ה- Script באמצעות PowerShell.

    הערה

    מקם את קובץ ה- Script של ההתקנה בשולחן העבודה המקומי. אל תאחסן אותו ב- One Drive.

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

    טיפ

    כאשר הכרחי = $true, PowerShell מבקש ממך להזין את הפרמטרים באופן אינטראקטיבי, כך שאין צורך לעדכן אותם ישירות בקובץ ה- Script.

    אם ברצונך להימנע מקלט ידני וברצונך להגדיר מראש את הפרמטרים בתוך קובץ ה- Script של ההתקנה, הגדר את Mandatory = $false במקטע Param של הקוד לדוגמה הבא.

    העתק את הקוד הבא לקובץ ה- Script של ההתקנה ושמור אותו בשם 'Install.ps1'. עדכן את המשתנים בשדות הפרמטר המתאימים במקטע הפרמטר. עליך לעדכן 10 משתנים.

    טיפ

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

    #requires -Version 7
    Param(
    
       [Parameter(Mandatory=$true, HelpMessage="Dataverse environment id")]
       [string]$DataverseEnvironmentId = "xxxx-xxxx-xxxx-xxx-xxxxxxxxxx", 
    
       [Parameter(Mandatory=$true, HelpMessage="Dataverse environment URL")]
       [string]$DataverseUrl = "https://org123.crm.dynamics.com",
    
       [Parameter(Mandatory=$true, HelpMessage="Finance and Operations instance URL")]
       [string]$D365FinanceAndOperationsUrl = "https://org123.operations.dynamics.com",
    
       [Parameter(Mandatory=$true, HelpMessage="OutlookFolderPath")]
       [string]$OutlookFolderPath = "Inbox",
    
       [Parameter(Mandatory=$true, HelpMessage="Mailbox Address Id")]
       [string]$MailboxAddressId = "expenseagent@contoso.com",
    
       [Parameter(Mandatory=$true, HelpMessage="Microsoft Dataverse connection name")]
       [string]$MicrosoftDataverseConnectionName = "createdexpenseagentuser@contoso.com",
    
       [Parameter(Mandatory=$true, HelpMessage="Microsoft Copilot Studio connection name")]
       [string]$MicrosoftCopilotStudioConnectionName = "createdexpenseagentuser@contoso.com",
       
       [Parameter(Mandatory=$true, HelpMessage="Microsoft Office Outlook connection name")]
       [string]$Office365OutlookConnectionName = "createdexpenseagentuser@contoso.com",
    
       [Parameter(Mandatory=$true, HelpMessage="Microsoft Office 365 Users connection name")]
       [string]$Office365UsersConnectionName = "createdexpenseagentuser@contoso.com",
    
       [Parameter(Mandatory=$true, HelpMessage="Microsoft Teams connection name")]
       [string]$MicrosoftTeamsConnectionName = "createdexpenseagentuser@contoso.com",
    
       [Parameter(Mandatory=$false, HelpMessage="Checks for bot Sync Errors and if there is provisioning required before Agent publish step")]
       [boolean]$CheckBotSyncStatusAndProvisionBots = $false
    
    )
    
    $flows = @(
        "expense entry retry check",
        "expense configuration",
        "get expense outlook folder",
        "generate expense report",
        "send expense report adaptive card",
        "auto match expenses",
        "process emails",
        "extract unattached receipt ids for copilot invocation",
        "extract unattached receipt output using dataverse plugin",
        "generate expense line",
        "generate expense line without project id and status id",
        "identify project ids",
        "user calendar events",
        "process expense report using copilot",
        "invoke expense agent for receipt processing"
    )
    
    
    $agents = @(
        "msdyn_ExpenseEntryAgent",
        "msdyn_ExpenseReportAgent"
    )
    
    
    # Check PS version
    if ($PSVersionTable.PSVersion.Major -lt 7) {
        Write-Error 'This script requires at least PowerShell version 7' -ErrorAction Stop
    }
    
    # Install the required modules if not already installed or if the version is not 1.0.40
    if (-not (Get-Module -ListAvailable -Name Microsoft.PowerApps.PowerShell | Where-Object { $_.Version -ge [Version]"1.0.40" })) {
        Write-Host "Microsoft.PowerApps.PowerShell version 1.0.40 not found. Installing..." -ForegroundColor Yellow
        Install-Module -Name Microsoft.PowerApps.PowerShell -RequiredVersion 1.0.40 -Force -AllowClobber -Scope CurrentUser
    } else {
        Write-Host "Microsoft.PowerApps.PowerShell version 1.0.40 is already installed." -ForegroundColor Green
    }
    
    if (-not (Get-Module -ListAvailable -Name Microsoft.PowerApps.Administration.PowerShell | Where-Object { $_.Version -ge [Version]"2.0.147" })) {
        Install-Module -Name Microsoft.PowerApps.Administration.PowerShell -RequiredVersion 2.0.147 -Force -AllowClobber -Scope CurrentUser
    }
    
    # Install the required modules if not already installed
    if (-not (Get-Module -ListAvailable -Name Az.Accounts | Where-Object { $_.Version -ge [Version]"5.0.1"})) {
        Install-Module -Name Az.Accounts -RequiredVersion 5.0.1 -Force -AllowClobber -Scope CurrentUser
    }
    
    # Import required modulesds
    Import-Module Az.Accounts
    Import-Module Microsoft.PowerApps.PowerShell
    Import-Module Microsoft.PowerApps.Administration.PowerShell
    
    # global variable declaration
    $filter = '$filter'
    
    
    function Get-AccessToken {
        # Retrieve the access token for the Dataverse environment
        $accessToken = (Get-AzAccessToken -ResourceUrl "$DataverseUrl" -AsSecureString).Token
        Write-Host "Access token for $userId retrieved successfully." -ForegroundColor Green
        return $accessToken
    }
    
    function Get-AccessTokenPlainText {
        param(
            [Parameter(Mandatory=$true, HelpMessage="Access token for authentication")]
            [securestring]$accessToken
        )
        # Retrieve the access token for the PVA environment
        $token = [Runtime.InteropServices.Marshal]::PtrToStringAuto(
        [Runtime.InteropServices.Marshal]::SecureStringToBSTR($accessToken))
        return $token
    }
    
    function update-EnvironmentVaribleValue {
            param (
            [string]$accessToken,
            [string]$env_key,
            [string]$env_value   # Access token for authentication
        )
    
        try 
        {
            # Get the environment variable definition
            $envVarDefinition = Invoke-RestMethod -Method Get -Uri "$DataverseUrl/api/data/v9.2/environmentvariabledefinitions?$filter=schemaname eq '$env_key'" -Headers @{
                Authorization = "Bearer $accessToken"
            }
    
            if ($envVarDefinition.value -ne $null) {
                $envVarDefId = $envVarDefinition.value[0].environmentvariabledefinitionid
    
                # Get the environment variable value record
                $filterValue = [System.Web.HttpUtility]::UrlEncode("_environmentvariabledefinitionid_value eq $envVarDefId")
                $envVarValue = Invoke-RestMethod -Method Get -Uri "$DataverseUrl/api/data/v9.2/environmentvariablevalues?$filter=$filterValue" -Headers @{
                    Authorization = "Bearer $accessToken"
                }
    
                if ($envVarValue.value -ne $null) {
                    $envVarValueId = $envVarValue.value[0].environmentvariablevalueid
                    # Update the environment variable value
                    Invoke-RestMethod -Method Patch -Uri "$DataverseUrl/api/data/v9.2/environmentvariablevalues($envVarValueId)" -Headers @{
                        Authorization = "Bearer $accessToken"
                        "Content-Type" = "application/json"
                    } -Body (@{ value = $env_value } | ConvertTo-Json -Depth 1)
                    Write-Host "Environment variable updated with name $env_key and value $env_value" -ForegroundColor Green
                } else {
                    Write-Host "Environment variable value not found for $env_key. Skipping..." -ForegroundColor Red
                }
            } 
            else {
                Write-Host "Environment variable definition not found for $env_key. Skipping..." -ForegroundColor Yellow
            }
      }
      catch {
            Write-Host "Failed to update environment variable $env_key. Error: $($_)" -ForegroundColor Red
            throw $_  # Re-throw the error to stop the script if this step is critical
        }
    
    }
    
    function update_EnvironmentVariablesForExpense {
            param (
            [string]$accessToken   # Access token for authentication
        )
    
        write-host "Updating environment variables..." -ForegroundColor Yellow
    
        try 
        {
            update-EnvironmentVaribleValue -accessToken $accessToken -env_key "msdyn_ExpenseFnoInstanceUrl" -env_value $D365FinanceAndOperationsUrl
            update-EnvironmentVaribleValue -accessToken $accessToken -env_key "msdyn_ExpenseAgentOutlookFolderPath" -env_value $OutlookFolderPath
            update-EnvironmentVaribleValue -accessToken $accessToken -env_key "msdyn_ExpenseAgentMailboxAddressId" -env_value $MailboxAddressId
            
        }
        Catch {
            Write-Host "Failed to update environment variables. Error: $($_)" -ForegroundColor Red -ErrorAction Stop
        }
    }
    
    # Function to publish the solution
    function Publish-Solution {
        param (
            [string]$accessToken
        )
    
        Write-Host "Publishing All" -ForegroundColor Yellow
    
        # Construct the API endpoint for publishing the solution
        $uri = "$DataverseUrl/api/data/v9.2/PublishAllXml"
    
    
        # Make the API call
        try {
            Invoke-RestMethod -Method Post `
                -Uri $uri `
                -Headers @{
                    Authorization = "Bearer $accessToken"
                    "Content-Type" = "application/json"
                }
    
            Write-Host "Publish All - Success!" -ForegroundColor Green
        } catch {
            Write-Host "Failed to publish. Error: $($_.Exception)" -ForegroundColor Red
            
        }
    }
    
    function Get-FlowGuidByName {
        param (
            [string]$accessToken,   # Access token for authentication
            [string]$flowName       # Name of the flow to search for
        )
    
        #Write-Host "Retrieving GUID for flow: $flowName" -ForegroundColor Yellow
    
        # Construct the API endpoint with a filter for the flow name
        $encodedFlowName = [System.Web.HttpUtility]::UrlEncode($flowName)
        $uri = "$DataverseUrl/api/data/v9.2/workflows?$filter=name eq '$encodedFlowName'"
    
        try {
            # Make the API call
            $response = Invoke-RestMethod -Method Get `
                -Uri $uri `
                -Headers @{
                    Authorization = "Bearer $accessToken"
                    "Content-Type" = "application/json"
                }
    
            # Check if the flow was found
            if ($response.value.Count -gt 0) {
                $flow = $response.value[0]
                Write-Host "Flow found: $($flow.name) with GUID: $($flow.workflowid)" -ForegroundColor Green
                return $flow.workflowid
            } else {
                Write-Host "No flow found with the name: $flowName" -ForegroundColor Red
                return $null
            }
        } catch {
            Write-Host "Failed to retrieve flow GUID. Error: $($_.Exception.Message)" -ForegroundColor Red
            return $null
        }
    }
    
    
    # Function to activate a Power Automate flow
    function Activate-Flow {
        param (
            [string]$DataverseUrl,  # Dataverse environment URL
            [string]$accessToken,   # Access token for authentication
            [string]$flowId         # GUID of the flow to activate
        )
    
        # Construct the request body
        $body = @{
            "statecode" = 1  # Activated
            "statuscode" = 2 # Activated
        } | ConvertTo-Json -Depth 1 -Compress
    
        # Construct the API endpoint
        $uri = "$DataverseUrl/api/data/v9.2/workflows($flowId)"
    
        # Make the API call
        try {
            Invoke-RestMethod -Method Patch `
                -Uri $uri `
                -Headers @{
                    Authorization = "Bearer $accessToken"
                    "Content-Type" = "application/json"
                } `
                -Body $body
    
            Write-Host "Flow activated successfully." -ForegroundColor Green
        } catch {
            Write-Host "Failed to activate flow. Error: $($_.Exception.Message)" -ForegroundColor Red
        }
    }
    
    function Get-ConnectionRefIdFromLogicalName  {
        param (
            [string]$accessToken,
            [string]$connectionRefLogicalName
        )
        $uri = "$DataverseUrl/api/data/v9.2/connectionreferences?$filter=connectionreferencelogicalname eq '$connectionRefLogicalName'"
        $response = Invoke-RestMethod -Method Get `
        -Uri $uri `
        -Headers @{
            Authorization = "Bearer $accessToken"
            "Content-Type" = "application/json"
        }
    
        if ($response -ne $null) {
            write-host "Connection reference id found: $($response.value[0].connectionreferenceid) " -ForegroundColor Green
            return $response.value[0].connectionreferenceid
        }
        else {
            Write-Host "No connection reference found for logical name: $connectionRefLogicalName" -ForegroundColor Red
            return $null
        }
    }
    
    function Get-ConnectionId {
        param (
            [string]$userProvidedName,
            [string]$providerName
        )
    
        try {
            $matchedConnectionId = $null
            # Added -ErrorAction Stop to ensure the catch block is triggered on failure
            $connections = Get-PowerAppConnection -EnvironmentName $DataverseEnvironmentId -ConnectorNameFilter $providerName -ErrorAction Stop
            
            foreach ($con in $connections) {
                if (($con.ConnectionName -eq $userProvidedName) -or ($con.DisplayName -eq $userProvidedName)) {
                    $matchedConnectionId = $con.ConnectionName
                    break
                }
            }
    
            if ($null -eq $matchedConnectionId) {
                # Use 'throw' to create a terminating error that the calling function can catch
                throw "Unable to find connection '$userProvidedName' for provider '$providerName'."
            }
    
            return $matchedConnectionId
        }
        catch {
            # Catch any errors from Get-PowerAppConnection or the 'throw' statement above
            Write-Error "Failed to get connection ID for '$userProvidedName'. Error: $_"
            throw # Re-throw the error to stop the script if this step is critical
        }
    }
    
    function Get-ConnectionReferenceId {
        param(
            [string]$connectionReferenceLogicalName,
            [securestring]$accessToken
        )
    
        try {
            $uri = "$DataverseUrl/api/data/v9.2/connectionreferences?$filter=connectionreferencelogicalname eq '$connectionReferenceLogicalName'"
            
            # Added -ErrorAction Stop for clarity, though Invoke-RestMethod often terminates on HTTP errors
            $response = Invoke-RestMethod -Method Get -Uri $uri -Authentication Bearer -Token $accessToken -ContentType 'application/json' -ErrorAction Stop
                
            if ($null -eq $response -or $response.value.Count -eq 0) {
                throw "Connection reference not found for logical name '$connectionReferenceLogicalName'."
            }
    
            $connectionReferenceDisplayName = $response.value[0].connectionreferencedisplayname
            $connectionReferenceId = $response.value[0].connectionreferenceid
    
            Write-Host "updating connection $connectionReferenceDisplayName for logical name $connectionReferenceLogicalName)"
            return $connectionReferenceId
        }
        catch {
            Write-Error "Failed to get connection reference ID for '$connectionReferenceLogicalName'. Error: $_"
            throw # Re-throw to notify the calling function
        }
    }
    
    function Set-ConnectionReferenceConnection {
        param (
            [string]$connectionReferenceLogicalName,
            [string]$userProvidedConnectionName,
            [string]$providerName,
            [securestring]$accessToken
        )
    
        try {
    
            # These functions will now throw terminating errors if they fail
            $connectionReferenceId = Get-ConnectionReferenceId -connectionReferenceLogicalName $connectionReferenceLogicalName -accessToken $accessToken
            $connectionId = Get-ConnectionId -userProvidedName $userProvidedConnectionName -providerName $providerName
    
            $body = @{
                "connectionid" = "$connectionId"
            } | ConvertTo-Json -Depth 1
    
            $uri = "$DataverseUrl/api/data/v9.2/connectionreferences($connectionReferenceId)"
            # Write-Host "Updating connection reference URI: $uri with connection id $connectionId"
    
            Invoke-RestMethod -Method Patch -Uri $uri -Authentication Bearer -Token $accessToken -ContentType 'application/json' -Body $body -ErrorAction Stop
        
            Write-Host "Connection reference updated successfully." -ForegroundColor Green
        }
        catch {
            # This block will catch errors from any of the functions called within the try block
            Write-Error "Failed to set connection reference for '$connectionReferenceLogicalName'. Error: $_"
            throw
        }
    }
    
    function Activate-Flows {
        param (
            [string]$accessToken,
            [array]$expenseAIFlows
        )
    
        foreach ($flowName in $expenseAIFlows) {
             Write-Host "Activating flow: $flowName" -ForegroundColor Yellow
    
            # Call the Get-FlowGuidByName function to get the flow GUID
            $flowGuid = Get-FlowGuidByName -dataverseUrl $DataverseUrl -accessToken $accessToken -flowName $flowName
    
            if ($flowGuid -ne $null) {
                # Write-Host "Flow Name: $flowName, Flow GUID: $flowGuid" -ForegroundColor Green
                Activate-Flow -dataverseUrl $DataverseUrl -accessToken $accessToken -flowId $flowGuid
                # Write-Host "Flow Name: $flowName, Flow GUID: $flowGuid Activated" -ForegroundColor Green
            } else {
                Write-Host "Flow Name: $flowName not found." -ForegroundColor Red
            }
        }
    }
    
    
    # Function to retrieve the Agent ID by name
    function Get-AgentIdBySchemaName {
        param (
            [string]$DataverseUrl,
            [string]$accessToken,
            [string]$agentSchemaName
        )
    
        Write-Host "Retrieving agent ID for agent schema: $agentSchemaName" -ForegroundColor Yellow
    
        # Construct the API endpoint to retrieve the bot
        $uri = "$DataverseUrl/api/data/v9.2/bots?$filter=schemaname eq '$agentSchemaName'"
    
        try {
            # Make the API call
            $response = Invoke-RestMethod -Method Get -Uri $uri -Headers @{
                Authorization = "Bearer $accessToken"
                "Content-Type" = "application/json"
            }
    
            if ($response.value.Count -gt 0) {
                $agentId = $response.value[0].botid
                return $agentId
            } else {
                Write-Host "No agent found with the name: $agentSchemaName" -ForegroundColor Red
                return $null
            }
        } catch {
            Write-Host "Failed to retrieve agent ID. Error: $($_)" -ForegroundColor Red
            return $null
        }
    }
    
    function Check-BotSyncErrors {
            param (
            [string]$DataverseUrl,
            [string]$accessToken,
            [string]$botId
        )
    
        Write-Host "Retrieving Sync Status for bot ID: $botId" -ForegroundColor Yellow
    
        # Construct the API endpoint to retrieve the bot
        $uri = "$DataverseUrl/api/data/v9.2/bots($botId)"
        try {
            # Make the API call
            $response = Invoke-RestMethod -Method Get -Uri $uri -Headers @{
                Authorization = "Bearer $accessToken"
                "Content-Type" = "application/json"
            }
    
            if ($null -ne $response.synchronizationstatus) {
                # Parse the JSON string in synchronizationstatus
                $syncStatusObj = $response.synchronizationstatus | ConvertFrom-Json
                $state = $syncStatusObj.currentSynchronizationState.state
                $provisioningStatus = $syncStatusObj.currentSynchronizationState.provisioningStatus
    
                Write-Host "Synchronization State: $state" -ForegroundColor Green
                Write-Host "Provisioning Status: $provisioningStatus" -ForegroundColor Green
    
                if ( $state -contains "Error" -or $provisioningStatus -contains "Error") {
                    Write-Host "Bot has synchronization errors." -ForegroundColor Red
                    return 0
                } else {
                    if ( $state -eq "Synchronized" -or $state -eq 'Synchronizing' -and ($provisioningStatus -eq  "Provisioned" -or $provisioningStatus -eq  "ProvisionedWithoutRegistration")) {
                        Write-Host "Bot synchronization is done." -ForegroundColor Yellow
                        return 1
                    } else {
                        Write-Host "Bot synchronization is in progress." -ForegroundColor Green
                        return 2
                    }
                }
            } else {
                Write-Host "No synchronization status found for bot ID: $botId" -ForegroundColor Red
                return $null
            }
        } catch {
            Write-Host "Failed to retrieve agent ID. Error: $($_)" -ForegroundColor Red
            return $null
        }
    }
    
    
    # Function to provision a PVA bot
    function Provision-Agent {
        param (
            [string]$DataverseUrl,
            [string]$accessToken,
            [string]$agentId
        )
    
        # Construct the API endpoint for publishing the bot
        $uri = "$DataverseUrl/api/data/v9.2/bots($agentId)/Microsoft.Dynamics.CRM.PvaProvision"
    
        try {
            # Make the API call
            Invoke-RestMethod -Method Post -Uri $uri -Headers @{
                Authorization = "Bearer $accessToken"
                "Content-Type" = "application/json"
            }
    
            Write-Host "Agent Provisioning successfully!" -ForegroundColor Green
            # Add 30 second delay to allow the publish process to complete
            Start-Sleep -Seconds 30
            return $true
        } catch {
            Write-Host "Failed to Provision Agent. Error: $($_.Exception.Message)" -ForegroundColor Red
        }
        return $false
    }
    
    
    # Function to publish a PVA bot
    function Publish-Agent {
        param (
            [string]$DataverseUrl,
            [string]$accessToken,
            [string]$agentId
        )
    
        Write-Host "Publishing agent with ID: $agentId" -ForegroundColor Yellow
    
        # Construct the API endpoint for publishing the bot
        $uri = "$DataverseUrl/api/data/v9.2/bots($agentId)/Microsoft.Dynamics.CRM.PvaPublish"
    
        try {
            # Make the API call
            Invoke-RestMethod -Method Post -Uri $uri -Headers @{
                Authorization = "Bearer $accessToken"
                "Content-Type" = "application/json"
            }
    
            Write-Host "Agent published successfully!" -ForegroundColor Green
            # Add 30 second delay to allow the publish process to complete
            Start-Sleep -Seconds 30
        } catch {
            Write-Host "Failed to publish Agent. Error: $($_.Exception.Message)" -ForegroundColor Red
        }
    }
    
    function Publish-Agents {
        param (
            [string]$accessToken,
            [array]$agentSchemas
        )
    
        if (-not $agentSchemas -or $agentSchemas.Count -eq 0) {
            Write-Host "No agent schemas provided. Skipping agent publishing." -ForegroundColor Yellow
            return
        }
    
        foreach ($agentSchema in $agentSchemas) {
            #Write-Host "Publishing agent schema: $agentSchema" -ForegroundColor Yellow
    
            try {
                    # Construct the API endpoint for publishing the agent schema
                    $agentId = Get-AgentIdBySchemaName -dataverseUrl $DataverseUrl -accessToken $accessToken -agentSchemaName $agentSchema
    
                    if ($agentId -ne $null) {
                        # check for sync errors
                        if ($CheckBotSyncStatusAndProvisionBots) {
                            $syncStatus = Check-BotSyncErrors -dataverseUrl $DataverseUrl -accessToken $accessToken -botId $agentId
                            if (0 -eq $syncStatus) {
                                Write-Host "Agent has sync errors. Skipping the publish process. Please check the bot: $agentId details" -ForegroundColor Red
                                continue
                            } elseif (2 -eq $syncStatus) {
                                Write-Host "Agent synchronization is still in progress. reprovisioning the agent." -ForegroundColor Yellow
                                if (Provision-Agent -dataverseUrl $DataverseUrl -accessToken $accessToken -agentId $agentId -eq $false) {
                                    Write-Host "Agent reprovisioning failed. Skipping the publish process. Please check the bot: $agentId details" -ForegroundColor Red
                                    continue
                                }
                            } else {
                                Write-Host "Agent synchronization is done. Proceeding to publish." -ForegroundColor Green
                            }
                        }
                        # Step 4: Publish the bot
                        Publish-Agent -dataverseUrl $DataverseUrl -accessToken $accessToken -agentId $agentId
                    } else {
                        Write-Host "Agent not found. Cannot proceed with publishing.Skipping the step" -ForegroundColor Yellow
                    }
            }
            catch {
                Write-Host "An error occurred while publishing agent schema: $agentSchema. Error: $_" -ForegroundColor Red
            }
        }
    
    }
    
    
    # Main script execution
    try {
    
        $expenseAIFlows = $flows
        $agentSchemas = $agents
    
        # Step 1: Interactive login to Azure
        Connect-AzAccount -UseDeviceAuthentication
        $accessToken = Get-AccessToken
        $accessTokenPlainText = Get-AccessTokenPlainText -accessToken $accessToken
    
        # Step 2: Setup ennviornment variables
        update_EnvironmentVariablesForExpense -accessToken $accessTokenPlainText 
        Write-Host "Environment variables updated successfully!" -ForegroundColor Green
    
        # Step 3: Check active connections
        Set-ConnectionReferenceConnection -userProvidedConnectionName $MicrosoftDataverseConnectionName -providerName "/providers/Microsoft.PowerApps/apis/shared_commondataserviceforapps" -connectionReferenceLogicalName "msdyn_sharedcommondataserviceforapps_2c2d4" -accessToken $accessToken
    
        Set-ConnectionReferenceConnection -userProvidedConnectionName $MicrosoftCopilotStudioConnectionName -providerName "/providers/Microsoft.PowerApps/apis/shared_microsoftcopilotstudio" -connectionReferenceLogicalName "msdyn_sharedmicrosoftcopilotstudio_26d9d" -accessToken $accessToken
    
        Set-ConnectionReferenceConnection -userProvidedConnectionName $Office365OutlookConnectionName -providerName "/providers/Microsoft.PowerApps/apis/shared_office365" -connectionReferenceLogicalName "msdyn_sharedoffice365_9b471" -accessToken $accessToken
    
        Set-ConnectionReferenceConnection -userProvidedConnectionName $MicrosoftTeamsConnectionName -providerName "/providers/Microsoft.PowerApps/apis/shared_teams" -connectionReferenceLogicalName "msdyn_sharedteams_8ea9c" -accessToken $accessToken
    
        Set-ConnectionReferenceConnection -userProvidedConnectionName $Office365UsersConnectionName -providerName "/providers/Microsoft.PowerApps/apis/shared_office365users" -connectionReferenceLogicalName "msdyn_sharedoffice365users_909b9" -accessToken $accessToken
        
    
        # Step 4: Activate flows
        Activate-Flows -accessToken $accessTokenPlainText -expenseAIFlows $expenseAIFlows
    
        # step 5: publish the agents
        Publish-Agents -accessToken $accessTokenPlainText -agentSchemas $agentSchemas
    
        # Step 6: Publish the solution 
        Publish-Solution -accessToken $accessTokenPlainText
    
        Write-Host "Agent setup completed successfully!" -ForegroundColor Green
    
    } catch {
        Write-Host "An error occurred: $_" -ForegroundColor Red
    }
    
    

    כדי להפעיל את קובץ PowerShell, בצע את הפעולות הבאות:

    1. פתח את PowerShell (נדרשת גירסה מינימלית - PowerShell 7).
    2. עבור אל המיקום שבו שמרת את הקובץ. (השתמשו ב<מיקום הקובץ> command cd).
    3. הפעילו את קובץ ה- Script של ההתקנה. (השתמשו בפקודה '.\Install.ps1').
    4. בצע את ההוראות כדי להיכנס ל- Azure.
    5. לאחר שתיכנס, ייתכן שתצטרך לאשר פעם נוספת. (השתמשו במזהה המשתמש של הסוכן שנוצר.).

    המתן להפעלת קובץ ה- Script לחלוטין וחפש את ההודעה הגדרת סוכן הושלמה בהצלחה!

    הערה

    קובץ ה- Script הקודם מבצע פעולות אלה:

    • הגדרת משתני סביבה.
    • מאמת ומקשר הפניות לחיבור.
    • הפעלת זרימות Power Automate.
    • מפרסם את סוכני Copilot הנדרשים.
    • מפרסם את הפתרון Dataverse.

    לאחר שקובץ ה- Script פועל בהצלחה, סוכן ההוצאות מוגדר באופן מלא ומוכן לשימוש.

    אפשרות ב': הגדרה ידנית ב- Power Apps (ללא PowerShell)

    אם אינך מעוניין להשתמש בקובץ ה- Script של PowerShell, באפשרותך להגדיר באופן ידני את סוכן ההוצאות באמצעות Power Apps. תהליך זה כולל עדכון משתני סביבה, הפעלת זרימות Power Automate ופרסום הפתרון.

    עדכון משתני סביבה

    כדי לעדכן משתני סביבה, בצע את הפעולות הבאות:

    1. היכנסו אל Power Apps ובחרו את הסביבה שלכם.

    2. בחרו פתרונות ולאחר מכן פתחו את פתרון ברירת המחדל (או את הפתרון שבו הסוכן מותקן).

    3. עברו אל משתני סביבה והגדירו את הערכים הבאים.

      שם משתנה תיאור
      נתיב תיקיית סוכן ההוצאות ב-Outlook ציינו את נתיב התיקיה לניטור בתיבת הדואר המשותפת (כברירת מחדל, תיבת דואר נכנס).
      מזהה כתובת תיבת דואר משותפת של סוכן הוצאות ציינו את כתובת הדואר האלקטרוני של תיבת הדואר המשותפת. כדי להשתמש בתיבת הדואר של המשתמש המחובר, הזינו NA.
      כתובת ה-URL של מופע פיננסים ותפעול ציינו את כתובת ה- URL של סביבת יישומי פיננסים ותפעול (לדוגמה, https://org123.contoso.com).

    הפעלת זרימות Power Automate

    סוכן ההוצאות מסתמך על זרימות Power Automate הבאות:

    • בדיקת ניסיון חוזר לישות הוצאות
    • תצורת הוצאות
    • קבלת תיקיית Outlook של הוצאות
    • הפקת דוח הוצאות
    • שליחת כרטיס מסתגל של דוח הוצאות
    • הוצאות התאמה אוטומטית
    • עיבוד הודעות דואר אלקטרוני
    • חילוץ מזהי קבלה בלתי מחוברים להפעלת Copilot
    • חילוץ פלט קבלה לא מצורף באמצעות תוסף Dataverse
    • יצירת שורת הוצאות
    • יצירת שורת הוצאות ללא מזהה פרוייקט ומזהה מצב
    • זיהוי מזהי פרוייקט
    • אירועי לוח שנה של משתמש
    • עיבוד דוח הוצאות באמצעות Copilot
    • הפעל סוכן הוצאות לעיבוד קבלות

    כדי להפוך את הזרימות לזמינות, בצע את הפעולות הבאות:

    1. היכנסו אל Power Automate ובחרו את הסביבה שלכם.

    2. ‏‏בחר הזרימות שלי.

    3. עבור כל אחת מ- 15 הזרימות ברשימה הקודמת, בצע את הפעולות הבאות:

      1. אתרו את הזרימה.
      2. בחר Edit.
      3. עברו לתצוגת המעצב הישן על-ידי ביטול האפשרות מעצב חדש.
      4. בצעו אימות של החיבורים הנדרשים (עד להופעת סימני ביקורת ירוקים).
      5. בחר המשך ולאחר מכן בחר שמור.
      6. בחר הפעל כדי להפעיל את הזרימה.

    פרסמו את הפתרון

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

    1. ב- Power Apps, עברו אל פתרונות.
    2. בחר את הסביבה והפתרון שלך.
    3. בחר פרסם את כל ההתאמות האישיות.

    לאחר השלמת שלבים אלה, סוכן ההוצאות מוגדר באופן מלא ומוכן לשימוש.

    שלב 6: הפיכת סוכן ההוצאות לזמין ב- Microsoft Teams (אופציונלי)

    כדי להפוך תקשורת מבוססת-Teams לזמינה עבור סוכן ההוצאות, הוסף את ערוץ Teams לסוכן ב- Power Apps. לאחר מכן, הסוכן יוכל לשלוח כרטיסים גמישים באמצעות Teams.

    הפיכת ערוץ Teams לזמין

    כדי להפוך את ערוץ Teams לזמין, בצע את הפעולות הבאות:

    1. היכנסו אל Copilot Studio ובחרו את הסביבה הנכונה.
    2. בכרטיסיה סוכנים , בחרו סוכן ישות הוצאות.
    3. בתצוגת הסוכן, בכרטיסיה ערוצים , בחרו Teams ו- Microsoft 365 Copilot.
    4. בחרו הוסף ערוץ כדי לאפשר שילוב של Teams ובצעו את השלבים במקטע הגדרת זמינות של אפליקציית Teams כדי לקבוע עם מי לשתף את האפליקציה.

    מידע נוסף זמין בקטע פתיחת לוח התצורה עבור ערוץ Teams + Microsoft 365.

    קביעת תצורה של זמינות אפליקציית Teams

    כדי לקבוע את התצורה של זמינות האפליקציות של Teams, בצע את הפעולות הבאות:

    1. לאחר יצירת היישום Teams, בחר אפשרויות זמינות.

    2. בחרו עם מי לשתף את האפליקציה:

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

    פרסום האפליקציה במרכז הניהול של Teams

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

    1. היכנס למרכז הניהול של Teams.
    2. עבור אל אפליקציית Teams ניהול > יישומים. חפש את "הוצאות" ובחר את היישום 'סוכן רישום הוצאות ' שבו מצב היישום חסום.
    3. בחרו פרסם כדי לבטל את נעילת האפליקציה. לאחר שפעולה הפרסום מסתיימת בהצלחה, ודא שמצב היישום משתנה לבטל את החסימה.

    מידע נוסף: התחברות וקביעת תצורה של סוכן עבור Teams ו- Microsoft 365.

    לאחר השלמת שלבים אלה, סוכן ההוצאות שלך מוכן לשימוש.

    הערה

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

    הסרת ההתקנה של סוכן הוצאות

    כדי להסיר את ההתקנה של סוכן ההוצאות, בצע את הפעולות הבאות:

    1. היכנס לפורטל היוצר של Microsoft Power Apps.
    2. בחרו פתרונות, חפשו msdyn_ExpenseAI, בחרו את שלוש הנקודות ובחרו מחק.
    3. חפש msdyn_FnOCopilotAnchor ומחק את הפתרון.