Add directly purchased cars to My Requests page
- Add new /my-vehicles API endpoint returning both recommended and direct purchases - Add DirectPurchasedCarResponse and MyVehiclesResponse schemas - Update frontend to display directly purchased cars (from banners with 1CC) - Show separate collapsible section for direct purchases 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,12 +4,12 @@ from typing import List
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from ..database import get_db
|
||||
from ..models import VehicleRequest, RequestVehicle, PurchasedVehicle, User, DealerInfo, SystemSettings, Car
|
||||
from ..models import VehicleRequest, RequestVehicle, PurchasedVehicle, User, DealerInfo, SystemSettings, Car, CarView
|
||||
from ..schemas import (
|
||||
VehicleRequestCreate, VehicleRequestResponse,
|
||||
RequestVehicleCreate, RequestVehicleResponse, RequestVehicleApprove,
|
||||
PurchasedVehicleCreate, PurchasedVehicleResponse, PurchasedVehicleUpdateStatus,
|
||||
VehicleRequestWithVehicles,
|
||||
VehicleRequestWithVehicles, DirectPurchasedCarResponse, MyVehiclesResponse,
|
||||
)
|
||||
from .auth import get_current_user
|
||||
from .notification import notify_vehicle_recommended, notify_shipping_update
|
||||
@@ -120,6 +120,97 @@ def get_my_requests(
|
||||
return result
|
||||
|
||||
|
||||
@router.get("/my-vehicles", response_model=MyVehiclesResponse)
|
||||
def get_my_vehicles(
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""Get all vehicles accessible to user: recommended + directly purchased from banners"""
|
||||
|
||||
# 1. Get vehicle requests with recommended vehicles (existing logic)
|
||||
requests = db.query(VehicleRequest).filter(
|
||||
VehicleRequest.user_id == current_user.id
|
||||
).order_by(VehicleRequest.created_at.desc()).all()
|
||||
|
||||
vehicle_requests = []
|
||||
for req in requests:
|
||||
if DEV_MODE or (req.created_at and datetime.utcnow() - req.created_at > timedelta(hours=24)):
|
||||
approved_vehicles = [v for v in req.recommended_vehicles if v.is_approved]
|
||||
else:
|
||||
approved_vehicles = []
|
||||
|
||||
enriched_vehicles = []
|
||||
for v in approved_vehicles:
|
||||
vehicle_response = RequestVehicleResponse.model_validate(v)
|
||||
if v.car_id:
|
||||
car = db.query(Car).filter(Car.id == v.car_id).first()
|
||||
if car:
|
||||
vehicle_response.car_data = {**vehicle_response.car_data, "soldout": car.soldout}
|
||||
enriched_vehicles.append(vehicle_response)
|
||||
|
||||
vehicle_requests.append(VehicleRequestWithVehicles(
|
||||
request=VehicleRequestResponse.model_validate(req),
|
||||
approved_vehicles=enriched_vehicles
|
||||
))
|
||||
|
||||
# 2. Get directly purchased cars (from CarView - paid 1CC on banner)
|
||||
car_views = db.query(CarView).filter(
|
||||
CarView.user_id == current_user.id
|
||||
).order_by(CarView.created_at.desc()).all()
|
||||
|
||||
# Get the car_ids that are already in recommended vehicles (to avoid duplicates)
|
||||
recommended_car_ids = set()
|
||||
for vr in vehicle_requests:
|
||||
for v in vr.approved_vehicles:
|
||||
if v.car_id:
|
||||
recommended_car_ids.add(v.car_id)
|
||||
|
||||
direct_purchases = []
|
||||
for cv in car_views:
|
||||
# Skip if already in recommended (user got recommendation first, then it's not a "direct" purchase)
|
||||
if cv.car_id in recommended_car_ids:
|
||||
continue
|
||||
|
||||
car = db.query(Car).filter(Car.id == cv.car_id).first()
|
||||
if car:
|
||||
# Build car_data similar to recommended vehicles
|
||||
main_image = None
|
||||
if car.images:
|
||||
main_img = next((img for img in car.images if img.is_main), None)
|
||||
if main_img:
|
||||
main_image = main_img.url
|
||||
elif car.images:
|
||||
main_image = car.images[0].url
|
||||
|
||||
car_data = {
|
||||
"id": str(car.source_id) if car.source_id else str(car.id),
|
||||
"car_name": car.car_name,
|
||||
"maker_name": car.maker.name if car.maker else None,
|
||||
"year": car.year,
|
||||
"mileage": car.mileage,
|
||||
"final_price": car.final_price_krw,
|
||||
"fuel": car.fuel,
|
||||
"transmission": car.transmission,
|
||||
"color": car.color,
|
||||
"main_image": main_image,
|
||||
"soldout": car.soldout,
|
||||
"local_car_id": car.id,
|
||||
}
|
||||
|
||||
direct_purchases.append(DirectPurchasedCarResponse(
|
||||
id=cv.id,
|
||||
car_id=cv.car_id,
|
||||
car_data=car_data,
|
||||
cc_paid=cv.cc_paid,
|
||||
purchased_at=cv.created_at
|
||||
))
|
||||
|
||||
return MyVehiclesResponse(
|
||||
vehicle_requests=vehicle_requests,
|
||||
direct_purchases=direct_purchases
|
||||
)
|
||||
|
||||
|
||||
# =====================
|
||||
# Purchased Vehicles (Find My Car)
|
||||
# =====================
|
||||
|
||||
@@ -123,3 +123,21 @@ class VehicleRequestWithVehicles(BaseModel):
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
# Directly purchased car (from CarView - when user pays 1CC on banner car)
|
||||
class DirectPurchasedCarResponse(BaseModel):
|
||||
id: int # CarView id
|
||||
car_id: int
|
||||
car_data: dict # Car details for display
|
||||
cc_paid: float
|
||||
purchased_at: datetime
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
# Full response including both recommended and directly purchased cars
|
||||
class MyVehiclesResponse(BaseModel):
|
||||
vehicle_requests: List[VehicleRequestWithVehicles]
|
||||
direct_purchases: List[DirectPurchasedCarResponse] # Cars purchased directly from banner
|
||||
|
||||
Reference in New Issue
Block a user