update
This commit is contained in:
parent
e79785bce6
commit
e77c600262
@ -2,7 +2,7 @@ from fastapi import APIRouter, Depends
|
||||
from sqlalchemy.orm import Session
|
||||
from sqlalchemy import and_
|
||||
from typing import List, Optional
|
||||
from app.models.address import AddressDB, AddressCreate, AddressUpdate, AddressInfo
|
||||
from app.models.address import AddressDB, AddressCreate, AddressUpdate, AddressInfo, AddressType
|
||||
from app.models.community import CommunityDB
|
||||
from app.models.database import get_db
|
||||
from app.api.deps import get_current_user
|
||||
@ -21,6 +21,7 @@ async def create_address(
|
||||
if address.is_default:
|
||||
db.query(AddressDB).filter(
|
||||
and_(
|
||||
AddressDB.address_type == address.address_type,
|
||||
AddressDB.user_id == current_user.userid,
|
||||
AddressDB.is_default == True
|
||||
)
|
||||
@ -50,6 +51,7 @@ async def create_address(
|
||||
@router.get("", response_model=ResponseModel)
|
||||
async def get_addresses(
|
||||
community_id: Optional[int] = None,
|
||||
address_type : Optional[AddressType] = AddressType.PICKUP,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: UserDB = Depends(get_current_user)
|
||||
):
|
||||
@ -59,6 +61,9 @@ async def get_addresses(
|
||||
).filter(
|
||||
AddressDB.user_id == current_user.userid
|
||||
)
|
||||
|
||||
if address_type:
|
||||
addresses.filter(AddressDB.address_type == address_type)
|
||||
|
||||
if community_id is not None:
|
||||
addresses = addresses.filter(AddressDB.community_id == community_id)
|
||||
@ -143,12 +148,14 @@ async def delete_address(
|
||||
@router.post("/{address_id}/set-default", response_model=ResponseModel)
|
||||
async def set_default_address(
|
||||
address_id: int,
|
||||
address_type: AddressType = AddressType.PICKUP,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: UserDB = Depends(get_current_user)
|
||||
):
|
||||
"""设置默认地址"""
|
||||
db.query(AddressDB).filter(
|
||||
and_(
|
||||
AddressDB.address_type == address_type,
|
||||
AddressDB.user_id == current_user.userid,
|
||||
AddressDB.is_default == True
|
||||
)
|
||||
|
||||
@ -8,6 +8,7 @@ from app.models.merchant_order import (
|
||||
MerchantOrderInfo,
|
||||
MerchantOrderStatus
|
||||
)
|
||||
from app.models.address import AddressDB, AddressType
|
||||
from app.models.merchant_product import MerchantProductDB
|
||||
from app.models.database import get_db
|
||||
from app.api.deps import get_current_user, get_admin_user, get_merchant_user
|
||||
@ -69,12 +70,16 @@ async def create_merchant_order(
|
||||
order_id = CommonUtils.generate_order_id('M')
|
||||
verify_code = CommonUtils.generate_verify_code()
|
||||
|
||||
|
||||
# 创建订单
|
||||
pay_amount = float(product.sale_price)
|
||||
pay_amount = float(product.sale_price) * order.qty
|
||||
db_order = MerchantOrderDB(
|
||||
order_id=order_id,
|
||||
user_id=current_user.userid,
|
||||
merchant_product_id=order.merchant_product_id,
|
||||
unit_price=product.sale_price,
|
||||
qty=order.qty,
|
||||
address_id=order.address_id,
|
||||
order_amount=pay_amount,
|
||||
pay_amount=pay_amount,
|
||||
gift_points=int(float(product.sale_price) * (float(product.gift_points_rate) / 100) * settings.POINT_RATIO),
|
||||
@ -285,69 +290,41 @@ async def get_order_detail(
|
||||
current_user: UserDB = Depends(get_current_user)
|
||||
):
|
||||
"""获取订单详情"""
|
||||
query = db.query(
|
||||
MerchantOrderDB,
|
||||
MerchantProductDB.name.label('product_name'),
|
||||
MerchantProductDB.image_url.label('product_image'),
|
||||
MerchantProductDB.tags.label('product_tags'),
|
||||
MerchantDB.name.label('merchant_name'),
|
||||
MerchantDB.latitude.label('merchant_latitude'),
|
||||
MerchantDB.longitude.label('merchant_longitude'),
|
||||
MerchantDB.phone.label('merchant_phone')
|
||||
)
|
||||
|
||||
if longitude is not None and latitude is not None:
|
||||
query = query.add_columns(
|
||||
text("ST_Distance_Sphere(point(merchants.longitude, merchants.latitude), "
|
||||
"point(:lon, :lat)) as distance").params(lon=longitude, lat=latitude)
|
||||
)
|
||||
else:
|
||||
query = query.add_columns(text("NULL as distance"))
|
||||
|
||||
order = query.join(
|
||||
MerchantProductDB,
|
||||
MerchantOrderDB.merchant_product_id == MerchantProductDB.id
|
||||
).join(
|
||||
MerchantDB,
|
||||
MerchantProductDB.merchant_id == MerchantDB.id
|
||||
).filter(
|
||||
order = db.query(MerchantOrderDB).filter(
|
||||
MerchantOrderDB.order_id == order_id
|
||||
).first()
|
||||
|
||||
|
||||
if not order:
|
||||
return error_response(code=404, message="订单不存在")
|
||||
|
||||
# 检查权限
|
||||
if order.MerchantOrderDB.user_id != current_user.userid:
|
||||
return error_response(code=403, message="无权查看此订单")
|
||||
|
||||
# 构建返回数据
|
||||
|
||||
product = db.query(MerchantProductDB).filter(
|
||||
MerchantProductDB.id == order.merchant_product_id
|
||||
).first()
|
||||
|
||||
if not product:
|
||||
return error_response(code=404, message="商品不存在")
|
||||
|
||||
|
||||
merchant = db.query(MerchantDB).filter(
|
||||
MerchantDB.id == product.merchant_id
|
||||
).first()
|
||||
|
||||
if not merchant:
|
||||
return error_response(code=404, message="商家不存在")
|
||||
|
||||
|
||||
order_data = {
|
||||
"id": order.MerchantOrderDB.id,
|
||||
"order_id": order.MerchantOrderDB.order_id,
|
||||
"user_id": order.MerchantOrderDB.user_id,
|
||||
"merchant_product_id": order.MerchantOrderDB.merchant_product_id,
|
||||
"order_amount": order.MerchantOrderDB.order_amount,
|
||||
"status": order.MerchantOrderDB.status,
|
||||
"order_verify_code": order.MerchantOrderDB.order_verify_code,
|
||||
"verify_time": order.MerchantOrderDB.verify_time,
|
||||
"verify_user_id": order.MerchantOrderDB.verify_user_id,
|
||||
"create_time": order.MerchantOrderDB.create_time,
|
||||
"update_time": order.MerchantOrderDB.update_time,
|
||||
# 商品信息
|
||||
"product_name": order.product_name,
|
||||
"product_tags": order.product_tags,
|
||||
"product_image": process_image(order.product_image).thumbnail(width=800, height=800).format(ImageFormat.WEBP).build(),
|
||||
# 商家信息
|
||||
"merchant_name": order.merchant_name,
|
||||
"merchant_latitude": order.merchant_latitude,
|
||||
"merchant_longitude": order.merchant_longitude,
|
||||
"merchant_phone": order.merchant_phone,
|
||||
# 距离信息
|
||||
"distance": round(order[8]) if order[8] else None
|
||||
**order.model_dump(),
|
||||
**product.model_dump(),
|
||||
**merchant.model_dump()
|
||||
}
|
||||
|
||||
if order.address_id:
|
||||
address = db.query(AddressDB).filter(
|
||||
AddressDB.id == order.address_id
|
||||
).first()
|
||||
order_data["address"] = address.model_dump()
|
||||
|
||||
return success_response(data=order_data)
|
||||
|
||||
@router.post("/calculate-price", response_model=ResponseModel)
|
||||
|
||||
@ -1,9 +1,16 @@
|
||||
from sqlalchemy import Column, Integer, String, ForeignKey, DateTime, Boolean, Enum
|
||||
from sqlalchemy.sql import func
|
||||
from sqlalchemy.dialects.mysql import DECIMAL
|
||||
from pydantic import BaseModel, Field
|
||||
from .database import Base
|
||||
from typing import Optional
|
||||
from app.models.user import Gender # 复用用户模型中的性别枚举
|
||||
import enum
|
||||
|
||||
# 地址类型枚举
|
||||
class AddressType(str, enum.Enum):
|
||||
PICKUP = "PICKUP" # 代取地址
|
||||
COMMON = "COMMON" # 通用地址
|
||||
|
||||
# 数据库模型
|
||||
class AddressDB(Base):
|
||||
@ -20,6 +27,9 @@ class AddressDB(Base):
|
||||
phone = Column(String(11))
|
||||
gender = Column(Enum(Gender), nullable=False, default=Gender.UNKNOWN)
|
||||
is_default = Column(Boolean, default=False)
|
||||
address_type = Column(Enum(AddressType), nullable=False, default=AddressType.PICKUP) # 地址类型
|
||||
longitude = Column(DECIMAL(9,6), nullable=True) # 经度,精确到小数点后6位
|
||||
latitude = Column(DECIMAL(9,6), nullable=True) # 纬度,精确到小数点后6位
|
||||
create_time = Column(DateTime(timezone=True), server_default=func.now())
|
||||
update_time = Column(DateTime(timezone=True), onupdate=func.now())
|
||||
|
||||
@ -32,6 +42,9 @@ class AddressCreate(BaseModel):
|
||||
phone: str = Field(..., pattern="^1[3-9]\d{9}$")
|
||||
gender: Gender = Gender.UNKNOWN
|
||||
is_default: bool = True
|
||||
address_type: AddressType = AddressType.PICKUP # 地址类型,默认为代取
|
||||
longitude: Optional[float] = Field(None, ge=-180, le=180) # 经度
|
||||
latitude: Optional[float] = Field(None, ge=-90, le=90) # 纬度
|
||||
|
||||
class AddressUpdate(BaseModel):
|
||||
community_id: Optional[int] = None
|
||||
@ -41,6 +54,9 @@ class AddressUpdate(BaseModel):
|
||||
phone: Optional[str] = Field(None, pattern="^1[3-9]\d{9}$")
|
||||
gender: Optional[Gender] = None
|
||||
is_default: Optional[bool] = None
|
||||
address_type: Optional[AddressType] = None # 地址类型
|
||||
longitude: Optional[float] = Field(None, ge=-180, le=180) # 经度
|
||||
latitude: Optional[float] = Field(None, ge=-90, le=90) # 纬度
|
||||
|
||||
class AddressInfo(BaseModel):
|
||||
id: int
|
||||
@ -53,6 +69,9 @@ class AddressInfo(BaseModel):
|
||||
phone: str
|
||||
gender: Gender
|
||||
is_default: bool
|
||||
address_type: AddressType # 地址类型
|
||||
longitude: Optional[float] = None # 经度
|
||||
latitude: Optional[float] = None # 纬度
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
@ -24,6 +24,9 @@ class MerchantOrderDB(Base):
|
||||
qrcode_url = Column(String(200)) # 核销码二维码图片地址
|
||||
user_id = Column(Integer, ForeignKey("users.userid"), nullable=False)
|
||||
merchant_product_id = Column(Integer, ForeignKey("merchant_products.id"), nullable=False)
|
||||
address_id = Column(Integer, ForeignKey("delivery_addresses.id"), nullable=False) # 收货地址ID
|
||||
qty = Column(Integer, nullable=False, default=1) # 购买数量
|
||||
unit_price = Column(DECIMAL(10,2), nullable=False) # 产品单价
|
||||
order_amount = Column(DECIMAL(10,2), nullable=False)
|
||||
pay_amount = Column(DECIMAL(10,2), nullable=False, default=0)
|
||||
gift_points = Column(Integer, nullable=False, default=0) # 赠送的积分
|
||||
@ -39,16 +42,23 @@ class MerchantOrderDB(Base):
|
||||
refund_transaction_id = Column(String(64)) # 微信退款交易号
|
||||
refund_time = Column(DateTime(timezone=True), nullable=True)
|
||||
|
||||
|
||||
class MerchantOrderCreate(BaseModel):
|
||||
merchant_product_id: int
|
||||
qty: int = Field(..., gt=0) # 购买数量,必须大于0
|
||||
address_id: int # 收货地址ID
|
||||
|
||||
class MerchantOrderVerify(BaseModel):
|
||||
verify_code: str
|
||||
|
||||
class MerchantOrderInfo(BaseModel):
|
||||
id: int
|
||||
order_id: str
|
||||
user_id: int
|
||||
merchant_product_id: int
|
||||
address_id: int # 收货地址ID
|
||||
qty: int # 购买数量
|
||||
unit_price: float # 产品单价
|
||||
order_amount: float
|
||||
pay_amount: float
|
||||
gift_points: int
|
||||
|
||||
@ -52,4 +52,38 @@ ADD COLUMN latitude DECIMAL(9,6) COMMENT '纬度,精确到小数点后6位';
|
||||
|
||||
-- 为merchant_products表添加已售数量字段
|
||||
ALTER TABLE merchant_products
|
||||
ADD COLUMN sold_total INT NOT NULL DEFAULT 0 COMMENT '已售数量';
|
||||
ADD COLUMN sold_total INT NOT NULL DEFAULT 0 COMMENT '已售数量';
|
||||
|
||||
-- 为delivery_addresses表添加地址类型和经纬度字段
|
||||
ALTER TABLE delivery_addresses
|
||||
ADD COLUMN address_type ENUM('PICKUP', 'COMMON') NOT NULL DEFAULT 'PICKUP' COMMENT '地址类型:代取或通用',
|
||||
ADD COLUMN longitude DECIMAL(9,6) COMMENT '经度,精确到小数点后6位',
|
||||
ADD COLUMN latitude DECIMAL(9,6) COMMENT '纬度,精确到小数点后6位';
|
||||
|
||||
|
||||
|
||||
-- 添加address_id字段(先不添加外键约束)
|
||||
ALTER TABLE merchant_orders
|
||||
ADD COLUMN address_id INT COMMENT '收货地址ID' AFTER merchant_product_id;
|
||||
|
||||
-- 添加qty字段
|
||||
ALTER TABLE merchant_orders
|
||||
ADD COLUMN qty INT NOT NULL DEFAULT 1 COMMENT '购买数量' AFTER address_id;
|
||||
|
||||
-- 添加unit_price字段
|
||||
ALTER TABLE merchant_orders
|
||||
ADD COLUMN unit_price DECIMAL(10,2) NOT NULL COMMENT '产品单价' AFTER qty;
|
||||
|
||||
-- 更新现有记录的address_id为NULL
|
||||
UPDATE merchant_orders
|
||||
SET address_id = NULL
|
||||
WHERE address_id IS NOT NULL;
|
||||
|
||||
-- 添加外键约束
|
||||
ALTER TABLE merchant_orders
|
||||
ADD CONSTRAINT fk_merchant_orders_address
|
||||
FOREIGN KEY (address_id) REFERENCES delivery_addresses(id);
|
||||
|
||||
-- 修改address_id为NOT NULL
|
||||
ALTER TABLE merchant_orders
|
||||
MODIFY COLUMN address_id INT NOT NULL COMMENT '收货地址ID';
|
||||
BIN
jobs.sqlite
BIN
jobs.sqlite
Binary file not shown.
Loading…
Reference in New Issue
Block a user