diff --git a/app/api/endpoints/merchant_product.py b/app/api/endpoints/merchant_product.py index c9f6be3..386ac09 100644 --- a/app/api/endpoints/merchant_product.py +++ b/app/api/endpoints/merchant_product.py @@ -12,7 +12,9 @@ from app.api.deps import get_admin_user from app.models.user import UserDB from app.core.response import success_response, error_response, ResponseModel from app.models.merchant import MerchantDB - +from sqlalchemy import func +from sqlalchemy.orm import joinedload +from app.models.merchant_product import OperationType, DeliveryType, DeliveryTimeType router = APIRouter() @router.post("", response_model=ResponseModel) @@ -72,20 +74,34 @@ async def update_product( @router.get("/list", response_model=ResponseModel) async def list_merchant_products( + user_id: Optional[int] = None, merchant_id: Optional[int] = None, + longitude: Optional[float] = None, + latitude: Optional[float] = None, skip: int = 0, limit: int = 20, db: Session = Depends(get_db) ): """获取商品列表""" # 联表查询商家信息 - query = db.query( - MerchantProductDB, - MerchantDB.name.label('merchant_name') - ).join( - MerchantDB, - MerchantProductDB.merchant_id == MerchantDB.id + query = db.query(MerchantProductDB).options( + joinedload(MerchantProductDB.merchant) ) + + # 如果指定了用户ID,添加筛选条件 + if user_id: + query = query.filter(MerchantProductDB.merchant_id == user_id) + + # 如果指定了经纬度,只返回2公里内的商品 + if longitude and latitude: + #使用 SQL 函数计算 + query = query.filter( + func.ST_Distance( + func.ST_SetSRID(func.ST_MakePoint(longitude, latitude), 4326), + MerchantProductDB.longitude, + MerchantProductDB.latitude + ) <= 2000 + ) # 如果指定了商家ID,添加筛选条件 if merchant_id: @@ -98,11 +114,14 @@ async def list_merchant_products( # 处理返回数据 products = [] - for product, merchant_name in results: + for product in results: product_info = MerchantProductInfo.model_validate(product) products.append({ **product_info.model_dump(), - "merchant_name": merchant_name + "merchant_name": product.merchant.name, + "operation_type_name": "蜂快" if product.operation_type == OperationType.SELF_OPERATED else "业主", + "delivery_type_name": "配送到家" if product.delivery_type == DeliveryType.DELIVERY else "自提", + "delivery_time_type_name": "及时达" if product.delivery_time_type == DeliveryTimeType.IMMEDIATE else "定时达" }) return success_response(data={ diff --git a/app/models/merchant_product.py b/app/models/merchant_product.py index 7d76dfb..63bdcc5 100644 --- a/app/models/merchant_product.py +++ b/app/models/merchant_product.py @@ -47,7 +47,10 @@ class MerchantProductDB(Base): product_detail = Column(Text, nullable=True) # 产品详细描述,Markdown格式 purchase_note = Column(Text, nullable=True) # 购买须知,用于提供商品购买相关注意事项 operation_type = Column(Enum(OperationType), nullable=False, default=OperationType.MERCHANT) # 经营类型:自营或商家 + longitude = Column(DECIMAL(9,6), nullable=True) # 经度,精确到小数点后6位 + latitude = Column(DECIMAL(9,6), nullable=True) # 纬度,精确到小数点后6位 qty = Column(Integer, nullable=False, default=0) # 库存 + sold_total = Column(Integer, nullable=False, default=0) # 已售数量 is_sellout = Column(Boolean, nullable=False, default=False) # 是否售罄 delivery_type = Column(Enum(DeliveryType), nullable=False, default=DeliveryType.DELIVERY) # 配送类型 pickup_place = Column(String(200), nullable=True) # 自提点 @@ -58,6 +61,8 @@ class MerchantProductDB(Base): update_time = Column(DateTime(timezone=True), onupdate=func.now()) status = Column(Enum(ProductStatus), nullable=False, default=ProductStatus.UNLISTING) + merchant = relationship("MerchantDB", backref="products") + @property def optimized_image_url(self): return process_image(self.image_url).thumbnail(width=800, height=800).format(ImageFormat.WEBP).build() @@ -75,7 +80,10 @@ class MerchantProductCreate(BaseModel): product_detail: Optional[str] = None # 产品详细描述,Markdown格式 purchase_note: Optional[str] = None # 购买须知,用于提供商品购买相关注意事项 operation_type: OperationType = Field(OperationType.MERCHANT) # 经营类型:自营或商家 + longitude: Optional[float] = Field(None, ge=-180, le=180) # 经度 + latitude: Optional[float] = Field(None, ge=-90, le=90) # 纬度 qty: int = Field(0, ge=0) # 库存 + sold_total: int = Field(0, ge=0) # 已售数量 is_sellout: bool = Field(False) # 是否售罄 delivery_type: DeliveryType = Field(DeliveryType.DELIVERY) # 配送类型 pickup_place: Optional[str] = Field(None, max_length=200) # 自提点 @@ -97,7 +105,10 @@ class MerchantProductUpdate(BaseModel): product_detail: Optional[str] = None # 产品详细描述,Markdown格式 purchase_note: Optional[str] = None # 购买须知,用于提供商品购买相关注意事项 operation_type: Optional[OperationType] = None # 经营类型:自营或商家 + longitude: Optional[float] = Field(None, ge=-180, le=180) # 经度 + latitude: Optional[float] = Field(None, ge=-90, le=90) # 纬度 qty: Optional[int] = Field(None, ge=0) # 库存 + sold_total: Optional[int] = Field(None, ge=0) # 已售数量 is_sellout: Optional[bool] = None # 是否售罄 delivery_type: Optional[DeliveryType] = None # 配送类型 pickup_place: Optional[str] = Field(None, max_length=200) # 自提点 @@ -123,7 +134,10 @@ class MerchantProductInfo(BaseModel): product_detail: Optional[str] = None # 产品详细描述,Markdown格式 purchase_note: Optional[str] = None # 购买须知,用于提供商品购买相关注意事项 operation_type: OperationType # 经营类型:自营或商家 + longitude: Optional[float] = None # 经度 + latitude: Optional[float] = None # 纬度 qty: int # 库存 + sold_total: int = 0 # 已售数量 is_sellout: bool # 是否售罄 delivery_type: DeliveryType # 配送类型 pickup_place: Optional[str] = None # 自提点 diff --git a/app/sql/v1.1.sql b/app/sql/v1.1.sql index 1e61c31..4770927 100644 --- a/app/sql/v1.1.sql +++ b/app/sql/v1.1.sql @@ -42,4 +42,14 @@ ADD COLUMN pickup_time DATETIME COMMENT '自提时间,用于指定商品自提 -- 为merchant_products表添加operation_type字段(枚举类型) ALTER TABLE merchant_products -ADD COLUMN operation_type ENUM('SELF_OPERATED', 'MERCHANT') NOT NULL DEFAULT 'MERCHANT' COMMENT '经营类型:自营或商家'; \ No newline at end of file +ADD COLUMN operation_type ENUM('SELF_OPERATED', 'MERCHANT') NOT NULL DEFAULT 'MERCHANT' COMMENT '经营类型:自营或商家'; + + +-- 为merchant_products表添加经纬度字段 +ALTER TABLE merchant_products +ADD COLUMN longitude DECIMAL(9,6) COMMENT '经度,精确到小数点后6位', +ADD COLUMN latitude DECIMAL(9,6) COMMENT '纬度,精确到小数点后6位'; + +-- 为merchant_products表添加已售数量字段 +ALTER TABLE merchant_products +ADD COLUMN sold_total INT NOT NULL DEFAULT 0 COMMENT '已售数量'; \ No newline at end of file diff --git a/jobs.sqlite b/jobs.sqlite index 99c31ef..7dade05 100644 Binary files a/jobs.sqlite and b/jobs.sqlite differ