baodan/api/insurance/poster/content_builder.py

110 lines
4.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""海报内容构建器 — 将计划书和小册子数据组装为单图/长图模块。"""
import logging
logger = logging.getLogger(__name__)
def build_poster_content(parsed_data: dict, product_rules: dict, output_mode: str = "single") -> dict:
"""组装海报内容模块。
参数:
parsed_data: 计划书解析数据(含 benefit_table
product_rules: 产品小册子解析数据(含 features 来源页)
output_mode: 'single''long'
返回:
结构化的海报内容 dict供前端 PosterHtmlCanvas 使用
"""
content = {
"summary": _build_summary(parsed_data),
"features": _build_features(product_rules),
"benefit_table": _build_benefit_table(parsed_data),
"bonus_mechanism": product_rules.get("bonus_mechanism", ""),
"flexible_options": product_rules.get("flexible_options", []),
"risk_warnings": product_rules.get("risk_warnings", []),
"investment_rules": product_rules.get("investment_rules", {}),
"currency_options": product_rules.get("currency_options", []),
"data_completeness": _assess_completeness(parsed_data, product_rules),
}
return content
def _build_summary(parsed_data: dict) -> dict:
"""构建客户摘要卡片数据。"""
return {
"age": parsed_data.get("age"),
"gender": parsed_data.get("gender"),
"currency": parsed_data.get("currency"),
"sum_assured": parsed_data.get("sum_assured"),
"annual_premium": parsed_data.get("annual_premium"),
"premium_term": parsed_data.get("premium_term"),
"coverage_period": parsed_data.get("coverage_period"),
}
def _build_features(product_rules: dict) -> list:
"""构建产品亮点列表,保留来源页码。
优先使用小册子提取的 features带 source_page
如果小册子无数据,回退到计划书的 key_benefits。
"""
features = product_rules.get("features", [])
if features:
result = []
for f in features[:8]:
item = {
"title": f.get("title", ""),
"summary": f.get("summary", ""),
"source_page": f.get("source_page"),
}
if item["title"]:
result.append(item)
return result
# 回退:使用计划书的 key_benefits
return [] # 由调用方从 parsed_data.key_benefits 补充
def _build_benefit_table(parsed_data: dict) -> list:
"""构建利益演示表数据(供图表组件使用)。"""
table = (
parsed_data.get("benefit_table")
or parsed_data.get("benefit_illustration")
or []
)
if not table:
return []
result = []
for row in table:
entry = {
"year": row.get("year") or row.get("policy_year") or row.get("policyYear") or 0,
"guaranteed": row.get("guaranteed_csv") or row.get("guaranteedCashValue") or row.get("guaranteed") or 0,
"nonGuaranteed": row.get("non_guaranteed") or row.get("nonGuaranteed") or 0,
"totalSurrender": row.get("total_surrender") or row.get("totalSurrenderValue") or row.get("total") or 0,
"deathBenefit": row.get("death_benefit") or row.get("deathBenefit") or 0,
}
if entry["year"] > 0:
result.append(entry)
return result
def _assess_completeness(parsed_data: dict, product_rules: dict) -> dict:
"""评估数据完整度,决定哪些模块应显示。
返回:
{field: bool} 表示各模块是否有足够数据
"""
has_benefit_table = bool(parsed_data.get("benefit_table") or parsed_data.get("benefit_illustration"))
benefit_rows = parsed_data.get("benefit_table") or parsed_data.get("benefit_illustration") or []
return {
"has_summary": bool(parsed_data.get("age") or parsed_data.get("sum_assured")),
"has_benefit_chart": has_benefit_table and len(benefit_rows) >= 3,
"has_features": bool(product_rules.get("features")),
"has_currency_options": bool(product_rules.get("currency_options")),
"has_bonus": bool(product_rules.get("bonus_mechanism")),
"has_flexible_options": bool(product_rules.get("flexible_options")),
"has_risk_warnings": bool(product_rules.get("risk_warnings")),
}