מקרה בוחן · פלטפורמה לתפעול תוכניות חינוך · ⁦2019–2026⁩

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

גוף ארצי שמפעיל תוכניות חינוך מריץ קבוצות העשרה בבתי ספר ברחבי הארץ. בקבוצות עובדים אנשי חינוך בשטח, שמקבלים שכר לפי שעה או לפי יחידה. הובלתי את הפלטפורמה שמתכננת את התוכניות, אוספת כל שעה שמדווחת בשטח, מעבירה אותה בשרשרת אישורים רב־שלבית ומפיקה את דוחות השכר והתקציב. היא התחילה על ⁦.NET Core 2⁩.2 ב־⁠2019, והיום היא רצה על ⁦.NET 8⁩ בגרסת LTS.

⁦.NET 8⁩ / ⁦ASP.NET Core⁩EF Core 8SQL ServerSSRSAngularAngular Material · RTLJWTPython tooling
לקוח
מפעיל ישראלי של תוכניות חינוך (חסוי)
התפקיד שלי
ראש צוות, ארכיטקט ומפתח בפועל
ציר זמן
דצמבר 2019 – ספטמבר 2026, בפרודקשן לאורך כל התקופה
סטטוס
באוויר
במבט מהיר
2.2 עד 8גרסת ⁦.NET⁩, שעודכנה ב־⁠3 מיגרציות גדולות בלי שכתוב
1 עד 0פניות למסד הנתונים לבדיקת הרשאות בכל בקשה, ברגע שהנתון במטמון. התראות שינוי מ־⁠SQL Server מנקות את המטמון.
12 עד ⁦3×⁩4JOIN-ים על אוספים בטעינת פרויקט לשכפול, פוצלו כדי לעצור cartesian explosion
48טבלאות שנמחקות לפי סדר מפתחות זרים, במסגרת ארכוב שנוצרת אוטומטית, בטרנזקציה אחת
4 סביבותמכוסות בסקריפט PowerShell אחד שפורס 11 דוחות SSRS. קודם כל סביבה נפרסה ידנית.
474נקודות קצה REST מעל 128 טבלאות, 156 Views ו־⁠30 פרוצדורות שמורות
9 · 105תפקידים והרשאות מפורטות, שנאכפים לפי פרויקט בשרת ובלקוח
⁦5,200+⁩קומיטים ב־⁠4 ריפוזיטוריז לאורך 6.75 שנים
הבעיה

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

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

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

מה היה באחריותי

ארכיטקטורה, צוות והזנב הארוך

  • הובלתי את הצוות והייתי אחראי על הארכיטקטורה: ה־⁠API, מסד הנתונים, אפליקציית הניהול, אפליקציית הדיווח מהשטח ושכבת הדוחות.
  • כתבתי בעצמי את רוב הקוד: תהליך האישורים, מודל ההרשאות, הוולידציות, ייבוא וייצוא Excel ועבודת הביצועים.
  • שמרתי על הסטאק מעודכן: ⁦.NET Core 2⁩.2 → 3.1 → 6 → 8, שדרוגי EF Core ו־⁠scaffold מחודש של מסד הנתונים.
  • הובלתי את מבצע הביצועים ב־⁠2022 ואת עבודת האבטחה ושמירת הנתונים ב־⁠2026.
  • שמרתי על קצב אספקה קבוע מול הלקוח לאורך 6.75 שנים של בקשות שינוי.
מה בניתי

חמישה רכיבים, מקור אמת אחד

אפליקציית ניהול

Angular עם Material, בעברית ובאנגלית עם תמיכה מלאה ב־⁠RTL. יש בה 212 קומפוננטות ב־⁠59 מודולים בטעינה עצלה: פרויקטים, הקצאות, קבוצות, תלמידים, מוסדות, דיווחים, אישורים, מסמכים, טפסים דינמיים והודעות. כל רשימה משתמשת בטבלה גנרית אחת, וכל רשימה נפתחת מבוססת מטא־דאטה.

אפליקציית דיווח מהשטח

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

API ב־⁠⁦ASP.NET Core⁩

474 נקודות קצה ב־⁠16 קונטרולרים ושכבת שירותים. ה־⁠API מטפל ב־⁠JWT עם access ו־⁠refresh, בהרשאות ברמת ישות ובתהליך הסטטוסים של הדיווחים, מבצע ולידציה מול מכסות ולוחות שנה, ומטפל ב־⁠105 סוגי ייצוא ל־⁠Excel ובייבוא המוני מ־⁠Excel.

מודל SQL Server

פרויקט סכמה Database-first עם 128 טבלאות, 156 Views, ‏30 פרוצדורות שמורות ו־⁠333 הגדרות אינדקס, וגם טבלאות Audit והיסטוריה. Schema compare שומר על סביבות Dev,‏ QA,‏ Staging ו־⁠Production מסונכרנות.

