53 lines
2.0 KiB
Python
53 lines
2.0 KiB
Python
"""客户-产品关系中期记忆读取。"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from decimal import Decimal
|
|
from typing import Any
|
|
|
|
from repositories.fin_holdings import FinHoldingsRepo
|
|
|
|
|
|
class CustomerProductMemory:
|
|
"""读取客户持仓及其关联基金产品,供客服上下文使用。"""
|
|
|
|
def __init__(self, *, repository_factory=FinHoldingsRepo):
|
|
self.repository_factory = repository_factory
|
|
|
|
async def list(
|
|
self, db, customer_id: int, *, include_closed: bool = True
|
|
) -> list[dict[str, Any]]:
|
|
"""按客户 ID 返回持仓与产品信息,避免跨客户读取。"""
|
|
holdings = await self.repository_factory(db).list_with_products(
|
|
customer_id, include_closed=include_closed
|
|
)
|
|
return [self._to_dict(holding, product) for holding, product in holdings]
|
|
|
|
@staticmethod
|
|
def _to_dict(holding, product) -> dict[str, Any]:
|
|
"""将持仓和产品 ORM 对象转换为上下文可用的 JSON 友好结构。"""
|
|
def scalar(value):
|
|
return str(value) if isinstance(value, Decimal) else value
|
|
|
|
return {
|
|
"holding_id": holding.id,
|
|
"customer_id": holding.customer_id,
|
|
"product_id": holding.product_id,
|
|
"shares": scalar(holding.shares),
|
|
"cost_amount": scalar(holding.cost_amount),
|
|
"current_value": scalar(holding.current_value),
|
|
"profit_loss": scalar(holding.profit_loss),
|
|
"profit_ratio": scalar(holding.profit_ratio),
|
|
"holding_status": holding.status,
|
|
"holding_create_time": holding.create_time,
|
|
"holding_update_time": holding.update_time,
|
|
"product_code": product.product_code if product else None,
|
|
"product_name": product.product_name if product else None,
|
|
"product_type": product.product_type if product else None,
|
|
"risk_level": product.risk_level if product else None,
|
|
"product_status": product.status if product else None,
|
|
}
|
|
|
|
|
|
__all__ = ["CustomerProductMemory"]
|