feat(platform-orders): queue batch activate subscriptions job
This commit is contained in:
@@ -1592,87 +1592,21 @@ class PlatformOrderController extends Controller
|
||||
}
|
||||
$filterSummary = implode('&', $filterSummaryParts);
|
||||
|
||||
foreach ($orders as $orderRow) {
|
||||
try {
|
||||
$order = PlatformOrder::query()->find($orderRow->id);
|
||||
if (! $order) {
|
||||
continue;
|
||||
}
|
||||
// 队列化(M3 可运维化第一步):先把匹配到的订单 ID 列表投递为一个 Job,避免请求超时。
|
||||
// 注意:当前阶段仍由 Job 内逐条写 meta 与错误原因;后续可再升级为分片 Job + 结果聚合。
|
||||
$orderIds = $orders->pluck('id')->map(fn ($id) => (int) $id)->values()->all();
|
||||
|
||||
// 治理优先:续费单必须绑定订阅(兼容历史脏数据/手工改库等场景)
|
||||
if ((string) ($order->order_type ?? '') === 'renewal' && ! (int) ($order->site_subscription_id ?? 0)) {
|
||||
throw new \InvalidArgumentException('续费单未绑定订阅(site_subscription_id 为空),不允许批量同步订阅。');
|
||||
}
|
||||
\App\Jobs\BatchActivateSubscriptionsJob::dispatch(
|
||||
$orderIds,
|
||||
(int) $admin->id,
|
||||
$scope,
|
||||
(string) $filterSummary,
|
||||
(int) $limit,
|
||||
(int) $matchedTotal,
|
||||
(int) $processed,
|
||||
);
|
||||
|
||||
$subscription = $service->activateOrder($orderRow->id, $admin->id);
|
||||
|
||||
// 注意:activateOrder 过程中会写入 order 的 meta/site_subscription_id 等;此处必须 refresh,避免后续写审计时覆盖掉同步结果
|
||||
$order->refresh();
|
||||
|
||||
// 轻量审计:记录批量同步动作(方便追溯)
|
||||
if ($order) {
|
||||
$meta = (array) ($order->meta ?? []);
|
||||
$audit = (array) (data_get($meta, 'audit', []) ?? []);
|
||||
$nowStr = now()->toDateTimeString();
|
||||
$audit[] = [
|
||||
'action' => 'batch_activate_subscription',
|
||||
'scope' => $scope,
|
||||
'at' => $nowStr,
|
||||
'admin_id' => $admin->id,
|
||||
'subscription_id' => $subscription->id,
|
||||
'filters' => $filterSummary,
|
||||
'note' => '批量同步订阅(limit=' . $limit . ', matched=' . $matchedTotal . ', processed=' . $processed . ')',
|
||||
];
|
||||
data_set($meta, 'audit', $audit);
|
||||
|
||||
// 便于筛选/统计:记录最近一次批量同步信息(扁平字段)
|
||||
data_set($meta, 'batch_activation', [
|
||||
'at' => $nowStr,
|
||||
'admin_id' => $admin->id,
|
||||
'scope' => $scope,
|
||||
]);
|
||||
|
||||
$order->meta = $meta;
|
||||
$order->save();
|
||||
}
|
||||
|
||||
$success++;
|
||||
} catch (\Throwable $e) {
|
||||
$failed++;
|
||||
|
||||
$reason = trim((string) $e->getMessage());
|
||||
$reason = $reason !== '' ? $reason : '未知错误';
|
||||
$failedReasonCounts[$reason] = ($failedReasonCounts[$reason] ?? 0) + 1;
|
||||
|
||||
// 批量同步失败也需要可治理:写入失败原因到订单 meta,便于后续筛选/导出/清理
|
||||
$order = PlatformOrder::query()->find($orderRow->id);
|
||||
if ($order) {
|
||||
$meta = (array) ($order->meta ?? []);
|
||||
data_set($meta, 'subscription_activation_error', [
|
||||
'message' => $reason,
|
||||
'at' => now()->toDateTimeString(),
|
||||
'admin_id' => $admin->id,
|
||||
]);
|
||||
$order->meta = $meta;
|
||||
$order->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$msg = '批量同步订阅完成:成功 ' . $success . ' 条,失败 ' . $failed . ' 条(命中 ' . $matchedTotal . ' 条,本次处理 ' . $processed . ' 条,limit=' . $limit . ')';
|
||||
|
||||
if ($failed > 0 && count($failedReasonCounts) > 0) {
|
||||
arsort($failedReasonCounts);
|
||||
$top = array_slice($failedReasonCounts, 0, 3, true);
|
||||
$topText = collect($top)->map(function ($cnt, $reason) {
|
||||
$reason = mb_substr((string) $reason, 0, 60);
|
||||
return $reason . '(' . $cnt . ')';
|
||||
})->implode(';');
|
||||
|
||||
$msg .= ';失败原因Top:' . $topText;
|
||||
}
|
||||
|
||||
return redirect()->back()->with('success', $msg);
|
||||
return redirect()->back()->with('success', '批量同步订阅任务已提交到队列:命中 ' . $matchedTotal . ' 条,本次处理 ' . $processed . ' 条(limit=' . $limit . ')。');
|
||||
}
|
||||
|
||||
public function batchMarkPaidAndActivate(Request $request, SubscriptionActivationService $service): RedirectResponse
|
||||
|
||||
Reference in New Issue
Block a user