import json from typing import Optional from sqlalchemy import select, update from sqlalchemy.ext.asyncio import AsyncSession from app.models.pre_test_template import PreTestTemplate from app.utils.id_gen import generate_id async def create_pre_test_template( user_id: str, db: AsyncSession, name: str, note: Optional[str] = None, platform: Optional[str] = None, external_action: Optional[str] = None, cpa_bid: Optional[float] = None, audience_gender: Optional[str] = None, audience_age: Optional[list] = None, audience_region: Optional[list] = None, audience_network: Optional[list] = None, cus_name: Optional[str] = None, pricing_type: Optional[str] = None, cost_cap: Optional[bool] = None, target_cost: Optional[bool] = None, nobid: Optional[bool] = None, cpc_bid: Optional[float] = None, budget: Optional[float] = None, is_default: Optional[bool] = None, ) -> PreTestTemplate: if is_default: await db.execute( update(PreTestTemplate) .where( PreTestTemplate.user_id == user_id, PreTestTemplate.is_default == True, PreTestTemplate.deleted_at.is_(None), ) .values(is_default=False) ) template = PreTestTemplate( id=generate_id(), user_id=user_id, name=name, note=note, platform=platform, external_action=external_action, cpa_bid=cpa_bid, audience_gender=audience_gender, audience_age=json.dumps(audience_age) if audience_age else None, audience_region=json.dumps(audience_region) if audience_region else None, audience_network=json.dumps(audience_network) if audience_network else None, cus_name=cus_name, pricing_type=pricing_type, cost_cap=cost_cap, target_cost=target_cost, nobid=nobid, cpc_bid=cpc_bid, budget=budget, is_default=is_default, ) db.add(template) await db.commit() await db.refresh(template) return template async def update_pre_test_template( template_id: str, user_id: str, db: AsyncSession, **kwargs, ) -> Optional[PreTestTemplate]: result = await db.execute( select(PreTestTemplate).where( PreTestTemplate.id == template_id, PreTestTemplate.user_id == user_id, PreTestTemplate.deleted_at.is_(None), ) ) template = result.scalar_one_or_none() if not template: return None if kwargs.get("is_default"): await db.execute( update(PreTestTemplate) .where( PreTestTemplate.user_id == user_id, PreTestTemplate.is_default == True, PreTestTemplate.id != template_id, PreTestTemplate.deleted_at.is_(None), ) .values(is_default=False) ) update_data = {} if "name" in kwargs: update_data["name"] = kwargs["name"] if "note" in kwargs: update_data["note"] = kwargs["note"] if "platform" in kwargs: update_data["platform"] = kwargs["platform"] if "external_action" in kwargs: update_data["external_action"] = kwargs["external_action"] if "cpa_bid" in kwargs: update_data["cpa_bid"] = kwargs["cpa_bid"] if "audience_gender" in kwargs: update_data["audience_gender"] = kwargs["audience_gender"] if "audience_age" in kwargs: update_data["audience_age"] = json.dumps(kwargs["audience_age"]) if kwargs["audience_age"] else None if "audience_region" in kwargs: update_data["audience_region"] = json.dumps(kwargs["audience_region"]) if kwargs["audience_region"] else None if "audience_network" in kwargs: update_data["audience_network"] = json.dumps(kwargs["audience_network"]) if kwargs["audience_network"] else None if "cus_name" in kwargs: update_data["cus_name"] = kwargs["cus_name"] if "pricing_type" in kwargs: update_data["pricing_type"] = kwargs["pricing_type"] if "cost_cap" in kwargs: update_data["cost_cap"] = kwargs["cost_cap"] if "target_cost" in kwargs: update_data["target_cost"] = kwargs["target_cost"] if "nobid" in kwargs: update_data["nobid"] = kwargs["nobid"] if "cpc_bid" in kwargs: update_data["cpc_bid"] = kwargs["cpc_bid"] if "budget" in kwargs: update_data["budget"] = kwargs["budget"] if "is_default" in kwargs: update_data["is_default"] = kwargs["is_default"] if update_data: await db.execute( update(PreTestTemplate) .where(PreTestTemplate.id == template_id) .values(**update_data) ) await db.commit() await db.refresh(template) return template async def delete_pre_test_template( template_id: str, user_id: str, db: AsyncSession, ) -> bool: result = await db.execute( select(PreTestTemplate).where( PreTestTemplate.id == template_id, PreTestTemplate.user_id == user_id, PreTestTemplate.deleted_at.is_(None), ) ) template = result.scalar_one_or_none() if not template: return False from datetime import datetime template.deleted_at = datetime.now() await db.commit() return True async def get_pre_test_template( template_id: str, user_id: str, db: AsyncSession, ) -> Optional[PreTestTemplate]: result = await db.execute( select(PreTestTemplate).where( PreTestTemplate.id == template_id, PreTestTemplate.user_id == user_id, PreTestTemplate.deleted_at.is_(None), ) ) return result.scalar_one_or_none() async def get_pre_test_template_list( user_id: str, db: AsyncSession, platform: Optional[str] = None, page: int = 1, page_size: int = 10, ) -> dict: if page < 1: page = 1 if page_size < 1: page_size = 10 if page_size > 100: page_size = 100 query = select(PreTestTemplate).where( PreTestTemplate.user_id == user_id, PreTestTemplate.deleted_at.is_(None), ) if platform: query = query.where(PreTestTemplate.platform == platform) query = query.order_by(PreTestTemplate.is_default.desc(), PreTestTemplate.created_at.desc()) total_result = await db.execute(query.with_only_columns(PreTestTemplate.id)) total = len(total_result.scalars().all()) offset = (page - 1) * page_size query = query.offset(offset).limit(page_size) result = await db.execute(query) templates = result.scalars().all() return { "data": templates, "total": total, "page": page, "page_size": page_size, } async def get_default_template( user_id: str, db: AsyncSession, ) -> Optional[PreTestTemplate]: # 如果有默认模板,返回默认模板 # 如果有多条默认的模板,返回最新创建的模板 # 如果没有设置默认模板,返回最新创建的模板 result = await db.execute( select(PreTestTemplate) .where( PreTestTemplate.user_id == user_id, PreTestTemplate.is_default == True, PreTestTemplate.deleted_at.is_(None), ) .order_by(PreTestTemplate.created_at.desc()) ) template = result.scalar_one_or_none() if template: return template # 如果没有默认模板,返回最新创建的模板 result = await db.execute( select(PreTestTemplate) .where( PreTestTemplate.user_id == user_id, PreTestTemplate.deleted_at.is_(None), ) .order_by(PreTestTemplate.created_at.desc()) ) return result.scalar_one_or_none()