diff --git a/app/services/publish_export.py b/app/services/publish_export.py index fcab298..db99054 100644 --- a/app/services/publish_export.py +++ b/app/services/publish_export.py @@ -54,6 +54,15 @@ def _as_date(v): return None +def _display_name(v, code: str) -> str: + """标的列显示名。downstream_repo.fetch_names 返回 {"name": 简称, "full": 全称} + (取不到的代码它退回 name=代码本身) —— 公示表用简称, 缺简称用全称, 都没有用代码。 + 单元格必须是字符串, 字典直接写会被 openpyxl 拒收 (2026-08-28 实机报错修)。""" + if isinstance(v, dict): + v = v.get("name") or v.get("full") + return str(v) if v else code.split(".")[0] + + def compute_snapshot() -> dict: """组装公示快照: 持仓明细 / 平仓明细 / 汇总 / 当日净值。全部只读。""" today = date.today() @@ -87,7 +96,8 @@ def compute_snapshot() -> dict: od = _as_date(r.get("open_date")) or today chg = (px / cost - 1.0) if cost > 0 else 0.0 holdings.append({ - "account": account, "code": code.split(".")[0], "name": names.get(code) or code, + "account": account, "code": code.split(".")[0], + "name": _display_name(names.get(code), code), "amount": round(cost * qty, 2), "open_date": od, "upd_date": today, "structure": structure, "cost": cost, "qty": qty, "price": round(px, 3), "days": (today - od).days, "per_share": round(px - cost, 3), @@ -106,7 +116,8 @@ def compute_snapshot() -> dict: amt = cost * cq ret = (pnl / amt) if amt > 0 else 0.0 closed.append({ - "account": account, "code": code.split(".")[0], "name": names.get(code) or code, + "account": account, "code": code.split(".")[0], + "name": _display_name(names.get(code), code), "amount": round(amt, 2), "open_date": od, "close_date": cd, "structure": structure, "cost": cost, "qty": cq, "settle": round(settle, 3), "days": (cd - od).days, "per_share": round(settle - cost, 3),