"""Rule-based fraud amount assessment. Classifies each transaction into high / medium / low confidence fraud, and generates initial reason text. """ from app.models.transaction import TransactionRecord from app.models.assessment import ConfidenceLevel FRAUD_KEYWORDS = ["投资", "保证金", "手续费", "解冻", "税费", "充值", "提币", "提现"] def classify_transaction(tx: TransactionRecord) -> tuple[ConfidenceLevel, str, str]: """Return (confidence_level, reason, exclude_reason).""" if tx.is_transit: return ( ConfidenceLevel.low, f"该笔为本人账户间中转({tx.source_app.value} -> {tx.counterparty_name}),不直接计入被骗损失。", "本人账户间互转,仅作为资金路径展示。", ) if tx.direction.value == "in": return ( ConfidenceLevel.low, f"该笔为收入方向交易(+¥{float(tx.amount):,.2f}),通常不属于被骗损失。", "收入交易不计入损失。", ) remark = tx.remark or "" counterparty = tx.counterparty_name or "" confidence = tx.confidence has_fraud_keyword = any(kw in remark or kw in counterparty for kw in FRAUD_KEYWORDS) if confidence >= 0.9 and has_fraud_keyword: return ( ConfidenceLevel.high, f"受害人经{tx.source_app.value}向「{counterparty}」转账¥{float(tx.amount):,.2f}," f"备注为「{remark}」,与诈骗常见话术吻合,OCR置信度{confidence:.0%}。", "", ) if confidence >= 0.85: reason = ( f"受害人经{tx.source_app.value}向「{counterparty}」转账¥{float(tx.amount):,.2f}。" ) if has_fraud_keyword: reason += f"备注「{remark}」含涉诈关键词。" return ConfidenceLevel.high, reason, "" reason += "建议结合笔录确认是否受诱导操作。" return ConfidenceLevel.medium, reason, "如经核实该笔为受害人主动日常消费,应排除。" return ( ConfidenceLevel.medium, f"受害人经{tx.source_app.value}向「{counterparty}」转账¥{float(tx.amount):,.2f}," f"OCR置信度较低({confidence:.0%}),需人工复核。", "OCR置信度不足,可能存在识别误差。", )