סכמת PostgreSQL מלאה של מערכת ניטור המכירות בטלגרם עבור SmartAds
פרויקט Supabase: ohmkpunoxloxwvtkdkee
erDiagram
networks {
bigint id PK
text name UK
text deals_sheet_id
timestamptz created_at
}
agents {
bigint id PK
text name
timestamptz created_at
}
agent_accounts {
bigint id PK
bigint agent_id FK
bigint network_id FK
bigint telegram_user_id UK
text phone_number
text display_name
text session_status
timestamptz last_heartbeat
timestamptz created_at
}
groups {
bigint id PK
bigint telegram_chat_id UK
text name
bigint network_id FK
bigint company_id FK
text category
text folder_name
int total_messages
int outgoing_messages
timestamptz last_message_at
}
messages {
bigint id PK
bigint telegram_message_id
bigint chat_id
bigint sender_id
text direction
text chat_type
text text
timestamptz timestamp
bigint agent_account_id FK
bigint attributed_group_id FK
text attribution_method
}
group_members {
bigint id PK
bigint group_id FK
bigint telegram_user_id
boolean is_active
}
ingestion_health {
bigint id PK
bigint agent_account_id FK
text event
timestamptz timestamp
jsonb details
}
daily_scores {
bigint id PK
bigint group_id FK
date date
int score
text summary
}
weekly_reports {
bigint id PK
bigint agent_id FK
date week_start
date week_end
text report_text
jsonb highlights
jsonb follow_ups
jsonb concerns
}
companies {
bigint id PK
text name
text_arr aliases
text source
}
contacts {
bigint id PK
bigint company_id FK
bigint telegram_user_id UK
text display_name
}
deals {
bigint id PK
bigint network_id FK
bigint agent_id FK
bigint company_id FK
text brand_name_raw
numeric buy_price
numeric sell_price
numeric profit
}
group_assignments {
bigint id PK
bigint group_id FK
bigint agent_id FK
}
agents ||--o{ agent_accounts : "has accounts"
networks ||--o{ agent_accounts : "belongs to"
agent_accounts ||--o{ messages : "captures"
agent_accounts ||--o{ ingestion_health : "monitors"
groups ||--o{ messages : "attributed to"
groups ||--o{ group_members : "has members"
groups ||--o{ daily_scores : "scored daily"
networks ||--o{ groups : "organizes"
companies ||--o{ groups : "owns"
agents ||--o{ weekly_reports : "receives"
agents ||--o{ deals : "closes"
networks ||--o{ deals : "tracks"
companies ||--o{ deals : "for"
companies ||--o{ contacts : "employs"
agents ||--o{ group_assignments : "assigned"
groups ||--o{ group_assignments : "assigned to"
מי זה מי. מגדיר את רשתות הפרסום שרועי עובד איתן, את סוכני המכירות (מתחיל עם דייב), ואת חשבונות הטלגרם שלהם.
ערך עסקי: בלי השכבה הזו, הודעות הן סתם רעש. זה מה שמאפשר לנו לומר "דייב שלח 190 הודעות היום דרך רשת AllStar".
הפיד החי. כל הודעת טלגרם שנקלטת בזמן אמת, כל קבוצה/ערוץ שמתגלה, וטלמטריית בריאות מהליסנר. טבלת messages עם 317K+ שורות היא הלב של המערכת. קבוצות מסווגות לפי תיקיות טלגרם (broker/network/affiliate/finance/new).
ערך עסקי: זה ה"עין" ב-JangoEye — נראות מלאה של שיחות מכירות שמתרחשות ברחבי ערוצי הטלגרם, עם מעקב כיוון (נכנסת/יוצאת), זיהוי עריכה/מחיקה, ומודעות למדיה.
להבין את הנתונים. daily_scores מדרג כל קבוצה 0-10 יומית לפי איכות השיחה. weekly_reports הם סיכומי LLM לכל סוכן עם הדגשות, המלצות, מעקב עסקאות וחששות.
ערך עסקי: זה מה שרועי באמת קורא. במקום לגלול 10,000 הודעות בשבוע, הוא מקבל דשבורד עם ניקוד ותקציר שבועי. הניקוד מזהה אילו קבוצות חמות (קרובות לעסקה) לעומת רדומות.
עדיין לא פעיל. שמור לשלב 2 — שכבת CRM. יעקוב אחרי חברות (מותגי פרסום), אנשי קשר (אנשים באותן חברות לפי Telegram user ID), ועסקאות (מחירי קנייה/מכירה מגיליונות הרשתות). טבלת deals כוללת עמודות רווח/הפסד מלאות.
ערך עסקי (כשיופעל): סוגר את המעגל — מחבר שיחות להכנסות. "הקבוצה הזו ייצרה 3 עסקאות בשווי $X רווח החודש."
| Column | Type | Attributes | Notes |
|---|---|---|---|
| id | bigint | Auto-generated | |
| name | text | שם הרשת (למשל "AllStar") | |
| deals_sheet_id | text | Google Sheets ID לייבוא עסקאות (שלב 2) | |
| created_at | timestamptz |
agent_accounts.network_idgroups.network_iddeals.network_idagent_accounts (אחד לכל רשת).
| Column | Type | Attributes | Notes |
|---|---|---|---|
| id | bigint | ||
| name | text | שם תצוגה של הסוכן | |
| created_at | timestamptz |
agent_accounts.agent_idweekly_reports.agent_iddeals.agent_idgroup_assignments.agent_id| Column | Type | Attributes | Notes |
|---|---|---|---|
| id | bigint | ||
| agent_id | bigint | איזה סוכן אנושי | |
| network_id | bigint | באיזו רשת | |
| telegram_user_id | bigint | מזהה המשתמש בטלגרם | |
| phone_number | text | לזיהוי | |
| display_name | text | ||
| session_status | text | ברירת מחדל: 'pending' | |
| last_heartbeat | timestamptz | פינג אחרון מהליסנר | |
| created_at | timestamptz |
agents.id via agent_idnetworks.id via network_idmessages.agent_account_idingestion_health.agent_account_idfolder_sync.py - קרון יומי). קטגוריות: broker, network, affiliate, finance, new, industry, internal. רק broker+network+new נמדדות ומדוּוחות.
| Column | Type | Attributes | Notes |
|---|---|---|---|
| id | bigint | ||
| telegram_chat_id | bigint | מזהה הצ'אט בטלגרם | |
| name | text | כותרת הצ'אט מטלגרם | |
| network_id | bigint | לאיזו רשת שייכת | |
| company_id | bigint | שלב 2: קישור לחברה | |
| category | text | נגזר מתיקיות טלגרם | |
| folder_name | text | שם התיקייה (למשל "Broker 1", "Net 2") | |
| total_messages | integer | קאונטר מד-נורמליזציה | |
| outgoing_messages | integer | הודעות יוצאות בלבד | |
| last_message_at | timestamptz | בדיקת "רדום" מהירה | |
| created_at | timestamptz | ||
| updated_at | timestamptz |
networks.id via network_idcompanies.id via company_idmessages.attributed_group_idgroup_members.group_iddaily_scores.group_idgroup_assignments.group_idattributed_group_id באמצעות התאמה ישירה או היוריסטיקת התאמת חברים.
direction היא המפתח: הודעות outgoing = פעילות הסוכן, הודעות incoming = תגובות מהשוק.
| Column | Type | Attributes | Notes |
|---|---|---|---|
| id | bigint | ||
| telegram_message_id | bigint | מזהה ההודעה המקורי בטלגרם | |
| chat_id | bigint | מזהה הצ'אט בטלגרם | |
| sender_id | bigint | מי שלח (null לפוסטים בערוצים) | |
| direction | text | מטריקה מפתח: outgoing = פעילות סוכן | |
| chat_type | text | ||
| text | text | תוכן ההודעה (null להודעות מדיה בלבד) | |
| timestamp | timestamptz | מתי נשלחה בטלגרם | |
| agent_account_id | bigint | איזה ליסנר קלט את זה | |
| attributed_group_id | bigint | שיוך לקבוצה (גם ל-DM דרך member match) | |
| attribution_method | text | איך בוצע השיוך | |
| reply_to_msg_id | bigint | שרשור: לאיזו הודעה זו תשובה | |
| media_type | text | photo, video, document וכו' | |
| is_edited | boolean | ||
| is_deleted | boolean | ||
| created_at | timestamptz | מתי נכנס ל-DB |
agent_accounts.id via agent_account_idgroups.id via attributed_group_id| Column | Type | Attributes | Notes |
|---|---|---|---|
| id | bigint | ||
| group_id | bigint | ||
| telegram_user_id | bigint | UNIQUE(group_id, telegram_user_id) | |
| first_seen | timestamptz | מתי נראה לראשונה | |
| last_seen | timestamptz | פעילות אחרונה | |
| is_active | boolean |
| Column | Type | Attributes | Notes |
|---|---|---|---|
| id | bigint | ||
| agent_account_id | bigint | ||
| event | text | ||
| timestamp | timestamptz | ||
| details | jsonb | הודעות שגיאה, מטאדאטה |
score_conversations.py שמנתח דפוסי הודעות. רק קבוצות עם קטגוריה broker/network/new מנוקדות. שדה summary מכיל הסבר טקסטואלי לניקוד.
| Column | Type | Attributes | Notes |
|---|---|---|---|
| id | bigint | ||
| group_id | bigint | ||
| date | date | UNIQUE(group_id, date) | |
| score | integer | 0=רדום, 10=מוכן לעסקה | |
| summary | text | הסבר טקסטואלי | |
| created_at | timestamptz |
generate_weekly_report.py.
highlights, follow_ups, concerns הם JSON arrays שמאפשרים הצגה מובנית בדשבורד.
| Column | Type | Attributes | Notes |
|---|---|---|---|
| id | bigint | ||
| agent_id | bigint | ||
| week_start | date | UNIQUE(agent_id, week_start) | |
| week_end | date | ||
| report_text | text | דוח LLM מלא | |
| highlights | jsonb | מערך הדגשות | |
| follow_ups | jsonb | פעולות מומלצות | |
| concerns | jsonb | סיגנלי סיכון | |
| avg_score | numeric | ממוצע daily_scores לשבוע | |
| active_groups | integer | כמה קבוצות פעילות | |
| dormant_groups | integer | כמה קבוצות רדומות | |
| near_deal_count | integer | קבוצות קרובות לסגירה | |
| deals_closed | integer | עסקאות שנסגרו | |
| deals_closed_list | jsonb | פירוט עסקאות סגורות | |
| deals_in_progress | integer | עסקאות בתהליך | |
| deals_in_progress_list | jsonb | פירוט עסקאות בתהליך | |
| created_at | timestamptz |
aliases תומך בהתאמת מותגים מטושטשת (חברה יכולה להופיע כ-"ClickMedia", "Click Media Ltd", "CM" בהקשרים שונים). שדה source מבדיל בין לקוחות פעילים לרשימת הפורטפוליו הלא-פעיל שרועי דיבר עליה.
| Column | Type | Attributes | Notes |
|---|---|---|---|
| id | bigint | ||
| name | text | שם קנוני של החברה | |
| aliases | text[] | שמות חלופיים להתאמה | |
| source | text | ברירת מחדל: 'active_client' | |
| created_at | timestamptz |
sender_id מהודעות לאיש קשר מוכר בחברה. מאפשר ניתוח "מי מחברה X מדבר באילו קבוצות".
| Column | Type | Attributes | Notes |
|---|---|---|---|
| id | bigint | ||
| company_id | bigint | ||
| telegram_user_id | bigint | ||
| display_name | text | ||
| created_at | timestamptz |
match_status עוקב אם העסקה הותאמה אוטומטית לחברה או דורשת סקירה ידנית.
| Column | Type | Attributes | Notes |
|---|---|---|---|
| id | bigint | ||
| network_id | bigint | ||
| agent_id | bigint | ||
| company_id | bigint | ||
| brand_name_raw | text | שם המותג הגולמי מהגיליון | |
| date | date | תאריך העסקה | |
| buy_price | numeric | מחיר קנייה | |
| sell_price | numeric | מחיר מכירה | |
| profit | numeric | sell_price - buy_price | |
| match_status | text | ברירת מחדל: 'unmatched' | |
| created_at | timestamptz |
folder_sync.py, הסיווג קורה אוטומטית ממבנה התיקיות של טלגרם עצמו, מה שהופך שיוך ידני למיותר בפיילוט. ייתכן שינוצל מחדש לתרחישים מרובי-סוכנים בשלב 2.
| Column | Type | Attributes | Notes |
|---|---|---|---|
| id | bigint | ||
| group_id | bigint | ||
| agent_id | bigint | ||
| assigned_at | timestamptz | ||
| unassigned_at | timestamptz | הסרת שיוך רכה |
לכל הטבלאות מופעל RLS. מדיניות נוכחית: גישת קריאה בלבד עבור anon ו-authenticated. כתיבות עוברות דרך הליסנר ב-Python באמצעות מפתח service_role (עוקף RLS). מדיניות הכתיבה היחידה היא groups.UPDATE ל-anon (משמשת את ממשק הסיווג הישן).
flowchart LR
subgraph Telegram["Telegram"]
TG["קבוצות והודעות פרטיות"]
end
subgraph Listener["listener.py\n(VPS ווינדוס)"]
L1["קליטה בזמן אמת"]
L2["מעקב עריכה/מחיקה"]
L3["Heartbeat"]
end
subgraph Supabase["Supabase PostgreSQL"]
M["messages\n317K"]
G["groups\n837"]
GM["group_members\n35"]
IH["ingestion_health\n60K"]
end
subgraph DailyCron["קרונים יומיים"]
FS["folder_sync.py\nסיווג תיקיות"]
SC["score_conversations.py\nניקוד שיחות"]
end
subgraph WeeklyCron["קרון שבועי"]
WR["generate_weekly_report.py\nדוח LLM"]
end
subgraph Analytics["טבלאות אנליטיקס"]
DS["daily_scores\n580"]
WRT["weekly_reports\n5"]
end
subgraph Dashboard["דשבורד אדמין\n(Vercel)"]
D1["scores.html"]
D2["status.html"]
D3["progress.html"]
end
TG --> L1
L1 --> M
L1 --> G
L1 --> GM
L3 --> IH
FS --> G
SC --> DS
M --> SC
DS --> WR
WR --> WRT
M --> Dashboard
DS --> D1
IH --> D2
WRT --> Dashboard