דוחות

11 דוחות SSRS: תקציב מול ביצוע, שכר, נוכחות, פעילות וחריגות ממכסה. הם נפתחים עם מפתחות דוח חד־פעמיים שה־⁠API מנפיק, ותוקפם פג אחרי 60 דקות.

ארכיטקטורה

API שכבתי ב־⁠⁦.NET⁩ מעל מסד נתונים שבנוי לדוחות

התרשים רחב מהמסך: החליקו הצידה לצפייה בכולו →

הכול רץ על שרתי Windows ו־⁠SQL Server של הלקוח. מסד הנתונים הוא מקור האמת: לוגיקת הדוחות יושבת ב־⁠Views ובפרוצדורות ש־⁠SSRS וה־⁠API משתמשים בהן יחד, ומודל ה־⁠EF Core נוצר מפרויקט הסכמה, ולא להפך.

החלטות תכנון

החלטות שהיו צריכות להחזיק שנים

Database-first, ו־⁠Views לדוחות

דוחות שכר ותקציב הם שאלות רלציוניות, ולכן הם יושבים ב־⁠Views ובפרוצדורות ש־⁠SSRS, ייצוא ה־⁠Excel וה־⁠API חולקים. מודל EF Core נוצר מפרויקט סכמה שמנוהל בגרסאות. המחיר: כל שינוי סכמה הוא שינוי בשני שלבים, סקריפט DB ו־⁠scaffold. קיבלתי את זה בשביל הגדרה אחת לכל מספר.

הרשאות כנתונים, במטמון ועם עדכון יזום

תשעה תפקידים ו־⁠105 הרשאות מחושבים לכל פרויקט, קבוצה והקצאה. המפה המחושבת נשמרת בזיכרון עם חלון נע של 5 דקות, ותור מעקב שינויים ב־⁠SQL Server מנקה את הרשומה של משתמש ברגע שהתפקידים שלו משתנים. המחיר: צריך להפעיל Service Broker על מסד הנתונים, אבל אין גישה מיושנת ואין פנייה לכל בקשה.

צילום של הסכומים ברגע האישור

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

מחיקה לפי סדר FK, לעולם לא Cascade

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

לשדרג במקום, לא לשכתב

כל קפיצת ⁦.NET⁩ ‏(2.2 ← 3.1 ← 6 ← 8) נכנסה כענף מיגרציה ממוקד על המוצר החי, בזמן שהגרסאות ללקוח המשיכו לצאת. המחיר: חלק מכלי הפרונט הישנים נשארים. הלקוח לא שילם על שכתוב מאפס.

יומן הנדסי

בעיות קשות ואיך פתרנו אותן

מבחר מהיסטוריית הקומיטים, לפי סדר הזמנים.

מאי 2020

שאילתות ש־⁠EF Core 3 סירב להריץ

המעבר מ־⁠⁦.NET Core 2⁩.2 ל־⁠3.1 ביטל את ההערכה השקטה בצד הלקוח ב־⁠EF. כמה שאילתות השתמשו בהשוואות מחרוזות שאי אפשר לתרגם ל־⁠SQL.

כתבנו אותן מחדש כביטויים שמתורגמים בצד השרת, בהסתמך על ה־⁠collation של מסד הנתונים שאינו רגיש לאותיות גדולות וקטנות, והעברתי את תהליך ה־⁠build וה־⁠publish ל־⁠3.1.

אוגוסט 2020

ההרשאות היו השאילתה האיטית ביותר במערכת

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

פיצלנו אותה ל־⁠3 שאילתות ממוקדות כדי לצמצם את התוצאה, ויישמנו המלצות אינדקסים מסבב כיול של SQL Server.

ספטמבר 2021

שכפול פרויקט נתקע

טעינה של פרויקט עם כל 12 אוספי הילדים בשאילתה אחת הכפילה את השורות: cartesian explosion.

פיצלנו את הטעינה ל־⁠3 שאילתות עם 4 Includes כל אחת, ומיזגנו את התוצאות בזיכרון.

פברואר 2022

שינויי הרשאות נכנסו לתוקף באיחור

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

הוספתי טבלת מעקב שינויים ב־⁠SQL Server ותור Service Broker. ה־⁠API מאזין לתור ומנקה רק את רשומת המשתמש ברגע שהגישה שלו משתנה.

מרץ 2022

פחות משנייה ב־⁠SQL, איטי באפליקציה

אותו SQL ש־⁠EF ייצר רץ בפחות משנייה ב־⁠Management Studio, אבל היה איטי מאוד מה־⁠API.

