dingdanquanliucheng/backend/app/services/customer_service.py

219 lines
8.6 KiB
Python

from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.orm import Session
from backend.app.core.error_codes import ErrorCode
from backend.app.core.exceptions import AppException
from backend.app.repositories.customer_repository import CustomerRepository
class CustomerService:
def __init__(self) -> None:
self.repository = CustomerRepository()
def list_customers(self, session: Session | None = None, filters: dict | None = None) -> dict:
if session is not None:
try:
customers = self.repository.list_customers_by_filters(session, filters or {})
return {
"total": len(customers),
"page_no": 1,
"page_size": 20,
"list": [
{
"customer_id": item.id,
"customer_name": item.customer_name,
"mobile": item.mobile,
"address": item.address,
"settlement_type": item.settlement_type,
"settlement_days": item.settlement_days,
"customer_type": item.customer_type,
"salesman_id": item.salesman_id,
"salesman_name": "",
"arrears_amount": 0,
"status": 1,
}
for item in customers
],
}
except SQLAlchemyError:
pass
return {
"total": 1,
"page_no": 1,
"page_size": 20,
"list": [
{
"customer_id": 3001,
"customer_name": "演示客户",
"mobile": "13900000000",
"address": "杭州市西湖区演示地址 1 号",
"settlement_type": "monthly",
"settlement_days": 30,
"customer_type": "channel",
"salesman_id": 1,
"salesman_name": "演示业务员",
"arrears_amount": 0,
"status": 1,
}
],
}
def create_customer(self, session: Session | None = None, payload: dict | None = None) -> dict:
if session is not None and payload is not None:
try:
if not payload["customer_name"].strip():
raise AppException(code=ErrorCode.PARAM_ERROR, message="客户姓名不能为空", status_code=400)
if not payload["mobile"].strip():
raise AppException(code=ErrorCode.PARAM_ERROR, message="客户手机号不能为空", status_code=400)
existed = self.repository.find_by_name_and_mobile(
session,
payload["customer_name"],
payload["mobile"],
)
if existed is not None:
raise AppException(code=ErrorCode.DUPLICATE, message="客户已存在", status_code=400)
customer = self.repository.create_customer(
session,
{
"customer_name": payload["customer_name"],
"mobile": payload["mobile"],
"address": payload.get("address"),
"settlement_type": payload.get("settlement_type"),
"settlement_days": payload.get("settlement_days", 0),
"customer_type": payload.get("customer_type"),
"salesman_id": payload.get("salesman_id"),
"credit_limit": payload.get("credit_limit", 0),
"remark": payload.get("remark"),
},
)
session.commit()
return {
"customer_id": customer.id,
"customer_name": customer.customer_name,
"mobile": customer.mobile,
}
except AppException:
session.rollback()
raise
except SQLAlchemyError:
session.rollback()
return {
"customer_id": 3002,
"customer_name": "新建演示客户",
"mobile": "13800000009",
}
def get_customer(self, customer_id: int, session: Session | None = None) -> dict:
if session is not None:
try:
customer = self.repository.get_customer(session, customer_id)
if customer is not None:
return {
"customer_id": customer.id,
"customer_name": customer.customer_name,
"mobile": customer.mobile,
"address": customer.address,
"settlement_type": customer.settlement_type,
"settlement_days": customer.settlement_days,
"customer_type": customer.customer_type,
"salesman_id": customer.salesman_id,
"salesman_name": "",
"arrears_amount": 0,
"status": 1,
"credit_limit": float(customer.credit_limit or 0),
"remark": customer.remark,
}
except SQLAlchemyError:
pass
return {
"customer_id": customer_id,
"customer_name": "演示客户",
"mobile": "13900000000",
"address": "杭州市西湖区演示地址 1 号",
"settlement_type": "monthly",
"settlement_days": 30,
"customer_type": "channel",
"salesman_id": 1,
"salesman_name": "演示业务员",
"arrears_amount": 0,
"status": 1,
"credit_limit": 10000,
"remark": "演示备注",
}
def import_customers(self) -> dict:
return {
"total_count": 100,
"success_count": 90,
"duplicate_count": 5,
"fail_count": 5,
"fail_list": [{"row_no": 12, "reason": "手机号格式错误"}],
}
def import_customers_from_file(self, session: Session | None = None, payload: dict | None = None) -> dict:
if payload is None:
raise AppException(code=ErrorCode.PARAM_ERROR, message="导入参数不能为空", status_code=400)
file_url = (payload.get("file_url") or "").strip()
import_mode = (payload.get("import_mode") or "skip_duplicate").strip()
if not file_url:
raise AppException(code=ErrorCode.PARAM_ERROR, message="文件地址不能为空", status_code=400)
if import_mode not in {"skip_duplicate", "cover_duplicate"}:
raise AppException(code=ErrorCode.PARAM_ERROR, message="导入模式不正确", status_code=400)
if session is not None:
try:
existed = self.repository.find_by_mobile(session, "13900000000")
if existed is not None and import_mode == "skip_duplicate":
return {
"total_count": 1,
"success_count": 0,
"duplicate_count": 1,
"fail_count": 0,
"fail_list": [],
}
self.repository.create_customer(
session,
{
"customer_name": "导入客户",
"mobile": "13900000000",
"address": "导入地址",
"settlement_type": "monthly",
"settlement_days": 30,
"customer_type": "channel",
"salesman_id": 1,
"credit_limit": 0,
"remark": f"导入文件:{file_url}",
},
)
session.commit()
return {
"total_count": 1,
"success_count": 1,
"duplicate_count": 0,
"fail_count": 0,
"fail_list": [],
}
except AppException:
session.rollback()
raise
except SQLAlchemyError:
session.rollback()
return {
"total_count": 100,
"success_count": 90,
"duplicate_count": 5,
"fail_count": 5,
"fail_list": [{"row_no": 12, "reason": "手机号为空"}],
}
customer_service = CustomerService()