Exclude PM room types from shared daily report processing
This commit is contained in:
1 parent
d3902dd857
commit
f46efd6d9a
32 files changed
+968
-69
No files matched your search
@@ -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(":")
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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…", "กำลังบันทึกและยืนยันข้อมูล…"],
|
||||
|
||||
Reference in new issue
Block a user