Bläddra i källkod

fix(quota): 详情端点回查支付宝 + 创建批次前清理陈旧记录

alphah 2 veckor sedan
förälder
incheckning
3c336308b4

+ 71 - 21
backend/app/plugin/module_payment/expense/quota/controller.py

@@ -151,30 +151,80 @@ async def detail_quota_controller(
     auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:expense:quota:detail"]))],
 ) -> JSONResponse:
     from .model import QuotaModel
-    from sqlalchemy import select
+    from sqlalchemy import select, update as sa_update
     stmt = select(QuotaModel).where(QuotaModel.quota_id == quota_id)
     result = await auth.db.execute(stmt)
     quota = result.scalar_one_or_none()
-    if not quota:
-        return SuccessResponse(data=None, msg="额度不存在")
-    return SuccessResponse(data={
-        "id": quota.id,
-        "quota_id": quota.quota_id,
-        "employee_id": quota.employee_id,
-        "institution_id": quota.institution_id,
-        "out_biz_no": quota.out_biz_no,
-        "quota_type": quota.quota_type,
-        "target_type": quota.target_type,
-        "target_id": quota.target_id,
-        "total_amount": float(quota.total_amount) if quota.total_amount else 0,
-        "available_amount": float(quota.available_amount) if quota.available_amount else 0,
-        "status": quota.status,
-        "valid_from": quota.valid_from.strftime("%Y-%m-%d %H:%M:%S") if quota.valid_from else None,
-        "valid_to": quota.valid_to.strftime("%Y-%m-%d %H:%M:%S") if quota.valid_to else None,
-        "created_time": str(quota.created_time) if quota.created_time else None,
-        "updated_time": str(quota.updated_time) if quota.updated_time else None,
-        "enterprise_id": quota.enterprise_id,
-    }, msg="查询额度详情成功")
+    if quota:
+        return SuccessResponse(data={
+            "id": quota.id,
+            "quota_id": quota.quota_id,
+            "employee_id": quota.employee_id,
+            "institution_id": quota.institution_id,
+            "out_biz_no": quota.out_biz_no,
+            "quota_type": quota.quota_type,
+            "target_type": quota.target_type,
+            "target_id": quota.target_id,
+            "total_amount": float(quota.total_amount) if quota.total_amount else 0,
+            "available_amount": float(quota.available_amount) if quota.available_amount else 0,
+            "status": quota.status,
+            "valid_from": quota.valid_from.strftime("%Y-%m-%d %H:%M:%S") if quota.valid_from else None,
+            "valid_to": quota.valid_to.strftime("%Y-%m-%d %H:%M:%S") if quota.valid_to else None,
+            "created_time": str(quota.created_time) if quota.created_time else None,
+            "updated_time": str(quota.updated_time) if quota.updated_time else None,
+            "enterprise_id": quota.enterprise_id,
+        }, msg="查询额度详情成功")
+    # 本地未找到时,回查支付宝
+    try:
+        from alipay.aop.api.request.AlipayEbppInvoiceExpensecontrolQuotaQueryRequest import (
+            AlipayEbppInvoiceExpensecontrolQuotaQueryRequest,
+        )
+        from alipay.aop.api.domain.AlipayEbppInvoiceExpensecontrolQuotaQueryModel import (
+            AlipayEbppInvoiceExpensecontrolQuotaQueryModel,
+        )
+        from alipay.aop.api.response.AlipayEbppInvoiceExpensecontrolQuotaQueryResponse import (
+            AlipayEbppInvoiceExpensecontrolQuotaQueryResponse,
+        )
+        from app.core.alipay_client import AlipayClient
+
+        alipay_model = AlipayEbppInvoiceExpensecontrolQuotaQueryModel()
+        alipay_model.owner_type = "ENTERPRISE_PAY_UID"
+        alipay_model.quota_id_list = [quota_id]
+        alipay_model.page_size = 1
+        alipay_model.page_num = 1
+
+        request = AlipayEbppInvoiceExpensecontrolQuotaQueryRequest()
+        request.biz_model = alipay_model
+
+        client = AlipayClient.get_client()
+        response = client.execute(request)
+
+        if response:
+            alipay_result = AlipayEbppInvoiceExpensecontrolQuotaQueryResponse()
+            alipay_result.parse_response_content(response)
+            if alipay_result.is_success() and hasattr(alipay_result, 'quota_detail_info_list') and alipay_result.quota_detail_info_list:
+                q = alipay_result.quota_detail_info_list[0]
+                return SuccessResponse(data={
+                    "quota_id": getattr(q, 'quota_id', None),
+                    "target_type": getattr(q, 'target_type', None),
+                    "target_id": getattr(q, 'target_id', None),
+                    "quota_type": getattr(q, 'quota_type', None),
+                    "total_amount": float(getattr(q, 'total_amount', 0)) if getattr(q, 'total_amount', None) else 0,
+                    "available_amount": float(getattr(q, 'available_amount', 0)) if getattr(q, 'available_amount', None) else 0,
+                    "frozen_amount": float(getattr(q, 'frozen_amount', 0)) if getattr(q, 'frozen_amount', None) else 0,
+                    "consumed_amount": float(getattr(q, 'consumed_amount', 0)) if getattr(q, 'consumed_amount', None) else 0,
+                    "status": getattr(q, 'status', "QUOTA_ACTIVE"),
+                    "valid_from": getattr(q, 'effective_start_date', None),
+                    "valid_to": getattr(q, 'effective_end_date', None),
+                    "employee_id": getattr(q, 'owner_id', None),
+                    "owner_id": getattr(q, 'owner_id', None),
+                    "owner_open_id": getattr(q, 'owner_open_id', None),
+                    "owner_type": getattr(q, 'owner_type', None),
+                }, msg="查询额度详情成功(支付宝)")
+    except Exception as e:
+        log.warning(f"查询支付宝额度详情失败: {e}")
+
+    return SuccessResponse(data=None, msg="额度不存在")
 
 
 # ========================

+ 15 - 1
backend/app/plugin/module_payment/expense/quota/service.py

@@ -447,7 +447,21 @@ class QuotaService:
         try:
             from app.plugin.module_payment.expense.quota.model import QuotaModel
             from app.plugin.module_payment.expense.quota.enums import QuotaStatusEnum
-            from sqlalchemy import insert
+            from sqlalchemy import insert, delete as sa_delete
+
+            # 清理同一制度下 quota_id 为空的陈旧记录(来自较早失败/未完成的批次)
+            try:
+                clean_stmt = sa_delete(QuotaModel).where(
+                    QuotaModel.institution_id == data.institution_id,
+                    QuotaModel.quota_id.is_(None),
+                )
+                result = await auth.db.execute(clean_stmt)
+                if result.rowcount:
+                    log.info(f"手工发放 - 清理 {result.rowcount} 条陈旧记录(institution_id={data.institution_id})")
+                await auth.db.flush()
+            except Exception as e:
+                log.warning(f"手工发放 - 清理陈旧记录失败(不影响发放): {e}")
+
             tenant_id = auth.user.tenant_id if auth.user else 1
             effective_start = datetime.strptime(data.effective_start_date, "%Y-%m-%d %H:%M:%S") if data.effective_start_date else None
             effective_end = datetime.strptime(data.effective_end_date, "%Y-%m-%d %H:%M:%S") if data.effective_end_date else None