גרסה: יולי 2026 • סטטוס: עובד, נבדק end-to-end, מוכן ל-production
מסמך זה מלווה את מסירת המערכת. הוא מכסה: מה נבנה, איפה כל דבר גר, איך משנים דברים נפוצים, ואיך מעבירים בעלות.
שולחים קמפיין סמס (Inforu) עם קישור אישי קצר (אסימון) לכל נמען → הנמען נכנס לפאנל ווב בסגנון וואטסאפ (תפריט פתיחה: הלוואה / משיכה מקרן הפנסיה, עם החזר מס כהצעת המשך; עברית RTL, בסגנון הבוט של אוראל) → הליד נשמר ב-DB עם סיכום אוטומטי → דשבורד ניהול (שליחה במנות, סטטיסטיקות, לידים, ייצוא).
מיתוג נייטרלי: הפאנל מוצג בשם "פתרונות פיננסיים" (כותרת + כותרת עליונה), לא "נחמן". שם השולח ב-SMS נקבע לכל קמפיין בדשבורד (ברירת מחדל בקוד: DEFAULT_SENDER).
קישור אישי קצר (אסימון): כל נמען מקבל קישור בצורת https://lc76nj.short.gy/zk?t=<token> (אסימון בן 10 תווים), שמפנה לפאנל בכתובת https://nahmanbot.com/?t=<token>. הטלפון והשם נשמרים ב-DB מאחורי האסימון (sms_short_links) — כך הכתובת קצרה, הטלפון לא נחשף ב-URL, וכל טעינה נרשמת כקליק. הסרה מרשימת התפוצה: במסך הראשון קיימת אפשרות "הסרה מרשימת התפוצה" שנשמרת ב-DB (sms_opt_outs) וחוסמת שליחות עתידיות — מוסרים מסוננים אוטומטית לפני כל שליחה.
גם מי שלחץ ולא סיים — נרשם עם הטלפון שלו ("ליד חם").
שמירת התקדמות: מי שנכנס לפאנל ועושה רענון / סוגר וחוזר (עד 24 שעות) — ממשיך בדיוק מאיפה שעצר, עם כל היסטוריית הצ'אט (נשמר ב-localStorage). בנוסף כל תשובה נשמרת ב-DB כליד חלקי (is_completed=false, upsert אחד ל-24 שעות — לא נוצרות שורות כפולות), וברגע הסיום אותה שורה הופכת ל-is_completed=true. בדשבורד רואים תגית "חלקי" ליד לידים כאלה.
┌─────────────────┐ לינק אישי ┌──────────────────────────┐
│ Inforu (סמס) │ ─────────────► │ nahmanbot.com (nginx │
└─────────────────┘ ?p=&n=&c= │ בשרת; GitHub Pages = │
│ גיבוי) פאנל + דשבורד │
└─────────┬────────────────┘
│ RPC בלבד (anon key)
▼
┌───────────────────────────────────────────────────────┐
│ DB מרכזי: Supabase self-hosted על שרת הלקוח │
│ db.nahmanbot.com (Kong → Postgres, 13K+ לידים) │
│ הפאנל כותב לידים ישירות לטבלת leads המרכזית │
└───────────────────────────────────────────────────────┘
▲
┌──────────────────────────────┴───────────────────────┐
│ Edge Functions (בשרת + בענן כגיבוי, אותו קוד): │
│ send-sms-campaign ──► Inforu API │
│ admin-api ◄── דשבורד (x-admin-token) │
│ שתיהן מדברות אל ה-DB המרכזי ב-service key שלו │
└──────────────────────────────────────────────────────┘
ה-DB המרכזי הוא אותו DB שהבוט וה-CRM של הלקוח עובדים איתו — ליד מהפאנל נולד
ישירות בטבלת leads שהם רואים. פונקציות ה-edge מותקנות בשני מקומות במקביל
(אותו קוד, אותם קבועים): ב-edge-runtime של השרת (/root/supabase/volumes/functions/,
הותקן ואומת 19.7) ובפרויקט הענן הישן כגיבוי. אין בהן דאטה — רק קוד.
| נתיב | מה זה |
|---|---|
index.html |
הפאנל ללקוחות. הפלואו (תפריט: מסלול הלוואה / מסלול החזר מס) מוטמע בקוד באובייקט FLOW |
admin.html |
דשבורד ניהול: שליחת קמפיין / סטטיסטיקות / לידים + ייצוא CSV / קבוצות אנשי קשר |
supabase/functions/send-sms-campaign/ |
שליחה דרך Inforu (שרת-צד, מוגן טוקן). SHORTEN_URL=false — מקצר הקישורים כבוי (גרם לבליעת הודעות, ראה §5) |
supabase/functions/admin-api/ |
API קריאה/כתיבה לדשבורד (קמפיינים/לידים/ייצוא/קבוצות) |
supabase/functions/inforu-probe/ |
כלי בדיקה: קישוריות + Sender IDs מורשים |
supabase/migrations/ |
כל ה-DDL: RPCs (submit_web_lead, log_web_click, calc_summary_web) + טריגרים + טבלת קבוצות + 007: אסימונים, הסרות ומנות שליחה |
supabase/migrations/007_short_links_opt_outs.sql |
טבלאות sms_short_links / sms_opt_outs / sms_campaign_batches, ה-view sms_campaign_stats, וה-RPCs לשליחה במנות (register_sms_campaign, claim_sms_campaign_batch, prepare_sms_batch, finish_sms_campaign_batch), לפתרון אסימון (resolve_sms_short_link), ולהסרה (opt_out_sms, opt_out_sms_by_phone) |
tools/send.js |
סקריפט CLI חלופי לשליחה (לא דרך הדשבורד) |
| מה | ערך | היכן מוגדר |
|---|---|---|
| DB מרכזי (self-hosted) | https://db.nahmanbot.com |
בכל הרכיבים |
| anon key של ה-DB המרכזי | בראש index.html (SUPABASE_ANON) — מקור: /root/supabase/.env בשרת |
index.html |
| service key של ה-DB המרכזי | SUPA_KEY בשתי הפונקציות — מקור: /root/supabase/.env בשרת |
send-sms-campaign, admin-api |
| Supabase Cloud (מראה מיותרת של הפונקציות — לגיבוי בלבד) | dgmygsvwemgtnvmdnwnz |
— |
| סיסמת דשבורד / admin token | nahman-campaign-2026-x7q |
ADMIN_TOKEN בכל 3 הפונקציות |
| Inforu | user: Shimon123 / token: בקוד הפונקציה |
send-sms-campaign/index.ts |
| Sender ID | nahman (אומת מול ה-API) |
פרמטר sender / DEFAULT_SENDER |
⚠️ לפני production — מומלץ לשנות אתADMIN_TOKEN(בכל הפונקציות) ולסובב את מפתח ה-service של Supabase (הוא נחשף בריפו הישן WhatsAppCrmClean/rebuild-flow.js). סיבוב: Supabase Dashboard → Settings → API → Reset service key.
נוסח הודעת ברירת מחדל: DEFAULT_MESSAGE ב-send-sms-campaign/index.ts
(בדשבורד עצמו עורכים חופשי לכל קמפיין).
שאלות הפאנל: עורכים את FLOW ב-index.html. שדות נשמרים בפי field —
השמות חייבים להתאים לעמודות בטבלת leads (רשימה מלאה ב-submit_web_lead).
מאז 20.7 יש תפריט פתיחה: "במה נוכל לעזור לך היום?" — הלוואה / החזר מס
(שני המסלולים משוכפלים מ-bot_steps של הבוט הראשי). מסלול הלוואה: סוג עובד →
סכום → שם → אזור → נכס → רכב → חיובים חוזרים → עיקול → סוג כרטיס → ובסוף
הצעת החזר מס (כמו בבוט). מסלול המס: הצעה → וותק → החזר קודם → הכנסה →
ביטוחים → שם → אזור. lid_type נקבע מהבחירה בתפריט. מפתח ה-localStorage:
nahman_funnel_v3.
כתובת הפאנל בלינקים: FUNNEL_URL ב-send-sms-campaign/index.ts היא https://nahmanbot.com/
(הפאנל מוגש מהשרת עצמו; ראה §6). הלינק שמופיע ב-SMS מוגדר ב-SHORT_BASE:
https://lc76nj.short.gy/zk?t=<token> — קישור קצר דרך Short.io שמפנה לפאנל.
הכתובת הישנה ב-GitHub Pages עדיין עובדת כגיבוי.
שם שולח: שדה בדשבורד / DEFAULT_SENDER בפונקציה.
קבוצות אנשי קשר: טבלת contacts (מיגרציה 003_contacts_groups.sql), RLS נעול —
הגישה רק דרך admin-api (save_contacts / groups / group_contacts / delete_group / delete_contact).
ייחודיות על (phone, group_name) — שמירה חוזרת לאותה קבוצה מעדכנת ולא מכפילה.
בדשבורד: טאב 📇 לניהול, ובטאב השליחה — "טען מקבוצה שמורה" שממלא את רשימת הנמענים.
קיצור לינקים (כבוי 19.7!): SHORTEN_URL=false ב-send-sms-campaign/index.ts.
בדיקת A/B הוכיחה שהודעות עם ShortenUrlEnable=true לא נמסרות כלל (נבלעות
בשתיקה אצל Inforu — הפיצ'ר כנראה לא מופעל בחשבון), בעוד הודעות רגילות מגיעות.
להפעיל מחדש רק אחרי אישור תמיכת Inforu שהמקצר פעיל בחשבון.
שם שולח: הלקוח משתמש ב-sender ID מספרי (מספר טלפון) — מזינים אותו בשדה
"שם שולח" בדשבורד לכל קמפיין; ברירת המחדל בקוד: DEFAULT_SENDER.
מעבר ל-DB מרכזי (בוצע 19.7): מיגרציה 004_central_integration.sql הורצה על
ה-Postgres בשרת (גיבוי סכמה: /root/backups/pre-integration-2026-07-19.sql).
היא מוסיפה: sms_clicks, sms_campaigns, contacts + ויו contact_group_counts
- ה-RPCs (
log_web_click,submit_web_lead,calc_summary_web) + 2 טריגרים. הכל אדיטיבי — לא נגענו בטבלאות/דאטה/קוד של הבוט.
תסריט החזר מס (בוצע 19.7): מיגרציה 005_tax_funnel.sql — has_insurance
נוסף למיפוי ב-submit_web_lead, ותוקן ב-calc_summary_web סיווג שגוי:
"לא ביצעתי החזר מס" (ליד מצוין!) לא נרשם יותר כ"לא מעוניין". התיקון משפיע
לטובה גם על סיכומי הבוט.
התנהגות צ'אט חופשי (בוצע 20.7): שדה טקסט חופשי זמין תמיד לצד הכפתורים —
הודעה שרירותית שולחת מחדש את אותה השאלה עם האפשרויות (לא מקדמת); רק בחירת
אפשרות מקדמת. לאחר סיום התהליך, כל הודעה חדשה מאתחלת מהשאלה הראשונה. כל
הודעות הליד נצברות בעמודת remarks עם חותמת זמן [HH:MM:SS ,D.M.YYYY]
(הראשונה עם "הודעת פתיחה:") — מיגרציה 006_remarks_log.sql.
⚠️ תיקון שורש (בוצע 20.7): קמפיינים camp12/camp07 יצאו עם לינק github.io כי הדשבורד (admin.html) קרא לפונקציות בכתובת הענן הישנה ישירות (dgmygsvwemgtnvmdnwnz.supabase.co) — שם רצה עותק מיושן של הקוד. תוקן: הדשבורד מפנה כעת ל-db.nahmanbot.com(edge-runtime של השרת, קוד מעודכן), בשרת וב-GitHub Pages. הסרת ה-Custom Domain מהענן עדיין מומלצת כניקיון, אך אינה קריטית — שום רכיב שלנו לא קורא לענן יותר.
אסימונים, הסרות ושליחה במנות (מיגרציה 007): לקמפיינים גדולים (10K+) הדשבורד
מפצל את הנמענים למנות של 500 עם מזהה קמפיין אחיד (clientCampaignId) ושולח
מנה-מנה דרך send-sms-campaign. לכל מנה הפונקציה: (1) register_sms_campaign
(רישום/איתור ריצת הקמפיין, אידמפוטנטי), (2) claim_sms_campaign_batch (תפיסת
המנה פעם אחת — מנה שכבר נשלחה חוזרת כ-already_sent ולא נשלחת שוב),
(3) prepare_sms_batch (יצירת אסימונים + סינון מוסרים + דה-דופ בתוך ה-DB),
(4) שליחה ל-Inforu עם קישור אסימון אישי, (5) finish_sms_campaign_batch (רישום
תוצאה + עדכון מוני הקמפיין). אם הדשבורד נסגר באמצע — לחיצה חוזרת על "שיגור"
ממשיכה מהמנה הבאה (מצב נשמר ב-localStorage תחת nahman_campaign_run_v2); מנה
שנדחתה ניתנת לניסיון חוזר עד 3 פעמים. סטטוסי קמפיין: preparing / sending /
sent / partial / attention (מנה במצב לא ודאי — דורש בדיקה ידנית). ה-view
sms_campaign_stats מחשב קליקים/לידים ב-DB (מונע חיתוך שקט של PostgREST מעל
1,000 שורות). ההודעה חייבת לכלול [#Representative#] — שם מוזרק הקישור האישי.
- הפאנל על הדומיין הרשמי (19.7):
https://nahmanbot.comמוגש מהשרת — קבצים ב-/var/www/funnel/, בלוק nginx ב-/etc/nginx/sites-available/funnel(server_name:nahmanbot.com+start.nahmanbot.comמוכן מראש), תעודת Let's Encrypt דרך certbot (חידוש אוטומטי). לעדכון: מעתיקיםindex.html/admin.htmlחדשים ל-/var/www/funnel/— בלי restart. - דפים סטטיים (גיבוי): כל push ל-
main→ GitHub Pages מתעדכן אוטומטית (~דקה). - Edge Functions בשרת: מעתיקים את
index.tsל-/root/supabase/volumes/functions/<name>/ו-docker restart supabase-edge-functions. - Edge Functions בענן — גיבוי (אחרי
npm i -g supabase+supabase login):supabase functions deploy send-sms-campaign --project-ref dgmygsvwemgtnvmdnwnz supabase functions deploy admin-api --project-ref dgmygsvwemgtnvmdnwnz
- מיגרציות DB: להריץ את הקבצים ב-
supabase/migrations/לפי הסדר (SQL Editor בדשבורד Supabase אוsupabase db push).
הנקודה המוכנה: טבלת leads, שורות חדשות עם source = 'web_funnel'.
שתי דרכים מומלצות:
- Supabase Database Webhook על INSERT ל-
leads→ Edge Function חדשה ששולחת מייל (Resend/SendGrid). - קריאה מתוזמנת (pg_cron / GitHub Actions) ללידים אחרונים → מייל תקופתי.
היום הכל יושב תחת חשבונות של המפתח הקודם/הנוכחי. להעברה נקייה:
- GitHub: Repository → Settings → Transfer ownership → לחשבון הלקוח
(או Fork לחשבון שלו + עדכון
FUNNEL_URLאם שם המשתמש משתנה — ה-URL של Pages תלוי בו!). - Supabase: Organization → Invite (כ-owner) → הלקוח מסיר את המפתח.
- Inforu: החשבון כבר של הלקוח.
- אחרי ההעברה: לסובב סודות (סעיף 4) ולעדכן טוקנים.
כל נתוני הבדיקה נוקו. אם יצטברו שוב:
delete from sms_clicks where campaign_name like '%test%' or campaign_name like '%בדיקה%';
delete from leads where source = 'web_funnel' and phone in ('0501234567');- שליחת 2 סמסים אמיתיים דרך Inforu — התקבלו, Sender
nahmanתקין - לחיצה → רישום מייד (טלפון+קמפיין+user-agent) כולל זיהוי בוטים (Google-Read-Aloud)
- מילוי מלא של 12 השאלות → ליד עם כל השדות,
summaryאוטומטי,hechzer_mas, דה-דופ 24 שעות - דשבורד: התחברות, סטטיסטיקות, לידים, ייצוא
- קבוצות: שמירה (כולל דה-דופ ונרמול טלפונים), עדכון קבוצה קיימת, צפייה, מחיקת קבוצה/איש קשר, טעינה לטאב שליחה
- רענון באמצע הפאנל: היסטוריה מלאה + המשך מאותה שאלה; ליד חלקי ב-DB תוך שניות; השלמה אחרי רענון מעדכנת את אותה שורה (is_completed=true, summary + hechzer_mas תקינים, בלי כפילויות); רענון אחרי סיום מציג את הצ'אט המושלם
- הרשאות: ה-anon key לא יכול לקרוא/לכתוב אף טבלה — רק 2 ה-RPCs המסוננים
- אינטגרציית DB מרכזי: לחיצה + ליד חלקי מהפאנל נרשמו ישירות ב-Postgres בשרת (אומת ב-psql), CORS דרך Kong תקין, מיגרציית 004 הורצה בטרנזקציה אחת עם COMMIT נקי
- פונקציות מקומיות בשרת (19.7):
admin-apiעונהgroupsתקין + 401 על טוקן שגוי,send-sms-campaignOPTIONS 204 — אומת ששרת ה-edge-runtime המקומי בלוגים; שום רכיב במערכת הראשית (בוט/דשבורד) לא מפנה לפרויקט הענן הישן (אומת ב-grep מלא) - פאנל על דומיין רשמי (19.7):
https://nahmanbot.com+/admin.htmlעונים 200 עם תעודה תקינה והפניית http→https;FUNNEL_URLעודכן והופעל בשרת; crm/db/waha לא הושפעו - תסריט החזר מס (19.7): מיגרציית 005 COMMIT נקי; RPC עם כל שדות המס — ליד מלא "החזר מס סיים תהליך" + hechzer_mas=true + has_insurance נשמר; ליד דחייה "החזר מס לא מעוניין"; התיקון מונע סיווג שגוי של "לא ביצעתי החזר מס"; הפאנל החי מציג את התסריט החדש (אומת בכותרת וב-FLOW); דאטה בדיקה נוקה
- התנהגות צ'אט חופשי (20.7, e2e בדפדפן): הודעה חופשית בשאלת רשימה → אותה שאלה נשלחת מחדש עם האפשרויות (ללא התקדמות); אחרי סיום התהליך → הודעה חדשה מאתחלת מהשאלה הראשונה; שתי ההודעות נצברו ב-
remarksבפורמט[HH:MM:SS ,D.M.YYYY](ראשונה עם "הודעת פתיחה:") — אומת ב-DB; מיגרציית 006 הורצה ואומתה ב-RPC; דאטת בדיקה נוקתה - תפריט הלוואה/החזר מס (20.7, e2e בדפדפן על Pages): תפריט פתיחה עם שתי בחירות; מסלול הלוואה המלא (11 מסכים) הושלם עד תודה כולל הצעת המס המשולבת — ליד נשמר עם lid_type='הלוואה', כל השדות, summary="סיים תהליך הלוואה לכל מטרה + החזר מס בתהליך", hechzer_mas=true; אומת גם ב-RPC ישיר; דאטת בדיקה נוקתה