41 lines
2.0 KiB
Python
41 lines
2.0 KiB
Python
"""Serialize explicit ordered rows to the existing ARR processor XML format.
|
|
|
|
No API selection, report semantics, filtering, deduplication or pricing occurs
|
|
here. Output is a processing projection, not a native Opera report replica.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import xml.etree.ElementTree as ET
|
|
|
|
from .arr_xml_contract import MAX_BYTES, SCALARS, SourceDocument, validate_document
|
|
from .collect_arr_source import require
|
|
|
|
|
|
def serialize(document: SourceDocument) -> bytes:
|
|
validate_document(document)
|
|
root = ET.Element("RES_DETAIL")
|
|
groups = ET.SubElement(root, "LIST_G_GROUP_BY1")
|
|
group = ET.SubElement(groups, "G_GROUP_BY1")
|
|
day = document.report_date
|
|
ET.SubElement(group, "GROUPBY1_SORT_COL").text = f"{day.year:04d}{day.month:02d}{day.day:02d}"
|
|
# Use the full-year ISO representation accepted by the existing processor.
|
|
# A two-digit display year can silently map historical dates to another century.
|
|
ET.SubElement(group, "GROUPBY1_COL").text = document.report_date.isoformat()
|
|
rows = ET.SubElement(group, "LIST_G_RESERVATION")
|
|
for row in document.rows:
|
|
node = ET.SubElement(rows, "G_RESERVATION")
|
|
ET.SubElement(node, "RESORT").text = document.hotel_id
|
|
ET.SubElement(node, "RESV_NAME_ID").text = row.reservation_id
|
|
for attribute, tag in SCALARS:
|
|
ET.SubElement(node, tag).text = getattr(row, attribute)
|
|
comments = ET.SubElement(node, "LIST_G_COMMENT_RESV_NAME_ID")
|
|
for text in row.notes:
|
|
ET.SubElement(ET.SubElement(comments, "G_COMMENT_RESV_NAME_ID"), "RES_COMMENT").text = text
|
|
traces = ET.SubElement(node, "LIST_G_DEPT_ID")
|
|
for text in row.traces:
|
|
ET.SubElement(ET.SubElement(traces, "G_DEPT_ID"), "TRACE_TEXT").text = text
|
|
# XML parsers normalize literal CR; character references preserve it exactly.
|
|
raw = ET.tostring(root, encoding="utf-8", xml_declaration=True).replace(b"\r", b" ") + b"\n"
|
|
require(len(raw) <= MAX_BYTES, "arr_xml_output_budget_exceeded")
|
|
return raw
|