|
@@ -0,0 +1,122 @@
|
|
|
|
|
+<?php
|
|
|
|
|
+
|
|
|
|
|
+namespace App\Console\Commands;
|
|
|
|
|
+
|
|
|
|
|
+use App\Models\MpGenerateVideoTask;
|
|
|
|
|
+use App\Services\PointsService;
|
|
|
|
|
+use Illuminate\Console\Command;
|
|
|
|
|
+use Illuminate\Support\Facades\DB;
|
|
|
|
|
+
|
|
|
|
|
+class BackfillVideoTokensCommand extends Command
|
|
|
|
|
+{
|
|
|
|
|
+ /**
|
|
|
|
|
+ * The name and signature of the console command.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @var string
|
|
|
|
|
+ */
|
|
|
|
|
+ protected $signature = 'points:backfill-video-tokens
|
|
|
|
|
+ {--dry-run : 只统计将回填的记录数,不实际更新}
|
|
|
|
|
+ {--limit= : 最多处理记录数(默认全部)}';
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * The console command description.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @var string
|
|
|
|
|
+ */
|
|
|
|
|
+ protected $description = '回填视频积分明细缺失的 token(历史 bug:扣费时读取到未同步的 result_json 导致 tokens_consumed=0)';
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Execute the console command.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param PointsService $pointsService
|
|
|
|
|
+ * @return int
|
|
|
|
|
+ */
|
|
|
|
|
+ public function handle(PointsService $pointsService)
|
|
|
|
|
+ {
|
|
|
|
|
+ $dryRun = (bool)$this->option('dry-run');
|
|
|
|
|
+ $limit = (int)$this->option('limit');
|
|
|
|
|
+ if ($limit < 0) {
|
|
|
|
|
+ $limit = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $query = DB::table('mp_user_points_details as d')
|
|
|
|
|
+ ->leftJoin('mp_generate_video_tasks as t', 't.id', '=', 'd.task_id')
|
|
|
|
|
+ ->where('d.type', 'video')
|
|
|
|
|
+ ->where('d.points_consumed', '>', 0)
|
|
|
|
|
+ ->where('d.tokens_consumed', 0)
|
|
|
|
|
+ ->select('d.id', 'd.task_id', 't.api_type', 't.result_json');
|
|
|
|
|
+
|
|
|
|
|
+ $total = (clone $query)->count();
|
|
|
|
|
+ $this->info("待回填明细总数: {$total}" . ($dryRun ? '(dry-run 模式,不更新)' : ''));
|
|
|
|
|
+ if ($total <= 0) {
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ if ($limit > 0) {
|
|
|
|
|
+ $query->limit($limit);
|
|
|
|
|
+ $this->info("本次最多处理: {$limit} 条");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $updated = 0;
|
|
|
|
|
+ $skipped = 0;
|
|
|
|
|
+ $notFound = 0;
|
|
|
|
|
+
|
|
|
|
|
+ $rows = $query->get();
|
|
|
|
|
+ $bar = $this->output->createProgressBar($rows->count());
|
|
|
|
|
+ $bar->start();
|
|
|
|
|
+
|
|
|
|
|
+ foreach ($rows as $row) {
|
|
|
|
|
+ $bar->advance();
|
|
|
|
|
+
|
|
|
|
|
+ if (!$row->task_id || $row->result_json === null) {
|
|
|
|
|
+ $skipped++;
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $task = new MpGenerateVideoTask();
|
|
|
|
|
+ $task->api_type = (string)$row->api_type;
|
|
|
|
|
+ $task->result_json = $row->result_json;
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ $tokens = $pointsService->getVideoTokensConsumed($task);
|
|
|
|
|
+ } catch (\Throwable $e) {
|
|
|
|
|
+ dLog('points')->warning('视频 token 回填解析异常', [
|
|
|
|
|
+ 'detail_id' => $row->id,
|
|
|
|
|
+ 'task_id' => $row->task_id,
|
|
|
|
|
+ 'error' => $e->getMessage(),
|
|
|
|
|
+ ]);
|
|
|
|
|
+ $skipped++;
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if ($tokens <= 0) {
|
|
|
|
|
+ $skipped++;
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!$dryRun) {
|
|
|
|
|
+ DB::table('mp_user_points_details')
|
|
|
|
|
+ ->where('id', $row->id)
|
|
|
|
|
+ ->update([
|
|
|
|
|
+ 'tokens_consumed' => $tokens,
|
|
|
|
|
+ 'updated_at' => date('Y-m-d H:i:s'),
|
|
|
|
|
+ ]);
|
|
|
|
|
+ }
|
|
|
|
|
+ $updated++;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $bar->finish();
|
|
|
|
|
+ $this->newLine(2);
|
|
|
|
|
+
|
|
|
|
|
+ $this->info("可回填: {$updated} 条" . ($dryRun ? '(dry-run 未写入)' : ',已写入'));
|
|
|
|
|
+ $this->info("跳过(任务缺失/无 token 数据): {$skipped} 条");
|
|
|
|
|
+
|
|
|
|
|
+ if ($updated > 0 && !$dryRun) {
|
|
|
|
|
+ dLog('points')->info('视频积分明细 token 历史回填完成', [
|
|
|
|
|
+ 'updated' => $updated,
|
|
|
|
|
+ 'skipped' => $skipped,
|
|
|
|
|
+ ]);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|