"""回款管理接口(需求 2.2.3)。 回款按业务登记到账款项,批次号自动生成(HK 前缀)。校验规则(发货 批次同业务强校验、已核算禁改禁删、汇总重算)见 `receipt_service` 模块 docstring;基础数据属业务操作,登录即可访问。 """ from typing import Annotated from fastapi import APIRouter, Depends, Path, Query from app.api.deps import DbSession, PayrollWriter, RequestMetaDep, get_current_user from app.core.response import ApiResponse, PageResult, ok from app.models import User from app.schemas.receipt import ( ReceiptConfirmIn, ReceiptCreateIn, ReceiptOut, ReceiptQuery, ReceiptUpdateIn, ) from app.services import receipt_confirmation, receipt_service # 基础数据是业务操作:登录即可,不要求管理员(区别于系统管理的 AdminUser) CurrentUser = Annotated[User, Depends(get_current_user)] router = APIRouter(prefix="/receipts", tags=["回款管理"]) @router.get("/confirmation-policy", summary="回款人工确认开关状态") def confirmation_policy(session: DbSession, _: CurrentUser): return ok({"enabled": receipt_confirmation.enabled(session)}) @router.post("/{receipt_id}/confirm", response_model=ApiResponse[ReceiptOut], summary="独立人工确认回款") def confirm_receipt( receipt_id: Annotated[int, Path(ge=1)], payload: ReceiptConfirmIn, session: DbSession, current_user: CurrentUser, meta: RequestMetaDep, ): return ok(receipt_service.confirm_receipt( session, receipt_id, payload, operator=current_user, meta=meta, ), message="回款已人工确认") @router.get("", response_model=ApiResponse[PageResult[ReceiptOut]], summary="回款列表") def list_receipts( session: DbSession, _: CurrentUser, query: Annotated[ReceiptQuery, Query()], ) -> ApiResponse[PageResult[ReceiptOut]]: """分页查询回款。附业务号/发货单号与回款天数派生值,可按业务/日期/抵顶/核算状态筛选。""" return ok(receipt_service.list_receipts(session, query)) @router.post("", response_model=ApiResponse[ReceiptOut], summary="新增回款") def create_receipt( session: DbSession, current_user: PayrollWriter, payload: ReceiptCreateIn, meta: RequestMetaDep, ) -> ApiResponse[ReceiptOut]: """新增回款。批次号自动生成;发货批次须与本回款同属一个业务;业务须执行中。""" return ok( receipt_service.create_receipt(session, payload, operator=current_user, meta=meta), message="回款已登记", ) @router.get("/{receipt_id}", response_model=ApiResponse[ReceiptOut], summary="回款详情") def get_receipt( session: DbSession, _: CurrentUser, receipt_id: Annotated[int, Path(ge=1)], ) -> ApiResponse[ReceiptOut]: """回款详情(含回款天数派生值,未指定发货批次时为空)。""" return ok(receipt_service.get_detail(session, receipt_id)) @router.put("/{receipt_id}", response_model=ApiResponse[ReceiptOut], summary="编辑回款") def update_receipt( session: DbSession, current_user: PayrollWriter, receipt_id: Annotated[int, Path(ge=1)], payload: ReceiptUpdateIn, meta: RequestMetaDep, ) -> ApiResponse[ReceiptOut]: """编辑回款(全量替换并重算合计)。已核算回款禁止修改;发货批次重新校验同业务。""" return ok( receipt_service.update_receipt( session, receipt_id, payload, operator=current_user, meta=meta ), message="已保存", ) @router.delete("/{receipt_id}", response_model=ApiResponse[None], summary="删除回款") def delete_receipt( session: DbSession, current_user: PayrollWriter, receipt_id: Annotated[int, Path(ge=1)], meta: RequestMetaDep, ) -> ApiResponse[None]: """删除回款。已核算回款禁止删除;业务已完成或已终止时禁删。""" receipt_service.delete_receipt(session, receipt_id, operator=current_user, meta=meta) return ok(message="回款已删除")