"""一覧系画面で再利用するExplorerフレームワーク(最小版)。""" from dataclasses import dataclass from datetime import datetime, timedelta from typing import Optional, Tuple EXPLORER_PERIODS = { "7d": "直近7日", "30d": "直近30日", "3m": "直近3ヶ月", "1y": "直近1年", "all": "全期間", } EXPLORER_SORTS = { "date": "日付", "invoice_number": "伝票番号", "customer_name": "顧客名", "document_type": "種別", "updated_at": "更新日時", } @dataclass class ExplorerQueryState: """Explorerの検索状態。""" query: str = "" period_key: str = "3m" sort_key: str = "date" sort_desc: bool = True include_offsets: bool = False limit: int = 50 offset: int = 0 def to_date_range(period_key: str, now: Optional[datetime] = None) -> Tuple[Optional[str], Optional[str]]: """期間キーからISO形式の日付範囲を返す。""" now = now or datetime.now() if period_key == "all": return None, None if period_key == "7d": start = now - timedelta(days=7) elif period_key == "30d": start = now - timedelta(days=30) elif period_key == "3m": start = now - timedelta(days=90) elif period_key == "1y": start = now - timedelta(days=365) else: start = now - timedelta(days=90) return start.replace(microsecond=0).isoformat(), now.replace(microsecond=0).isoformat()