From 3b8a0eb7d8156809d2ac64ab6ec0dab814eb4ab6 Mon Sep 17 00:00:00 2001 From: zlwu <704541015@qq.com> Date: Mon, 17 Aug 2026 15:57:15 +0800 Subject: [PATCH] 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 --- backend/app/utils/bx_codegen.py | 14 ++++++++++++++ backend/tests/test_bx_optional_date.py | 22 ++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 backend/tests/test_bx_optional_date.py diff --git a/backend/app/utils/bx_codegen.py b/backend/app/utils/bx_codegen.py index 3d63d44a4..8e2b6ad40 100644 --- a/backend/app/utils/bx_codegen.py +++ b/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}" diff --git a/backend/tests/test_bx_optional_date.py b/backend/tests/test_bx_optional_date.py new file mode 100644 index 000000000..9cc6767c3 --- /dev/null +++ b/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")