Mr-Help commited on
Commit
fa969c2
·
verified ·
1 Parent(s): a42f9f6

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +165 -8
main.py CHANGED
@@ -1,15 +1,172 @@
1
  from fastapi import FastAPI, Request
 
 
 
 
2
 
3
  app = FastAPI()
4
 
5
- @app.post("/receive")
6
- async def receive_data(request: Request):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  try:
8
- data = await request.json()
9
- except:
10
- data = await request.body()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
- print("📥 RECEIVED ON HF BACKEND:")
13
- print(data)
 
 
14
 
15
- return {"status": "ok", "received": data}
 
 
 
 
 
 
1
  from fastapi import FastAPI, Request
2
+ import logging
3
+ import json
4
+ from datetime import datetime, timedelta
5
+ from typing import Any, Dict, List, Tuple
6
 
7
  app = FastAPI()
8
 
9
+ logging.basicConfig(
10
+ level=logging.INFO,
11
+ format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
12
+ )
13
+
14
+ log = logging.getLogger("supabase-receiver")
15
+
16
+
17
+ def extract_records(payload: Any) -> List[Dict]:
18
+ """
19
+ نحاول نطلع records من البودي بأي شكل محتمل:
20
+ - { "record": {...} }
21
+ - { "records": [ {...}, {...} ] }
22
+ - [ {...}, {...} ]
23
+ - أو dict واحد نعتبره row واحد.
24
+ """
25
+ if isinstance(payload, dict):
26
+ if "record" in payload and isinstance(payload["record"], dict):
27
+ return [payload["record"]]
28
+ if "records" in payload and isinstance(payload["records"], list):
29
+ return [r for r in payload["records"] if isinstance(r, dict)]
30
+ return [payload]
31
+ elif isinstance(payload, list):
32
+ return [r for r in payload if isinstance(r, dict)]
33
+ else:
34
+ return []
35
+
36
+
37
+ def parse_lead_timestamp(raw_ts: str) -> Tuple[str, str]:
38
+ """
39
+ يحوّل lead_timestamp إلى:
40
+ - deadline: تاريخ ووقت +24 ساعة (string)
41
+ - due_date: تاريخ فقط (string)
42
+ لو مفيش timestamp هنستخدم الوقت الحالي.
43
+ """
44
+ if not raw_ts:
45
+ now = datetime.utcnow()
46
+ deadline = now + timedelta(hours=24)
47
+ else:
48
+ ts = raw_ts.replace("Z", "+00:00")
49
+ dt = datetime.fromisoformat(ts)
50
+ deadline = dt + timedelta(hours=24)
51
+
52
+ deadline_str = deadline.strftime("%Y-%m-%d %H:%M:%S")
53
+ due_date = deadline.date().isoformat()
54
+ return deadline_str, due_date
55
+
56
+
57
+ def build_odoo_payload_from_lead(lead: Dict) -> Dict:
58
+ """
59
+ نفس المابّينج تقريبًا اللي هنعمله في السيرفر الحقيقي،
60
+ بس هنا عشان نطبع كود جاهز للتست لوكال.
61
+ """
62
+ full_name = lead.get("full_name") or lead.get("name") or "Lead"
63
+ email = lead.get("email") or ""
64
+ phone = lead.get("phone") or ""
65
+ city_from_lead = lead.get("city") or False
66
+ platform = lead.get("platform") or ""
67
+
68
+ lead_ts = lead.get("lead_timestamp")
69
+ deadline_str, due_date = parse_lead_timestamp(lead_ts)
70
+
71
+ body = {
72
+ "name": full_name,
73
+ "date_deadline": deadline_str,
74
+ "user_id": lead.get("lead_id"), # زي ما اتفقنا
75
+ "active": True,
76
+ "kanban_state": "grey",
77
+ "type": "opportunity",
78
+ "stage_id": 18,
79
+ "tag_ids": [],
80
+ "color": 0,
81
+ "adgroup_name": lead.get("campaign_name"),
82
+ "adset_name": lead.get("adset_name"),
83
+ "ad_name": lead.get("ad_name", ""),
84
+ "lead_timestamp": lead_ts,
85
+ "source_id": None,
86
+ "source_company": "Jizan",
87
+ "due_date": due_date,
88
+ "call_logs": "",
89
+ "call_log_result": "",
90
+ "age": None,
91
+ "specialty_id": False,
92
+ "gender_id": False,
93
+ "city_ar": city_from_lead or "غير محدد",
94
+ "email_from": email,
95
+ "city": False,
96
+ "phone": phone,
97
+ "platform": platform,
98
+ }
99
+ return body
100
+
101
+
102
+ def build_python_snippet_for_odoo(payload: Dict) -> str:
103
+ """
104
+ يبني كود Python جاهز تقدر تاخده كوبي-بيست،
105
+ وتستعمله لوكال عشان يبعته لـ Odoo.
106
+ """
107
+ payload_json = json.dumps(payload, ensure_ascii=False, indent=4)
108
+
109
+ snippet = f'''import requests
110
+
111
+ ODOO_LEAD_URL = "https://odoo.binrushd.care/api/crm.lead"
112
+ token = "PASTE_TOKEN_HERE" # حط التوكن اللي جالك من /api/auth/token
113
+
114
+ payload = {payload_json}
115
+
116
+ headers = {{
117
+ "Authorization": f"Bearer {{token}}",
118
+ "Content-Type": "application/json",
119
+ }}
120
+
121
+ resp = requests.post(ODOO_LEAD_URL, json=payload, headers=headers, timeout=30)
122
+ print(resp.status_code)
123
+ print(resp.text)
124
+ '''
125
+ return snippet
126
+
127
+
128
+ @app.post("/")
129
+ async def receive_from_supabase(request: Request):
130
+ """
131
+ Endpoint رئيسي تستقبله Supabase Webhook.
132
+ - يطبع البودي بالكامل في اللوج
133
+ - يطلع أول record
134
+ - يبني منه payload لـ Odoo
135
+ - يطبع كود Python في اللوج تقدر تاخده كوبي-بيست وتجرّبه لوكال.
136
+ """
137
  try:
