feat: sync latest ARR implementation

This commit is contained in:
Wyndham ARR
2026-07-31 15:11:42 +08:00
parent d6f8a747fa
commit bf7939dd1a
185 changed files with 17527 additions and 2260 deletions

View File

@@ -193,6 +193,7 @@ def build_company_report(
errors: List[ReportProblem] = []
eligible: List[Tuple[FinanceFact, str]] = []
blank_booking_facts: List[FinanceFact] = []
for fact in facts:
generic_period = f"{year:04d}-{month:02d}"
if not isinstance(fact.arrival, date) or not isinstance(fact.departure, date):
@@ -237,6 +238,24 @@ def build_company_report(
continue
group_code = normalize_group_code(fact.res_comment)
stored_group = normalize_group_code(fact.group_code_key)
if not group_code and not stored_group:
if (
not str(fact.room_category_label or "").strip()
or _decimal_or_none(fact.total_price) is None
):
errors.append(
_problem(
ErrorCode.TOTAL_PRICE_INVALID,
"pricing",
company,
period_key,
"the static price detail is missing or invalid",
[fact],
)
)
continue
blank_booking_facts.append(fact)
continue
if not group_code or not stored_group:
errors.append(
_problem(
@@ -244,7 +263,7 @@ def build_company_report(
"group_lookup",
company,
period_key,
"the source record has no usable Group Code",
"the source Group Code fields are inconsistent",
[fact],
)
)
@@ -290,6 +309,24 @@ def build_company_report(
warnings: List[ReportProblem] = []
rows: List[ReportRow] = []
used_booking_versions: Dict[str, int] = {}
for fact in blank_booking_facts:
total_booking_price, multi_price = _price_text([fact])
rows.append(
ReportRow(
arrival=fact.arrival, # type: ignore[arg-type]
departure=fact.departure, # type: ignore[arg-type]
nights=fact.nights, # type: ignore[arg-type]
block_code=_distinct_join([fact.block_code]),
res_comment=unicodedata.normalize(
"NFKC", str(fact.res_comment or "")
).strip(),
booking_room="",
total_booking_price=total_booking_price,
normalized_group_code="",
record_ids=(fact.daily_record_id,),
multi_price_review=multi_price,
)
)
for (group_code, arrival, departure), segment_facts in sorted(
grouped_facts.items(), key=lambda item: (item[0][2], item[0][1], item[0][0])
):
@@ -307,39 +344,6 @@ def build_company_report(
)
)
continue
parse_version_id = snapshot.group_parse_versions.get(group_code)
if parse_version_id is None:
errors.append(
_problem(
ErrorCode.BOOKING_PARSE_FAILED,
"group_lookup",
company,
period_key,
"no accepted current booking parse exists for the Group Code",
segment_facts,
)
)
continue
room_items = items_by_segment.get((group_code, arrival, departure), [])
valid_room_items = [
item
for item in room_items
if item.quantity > 0
and bool(item.room_type_raw.strip())
and item.nights == (departure - arrival).days
]
if not valid_room_items:
errors.append(
_problem(
ErrorCode.ROOM_ITEMS_MISSING,
"group_lookup",
company,
period_key,
"the Group Code has no room items for this output stay segment",
segment_facts,
)
)
continue
try:
total_booking_price, multi_price = _price_text(segment_facts)
except ValueError:
@@ -365,7 +369,18 @@ def build_company_report(
segment_facts,
)
)
used_booking_versions[group_code] = parse_version_id
parse_version_id = snapshot.group_parse_versions.get(group_code)
valid_room_items: List[BookingRoomItem] = []
if parse_version_id is not None:
used_booking_versions[group_code] = parse_version_id
room_items = items_by_segment.get((group_code, arrival, departure), [])
valid_room_items = [
item
for item in room_items
if item.quantity > 0
and bool(item.room_type_raw.strip())
and item.nights == (departure - arrival).days
]
rows.append(
ReportRow(
arrival=arrival,
@@ -383,9 +398,17 @@ def build_company_report(
)
)
duplicate_counts = Counter(row.normalized_group_code for row in rows)
duplicate_counts = Counter(
row.normalized_group_code for row in rows if row.normalized_group_code
)
rows = [
replace(row, duplicate_group=duplicate_counts[row.normalized_group_code] > 1)
replace(
row,
duplicate_group=bool(
row.normalized_group_code
and duplicate_counts[row.normalized_group_code] > 1
),
)
for row in rows
]
@@ -398,13 +421,20 @@ def build_company_report(
period_rows = tuple(
sorted(
rows_by_period.get(period.key, []),
key=lambda row: (row.departure, row.arrival, row.normalized_group_code),
key=lambda row: (
row.departure,
row.arrival,
row.normalized_group_code,
row.record_ids,
),
)
)
populated_periods.append(replace(period, rows=period_rows if period.active else tuple()))
filename = f"{company}-{ENGLISH_MONTH_NAMES[month]}-{year}.xlsx"
used_daily_ids = {fact.daily_version_id for fact, _ in eligible}
used_daily_ids = {
fact.daily_version_id for fact, _ in eligible
} | {fact.daily_version_id for fact in blank_booking_facts}
daily_versions = tuple(
pin
for pin in sorted(snapshot.daily_versions, key=lambda current: current.business_date)