业务员编辑客户时前端不传salesman_id,导致后端将其置为None, 列表查询按salesman_id过滤后该客户不再可见。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
132 lines
5.6 KiB
Python
132 lines
5.6 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"]
|
||
if "address" in payload:
|
||
customer.address = payload["address"]
|
||
if "settlement_type" in payload:
|
||
customer.settlement_type = payload["settlement_type"]
|
||
if "settlement_days" in payload:
|
||
customer.settlement_days = payload["settlement_days"]
|
||
if "settlement_day_of_month" in payload:
|
||
customer.settlement_day_of_month = payload["settlement_day_of_month"]
|
||
if "reminder_day_of_month" in payload:
|
||
customer.reminder_day_of_month = payload["reminder_day_of_month"]
|
||
if "customer_type" in payload:
|
||
customer.customer_type = payload["customer_type"]
|
||
if "salesman_id" in payload and payload["salesman_id"] is not None:
|
||
customer.salesman_id = payload["salesman_id"]
|
||
if "credit_limit" in payload:
|
||
customer.credit_limit = payload["credit_limit"]
|
||
if "remark" in payload:
|
||
customer.remark = payload["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()
|