feat: sync latest ARR implementation
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user