feat: P0-5 收款财务闭环(收款登记/作废/统计/账户管理/财务页)

This commit is contained in:
HHY
2026-09-25 03:20:10 -07:00
parent cc5b3de6b2
commit 436d006b5a
11 changed files with 528 additions and 4 deletions
+20 -3
View File
@@ -1,6 +1,7 @@
"""合同路由:意向单/正式单管理。"""
from fastapi import APIRouter
from pydantic import BaseModel, Field
from sqlalchemy import select
from huamenchuang.core.deps import CurrentUser, DbSession
from huamenchuang.core.response import fail, ok, paginated
@@ -46,11 +47,27 @@ async def create_contract(body: ContractBody, user: CurrentUser, db: DbSession):
@router.get("")
async def list_contracts(user: CurrentUser, db: DbSession, page: int = 1,
page_size: int = 15, keyword: str = "", status: int | None = None):
"""合同分页列表(结构对齐目标站 {"contracts": {...}})。"""
"""合同分页列表(结构对齐目标站 {"contracts": {...}},含已收金额)。"""
items, total = await ContractService(db).repo.search(
user.company_id, page, page_size, keyword, status)
return ok(data={"contracts": paginated(
[_to_out(c) for c in items], page, page_size, total)})
# 当页合同的有效收款聚合(一次 GROUP BY,避免逐行查询)
received_map: dict[int, float] = {}
if items:
from sqlalchemy import func
from huamenchuang.models.business import ContractReceipt
ids = [c.id for c in items]
rows = (await db.execute(
select(ContractReceipt.contract_id, func.sum(ContractReceipt.amount))
.where(ContractReceipt.contract_id.in_(ids), ContractReceipt.status == 1)
.group_by(ContractReceipt.contract_id))).all()
received_map = {cid: float(v or 0) for cid, v in rows}
outs = []
for c in items:
out = _to_out(c)
out["received"] = round(received_map.get(c.id, 0), 2)
out["unreceived"] = round(float(c.money) - out["received"], 2)
outs.append(out)
return ok(data={"contracts": paginated(outs, page, page_size, total)})
@router.put("/{contract_id}")