File size: 2,581 Bytes
b2be963
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session

from app.db.base import get_db
from app.models.product import Category, Product
from app.schemas.product import CategoryCreate, CategoryResponse
from app.schemas.auth import AuthResponse
from app.core.security import get_current_user

router = APIRouter(prefix="/categories", tags=["Categories"])


@router.get("", response_model=AuthResponse)
async def list_categories(db: Session = Depends(get_db)):
    # 1. Fetch all categories
    all_categories = db.query(Category).all()
    
    # 2. Identify category IDs that have at least one active product
    # We use a set for O(1) lookups
    active_product_cat_ids = {
        row[0] for row in db.query(Product.category_id)
        .filter(Product.is_active == True)
        .distinct()
        .all()
        if row[0] is not None
    }
    
    # 3. Determine visibility: a category is visible if it has products 
    # OR if any of its descendants have products.
    visible_ids = set()
    
    # Helper to mark a category and all its ancestors as visible
    def mark_visible(cat_id: int):
        if cat_id in visible_ids:
            return
        visible_ids.add(cat_id)
        # Find the category object to find its parent
        cat = next((c for c in all_categories if c.id == cat_id), None)
        if cat and cat.parent_id:
            mark_visible(cat.parent_id)
            
    for cat_id in active_product_cat_ids:
        mark_visible(cat_id)
        
    # 4. Filter and Sort
    filtered_categories = [c for c in all_categories if c.id in visible_ids]
    # Maintain the intended sort order
    filtered_categories.sort(key=lambda x: x.sort_order)
    
    items = [CategoryResponse.model_validate(c).model_dump() for c in filtered_categories]

    return AuthResponse(
        isSuccess=True,
        value={"items": items},
        statusCode=200,
    )


@router.post("", response_model=AuthResponse, status_code=status.HTTP_201_CREATED)
async def create_category(

    request: CategoryCreate,

    user_id: int = Depends(get_current_user),

    db: Session = Depends(get_db),

):
    category = Category(
        name_ar=request.name_ar,
        name_en=request.name_en,
        icon=request.icon,
        sort_order=request.sort_order,
    )
    db.add(category)
    db.commit()
    db.refresh(category)

    return AuthResponse(
        isSuccess=True,
        value={"category_id": category.id},
        statusCode=201,
    )