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