Files
wyndham-ARR/tests/company_reports_acceptance_fixture.py
2026-07-29 16:38:05 +08:00

307 lines
8.8 KiB
Python

"""Privacy-safe five-company acceptance facts for the downstream processor."""
from __future__ import annotations
from datetime import date
from decimal import Decimal
from typing import Dict, List
from company_reports.contracts import (
BatchSnapshot,
BookingRoomItem,
DailyVersionPin,
FinanceFact,
)
REPORT_YEAR = 2026
REPORT_MONTH = 7
AS_OF_DATE = date(2026, 7, 31)
def _fact(
record_id: int,
*,
business_date: date,
daily_version_id: int,
company_key: str,
channel_key: str,
group_code: str,
block_code: str,
arrival: date,
departure: date,
room_label: str,
total_price: str,
) -> FinanceFact:
return FinanceFact(
daily_record_id=record_id,
daily_version_id=daily_version_id,
business_date=business_date,
channel_key=channel_key,
company_key=company_key,
company_name=f"SYN-COMPANY-{company_key}",
block_code=block_code,
group_code_key=group_code,
res_comment=group_code,
room_category_label=room_label,
arrival=arrival,
departure=departure,
nights=(departure - arrival).days,
total_price=Decimal(total_price),
booking_source_match_status="matched",
)
def _room_item(
item_no: int,
*,
group_code: str,
parse_version_id: int,
segment_no: int,
arrival: date,
departure: date,
room_type: str,
quantity: int,
) -> BookingRoomItem:
return BookingRoomItem(
group_code_key=group_code,
parse_version_id=parse_version_id,
segment_no=segment_no,
arrival=arrival,
departure=departure,
nights=(departure - arrival).days,
item_no=item_no,
room_type_raw=room_type,
quantity=quantity,
)
def acceptance_snapshot() -> BatchSnapshot:
"""Return one synthetic month-end snapshot covering every accepted rule."""
facts: List[FinanceFact] = []
room_items: List[BookingRoomItem] = []
lt_arrival = date(2026, 7, 7)
lt_departure = date(2026, 7, 10)
for record_id, room_label, price, block_code in (
(101, "SYN-RM2", "900", "SYN-BLOCK-LT-A"),
(102, "SYN-RM2", "900", "SYN-BLOCK-LT-A"),
(103, "SYN-RM3", "3400", "SYN-BLOCK-LT-B"),
):
facts.append(
_fact(
record_id,
business_date=date(2026, 7, 8),
daily_version_id=1008,
company_key="LIAN TAI",
channel_key="SYN-CHANNEL-LT",
group_code="SYN-LT-0710",
block_code=block_code,
arrival=lt_arrival,
departure=lt_departure,
room_label=room_label,
total_price=price,
)
)
room_items.extend(
(
_room_item(
1,
group_code="SYN-LT-0710",
parse_version_id=7101,
segment_no=1,
arrival=lt_arrival,
departure=lt_departure,
room_type="SYN-SUP-TWN-BF",
quantity=2,
),
_room_item(
2,
group_code="SYN-LT-0710",
parse_version_id=7101,
segment_no=1,
arrival=lt_arrival,
departure=lt_departure,
room_type="SYN-SUP-TRP-BF",
quantity=1,
),
)
)
qbd_first_arrival = date(2026, 7, 7)
qbd_first_departure = date(2026, 7, 10)
for record_id, price in ((201, "900"), (202, "1800")):
facts.append(
_fact(
record_id,
business_date=date(2026, 7, 8),
daily_version_id=1008,
company_key="QBD",
channel_key="SYN-CHANNEL-QBD",
group_code="SYN-QBD-REPEAT",
block_code="SYN-BLOCK-QBD-A",
arrival=qbd_first_arrival,
departure=qbd_first_departure,
room_label="SYN-RM2",
total_price=price,
)
)
qbd_second_arrival = date(2026, 7, 17)
qbd_second_departure = date(2026, 7, 20)
for record_id in (203, 204, 205):
facts.append(
_fact(
record_id,
business_date=date(2026, 7, 18),
daily_version_id=1018,
company_key="QBD",
channel_key="SYN-CHANNEL-QBD",
group_code="SYN-QBD-REPEAT",
block_code="SYN-BLOCK-QBD-B",
arrival=qbd_second_arrival,
departure=qbd_second_departure,
room_label="SYN-RM2",
total_price="900",
)
)
room_items.extend(
(
_room_item(
1,
group_code="SYN-QBD-REPEAT",
parse_version_id=7201,
segment_no=1,
arrival=qbd_first_arrival,
departure=qbd_first_departure,
room_type="SYN-SUP-TWN-BF",
quantity=2,
),
_room_item(
1,
group_code="SYN-QBD-REPEAT",
parse_version_id=7201,
segment_no=2,
arrival=qbd_second_arrival,
departure=qbd_second_departure,
room_type="SYN-SUP-TWN-BF",
quantity=3,
),
)
)
dy_arrival = date(2026, 7, 18)
dy_departure = date(2026, 7, 20)
for record_id in (301, 302):
facts.append(
_fact(
record_id,
business_date=date(2026, 7, 18),
daily_version_id=1018,
company_key="SYN-UNMAPPED",
channel_key="DY-AI-EASY-KB",
group_code="SYN-DY-0720",
block_code="SYN-BLOCK-DY-A",
arrival=dy_arrival,
departure=dy_departure,
room_label="SYN-KB-RM",
total_price="800",
)
)
room_items.append(
_room_item(
1,
group_code="SYN-DY-0720",
parse_version_id=7301,
segment_no=1,
arrival=dy_arrival,
departure=dy_departure,
room_type="SYN-AI-EASY-TWN",
quantity=2,
)
)
fr_arrival = date(2026, 7, 27)
fr_departure = date(2026, 7, 31)
facts.append(
_fact(
401,
business_date=date(2026, 7, 28),
daily_version_id=1028,
company_key="FENGRUN",
channel_key="SYN-CHANNEL-FR",
group_code="SYN-FR-0731",
block_code="SYN-BLOCK-FR-A",
arrival=fr_arrival,
departure=fr_departure,
room_label="SYN-RM3",
total_price="3200",
)
)
room_items.append(
_room_item(
1,
group_code="SYN-FR-0731",
parse_version_id=7401,
segment_no=1,
arrival=fr_arrival,
departure=fr_departure,
room_type="SYN-SUP-TRP-BF",
quantity=1,
)
)
ht_arrival = date(2026, 7, 29)
ht_departure = date(2026, 7, 31)
for record_id in (501, 502):
facts.append(
_fact(
record_id,
business_date=date(2026, 7, 29),
daily_version_id=1029,
company_key="HANA TOUR",
channel_key="SYN-CHANNEL-HT",
group_code="SYN-HT-0731",
block_code="SYN-BLOCK-HT-A",
arrival=ht_arrival,
departure=ht_departure,
room_label="SYN-RM2",
total_price="1200",
)
)
room_items.append(
_room_item(
1,
group_code="SYN-HT-0731",
parse_version_id=7501,
segment_no=1,
arrival=ht_arrival,
departure=ht_departure,
room_type="SYN-SUP-TWN-BF",
quantity=2,
)
)
versions_by_date: Dict[date, int] = {}
for fact in facts:
existing = versions_by_date.get(fact.business_date)
if existing is not None and existing != fact.daily_version_id:
raise AssertionError("synthetic date has conflicting daily versions")
versions_by_date[fact.business_date] = fact.daily_version_id
return BatchSnapshot(
facts=tuple(facts),
room_items=tuple(room_items),
daily_versions=tuple(
DailyVersionPin(business_date, version_id)
for business_date, version_id in sorted(versions_by_date.items())
),
group_parse_versions={
"SYN-LT-0710": 7101,
"SYN-QBD-REPEAT": 7201,
"SYN-DY-0720": 7301,
"SYN-FR-0731": 7401,
"SYN-HT-0731": 7501,
},
)