覆盖所有模块: - api 层:17 个路由文件,每个接口标注用途、参数、返回值、权限 - services 层:18 个服务文件,每个方法标注作用、参数、返回值、调用方 - repositories 层:13 个仓储文件,每个方法标注查询逻辑和被调用方 - schemas 层:11 个请求/响应体文件,每个字段标注业务含义 - core 层:config、security、exceptions、responses、error_codes - models 层:19 个 ORM 模型类,每个表标注业务含义和关联关系 - scripts:bootstrap_data、smoke_check - migrations:env.py 和版本迁移文件 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
121 lines
5.0 KiB
Python
121 lines
5.0 KiB
Python
"""
|
||
客户数据访问层。
|
||
|
||
负责封装客户(Customer)模型的所有数据库查询操作,
|
||
提供按条件筛选、创建、更新等基础 CRUD 方法。
|
||
被 CustomerService、OrderService、AIService 调用。
|
||
"""
|
||
|
||
from sqlalchemy import select
|
||
from sqlalchemy.orm import Session
|
||
|
||
from backend.app.models.business import Customer
|
||
|
||
|
||
class CustomerRepository:
|
||
"""客户数据访问层,封装客户表的数据库操作。
|
||
|
||
被 CustomerService、OrderService、AIService 调用。
|
||
"""
|
||
|
||
def find_by_name_and_mobile(self, session: Session, customer_name: str, mobile: str) -> Customer | None:
|
||
"""根据客户姓名和手机号精确查找客户(用于去重校验)。
|
||
|
||
:param session: 数据库会话
|
||
:param customer_name: 客户姓名
|
||
:param mobile: 手机号
|
||
:return: 匹配的客户对象,不存在则返回 None
|
||
被 CustomerService.create_customer 调用,用于创建前校验是否已存在同名同号客户。
|
||
"""
|
||
stmt = select(Customer).where(
|
||
Customer.customer_name == customer_name,
|
||
Customer.mobile == mobile,
|
||
Customer.deleted == 0,
|
||
)
|
||
return session.execute(stmt).scalar_one_or_none()
|
||
|
||
def list_customers_by_filters(self, session: Session, filters: dict) -> list[Customer]:
|
||
"""根据筛选条件查询客户列表,支持模糊匹配姓名/手机号、精确匹配类型/结算方式/业务员。
|
||
|
||
:param session: 数据库会话
|
||
:param filters: 筛选条件字典,可包含 customer_name、mobile、customer_type、
|
||
settlement_type、salesman_id 等键
|
||
:return: 符合条件的客户列表,按 id 降序排列
|
||
被 CustomerService.list_customers 调用。
|
||
"""
|
||
stmt = select(Customer).where(Customer.deleted == 0)
|
||
|
||
if filters.get("customer_name"):
|
||
stmt = stmt.where(Customer.customer_name.contains(filters["customer_name"]))
|
||
if filters.get("mobile"):
|
||
stmt = stmt.where(Customer.mobile.contains(filters["mobile"]))
|
||
if filters.get("customer_type"):
|
||
stmt = stmt.where(Customer.customer_type == filters["customer_type"])
|
||
if filters.get("settlement_type"):
|
||
stmt = stmt.where(Customer.settlement_type == filters["settlement_type"])
|
||
if filters.get("salesman_id") is not None:
|
||
stmt = stmt.where(Customer.salesman_id == filters["salesman_id"])
|
||
|
||
stmt = stmt.order_by(Customer.id.desc())
|
||
return list(session.execute(stmt).scalars())
|
||
|
||
def get_customer(self, session: Session, customer_id: int) -> Customer | None:
|
||
"""根据 ID 获取单个客户详情。
|
||
|
||
:param session: 数据库会话
|
||
:param customer_id: 客户主键 ID
|
||
:return: 客户对象,不存在则返回 None
|
||
被 CustomerService.get_customer 调用。
|
||
"""
|
||
stmt = select(Customer).where(Customer.id == customer_id, Customer.deleted == 0)
|
||
return session.execute(stmt).scalar_one_or_none()
|
||
|
||
def create_customer(self, session: Session, payload: dict) -> Customer:
|
||
"""创建新客户记录。
|
||
|
||
:param session: 数据库会话
|
||
:param payload: 客户字段字典,键名与 Customer 模型字段对应
|
||
:return: 新创建的客户对象(含自增 ID)
|
||
被 CustomerService.create_customer 调用。
|
||
"""
|
||
customer = Customer(**payload)
|
||
session.add(customer)
|
||
session.flush()
|
||
return customer
|
||
|
||
def update_customer(self, session: Session, customer: Customer, payload: dict) -> Customer:
|
||
"""更新已有客户的各字段信息。
|
||
|
||
:param session: 数据库会话
|
||
:param customer: 待更新的客户对象(已从数据库查出)
|
||
:param payload: 更新字段字典
|
||
:return: 更新后的客户对象
|
||
被 CustomerService.update_customer 调用。
|
||
"""
|
||
customer.customer_name = payload["customer_name"]
|
||
customer.mobile = payload["mobile"]
|
||
customer.address = payload.get("address")
|
||
customer.settlement_type = payload.get("settlement_type")
|
||
customer.settlement_days = payload.get("settlement_days", 0)
|
||
customer.customer_type = payload.get("customer_type")
|
||
customer.salesman_id = payload.get("salesman_id")
|
||
customer.credit_limit = payload.get("credit_limit", 0)
|
||
customer.remark = payload.get("remark")
|
||
session.add(customer)
|
||
session.flush()
|
||
return customer
|
||
|
||
def find_by_mobile(self, session: Session, mobile: str) -> Customer | None:
|
||
"""根据手机号精确查找客户(用于创建/编辑时的唯一性校验)。
|
||
|
||
:param session: 数据库会话
|
||
:param mobile: 手机号
|
||
:return: 匹配的客户对象,不存在则返回 None
|
||
被 CustomerService.create_customer、OrderService 创建订单时调用。
|
||
"""
|
||
stmt = select(Customer).where(
|
||
Customer.mobile == mobile,
|
||
Customer.deleted == 0,
|
||
)
|
||
return session.execute(stmt).scalar_one_or_none()
|