File size: 2,022 Bytes
80a4a65
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""Per-category completion tracker — powers certificate eligibility.

Idempotent via ``UNIQUE(user_id, category, challenge_id)`` so duplicate
``/api/training/solved`` calls never double-count.
"""

from typing import Optional

import httpx

from app.core.config import SUPABASE_URL, SUPABASE_ANON_KEY
from app.services.supabase_service import supabase_headers


async def record_user_completion(
    user_id: Optional[str],
    team_role: str,
    category: str,
    module: str,
    challenge_id: str,
    xp_awarded: int,
):
    """Insert (or ignore) a row in ``user_completions``."""
    if not user_id:
        return
    if not (SUPABASE_URL and SUPABASE_ANON_KEY):
        return
    headers = supabase_headers(content_type=True)
    headers["Prefer"] = "return=minimal,resolution=ignore-duplicates"
    payload = {
        "user_id": user_id,
        "category": category,
        "module": module,
        "challenge_id": challenge_id,
        "xp_awarded": int(xp_awarded or 0),
    }
    try:
        async with httpx.AsyncClient(timeout=10) as client:
            r = await client.post(
                f"{SUPABASE_URL}/rest/v1/user_completions",
                json=payload,
                headers=headers,
            )
            if r.status_code not in (200, 201):
                print(f"[completions] insert failed {r.status_code}: {r.text[:200]}")
    except Exception as e:
        print(f"[completions] insert exception: {e}")


async def count_completions(user_id: str, category: str) -> int:
    if not (SUPABASE_URL and SUPABASE_ANON_KEY):
        return 0
    url = (
        f"{SUPABASE_URL}/rest/v1/user_completions"
        f"?user_id=eq.{user_id}&category=eq.{category}&select=id"
    )
    try:
        async with httpx.AsyncClient(timeout=10) as client:
            r = await client.get(url, headers=supabase_headers())
            if r.status_code == 200:
                return len(r.json())
    except Exception as e:
        print(f"[completions] count exception: {e}")
    return 0