from __future__ import annotations from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.orm import Session from app.database import get_db from app.auth import get_current_user from app.models.product import ( ProductConfig, ProductVersion, ProductVersionHighlight, SummerCamp, SummerCampPrinciple, SummerCampActivity, SummerCampItinerary, SummerCampFaq, SelectionGuide, ) from app.schemas.product import ( ProductConfigSchema, ProductVersionSchema, ProductVersionResponse, SummerCampSchema, SelectionGuideSchema, ) router = APIRouter(prefix="/api/products", tags=["产品管理"], dependencies=[Depends(get_current_user)]) def _get_config(db: Session) -> ProductConfig: config = db.query(ProductConfig).first() if not config: config = ProductConfig() db.add(config) db.flush() return config @router.get("/config", response_model=ProductConfigSchema) def get_config(db: Session = Depends(get_db)): config = _get_config(db) return ProductConfigSchema(narrative=config.narrative, pricing_philosophy=config.pricing_philosophy) @router.put("/config") def update_config(req: ProductConfigSchema, db: Session = Depends(get_db)): config = _get_config(db) config.narrative = req.narrative config.pricing_philosophy = req.pricing_philosophy db.commit() return {"message": "更新成功"} @router.get("/versions", response_model=list[ProductVersionResponse]) def list_versions(db: Session = Depends(get_db)): config = _get_config(db) versions = db.query(ProductVersion).filter_by(config_id=config.id).order_by(ProductVersion.sort_order).all() result = [] for v in versions: resp = ProductVersionResponse( id=v.id, version_id=v.version_id, name=v.name, days=v.days, nights=v.nights, audience=v.audience, description=v.description, tag=v.tag, sort_order=v.sort_order, highlights=[h.text for h in v.highlights], ) result.append(resp) return result @router.post("/versions", response_model=ProductVersionResponse, status_code=201) def create_version(req: ProductVersionSchema, db: Session = Depends(get_db)): config = _get_config(db) v = ProductVersion( config_id=config.id, version_id=req.version_id, name=req.name, days=req.days, nights=req.nights, audience=req.audience, description=req.description, tag=req.tag, ) db.add(v) db.flush() for i, h in enumerate(req.highlights): db.add(ProductVersionHighlight(version_id=v.id, text=h, sort_order=i)) db.commit() db.refresh(v) return ProductVersionResponse( id=v.id, version_id=v.version_id, name=v.name, days=v.days, nights=v.nights, audience=v.audience, description=v.description, tag=v.tag, sort_order=v.sort_order, highlights=[h.text for h in v.highlights], ) @router.put("/versions/{v_id}") def update_version(v_id: int, req: ProductVersionSchema, db: Session = Depends(get_db)): v = db.query(ProductVersion).get(v_id) if not v: raise HTTPException(status_code=404, detail="版本不存在") v.version_id = req.version_id v.name = req.name v.days = req.days v.nights = req.nights v.audience = req.audience v.description = req.description v.tag = req.tag # Replace highlights db.query(ProductVersionHighlight).filter_by(version_id=v.id).delete() for i, h in enumerate(req.highlights): db.add(ProductVersionHighlight(version_id=v.id, text=h, sort_order=i)) db.commit() return {"message": "更新成功"} @router.delete("/versions/{v_id}") def delete_version(v_id: int, db: Session = Depends(get_db)): v = db.query(ProductVersion).get(v_id) if not v: raise HTTPException(status_code=404, detail="版本不存在") db.delete(v) db.commit() return {"message": "删除成功"} @router.get("/summer-camp", response_model=SummerCampSchema) def get_summer_camp(db: Session = Depends(get_db)): config = _get_config(db) camp = db.query(SummerCamp).filter_by(config_id=config.id).first() if not camp: return SummerCampSchema() return SummerCampSchema( name=camp.name, positioning=camp.positioning, days=camp.days, nights=camp.nights, sessions=camp.sessions_json, difference_from_v9=camp.difference_from_v9, principles=[p.text for p in camp.principles], activities=[a.text for a in camp.activities], itinerary=[it.text for it in camp.itinerary], faq=[{"question": f.question, "answer": f.answer} for f in camp.faq], ) @router.put("/summer-camp") def update_summer_camp(req: SummerCampSchema, db: Session = Depends(get_db)): config = _get_config(db) camp = db.query(SummerCamp).filter_by(config_id=config.id).first() if not camp: camp = SummerCamp(config_id=config.id) db.add(camp) db.flush() camp.name = req.name camp.positioning = req.positioning camp.days = req.days camp.nights = req.nights camp.sessions_json = req.sessions camp.difference_from_v9 = req.difference_from_v9 # Replace sub-collections db.query(SummerCampPrinciple).filter_by(camp_id=camp.id).delete() for i, p in enumerate(req.principles): db.add(SummerCampPrinciple(camp_id=camp.id, text=p, sort_order=i)) db.query(SummerCampActivity).filter_by(camp_id=camp.id).delete() for i, a in enumerate(req.activities): db.add(SummerCampActivity(camp_id=camp.id, text=a, sort_order=i)) db.query(SummerCampItinerary).filter_by(camp_id=camp.id).delete() for i, it in enumerate(req.itinerary): db.add(SummerCampItinerary(camp_id=camp.id, text=it, sort_order=i)) db.query(SummerCampFaq).filter_by(camp_id=camp.id).delete() for i, f in enumerate(req.faq): db.add(SummerCampFaq(camp_id=camp.id, question=f.question, answer=f.answer, sort_order=i)) db.commit() return {"message": "夏令营更新成功"} @router.get("/selection-guide", response_model=SelectionGuideSchema) def get_selection_guide(db: Session = Depends(get_db)): config = _get_config(db) guide = db.query(SelectionGuide).filter_by(config_id=config.id).first() if not guide: return SelectionGuideSchema() return SelectionGuideSchema( by_vacation_length=guide.by_vacation_length or [], by_child_age=guide.by_child_age or [], by_preference=guide.by_preference or [], ) @router.put("/selection-guide") def update_selection_guide(req: SelectionGuideSchema, db: Session = Depends(get_db)): config = _get_config(db) guide = db.query(SelectionGuide).filter_by(config_id=config.id).first() if not guide: guide = SelectionGuide(config_id=config.id) db.add(guide) guide.by_vacation_length = req.by_vacation_length guide.by_child_age = req.by_child_age guide.by_preference = req.by_preference db.commit() return {"message": "选品指南更新成功"}