doge há 23 horas atrás
pai
commit
a574925c11

+ 73 - 0
app/Console/Commands/CollectSyncMember.php

@@ -0,0 +1,73 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\Services\CollectService;
+use Illuminate\Console\Command;
+
+class CollectSyncMember extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'collect:sync-member {member_id : 用户 member_id}';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = '按指定用户补建或刷新待归集记录,不执行链上归集';
+
+    /**
+     * Execute the console command.
+     *
+     * @return int
+     */
+    public function handle()
+    {
+        $memberId = $this->argument('member_id');
+
+        $this->info("开始处理用户 {$memberId} 的待归集记录...");
+
+        $result = CollectService::syncMemberCollectRecords($memberId);
+        if (empty($result['success'])) {
+            $this->error($result['message'] ?? '处理失败');
+            return Command::FAILURE;
+        }
+
+        $this->table(
+            ['member_id', 'recharge_count', 'processed_count', 'created_count', 'updated_count', 'skipped_count', 'failed_count'],
+            [[
+                $result['member_id'],
+                $result['recharge_count'],
+                $result['processed_count'],
+                $result['created_count'],
+                $result['updated_count'],
+                $result['skipped_count'],
+                $result['failed_count'],
+            ]]
+        );
+
+        if (!empty($result['items'])) {
+            $this->table(
+                ['from_address', 'action', 'collect_id', 'amount', 'recharge_txid', 'error'],
+                array_map(function ($item) {
+                    return [
+                        $item['from_address'],
+                        $item['action'],
+                        $item['collect_id'],
+                        $item['amount'],
+                        $item['recharge_txid'],
+                        $item['error'],
+                    ];
+                }, $result['items'])
+            );
+        }
+
+        $this->info('处理完成');
+        return Command::SUCCESS;
+    }
+}

+ 9 - 1
app/Console/Commands/RechargeSyncMember.php

@@ -40,7 +40,7 @@ class RechargeSyncMember extends Command
         }
 
         $this->table(
-            ['member_id', 'address', 'synced', 'checked', 'confirmed', 'remaining_pending'],
+            ['member_id', 'address', 'synced', 'checked', 'confirmed', 'remaining_pending', 'collect_ensured'],
             [[
                 $result['member_id'],
                 $result['address'],
@@ -48,6 +48,7 @@ class RechargeSyncMember extends Command
                 $result['checked'],
                 $result['confirmed'],
                 $result['remaining_pending'],
+                $result['collect_ensured'],
             ]]
         );
 
@@ -58,6 +59,13 @@ class RechargeSyncMember extends Command
             }
         }
 
+        if (!empty($result['collect_addresses'])) {
+            $this->line('已补建待归集地址:');
+            foreach ($result['collect_addresses'] as $address) {
+                $this->line($address);
+            }
+        }
+
         $this->info('处理完成');
         return Command::SUCCESS;
     }

+ 100 - 0
app/Services/CollectService.php

@@ -5,6 +5,7 @@ namespace App\Services;
 
 use App\Services\BaseService;
 use App\Models\Collect;
+use App\Models\Recharge;
 use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Collection;
 use Illuminate\Support\Facades\Cache;
@@ -136,6 +137,105 @@ class CollectService extends BaseService
 
     }
 
