|
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: |
|
|
|
funds = await UTTFund.all() |
|
|
|
if not funds: |
|
raise AppException(status_code=404, detail="No UTT funds found") |
|
|
|
|
|
fund_ids = [fund.id for fund in funds] |
|
latest_data = {} |
|
|
|
|
|
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 |
|
|
|
|
|
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} |
|
) |
|
|