From 07dea36a84535dfdb729774d6fc29d3373de3a78 Mon Sep 17 00:00:00 2001 From: wangwb Date: Tue, 3 Jun 2025 18:35:34 +0800 Subject: [PATCH] [fix][cloudkitty]Add code for optimized download rating PDF file --- dingo_command/api/cloudkitty.py | 11 ++++++++--- dingo_command/api/model/cloudkitty.py | 3 ++- dingo_command/common/cloudkitty_client.py | 3 ++- dingo_command/common/ironic_client.py | 3 ++- dingo_command/services/cloudkitty.py | 17 ++++++++++++----- 5 files changed, 26 insertions(+), 11 deletions(-) diff --git a/dingo_command/api/cloudkitty.py b/dingo_command/api/cloudkitty.py index be794778..291eb21c 100644 --- a/dingo_command/api/cloudkitty.py +++ b/dingo_command/api/cloudkitty.py @@ -3,6 +3,7 @@ from typing import List from fastapi.responses import FileResponse +from urllib.parse import unquote from starlette.background import BackgroundTask from dingo_command.api.model.cloudkitty import CloudKittyRatingSummaryDetail from dingo_command.services.cloudkitty import CloudKittyService @@ -56,7 +57,7 @@ async def download_rating_summary_execl(begin: str = Query(None, description=" ) raise HTTPException(status_code=400, detail="Execl file not found") -@router.post("/cloudkitty/download/ratingSummaryDetail/pdf", summary="下载计费汇总详情PDF", description="下载计费汇总详情PDF") +@router.post("/cloudkitty/download/ratingSummaryDetail/pdf/preprocessing", summary="预处理下载计费汇总详情需要的PDF文件", description="预处理下载计费汇总详情需要的PDF文件") async def download_rating_summary_detail_pdf(detail: List[CloudKittyRatingSummaryDetail], language: str = Query(None, description="当前环境语言")): result_file_pdf_name = "rating_summary_detail_" + format_d8q_timestamp() + ".pdf" @@ -66,18 +67,22 @@ async def download_rating_summary_detail_pdf(detail: List[CloudKittyRatingSummar # 1. 生成PDF文件 try: cloudkitty_service.download_rating_summary_detail_pdf(result_file_pdf_path, detail, language) + return os.path.basename(result_file_pdf_path) except Exception as e: import traceback traceback.print_exc() file_utils.cleanup_temp_file(result_file_pdf_path) raise HTTPException(status_code=400, detail="generate pdf file error") +@router.get("/cloudkitty/download/ratingSummaryDetail/pdf", summary="下载计费汇总详情PDF", description="下载计费汇总详情PDF") +async def download_rating_summary_detail_pdf(filePath: str = Query(None, description="下载PDF文件名称")): # 文件存在则下载 - if os.path.exists(result_file_pdf_path): + result_file_pdf_path = EXCEL_TEMP_DIR + unquote(filePath) + if filePath is not None and os.path.exists(result_file_pdf_path): return FileResponse( path=result_file_pdf_path, media_type="application/octet-stream", - filename=result_file_pdf_name, # 下载时显示的文件名 + filename=unquote(filePath), # 下载时显示的文件名 background=BackgroundTask(file_utils.cleanup_temp_file, result_file_pdf_path) ) raise HTTPException(status_code=400, detail="PDf file not found") diff --git a/dingo_command/api/model/cloudkitty.py b/dingo_command/api/model/cloudkitty.py index 051daac8..30477d3c 100644 --- a/dingo_command/api/model/cloudkitty.py +++ b/dingo_command/api/model/cloudkitty.py @@ -11,7 +11,8 @@ class FlavorObject(BaseModel): class CloudKittyRatingSummaryDetail(BaseModel): service: Optional[str] = Field(None, description="服务类型") - tenant_id: Optional[str] = Field(None, description="租户ID") + tenant_id: Optional[str] = Field(None, description="项目ID") + tenant_name: Optional[str] = Field(None, description="项目名称") end: Optional[str] = Field(None, description="结束时间") total: Optional[str] = Field(None, description="总计") flavor: Optional[List[FlavorObject]] = Field(None, description="描述信息") \ No newline at end of file diff --git a/dingo_command/common/cloudkitty_client.py b/dingo_command/common/cloudkitty_client.py index b112a2af..e134ed26 100644 --- a/dingo_command/common/cloudkitty_client.py +++ b/dingo_command/common/cloudkitty_client.py @@ -1,6 +1,7 @@ import json import uuid from datetime import datetime, timedelta +from oslo_utils import timeutils from functools import wraps import requests @@ -46,7 +47,7 @@ def _is_token_valid(cls): print(f"cloudkitty client single instance id: {instance._singleton_instance_uuid}, token[{instance._current_token}]无效,token过期阈值:{cls.TOKEN_EXPIRY_THRESHOLD}") return False - remaining_time = instance._token_expiry - datetime.utcnow() + remaining_time = instance._token_expiry - timeutils.utcnow() #print(f"cloudkitty client single instance id: {instance._singleton_instance_uuid}, token[{instance._current_token}]剩余时间:{remaining_time}, token过期阈值:{cls.TOKEN_EXPIRY_THRESHOLD}, 当前token是否有效:{remaining_time > cls.TOKEN_EXPIRY_THRESHOLD}") return remaining_time > cls.TOKEN_EXPIRY_THRESHOLD diff --git a/dingo_command/common/ironic_client.py b/dingo_command/common/ironic_client.py index 621e1d20..7fb1a64b 100644 --- a/dingo_command/common/ironic_client.py +++ b/dingo_command/common/ironic_client.py @@ -2,6 +2,7 @@ # self.region_name = region_name import uuid from datetime import datetime, timedelta +from oslo_utils import timeutils from functools import wraps import requests @@ -47,7 +48,7 @@ def _is_token_valid(cls): print(f"ironic client single instance id: {instance._singleton_instance_uuid}, token[{instance._current_token}]无效,token过期阈值:{cls.TOKEN_EXPIRY_THRESHOLD}") return False - remaining_time = instance._token_expiry - datetime.utcnow() + remaining_time = instance._token_expiry - timeutils.utcnow() #print(f"ironic client single instance id: {instance._singleton_instance_uuid}, token[{instance._current_token}]剩余时间:{remaining_time}, token过期阈值:{cls.TOKEN_EXPIRY_THRESHOLD}, 当前token是否有效:{remaining_time > cls.TOKEN_EXPIRY_THRESHOLD}") return remaining_time > cls.TOKEN_EXPIRY_THRESHOLD diff --git a/dingo_command/services/cloudkitty.py b/dingo_command/services/cloudkitty.py index ffe10835..4bace625 100644 --- a/dingo_command/services/cloudkitty.py +++ b/dingo_command/services/cloudkitty.py @@ -166,10 +166,17 @@ def generate_rating_summary_detail_data(self, ratingSummaryDetailList, language) temp_data = [] # 项目ID tenant_id = None if ratingSummaryDetailList is None else ratingSummaryDetailList[0].tenant_id + tenant_name = None if ratingSummaryDetailList is None else ratingSummaryDetailList[0].tenant_name if language is None or language == "EN": - temp_data.append({'Tenant ID': tenant_id}) + if tenant_name is None: + temp_data.append({'Tenant ID': tenant_id}) + else: + temp_data.append({'Tenant Name': tenant_name}) else: - temp_data.append({'项目ID':tenant_id}) + if tenant_name is None: + temp_data.append({'项目ID':tenant_id}) + else: + temp_data.append({'项目名称':tenant_name}) # 开始时间 begin_datatime = None if ratingSummaryDetailList is None or ratingSummaryDetailList[0].flavor is None \ or ratingSummaryDetailList[0].flavor is None or ratingSummaryDetailList[0].flavor[0] is None \ @@ -209,11 +216,11 @@ def generate_rating_summary_detail_data(self, ratingSummaryDetailList, language) temp_instance_flavor_data.append({'instance':ratingSummaryDetail.total}) if ratingSummaryDetail.flavor is not None: if language is None or language == "EN": - temp_instance_flavor_data.append({'VM Type': 'Rate'}) + temp_instance_flavor_data.append({' VM Type': 'Rate'}) else: - temp_instance_flavor_data.append({'云主机类型': '费率'}) + temp_instance_flavor_data.append({' 云主机类型': '费率'}) for flavor in ratingSummaryDetail.flavor: - temp_instance_flavor_data.append({flavor.flavor_name: flavor.rate}) + temp_instance_flavor_data.append({" " + flavor.flavor_name: flavor.rate}) else: temp_non_instance_data.append({ratingSummaryDetail.service:ratingSummaryDetail.total})