247 lines
9.0 KiB
Python
247 lines
9.0 KiB
Python
"""Local entry point. Production injects private OSS and processing adapters."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
from pathlib import Path
|
|
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.booking_uploads import ProgramBookingSourceCoordinator
|
|
from arr_web.company_jobs import (
|
|
PersistentCompanyReportCoordinator,
|
|
ProgramCompanyReportExecutor,
|
|
)
|
|
from arr_web.downloads import (
|
|
ControlledProjectArtifactReader,
|
|
ManagedObjectArtifactReader,
|
|
RoutedArtifactReader,
|
|
)
|
|
from arr_web.repository import PostgresPortalRepository, UnavailablePortalRepository
|
|
from arr_web.processing_runtime import (
|
|
ProcessingInputRuntime,
|
|
compose_programmatic_processing,
|
|
)
|
|
from arr_web.server import serve
|
|
from arr_web.services import ProgramMonthlyCoordinator
|
|
from monthly_reports.publishing import ArtifactToolBuilder, AtomicReportPublisher
|
|
from monthly_reports.repository import DatabaseConfig, PostgresReportRepository
|
|
from monthly_reports.service import MonthlyReportService
|
|
from company_reports.publishing import (
|
|
ArtifactToolBuilder as CompanyArtifactToolBuilder,
|
|
AtomicReportPublisher as AtomicCompanyReportPublisher,
|
|
)
|
|
from company_reports.repository import (
|
|
DatabaseConfig as CompanyDatabaseConfig,
|
|
PostgresReportRepository as PostgresCompanyReportRepository,
|
|
)
|
|
from company_reports.service import CompanyReportService
|
|
from booking_ingestion.excel_postgres import (
|
|
DatabaseConfig as BookingExcelDatabaseConfig,
|
|
)
|
|
from booking_ingestion.excel_review_postgres import PostgresBookingReviewRepository
|
|
|
|
|
|
PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
|
|
|
|
|
def _parser() -> argparse.ArgumentParser:
|
|
parser = argparse.ArgumentParser(prog="arr-web")
|
|
parser.add_argument("--host", default="127.0.0.1")
|
|
parser.add_argument("--port", type=int, default=8765)
|
|
parser.add_argument(
|
|
"--db-config",
|
|
type=Path,
|
|
help="local controlled ARR_DB_* env file; values are never logged",
|
|
)
|
|
parser.add_argument(
|
|
"--driver-path",
|
|
type=Path,
|
|
help="optional local directory containing the PostgreSQL driver",
|
|
)
|
|
parser.add_argument(
|
|
"--enable-monthly-generation",
|
|
action="store_true",
|
|
help="enable the database monthly-report mutation endpoint",
|
|
)
|
|
parser.add_argument(
|
|
"--enable-company-reports",
|
|
action="store_true",
|
|
help="enable Bangkok-gated five-company channel-detail jobs",
|
|
)
|
|
parser.add_argument(
|
|
"--enable-processing",
|
|
action="store_true",
|
|
help="enable ARR-owned deterministic XML processing and ingestion",
|
|
)
|
|
parser.add_argument(
|
|
"--secure-cookies",
|
|
action="store_true",
|
|
help="mark browser session cookies Secure for an HTTPS deployment",
|
|
)
|
|
parser.add_argument("--node-binary", type=Path)
|
|
parser.add_argument("--artifact-tool-module", type=Path)
|
|
return parser
|
|
|
|
|
|
def main(argv: Optional[Sequence[str]] = None) -> int:
|
|
args = _parser().parse_args(argv)
|
|
try:
|
|
login_credentials = LoginCredentials.from_environment()
|
|
except ValueError as error:
|
|
raise SystemExit(str(error)) from None
|
|
connect: Optional[Callable[[str], Any]] = None
|
|
try:
|
|
if args.db_config:
|
|
connect = controlled_connect(args.db_config, args.driver_path)
|
|
repository = PostgresPortalRepository(
|
|
"controlled",
|
|
connect=connect,
|
|
)
|
|
else:
|
|
repository = PostgresPortalRepository.from_environment()
|
|
repository.list_months()
|
|
database_ready = True
|
|
except Exception:
|
|
repository = UnavailablePortalRepository()
|
|
database_ready = False
|
|
|
|
monthly = None
|
|
monthly_ready = False
|
|
if args.enable_monthly_generation and database_ready:
|
|
try:
|
|
report_repository = PostgresReportRepository(
|
|
DatabaseConfig("controlled"),
|
|
connect=connect,
|
|
) if connect is not None else PostgresReportRepository(DatabaseConfig.from_environment())
|
|
builder = ArtifactToolBuilder(
|
|
PROJECT_ROOT / "monthly_reports" / "xlsx" / "build_workbook.mjs",
|
|
node_binary=str(args.node_binary) if args.node_binary else None,
|
|
artifact_tool_module=args.artifact_tool_module,
|
|
)
|
|
output_root = PROJECT_ROOT / "outputs" / "monthly_reports"
|
|
monthly = ProgramMonthlyCoordinator(
|
|
MonthlyReportService(
|
|
report_repository,
|
|
builder,
|
|
AtomicReportPublisher(PROJECT_ROOT, output_root),
|
|
output_root / ".staging",
|
|
)
|
|
)
|
|
monthly_ready = True
|
|
except Exception:
|
|
monthly = None
|
|
monthly_ready = False
|
|
company_reports = None
|
|
company_reports_ready = False
|
|
if args.enable_company_reports and database_ready:
|
|
try:
|
|
company_repository = (
|
|
PostgresCompanyReportRepository(
|
|
CompanyDatabaseConfig("controlled"),
|
|
connect=connect,
|
|
)
|
|
if connect is not None
|
|
else PostgresCompanyReportRepository(
|
|
CompanyDatabaseConfig.from_environment()
|
|
)
|
|
)
|
|
company_builder = CompanyArtifactToolBuilder(
|
|
PROJECT_ROOT / "company_reports" / "xlsx" / "build_workbook.mjs",
|
|
node_binary=str(args.node_binary) if args.node_binary else None,
|
|
artifact_tool_module=args.artifact_tool_module,
|
|
)
|
|
company_output_root = PROJECT_ROOT / "outputs" / "company_reports"
|
|
company_service = CompanyReportService(
|
|
company_repository,
|
|
company_builder,
|
|
AtomicCompanyReportPublisher(PROJECT_ROOT, company_output_root),
|
|
company_output_root / ".staging",
|
|
)
|
|
company_reports = PersistentCompanyReportCoordinator(
|
|
PROJECT_ROOT,
|
|
company_output_root,
|
|
ProgramCompanyReportExecutor(company_service),
|
|
)
|
|
company_reports_ready = True
|
|
except Exception:
|
|
company_reports = None
|
|
company_reports_ready = False
|
|
processing_input: Optional[ProcessingInputRuntime] = None
|
|
processing_ready = False
|
|
if args.enable_processing and database_ready:
|
|
try:
|
|
processing_input = compose_programmatic_processing(
|
|
project_root=PROJECT_ROOT,
|
|
connect=connect,
|
|
)
|
|
processing_ready = True
|
|
except Exception:
|
|
processing_input = None
|
|
processing_ready = False
|
|
booking_sources = None
|
|
company_source_upload_ready = False
|
|
if args.enable_company_reports and database_ready and processing_input is not None:
|
|
try:
|
|
booking_repository = PostgresBookingReviewRepository(
|
|
BookingExcelDatabaseConfig("controlled"),
|
|
connect=connect,
|
|
) if connect is not None else PostgresBookingReviewRepository(
|
|
BookingExcelDatabaseConfig.from_environment()
|
|
)
|
|
booking_sources = ProgramBookingSourceCoordinator(
|
|
processing_input.object_store,
|
|
booking_repository,
|
|
)
|
|
booking_sources.current()
|
|
booking_sources.draft()
|
|
company_source_upload_ready = True
|
|
except Exception:
|
|
booking_sources = None
|
|
company_source_upload_ready = False
|
|
application = PortalApplication(
|
|
repository=repository,
|
|
upload=(
|
|
processing_input.coordinator if processing_input is not None else None
|
|
),
|
|
monthly=monthly,
|
|
company_reports=company_reports,
|
|
booking_sources=booking_sources,
|
|
artifact_reader=(
|
|
RoutedArtifactReader(
|
|
daily_reader=(
|
|
ManagedObjectArtifactReader(processing_input.object_store)
|
|
if processing_input is not None
|
|
else None
|
|
),
|
|
local_reader=ControlledProjectArtifactReader(PROJECT_ROOT),
|
|
)
|
|
if database_ready
|
|
else None
|
|
),
|
|
health=RuntimeHealth(
|
|
database_ready=database_ready,
|
|
upload_ready=processing_ready,
|
|
monthly_ready=monthly_ready,
|
|
download_ready=database_ready,
|
|
company_reports_ready=company_reports_ready,
|
|
company_source_upload_ready=company_source_upload_ready,
|
|
),
|
|
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()
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|