138
+ body = await request.json()
139
+ except Exception as e:
140
+ log.error("Failed to parse JSON body: %s", e)
141
+ return {"status": "error", "detail": f"Invalid JSON: {e}"}
142
+
143
+ # 1) طباعة البودي الخام
144
+ log.info("=== RAW WEBHOOK BODY FROM SUPABASE ===")
145
+ log.info(json.dumps(body, ensure_ascii=False, indent=2))
146
+
147
+ # 2) استخراج records
148
+ records = extract_records(body)
149
+ if not records:
150
+ log.warning("No records found in webhook payload.")
151
+ return {"status": "ok", "note": "no records in payload"}
152
+
153
+ first = records[0]
154
+ log.info("=== FIRST RECORD (lead) ===")
155
+ log.info(json.dumps(first, ensure_ascii=False, indent=2))
156
+
157
+ # 3) بناء payload لـ Odoo
158
+ odoo_payload = build_odoo_payload_from_lead(first)
159
+ log.info("=== ODOO PAYLOAD (dict) ===")
160
+ log.info(json.dumps(odoo_payload, ensure_ascii=False, indent=2))
161
 
162
+ # 4) توليد كود Python جاهز
163
+ python_snippet = build_python_snippet_for_odoo(odoo_payload)
164
+ log.info("=== PYTHON SNIPPET TO SEND THIS LEAD TO ODOO ===")
165
+ log.info("\n%s", python_snippet)
166
 
167
+ # 5) نرجّع response بسيط
168
+ return {
169
+ "status": "ok",
170
+ "records_received": len(records),
171
+ "preview_odoo_payload": odoo_payload,
172
+ }