feat: add appointments, campaigns, admin, storage, tests and various updates

- Add new routers: admin, appointments, campaigns
- Add storage service and logging config
- Add migrations directory and test suite with pytest config
- Add supabase_migration_features.sql
- Update models, dependencies, config, and existing routers
- Remove whatsapp_service (deleted)
- Update pyproject.toml and uv.lock dependencies

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
belviskhoremk
2026-04-03 09:11:58 +00:00
parent 9dccc83293
commit 92d4c2fc5e
51 changed files with 7076 additions and 515 deletions

View File

@@ -58,6 +58,12 @@ async def signup(data: UserSignup):
}
).execute()
# Safety-net: ensure user_profiles row exists (trigger should handle it, but just in case)
try:
supabase.table("user_profiles").insert({"user_id": user.id}).execute()
except Exception:
pass # Row may already exist from trigger
token = auth_resp.session.access_token if auth_resp.session else ""
return TokenResponse(
access_token=token,
@@ -66,6 +72,7 @@ async def signup(data: UserSignup):
email=user.email,
company_name=data.company_name,
plan="free",
is_admin=False,
),
)
except HTTPException:
@@ -109,6 +116,13 @@ async def login(data: UserLogin):
)
plan = sub.data[0]["plan"] if sub.data else "free"
# Get is_admin flag
try:
profile = supabase.table("user_profiles").select("is_admin").eq("user_id", user.id).execute()
is_admin = profile.data[0].get("is_admin", False) if profile.data else False
except Exception:
is_admin = False
return TokenResponse(
access_token=auth_resp.session.access_token,
user=UserResponse(
@@ -116,6 +130,7 @@ async def login(data: UserLogin):
email=user.email,
company_name=company_name,
plan=plan,
is_admin=is_admin,
),
)
except HTTPException:
@@ -230,9 +245,16 @@ async def get_me(user=Depends(get_current_user)):
)
plan = sub.data[0]["plan"] if sub.data else "free"
try:
profile = supabase.table("user_profiles").select("is_admin").eq("user_id", user.id).execute()
is_admin = profile.data[0].get("is_admin", False) if profile.data else False
except Exception:
is_admin = False
return UserResponse(
id=user.id,
email=user.email,
company_name=company_name,
plan=plan,
is_admin=is_admin,
)