File size: 3,510 Bytes
9d4bd7c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
from fastapi import APIRouter, BackgroundTasks
from .models import UTTFund, UTTFundData
from .schemas import UTTFundResponse, UTTFundListResponse, ResponseModel
from .service import fetch_all_utt_data, parse_utt_api_row
from App.routers.tasks.models import ImportTask
from App.routers.utt.utils import run_utt_import_task
from App.schemas import AppException
from tortoise.contrib.pydantic import pydantic_queryset_creator


UTTFundData_Pydantic_List = pydantic_queryset_creator(UTTFundData)
UTTFund_Pydantic_List = pydantic_queryset_creator(UTTFund)

router = APIRouter(prefix="/utt", tags=["UTT"])


@router.get("/", response_model=ResponseModel)
async def list_funds_orm():
    """
    Alternative using Tortoise ORM - less efficient but more ORM-friendly
    """
    try:
        # Get all funds
        funds = await UTTFund.all()

        if not funds:
            raise AppException(status_code=404, detail="No UTT funds found")

        # Get latest data for each fund
        fund_ids = [fund.id for fund in funds]
        latest_data = {}

        # For each fund, get only the latest data (most recent date)
        for fund_id in fund_ids:
            latest = await UTTFundData.filter(fund_id=fund_id).order_by("-date").first()

            if latest:
                latest_data[fund_id] = latest

        # Build the response
        fund_list = []
        for fund in funds:
            latest = latest_data.get(fund.id)

            fund_data = {
                "id": fund.id,
                "symbol": fund.symbol,
                "name": fund.name,
                "nav_per_unit": latest.nav_per_unit if latest else None,
                "sale_price_per_unit": latest.sale_price_per_unit if latest else None,
                "repurchase_price_per_unit": (
                    latest.repurchase_price_per_unit if latest else None
                ),
                "outstanding_number_of_units": (
                    latest.outstanding_number_of_units if latest else None
                ),
                "net_asset_value": latest.net_asset_value if latest else None,
                "latest_date": latest.date.isoformat() if latest else None,
            }
            fund_list.append(fund_data)

        return ResponseModel(
            success=True,
            message=f"Retrieved {len(fund_list)} UTT funds with latest data",
            data={"funds": fund_list, "count": len(fund_list)},
        )

    except Exception as e:
        raise AppException(
            status_code=500, detail=f"Error retrieving UTT funds: {str(e)}"
        )


@router.get("/{symbol}", response_model=ResponseModel)
async def get_fund_data(symbol: str):
    fund = await UTTFund.get_or_none(symbol=symbol)
    if not fund:
        raise AppException(status_code=404, detail="Fund not found")
    data_queryset = UTTFundData.filter(fund=fund).order_by("-date").limit(100)
    utt_fund_data_pydantic = await UTTFundData_Pydantic_List.from_queryset(
        data_queryset
    )

    return ResponseModel(
        success=True,
        message="Fund data",
        data={"data": utt_fund_data_pydantic.model_dump()},
    )


@router.post("/import-all", response_model=ResponseModel)
async def queue_import_utt(background_tasks: BackgroundTasks):
    task = await ImportTask.create(task_type="utt", status="pending", details={})
    background_tasks.add_task(run_utt_import_task, task.id)
    return ResponseModel(
        success=True, message="UTT import task queued", data={"task_id": task.id}
    )