mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-03 01:40:21 +08:00
fix(config): 统一 APP_TIMEZONE 至 Config 类,修复 wallet 循环导入
将散落在 scheduler / stats_aggregator / daily_usage_ledger / routes
中的 os.getenv("APP_TIMEZONE") 收归 Config.app_timezone,消除
wallet → system → maintenance_scheduler → user.preference → wallet
的循环导入链。
This commit is contained in:
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import os
|
|
||||||
from datetime import datetime, timedelta, timezone
|
from datetime import datetime, timedelta, timezone
|
||||||
from typing import Any, Literal
|
from typing import Any, Literal
|
||||||
from zoneinfo import ZoneInfo
|
from zoneinfo import ZoneInfo
|
||||||
@@ -18,6 +17,7 @@ from sqlalchemy.orm import Session
|
|||||||
from src.api.base.admin_adapter import AdminApiAdapter
|
from src.api.base.admin_adapter import AdminApiAdapter
|
||||||
from src.api.base.context import ApiRequestContext
|
from src.api.base.context import ApiRequestContext
|
||||||
from src.api.base.pipeline import ApiRequestPipeline
|
from src.api.base.pipeline import ApiRequestPipeline
|
||||||
|
from src.config import config
|
||||||
from src.core.exceptions import InvalidRequestException, NotFoundException
|
from src.core.exceptions import InvalidRequestException, NotFoundException
|
||||||
from src.core.logger import logger
|
from src.core.logger import logger
|
||||||
from src.database import get_db, get_db_context
|
from src.database import get_db, get_db_context
|
||||||
@@ -27,8 +27,7 @@ from src.services.user.apikey import ApiKeyService
|
|||||||
from src.services.user.bulk_cleanup import pre_clean_api_key
|
from src.services.user.bulk_cleanup import pre_clean_api_key
|
||||||
from src.services.wallet import WalletService
|
from src.services.wallet import WalletService
|
||||||
|
|
||||||
# 应用时区配置,默认为 Asia/Shanghai
|
APP_TIMEZONE = ZoneInfo(config.app_timezone)
|
||||||
APP_TIMEZONE = ZoneInfo(os.getenv("APP_TIMEZONE", "Asia/Shanghai"))
|
|
||||||
|
|
||||||
|
|
||||||
def parse_expiry_date(date_str: str | None) -> datetime | None:
|
def parse_expiry_date(date_str: str | None) -> datetime | None:
|
||||||
|
|||||||
@@ -647,12 +647,12 @@ class UserDashboardStatsAdapter(DashboardAdapter):
|
|||||||
async def handle(self, context: ApiRequestContext) -> Any: # type: ignore[override]
|
async def handle(self, context: ApiRequestContext) -> Any: # type: ignore[override]
|
||||||
from zoneinfo import ZoneInfo
|
from zoneinfo import ZoneInfo
|
||||||
|
|
||||||
from src.services.system.stats_aggregator import APP_TIMEZONE
|
from src.config import config
|
||||||
|
|
||||||
db = context.db
|
db = context.db
|
||||||
user = context.user
|
user = context.user
|
||||||
# 使用业务时区计算日期,确保与用户感知的"今天"一致
|
# 使用业务时区计算日期,确保与用户感知的"今天"一致
|
||||||
app_tz = ZoneInfo(APP_TIMEZONE)
|
app_tz = ZoneInfo(config.app_timezone)
|
||||||
now_local = datetime.now(app_tz)
|
now_local = datetime.now(app_tz)
|
||||||
today_local = now_local.replace(hour=0, minute=0, second=0, microsecond=0)
|
today_local = now_local.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||||
# 转换为 UTC 用于数据库查询
|
# 转换为 UTC 用于数据库查询
|
||||||
@@ -1159,9 +1159,9 @@ class DashboardDailyStatsAdapter(DashboardAdapter):
|
|||||||
# 使用业务时区计算日期,确保每日统计与业务日期一致
|
# 使用业务时区计算日期,确保每日统计与业务日期一致
|
||||||
from zoneinfo import ZoneInfo
|
from zoneinfo import ZoneInfo
|
||||||
|
|
||||||
from src.services.system.stats_aggregator import APP_TIMEZONE
|
from src.config import config
|
||||||
|
|
||||||
app_tz = ZoneInfo(APP_TIMEZONE)
|
app_tz = ZoneInfo(config.app_timezone)
|
||||||
now_local = datetime.now(app_tz)
|
now_local = datetime.now(app_tz)
|
||||||
today_local = now_local.replace(hour=0, minute=0, second=0, microsecond=0)
|
today_local = now_local.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||||
# 转换为 UTC 用于数据库查询
|
# 转换为 UTC 用于数据库查询
|
||||||
|
|||||||
@@ -87,6 +87,9 @@ class Config:
|
|||||||
# 注意: allow_credentials=True 时不能使用 allow_origins=["*"]
|
# 注意: allow_credentials=True 时不能使用 allow_origins=["*"]
|
||||||
self.cors_allow_credentials = os.getenv("CORS_ALLOW_CREDENTIALS", "true").lower() == "true"
|
self.cors_allow_credentials = os.getenv("CORS_ALLOW_CREDENTIALS", "true").lower() == "true"
|
||||||
|
|
||||||
|
# 应用时区配置(用于定时任务、账单日期等业务逻辑)
|
||||||
|
self.app_timezone = os.getenv("APP_TIMEZONE", "Asia/Shanghai")
|
||||||
|
|
||||||
# 管理员账户配置(用于初始化)
|
# 管理员账户配置(用于初始化)
|
||||||
self.admin_email = os.getenv("ADMIN_EMAIL", "admin@localhost")
|
self.admin_email = os.getenv("ADMIN_EMAIL", "admin@localhost")
|
||||||
self.admin_username = os.getenv("ADMIN_USERNAME", "admin")
|
self.admin_username = os.getenv("ADMIN_USERNAME", "admin")
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from src.services.system.maintenance_scheduler import (
|
|||||||
MaintenanceScheduler,
|
MaintenanceScheduler,
|
||||||
get_maintenance_scheduler,
|
get_maintenance_scheduler,
|
||||||
)
|
)
|
||||||
from src.services.system.scheduler import APP_TIMEZONE, TaskScheduler, get_scheduler
|
from src.services.system.scheduler import TaskScheduler, get_scheduler
|
||||||
from src.services.system.sync_stats import SyncStatsService
|
from src.services.system.sync_stats import SyncStatsService
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
@@ -23,5 +23,4 @@ __all__ = [
|
|||||||
"SyncStatsService",
|
"SyncStatsService",
|
||||||
"TaskScheduler",
|
"TaskScheduler",
|
||||||
"get_scheduler",
|
"get_scheduler",
|
||||||
"APP_TIMEZONE",
|
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import os
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Any, Callable
|
from typing import Any, Callable
|
||||||
|
|
||||||
@@ -17,10 +16,11 @@ from apscheduler.triggers.cron import CronTrigger
|
|||||||
from apscheduler.triggers.date import DateTrigger
|
from apscheduler.triggers.date import DateTrigger
|
||||||
from apscheduler.triggers.interval import IntervalTrigger
|
from apscheduler.triggers.interval import IntervalTrigger
|
||||||
|
|
||||||
|
from src.config import config
|
||||||
from src.core.logger import logger
|
from src.core.logger import logger
|
||||||
|
|
||||||
# 应用时区配置,默认为 Asia/Shanghai
|
# 统一从 config 读取,不再重复 os.getenv
|
||||||
APP_TIMEZONE = os.getenv("APP_TIMEZONE", "Asia/Shanghai")
|
APP_TIMEZONE = config.app_timezone
|
||||||
|
|
||||||
|
|
||||||
class TaskScheduler:
|
class TaskScheduler:
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import os
|
|
||||||
import uuid
|
import uuid
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from datetime import date, datetime, time, timedelta, timezone
|
from datetime import date, datetime, time, timedelta, timezone
|
||||||
@@ -16,6 +15,7 @@ from sqlalchemy import Date, Float, and_, case, cast, func, text
|
|||||||
from sqlalchemy.exc import IntegrityError
|
from sqlalchemy.exc import IntegrityError
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
from src.config import config
|
||||||
from src.core.logger import logger
|
from src.core.logger import logger
|
||||||
from src.models.database import (
|
from src.models.database import (
|
||||||
ApiKey,
|
ApiKey,
|
||||||
@@ -36,8 +36,7 @@ from src.models.database import (
|
|||||||
from src.models.database import User as DBUser
|
from src.models.database import User as DBUser
|
||||||
from src.services.system.time_range import TimeRangeParams, split_time_range_for_hourly
|
from src.services.system.time_range import TimeRangeParams, split_time_range_for_hourly
|
||||||
|
|
||||||
# App timezone (legacy defaults for dashboard)
|
APP_TIMEZONE = config.app_timezone
|
||||||
APP_TIMEZONE = os.getenv("APP_TIMEZONE", "Asia/Shanghai")
|
|
||||||
MIN_PERCENTILE_SAMPLES = 10
|
MIN_PERCENTILE_SAMPLES = 10
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,10 +8,12 @@ from zoneinfo import ZoneInfo
|
|||||||
from sqlalchemy import func
|
from sqlalchemy import func
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
from src.config import config
|
||||||
from src.core.logger import logger
|
from src.core.logger import logger
|
||||||
from src.models.database import Usage, WalletDailyUsageLedger
|
from src.models.database import Usage, WalletDailyUsageLedger
|
||||||
from src.services.billing.precision import to_money_decimal
|
from src.services.billing.precision import to_money_decimal
|
||||||
from src.services.system.scheduler import APP_TIMEZONE
|
|
||||||
|
APP_TIMEZONE = config.app_timezone
|
||||||
|
|
||||||
|
|
||||||
@dataclass(slots=True)
|
@dataclass(slots=True)
|
||||||
|
|||||||
Reference in New Issue
Block a user