+    /**
+     * @description: 按会员补建或刷新待归集记录,不执行链上归集
+     * @param {*} $memberId
+     * @return array
+     */
+    public static function syncMemberCollectRecords($memberId)
+    {
+        $recharges = Recharge::where('member_id', $memberId)
+            ->where('status', Recharge::STATUS_SUCCESS)
+            ->where('type', Recharge::TYPE_AUTO)
+            ->orderByDesc('id')
+            ->get();
+
+        $result = [
+            'success' => true,
+            'member_id' => $memberId,
+            'recharge_count' => $recharges->count(),
+            'processed_count' => 0,
+            'created_count' => 0,
+            'updated_count' => 0,
+            'skipped_count' => 0,
+            'failed_count' => 0,
+            'items' => [],
+        ];
+
+        if ($recharges->isEmpty()) {
+            $result['success'] = false;
+            $result['message'] = '未找到已确认的自动充值记录';
+            return $result;
+        }
+
+        $seen = [];
+        foreach ($recharges as $recharge) {
+            $address = $recharge->to_address;
+            if (empty($address) || isset($seen[$address])) {
+                continue;
+            }
+
+            $seen[$address] = true;
+            $item = [
+                'from_address' => $address,
+                'recharge_txid' => $recharge->txid,
+                'action' => 'pending',
+                'collect_id' => null,
+                'amount' => null,
+                'error' => null,
+            ];
+
+            $openCollect = self::model()::where('from_address', $address)
+                ->whereIn('status', [self::model()::STATUS_STAY, self::model()::STATUS_START])
+                ->orderByDesc('id')
+                ->first();
+
+            if ($openCollect && intval($openCollect->status) === self::model()::STATUS_START) {
+                $item['action'] = 'skipped_started';
+                $item['collect_id'] = $openCollect->id;
+                $item['amount'] = $openCollect->amount;
+                $result['skipped_count']++;
+                $result['processed_count']++;
+                $result['items'][] = $item;
+                continue;
+            }
+
+            $hadPending = $openCollect && intval($openCollect->status) === self::model()::STATUS_STAY;
+
+            try {
+                self::createCollect($address, $recharge->coin, $recharge->net);
+                $collect = self::model()::where('from_address', $address)
+                    ->where('status', self::model()::STATUS_STAY)
+                    ->orderByDesc('id')
+                    ->first();
+
+                $item['action'] = $hadPending ? 'updated' : 'created';
+                $item['collect_id'] = $collect->id ?? null;
+                $item['amount'] = $collect->amount ?? null;
+
+                if ($hadPending) {
+                    $result['updated_count']++;
+                } else {
+                    $result['created_count']++;
+                }
+            } catch (\Throwable $e) {
+                $item['action'] = 'failed';
+                $item['error'] = $e->getMessage();
+                $result['failed_count']++;
+            }
+
+            $result['processed_count']++;
+            $result['items'][] = $item;
+        }
+
+        if ($result['processed_count'] === 0) {
+            $result['success'] = false;
+            $result['message'] = '未找到可处理的充值地址';
+        }
+
+        return $result;
+    }
+
     /**
      * @description: 处理待归集的
      * @return {*}

+ 49 - 0
app/Services/RechargeService.php

@@ -4,6 +4,7 @@
 namespace App\Services;
 
 use App\Services\BaseService;
+use App\Models\Collect;
 use App\Models\Recharge;
 use App\Models\User;
 use Illuminate\Support\Facades\DB;
@@ -233,6 +234,8 @@ class RechargeService extends BaseService
             'type' => self::model()::TYPE_AUTO,
         ]))->count();
 
+        $collectResult = self::ensureCollectRecordsForMember($memberId);
+
         return [
             'success' => true,
             'member_id' => $memberId,
@@ -242,6 +245,52 @@ class RechargeService extends BaseService
             'confirmed' => $confirmed,
             'remaining_pending' => $remainingPending,
             'confirmed_txids' => $confirmedTxids,
+            'collect_ensured' => $collectResult['ensured'],
+            'collect_addresses' => $collectResult['addresses'],
+        ];
+    }
+
+    /**
+     * @description: 为已确认充值补建待归集记录
+     * @param {*} $memberId
+     * @return array
+     */
+    public static function ensureCollectRecordsForMember($memberId)
+    {
+        $list = self::model()::where(self::getWhere([
+            'member_id' => $memberId,
+            'status' => self::model()::STATUS_SUCCESS,
+            'type' => self::model()::TYPE_AUTO,
+        ]))->orderByDesc('id')->get();
+
+        $ensured = 0;
+        $addresses = [];
+        $seen = [];
+
+        foreach ($list as $item) {
+            $address = $item->to_address;
+            if (empty($address) || isset($seen[$address])) {
+                continue;
+            }
+
+            $seen[$address] = true;
+
+            $hasOpenCollect = Collect::where('from_address', $address)
+                ->whereIn('status', [Collect::STATUS_STAY, Collect::STATUS_START])
+                ->exists();
+
+            if ($hasOpenCollect) {
+                continue;
+            }
+
+            CollectService::createCollect($address, $item->coin, $item->net);
+            $ensured++;
+            $addresses[] = $address;
+        }
+
+        return [
+            'ensured' => $ensured,
+            'addresses' => $addresses,
         ];
     }