Exclude PM room types from shared daily report processing

This commit is contained in:
Wyndham ARR committed 2026-10-08 22:30:04 +08:00
1 parent d3902dd857
commit f46efd6d9a
32 files changed
+968 -69

No files matched your search

+25 -8
View File
@@ -277,16 +277,19 @@ class DataFieldReviews:
data["status"] = "collected_with_gaps" if unresolved else "collected"
return data
def _issues(self, directory, data):
def _normalized(self, directory, data):
# Use the exact frozen processor's normalizer and field validation; the
# acquisition layer never maintains a second whitelist or numeric rule.
with tempfile.NamedTemporaryFile(suffix=".json", dir=directory) as stream:
stream.write(json_bytes(data))
stream.flush()
business_date, records = self.rules.read_data_source(Path(stream.name))
return self.rules.read_data_source(Path(stream.name))
def _issues(self, directory, data):
business_date, records = self._normalized(directory, data)
issues = {}
for row, record in zip(data["records"], records):
if self.rules.is_cancelled_record(record):
if self.rules.is_cancelled_record(record) or self.rules.is_pm_record(record):
continue
rate = record["_NORMALIZED_RATE_CODE"]
fields = {}
@@ -312,13 +315,24 @@ class DataFieldReviews:
value = observation.get("value")
return value if observation.get("state") == "available" and isinstance(value, (str, int)) else ""
def _excluded_sequences(self, directory, data):
cancelled, pm = set(), set()
_date, records = self._normalized(directory, data)
for row, record in zip(data["records"], records):
sequence = row["source_sequence"]
if self.rules.is_cancelled_record(record):
cancelled.add(sequence)
elif self.rules.is_pm_record(record):
pm.add(sequence)
return cancelled, pm
def _public(self, directory, meta, original, state):
data = self._derive(directory, original, state)
issues = self._issues(directory, data)
cancelled_sequences = {row["source_sequence"] for row in data["records"]
if self.rules.is_cancelled_record({"_RESERVATION_STATUS": row.get("reservation_status", "")})}
cancelled_sequences, pm_sequences = self._excluded_sequences(directory, data)
keys = set(issues) | {key for key in state["decisions"]
if int(key.split(":")[0]) not in cancelled_sequences}
if int(key.split(":")[0]) not in cancelled_sequences
and (int(key.split(":")[0]) not in pm_sequences or key.endswith(":ROOM_CATEGORY_LABEL"))}
items = []
for item_id in sorted(keys, key=lambda key: (int(key.split(":")[0]), key.split(":")[1])):
sequence, field = item_id.split(":")
@@ -335,6 +349,7 @@ class DataFieldReviews:
"revision": state["revision"], "status": state["status"], "items": items,
"pending_count": len(issues), "total_count": len(items),
"excluded_cancelled_count": len(cancelled_sequences),
"excluded_pm_count": len(pm_sequences),
"can_finalize": not issues and state["status"] == "editing"}
def prepare(self, request_id, payload, manifest_sha256, report_date):
@@ -523,9 +538,11 @@ class DataFieldReviews:
actor = self._actor(actor)
data = self._derive(directory, original, state)
sequence = int(item_id.split(":")[0]) if isinstance(item_id, str) and re.fullmatch(r"[1-9][0-9]*:[A-Z_]+", item_id) else 0
if 1 <= sequence <= len(data["records"]) and self.rules.is_cancelled_record(
{"_RESERVATION_STATUS": data["records"][sequence - 1].get("reservation_status", "")}):
cancelled_sequences, pm_sequences = self._excluded_sequences(directory, data)
if sequence in cancelled_sequences:
raise _error(message="已取消预订不参与日报,无需完善字段")
if sequence in pm_sequences and not (item_id.endswith(":ROOM_CATEGORY_LABEL") and item_id in state["decisions"]):
raise _error(message="PM 房型不参与日报,无需完善字段")
if item_id not in self._issues(directory, data) and item_id not in state["decisions"]:
raise _error(message="只能完善当前任务列出的异常字段")
sequence, field = item_id.split(":")
+1 -1
View File
@@ -215,7 +215,7 @@ def open_portal(root, port):
load_key(credential_file)
access = AccessState(root)
with job_lock(root):
database = ReplayDatabase(root, schema_version=20)
database = ReplayDatabase(root, schema_version=21)
try:
database.start()
def factory(*, root, snapshot, **dependencies):
+2 -2
View File
@@ -14,8 +14,8 @@ from integrations.ohip.capture_job import atomic_json, private_directory
class ReplayDatabase:
def __init__(self, root: Path, *, schema_version: int = 20):
if schema_version not in (18, 19, 20):
def __init__(self, root: Path, *, schema_version: int = 21):
if schema_version not in (18, 19, 20, 21):
raise ValueError("unsupported_local_schema")
self.schema_version = schema_version
self.root = root
+1
View File
@@ -80,6 +80,7 @@ def compose_programmatic_processing(
connect=connect,
)
repository.assert_cancelled_scope_schema()
repository.assert_pm_scope_schema()
policy = load_processor_policy(project_root)
ingestion = IngestionService(DeliveryValidator(object_store, policy), repository)
processor = LocalDailyProcessor(policy)
+3
View File
@@ -698,6 +698,9 @@
if (Number.isInteger(review?.excluded_cancelled_count) && review.excluded_cancelled_count > 0) {
$("#arr-data-review-progress").textContent += ` · ${I18N.t("data_review.excluded_cancelled", { count: review.excluded_cancelled_count })}`;
}
if (Number.isInteger(review?.excluded_pm_count) && review.excluded_pm_count > 0) {
$("#arr-data-review-progress").textContent += ` · ${I18N.t("data_review.excluded_pm", { count: review.excluded_pm_count })}`;
}
$("#arr-data-review-refresh").textContent = I18N.t("data_review.refresh");
$("#arr-data-review-refresh").disabled = busy;
const finalize = $("#arr-data-review-finalize");
+1
View File
@@ -172,6 +172,7 @@
"data_review.loading": ["正在读取待完善字段…", "Loading fields for review…", "กำลังโหลดข้อมูลที่ต้องตรวจสอบ…"],
"data_review.no_items": ["没有待完善字段。", "No fields need review.", "ไม่มีข้อมูลที่ต้องตรวจสอบ"],
"data_review.excluded_cancelled": ["已排除 {count} 笔取消预订,原始数据保留", "{count} cancelled reservations excluded; original data retained", "ไม่รวมการจองที่ยกเลิก {count} รายการ โดยเก็บข้อมูลต้นฉบับไว้"],
"data_review.excluded_pm": ["已排除 {count} 笔 PM 预订,原始数据保留", "{count} PM reservations excluded; original data retained", "ไม่รวมการจองประเภทห้อง PM {count} รายการ โดยเก็บข้อมูลต้นฉบับไว้"],
"data_review.region": ["待完善报表字段", "Report fields to review", "ข้อมูลรายงานที่ต้องตรวจสอบ"],
"data_review.disconnected": ["字段读取中断,请刷新字段后继续。", "Field connection lost. Refresh the fields to continue.", "การเชื่อมต่อข้อมูลขัดข้อง โปรดรีเฟรชข้อมูลเพื่อดำเนินการต่อ"],
"data_review.saving": ["正在保存并确认字段…", "Saving and confirming field…", "กำลังบันทึกและยืนยันข้อมูล…"],