"""Risk prediction use-case orchestration.""" from sqlalchemy.ext.asyncio import AsyncSession from app.core.exceptions import AppException from app.domain.risk_engine import BaselineRiskEngine, IndicatorValue from app.schemas.risk_prediction import ( ModelInfo, RiskAssessmentRequest, RiskAssessmentResult, RiskDimensionScore, RiskFactorResult, ) from app.services.database_risk_scoring import DatabaseRiskScoringService class RiskPredictionService: _engine = BaselineRiskEngine() @classmethod def model_info(cls) -> ModelInfo: return ModelInfo(model_version="database-seven-dimension-v1") @classmethod async def preview( cls, request: RiskAssessmentRequest, session: AsyncSession | None = None, ) -> RiskAssessmentResult: if session and any( value is not None for value in ( request.product_category, request.material_type, request.supplier, request.factory, request.stage_new, request.defect_level, ) ): database_score = await DatabaseRiskScoringService(session).score( category=request.product_category, material=request.material_type, supplier=request.supplier, factory=request.factory, stage=request.stage_new, defect_level=request.defect_level, ) dimensions = [ RiskDimensionScore( dimension=item.name, score=item.score, weight=item.weight, status=item.status, reason=item.reason, sample_size=item.sample_size, raw_value=item.raw_value, ) for item in database_score.dimensions ] return RiskAssessmentResult( subject_id=request.subject_id, score=database_score.score, level=database_score.level, model_version="database-seven-dimension-v1", factors=[ RiskFactorResult( name=item.name, value=round(100 - item.score, 2), weight=item.weight, contribution=round(item.score * item.weight / 100, 2), ) for item in database_score.dimensions ], dimension_scores=dimensions, ) if not request.indicators: raise AppException("请填写产品评估参数", code=422, status_code=422) score = cls._engine.predict( [ IndicatorValue(name=item.name, value=item.value, weight=item.weight) for item in request.indicators ] ) return RiskAssessmentResult( subject_id=request.subject_id, score=score.score, level=score.level, model_version=cls._engine.model_version, factors=[ RiskFactorResult( name=item.name, value=item.value, weight=item.weight, contribution=item.contribution, ) for item in score.factors ], )