管理员后台新增"客户对账单"页面,按客户+时间段汇总订单和欠款明细, 支持逾期高亮和 CSV 导出。 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
101 lines
3.6 KiB
Python
101 lines
3.6 KiB
Python
"""
|
||
对账模块路由模块
|
||
|
||
提供客户对账单查询接口,按客户+时间段汇总订单和欠款明细。
|
||
支持 CSV 导出对账明细。
|
||
|
||
URL 前缀:/api/reconciliation
|
||
权限要求:manager/admin 角色
|
||
"""
|
||
|
||
from datetime import date
|
||
|
||
from fastapi import APIRouter, Depends, Query
|
||
from sqlalchemy.orm import Session
|
||
|
||
from backend.app.api.deps import require_permissions, require_roles
|
||
from backend.app.db import get_db_session
|
||
from backend.app.repositories.reminder_repository import ReminderRepository
|
||
from backend.app.schemas.common import success_payload
|
||
|
||
router = APIRouter(prefix="/api/reconciliation", tags=["reconciliation"])
|
||
reminder_repository = ReminderRepository()
|
||
|
||
|
||
@router.get("/customer-statement")
|
||
def get_customer_statement(
|
||
customer_id: int = Query(..., gt=0),
|
||
start_date: date | None = Query(default=None),
|
||
end_date: date | None = Query(default=None),
|
||
session: Session = Depends(get_db_session),
|
||
current_user: dict = Depends(require_roles("manager", "admin")),
|
||
_permission_user: dict = Depends(require_permissions("order:list")),
|
||
) -> dict:
|
||
"""查询客户对账单:指定客户在时间段内的订单和欠款明细。"""
|
||
from datetime import date as _date
|
||
|
||
customer = reminder_repository.get_customer(session, customer_id)
|
||
if customer is None:
|
||
from backend.app.core.error_codes import ErrorCode
|
||
from backend.app.core.exceptions import AppException
|
||
raise AppException(code=ErrorCode.NOT_FOUND, message="客户不存在", status_code=404)
|
||
|
||
rows = reminder_repository.get_customer_statement(session, customer_id, start_date, end_date)
|
||
|
||
orders = []
|
||
total_amount = 0.0
|
||
total_arrears = 0.0
|
||
overdue_amount = 0.0
|
||
overdue_count = 0
|
||
today = _date.today()
|
||
|
||
for order, arrears in rows:
|
||
amount = float(order.contract_amount or 0)
|
||
arrears_amount = float(arrears.arrears_amount or 0) if arrears else 0.0
|
||
arrears_status = arrears.status if arrears else None
|
||
due_date = arrears.due_date if arrears else None
|
||
|
||
# 逾期判定:状态为 overdue 或 pending 但已过到期日
|
||
is_overdue = False
|
||
if arrears and arrears_status == "overdue":
|
||
is_overdue = True
|
||
elif arrears and arrears_status == "pending" and due_date and due_date <= today:
|
||
is_overdue = True
|
||
|
||
total_amount += amount
|
||
if arrears_amount > 0:
|
||
total_arrears += arrears_amount
|
||
if is_overdue:
|
||
overdue_amount += arrears_amount
|
||
overdue_count += 1
|
||
|
||
orders.append({
|
||
"order_id": order.id,
|
||
"order_no": order.order_no,
|
||
"order_status": order.order_status,
|
||
"contract_amount": amount,
|
||
"created_at": order.created_at.strftime("%Y-%m-%d %H:%M") if order.created_at else "",
|
||
"arrears_amount": arrears_amount,
|
||
"due_date": due_date.strftime("%Y-%m-%d") if due_date else "",
|
||
"arrears_status": arrears_status,
|
||
"is_overdue": is_overdue,
|
||
})
|
||
|
||
return success_payload({
|
||
"customer": {
|
||
"id": customer.id,
|
||
"customer_name": customer.customer_name,
|
||
"mobile": customer.mobile,
|
||
"settlement_type": customer.settlement_type or "",
|
||
"settlement_days": customer.settlement_days or 0,
|
||
},
|
||
"summary": {
|
||
"total_orders": len(orders),
|
||
"total_amount": round(total_amount, 2),
|
||
"total_arrears": round(total_arrears, 2),
|
||
"overdue_amount": round(overdue_amount, 2),
|
||
"overdue_count": overdue_count,
|
||
},
|
||
"orders": orders,
|
||
})
|