guzhi/app/controllers/user_valuation.py
邹方成 c690a95cab feat: 新增发票管理模块和用户端接口
refactor: 优化响应格式和错误处理

fix: 修复文件上传类型校验和删除无用PDF文件

perf: 添加估值评估审核时间字段和查询条件

docs: 更新Docker镜像版本至v1.8

test: 添加响应格式检查脚本

style: 统一API响应数据结构

chore: 清理无用静态文件和更新构建脚本
2025-11-24 16:39:53 +08:00

258 lines
12 KiB
Python

from typing import Optional
from tortoise.expressions import Q
from tortoise.queryset import QuerySet
from app.models.valuation import ValuationAssessment
from app.schemas.valuation import (
UserValuationCreate,
UserValuationQuery,
UserValuationList,
UserValuationOut,
UserValuationDetail
)
class UserValuationController:
"""用户端估值评估控制器"""
def __init__(self):
self.model = ValuationAssessment
async def create_valuation(self, user_id: int, data: UserValuationCreate, calculation_result: dict = None, calculation_input: dict = None, drp_result: float = None, status: str = 'pending') -> UserValuationDetail:
"""用户创建估值评估"""
valuation_data = data.model_dump()
valuation_data['user_id'] = user_id
valuation_data['status'] = "success" # 根据计算结果显示设置状态
# 添加计算结果到数据库
if calculation_result:
valuation_data['model_value_b'] = calculation_result.get('model_value_b')
valuation_data['market_value_c'] = calculation_result.get('market_value_c')
valuation_data['final_value_ab'] = calculation_result.get('final_value_ab')
valuation_data['calculation_result'] = calculation_result
if calculation_input:
valuation_data['calculation_input'] = calculation_input
if drp_result is not None:
valuation_data['dynamic_pledge_rate'] = drp_result
valuation = await self.model.create(**valuation_data)
return await self._to_user_detail(valuation)
async def get_user_valuations(self, user_id: int, query: UserValuationQuery) -> UserValuationList:
"""获取用户的估值评估列表"""
queryset = self.model.filter(user_id=user_id, is_active=True)
# 构建查询条件
if query.status:
queryset = queryset.filter(status=query.status)
if query.asset_name:
queryset = queryset.filter(asset_name__icontains=query.asset_name)
# 计算总数
total = await queryset.count()
# 分页查询
offset = (query.page - 1) * query.size
items = await queryset.offset(offset).limit(query.size).order_by('-created_at')
# 转换为输出模型
user_valuations = [await self._to_user_out(item) for item in items]
pages = (total + query.size - 1) // query.size
return UserValuationList(
items=user_valuations,
total=total,
page=query.page,
size=query.size,
pages=pages
)
async def get_user_valuation_detail(self, user_id: int, valuation_id: int) -> Optional[UserValuationDetail]:
"""获取用户的估值评估详情"""
valuation = await self.model.filter(
id=valuation_id,
user_id=user_id,
is_active=True
).first()
if not valuation:
return None
return await self._to_user_detail(valuation)
async def get_user_valuation_statistics(self, user_id: int) -> dict:
"""获取用户的估值评估统计信息"""
total = await self.model.filter(user_id=user_id, is_active=True).count()
pending = await self.model.filter(user_id=user_id, status='pending', is_active=True).count()
approved = await self.model.filter(user_id=user_id, status='approved', is_active=True).count()
rejected = await self.model.filter(user_id=user_id, status='rejected', is_active=True).count()
return {
'total': total,
'pending': pending,
'approved': approved,
'rejected': rejected
}
async def delete_user_valuation(self, user_id: int, valuation_id: int) -> bool:
"""删除用户的估值评估(软删除)"""
valuation = await self.model.filter(
id=valuation_id,
user_id=user_id,
is_active=True
).first()
if not valuation:
return False
# 软删除:设置 is_active 为 False
await valuation.update_from_dict({'is_active': False}).save()
return True
async def _to_user_out(self, valuation: ValuationAssessment) -> UserValuationOut:
"""转换为用户端输出模型"""
return UserValuationOut(
id=valuation.id,
asset_name=valuation.asset_name,
institution=valuation.institution,
industry=valuation.industry,
annual_revenue=valuation.annual_revenue,
rd_investment=valuation.rd_investment,
three_year_income=valuation.three_year_income,
funding_status=valuation.funding_status,
inheritor_level=valuation.inheritor_level,
inheritor_ages=valuation.inheritor_ages,
inheritor_age_count=valuation.inheritor_age_count,
inheritor_certificates=valuation.inheritor_certificates,
heritage_level=valuation.heritage_level,
heritage_asset_level=valuation.heritage_asset_level,
patent_application_no=valuation.patent_application_no,
patent_remaining_years=valuation.patent_remaining_years,
historical_evidence=valuation.historical_evidence,
patent_certificates=valuation.patent_certificates,
pattern_images=valuation.pattern_images,
report_url=valuation.report_url,
certificate_url=valuation.certificate_url,
application_maturity=valuation.application_maturity,
implementation_stage=valuation.implementation_stage,
application_coverage=valuation.application_coverage,
coverage_area=valuation.coverage_area,
cooperation_depth=valuation.cooperation_depth,
collaboration_type=valuation.collaboration_type,
offline_activities=valuation.offline_activities,
offline_teaching_count=valuation.offline_teaching_count,
online_accounts=valuation.online_accounts,
platform_accounts=valuation.platform_accounts,
sales_volume=valuation.sales_volume,
link_views=valuation.link_views,
circulation=valuation.circulation,
scarcity_level=valuation.scarcity_level,
last_market_activity=valuation.last_market_activity,
market_activity_time=valuation.market_activity_time,
monthly_transaction=valuation.monthly_transaction,
monthly_transaction_amount=valuation.monthly_transaction_amount,
price_fluctuation=valuation.price_fluctuation,
price_range=valuation.price_range,
market_price=valuation.market_price,
credit_code_or_id=valuation.credit_code_or_id,
biz_intro=valuation.biz_intro,
infringement_record=valuation.infringement_record,
patent_count=valuation.patent_count,
esg_value=valuation.esg_value,
policy_matching=valuation.policy_matching,
online_course_views=valuation.online_course_views,
pattern_complexity=valuation.pattern_complexity,
normalized_entropy=valuation.normalized_entropy,
legal_risk=valuation.legal_risk,
base_pledge_rate=valuation.base_pledge_rate,
flow_correction=valuation.flow_correction,
model_value_b=valuation.model_value_b,
market_value_c=valuation.market_value_c,
final_value_ab=valuation.final_value_ab,
dynamic_pledge_rate=valuation.dynamic_pledge_rate,
calculation_result=valuation.calculation_result,
calculation_input=valuation.calculation_input,
status=valuation.status,
admin_notes=valuation.admin_notes,
created_at=valuation.created_at,
updated_at=valuation.updated_at,
is_active=valuation.is_active,
)
async def _to_user_detail(self, valuation: ValuationAssessment) -> UserValuationDetail:
"""转换为用户端详细模型"""
return UserValuationDetail(
id=valuation.id,
asset_name=valuation.asset_name,
institution=valuation.institution,
industry=valuation.industry,
annual_revenue=valuation.annual_revenue,
rd_investment=valuation.rd_investment,
three_year_income=valuation.three_year_income,
funding_status=valuation.funding_status,
inheritor_level=valuation.inheritor_level,
inheritor_ages=valuation.inheritor_ages,
inheritor_age_count=valuation.inheritor_age_count,
inheritor_certificates=valuation.inheritor_certificates,
heritage_level=valuation.heritage_level,
heritage_asset_level=valuation.heritage_asset_level,
patent_application_no=valuation.patent_application_no,
patent_remaining_years=valuation.patent_remaining_years,
historical_evidence=valuation.historical_evidence,
patent_certificates=valuation.patent_certificates,
pattern_images=valuation.pattern_images,
report_url=valuation.report_url,
certificate_url=valuation.certificate_url,
application_maturity=valuation.application_maturity,
implementation_stage=valuation.implementation_stage,
application_coverage=valuation.application_coverage,
coverage_area=valuation.coverage_area,
cooperation_depth=valuation.cooperation_depth,
collaboration_type=valuation.collaboration_type,
offline_activities=valuation.offline_activities,
offline_teaching_count=valuation.offline_teaching_count,
online_accounts=valuation.online_accounts,
platform_accounts=valuation.platform_accounts,
sales_volume=valuation.sales_volume,
link_views=valuation.link_views,
circulation=valuation.circulation,
scarcity_level=valuation.scarcity_level,
last_market_activity=valuation.last_market_activity,
market_activity_time=valuation.market_activity_time,
monthly_transaction=valuation.monthly_transaction,
monthly_transaction_amount=valuation.monthly_transaction_amount,
price_fluctuation=valuation.price_fluctuation,
price_range=valuation.price_range,
market_price=valuation.market_price,
credit_code_or_id=valuation.credit_code_or_id,
biz_intro=valuation.biz_intro,
infringement_record=valuation.infringement_record,
patent_count=valuation.patent_count,
esg_value=valuation.esg_value,
policy_matching=valuation.policy_matching,
online_course_views=valuation.online_course_views,
pattern_complexity=valuation.pattern_complexity,
normalized_entropy=valuation.normalized_entropy,
legal_risk=valuation.legal_risk,
base_pledge_rate=valuation.base_pledge_rate,
flow_correction=valuation.flow_correction,
# 添加计算结果字段
model_value_b=valuation.model_value_b,
market_value_c=valuation.market_value_c,
final_value_ab=valuation.final_value_ab,
dynamic_pledge_rate=valuation.dynamic_pledge_rate,
calculation_result=valuation.calculation_result,
calculation_input=valuation.calculation_input,
status=valuation.status,
admin_notes=valuation.admin_notes,
created_at=valuation.created_at,
updated_at=valuation.updated_at
)
# 创建控制器实例
user_valuation_controller = UserValuationController()