feat: 安全应用采购规格解析结果 (#257)

This commit is contained in:
chengma
2026-08-17 17:43:25 +08:00
parent 484ce4e8ec
commit afc1cdf719
19 changed files with 1669 additions and 24 deletions
+92
View File
@@ -54,6 +54,7 @@ from .pdd_purchase_adapter import (
PddPurchaseError,
PddPurchaseSpecResolutionRequired,
PurchaseSizeObservation,
PurchaseSpecCandidate,
PurchaseSpecCandidateSnapshot,
PurchasePageState,
)
@@ -1262,6 +1263,97 @@ class U2PddPurchaseAdapter(PddPurchaseAdapter):
)
return service.collect_second_dimension_candidates(device)
def apply_resolved_size(
self,
expected_snapshot: PurchaseSpecCandidateSnapshot,
candidate: PurchaseSpecCandidate,
) -> None:
"""重读并复算候选快照,只按响应中的页面原文选择一次尺码。"""
self._check_cancelled("purchase_resolve_options")
if (
expected_snapshot.goods_id != self._goods_id
or candidate not in expected_snapshot.candidates
or candidate.options.get("color") != expected_snapshot.selected_color
or candidate.options.get("size") != candidate.raw_text
):
raise PddPurchaseError(
"PURCHASE_SPEC_RESOLUTION_INVALID",
"规格解析结果不属于本次商品和候选快照",
step="purchase_resolve_options",
)
current_xml = self._dump_hierarchy()
root = _parse_xml(current_xml)
if _page_kind(root, "") != "order_confirmation" or not _selected(
root, expected_snapshot.selected_color
):
raise PddPurchaseError(
"PURCHASE_SPEC_CONTEXT_CHANGED",
"等待规格解析期间页面或已选颜色发生变化",
step="purchase_resolve_options",
)
current_xml = self._restore_purchase_panel_color_region(current_xml)
try:
dimension = self._size_candidate_collector(self._require_device())
except PddCollectError as exc:
raise PddPurchaseError(
"PURCHASE_SPEC_CANDIDATES_CHANGED",
f"无法重新完整读取尺码候选:{exc.message}",
step="purchase_resolve_options",
diagnostics={"candidate_scan_error": exc.code},
) from exc
if dimension is None:
raise PddPurchaseError(
"PURCHASE_SPEC_CANDIDATES_CHANGED",
"等待规格解析期间尺码候选已经消失",
step="purchase_resolve_options",
)
self._validate_size_candidate_dimension(dimension)
current_snapshot = PurchaseSpecCandidateSnapshot.build(
goods_id=self._goods_id,
selected_color=expected_snapshot.selected_color,
target_size=expected_snapshot.target_size,
dimension_name=dimension.name,
observations=tuple(
PurchaseSizeObservation(item.text, item.available)
for item in dimension.values
),
observed_at=expected_snapshot.observed_at,
)
if (
current_snapshot.dimension_name != expected_snapshot.dimension_name
or current_snapshot.candidate_snapshot_hash
!= expected_snapshot.candidate_snapshot_hash
or current_snapshot.candidates != expected_snapshot.candidates
):
raise PddPurchaseError(
"PURCHASE_SPEC_CANDIDATES_CHANGED",
"等待规格解析期间真机尺码候选已经变化",
step="purchase_resolve_options",
)
latest_xml = self._restore_purchase_panel_color_region(
self._dump_hierarchy()
)
if not self._select_size(
self._require_device(), latest_xml, candidate.raw_text, action_delay=0.2
):
raise PddPurchaseError(
"PURCHASE_RESOLVED_SIZE_NOT_SELECTED",
"解析得到的原始尺码没有可靠选中",
step="purchase_resolve_options",
)
selected_xml = self._dump_hierarchy()
if not _selected(_parse_xml(selected_xml), candidate.raw_text):
raise PddPurchaseError(
"PURCHASE_RESOLVED_SIZE_NOT_SELECTED",
"点击解析尺码后页面没有确认选中",
step="purchase_resolve_options",
)
self._requested_options["size"] = candidate.raw_text
def set_quantity(self, quantity: int) -> None:
device = self._require_device()
if isinstance(quantity, bool) or not isinstance(quantity, int) or quantity <= 0: