Quellcode durchsuchen

feat(bx): add parse_optional_date for nullable occur dates

Empty values map to None so optional detail dates do not default to today.

Co-authored-by: Cursor <cursoragent@cursor.com>
zlwu vor 2 Monaten
Ursprung
Commit
3b8a0eb7d8
2 geänderte Dateien mit 36 neuen und 0 gelöschten Zeilen
  1. 14 0
      backend/app/utils/bx_codegen.py
  2. 22 0
      backend/tests/test_bx_optional_date.py

+ 14 - 0
backend/app/utils/bx_codegen.py

@@ -50,6 +50,20 @@ def parse_reimburse_date(value: str | date | datetime | None) -> date:
     return datetime.strptime(text_value, "%Y-%m-%d").date()
 
 
+def parse_optional_date(value: str | date | datetime | None) -> date | None:
+    """可选日期:空 → None;合法 YYYY-MM-DD / date / datetime → date。"""
+    if value is None:
+        return None
+    if isinstance(value, datetime):
+        return value.date()
+    if isinstance(value, date):
+        return value
+    text_value = str(value).strip()
+    if not text_value:
+        return None
+    return datetime.strptime(text_value, "%Y-%m-%d").date()
+
+
 def format_reimburse_title(applicant_name: str, reimburse_date: date, seq: int) -> str:
     return f"{applicant_name}报销单{reimburse_date.strftime('%Y%m%d')}{seq:03d}"
 

+ 22 - 0
backend/tests/test_bx_optional_date.py

@@ -0,0 +1,22 @@
+from datetime import date, datetime
+
+import pytest
+
+from app.utils.bx_codegen import parse_optional_date
+
+
+def test_parse_optional_date_none_and_blank():
+    assert parse_optional_date(None) is None
+    assert parse_optional_date("") is None
+    assert parse_optional_date("   ") is None
+
+
+def test_parse_optional_date_string_and_date():
+    assert parse_optional_date("2026-08-17") == date(2026, 8, 17)
+    assert parse_optional_date(date(2026, 1, 2)) == date(2026, 1, 2)
+    assert parse_optional_date(datetime(2026, 3, 4, 12, 0, 0)) == date(2026, 3, 4)
+
+
+def test_parse_optional_date_invalid():
+    with pytest.raises(ValueError):
+        parse_optional_date("2026/08/17")