# -*- coding: utf-8 -*- """小程序业务时钟路由。 仅用于小程序读取当前门店的"业务日 / 业务年月 / 模式"——sandbox 模式下, 小程序的 performance / task-list / customer-records 等页面应以 RuntimeContext 返回的业务时钟为准,禁止再用 ``new Date()`` 构造请求参数。 端点: - GET /api/xcx/runtime/clock — 返回当前门店的业务时钟与运行模式(live / sandbox)。 所有端点均需 JWT(approved 状态),但不要求特定模块权限。 """ from __future__ import annotations from fastapi import APIRouter, Depends from app.auth.dependencies import CurrentUser from app.middleware.permission import require_approved from app.services.runtime_context import get_runtime_context from app.trace.decorators import trace_service router = APIRouter(prefix="/api/xcx/runtime", tags=["小程序业务时钟"]) @router.get("/clock") @trace_service("获取业务时钟", "Get business clock") async def get_business_clock( user: CurrentUser = Depends(require_approved), ): """返回当前门店的业务时钟。 返回示例(live):: { "mode": "live", "business_date": "2026-05-02", "business_year": 2026, "business_month": 5, "business_year_month": "2026-05", "is_sandbox": false, "sandbox_date": null } sandbox 模式下 ``business_date`` 等于配置的 ``sandbox_date``。 小程序页面应使用本接口结果替代 ``new Date()``,以确保 sandbox 模式下 展示和请求都对齐到 sandbox_date。 """ ctx = get_runtime_context(user.site_id) bd = ctx.business_date return { "mode": ctx.mode, "business_date": bd.isoformat(), "business_year": bd.year, "business_month": bd.month, "business_year_month": f"{bd.year:04d}-{bd.month:02d}", "business_now": ctx.business_now.isoformat(), "is_sandbox": ctx.is_sandbox, "sandbox_date": ctx.sandbox_date.isoformat() if ctx.sandbox_date else None, "sandbox_instance_id": ctx.sandbox_instance_id, }