Upload three_year_tool.py
Browse files- service/three_year_tool.py +52 -21
service/three_year_tool.py
CHANGED
|
@@ -20,10 +20,15 @@ def safe_float(val, default=0.0):
|
|
| 20 |
return default
|
| 21 |
|
| 22 |
# -----------------------------
|
| 23 |
-
# 步骤1
|
| 24 |
# -----------------------------
|
| 25 |
def extract_last_three_with_fallback(data_list):
|
| 26 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
priority_levels = [
|
| 28 |
("FY", [f"FY{y}" for y in years]),
|
| 29 |
("Q4", [f"{y}Q4" for y in years]),
|
|
@@ -34,6 +39,7 @@ def extract_last_three_with_fallback(data_list):
|
|
| 34 |
|
| 35 |
data_map = {item["period"]: item for item in data_list if isinstance(item, dict) and "period" in item}
|
| 36 |
|
|
|
|
| 37 |
for level_name, periods in priority_levels:
|
| 38 |
records = []
|
| 39 |
valid = True
|
|
@@ -42,7 +48,12 @@ def extract_last_three_with_fallback(data_list):
|
|
| 42 |
if not isinstance(item, dict) or item.get("total_revenue") is None:
|
| 43 |
valid = False
|
| 44 |
break
|
| 45 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
records.append({
|
| 47 |
"period": period,
|
| 48 |
"fiscal_year": fiscal_year,
|
|
@@ -56,13 +67,17 @@ def extract_last_three_with_fallback(data_list):
|
|
| 56 |
if valid:
|
| 57 |
return records
|
| 58 |
|
| 59 |
-
# Fallback:
|
| 60 |
for level_name, periods in priority_levels:
|
| 61 |
records = []
|
| 62 |
for period in periods:
|
| 63 |
item = data_map.get(period)
|
| 64 |
if isinstance(item, dict) and item.get("total_revenue") is not None:
|
| 65 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
records.append({
|
| 67 |
"period": period,
|
| 68 |
"fiscal_year": fiscal_year,
|
|
@@ -191,6 +206,8 @@ def build_financial_metrics(three_year_data):
|
|
| 191 |
def process_financial_data_with_metadata(raw_data):
|
| 192 |
"""
|
| 193 |
返回包含 financial_metrics + year_data + three_year_data 的完整结果
|
|
|
|
|
|
|
| 194 |
"""
|
| 195 |
return_value = {"financial_metrics": [], "year_data": "N/A", "three_year_data": []}
|
| 196 |
if not raw_data:
|
|
@@ -199,37 +216,51 @@ def process_financial_data_with_metadata(raw_data):
|
|
| 199 |
return return_value
|
| 200 |
if not isinstance(raw_data[0], dict):
|
| 201 |
return {"financial_metrics": [], "year_data": "N/A", "three_year_data": []}
|
|
|
|
| 202 |
# 1. 解析输入
|
| 203 |
if isinstance(raw_data, str):
|
| 204 |
raw_data = json.loads(raw_data)
|
| 205 |
if not isinstance(raw_data, list):
|
| 206 |
raise TypeError("raw_data 必须是列表或 JSON 字符串")
|
| 207 |
|
| 208 |
-
# 2.
|
| 209 |
-
|
| 210 |
-
if not
|
| 211 |
-
print("
|
| 212 |
-
# raise ValueError("无法提取有效的三年财务数据")
|
| 213 |
return return_value
|
| 214 |
-
|
| 215 |
-
#
|
| 216 |
-
|
| 217 |
-
|
| 218 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 219 |
|
| 220 |
if level == "FY":
|
| 221 |
year_data = f"{year} FY"
|
| 222 |
else: # Q1, Q2, Q3, Q4
|
| 223 |
year_data = f"{year} {level}"
|
| 224 |
|
| 225 |
-
#
|
| 226 |
-
financial_metrics = build_financial_metrics(
|
| 227 |
|
| 228 |
-
#
|
| 229 |
return {
|
| 230 |
-
"financial_metrics": financial_metrics,
|
| 231 |
-
"year_data": year_data,
|
| 232 |
-
"three_year_data":
|
| 233 |
}
|
| 234 |
|
| 235 |
# -----------------------------
|
|
|
|
| 20 |
return default
|
| 21 |
|
| 22 |
# -----------------------------
|
| 23 |
+
# 步骤1:提取带 fallback 的数据(支持最新年+历史3年)
|
| 24 |
# -----------------------------
|
| 25 |
def extract_last_three_with_fallback(data_list):
|
| 26 |
+
"""
|
| 27 |
+
从数据列表中提取最新的4年数据(最新1年 + 历史3年)
|
| 28 |
+
优先级: FY > Q4 > Q3 > Q2 > Q1
|
| 29 |
+
返回: 最新的4个period的数据
|
| 30 |
+
"""
|
| 31 |
+
years = [2025, 2024, 2023, 2022] # 扩展到4年
|
| 32 |
priority_levels = [
|
| 33 |
("FY", [f"FY{y}" for y in years]),
|
| 34 |
("Q4", [f"{y}Q4" for y in years]),
|
|
|
|
| 39 |
|
| 40 |
data_map = {item["period"]: item for item in data_list if isinstance(item, dict) and "period" in item}
|
| 41 |
|
| 42 |
+
# 尝试找到完整的4年数据
|
| 43 |
for level_name, periods in priority_levels:
|
| 44 |
records = []
|
| 45 |
valid = True
|
|
|
|
| 48 |
if not isinstance(item, dict) or item.get("total_revenue") is None:
|
| 49 |
valid = False
|
| 50 |
break
|
| 51 |
+
# 从period中提取fiscal_year
|
| 52 |
+
if level_name == "FY":
|
| 53 |
+
fiscal_year = int(period[2:]) # FY2025 -> 2025
|
| 54 |
+
else:
|
| 55 |
+
fiscal_year = int(period[:4]) # 2025Q3 -> 2025
|
| 56 |
+
|
| 57 |
records.append({
|
| 58 |
"period": period,
|
| 59 |
"fiscal_year": fiscal_year,
|
|
|
|
| 67 |
if valid:
|
| 68 |
return records
|
| 69 |
|
| 70 |
+
# Fallback: 返回第一个有数据的层级(即使不全)
|
| 71 |
for level_name, periods in priority_levels:
|
| 72 |
records = []
|
| 73 |
for period in periods:
|
| 74 |
item = data_map.get(period)
|
| 75 |
if isinstance(item, dict) and item.get("total_revenue") is not None:
|
| 76 |
+
if level_name == "FY":
|
| 77 |
+
fiscal_year = int(period[2:])
|
| 78 |
+
else:
|
| 79 |
+
fiscal_year = int(period[:4])
|
| 80 |
+
|
| 81 |
records.append({
|
| 82 |
"period": period,
|
| 83 |
"fiscal_year": fiscal_year,
|
|
|
|
| 206 |
def process_financial_data_with_metadata(raw_data):
|
| 207 |
"""
|
| 208 |
返回包含 financial_metrics + year_data + three_year_data 的完整结果
|
| 209 |
+
financial_metrics: 最新1年的指标(与前一年对比)
|
| 210 |
+
three_year_data: 最新的前3年数据(排除最新年,用于Latest 3 Years表格)
|
| 211 |
"""
|
| 212 |
return_value = {"financial_metrics": [], "year_data": "N/A", "three_year_data": []}
|
| 213 |
if not raw_data:
|
|
|
|
| 216 |
return return_value
|
| 217 |
if not isinstance(raw_data[0], dict):
|
| 218 |
return {"financial_metrics": [], "year_data": "N/A", "three_year_data": []}
|
| 219 |
+
|
| 220 |
# 1. 解析输入
|
| 221 |
if isinstance(raw_data, str):
|
| 222 |
raw_data = json.loads(raw_data)
|
| 223 |
if not isinstance(raw_data, list):
|
| 224 |
raise TypeError("raw_data 必须是列表或 JSON 字符串")
|
| 225 |
|
| 226 |
+
# 2. 提取4年数据(最新1年 + 历史3年,带 fallback)
|
| 227 |
+
four_years = extract_last_three_with_fallback(raw_data)
|
| 228 |
+
if not four_years:
|
| 229 |
+
print("无法提取有效的财务数据")
|
|
|
|
| 230 |
return return_value
|
| 231 |
+
|
| 232 |
+
# 按fiscal_year降序排序
|
| 233 |
+
four_years_sorted = sorted(four_years, key=lambda x: x["fiscal_year"], reverse=True)
|
| 234 |
+
|
| 235 |
+
# 3. 分离最新1年和历史3年
|
| 236 |
+
if len(four_years_sorted) < 2:
|
| 237 |
+
print("数据不足,至少需要2年数据")
|
| 238 |
+
return return_value
|
| 239 |
+
|
| 240 |
+
# 最新年用于financial_metrics
|
| 241 |
+
latest_year = four_years_sorted[0]
|
| 242 |
+
previous_year = four_years_sorted[1]
|
| 243 |
+
|
| 244 |
+
# 历史3年用于three_year_data表格(排除最新年)
|
| 245 |
+
three_years_for_table = four_years_sorted[1:4] if len(four_years_sorted) >= 4 else four_years_sorted[1:]
|
| 246 |
+
|
| 247 |
+
# 4. 获取最新年份和报告类型(用于 year_data)
|
| 248 |
+
year = latest_year["fiscal_year"]
|
| 249 |
+
level = latest_year["level"]
|
| 250 |
|
| 251 |
if level == "FY":
|
| 252 |
year_data = f"{year} FY"
|
| 253 |
else: # Q1, Q2, Q3, Q4
|
| 254 |
year_data = f"{year} {level}"
|
| 255 |
|
| 256 |
+
# 5. 构建最新年的financial_metrics(与前一年对比)
|
| 257 |
+
financial_metrics = build_financial_metrics([latest_year, previous_year])
|
| 258 |
|
| 259 |
+
# 6. 返回完整结构
|
| 260 |
return {
|
| 261 |
+
"financial_metrics": financial_metrics, # 最新1年的指标
|
| 262 |
+
"year_data": year_data, # 最新年份标签
|
| 263 |
+
"three_year_data": three_years_for_table # 历史3年数据(用于表格)
|
| 264 |
}
|
| 265 |
|
| 266 |
# -----------------------------
|