שני החיבורים השתמשו בהגדרות ARITHABORT שונות, ולכן קיבלו execution plans שמורים שונים. התיקון מגדיר SET ARITHABORT ON בכל פקודת EF, ועכשיו האפליקציה מקבלת את אותו plan.

מרץ–מאי 2022

ייצוא Excel גדול נכשל

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

הייצוא קורא עכשיו במנות של עד 100,000 שורות. הוא עבר מ־⁠OpenXML ל־⁠ClosedXML עם עיצוב מזהים ששומר על אפסים מובילים, ומסד הנתונים קיבל סבב אינדקסים חדש.

אפריל–יוני 2022

מרדף אחרי עובדים שלא דיווחו

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

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

יוני 2026

טקסט בעברית הפיל את דוח השכר

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

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

אוגוסט 2026

משתמש יכול היה לשנות לעצמו את התפקיד

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

חסמנו את נתיב שינוי התפקיד, הוספתי בדיקת סוג קובץ בהעלאה, הסתרנו נתוני תפקידים והרשאות מ־⁠API התצורה, והסרנו נקודת קצה גנרית לנתונים שלא הייתה בשימוש.

2026

שבע שנים של נתונים, בלי דרך בטוחה לארכב אותם

פרויקטים סגורים הגיעו ל־⁠48 טבלאות בעומק של עד 6 רמות מפתחות זרים, ולחלק מהטבלאות היו כמה מסלולים חזרה לפרויקט.

כתבתי כלי Python שעובר על גרף ה־⁠FK החי (237 קשרים) ומייצר 6 פרוצדורות מחיקה לפי רמה ו־⁠74 אינדקסים תומכים. פרוצדורה מתזמרת אחת מריצה את כולן בטרנזקציה אחת, במנות של 1,000 שורות, ומבצעת rollback בכל שגיאה.

מסלול המודרניזציה

שבע שנים, מוצר אחד שרץ כל הזמן

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

תוצאות

איפה זה נחת

תחוםלפניאחרי
סביבת ריצה⁦.NET Core 2⁩.2 ‏(2019)⁦.NET 8⁩ LTS ו־⁠EF Core 8, דרך 3 מיגרציות במקום
בדיקות הרשאהשאילתה רחבה למסד הנתונים בכל בקשה3 שאילתות ממוקדות, ואז מטמון שמתנקה בהתראות שינוי
שכפול פרויקטשאילתה אחת עם JOIN על 12 אוספים3 שאילתות × 4 Includes
זמן שאילתה באפליקציה מול SQLמהיר ב־⁠SQL, איטי מהאפליקציהאותו plan בשניהם: פחות משנייה, כפי שנמדד ב־⁠SQL
ייצוא Excel גדולבקשה אחת, שנכשלת בפרויקטים גדוליםמנות של עד 100 אלף שורות; 105 סוגי ייצוא
פריסת דוחותידנית, פעם אחת לכל סביבהסקריפט אחד, 11 דוחות, 4 סביבות
מחזור הדיווח החודשיאיסוף ובדיקה ידניים (≈5 ימי עבודה, הערכה)דיווח בווב ובמובייל עם ולידציה ואישור מרוכז (≈⁦1–2⁩ ימים, הערכה)
ארכוב פרויקטים ישניםאין דרך בטוחה (≈⁦2–3⁩ ימי עבודת DBA ידנית, הערכה)מחיקה טרנזקציונית של 48 טבלאות, שנוצרת אוטומטית (פחות משעה, הערכה)

ההערכות הן הערכות הנדסיות שמרניות, ומסומנות ב־⁠”≈”. כל השאר לקוח מהקוד ומהיסטוריית הקומיטים.

סטאק

סטאק טכנולוגי

צד שרת
⁦.NET 8⁩, ⁦ASP.NET Core⁩, EF Core 8, AutoMapper, NLog, Swagger
נתונים
SQL Server, פרויקט סכמה ו־⁠Schema compare, Service Broker, SqlTableDependency
דוחות
SSRS ‏(11 דוחות), פריסה ב־⁠PowerShell, Excel עם ClosedXML ו־⁠NPOI
צד לקוח
Angular, Angular Material, RxJS, ngx-translate (עברית/אנגלית, RTL)
אבטחה
JWT ו־⁠refresh tokens, נעילת חשבון, מדיניות סיסמאות, הרשאות ברמת ישות, Audit log
כלים
מנתח גרף FK ומחולל SQL ב־⁠Python

שיחת אבחון חינם · 30 דקות · ללא התחייבות

הביאו תהליך אחד. קבלו תוכנית ומספר לשפר.

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

לשיחת אבחון חינםafif.mansour@gmail.com

נפתח מייל מוכן מראש · מענה תוך יום עסקים

ה־AI קורא. הקוד סופר.

כל הפרויקטים