Shiftly - מערכת לניהול שעות וחישוב שכר
May 1, 2026 · View on GitHub
Shiftly - מערכת לניהול שעות וחישוב שכר
📘 גרסה באנגלית זמינה כאן: README.md
מערכת זו היא אפליקציה לניהול שעות עבודה וחישוב שכר מבוססת על React + TypeScript. חישוב שכר כולל משמרות יומיות, ימים מיוחדים, אש״ל, כלכלה וחוקי עבודה מהעולם האמיתי.
הפרויקט שם דגש לא רק על נכונות החישוב, אלא גם על מידול דומיין ברור, יציבות ארכיטקטונית ותחזוקה ארוכת טווח.
⚠️ המערכת מספקת חישוב אינדיקטיבי בלבד.
אין להסתמך על התוצאות לצורכי תלוש שכר רשמי,
והן אינן מחליפות חישוב המתבצע על ידי מדור שכר.
מוטיבציה
Shiftly נולד מבעיה אמיתית שנצפתה בסביבת עבודה ממשלתית.
עובדים עוקבים אחר שעות העבודה שלהם לפי משמרות — בלוק רציף של שעות עם התחלה וסוף ברורים. אבל תלושי השכר הישראליים לא עובדים כך. הם מחושבים לפי קטעים משוקללים: מדרגות שעות נוספות שמתאפסות בכל יום, תוספות שבת וחג שנכנסות לתוקף בשעות מסוימות, ותוספות לילה שחוצות משמרת באמצעה.
התוצאה היא מקור מתסכול ידוע מראש: עובדים מקבלים תלוש שכר שאין להם דרך מעשית לאמת, ואין כלי פשוט שיסביר מאיפה הגיעו המספרים.
Shiftly גושר על הפער הזה. הוא מקבל קלט של משמרות בצורה שבה עובדים באמת חושבים — ומחשב את התגמול לפי חוקי העבודה הישראליים: מדרגות שעות נוספות, תוספות שבת וחג, ותוספות לילה — כדי להפוך את החישוב לשקוף וניתן לאימות עבור מי שמקבל את התלוש.
עיקרון תכנוני מרכזי
העיקרון המרכזי מאחורי Shiftly הוא שלוגיקת החישוב נשארת יציבה לאורך זמן.
חוקי השכר אינם משתנים לפי מימוש, אלא לפי הקשר תקופתי. תאריכים, שעון קיץ/חורף, שכר שעתי, אש״ל וכלכלה מוגדרים כקלטים ולא כלוגיקה מקודדת.
גישה זו מאפשרת חישוב לאחור של חודשים קודמים באמצעות אותו שלד חישוב, רק עם פרמטרים תקופתיים שונים - ללא שינוי בקוד הדומיין.
יכולות עיקריות
- חישוב שכר מבוסס משמרות
- תמיכה ב:
- ימי עבודה רגילים
- ימים מיוחדים חלקיים (למשל ימי שישי וערבי חג)
- ימים מיוחדים מלאים (שבת, חגים)
- זיהוי חגים באמצעות API של Hebcal
- פתרון אוטומטי של חגים יהודיים
- הבחנה בין ימים מיוחדים מלאים לימים מיוחדים חלקיים
- ימי מחלה וחופשה
- משמרות החוצות יום
- חישוב אש״ל לפי ציר זמן היסטורי
- חישוב כלכלה (קטנה / גדולה)
- פירוט חודשי מצטבר
- חישוב אינקרמנטלי (הוספה / עדכון / הסרה של משמרות)
- ממשק משתמש ריאקטיבי לחלוטין
סקירת ארכיטקטורה
Shiftly מבוססת על עקרונות Clean Architecture, עם הפרדה ברורה בין לוגיקה עסקית, ממשק משתמש, ניהול מצב ושירותים חיצוניים.
המטרה היא לשמור על לוגיקת הדומיין צפויה, ניתנת לבדיקה ובלתי תלויה בפריימוורקים.
זרימת חישוב כללית
משמרת -> יום -> חודש
כל רמה מחושבת בנפרד ומצטברת באופן דטרמיניסטי.
שכבות מערכת
דומיין
שכבת הדומיין מכילה לוגיקה עסקית טהורה ואינה תלויה בRedux, React או ספריות חיצוניות.
-
Builders בניית מבני נתונים מורכבים ללא חוקים עסקיים.
-
Calculators פונקציות טהורות המממשות חוקי שכר.
-
Reducers צבירה וביטול צבירה של נתונים מחושבים, המאפשרים חישוב אינקרמנטלי.
-
Resolvers לוגיקת החלטה המבוססת על תאריך, זמן והקשר.
-
Factories & Composition חיבור מרכזי של רכיבי הדומיין.
Adapters
המרת אובייקטי דומיין למודלי תצוגה עבור ה-UI, תוך שמירה על ניתוק מלא מהדומיין.
Hooks
שכבת תיאום דקה בין ה-UI, הדומיין וה-state. אינה מכילה לוגיקה עסקית.
ניהול מצב (Redux)
- ניהול מצב גלובלי וחודשי
- לוגיקה add / subtract דטרמיניסטית
- ללא חישוב מחדש מלא בכל שינוי
Slices מרכזיים:
workDaysSliceglobalSlice
רכיבי UI
רכיבי תצוגה בלבד. ה-UI מגיב לנתונים מחושבים ואינם מכיל חוקי שכר.
מושגי דומיין
Builders
אחראים להרכבת מבני דומיין:
ShiftMapBuilderShiftSegmentBuilderDayPayMapBuilderWorkDaysForMonthBuilder
Calculators
לוגיקת חישוב טהורה מאורגנת לפי תחום:
- שעות רגילות: לפי משמרת / יום
- מקטעים נוספים ומיוחדים: תוספות מבוססות זמן
- אש״ל: רמות משמרת / יום / חודש
- כלכלה: חישוב זכאות ותעריף
Reducers
צבירה והפחתה של נתונים:
- Reducer חודשי למפת שכר
- צובר שעות רגילות
- Reducer חודשי למקטעים קבועים
- Reducer חודשי לאש״ל
- Reducer חודשי לימי עבודה
Resolvers
לוגיקת החלטה תלוית הקשר:
- Resolver חגים (מבוסס Hebcal)
- Resolver מקטעי משמרת
- Resolver תעריפי אש״ל מבוסס ציר זמן
- Resolver תעריפי כלכלה מבוסס ציר זמן
- Resolver חודש
- Resolver מידע יום עבודה
Services
כלי שירות ברמת הדומיין:
DateService: טיפול ואימות תאריכיםShiftService: לוגיקה עסקית הקשורה למשמרות
Pipelines
צינורות הרכבה לחיבור רכיבי דומיין:
buildCoreServices: שירותי תאריך ומשמרתbuildResolvers: כל מופעי ה־ResolversbuildCalculators: מופעי CalculatorsbuildShiftLayer: לוגיקה ברמת משמרתbuildDayLayer: צבירה ברמת יוםbuildMonthLayer: צבירה ברמת חודש
Factories
יצירת מופעי calculators ספציפיים:
FixedSegmentFactoryRegularFactory
טכנולוגיות
ליבה
- React 19.2.3
- TypeScript 5.7.2
- Vite 6.2.0
State וניווט
- Redux Toolkit 2.11.0
- React Router 7.11.0
UI ועיצוב
- Material UI (MUI) 7.0.2
- Notistack 3.0.2 (התראות)
נתונים ושירותים
- Axios 1.9.0 (HTTP client)
- date-fns 4.1.0 (טיפול בתאריכים)
- Hebcal API (זיהוי חגים)
בדיקות
- Vitest 4.0.16
- Testing Library (React, Jest-DOM, User Event)
מבנה הפרויקט
src/
├── app/ # מעטפת האפליקציה
│ ├── domain/ # אתחול וחיבור הדומיין
│ ├── providers/ # ספקי Context
│ └── routes/ # הגדרות ניתוב
├── domain/ # לוגיקה עסקית (בלתי תלויה בפריימוורקים)
│ ├── builder/ # בוני מבני דומיין
│ ├── calculator/ # לוגיקת חישוב שכר
│ │ ├── regular/
│ │ ├── special/
│ │ ├── perdiem/
│ │ └── mealallowance/
│ ├── reducer/ # צבירה והפחתה של מצב
│ ├── resolve/ # החלטות תלויות הקשר
│ ├── factory/ # פקטוריות רכיבים
│ ├── pipelines/ # צינורות הרכבה
│ ├── services/ # שירותי דומיין (תאריך, משמרת)
│ └── types/ # הגדרות טיפוסים
├── adapters/ # המרת דומיין ל־UI
├── features/ # מודולי UI ספציפיים
│ ├── calculation-rules/
│ ├── config/
│ ├── info-dialog/
│ ├── salary-summary/
│ ├── work-table/
│ └── workday-timeline/
├── hooks/ # React hooks (שכבת תיאום)
├── hoc/ # רכיבי Higher-order
├── layout/ # רכיבי פריסה ו־error boundaries
├── pages/ # רכיבי עמודים (יומי, חודשי, כללים)
├── redux/ # ניהול מצב
│ └── states/ # Redux slices
├── services/ # שירותים חיצוניים
│ ├── analytics/ # שירות משוב שכר
│ └── hebcal/ # אינטגרציה עם API חגים
├── constants/ # קבועי אפליקציה
└── utils/ # עזרי שירות
התנהגות ממשק המשתמש
תצוגות מערכת
Shiftly כוללת שתי תצוגות חישוב עיקריות:
תצוגה יומית
- מיועדת להזנת משמרות יומיות
- מאפשרת הוספה, עריכה ובקרה של משמרות
- מציגה פירוק שכר יומי
- הסיכום החודשי מתעדכן באופן אינקרמנטלי
תצוגה חודשית
- מיועדת לניתוח שכר חודשי מצטבר
- מחייבת בחירת שנה וחודש
- מבטיחה דיוק תעריפי אש״ל וכלכלה לפי התקופה
- מציגה סיכום חודשי קומפקטי וברור
שתי התצוגות משתמשות באותו מנגנון חישוב דומיין. רק ההקשר וההצגה משתנים.
פאנל הגדרות (ConfigPanel)
רכיב ה־ConfigPanel מותאם להקשר הפעיל:
-
בתצוגה יומית:
- הגדרת שעות תקן ושכר שעתי
- החישוב החודשי נגזר מהנתונים היומיים
-
בתצוגה חודשית:
- בחירת שנה וחודש היא הכרחית
- מבטיחה תעריפי אש״ל וכלכלה מדויקים לפי התקופה
- מחייבת הגדרת שכר שעתי לצורך חישוב
הפרדה זו מונעת חישוב שגוי ומחדדת אחריות.
תצוגת יום עבודה
- אם
baseRateלא הוגדר: מוצגות רק שעות העבודה. - אם
baseRateהוגדר: מוצג שכר יומי וסיכום חודשי. - ימי מחלה / חופשה: לא מאפשרים הזנת משמרות.
- שבת / חג: מאפשרים עבודה בלבד (ללא היעדרות).
- משמרת חוצה יום: דורשת אישור מפורש מהמשתמש.
לוגיקת הגדרת יום עבודה
שבת או חג - עבודה מותרת
- לא ניתן לסמן יום כמחלה או חופש, אך ניתן להזין משמרות עבודה.

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

