瀏覽代碼

fix(oa): coerce dept max prop when validating form_data

Co-authored-by: Cursor <cursoragent@cursor.com>
zlwu 3 月之前
父節點
當前提交
babe26a23d
共有 2 個文件被更改,包括 45 次插入 和 9 次删除
  1. 26 9
      backend/app/services/oa_dept_select.py
  2. 19 0
      backend/tests/test_oa_dept_select.py

+ 26 - 9
backend/app/services/oa_dept_select.py

@@ -28,27 +28,45 @@ def _schema_rules(schema: Any) -> List[dict]:
     return out
 
 
+def _rule_props(rule: dict) -> dict:
+    props = rule.get("props")
+    return props if isinstance(props, dict) else {}
+
+
 def _field_label(rule: dict) -> str:
     return str(rule.get("title") or rule.get("label") or rule.get("field") or "部门")
 
 
 def _is_required(rule: dict) -> bool:
-    props = rule.get("props") or {}
-    if rule.get("$required"):
+    props = _rule_props(rule)
+    if rule.get("$required") is True:
         return True
-    if rule.get("required"):
+    if rule.get("required") is True:
         return True
-    if props.get("required"):
+    if props.get("required") is True:
         return True
     return False
 
 
 def _is_multiple(rule: dict) -> bool:
-    props = rule.get("props") or {}
+    props = _rule_props(rule)
     multiple = props.get("multiple")
     if multiple is None:
         return True
-    return bool(multiple)
+    return multiple is True
+
+
+def _max_count(rule: dict) -> Optional[int]:
+    raw = _rule_props(rule).get("max")
+    if raw is None or raw == "":
+        return None
+    try:
+        value = int(raw)
+    except (TypeError, ValueError):
+        return None
+    if value <= 0:
+        return None
+    return value
 
 
 def _is_valid_dept_item(item: Any) -> bool:
@@ -71,8 +89,7 @@ def _validate_dept_rule(rule: dict, data: Dict[str, Any]) -> List[str]:
     label = _field_label(rule)
     required = _is_required(rule)
     multiple = _is_multiple(rule)
-    props = rule.get("props") or {}
-    max_count = props.get("max")
+    max_count = _max_count(rule)
     value = data.get(field)
     errors: List[str] = []
 
@@ -91,7 +108,7 @@ def _validate_dept_rule(rule: dict, data: Dict[str, Any]) -> List[str]:
             if not _is_valid_dept_item(item):
                 errors.append(f"「{label}」部门项格式不正确,需包含有效的 id 与 name")
                 break
-        if max_count is not None and isinstance(max_count, int) and len(value) > max_count:
+        if max_count is not None and len(value) > max_count:
             errors.append(f"「{label}」选择部门数量超过最大上限 {max_count} 个")
         return errors
 

+ 19 - 0
backend/tests/test_oa_dept_select.py

@@ -70,6 +70,25 @@ class TestValidateDeptFormValues(unittest.TestCase):
         errs = validate_dept_form_values(schema, data)
         self.assertTrue(any("最大" in e or "上限" in e for e in errs))
 
+    def test_max_exceeded_string_max(self):
+        schema = {
+            "rule": [
+                {
+                    "type": "dept",
+                    "field": "depts",
+                    "props": {"multiple": True, "max": "1"},
+                }
+            ]
+        }
+        data = {
+            "depts": [
+                {"id": "d1", "name": "A"},
+                {"id": "d2", "name": "B"},
+            ]
+        }
+        errs = validate_dept_form_values(schema, data)
+        self.assertTrue(any("最大" in e or "上限" in e for e in errs))
+
     def test_nested_fc_row(self):
         schema = {
             "rule": [