Quellcode durchsuchen

fix: 成员范围修改覆盖所有类型转换场景正确计算员工差异

alphah vor 2 Wochen
Ursprung
Commit
8a1afa12b8
1 geänderte Dateien mit 78 neuen und 30 gelöschten Zeilen
  1. 78 30
      backend/app/plugin/module_payment/expense/institution/controller.py

+ 78 - 30
backend/app/plugin/module_payment/expense/institution/controller.py

@@ -400,34 +400,81 @@ async def modify_scope_controller(
     auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:expense:institution:scope:modify"]))],
 ) -> JSONResponse:
     """设置制度成员"""
-    enterprise_id = data.get("enterprise_id", "")
+    from app.plugin.module_payment.employee.model import EmployeeModel
+    from sqlalchemy import select
 
-    # 计算新旧员工差异(用于额度联动)
-    add_ids: list[str] = []
-    delete_ids: list[str] = []
-    adapter_type = data.get("adapter_type", "EMPLOYEE_ALL")
+    enterprise_id = data.get("enterprise_id", "")
+    new_adapter = data.get("adapter_type", "EMPLOYEE_ALL")
 
-    if adapter_type in ("EMPLOYEE_SELECT", "EMPLOYEE_DEPARTMENT"):
-        new_ids_raw = data.get("add_owner_id_list") or []
-        new_ids = [str(i) for i in new_ids_raw if i is not None and str(i).strip()]
-        try:
-            scope_old = await InstitutionScopeService.scopepageinfo_query_service(
-                auth=auth, institution_id=institution_id, enterprise_id=enterprise_id,
-                page_num=1, page_size=500,
+    # ====== 1. 查询旧适配类型和老员工ID列表 ======
+    old_adapter = new_adapter
+    old_employee_ids: set[str] = set()
+    try:
+        scope_old = await InstitutionScopeService.scopepageinfo_query_service(
+            auth=auth, institution_id=institution_id, enterprise_id=enterprise_id,
+            page_num=1, page_size=500,
+        )
+        old_adapter = scope_old.get("adapter_type", old_adapter)
+        raw_old = [str(i) for i in (scope_old.get("owner_id_list") or []) if i]
+        if old_adapter == "EMPLOYEE_ALL":
+            # 全体员工模式 → 所有已签约员工
+            stmt = select(EmployeeModel.employee_id).where(
+                EmployeeModel.enterprise_id == enterprise_id,
+                EmployeeModel.status == "ACTIVATED",
             )
-            old_ids = [str(i) for i in (scope_old.get("owner_id_list") or []) if i]
-        except Exception:
-            old_ids = []
-            log.warning(f"查询旧scope失败,将全量覆盖: institution_id={institution_id}")
-
-        old_set, new_set = set(old_ids), set(new_ids)
-        add_ids = list(new_set - old_set)
-        delete_ids = list(old_set - new_set)
-
-    # 构建请求数据(传差异)
+            result = await auth.db.execute(stmt)
+            old_employee_ids = {row[0] for row in result.fetchall() if row[0]}
+        elif old_adapter == "EMPLOYEE_DEPARTMENT":
+            # 按部门模式 → 部门下的所有已签约员工
+            from app.plugin.module_payment.employee.model import EmployeeModel
+            stmt = select(EmployeeModel.employee_id, EmployeeModel.department_ids).where(
+                EmployeeModel.enterprise_id == enterprise_id,
+                EmployeeModel.status == "ACTIVATED",
+            )
+            result = await auth.db.execute(stmt)
+            dept_set = set(raw_old)
+            for row in result.fetchall():
+                if row[1] and dept_set.intersection(set(row[1])):
+                    if row[0]:
+                        old_employee_ids.add(row[0])
+        else:
+            old_employee_ids = set(raw_old)
+    except Exception:
+        log.warning(f"查询旧scope失败(将全量处理): institution_id={institution_id}")
+
+    # ====== 2. 计算新员工ID列表 ======
+    new_employee_ids: set[str] = set()
+    if new_adapter == "EMPLOYEE_ALL":
+        stmt = select(EmployeeModel.employee_id).where(
+            EmployeeModel.enterprise_id == enterprise_id,
+            EmployeeModel.status == "ACTIVATED",
+        )
+        result = await auth.db.execute(stmt)
+        new_employee_ids = {row[0] for row in result.fetchall() if row[0]}
+    elif new_adapter == "EMPLOYEE_DEPARTMENT":
+        dept_ids = data.get("add_owner_id_list") or []
+        dept_set = set(str(d) for d in dept_ids if d)
+        stmt = select(EmployeeModel.employee_id, EmployeeModel.department_ids).where(
+            EmployeeModel.enterprise_id == enterprise_id,
+            EmployeeModel.status == "ACTIVATED",
+        )
+        result = await auth.db.execute(stmt)
+        for row in result.fetchall():
+            if row[1] and dept_set.intersection(set(row[1])):
+                if row[0]:
+                    new_employee_ids.add(row[0])
+    else:
+        raw_new = data.get("add_owner_id_list") or []
+        new_employee_ids = set(str(i) for i in raw_new if i is not None and str(i).strip())
+
+    # ====== 3. 计算差异 ======
+    add_ids = list(new_employee_ids - old_employee_ids)
+    delete_ids = list(old_employee_ids - new_employee_ids)
+
+    # ====== 4. 调用支付宝 scope.modify(只传差异) ======
     scope_data = {
         "enterprise_id": enterprise_id,
-        "adapter_type": adapter_type,
+        "adapter_type": new_adapter,
         "owner_type": data.get("owner_type", "EMPLOYEE"),
     }
     if add_ids:
@@ -441,22 +488,23 @@ async def modify_scope_controller(
         data=scope_data,
     )
 
-    # 成功后在本地同步 scope 数据
+    # ====== 5. 更新本地库 + 额度联动 ======
     try:
         from .crud import InstitutionCRUD
         crud = InstitutionCRUD(auth)
         scope_map = {"EMPLOYEE_ALL": "all", "EMPLOYEE_SELECT": "employee", "EMPLOYEE_DEPARTMENT": "department"}
-        applicable_scope = scope_map.get(adapter_type, "all")
+        applicable_scope = scope_map.get(new_adapter, "all")
         update_data = {"applicable_scope": applicable_scope}
-        if adapter_type == "EMPLOYEE_DEPARTMENT" and new_ids:
-            update_data["department_id"] = new_ids[0]
+        if new_adapter == "EMPLOYEE_DEPARTMENT":
+            dept_ids = data.get("add_owner_id_list") or []
+            if dept_ids:
+                update_data["department_id"] = str(dept_ids[0])
         await crud.update_by_institution_id(institution_id, update_data)
 
-        # 同步员工额度记录(使用计算好的差异)
         if enterprise_id:
             from .service import InstitutionService
             scope_info = {
-                "adapter_type": adapter_type,
+                "adapter_type": new_adapter,
                 "owner_type": "EMPLOYEE",
                 "add_owner_id_list": add_ids,
                 "delete_owner_id_list": delete_ids,
@@ -471,7 +519,7 @@ async def modify_scope_controller(
     except Exception as e:
         log.warning(f"本地scope同步失败(不影响支付宝侧): {e}")
 
-    log.info(f"设置制度成员成功: institution_id={institution_id}, adapter_type={adapter_type}, "
+    log.info(f"设置成员成功: {old_adapter}→{new_adapter}, "
              f"加{len(add_ids)}人, 减{len(delete_ids)}人")
     return SuccessResponse(data=result, msg="设置成功")