diff --git a/app/repository/risk_repository.py b/app/repository/risk_repository.py index 97d3493..0500b94 100644 --- a/app/repository/risk_repository.py +++ b/app/repository/risk_repository.py @@ -7,6 +7,7 @@ from __future__ import annotations +import json from collections.abc import Callable from dataclasses import dataclass from datetime import UTC, date, datetime @@ -753,7 +754,14 @@ class RiskRepository: if risk_level: conditions.append(FundRiskAlert.alert_level == risk_level) if rule_code: - conditions.append(FundRiskAlert.trigger_rule_codes.contains([rule_code])) + # 必须用 `JSON_CONTAINS`,**不能用 `.contains([rule_code])`**: + # SQLAlchemy 会把 `.contains()` 编译成 `LIKE`(见 compiler 的 + # `visit_contains_op_binary -> visit_like_op_binary`), + # 对 JSON 数组列等于在匹配 `'["RW-015"]'` 这个字符串, + # 于是 `rule_code` 筛选**恒返回 0 条**,而且不报任何错。 + conditions.append( + func.json_contains(FundRiskAlert.trigger_rule_codes, json.dumps(rule_code)) + ) if start_time is not None: conditions.append(FundRiskAlert.created_at >= start_time) if end_time is not None: diff --git a/app/service/risk_scan_service.py b/app/service/risk_scan_service.py index 9a203da..761bef5 100644 --- a/app/service/risk_scan_service.py +++ b/app/service/risk_scan_service.py @@ -7,6 +7,7 @@ from __future__ import annotations import asyncio +import json import logging from datetime import UTC, date, datetime, timedelta from decimal import Decimal @@ -452,7 +453,9 @@ class RiskRuleEngine: return await self.session.scalar( select(FundRiskAlert.id).where( FundRiskAlert.related_transaction_id == transaction_id, - FundRiskAlert.trigger_rule_codes.contains([rule_code]), + # 同 risk_repository:`.contains()` 会被编译成 `LIKE`, + # 对 JSON 数组列永远不匹配,去重就形同失效。 + func.json_contains(FundRiskAlert.trigger_rule_codes, json.dumps(rule_code)), ) ) is not None diff --git a/app/service/trade_service.py b/app/service/trade_service.py index d9aae4e..174075f 100644 --- a/app/service/trade_service.py +++ b/app/service/trade_service.py @@ -24,6 +24,7 @@ from __future__ import annotations from dataclasses import dataclass from datetime import UTC, datetime, timedelta from decimal import ROUND_HALF_UP, Decimal +from typing import Any from uuid import uuid4 from sqlalchemy import func, select @@ -105,7 +106,7 @@ class TradeService: self._session = session self._suitability_evaluator = suitability_evaluator - async def _next_id(self, model: type) -> int: + async def _next_id(self, model: Any) -> int: """返回 ``model`` 表的下一个可用主键。 底座 ``fin_*`` 表 ``id`` 列实际**未**配置 AUTO_INCREMENT(与 ``docs/00`` 设计稿