Files
wyndham-ARR/arr_web/services.py
2026-07-31 15:11:42 +08:00

70 lines
2.2 KiB
Python

"""Small active Web mutation ports for ARR2.0."""
from __future__ import annotations
import threading
from dataclasses import dataclass
from datetime import date
from typing import Any, Dict, Protocol
from arr_web.contracts import PortalError
from monthly_reports.service import MonthlyReportService, RunRequest
class UploadCoordinator(Protocol):
def submit(self, original_filename: str, payload: bytes) -> Dict[str, Any]:
...
class MonthlyCoordinator(Protocol):
def generate(self, month_key: str, as_of_date: date) -> Dict[str, Any]:
...
class UnavailableUploadCoordinator:
def submit(self, original_filename: str, payload: bytes) -> Dict[str, Any]:
raise PortalError(
"PROCESSING_GATEWAY_UNAVAILABLE",
"文件接收服务尚未完成生产接线",
503,
)
class UnavailableMonthlyCoordinator:
def generate(self, month_key: str, as_of_date: date) -> Dict[str, Any]:
raise PortalError(
"MONTHLY_GENERATOR_UNAVAILABLE",
"月报生成服务暂不可用",
503,
)
@dataclass
class ProgramMonthlyCoordinator:
"""Run the deterministic monthly database program."""
service: MonthlyReportService
def __post_init__(self) -> None:
self._lock = threading.Lock()
def generate(self, month_key: str, as_of_date: date) -> Dict[str, Any]:
year, month = (int(part) for part in month_key.split("-"))
request = RunRequest(year, month, as_of_date)
try:
request.validate()
except Exception:
raise PortalError("MONTHLY_REQUEST_INVALID", "月报日期范围无效") from None
if not self._lock.acquire(blocking=False):
raise PortalError("MONTHLY_ALREADY_RUNNING", "该服务正在生成月报", 409)
try:
result = self.service.run(request)
finally:
self._lock.release()
payload = result.to_dict()
if result.status != "success":
error = payload.get("errors", [{}])[0]
code = str(error.get("code") or "MONTHLY_GENERATION_FAILED")
raise PortalError(code, "月报生成未完成", 422)
return payload