新增设置分润
This commit is contained in:
parent
aae96d1a6e
commit
560dfa82ad
@ -1,5 +1,5 @@
|
||||
from fastapi import APIRouter, Depends
|
||||
from sqlalchemy.orm import Session
|
||||
from sqlalchemy.orm import Session, joinedload
|
||||
from typing import List, Optional
|
||||
from app.models.community import (
|
||||
CommunityDB, CommunityCreate, CommunityUpdate,
|
||||
@ -9,6 +9,8 @@ from app.models.database import get_db
|
||||
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.community_profit_sharing import CommunityProfitSharing
|
||||
from app.api.endpoints.community_profit_sharing import CommunityProfitSharingResponse
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@ -67,8 +69,8 @@ async def get_communities(
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""获取社区列表"""
|
||||
# 构建查询
|
||||
query = db.query(CommunityDB)
|
||||
# 构建查询, 关联社区分润
|
||||
query = db.query(CommunityDB).options(joinedload(CommunityDB.community_profit_sharing))
|
||||
|
||||
# 状态过滤
|
||||
if status:
|
||||
@ -82,21 +84,40 @@ async def get_communities(
|
||||
|
||||
community_list = []
|
||||
for community in communities:
|
||||
community_info = CommunityInfo.model_validate(community)
|
||||
community_info = {
|
||||
"id": community.id,
|
||||
"name": community.name,
|
||||
"address": community.address,
|
||||
"latitude": float(community.latitude),
|
||||
"longitude": float(community.longitude),
|
||||
"status": community.status,
|
||||
"qy_group_qrcode": community.qy_group_qrcode,
|
||||
"webot_webhook": community.webot_webhook,
|
||||
"base_price": float(community.base_price),
|
||||
"extra_package_price": float(community.extra_package_price),
|
||||
"extra_package_threshold": community.extra_package_threshold,
|
||||
"profit_sharing": None if community.community_profit_sharing is None else {
|
||||
"id": community.community_profit_sharing.id,
|
||||
"platform_rate": float(community.community_profit_sharing.platform_rate),
|
||||
"partner_rate": float(community.community_profit_sharing.partner_rate),
|
||||
"admin_rate": float(community.community_profit_sharing.admin_rate),
|
||||
"delivery_rate": float(community.community_profit_sharing.delivery_rate)
|
||||
}
|
||||
}
|
||||
|
||||
# 如果提供了经纬度,则计算距离
|
||||
if latitude is not None and longitude is not None:
|
||||
distance = calculate_distance(
|
||||
latitude, longitude,
|
||||
community.latitude, community.longitude
|
||||
float(community.latitude), float(community.longitude)
|
||||
)
|
||||
community_info.distance = distance
|
||||
community_info["distance"] = distance
|
||||
|
||||
community_list.append(community_info)
|
||||
|
||||
# 如果计算了距离,则按距离排序
|
||||
if latitude is not None and longitude is not None:
|
||||
community_list.sort(key=lambda x: x.distance)
|
||||
community_list.sort(key=lambda x: x["distance"])
|
||||
|
||||
return success_response(data={
|
||||
"total": total,
|
||||
@ -127,7 +148,7 @@ async def get_community(
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""获取社区详情"""
|
||||
community = db.query(CommunityDB).filter(CommunityDB.id == community_id).first()
|
||||
community = db.query(CommunityDB).options(joinedload(CommunityDB.community_profit_sharing)).filter(CommunityDB.id == community_id).first()
|
||||
if not community:
|
||||
return error_response(code=404, message="社区不存在")
|
||||
return success_response(data=CommunityInfo.model_validate(community))
|
||||
|
||||
206
app/api/endpoints/community_profit_sharing.py
Normal file
206
app/api/endpoints/community_profit_sharing.py
Normal file
@ -0,0 +1,206 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, Path
|
||||
from sqlalchemy.orm import Session
|
||||
from typing import List, Optional
|
||||
from pydantic import BaseModel, Field, field_validator
|
||||
from app.models.database import get_db
|
||||
from app.models.community_profit_sharing import CommunityProfitSharing
|
||||
from app.models.community import CommunityDB
|
||||
from app.api.deps import get_current_user, get_admin_user
|
||||
from app.models.user import UserDB
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
from app.core.response import error_response, success_response
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
# 请求和响应模型
|
||||
class CommunityProfitSharingCreate(BaseModel):
|
||||
community_id: int = Field(..., ge=1, description="社区ID")
|
||||
platform_rate: float = Field(..., ge=0, le=100, description="平台分润比例(%)")
|
||||
partner_rate: float = Field(..., ge=0, le=100, description="合伙人分润比例(%)")
|
||||
admin_rate: float = Field(..., ge=0, le=100, description="管理员分润比例(%)")
|
||||
delivery_rate: float = Field(..., ge=0, le=100, description="配送员分润比例(%)")
|
||||
|
||||
class CommunityProfitSharingUpdate(BaseModel):
|
||||
platform_rate: float = Field(..., ge=0, le=100, description="平台分润比例(%)")
|
||||
partner_rate: float = Field(..., ge=0, le=100, description="合伙人分润比例(%)")
|
||||
admin_rate: float = Field(..., ge=0, le=100, description="管理员分润比例(%)")
|
||||
delivery_rate: float = Field(..., ge=0, le=100, description="配送员分润比例(%)")
|
||||
|
||||
class CommunityProfitSharingResponse(BaseModel):
|
||||
id: int
|
||||
community_id: int
|
||||
platform_rate: float
|
||||
partner_rate: float
|
||||
admin_rate: float
|
||||
delivery_rate: float
|
||||
create_time: datetime
|
||||
update_time: datetime
|
||||
|
||||
# 包含社区名称
|
||||
community_name: Optional[str] = None
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
# 创建社区分润
|
||||
@router.post("/", response_model=CommunityProfitSharingResponse)
|
||||
async def create_community_profit_sharing(
|
||||
profit_sharing: CommunityProfitSharingCreate,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: UserDB = Depends(get_admin_user)
|
||||
):
|
||||
"""创建社区分润"""
|
||||
# 检查社区是否存在
|
||||
community = db.query(CommunityDB).filter(CommunityDB.id == profit_sharing.community_id).first()
|
||||
if not community:
|
||||
return error_response(code=404, message="社区不存在")
|
||||
|
||||
# 检查该社区是否已有分润记录
|
||||
existing_profit_sharing = db.query(CommunityProfitSharing).filter(
|
||||
CommunityProfitSharing.community_id == profit_sharing.community_id
|
||||
).first()
|
||||
|
||||
if existing_profit_sharing:
|
||||
return error_response(code=400, message="该社区已有分润记录,请使用更新接口")
|
||||
|
||||
# 检查分润比例之和是否等于100%
|
||||
total_rate = profit_sharing.platform_rate + profit_sharing.partner_rate + profit_sharing.admin_rate + profit_sharing.delivery_rate
|
||||
if total_rate != 100:
|
||||
return error_response(code=400, message="分润比例之和必须等于100%")
|
||||
|
||||
# 创建新分润记录
|
||||
new_profit_sharing = CommunityProfitSharing(
|
||||
community_id=profit_sharing.community_id,
|
||||
platform_rate=profit_sharing.platform_rate,
|
||||
partner_rate=profit_sharing.partner_rate,
|
||||
admin_rate=profit_sharing.admin_rate,
|
||||
delivery_rate=profit_sharing.delivery_rate
|
||||
)
|
||||
|
||||
db.add(new_profit_sharing)
|
||||
db.commit()
|
||||
db.refresh(new_profit_sharing)
|
||||
|
||||
# 添加社区名称
|
||||
result = CommunityProfitSharingResponse.model_validate(new_profit_sharing)
|
||||
result.community_name = community.name
|
||||
|
||||
return success_response(data=result)
|
||||
|
||||
# 获取所有社区分润
|
||||
@router.get("/", response_model=List[CommunityProfitSharingResponse])
|
||||
async def get_community_profit_sharings(
|
||||
db: Session = Depends(get_db),
|
||||
current_user: UserDB = Depends(get_admin_user),
|
||||
skip: int = Query(0, ge=0),
|
||||
limit: int = Query(100, ge=1, le=100)
|
||||
):
|
||||
"""获取所有社区分润"""
|
||||
profit_sharings = db.query(CommunityProfitSharing).offset(skip).limit(limit).all()
|
||||
|
||||
# 添加社区名称
|
||||
results = []
|
||||
for profit_sharing in profit_sharings:
|
||||
community = db.query(CommunityDB).filter(CommunityDB.id == profit_sharing.community_id).first()
|
||||
result = CommunityProfitSharingResponse.model_validate(profit_sharing)
|
||||
result.community_name = community.name if community else None
|
||||
results.append(result)
|
||||
|
||||
return success_response(data=results)
|
||||
|
||||
# 获取特定社区的分润
|
||||
@router.get("/community/{community_id}", response_model=CommunityProfitSharingResponse)
|
||||
async def get_community_profit_sharing(
|
||||
community_id: int = Path(..., ge=1),
|
||||
db: Session = Depends(get_db),
|
||||
current_user: UserDB = Depends(get_admin_user)
|
||||
):
|
||||
"""获取特定社区的分润"""
|
||||
# 检查社区是否存在
|
||||
community = db.query(CommunityDB).filter(CommunityDB.id == community_id).first()
|
||||
if not community:
|
||||
return error_response(code=404, message="社区不存在")
|
||||
|
||||
profit_sharing = db.query(CommunityProfitSharing).filter(
|
||||
CommunityProfitSharing.community_id == community_id
|
||||
).first()
|
||||
|
||||
if not profit_sharing:
|
||||
return error_response(code=404, message="该社区暂无分润记录")
|
||||
|
||||
# 添加社区名称
|
||||
result = CommunityProfitSharingResponse.model_validate(profit_sharing)
|
||||
result.community_name = community.name
|
||||
|
||||
return success_response(data=result)
|
||||
|
||||
# 更新社区分润
|
||||
@router.put("/community/{community_id}", response_model=CommunityProfitSharingResponse)
|
||||
async def update_community_profit_sharing(
|
||||
profit_sharing: CommunityProfitSharingUpdate,
|
||||
community_id: int = Path(..., ge=1),
|
||||
db: Session = Depends(get_db),
|
||||
current_user: UserDB = Depends(get_admin_user)
|
||||
):
|
||||
"""更新社区分润"""
|
||||
# 检查社区是否存在
|
||||
community = db.query(CommunityDB).filter(CommunityDB.id == community_id).first()
|
||||
if not community:
|
||||
return error_response(code=404, message="社区不存在")
|
||||
|
||||
# 检查该社区是否有分润记录
|
||||
db_profit_sharing = db.query(CommunityProfitSharing).filter(
|
||||
CommunityProfitSharing.community_id == community_id
|
||||
).first()
|
||||
|
||||
if not db_profit_sharing:
|
||||
return error_response(code=404, message="该社区暂无分润记录,请先创建")
|
||||
|
||||
# 检查分润比例之和是否等于100%
|
||||
total_rate = profit_sharing.platform_rate + profit_sharing.partner_rate + profit_sharing.admin_rate + profit_sharing.delivery_rate
|
||||
if total_rate != 100:
|
||||
return error_response(code=400, message="分润比例之和必须等于100%")
|
||||
|
||||
# 更新分润记录
|
||||
db_profit_sharing.platform_rate = profit_sharing.platform_rate
|
||||
db_profit_sharing.partner_rate = profit_sharing.partner_rate
|
||||
db_profit_sharing.admin_rate = profit_sharing.admin_rate
|
||||
db_profit_sharing.delivery_rate = profit_sharing.delivery_rate
|
||||
db_profit_sharing.update_time = datetime.now()
|
||||
|
||||
db.commit()
|
||||
db.refresh(db_profit_sharing)
|
||||
|
||||
# 添加社区名称
|
||||
result = CommunityProfitSharingResponse.model_validate(db_profit_sharing)
|
||||
result.community_name = community.name
|
||||
|
||||
return success_response(data=result)
|
||||
|
||||
# 删除社区分润
|
||||
@router.delete("/community/{community_id}", response_model=dict)
|
||||
async def delete_community_profit_sharing(
|
||||
community_id: int = Path(..., ge=1),
|
||||
db: Session = Depends(get_db),
|
||||
current_user: UserDB = Depends(get_admin_user)
|
||||
):
|
||||
"""删除社区分润"""
|
||||
# 检查社区是否存在
|
||||
community = db.query(CommunityDB).filter(CommunityDB.id == community_id).first()
|
||||
if not community:
|
||||
return error_response(code=404, message="社区不存在")
|
||||
|
||||
# 检查该社区是否有分润记录
|
||||
db_profit_sharing = db.query(CommunityProfitSharing).filter(
|
||||
CommunityProfitSharing.community_id == community_id
|
||||
).first()
|
||||
|
||||
if not db_profit_sharing:
|
||||
return error_response(code=404, message="该社区暂无分润记录")
|
||||
|
||||
# 删除分润记录
|
||||
db.delete(db_profit_sharing)
|
||||
db.commit()
|
||||
|
||||
return success_response(message="社区分润记录已删除")
|
||||
@ -1,6 +1,6 @@
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from app.api.endpoints import wechat,user, address, community, station, order, coupon, community_building, upload, merchant, merchant_product, merchant_order, point, config, merchant_category, log, account,merchant_pay_order, message, bank_card, withdraw, mp, point_product, point_product_order, coupon_activity, dashboard, wecom, feedback, timeperiod, community_timeperiod, order_additional_fee, ai, community_set, community_set_mapping
|
||||
from app.api.endpoints import wechat,user, address, community, station, order, coupon, community_building, upload, merchant, merchant_product, merchant_order, point, config, merchant_category, log, account,merchant_pay_order, message, bank_card, withdraw, mp, point_product, point_product_order, coupon_activity, dashboard, wecom, feedback, timeperiod, community_timeperiod, order_additional_fee, ai, community_set, community_set_mapping, community_profit_sharing, partner
|
||||
from app.models.database import Base, engine
|
||||
from fastapi.exceptions import RequestValidationError
|
||||
from fastapi.responses import JSONResponse
|
||||
@ -13,7 +13,6 @@ from app.core.config import settings
|
||||
from app.core.wecombot import WecomBot
|
||||
from app.api.endpoints import wecom
|
||||
from app.api.endpoints import feedback
|
||||
from app.api.endpoints import partner
|
||||
from starlette.middleware.sessions import SessionMiddleware
|
||||
import os
|
||||
|
||||
@ -62,6 +61,7 @@ app.include_router(address.router, prefix="/api/address", tags=["配送地址"])
|
||||
app.include_router(community.router, prefix="/api/community", tags=["社区"])
|
||||
app.include_router(community_set.router, prefix="/api/community-sets", tags=["社区集合"])
|
||||
app.include_router(community_set_mapping.router, prefix="/api/community-set-mappings", tags=["社区集合映射"])
|
||||
app.include_router(community_profit_sharing.router, prefix="/api/community-profit-sharings", tags=["社区分润"])
|
||||
app.include_router(timeperiod.router, prefix="/api/time-periods", tags=["配送时段"])
|
||||
app.include_router(community_timeperiod.router, prefix="/api/community-time-periods", tags=["社区配送时段"])
|
||||
app.include_router(community_building.router, prefix="/api/community/building", tags=["社区楼栋"])
|
||||
|
||||
@ -2,7 +2,7 @@ from typing import Optional
|
||||
import enum
|
||||
from sqlalchemy import Column, Integer, String, DECIMAL, DateTime, Enum
|
||||
from sqlalchemy.sql import func
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import BaseModel, Field, model_validator
|
||||
from .database import Base
|
||||
from sqlalchemy.orm import relationship
|
||||
from app.core.imageprocessor import process_image, ImageFormat
|
||||
@ -32,6 +32,12 @@ class CommunityDB(Base):
|
||||
create_time = Column(DateTime(timezone=True), server_default=func.now())
|
||||
update_time = Column(DateTime(timezone=True), onupdate=func.now())
|
||||
|
||||
# 通过映射表关联的社区分润
|
||||
community_profit_sharing = relationship("CommunityProfitSharing", backref="community", uselist=False)
|
||||
|
||||
# 关联社区集合
|
||||
community_set_mappings = relationship("CommunitySetMapping", backref="community")
|
||||
|
||||
@property
|
||||
def optimized_qy_group_qrcode(self):
|
||||
if self.qy_group_qrcode:
|
||||
@ -75,5 +81,22 @@ class CommunityInfo(BaseModel):
|
||||
optimized_qy_group_qrcode: Optional[str] = None
|
||||
distance: Optional[float] = None # 距离,单位:米
|
||||
|
||||
# 添加分润信息字段
|
||||
profit_sharing: Optional[dict] = None
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
from_attributes = True
|
||||
|
||||
@model_validator(mode='after')
|
||||
def set_profit_sharing(self):
|
||||
# 从ORM对象中获取分润信息
|
||||
if hasattr(self, 'community_profit_sharing') and getattr(self, 'community_profit_sharing') is not None:
|
||||
profit_sharing = getattr(self, 'community_profit_sharing')
|
||||
self.profit_sharing = {
|
||||
"id": profit_sharing.id,
|
||||
"platform_rate": profit_sharing.platform_rate,
|
||||
"partner_rate": profit_sharing.partner_rate,
|
||||
"admin_rate": profit_sharing.admin_rate,
|
||||
"delivery_rate": profit_sharing.delivery_rate
|
||||
}
|
||||
return self
|
||||
17
app/models/community_profit_sharing.py
Normal file
17
app/models/community_profit_sharing.py
Normal file
@ -0,0 +1,17 @@
|
||||
from sqlalchemy import Column, Integer, String, ForeignKey, DateTime, DECIMAL, UniqueConstraint
|
||||
from sqlalchemy.orm import relationship
|
||||
from app.models.database import Base
|
||||
import datetime
|
||||
|
||||
class CommunityProfitSharing(Base):
|
||||
"""社区分润模型,记录每个社区的分润比例"""
|
||||
__tablename__ = "community_profit_sharings"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
|
||||
community_id = Column(Integer, ForeignKey("communities.id"), nullable=False, unique=True, comment="社区ID")
|
||||
platform_rate = Column(DECIMAL(5, 2), nullable=False, default=0, comment="平台分润比例(%)")
|
||||
partner_rate = Column(DECIMAL(5, 2), nullable=False, default=0, comment="合伙人分润比例(%)")
|
||||
admin_rate = Column(DECIMAL(5, 2), nullable=False, default=0, comment="管理员分润比例(%)")
|
||||
delivery_rate = Column(DECIMAL(5, 2), nullable=False, default=0, comment="配送员分润比例(%)")
|
||||
create_time = Column(DateTime, default=datetime.datetime.now, comment="创建时间")
|
||||
update_time = Column(DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now, comment="更新时间")
|
||||
@ -11,4 +11,7 @@ class CommunitySet(Base):
|
||||
set_name = Column(String(100), nullable=False, comment="集合名称")
|
||||
user_id = Column(Integer, nullable=True, comment="创建用户ID")
|
||||
create_time = Column(DateTime, default=datetime.datetime.now, comment="创建时间")
|
||||
update_time = Column(DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now, comment="更新时间")
|
||||
update_time = Column(DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now, comment="更新时间")
|
||||
|
||||
# 关联社区集合映射
|
||||
community_set_mappings = relationship("CommunitySetMapping", backref="set")
|
||||
|
||||
@ -11,4 +11,4 @@ class CommunitySetMapping(Base):
|
||||
set_id = Column(Integer, ForeignKey("community_sets.id"), nullable=False, comment="社区集合ID")
|
||||
community_id = Column(Integer, ForeignKey("communities.id"), nullable=False, comment="社区ID")
|
||||
create_time = Column(DateTime, default=datetime.datetime.now, comment="创建时间")
|
||||
update_time = Column(DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now, comment="更新时间")
|
||||
update_time = Column(DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now, comment="更新时间")
|
||||
Loading…
Reference in New Issue
Block a user