משמרת חוצה יום - תיבת סימון ״חוצה יום״
- כאשר שעת הסיום היא ביום הבא המערכת מבקשת אישור מפורש על חציית יום.

סיכום פירוק יומי - מורחב

סיכום פירוק יומי - קומפקטי

סיכום חודשי

למה ארכיטקטורה זו?
הארכיטקטורה נבחרה כדי להתמודד עם:
- חוקי שכר מורכבים
- מקרי קצה מבוססי זמן
- רמות צבירה שונות (משמרת → יום → חודש)
- חישוב אינקרמנטלי ללא חישוב מחדש מלא
- דיוק היסטורי ללא שינוי בלוגיקה הליבה
היא מאפשרת התפתחות עתידית של המערכת בלי להעמיס לוגיקה מותנית ברכיבי ה-UI.
הערות מימוש
- כל האחוזים מנורמלים (לדוגמה:
1= 100%,1.5= 150%,2= 200%) - לוגיקת הדומיין בלתי תלויה בפריימוורק וניתנת לבדיקה באופן מלא
- ה־UI מגיב לנתונים ולא מכיל חוקים עסקיים
- חישובים היסטוריים משתמשים בהקשר מבוסס זמן, לא בשינויי קוד
בדיקות
Shiftly משתמשת ב־Vitest לבדיקות יחידה ואינטגרציה, עם דגש על אימות לוגיקת הדומיין.
הרצת בדיקות
# הרצת בדיקות במצב watch
npm run test
# הרצת בדיקות עם ממשק UI
npm run test:ui
# הרצת בדיקות עם כיסוי קוד
npm run test:coverage
# הרצת בדיקות במצב CI (הרצה חד־פעמית)
npm run test:ci
כיסוי בדיקות
הבדיקות מכסות:
- לוגיקת חישוב (builders, calculators, reducers)
- פתרונות מבוססי זמן (חגים, תעריפים, מקטעים)
- מקרי קצה (משמרות חוצות יום, ימים חלקיים, מחלה/חופשה)
- תרחישי חישוב מקצה לקצה
שכבת הדומיין ניתנת לבדיקה באופן מלא ובלתי תלויה בפריימוורק, מה שמקל על אימות חוקים עסקיים בבידוד.
התחלה מהירה
git clone https://github.com/dmaman86/shiftly.git
cd shiftly
npm install
npm run dev
כניסה ל־http://localhost:5173/shiftly בדפדפן.
רישיון
הפרויקט מופץ תחת רישיון MIT.