feat: add customer travel records and browse history
This commit is contained in:
1 parent
0139fe6382
commit
6d9a546918
79 files changed
+12362
-112
No files matched your search
@@ -1,13 +1,14 @@
|
||||
from datetime import datetime, time
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from sqlalchemy import select
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, status
|
||||
from sqlalchemy import func, select
|
||||
from sqlalchemy.orm import Session, selectinload
|
||||
from .shared import site_config
|
||||
from ..auth import create_customer_token, optional_customer, require_customer
|
||||
from ..api_response import success_response
|
||||
from ..database import get_db
|
||||
from ..models import ConciergeAdvisor, Customer, DetailRecord, HomeTeamBuilding, HomeWanfaRecommendation, HomeWildArchive, Lead, WanfaCategory
|
||||
from ..schemas import LeadCreateIn, PhoneLoginIn
|
||||
from ..models import ConciergeAdvisor, Customer, CustomerBrowseHistory, DetailRecord, HomeTeamBuilding, HomeWanfaRecommendation, HomeWildArchive, Lead, WanfaCategory, WanfaRoute, utc_now
|
||||
from ..schemas import BrowseHistoryCreateIn, LeadCreateIn, PhoneLoginIn
|
||||
from ..media_urls import resolve_media_url
|
||||
from ..serializers import (
|
||||
public_concierge_advisor_dict,
|
||||
public_home_team_building_dict,
|
||||
@@ -35,6 +36,52 @@ def public_customer_dict(customer: Customer) -> dict:
|
||||
return {"id": customer.id, "phoneMasked": mask_phone(customer.phone)}
|
||||
|
||||
|
||||
def public_vehicle_demand_dict(lead: Lead) -> dict:
|
||||
return {
|
||||
"id": lead.id,
|
||||
"status": lead.status,
|
||||
"contactName": lead.contactName,
|
||||
"phoneMasked": mask_phone(lead.phone),
|
||||
"destination": lead.destination,
|
||||
"travelDate": lead.travelDate.isoformat() if lead.travelDate else None,
|
||||
"peopleCount": lead.peopleCount,
|
||||
"note": lead.note,
|
||||
"vehicleDemand": lead.vehicleDemand or {},
|
||||
"createdAt": lead.createdAt.isoformat(),
|
||||
"updatedAt": lead.updatedAt.isoformat(),
|
||||
}
|
||||
|
||||
|
||||
def public_browse_history_dict(item: CustomerBrowseHistory) -> dict:
|
||||
return {
|
||||
"id": item.id,
|
||||
"itemType": item.itemType,
|
||||
"itemId": item.itemId,
|
||||
"title": item.title,
|
||||
"image": resolve_media_url(item.image) or "",
|
||||
"visitedAt": item.visitedAt.isoformat(),
|
||||
}
|
||||
|
||||
|
||||
def browse_source(item_type: str, item_id: str, db: Session):
|
||||
models = {
|
||||
"wanfa-route": WanfaRoute,
|
||||
"team-building": HomeTeamBuilding,
|
||||
"wild-archive": HomeWildArchive,
|
||||
}
|
||||
model = models.get(item_type)
|
||||
if model is None:
|
||||
raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="浏览内容类型不支持")
|
||||
|
||||
conditions = [model.id == item_id]
|
||||
if hasattr(model, "isActive"):
|
||||
conditions.append(model.isActive.is_(True))
|
||||
source = db.scalar(select(model).where(*conditions))
|
||||
if not source:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="浏览内容不存在")
|
||||
return source
|
||||
|
||||
|
||||
@router.get("/health")
|
||||
def health():
|
||||
return success_response({"ok": True, "service": "miniapp-api"})
|
||||
@@ -170,6 +217,113 @@ def current_customer(customer: Customer = Depends(require_customer)):
|
||||
return success_response(public_customer_dict(customer))
|
||||
|
||||
|
||||
@router.get("/api/public/customer/vehicle-demands")
|
||||
def list_customer_vehicle_demands(
|
||||
pageNum: int = Query(default=1, ge=1),
|
||||
pageSize: int = Query(default=20, ge=1, le=50),
|
||||
customer: Customer = Depends(require_customer),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
filters = [Lead.customerId == customer.id, Lead.leadType == "vehicle"]
|
||||
leads = db.scalars(
|
||||
select(Lead)
|
||||
.where(*filters)
|
||||
.order_by(Lead.createdAt.desc())
|
||||
.offset((pageNum - 1) * pageSize)
|
||||
.limit(pageSize)
|
||||
).all()
|
||||
total = db.scalar(select(func.count()).select_from(Lead).where(*filters)) or 0
|
||||
return success_response(
|
||||
{
|
||||
"items": [public_vehicle_demand_dict(lead) for lead in leads],
|
||||
"total": total,
|
||||
"pageNum": pageNum,
|
||||
"pageSize": pageSize,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@router.get("/api/public/customer/vehicle-demands/{lead_id}")
|
||||
def get_customer_vehicle_demand(
|
||||
lead_id: str,
|
||||
customer: Customer = Depends(require_customer),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
lead = db.scalar(
|
||||
select(Lead).where(
|
||||
Lead.id == lead_id,
|
||||
Lead.customerId == customer.id,
|
||||
Lead.leadType == "vehicle",
|
||||
)
|
||||
)
|
||||
if not lead:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="用车记录不存在")
|
||||
return success_response(public_vehicle_demand_dict(lead))
|
||||
|
||||
|
||||
@router.get("/api/public/customer/browse-history")
|
||||
def list_customer_browse_history(
|
||||
pageNum: int = Query(default=1, ge=1),
|
||||
pageSize: int = Query(default=20, ge=1, le=50),
|
||||
customer: Customer = Depends(require_customer),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
filters = [CustomerBrowseHistory.customerId == customer.id]
|
||||
items = db.scalars(
|
||||
select(CustomerBrowseHistory)
|
||||
.where(*filters)
|
||||
.order_by(CustomerBrowseHistory.visitedAt.desc())
|
||||
.offset((pageNum - 1) * pageSize)
|
||||
.limit(pageSize)
|
||||
).all()
|
||||
total = db.scalar(select(func.count()).select_from(CustomerBrowseHistory).where(*filters)) or 0
|
||||
return success_response(
|
||||
{
|
||||
"items": [public_browse_history_dict(item) for item in items],
|
||||
"total": total,
|
||||
"pageNum": pageNum,
|
||||
"pageSize": pageSize,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@router.post("/api/public/customer/browse-history", status_code=status.HTTP_201_CREATED)
|
||||
def save_customer_browse_history(
|
||||
body: BrowseHistoryCreateIn,
|
||||
customer: Customer = Depends(require_customer),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
source = browse_source(body.itemType, body.itemId, db)
|
||||
item = db.scalar(
|
||||
select(CustomerBrowseHistory).where(
|
||||
CustomerBrowseHistory.customerId == customer.id,
|
||||
CustomerBrowseHistory.itemType == body.itemType,
|
||||
CustomerBrowseHistory.itemId == body.itemId,
|
||||
)
|
||||
)
|
||||
now = utc_now()
|
||||
if item:
|
||||
item.title = source.title
|
||||
item.image = source.image or ""
|
||||
item.visitedAt = now
|
||||
item.updatedAt = now
|
||||
else:
|
||||
item = CustomerBrowseHistory(
|
||||
customerId=customer.id,
|
||||
itemType=body.itemType,
|
||||
itemId=body.itemId,
|
||||
title=source.title,
|
||||
image=source.image or "",
|
||||
visitedAt=now,
|
||||
createdAt=now,
|
||||
updatedAt=now,
|
||||
)
|
||||
db.add(item)
|
||||
db.commit()
|
||||
db.refresh(item)
|
||||
return success_response(public_browse_history_dict(item), status_code=status.HTTP_201_CREATED)
|
||||
|
||||
|
||||
@router.post("/api/public/leads", status_code=status.HTTP_201_CREATED)
|
||||
def create_lead(
|
||||
body: LeadCreateIn,
|
||||
|
||||
Reference in new issue
Block a user