feat: prepare ARR for controlled public deployment

This commit is contained in:
Wyndham ARR
2026-07-29 16:38:05 +08:00
commit a701de9f0e
271 changed files with 48472 additions and 0 deletions

View File

@@ -0,0 +1,147 @@
from __future__ import annotations
import unittest
from datetime import date
from decimal import Decimal
from monthly_reports.contracts import (
KB_HEADER,
ChannelObservation,
DailyVersionPin,
ErrorCode,
MonthlyFact,
MonthlyReportError,
MonthlySnapshot,
STANDARD_SHEETS,
)
from monthly_reports.core import build_monthly_report
def fact(
record_id: int,
*,
business_date: date = date(2026, 7, 2),
daily_version_id: int = 102,
channel: str = "QBD",
rooms: int = 1,
nights: int = 2,
real_price: Decimal = Decimal("450.00"),
) -> MonthlyFact:
return MonthlyFact(
daily_record_id=record_id,
daily_version_id=daily_version_id,
business_date=business_date,
channel_key=channel,
arrival=business_date,
departure=date.fromordinal(business_date.toordinal() + nights),
nights=nights,
adults=2,
children=0,
block_code="SYN-BLOCK",
no_of_rooms=rooms,
company_name="SYN-COMPANY",
confirmation_no=f"SYN-{record_id}",
disp_room_no=f"SYN-RM-{record_id}",
effective_rate_amount=real_price,
full_name="SYN-GUEST",
res_comment="SYN-COMMENT",
trace_text="",
products="",
rate_code="SYN-RATE",
room_category_label="SYN-TYPE",
real_price=real_price,
total_price=real_price * rooms * nights,
kb_amount=Decimal(rooms * 100) if channel == "DY-AI-Easy-KB" else None,
)
def snapshot(*facts: MonthlyFact, preferred: tuple[str, ...] = ()) -> MonthlySnapshot:
pins = tuple(
DailyVersionPin(day, version)
for day, version in sorted(
{item.business_date: item.daily_version_id for item in facts}.items()
)
)
counts: dict[tuple[date, int, str], int] = {}
for item in facts:
key = (item.business_date, item.daily_version_id, item.channel_key)
counts[key] = counts.get(key, 0) + 1
observations = tuple(
ChannelObservation(day, version, channel, None, count)
for (day, version, channel), count in sorted(counts.items())
)
return MonthlySnapshot(tuple(facts), pins, observations, preferred)
class MonthlyReportsCoreTests(unittest.TestCase):
def test_standard_sheets_are_retained_and_unknown_order_is_stable(self):
report = build_monthly_report(
2026,
7,
date(2026, 7, 26),
snapshot(
fact(2, channel="T- HANATOUR TD CO., L"),
fact(1),
preferred=("T- HANATOUR TD CO., L",),
),
)
self.assertEqual(
tuple(channel.worksheet for channel in report.channels),
STANDARD_SHEETS + ("T- HANATOUR TD CO., L",),
)
self.assertEqual(report.row_count, 2)
self.assertEqual(report.channel_manifest[-1], ("T- HANATOUR TD CO., L", 6, 1))
self.assertEqual(report.filename, "各渠道情况-2026年07月-更新至7.26.xlsx")
def test_kb_payload_has_extra_typed_amount(self):
report = build_monthly_report(
2026,
7,
date(2026, 7, 26),
snapshot(fact(1, channel="DY-AI-Easy-KB", rooms=2)),
)
payload = report.to_workbook_payload()
kb = next(item for item in payload["channels"] if item["worksheet"] == "DY-AI-Easy-KB")
self.assertEqual(kb["headers"][-1], KB_HEADER)
self.assertEqual(kb["rows"][0][KB_HEADER], "200")
self.assertEqual(kb["rows"][0]["TOTAL PRICE"], "1800")
def test_empty_current_day_is_pinned(self):
report = build_monthly_report(
2026,
7,
date(2026, 7, 26),
MonthlySnapshot(
facts=(),
daily_versions=(DailyVersionPin(date(2026, 7, 26), 126),),
channel_observations=(),
),
)
self.assertEqual(report.row_count, 0)
self.assertEqual(report.daily_versions[0].daily_version_id, 126)
def test_mismatched_metric_or_pin_is_rejected(self):
source = fact(1)
cases = (
MonthlySnapshot(
(source,),
(DailyVersionPin(source.business_date, 999),),
(ChannelObservation(source.business_date, 999, "QBD", 1, 1),),
),
MonthlySnapshot(
(source,),
(DailyVersionPin(source.business_date, source.daily_version_id),),
(ChannelObservation(source.business_date, source.daily_version_id, "QBD", 1, 2),),
),
)
for current in cases:
with self.subTest(current=current):
with self.assertRaises(MonthlyReportError) as caught:
build_monthly_report(2026, 7, date(2026, 7, 26), current)
self.assertEqual(caught.exception.code, ErrorCode.SOURCE_INVALID)
if __name__ == "__main__":
unittest.main()