המטרה
המשרד רדף אחרי מסמכים חסרים ידנית, הקליד נתונים מתוכנת הנהלת החשבונות לתבניות Excel של הערכות מס, וניהל הצהרות הון בחוברת עבודה. המטרה: מערכת אחת שאוספת מסמכים מהלקוחות, עוקבת מה עוד חסר לפי סוג דוח ושנה, ומפיקה את הניירת החוזרת אוטומטית - נגישה מחוץ למשרד, כשהקבצים נשארים על השרת של המשרד.
הפתרון
אפליקציית Web בעברית RTL (Vue 3 + Express + MongoDB) עם 10 אזורי ניהול ו-3 דפים ציבוריים ללקוחות. כל לקוח מקבל במייל ממותג קישור לפורטל אישי, ממלא טפסים דינאמיים ומעלה מסמכים (תמונות מומרות ל-PDF ונשמרות בתיקיית הלקוח). מעל זה יושבים שני מודולי אוטומציה: הערכות מס שנמשכות ישירות מה-REST API של paperless.tax ונכתבות לתבניות ה-Excel ולתיקיות של המשרד עצמו, והצהרות הון (טופס 1219) שנערכות בדפדפן ומודפסות ל-PDF. המערכת רצה כשירות Windows על השרת של הלקוח מאחורי Cloudflare, עם פריסה דרך GitHub Actions self-hosted runner.
עיקרי הדברים
- הערכות מס מופקות ישירות מה-API של תוכנת הנהלת החשבונות לתבניות ה-Excel ולתיקיות של המשרד
- חוברת הצהרות ההון הוחלפה בסביבת עבודה ב-Web שמדפיסה את טופס 1219 על כל שדותיו
- איסוף מסמכים מלקוחות עם קישורי פורטל אישיים, תיוק תמונות כ-PDF ומעקב לפי שנה
- אחסון עצמי על ה-Windows Server של הלקוח עם פריסה אוטומטית בכל push וגיבוי יומי
- חסומה בכוונה למנועי חיפוש ולסורקי AI
האתגר
תבנית ה-Excel של הערכת המס כוללת לוגו, עיצוב והגדרות הדפסה של המשרד ונשלחת ללקוחות, ורואה החשבון עורך אותה בחופשיות - מיפוי תאים קשיח היה כותב מספרים שורה אחת לא נכון בשקט אחרי כל הוספת שורה.
כל תא יעד מאותר לפי התווית העברית שלידו במקום כתובת קבועה, והערכים נכתבים בעריכת ה-XML של הגיליון במקום, כך שכל שאר הקובץ נשאר זהה לחלוטין; נוסחאות לא נוגעות ו-Excel מחשב אותן מחדש בפתיחה.
לתוכנת הנהלת החשבונות, לדוחות התשלום המיוצאים ולרשימת הלקוחות של המשרד אין מפתח משותף - ובני זוג מדווחים תחת תיק מס הכנסה אחד, בעוד שבמקומות אחרים כל אחד מוכר לפי מספר הזהות שלו.
נבנתה שכבת התאמה מפורשת עם כללים נוקשים (מספר לקוח של המשרד מושווה בדיוק, מספר זהות מרופד רק לצורך ההשוואה), שלב תיחום שמבין תיקי מס משותפים, ודוח התאמה מדוד על המסך במקום ניחוש שקט.
המערכת הייתה צריכה להיות נגישה מכל דפדפן בזמן שהמסמכים נשארים על ה-Windows Server של המשרד, בלי מתזמן או צינור פריסה של פלטפורמה מולה.
מעבר מ-Vercel + Blob לאחסון עצמי: תהליך Node אחד מגיש גם את ה-API וגם את ה-SPA כשירות Windows (NSSM) מאחורי Cloudflare, הגיבויים רצים בתוך התהליך, ו-GitHub Actions self-hosted runner על השרת פורס כל push ונכשל בקול במקום לדווח הצלחה שגויה.
סכומים מה-API של תוכנת הנהלת החשבונות מגיעים באגורות, ושותפות מנהלת ספרים אחדים בעוד שהמס מחושב לכל שותף בנפרד.
שני הכללים קודדו במפענחים ייעודיים - הסכומים מחולקים פעם אחת במקור, ושותפות נפרסת להערכה נפרדת לכל שותף לפי אחוז החלק הרשום בתוכנה.
מה נמסר
- אפליקציית ניהול Vue 3 + פורטל לקוחות ציבורי (עברית RTL, מותאם למובייל)
- API ב-Express + MongoDB עם התחברות אדמין ב-JWT
- מודולי אוטומציה להערכות מס ולהצהרות הון
- סקריפטי פריסה ל-Windows Server, שירות NSSM ו-workflow ב-GitHub Actions
- חבילות בדיקות E2E ב-Playwright וסקריפטי בדיקה לשרת
תוצאות
10
אזורי ניהול
10
מודלי נתונים
96
קומיטים
Hebrew RTL
ממשק
מה זה לימד אותי
- כשהפלט מגיע ללקוח של הלקוח, ריצה שנכשלת עדיפה על מספר שגוי - לעגן לפי תוויות ולא לפי כתובות תאים
- למדוד עד כמה שתי מערכות מזהות את אותם אנשים לפני שמחברים ביניהן, ולהציג את הפער על המסך
- בשרת באחסון עצמי, כל מה שיכול להיכשל בשקט (גיבויים, פריסות, חיבור שפג תוקפו) צריך בדיקה מתוזמנת ורועשת
