This commit is contained in:
@@ -25,7 +25,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import csv
|
||||
from dataclasses import dataclass
|
||||
from dataclasses import dataclass, replace
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
from pathlib import Path
|
||||
@@ -1158,6 +1158,44 @@ def write_step2(
|
||||
return [w[2] for w in warnings]
|
||||
|
||||
|
||||
def _apply_package_lifecycle_override(
|
||||
iccid: str,
|
||||
lifecycles: list[LegacyPackageLifecycle],
|
||||
mapping: Mapping,
|
||||
) -> tuple[list[LegacyPackageLifecycle], str]:
|
||||
"""应用经确认的逐卡裁决;未覆盖资产保持原始分类。"""
|
||||
override = mapping.lookup_package_lifecycle_override(iccid)
|
||||
if override is None:
|
||||
return lifecycles, ""
|
||||
|
||||
records = {item.life_id: item for item in lifecycles if item.source_table == "tbl_card_life"}
|
||||
selected = {override.active_life_id, *override.pending_life_ids, *override.skipped_life_ids}
|
||||
unknown = selected - set(records)
|
||||
if unknown:
|
||||
return lifecycles, f"套餐生命周期覆盖引用不属于该卡的 tbl_card_life 记录: {sorted(unknown)}"
|
||||
|
||||
migratable = {
|
||||
item.life_id for item in records.values()
|
||||
if item.migration_status in mapping.package_rules.migrate_statuses
|
||||
}
|
||||
if selected != migratable:
|
||||
missing = sorted(migratable - selected)
|
||||
extra = sorted(selected - migratable)
|
||||
return lifecycles, f"套餐生命周期覆盖必须完整裁决原本可迁移记录: 未覆盖={missing}, 非可迁移={extra}"
|
||||
|
||||
status_by_id = {override.active_life_id: "active"}
|
||||
status_by_id.update({life_id: "pending" for life_id in override.pending_life_ids})
|
||||
status_by_id.update({life_id: "skipped" for life_id in override.skipped_life_ids})
|
||||
return [
|
||||
replace(
|
||||
item,
|
||||
migration_status=status_by_id[item.life_id],
|
||||
skip_reason="套餐生命周期覆盖指定跳过" if status_by_id.get(item.life_id) == "skipped" else item.skip_reason,
|
||||
) if item.life_id in status_by_id else item
|
||||
for item in lifecycles
|
||||
], ""
|
||||
|
||||
|
||||
def _resolve_runtime_packages(
|
||||
*,
|
||||
cards: list[CardRow],
|
||||
@@ -1184,6 +1222,14 @@ def _resolve_runtime_packages(
|
||||
|
||||
for card, asset_type, asset_identifier in source_cards:
|
||||
lifecycles = package_lifecycles.get(card.iccid_full, [])
|
||||
lifecycles, override_error = _apply_package_lifecycle_override(card.iccid_full, lifecycles, mapping)
|
||||
if override_error:
|
||||
errors.append(ErrorRow("mapping.yaml", 0, "iccid", card.iccid_full, "package_lifecycle_override_invalid", override_error))
|
||||
for item in lifecycles:
|
||||
resolution_rows.append(_package_resolution_row(
|
||||
asset_type, asset_identifier, card.iccid_full, item, "", "", "blocked", override_error
|
||||
))
|
||||
continue
|
||||
migratable = [
|
||||
item for item in lifecycles
|
||||
if item.migration_status in mapping.package_rules.migrate_statuses
|
||||
@@ -1430,6 +1476,7 @@ def _write_package_usages(
|
||||
" package_name,\n"
|
||||
" package_price_config_status, package_is_gift,\n"
|
||||
" data_reset_cycle,\n"
|
||||
" expiry_base_snapshot, calendar_type_snapshot, duration_months_snapshot, duration_days_snapshot,\n"
|
||||
" creator, updater, created_at, updated_at\n"
|
||||
")\n"
|
||||
f"SELECT o.id, o.order_no, p.id, {_sql_str(usage_type)},\n"
|
||||
@@ -1443,6 +1490,9 @@ def _write_package_usages(
|
||||
" p.package_name,\n"
|
||||
" p.price_config_status, p.is_gift,\n"
|
||||
" p.data_reset_cycle,\n"
|
||||
" p.expiry_base, p.calendar_type,\n"
|
||||
" CASE WHEN p.calendar_type = 'natural_month' THEN p.duration_months ELSE 0 END,\n"
|
||||
" CASE WHEN p.calendar_type = 'by_day' THEN p.duration_days ELSE 0 END,\n"
|
||||
f" {user_id}, {user_id}, NOW(), NOW()\n"
|
||||
"FROM tb_order o\n"
|
||||
f"JOIN tb_package p ON p.id = {pkg.target_package_id} AND p.package_type = 'formal' AND p.deleted_at IS NULL\n"
|
||||
|
||||
Reference in New Issue
Block a user