110 lines
2.9 KiB
Python
110 lines
2.9 KiB
Python
"""Shared product-status rules for the collection, generation, and apply flows."""
|
||||
|
|
|
|||
|
|
from __future__ import annotations
|
|||
|
|
|
|||
|
|
import re
|
|||
|
|
|
|||
|
|
|
|||
|
|
STATUS_NORMAL = "normal"
|
|||
|
|
STATUS_UNLISTED = "unlisted"
|
|||
|
|
STATUS_REVIEWING = "reviewing"
|
|||
|
|
STATUS_UNKNOWN = "unknown"
|
|||
|
|
|
|||
|
|
VALID_PRODUCT_STATUSES = frozenset(
|
|||
|
|
{
|
|||
|
|
STATUS_NORMAL,
|
|||
|
|
STATUS_UNLISTED,
|
|||
|
|
STATUS_REVIEWING,
|
|||
|
|
STATUS_UNKNOWN,
|
|||
|
|
}
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
PRODUCT_STATUS_LABELS = {
|
|||
|
|
STATUS_NORMAL: "正常",
|
|||
|
|
STATUS_UNLISTED: "未上架",
|
|||
|
|
STATUS_REVIEWING: "审核中",
|
|||
|
|
STATUS_UNKNOWN: "状态未知",
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_WHITESPACE_RE = re.compile(r"\s+")
|
|||
|
|
_NOTE_LIMIT = 2000
|
|||
|
|
|
|||
|
|
|
|||
|
|
def normalize_status(value) -> str:
|
|||
|
|
"""Return a stable status code; legacy and invalid values are unknown."""
|
|||
|
|
|
|||
|
|
normalized = str(value or "").strip().lower()
|
|||
|
|
if normalized in VALID_PRODUCT_STATUSES:
|
|||
|
|
return normalized
|
|||
|
|
return STATUS_UNKNOWN
|
|||
|
|
|
|||
|
|
|
|||
|
|
def status_label(value) -> str:
|
|||
|
|
return PRODUCT_STATUS_LABELS[normalize_status(value)]
|
|||
|
|
|
|||
|
|
|
|||
|
|
def is_normal(value) -> bool:
|
|||
|
|
return normalize_status(value) == STATUS_NORMAL
|
|||
|
|
|
|||
|
|
|
|||
|
|
def is_known_abnormal(value) -> bool:
|
|||
|
|
return normalize_status(value) in {STATUS_UNLISTED, STATUS_REVIEWING}
|
|||
|
|
|
|||
|
|
|
|||
|
|
def normalize_text(value) -> str:
|
|||
|
|
return _WHITESPACE_RE.sub(" ", str(value or "").strip())
|
|||
|
|
|
|||
|
|
|
|||
|
|
def classify_alerts(alerts) -> dict:
|
|||
|
|
"""Classify normalized EDS warning-alert data without retaining page HTML."""
|
|||
|
|
|
|||
|
|
if not isinstance(alerts, list):
|
|||
|
|
return _snapshot(STATUS_UNKNOWN, "")
|
|||
|
|
if not alerts:
|
|||
|
|
return _snapshot(STATUS_NORMAL, "")
|
|||
|
|
|
|||
|
|
first_note = ""
|
|||
|
|
valid_alert_seen = False
|
|||
|
|
for alert in alerts:
|
|||
|
|
if not isinstance(alert, dict):
|
|||
|
|
continue
|
|||
|
|
valid_alert_seen = True
|
|||
|
|
title = normalize_text(alert.get("title"))
|
|||
|
|
description = normalize_text(alert.get("description"))
|
|||
|
|
note = _alert_note(title, description)
|
|||
|
|
if not first_note:
|
|||
|
|
first_note = note
|
|||
|
|
if title in {"審核中", "审核中"}:
|
|||
|
|
return _snapshot(STATUS_REVIEWING, note)
|
|||
|
|
if "您的商品未上架" in title:
|
|||
|
|
return _snapshot(STATUS_UNLISTED, note)
|
|||
|
|
|
|||
|
|
if not valid_alert_seen:
|
|||
|
|
return _snapshot(STATUS_UNKNOWN, "")
|
|||
|
|
return _snapshot(STATUS_UNKNOWN, first_note)
|
|||
|
|
|
|||
|
|
|
|||
|
|
def partition_tasks(tasks) -> dict:
|
|||
|
|
"""Return tasks grouped by normalized status for callers' run planners."""
|
|||
|
|
|
|||
|
|
grouped = {status: [] for status in VALID_PRODUCT_STATUSES}
|
|||
|
|
for task in tasks:
|
|||
|
|
grouped[normalize_status(getattr(task, "product_status", None))].append(task)
|
|||
|
|
return grouped
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _alert_note(title: str, description: str) -> str:
|
|||
|
|
parts = []
|
|||
|
|
if title:
|
|||
|
|
parts.append(f"标题:{title}")
|
|||
|
|
if description:
|
|||
|
|
parts.append(f"说明:{description}")
|
|||
|
|
return ";".join(parts)[:_NOTE_LIMIT]
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _snapshot(status: str, note: str) -> dict:
|
|||
|
|
return {
|
|||
|
|
"product_status": normalize_status(status),
|
|||
|
|
"product_status_note": str(note or "")[:_NOTE_LIMIT] or None,
|
|||
|
|
}
|