feat: add date-based OHIP data reporting alongside XML
This commit is contained in:
1 parent
5ecd571e3b
commit
ad2c59256f
259 files changed
+37326
-126
No files matched your search
+43
-10
@@ -3,12 +3,16 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
from contextlib import ExitStack
|
||||
from pathlib import Path
|
||||
import signal
|
||||
import threading
|
||||
from typing import Any, Callable, Optional, Sequence
|
||||
|
||||
from arr_database import controlled_connect
|
||||
from arr_web.app import PortalApplication, RuntimeHealth
|
||||
from arr_web.auth import LoginCredentials
|
||||
from arr_web.arr_download_runtime import CapturedARRSource, DirectARRSource, compose_arr_downloads
|
||||
from arr_web.booking_uploads import ProgramBookingSourceCoordinator
|
||||
from arr_web.company_jobs import (
|
||||
PersistentCompanyReportCoordinator,
|
||||
@@ -83,15 +87,38 @@ def _parser() -> argparse.ArgumentParser:
|
||||
action="store_true",
|
||||
help="mark browser session cookies Secure for an HTTPS deployment",
|
||||
)
|
||||
parser.add_argument("--ohip-hotel-id", help="Hotel used by the direct ARR data entry")
|
||||
parser.add_argument("--ohip-credential-file", type=Path, help="Private OHIP credential file, read only on download")
|
||||
parser.add_argument("--ohip-state-root", type=Path, help="Private persistent OHIP task directory outside the repository")
|
||||
return parser
|
||||
|
||||
|
||||
def main(argv: Optional[Sequence[str]] = None) -> int:
|
||||
def main(argv: Optional[Sequence[str]] = None, *, arr_source: CapturedARRSource | DirectARRSource | None = None) -> int:
|
||||
args = _parser().parse_args(argv)
|
||||
direct_values = (args.ohip_hotel_id, args.ohip_credential_file, args.ohip_state_root)
|
||||
if any(value is not None for value in direct_values):
|
||||
if arr_source is not None or not all(value is not None for value in direct_values):
|
||||
raise SystemExit("Provide all three OHIP options without an injected source")
|
||||
arr_source = DirectARRSource(args.ohip_state_root, args.ohip_hotel_id, args.ohip_credential_file)
|
||||
if arr_source is not None and not args.enable_processing:
|
||||
raise SystemExit("ARR downloads require --enable-processing")
|
||||
try:
|
||||
login_credentials = LoginCredentials.from_environment()
|
||||
except ValueError as error:
|
||||
raise SystemExit(str(error)) from None
|
||||
with ExitStack() as resources:
|
||||
if arr_source is not None and threading.current_thread() is threading.main_thread():
|
||||
previous = signal.signal(signal.SIGTERM, _terminate)
|
||||
resources.callback(signal.signal, signal.SIGTERM, previous)
|
||||
return _run(args, login_credentials, resources, arr_source=arr_source)
|
||||
|
||||
|
||||
def _terminate(signum, _frame):
|
||||
# Let ExitStack drain the active ARR task before shared clients close.
|
||||
raise SystemExit(128 + signum)
|
||||
|
||||
|
||||
def _run(args, login_credentials, resources: ExitStack, *, arr_source: CapturedARRSource | DirectARRSource | None) -> int:
|
||||
connect: Optional[Callable[[str], Any]] = None
|
||||
try:
|
||||
if args.db_config:
|
||||
@@ -116,6 +143,7 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
|
||||
project_root=PROJECT_ROOT,
|
||||
connect=connect,
|
||||
)
|
||||
resources.callback(processing_input.close)
|
||||
processing_ready = True
|
||||
except Exception:
|
||||
processing_input = None
|
||||
@@ -130,6 +158,7 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
|
||||
):
|
||||
try:
|
||||
report_storage_runtime = compose_object_store()
|
||||
resources.callback(report_storage_runtime.close)
|
||||
report_object_store = report_storage_runtime.object_store
|
||||
except Exception:
|
||||
report_storage_runtime = None
|
||||
@@ -191,6 +220,7 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
|
||||
ProgramCompanyReportExecutor(company_service),
|
||||
object_store=report_object_store,
|
||||
)
|
||||
resources.callback(company_reports.close)
|
||||
company_reports_ready = True
|
||||
except Exception:
|
||||
company_reports = None
|
||||
@@ -215,8 +245,19 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
|
||||
except Exception:
|
||||
booking_sources = None
|
||||
company_source_upload_ready = False
|
||||
arr_downloads = None
|
||||
if arr_source is not None:
|
||||
if processing_input is None:
|
||||
raise SystemExit("ARR download processing dependencies are unavailable")
|
||||
try:
|
||||
arr_downloads = compose_arr_downloads(arr_source, processing_input)
|
||||
except Exception:
|
||||
raise SystemExit("ARR download source initialization failed") from None
|
||||
# Last registered, first closed: a running delivery still needs OSS/SQL.
|
||||
resources.callback(arr_downloads.close, wait=True)
|
||||
application = PortalApplication(
|
||||
repository=repository,
|
||||
arr_downloads=arr_downloads,
|
||||
upload=(
|
||||
processing_input.coordinator if processing_input is not None else None
|
||||
),
|
||||
@@ -254,15 +295,7 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
|
||||
credentials=login_credentials,
|
||||
secure_cookies=args.secure_cookies,
|
||||
)
|
||||
try:
|
||||
serve(application, args.host, args.port)
|
||||
finally:
|
||||
if company_reports is not None:
|
||||
company_reports.close()
|
||||
if processing_input is not None:
|
||||
processing_input.close()
|
||||
if report_storage_runtime is not None:
|
||||
report_storage_runtime.close()
|
||||
serve(application, args.host, args.port)
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user