File size: 1,823 Bytes
b4f2238
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
"""
合同财务统计 API 层
符合三层架构规范:只做请求/响应处理,业务逻辑在 Service 层
"""

from __future__ import annotations

from typing import Any

from django.http import HttpRequest
from django.utils.dateparse import parse_date
from ninja import Router

from apps.contracts.schemas import FinanceStatsItem, FinanceStatsOut
from apps.contracts.services.payment.contract_finance_service import ContractFinanceService

router = Router()


def _get_finance_service() -> ContractFinanceService:
    """工厂函数:创建 ContractFinanceService 实例"""
    return ContractFinanceService()


@router.get("/finance/stats", response=FinanceStatsOut)
def finance_stats(
    request: HttpRequest,
    contract_id: int | None = None,
    start_date: str | None = None,
    end_date: str | None = None,
) -> FinanceStatsOut:
    """
    获取财务统计数据

    API 层职责:
    1. 接收请求参数
    2. 解析日期参数
    3. 调用 Service 层方法
    4. 返回响应
    """
    service = _get_finance_service()

    # 解析日期参数
    d1 = parse_date(start_date) if start_date else None
    d2 = parse_date(end_date) if end_date else None

    # 调用 Service 层
    result = service.get_finance_stats(
        contract_id=contract_id,
        start_date=d1,
        end_date=d2,
    )

    # 转换为 Schema
    items = [
        FinanceStatsItem(
            contract_id=item["contract_id"],
            total_received=item["total_received"],
            total_invoiced=item["total_invoiced"],
            unpaid_amount=item["unpaid_amount"],
        )
        for item in result["items"]
    ]

    return FinanceStatsOut(
        items=items,
        total_received_all=result["total_received_all"],
        total_invoiced_all=result["total_invoiced_all"],
    )