From b38df737e13487d95149a402fbabdbb4b0ae7d93 Mon Sep 17 00:00:00 2001 From: break Date: Thu, 9 Jul 2026 18:23:29 +0900 Subject: [PATCH] =?UTF-8?q?=E5=85=88=E7=9F=AD=E6=9A=82=E5=8E=BB=E9=99=A4?= =?UTF-8?q?=E9=99=90=E5=88=B6,=E4=B8=8A=E4=BC=A0=E8=BF=81=E7=A7=BB?= =?UTF-8?q?=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/handler/app/client_wallet.go | 22 +++++------ internal/service/client_order/service.go | 48 ++++++++++++------------ scripts/migration/lib/mapping_loader.py | 8 ++++ scripts/migration/lib/sql_builder.py | 18 ++++++++- 4 files changed, 59 insertions(+), 37 deletions(-) diff --git a/internal/handler/app/client_wallet.go b/internal/handler/app/client_wallet.go index fc1d851..ad6ee5b 100644 --- a/internal/handler/app/client_wallet.go +++ b/internal/handler/app/client_wallet.go @@ -279,17 +279,17 @@ func (h *ClientWalletHandler) CreateRecharge(c *fiber.Ctx) error { return err } - // 第三方支付方式与资产类型必须匹配:单卡只允许支付宝,设备只允许微信 - switch resolved.Asset.AssetType { - case "card": - if req.PaymentMethod != constants.RechargeMethodAlipay { - return errors.New(errors.CodeInvalidParam, "单卡资产只支持支付宝充值") - } - case "device": - if req.PaymentMethod != constants.RechargeMethodWechat { - return errors.New(errors.CodeInvalidParam, "设备资产只支持微信充值") - } - } + // 第三方支付方式与资产类型必须匹配:单卡只允许支付宝,设备只允许微信(已暂时注释) + // switch resolved.Asset.AssetType { + // case "card": + // if req.PaymentMethod != constants.RechargeMethodAlipay { + // return errors.New(errors.CodeInvalidParam, "单卡资产只支持支付宝充值") + // } + // case "device": + // if req.PaymentMethod != constants.RechargeMethodWechat { + // return errors.New(errors.CodeInvalidParam, "设备资产只支持微信充值") + // } + // } config, err := h.wechatConfigService.GetActiveConfig(resolved.SkipPermissionCtx) if err != nil { diff --git a/internal/service/client_order/service.go b/internal/service/client_order/service.go index fd0a4bd..c846084 100644 --- a/internal/service/client_order/service.go +++ b/internal/service/client_order/service.go @@ -229,17 +229,17 @@ func (s *Service) CreateOrder(ctx context.Context, customerID uint, req *dto.Cli }() if forceRecharge.NeedForceRecharge { - // 强充第三方支付方式与资产类型必须匹配:单卡只允许支付宝,设备只允许微信 - switch assetInfo.AssetType { - case "card": - if req.PaymentMethod != model.PaymentMethodAlipay { - return nil, errors.New(errors.CodeInvalidParam, "单卡资产强充只支持支付宝支付") - } - case constants.ResourceTypeDevice: - if req.PaymentMethod == model.PaymentMethodAlipay { - return nil, errors.New(errors.CodeInvalidParam, "设备资产强充只支持微信支付") - } - } + // 强充第三方支付方式与资产类型必须匹配:单卡只允许支付宝,设备只允许微信(已暂时注释) + // switch assetInfo.AssetType { + // case "card": + // if req.PaymentMethod != model.PaymentMethodAlipay { + // return nil, errors.New(errors.CodeInvalidParam, "单卡资产强充只支持支付宝支付") + // } + // case constants.ResourceTypeDevice: + // if req.PaymentMethod == model.PaymentMethodAlipay { + // return nil, errors.New(errors.CodeInvalidParam, "设备资产强充只支持微信支付") + // } + // } if req.PaymentMethod == model.PaymentMethodAlipay { // 支付宝强充:不需要 app_type / OpenID @@ -1253,19 +1253,19 @@ func (s *Service) PayOrder(ctx context.Context, customerID uint, orderID uint, r return nil, errors.New(errors.CodeNeedRealname) } - // 第三方支付方式与资产类型必须匹配:单卡只允许支付宝,设备只允许微信 - if req.PaymentMethod == model.PaymentMethodWechat || req.PaymentMethod == model.PaymentMethodAlipay { - switch order.OrderType { - case model.OrderTypeSingleCard: - if req.PaymentMethod != model.PaymentMethodAlipay { - return nil, errors.New(errors.CodeInvalidParam, "单卡资产只支持支付宝支付") - } - case model.OrderTypeDevice: - if req.PaymentMethod != model.PaymentMethodWechat { - return nil, errors.New(errors.CodeInvalidParam, "设备资产只支持微信支付") - } - } - } + // 第三方支付方式与资产类型必须匹配:单卡只允许支付宝,设备只允许微信(已暂时注释) + // if req.PaymentMethod == model.PaymentMethodWechat || req.PaymentMethod == model.PaymentMethodAlipay { + // switch order.OrderType { + // case model.OrderTypeSingleCard: + // if req.PaymentMethod != model.PaymentMethodAlipay { + // return nil, errors.New(errors.CodeInvalidParam, "单卡资产只支持支付宝支付") + // } + // case model.OrderTypeDevice: + // if req.PaymentMethod != model.PaymentMethodWechat { + // return nil, errors.New(errors.CodeInvalidParam, "设备资产只支持微信支付") + // } + // } + // } switch req.PaymentMethod { case model.PaymentMethodWallet: diff --git a/scripts/migration/lib/mapping_loader.py b/scripts/migration/lib/mapping_loader.py index 232ff65..bc86c5b 100644 --- a/scripts/migration/lib/mapping_loader.py +++ b/scripts/migration/lib/mapping_loader.py @@ -139,6 +139,7 @@ class AgentMapping: legacy_agent_id: str legacy_agent_name: str target_shop_code: Optional[str] # legacy_agent 模式下允许 null,表示该代理资产进平台库存 + no_downtime: bool = False # 迁移时免停机:有生效套餐的卡直接以 network_status=1 导入 @dataclass @@ -166,6 +167,11 @@ class Mapping: return None return self.series.get(str(legacy_series_id).strip()) + def is_no_downtime_agent(self, legacy_agent_id: str) -> bool: + """判断代理是否配置了免停机迁移。""" + agent = self.agents.get(str(legacy_agent_id or "").strip()) + return agent.no_downtime if agent else False + def lookup_agent_shop_code(self, legacy_agent_id: str) -> Optional[str]: """按 agent_id 查 target_shop_code,空字符串视为 None(进平台库存)。""" if not legacy_agent_id: @@ -260,6 +266,7 @@ def load_mapping(config_dir: Path) -> Mapping: legacy_agent_id=str(item["legacy_agent_id"]).strip(), legacy_agent_name=str(item.get("legacy_agent_name") or ""), target_shop_code=_opt_shop_code(item.get("target_shop_code"), "agents[].target_shop_code"), + no_downtime=bool(item.get("no_downtime", False)), ) m.agents[a.legacy_agent_id] = a @@ -536,6 +543,7 @@ def _append_agents(lines: list[str], mapping: Mapping) -> None: f" - legacy_agent_id: {_yaml_scalar(item.legacy_agent_id)}", f" legacy_agent_name: {_yaml_scalar(item.legacy_agent_name)}", f" target_shop_code: {_yaml_scalar(item.target_shop_code)}", + f" no_downtime: {_yaml_scalar(item.no_downtime)}", ]) diff --git a/scripts/migration/lib/sql_builder.py b/scripts/migration/lib/sql_builder.py index 6d864b1..4118ed8 100644 --- a/scripts/migration/lib/sql_builder.py +++ b/scripts/migration/lib/sql_builder.py @@ -621,6 +621,20 @@ def _write_iot_cards( card_status = 2 if shop_code else 1 shop_id_expr = _shop_id_sub(shop_code) + # 免停机迁移:代理配置 no_downtime=true 且卡在奇成有当前生效正式套餐 + # finalize 保证最后执行,此时 step2 套餐已落库,轮询系统不会在此之前触碰这张卡 + is_no_downtime = bool(meta.current_meal_id) and mapping.is_no_downtime_agent(meta.agent_id) + if is_no_downtime: + activation_status = 1 + real_name_status = 1 # 卡在线说明已实名,写 1 防止 EvaluateAndAct 因 not_realname 停机 + network_status = 1 + stop_reason_expr = "NULL" + else: + activation_status = 0 + real_name_status = 0 + network_status = 0 + stop_reason_expr = _sql_str(_initial_polling_stop_reason(c)) + f.write( "INSERT INTO tb_iot_card (\n" " iccid, iccid_19, iccid_20,\n" @@ -636,9 +650,9 @@ def _write_iot_cards( f" {_sql_str(c.iccid_full)}, {_sql_str(c.iccid_19)}, {iccid_20_expr},\n" f" {carrier.target_carrier_id}, {_sql_str(carrier.target_carrier_type)}, {_sql_str(carrier.target_carrier_name)},\n" f" {_sql_str(card_category)}, {_sql_str(mapping.migration_batch_no)},\n" - f" {card_status}, 0, 0, 0,\n" + f" {card_status}, {activation_status}, {real_name_status}, {network_status},\n" f" 1, 1, {is_standalone},\n" - f" 'after_order', {_sql_str(_initial_polling_stop_reason(c))},\n" + f" 'after_order', {stop_reason_expr},\n" f" {_sql_str(meta.msisdn) if meta.msisdn else 'NULL'}, " f"{_sql_str(card_virtual_no) if card_virtual_no else 'NULL'}, " f"{shop_id_expr}, {series_id_expr},\n"