Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.09% covered (danger)
0.09%
1 / 1098
5.00% covered (danger)
5.00%
1 / 20
CRAP
0.00% covered (danger)
0.00%
0 / 1
MagoCommand
0.09% covered (danger)
0.09%
1 / 1098
5.00% covered (danger)
5.00%
1 / 20
23192.93
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 handle
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 fixDuplicates
0.00% covered (danger)
0.00%
0 / 98
0.00% covered (danger)
0.00%
0 / 1
90
 fixShortcuts
0.00% covered (danger)
0.00%
0 / 53
0.00% covered (danger)
0.00%
0 / 1
72
 fixDaily
0.00% covered (danger)
0.00%
0 / 67
0.00% covered (danger)
0.00%
0 / 1
90
 fixWagePerHour
0.00% covered (danger)
0.00%
0 / 47
0.00% covered (danger)
0.00%
0 / 1
72
 fixPlans
0.00% covered (danger)
0.00%
0 / 69
0.00% covered (danger)
0.00%
0 / 1
90
 fixCorporateUsersOnHubspot
0.00% covered (danger)
0.00%
0 / 81
0.00% covered (danger)
0.00%
0 / 1
132
 fixEnterpriseUsersEndDate
0.00% covered (danger)
0.00%
0 / 63
0.00% covered (danger)
0.00%
0 / 1
90
 fixDeleteUsers
0.00% covered (danger)
0.00%
0 / 80
0.00% covered (danger)
0.00%
0 / 1
132
 fixPricing
0.00% covered (danger)
0.00%
0 / 99
0.00% covered (danger)
0.00%
0 / 1
420
 fixAppsumoLifePlan
0.00% covered (danger)
0.00%
0 / 51
0.00% covered (danger)
0.00%
0 / 1
42
 fixUserEmailDomainCount
0.00% covered (danger)
0.00%
0 / 51
0.00% covered (danger)
0.00%
0 / 1
42
 fixUserEmailDomain
0.00% covered (danger)
0.00%
0 / 51
0.00% covered (danger)
0.00%
0 / 1
42
 fixUserStatus
0.00% covered (danger)
0.00%
0 / 52
0.00% covered (danger)
0.00%
0 / 1
42
 fixUserAccountCreationDate
0.00% covered (danger)
0.00%
0 / 52
0.00% covered (danger)
0.00%
0 / 1
42
 fixUserUpdatedAt
0.00% covered (danger)
0.00%
0 / 52
0.00% covered (danger)
0.00%
0 / 1
42
 fixUserCreatedAt
0.00% covered (danger)
0.00%
0 / 52
0.00% covered (danger)
0.00%
0 / 1
42
 fixUserLastLogin
0.00% covered (danger)
0.00%
0 / 52
0.00% covered (danger)
0.00%
0 / 1
42
 cleanShortcutHtml
0.00% covered (danger)
0.00%
0 / 23
0.00% covered (danger)
0.00%
0 / 1
72
1<?php
2
3namespace App\Console\Commands;
4
5use App\Http\Models\Admin\Company;
6use App\Http\Models\Admin\CompanyGroup;
7use App\Http\Models\Admin\CompanyLicenses;
8use App\Http\Models\Auth\User;
9use App\Http\Models\FlyCutUsage;
10use App\Http\Models\FlyMsgUserDailyUsage;
11use App\Http\Models\HubspotProperties;
12use App\Http\Models\Plans;
13use App\Http\Models\Shortcut;
14use App\Http\Models\Subscription;
15use App\Http\Models\UserInfo;
16use App\Http\Services\HubspotServiceV2;
17use App\Http\Services\InstancyServiceV2;
18use App\Http\Services\StatisticsService;
19use App\Services\UserInfo\FlyMsgUserDailyUsageService;
20use App\Services\UserInfo\SubscriptionService;
21use App\Services\UserInfo\UserInfoService;
22use Carbon\Carbon;
23use Illuminate\Console\Command;
24use Illuminate\Support\Facades\Log;
25use MongoDB\BSON\UTCDateTime;
26use Illuminate\Support\Str;
27
28class MagoCommand extends Command
29{
30    public function __construct(
31        public UserInfoService $userInfoService,
32        public FlyMsgUserDailyUsageService $flyMsgUserDailyUsageService,
33        public StatisticsService $statisticsService,
34    ) {
35        parent::__construct();
36    }
37
38    protected $signature = 'mago {perPage} {page}';
39
40    protected $description = 'MagoCommand';
41
42    public function handle(): void
43    {
44        $this->info("MagoCommand started");
45        $totalTimeStartAt = now();
46
47        //$this->fixDuplicates();
48        // $this->fixShortcuts();
49        // $this->fixDaily();
50        // $this->fixWagePerHour();
51        // $this->fixPlans();
52        // $this->fixDaily();
53        // $this->fixWagePerHour();
54        // $this->fixPlans();
55        // $this->fixCorporateUsersOnHubspot();
56        $this->fixEnterpriseUsersEndDate();
57        // $this->fixDeleteUsers();
58        // $this->fixPricing();
59        // $this->fixAppsumoLifePlan();
60        // $this->fixUserLastLogin();
61        // $this->fixUserCreatedAt();
62        // $this->fixUserStatus();
63        // $this->fixUserEmailDomain();
64        // $this->fixUserEmailDomainCount();
65        // $this->fixUserAccountCreationDate();
66        // $this->fixUserUpdatedAt();
67
68        $this->info("MagoCommand ended with duration of " . now()->diffInSeconds($totalTimeStartAt) . " seconds");
69    }
70
71    private function fixDuplicates()
72    {
73        $perPage = $this->argument('perPage');
74        $page = $this->argument('page');
75
76        $this->info("fixDuplicates started");
77        $totalTimeStartAt = now();
78
79        ini_set('memory_limit', '-1');
80
81        $failed_users_count = 0;
82
83        // test $userIds = User::whereIsNotNull('company_id')->pluck('id')->toArray();
84
85        $pipeline = [
86            [
87                '$match' => [
88                    '$or' => [
89                        ['flymsg_freemium_subscription_status' => 'Active'],
90                        ['flymsg_growth_subscription_status' => 'Active'],
91                        ['flymsg_starter_subscription_status' => 'Active'],
92                        ['professional_subscription_status' => 'Active'],
93                        ['sales_pro_teams_subscription_status' => 'Active'],
94                    ],
95                ],
96            ],
97            [
98                '$addFields' => [
99                    'activeCount' => [
100                        '$add' => [
101                            ['$cond' => [['$eq' => ['$flymsg_freemium_subscription_status', 'Active']], 1, 0]],
102                            ['$cond' => [['$eq' => ['$flymsg_growth_subscription_status', 'Active']], 1, 0]],
103                            ['$cond' => [['$eq' => ['$flymsg_starter_subscription_status', 'Active']], 1, 0]],
104                            ['$cond' => [['$eq' => ['$professional_subscription_status', 'Active']], 1, 0]],
105                            ['$cond' => [['$eq' => ['$sales_pro_teams_subscription_status', 'Active']], 1, 0]],
106                        ],
107                    ],
108                ],
109            ],
110            [
111                '$match' => [
112                    'activeCount' => ['$gte' => 2],
113                ],
114            ],
115            [
116                '$project' => [
117                    'email' => '$email',
118                    'hubspot' => '$hubspot_id',
119                    'free' => '$flymsg_freemium_subscription_status',
120                    'growth' => '$flymsg_growth_subscription_status',
121                    'starter' => '$flymsg_starter_subscription_status',
122                    'pro' => '$professional_subscription_status',
123                    'enterprise' => '$sales_pro_teams_subscription_status',
124                    'user_id' => '$user_id',
125                    'end_free' => '$freemium_subscription_churn_date',
126                    '_id' => 0 // To remove the default _id field from the result
127                ],
128            ],
129        ];
130
131        $results = UserInfo::raw(function ($collection) use ($pipeline) {
132            return $collection->aggregate($pipeline);
133        });
134
135        $totalFlyCutUsage = count($results);
136        $this->info("Processing " . $totalFlyCutUsage . " users");
137
138        $shortcutDispatcher = Shortcut::getEventDispatcher();
139        Shortcut::unsetEventDispatcher();
140        $userInfoDispatcher = UserInfo::getEventDispatcher();
141        UserInfo::unsetEventDispatcher();
142        $userDispatcher = User::getEventDispatcher();
143        User::unsetEventDispatcher();
144        $dailyDispatcher = FlyMsgUserDailyUsage::getEventDispatcher();
145        FlyMsgUserDailyUsage::unsetEventDispatcher();
146        $flyCutDispatcher = FlyCutUsage::getEventDispatcher();
147        FlyCutUsage::unsetEventDispatcher();
148
149        foreach ($results as $userInfo) {
150            try {
151                if ($userInfo['free'] === "Active") {
152                    $subscriptionService = new SubscriptionService();
153
154                    $carbonDate = Carbon::parse($userInfo['end_free']);
155
156                    $data = $subscriptionService->endFreemiumSubscription($userInfo['user_id'], $carbonDate);
157
158                    $user = UserInfo::where('user_id', $userInfo['user_id'])->first();
159
160                    $user->update($data);
161
162                    $this->userInfoService->pushItToHubspot($user->user_id, false);
163                }
164            } catch (\Exception $e) {
165                $this->error("Failed to process flyCutUsage {$userInfo->email}" . $e->getMessage());
166                $failed_users_count++;
167            }
168
169            $totalFlyCutUsage--;
170            $this->output->write("\rRemaining flyCut Usage: " . $totalFlyCutUsage . " | Percentage: " . round(($totalFlyCutUsage / count($results)) * 100, 2) . "%", false);
171        }
172        $this->output->writeln('');
173
174        if ($shortcutDispatcher) {
175            Shortcut::setEventDispatcher($shortcutDispatcher);
176        }
177        if ($userInfoDispatcher) {
178            UserInfo::setEventDispatcher($userInfoDispatcher);
179        }
180        if ($userDispatcher) {
181            User::setEventDispatcher($userDispatcher);
182        }
183        if ($dailyDispatcher) {
184            FlyMsgUserDailyUsage::setEventDispatcher($dailyDispatcher);
185        }
186        if ($flyCutDispatcher) {
187            FlyCutUsage::setEventDispatcher($flyCutDispatcher);
188        }
189
190        $totalDurationInMinutes = now()->diffInMinutes($totalTimeStartAt);
191        $totalDurationInSeconds = now()->diffInSeconds($totalTimeStartAt);
192
193        $total = count($results);
194        $this->info("fixDuplicates completed");
195        $this->info("Total items processed: {$total}");
196        $this->info("Total duration in minutes: {$totalDurationInMinutes}");
197        $this->info("Total duration in seconds: {$totalDurationInSeconds}");
198        $this->info("Failed Count: {$failed_users_count}");
199    }
200
201    private function fixShortcuts()
202    {
203        $perPage = $this->argument('perPage');
204        $page = $this->argument('page');
205
206        $this->info("fixShortcuts started");
207        $totalTimeStartAt = now();
208
209        ini_set('memory_limit', '-1');
210
211        $failed_users_count = 0;
212
213        // test $userIds = User::whereIsNotNull('company_id')->pluck('id')->toArray();
214
215        $shortcuts = Shortcut::where('fix_user_group', null)
216            ->skip(($page - 1) * $perPage)
217            ->take($perPage)
218            ->get();
219
220        $totalFlyCutUsage = count($shortcuts);
221        $this->info("Processing " . $totalFlyCutUsage . " users");
222
223        $shortcutDispatcher = Shortcut::getEventDispatcher();
224        Shortcut::unsetEventDispatcher();
225        $userInfoDispatcher = UserInfo::getEventDispatcher();
226        UserInfo::unsetEventDispatcher();
227        $userDispatcher = User::getEventDispatcher();
228        User::unsetEventDispatcher();
229        $dailyDispatcher = FlyMsgUserDailyUsage::getEventDispatcher();
230        FlyMsgUserDailyUsage::unsetEventDispatcher();
231        $flyCutDispatcher = FlyCutUsage::getEventDispatcher();
232        FlyCutUsage::unsetEventDispatcher();
233
234        foreach ($shortcuts as $shortcut) {
235            try {
236                $shortcut->html_backup = $shortcut->html;
237                $shortcut->html = $this->cleanShortcutHtml($shortcut->html);
238                $shortcut->text_backup = $shortcut->text;
239                $shortcut->text = $this->cleanShortcutHtml($shortcut->text);
240                $shortcut->fix_user_group = true;
241                $shortcut->save();
242            } catch (\Exception $e) {
243                $this->error("Failed to process flyCutUsage {$shortcut->id}" . $e->getMessage());
244                $failed_users_count++;
245            }
246
247            $totalFlyCutUsage--;
248            $this->output->write("\rRemaining flyCut Usage: " . $totalFlyCutUsage . " | Percentage: " . round(($totalFlyCutUsage / count($shortcuts)) * 100, 2) . "%", false);
249        }
250        $this->output->writeln('');
251
252        if ($shortcutDispatcher) {
253            Shortcut::setEventDispatcher($shortcutDispatcher);
254        }
255        if ($userInfoDispatcher) {
256            UserInfo::setEventDispatcher($userInfoDispatcher);
257        }
258        if ($userDispatcher) {
259            User::setEventDispatcher($userDispatcher);
260        }
261        if ($dailyDispatcher) {
262            FlyMsgUserDailyUsage::setEventDispatcher($dailyDispatcher);
263        }
264        if ($flyCutDispatcher) {
265            FlyCutUsage::setEventDispatcher($flyCutDispatcher);
266        }
267
268        $totalDurationInMinutes = now()->diffInMinutes($totalTimeStartAt);
269        $totalDurationInSeconds = now()->diffInSeconds($totalTimeStartAt);
270
271        $total = count($shortcuts);
272        $this->info("fixShortcuts completed");
273        $this->info("Total items processed: {$total}");
274        $this->info("Total duration in minutes: {$totalDurationInMinutes}");
275        $this->info("Total duration in seconds: {$totalDurationInSeconds}");
276        $this->info("Failed Count: {$failed_users_count}");
277    }
278
279    private function fixDaily()
280    {
281        $perPage = $this->argument('perPage');
282        $page = $this->argument('page');
283
284        $this->info("fixDaily started");
285        $totalTimeStartAt = now();
286
287        ini_set('memory_limit', '-1');
288
289        $failed_users_count = 0;
290
291        // test $userIds = User::whereIsNotNull('company_id')->pluck('id')->toArray();
292
293        $users = User::where('fix_user_group', null)
294            ->where('company_id', '!=', null)
295            ->skip(($page - 1) * $perPage)
296            ->take($perPage)
297            ->get();
298
299        $totalFlyCutUsage = count($users);
300        $this->info("Processing " . $totalFlyCutUsage . " users");
301
302        $userInfoDispatcher = UserInfo::getEventDispatcher();
303        UserInfo::unsetEventDispatcher();
304        $userDispatcher = User::getEventDispatcher();
305        User::unsetEventDispatcher();
306        $dailyDispatcher = FlyMsgUserDailyUsage::getEventDispatcher();
307        FlyMsgUserDailyUsage::unsetEventDispatcher();
308        $flyCutDispatcher = FlyCutUsage::getEventDispatcher();
309        FlyCutUsage::unsetEventDispatcher();
310
311        foreach ($users as $user) {
312            try {
313                $userInfo = UserInfo::where('user_id', $user->id)->first();
314
315                $group = CompanyGroup::where('id', $userInfo->group_id)->first();
316                if ($group) {
317                    $parentGroup = CompanyGroup::where('id', $group->parent_id)->first();
318
319                    if ($parentGroup) {
320                        $userInfo->subgroup_id = $group->id;
321                        $userInfo->subgroup_name = $group->name;
322
323                        $userInfo->group_id = $parentGroup->id;
324                        $userInfo->group_name = $parentGroup->name;
325                    } else {
326                        $userInfo->group_id = $group->id;
327                        $userInfo->group_name = $group->name;
328                    }
329
330                    $userInfo->save();
331                } else {
332
333                    UserInfo::where('user_id', $user->id)
334                        ->update([
335                            '$unset' => [
336                                'group_id' => 1,
337                                'group_name' => 1,
338                                'subgroup_id' => 1,
339                                'subgroup_name' => 1,
340                            ]
341                        ]);
342                }
343
344                $user->fix_user_group = true;
345                $user->save();
346            } catch (\Exception $e) {
347                $this->error("Failed to process flyCutUsage {$user->user_id}" . $e->getMessage());
348                $failed_users_count++;
349            }
350
351            $totalFlyCutUsage--;
352            $this->output->write("\rRemaining flyCut Usage: " . $totalFlyCutUsage . " | Percentage: " . round(($totalFlyCutUsage / count($users)) * 100, 2) . "%", false);
353        }
354        $this->output->writeln('');
355
356        if ($userInfoDispatcher) {
357            UserInfo::setEventDispatcher($userInfoDispatcher);
358        }
359        if ($userDispatcher) {
360            User::setEventDispatcher($userDispatcher);
361        }
362        if ($dailyDispatcher) {
363            FlyMsgUserDailyUsage::setEventDispatcher($dailyDispatcher);
364        }
365        if ($flyCutDispatcher) {
366            FlyCutUsage::setEventDispatcher($flyCutDispatcher);
367        }
368
369        $totalDurationInMinutes = now()->diffInMinutes($totalTimeStartAt);
370        $totalDurationInSeconds = now()->diffInSeconds($totalTimeStartAt);
371
372        $total = count($users);
373        $this->info("fixDaily completed");
374        $this->info("Total items processed: {$total}");
375        $this->info("Total duration in minutes: {$totalDurationInMinutes}");
376        $this->info("Total duration in seconds: {$totalDurationInSeconds}");
377        $this->info("Failed Count: {$failed_users_count}");
378    }
379
380    private function fixWagePerHour()
381    {
382        $this->info("fixWagePerHour started");
383        $totalTimeStartAt = now();
384
385        ini_set('memory_limit', '-1');
386
387        $failed_users_count = 0;
388
389        // test $userIds = User::whereIsNotNull('company_id')->pluck('id')->toArray();
390
391        $flyCutUsages = FlyCutUsage::where('recalculated_wage_per_hour', null)->get();
392
393        $totalFlyCutUsage = count($flyCutUsages);
394        $this->info("Processing " . $totalFlyCutUsage . " fly cut usage");
395
396        $userInfoDispatcher = UserInfo::getEventDispatcher();
397        UserInfo::unsetEventDispatcher();
398        $userDispatcher = User::getEventDispatcher();
399        User::unsetEventDispatcher();
400        $dailyDispatcher = FlyMsgUserDailyUsage::getEventDispatcher();
401        FlyMsgUserDailyUsage::unsetEventDispatcher();
402        $flyCutDispatcher = FlyCutUsage::getEventDispatcher();
403        FlyCutUsage::unsetEventDispatcher();
404
405        foreach ($flyCutUsages as $flyCutUsage) {
406            try {
407                $user = User::withTrashed()->find($flyCutUsage->user_id);
408                if ($user) {
409                    $timeSaved = $this->statisticsService->getTimeSaved($user, $flyCutUsage->characters_saved);
410                    $carbonDate = Carbon::createFromFormat('Y-m-d H:i:s', $flyCutUsage->created_at);
411                    $costSaved = $this->statisticsService->getCostSaved($user, $timeSaved, $carbonDate);
412                    $flyCutUsage->time_saved = $timeSaved;
413                    $flyCutUsage->cost_saved = $costSaved;
414                    $flyCutUsage->recalculated_wage_per_hour = true;
415                    $flyCutUsage->save();
416                }
417            } catch (\Exception $e) {
418                $this->error("Failed to process flyCutUsage {$flyCutUsage->user_id}" . $e->getMessage());
419                $failed_users_count++;
420            }
421
422            $totalFlyCutUsage--;
423            $this->output->write("\rRemaining flyCut Usage: " . $totalFlyCutUsage . " | Percentage: " . round(($totalFlyCutUsage / count($flyCutUsages)) * 100, 2) . "%", false);
424        }
425        $this->output->writeln('');
426
427        if ($userInfoDispatcher) {
428            UserInfo::setEventDispatcher($userInfoDispatcher);
429        }
430        if ($userDispatcher) {
431            User::setEventDispatcher($userDispatcher);
432        }
433        if ($dailyDispatcher) {
434            FlyMsgUserDailyUsage::setEventDispatcher($dailyDispatcher);
435        }
436        if ($flyCutDispatcher) {
437            FlyCutUsage::setEventDispatcher($flyCutDispatcher);
438        }
439
440        $totalDurationInMinutes = now()->diffInMinutes($totalTimeStartAt);
441        $totalDurationInSeconds = now()->diffInSeconds($totalTimeStartAt);
442
443        $total = count($flyCutUsages);
444        $this->info("fixWagePerHour completed");
445        $this->info("Total items processed: {$total}");
446        $this->info("Total duration in minutes: {$totalDurationInMinutes}");
447        $this->info("Total duration in seconds: {$totalDurationInSeconds}");
448        $this->info("Failed Count: {$failed_users_count}");
449    }
450
451    private function fixPlans()
452    {
453        $this->info("fixPlans started");
454        $totalTimeStartAt = now();
455
456        ini_set('memory_limit', '-1');
457
458        $failed_users = [];
459        $failed_users_count = 0;
460        $added_users_count = 0;
461
462        $subscriptions = Subscription::where('jon_fix_trial_plans', null)->get();
463
464        $totalSubs = count($subscriptions);
465        $this->info("Processing " . $totalSubs . " users");
466
467        $userInfoDispatcher = UserInfo::getEventDispatcher();
468        UserInfo::unsetEventDispatcher();
469        $userDispatcher = User::getEventDispatcher();
470        User::unsetEventDispatcher();
471        $dailyDispatcher = FlyMsgUserDailyUsage::getEventDispatcher();
472        FlyMsgUserDailyUsage::unsetEventDispatcher();
473        $subscriptionService = new SubscriptionService();
474
475        foreach ($subscriptions as $sub) {
476            $userStarted = now();
477            try {
478                $user_info = UserInfo::where('user_id', $sub->user_id)->first();
479                if (!$user_info) {
480                    continue;
481                }
482
483                $fields = $sub->toArray();
484                $result = $subscriptionService->endSubscription($fields, $sub, false, $sub->ends_at);
485                $user_info->fill($result);
486                $fields = $sub->toArray();
487                $result = $subscriptionService->startSubscription($fields, $sub);
488                $user_info->fill($result);
489                $haveActiveSubscription = Subscription::where('user_id', $sub->user_id)->where('stripe_status', 'active')->count() > 0;
490                if (!$haveActiveSubscription) {
491                    $user_info->fill($subscriptionService->initFreemiumSubscription($sub->user_id));
492                }
493
494                $user_info->save();
495                $sub->jon_fix_trial_plans = true;
496                $sub->save();
497                $this->userInfoService->pushItToHubspot($sub->user_id, false);
498                $added_users_count++;
499            } catch (\Exception $e) {
500                $this->error("Failed to process subscription {$sub->stripe_plan}" . $e->getMessage());
501                $failed_users[] = [
502                    'user_id' => $sub->stripe_plan,
503                    'email' => $sub->user_id,
504                    'error' => $e->getMessage(),
505                ];
506                $failed_users_count++;
507            }
508
509            $durationInMilliseconds = now()->diffInMilliseconds($userStarted);
510
511            // if short than 150 milliseconds, sleep until 150 milliseconds
512            if ($durationInMilliseconds < 150) {
513                usleep(150000 - $durationInMilliseconds);
514            }
515
516            $totalSubs--;
517            $this->output->write("\rRemaining subscriptions: " . $totalSubs . " | Percentage: " . round(($totalSubs / count($subscriptions)) * 100, 2) . "%", false);
518        }
519        $this->output->writeln('');
520
521        if ($userInfoDispatcher) {
522            UserInfo::setEventDispatcher($userInfoDispatcher);
523        }
524        if ($userDispatcher) {
525            User::setEventDispatcher($userDispatcher);
526        }
527        if ($dailyDispatcher) {
528            FlyMsgUserDailyUsage::setEventDispatcher($dailyDispatcher);
529        }
530
531        $totalDurationInMinutes = now()->diffInMinutes($totalTimeStartAt);
532        $totalDurationInSeconds = now()->diffInSeconds($totalTimeStartAt);
533
534        Log::info("fixPlans completed", [
535            'completed_subscriptions_count' => $added_users_count,
536            'total_duration_in_minutes' => $totalDurationInMinutes,
537            'total_duration_in_seconds' => $totalDurationInSeconds,
538            'failed_subs_count' => $failed_users_count,
539            'failed_subs' => $failed_users,
540        ]);
541
542        $this->info("fixPlans completed");
543        $this->info("Total duration in minutes: {$totalDurationInMinutes}");
544        $this->info("Total duration in seconds: {$totalDurationInSeconds}");
545        $this->info("Completed subs: {$added_users_count}");
546        $this->info("Failed subs: {$failed_users_count}");
547    }
548
549    private function fixCorporateUsersOnHubspot()
550    {
551        $this->info("fixCorporateUsersOnHubspot started");
552        $totalTimeStartAt = now();
553
554        ini_set('memory_limit', '-1');
555
556        $failed_users = [];
557        $failed_users_count = 0;
558        $added_users_count = 0;
559
560        $users = User::where('company_id', '!=', null)->where('mago_reprocess', null)->get();
561
562        $totalUsers = count($users);
563        $this->info("Processing " . $totalUsers . " users");
564
565        $userInfoDispatcher = UserInfo::getEventDispatcher();
566        UserInfo::unsetEventDispatcher();
567        $userDispatcher = User::getEventDispatcher();
568        User::unsetEventDispatcher();
569        $dailyDispatcher = FlyMsgUserDailyUsage::getEventDispatcher();
570        FlyMsgUserDailyUsage::unsetEventDispatcher();
571        $subscriptionService = new SubscriptionService();
572
573        foreach ($users as $user) {
574            $userStarted = now();
575            try {
576                $user_info = UserInfo::where('user_id', $user->id)->first();
577
578                #region Licenses
579                #region Inactive Subscriptions
580                $inactiveSubscriptions = Subscription::where('user_id', $user->id)
581                    ->where('stripe_status', '!=', 'active')
582                    ->orderBy('created_at', 'asc')
583                    ->get();
584                foreach ($inactiveSubscriptions as $subscription) {
585                    $fields = $subscription->toArray();
586                    $result = $subscriptionService->endSubscription($fields, $subscription);
587                    $user_info->fill($result);
588                }
589                #endregion
590
591                #region Active Subscriptions
592                $activeSubscriptions = Subscription::where('user_id', $user->id)
593                    ->where('stripe_status', 'active')
594                    ->orderBy('created_at', 'asc')
595                    ->get();
596
597                $haveActiveSubscription = false;
598
599                foreach ($activeSubscriptions as $subscription) {
600                    $fields = $subscription->toArray();
601                    $result = $subscriptionService->startSubscription($fields, $subscription);
602                    $user_info->fill($result);
603                    $haveActiveSubscription = true;
604                }
605
606                if (!$haveActiveSubscription) {
607                    $user_info->fill($subscriptionService->initFreemiumSubscription($user->id));
608                }
609                #endregion
610                #endregion
611                if (empty($user->signup_source)) {
612                    $user->signup_source = $user_info->signup_source ?? $user_info->signin_source;
613                }
614                $user_info->signup_source = $user->signup_source;
615                $user_info->save();
616                $user->mago_reprocess = true;
617                $user->save();
618                $this->userInfoService->pushItToHubspot($user->id, false);
619                $added_users_count++;
620            } catch (\Exception $e) {
621                $this->error("Failed to process user {$user->email}" . $e->getMessage());
622                $failed_users[] = [
623                    'user_id' => $user->id,
624                    'email' => $user->email,
625                    'error' => $e->getMessage(),
626                ];
627                $failed_users_count++;
628            }
629
630            $durationInMilliseconds = now()->diffInMilliseconds($userStarted);
631
632            // if short than 150 milliseconds, sleep until 150 milliseconds
633            if ($durationInMilliseconds < 150) {
634                usleep(150000 - $durationInMilliseconds);
635            }
636
637            $totalUsers--;
638            $this->output->write("\rRemaining users: " . $totalUsers . " | Percentage: " . round(($totalUsers / count($users)) * 100, 2) . "%", false);
639        }
640        $this->output->writeln('');
641
642        if ($userInfoDispatcher) {
643            UserInfo::setEventDispatcher($userInfoDispatcher);
644        }
645        if ($userDispatcher) {
646            User::setEventDispatcher($userDispatcher);
647        }
648        if ($dailyDispatcher) {
649            FlyMsgUserDailyUsage::setEventDispatcher($dailyDispatcher);
650        }
651
652        $totalDurationInMinutes = now()->diffInMinutes($totalTimeStartAt);
653        $totalDurationInSeconds = now()->diffInSeconds($totalTimeStartAt);
654
655        Log::info("fixCorporateUsersOnHubspot completed", [
656            'completed_users_count' => $added_users_count,
657            'total_duration_in_minutes' => $totalDurationInMinutes,
658            'total_duration_in_seconds' => $totalDurationInSeconds,
659            'failed_users_count' => $failed_users_count,
660            'failed_users' => $failed_users,
661        ]);
662
663        $this->info("fixCorporateUsersOnHubspot completed");
664        $this->info("Total duration in minutes: {$totalDurationInMinutes}");
665        $this->info("Total duration in seconds: {$totalDurationInSeconds}");
666        $this->info("Completed users: {$added_users_count}");
667        $this->info("Failed users: {$failed_users_count}");
668    }
669
670    private function fixEnterpriseUsersEndDate()
671    {
672        $this->info("fixEnterpriseUsersEndDate started");
673        $totalTimeStartAt = now();
674
675        ini_set('memory_limit', '-1');
676
677        $failed_users = [];
678        $failed_users_count = 0;
679        $added_users_count = 0;
680
681        //$users = User::whereNotNull('company_id')->get();
682        $users = User::whereNotNull('company_id')->where('company_id', '67eb1de57b3e7140cc045567')->get();
683
684        $totalUsers = count($users);
685        $this->info("Processing " . $totalUsers . " users");
686
687        $userInfoDispatcher = UserInfo::getEventDispatcher();
688        UserInfo::unsetEventDispatcher();
689        $userDispatcher = User::getEventDispatcher();
690        User::unsetEventDispatcher();
691        $dailyDispatcher = FlyMsgUserDailyUsage::getEventDispatcher();
692        FlyMsgUserDailyUsage::unsetEventDispatcher();
693
694        $instancyService = new InstancyServiceV2();
695        foreach ($users as $user) {
696            $userStarted = now();
697            try {
698                $company = Company::find($user->company_id);
699                $companyLicense = CompanyLicenses::where('company_id', $company->id)->first();
700                $endDate = Carbon::parse($companyLicense->contract_end_date); //contract_end_date
701
702                $subscription = Subscription::where('user_id', $user->id)->where('stripe_status', 'active')->first();
703                if ($subscription) {
704                    $subscription->ends_at = new UTCDateTime($endDate->getTimestamp() * 1000);
705                    $subscription->save();
706
707                    $plan = Plans::where('stripe_id', $subscription->stripe_plan)->first();
708
709                    if (Str::contains($plan->identifier, 'pro')) {
710                        $instancyService->updateMembership($user->email, $endDate->subDay()->toDateString());
711                    }
712                }
713
714                $added_users_count++;
715            } catch (\Exception $e) {
716                $this->error("Failed to process user {$user->email}" . $e->getMessage());
717                $failed_users[] = [
718                    'user_id' => $user->id,
719                    'email' => $user->email,
720                    'error' => $e->getMessage(),
721                ];
722                $failed_users_count++;
723            }
724
725            $durationInMilliseconds = now()->diffInMilliseconds($userStarted);
726
727            // if short than 150 milliseconds, sleep until 150 milliseconds
728            if ($durationInMilliseconds < 150) {
729                usleep(150000 - $durationInMilliseconds);
730            }
731
732            $totalUsers--;
733            $this->output->write("\rRemaining users: " . $totalUsers . " | Percentage: " . round(($totalUsers / count($users)) * 100, 2) . "%", false);
734        }
735        $this->output->writeln('');
736
737        if ($userInfoDispatcher) {
738            UserInfo::setEventDispatcher($userInfoDispatcher);
739        }
740        if ($userDispatcher) {
741            User::setEventDispatcher($userDispatcher);
742        }
743        if ($dailyDispatcher) {
744            FlyMsgUserDailyUsage::setEventDispatcher($dailyDispatcher);
745        }
746
747        $totalDurationInMinutes = now()->diffInMinutes($totalTimeStartAt);
748        $totalDurationInSeconds = now()->diffInSeconds($totalTimeStartAt);
749
750        Log::info("fixUserEmailDomainCount completed", [
751            'completed_users_count' => $added_users_count,
752            'total_duration_in_minutes' => $totalDurationInMinutes,
753            'total_duration_in_seconds' => $totalDurationInSeconds,
754            'failed_users_count' => $failed_users_count,
755            'failed_users' => $failed_users,
756        ]);
757
758        $this->info("fixEnterpriseUsersEndDate completed");
759        $this->info("Total duration in minutes: {$totalDurationInMinutes}");
760        $this->info("Total duration in seconds: {$totalDurationInSeconds}");
761        $this->info("Completed users: {$added_users_count}");
762        $this->info("Failed users: {$failed_users_count}");
763    }
764
765    private function fixDeleteUsers()
766    {
767        $this->info("fixDeleteUsers started");
768        $totalTimeStartAt = now();
769
770        ini_set('memory_limit', '-1');
771
772        $failed_users = [];
773        $failed_users_count = 0;
774        $added_users_count = 0;
775
776        $users = User::withTrashed()->whereNotNull('deleted_at')->get();
777
778        $totalUsers = count($users);
779        $this->info("Processing " . $totalUsers . " users");
780
781        $userInfoDispatcher = UserInfo::getEventDispatcher();
782        UserInfo::unsetEventDispatcher();
783        $userDispatcher = User::getEventDispatcher();
784        User::unsetEventDispatcher();
785        $dailyDispatcher = FlyMsgUserDailyUsage::getEventDispatcher();
786        FlyMsgUserDailyUsage::unsetEventDispatcher();
787
788        foreach ($users as $user) {
789            $userStarted = now();
790            try {
791                $cancellation_date = new UTCDateTime($user->deleted_at->getTimestamp() * 1000);
792
793                $userInfo = UserInfo::where('user_id', $user->id)->first();
794
795                if (!$userInfo || !empty($userInfo->deleted_at) || empty($user->hubspot_id)) {
796                    continue;
797                }
798
799                (new HubspotServiceV2())->updateHubspotOptOutProperty($user->email);
800
801                // if not includes delete_from_flymsg_ then add it
802                $delete_from_flymsg_email = $user->email;
803                if (strpos($user->email, 'delete_from_flymsg_') === false) {
804                    $delete_from_flymsg_email = "delete_from_flymsg_$user->email";
805                }
806                $data = [
807                    'deleted_at' => $cancellation_date,
808                    'status' => 'Delete',
809                    'subscription_type' => 'Deleted Profile from FlyMSG',
810                    'email' => $delete_from_flymsg_email,
811                    'first_name' => "",
812                    'last_name' => "",
813                    'full_name' => "",
814                    'email_used_for_login' => "",
815                    'avatar' => "",
816                    'job_role' => "",
817                    'department' => "",
818                    'company' => ""
819                ];
820
821                $subscriptionService = new SubscriptionService();
822
823                $endFreemiumData = $subscriptionService->endFreemiumSubscription($user->id, $user->deleted_at);
824
825                $data = array_merge($data, $endFreemiumData);
826
827                $userInfo->update($data);
828
829                //////////
830
831                $user->save();
832                $this->userInfoService->pushItToHubspot($user->id, false);
833                $added_users_count++;
834            } catch (\Exception $e) {
835                $this->error("Failed to process user {$user->email}" . $e->getMessage());
836                $failed_users[] = [
837                    'user_id' => $user->id,
838                    'email' => $user->email,
839                    'error' => $e->getMessage(),
840                ];
841                $failed_users_count++;
842            }
843
844            $durationInMilliseconds = now()->diffInMilliseconds($userStarted);
845
846            // if short than 150 milliseconds, sleep until 150 milliseconds
847            if ($durationInMilliseconds < 150) {
848                usleep(150000 - $durationInMilliseconds);
849            }
850
851            $totalUsers--;
852            $this->output->write("\rRemaining users: " . $totalUsers . " | Percentage: " . round(($totalUsers / count($users)) * 100, 2) . "%", false);
853        }
854        $this->output->writeln('');
855
856        if ($userInfoDispatcher) {
857            UserInfo::setEventDispatcher($userInfoDispatcher);
858        }
859        if ($userDispatcher) {
860            User::setEventDispatcher($userDispatcher);
861        }
862        if ($dailyDispatcher) {
863            FlyMsgUserDailyUsage::setEventDispatcher($dailyDispatcher);
864        }
865
866        $totalDurationInMinutes = now()->diffInMinutes($totalTimeStartAt);
867        $totalDurationInSeconds = now()->diffInSeconds($totalTimeStartAt);
868
869        Log::info("fixUserEmailDomainCount completed", [
870            'completed_users_count' => $added_users_count,
871            'total_duration_in_minutes' => $totalDurationInMinutes,
872            'total_duration_in_seconds' => $totalDurationInSeconds,
873            'failed_users_count' => $failed_users_count,
874            'failed_users' => $failed_users,
875        ]);
876
877        $this->info("fixUserEmailDomainCount completed");
878        $this->info("Total duration in minutes: {$totalDurationInMinutes}");
879        $this->info("Total duration in seconds: {$totalDurationInSeconds}");
880        $this->info("Completed users: {$added_users_count}");
881        $this->info("Failed users: {$failed_users_count}");
882    }
883
884    private function fixPricing()
885    {
886        $this->info("fixPricing started");
887        $totalTimeStartAt = now();
888
889        ini_set('memory_limit', '-1');
890
891        $failed_users = [];
892        $failed_users_count = 0;
893        $added_users_count = 0;
894
895        $users = UserInfo::where('mago_fixing_prices', null)->get();
896        // $users = UserInfo::where('email', 'steve@executivesalescoaching.com.au')->get();
897
898        $totalUsers = count($users);
899        $this->info("Processing " . $totalUsers . " users");
900
901        $userInfoDispatcher = UserInfo::getEventDispatcher();
902        UserInfo::unsetEventDispatcher();
903        $userDispatcher = User::getEventDispatcher();
904        User::unsetEventDispatcher();
905        $dailyDispatcher = FlyMsgUserDailyUsage::getEventDispatcher();
906        FlyMsgUserDailyUsage::unsetEventDispatcher();
907
908        foreach ($users as $user) {
909            $userStarted = now();
910            try {
911                $hubspotProperties = HubspotProperties::where('flymsg_id', $user->user_id)->first();
912                $result = [];
913
914                #region Inactive Subscriptions
915                $inactiveSubscriptions = Subscription::where('user_id', $user->user_id)
916                    ->where('stripe_status', '!=', 'active')
917                    ->orderBy('created_at', 'asc')
918                    ->get();
919                foreach ($inactiveSubscriptions as $subscription) {
920                    $plan = Plans::where('stripe_id', $subscription->stripe_plan)->first();
921
922                    if (!empty($hubspotProperties) && !empty($hubspotProperties[$plan->hubspot_subscription_monthly_recurring_revenue])) {
923                        $result[$plan->hubspot_subscription_monthly_recurring_revenue] = $hubspotProperties[$plan->hubspot_subscription_monthly_recurring_revenue];
924                    }
925                }
926                #endregion
927
928                #region Active Subscriptions
929                $activeSubscriptions = Subscription::where('user_id', $user->user_id)
930                    ->where('stripe_status', 'active')
931                    ->orderBy('created_at', 'asc')
932                    ->get();
933
934                foreach ($activeSubscriptions as $subscription) {
935                    $useruser = User::find($user->user_id);
936
937                    $trialEndsAt = $subscription->trial_ends_at;
938                    $invoices = $useruser->invoices()->toArray();
939                    $invoices = array_reverse($invoices);
940                    $plan = Plans::where('stripe_id', $subscription->stripe_plan)->first();
941
942                    // Two  diffrent plans handle
943                    foreach ($invoices as $i => $invoice) {
944                        $invoiceDataIndex = $invoice['lines']['total_count'] > 0 ? $invoice['lines']['total_count'] - 1 : 0;
945                        if (empty($invoice['lines']['data'][$invoiceDataIndex]['subscription']) && $invoice['billing_reason'] == 'manual') {
946                            $this->info("No subscription is associated with invoice id: {$invoice['id']}");
947                            continue;
948                        }
949
950                        $interval = $invoice['lines']['data'][$invoiceDataIndex]['plan']['interval'];
951
952                        $price = $invoice['lines']['data'][$invoiceDataIndex]['price']['unit_amount_decimal'] / 100;
953
954                        if ($interval == "month") {
955                            $interval = 'Monthly';
956                            $annual_recurring_revenue = $price * 12;
957                            $monthly_recurring_revenue = $price;
958                        } else {
959                            $interval = 'Annual';
960                            $annual_recurring_revenue = $price;
961                            $monthly_recurring_revenue = $price / 12;
962                        }
963
964                        if (isset($plan->identifier) && $plan->identifier == 'sales-pro-monthly' && isset($trialEndsAt)) {
965                            $annual_recurring_revenue = 0;
966                            $monthly_recurring_revenue = 0;
967                        }
968                    }
969
970                    $result[$plan->hubspot_subscription_monthly_recurring_revenue] = $monthly_recurring_revenue;
971                    $result[$plan->hubspot_subscription_annual_recurring_revenue] = $annual_recurring_revenue;
972
973                    if ($plan->identifier == 'appsumo-growth-lifetime') {
974                        $result['flymsg_growth_subscription_monthly_recurring_revenue'] = 4;
975                        $result['growth_subscription_annual_recurring_revenue'] = 48;
976                    }
977
978                    $user->fill($result);
979                }
980                #endregion
981
982                $user->save();
983                $this->userInfoService->pushItToHubspot($user->user_id, false);
984                $user->mago_fixing_prices = true;
985                $user->save();
986                $added_users_count++;
987            } catch (\Exception $e) {
988                $this->error("Failed to process user {$user->email}" . $e->getMessage());
989                $failed_users[] = [
990                    'user_id' => $user->id,
991                    'email' => $user->email,
992                    'error' => $e->getMessage(),
993                ];
994                $failed_users_count++;
995            }
996
997            $durationInMilliseconds = now()->diffInMilliseconds($userStarted);
998
999            // if short than 150 milliseconds, sleep until 150 milliseconds
1000            if ($durationInMilliseconds < 150) {
1001                usleep(150000 - $durationInMilliseconds);
1002            }
1003
1004            $totalUsers--;
1005            $this->output->write("\rRemaining users: " . $totalUsers . " | Percentage: " . round(($totalUsers / count($users)) * 100, 2) . "%", false);
1006        }
1007        $this->output->writeln('');
1008
1009        if ($userInfoDispatcher) {
1010            UserInfo::setEventDispatcher($userInfoDispatcher);
1011        }
1012        if ($userDispatcher) {
1013            User::setEventDispatcher($userDispatcher);
1014        }
1015        if ($dailyDispatcher) {
1016            FlyMsgUserDailyUsage::setEventDispatcher($dailyDispatcher);
1017        }
1018
1019        $totalDurationInMinutes = now()->diffInMinutes($totalTimeStartAt);
1020        $totalDurationInSeconds = now()->diffInSeconds($totalTimeStartAt);
1021
1022        Log::info("fixUserEmailDomainCount completed", [
1023            'completed_users_count' => $added_users_count,
1024            'total_duration_in_minutes' => $totalDurationInMinutes,
1025            'total_duration_in_seconds' => $totalDurationInSeconds,
1026            'failed_users_count' => $failed_users_count,
1027            'failed_users' => $failed_users,
1028        ]);
1029
1030        $this->info("fixUserEmailDomainCount completed");
1031        $this->info("Total duration in minutes: {$totalDurationInMinutes}");
1032        $this->info("Total duration in seconds: {$totalDurationInSeconds}");
1033        $this->info("Completed users: {$added_users_count}");
1034        $this->info("Failed users: {$failed_users_count}");
1035    }
1036
1037    private function fixAppsumoLifePlan()
1038    {
1039        $this->info("fixUserEmailDomainCount started");
1040        $totalTimeStartAt = now();
1041
1042        ini_set('memory_limit', '-1');
1043
1044        $failed_users = [];
1045        $failed_users_count = 0;
1046        $added_users_count = 0;
1047
1048        $users = UserInfo::where('plan_name', 'Growth Lifetime Access Plan - AppSumo')->get();
1049
1050        $totalUsers = count($users);
1051        $this->info("Processing " . $totalUsers . " users");
1052
1053        $userInfoDispatcher = UserInfo::getEventDispatcher();
1054        UserInfo::unsetEventDispatcher();
1055        $userDispatcher = User::getEventDispatcher();
1056        User::unsetEventDispatcher();
1057        $dailyDispatcher = FlyMsgUserDailyUsage::getEventDispatcher();
1058        FlyMsgUserDailyUsage::unsetEventDispatcher();
1059
1060
1061        foreach ($users as $user) {
1062            try {
1063                $user->appsumo_flymsg_lifetime_access = 'true';
1064                // $user['flymsg_growth_subscription_monthly_recurring_revenue'] = 4;
1065                // $user['growth_subscription_annual_recurring_revenue'] = 48;
1066                $user->save();
1067                $this->userInfoService->pushItToHubspot($user->user_id, false);
1068                $added_users_count++;
1069            } catch (\Exception $e) {
1070                $this->error("Failed to process user {$user->email}" . $e->getMessage());
1071                $failed_users[] = [
1072                    'user_id' => $user->id,
1073                    'email' => $user->email,
1074                    'error' => $e->getMessage(),
1075                ];
1076                $failed_users_count++;
1077            }
1078
1079            $totalUsers--;
1080            $this->output->write("\rRemaining users: " . $totalUsers . " | Percentage: " . round(($totalUsers / count($users)) * 100, 2) . "%", false);
1081        }
1082        $this->output->writeln('');
1083
1084        if ($userInfoDispatcher) {
1085            UserInfo::setEventDispatcher($userInfoDispatcher);
1086        }
1087        if ($userDispatcher) {
1088            User::setEventDispatcher($userDispatcher);
1089        }
1090        if ($dailyDispatcher) {
1091            FlyMsgUserDailyUsage::setEventDispatcher($dailyDispatcher);
1092        }
1093
1094        $totalDurationInMinutes = now()->diffInMinutes($totalTimeStartAt);
1095        $totalDurationInSeconds = now()->diffInSeconds($totalTimeStartAt);
1096
1097        Log::info("fixUserEmailDomainCount completed", [
1098            'completed_users_count' => $added_users_count,
1099            'total_duration_in_minutes' => $totalDurationInMinutes,
1100            'total_duration_in_seconds' => $totalDurationInSeconds,
1101            'failed_users_count' => $failed_users_count,
1102            'failed_users' => $failed_users,
1103        ]);
1104
1105        $this->info("fixUserEmailDomainCount completed");
1106        $this->info("Total duration in minutes: {$totalDurationInMinutes}");
1107        $this->info("Total duration in seconds: {$totalDurationInSeconds}");
1108        $this->info("Completed users: {$added_users_count}");
1109        $this->info("Failed users: {$failed_users_count}");
1110    }
1111
1112    private function fixUserEmailDomainCount()
1113    {
1114        $this->info("fixUserEmailDomainCount started");
1115        $totalTimeStartAt = now();
1116
1117        ini_set('memory_limit', '-1');
1118
1119        $failed_users = [];
1120        $failed_users_count = 0;
1121        $added_users_count = 0;
1122
1123        $users = UserInfo::get();
1124
1125        $totalUsers = count($users);
1126        $this->info("Processing " . $totalUsers . " users");
1127
1128        $userInfoDispatcher = UserInfo::getEventDispatcher();
1129        UserInfo::unsetEventDispatcher();
1130        $userDispatcher = User::getEventDispatcher();
1131        User::unsetEventDispatcher();
1132        $dailyDispatcher = FlyMsgUserDailyUsage::getEventDispatcher();
1133        FlyMsgUserDailyUsage::unsetEventDispatcher();
1134
1135        foreach ($users as $user) {
1136            try {
1137                $user->email_domain_count = User::where('email', 'like', '%' . $user->email_domain)->count();
1138                $user->last_update_usage_at = new UTCDateTime(now()->getTimestamp() * 1000);
1139                $user->save();
1140                $added_users_count++;
1141            } catch (\Exception $e) {
1142                $this->error("Failed to process user {$user->email}" . $e->getMessage());
1143                $failed_users[] = [
1144                    'user_id' => $user->id,
1145                    'email' => $user->email,
1146                    'error' => $e->getMessage(),
1147                ];
1148                $failed_users_count++;
1149            }
1150
1151            $totalUsers--;
1152            $this->output->write("\rRemaining users: " . $totalUsers . " | Percentage: " . round(($totalUsers / count($users)) * 100, 2) . "%", false);
1153        }
1154        $this->output->writeln('');
1155
1156        if ($userInfoDispatcher) {
1157            UserInfo::setEventDispatcher($userInfoDispatcher);
1158        }
1159        if ($userDispatcher) {
1160            User::setEventDispatcher($userDispatcher);
1161        }
1162        if ($dailyDispatcher) {
1163            FlyMsgUserDailyUsage::setEventDispatcher($dailyDispatcher);
1164        }
1165
1166        $totalDurationInMinutes = now()->diffInMinutes($totalTimeStartAt);
1167        $totalDurationInSeconds = now()->diffInSeconds($totalTimeStartAt);
1168
1169        Log::info("fixUserEmailDomainCount completed", [
1170            'completed_users_count' => $added_users_count,
1171            'total_duration_in_minutes' => $totalDurationInMinutes,
1172            'total_duration_in_seconds' => $totalDurationInSeconds,
1173            'failed_users_count' => $failed_users_count,
1174            'failed_users' => $failed_users,
1175        ]);
1176
1177        $this->info("fixUserEmailDomainCount completed");
1178        $this->info("Total duration in minutes: {$totalDurationInMinutes}");
1179        $this->info("Total duration in seconds: {$totalDurationInSeconds}");
1180        $this->info("Completed users: {$added_users_count}");
1181        $this->info("Failed users: {$failed_users_count}");
1182    }
1183
1184    private function fixUserEmailDomain()
1185    {
1186        $this->info("fixUserEmailDomain started");
1187        $totalTimeStartAt = now();
1188
1189        ini_set('memory_limit', '-1');
1190
1191        $failed_users = [];
1192        $failed_users_count = 0;
1193        $added_users_count = 0;
1194
1195        $users = UserInfo::get();
1196
1197        $totalUsers = count($users);
1198        $this->info("Processing " . $totalUsers . " users");
1199
1200        $userInfoDispatcher = UserInfo::getEventDispatcher();
1201        UserInfo::unsetEventDispatcher();
1202        $userDispatcher = User::getEventDispatcher();
1203        User::unsetEventDispatcher();
1204        $dailyDispatcher = FlyMsgUserDailyUsage::getEventDispatcher();
1205        FlyMsgUserDailyUsage::unsetEventDispatcher();
1206
1207        foreach ($users as $user) {
1208            try {
1209                $user->email_domain = '@' . substr(strrchr($user->email, "@"), 1);
1210                $user->last_update_usage_at = new UTCDateTime(now()->getTimestamp() * 1000);
1211                $user->save();
1212                $added_users_count++;
1213            } catch (\Exception $e) {
1214                $this->error("Failed to process user {$user->email}" . $e->getMessage());
1215                $failed_users[] = [
1216                    'user_id' => $user->id,
1217                    'email' => $user->email,
1218                    'error' => $e->getMessage(),
1219                ];
1220                $failed_users_count++;
1221            }
1222
1223            $totalUsers--;
1224            $this->output->write("\rRemaining users: " . $totalUsers . " | Percentage: " . round(($totalUsers / count($users)) * 100, 2) . "%", false);
1225        }
1226        $this->output->writeln('');
1227
1228        if ($userInfoDispatcher) {
1229            UserInfo::setEventDispatcher($userInfoDispatcher);
1230        }
1231        if ($userDispatcher) {
1232            User::setEventDispatcher($userDispatcher);
1233        }
1234        if ($dailyDispatcher) {
1235            FlyMsgUserDailyUsage::setEventDispatcher($dailyDispatcher);
1236        }
1237
1238        $totalDurationInMinutes = now()->diffInMinutes($totalTimeStartAt);
1239        $totalDurationInSeconds = now()->diffInSeconds($totalTimeStartAt);
1240
1241        Log::info("fixUserEmailDomain completed", [
1242            'completed_users_count' => $added_users_count,
1243            'total_duration_in_minutes' => $totalDurationInMinutes,
1244            'total_duration_in_seconds' => $totalDurationInSeconds,
1245            'failed_users_count' => $failed_users_count,
1246            'failed_users' => $failed_users,
1247        ]);
1248
1249        $this->info("fixUserEmailDomain completed");
1250        $this->info("Total duration in minutes: {$totalDurationInMinutes}");
1251        $this->info("Total duration in seconds: {$totalDurationInSeconds}");
1252        $this->info("Completed users: {$added_users_count}");
1253        $this->info("Failed users: {$failed_users_count}");
1254    }
1255
1256    private function fixUserStatus()
1257    {
1258        $this->info("fixUserStatus started");
1259        $totalTimeStartAt = now();
1260
1261        ini_set('memory_limit', '-1');
1262
1263        $failed_users = [];
1264        $failed_users_count = 0;
1265        $added_users_count = 0;
1266
1267        $users = UserInfo::whereNull('status')->get();
1268
1269        $totalUsers = count($users);
1270        $this->info("Processing " . $totalUsers . " users");
1271
1272        $userInfoDispatcher = UserInfo::getEventDispatcher();
1273        UserInfo::unsetEventDispatcher();
1274        $userDispatcher = User::getEventDispatcher();
1275        User::unsetEventDispatcher();
1276        $dailyDispatcher = FlyMsgUserDailyUsage::getEventDispatcher();
1277        FlyMsgUserDailyUsage::unsetEventDispatcher();
1278
1279        foreach ($users as $user) {
1280            try {
1281                $realUser = User::find($user->user_id);
1282                $user->status = $realUser->status ?? 'Active';
1283                $user->last_update_usage_at = new UTCDateTime(now()->getTimestamp() * 1000);
1284                $user->save();
1285                $added_users_count++;
1286            } catch (\Exception $e) {
1287                $this->error("Failed to process user {$user->email}" . $e->getMessage());
1288                $failed_users[] = [
1289                    'user_id' => $user->id,
1290                    'email' => $user->email,
1291                    'error' => $e->getMessage(),
1292                ];
1293                $failed_users_count++;
1294            }
1295
1296            $totalUsers--;
1297            $this->output->write("\rRemaining users: " . $totalUsers . " | Percentage: " . round(($totalUsers / count($users)) * 100, 2) . "%", false);
1298        }
1299
1300        $this->output->writeln('');
1301
1302        if ($userInfoDispatcher) {
1303            UserInfo::setEventDispatcher($userInfoDispatcher);
1304        }
1305        if ($userDispatcher) {
1306            User::setEventDispatcher($userDispatcher);
1307        }
1308        if ($dailyDispatcher) {
1309            FlyMsgUserDailyUsage::setEventDispatcher($dailyDispatcher);
1310        }
1311
1312        $totalDurationInMinutes = now()->diffInMinutes($totalTimeStartAt);
1313        $totalDurationInSeconds = now()->diffInSeconds($totalTimeStartAt);
1314
1315        Log::info("fixUserStatus completed", [
1316            'completed_users_count' => $added_users_count,
1317            'total_duration_in_minutes' => $totalDurationInMinutes,
1318            'total_duration_in_seconds' => $totalDurationInSeconds,
1319            'failed_users_count' => $failed_users_count,
1320            'failed_users' => $failed_users,
1321        ]);
1322
1323        $this->info("fixUserStatus completed");
1324        $this->info("Total duration in minutes: {$totalDurationInMinutes}");
1325        $this->info("Total duration in seconds: {$totalDurationInSeconds}");
1326        $this->info("Completed users: {$added_users_count}");
1327        $this->info("Failed users: {$failed_users_count}");
1328    }
1329
1330    private function fixUserAccountCreationDate()
1331    {
1332        $this->info("fixUserAccountCreationDate started");
1333        $totalTimeStartAt = now();
1334
1335        ini_set('memory_limit', '-1');
1336
1337        $failed_users = [];
1338        $failed_users_count = 0;
1339        $added_users_count = 0;
1340
1341        $users = UserInfo::where('account_creation_date', '$type', 'string')->get();
1342
1343        $totalUsers = count($users);
1344        $this->info("Processing " . $totalUsers . " users");
1345
1346        $userInfoDispatcher = UserInfo::getEventDispatcher();
1347        UserInfo::unsetEventDispatcher();
1348        $userDispatcher = User::getEventDispatcher();
1349        User::unsetEventDispatcher();
1350        $dailyDispatcher = FlyMsgUserDailyUsage::getEventDispatcher();
1351        FlyMsgUserDailyUsage::unsetEventDispatcher();
1352
1353        foreach ($users as $user) {
1354            try {
1355                $carbonDate = Carbon::parse($user->account_creation_date);
1356                $user->account_creation_date = new UTCDateTime($carbonDate->getTimestamp() * 1000);
1357                $user->last_update_usage_at = new UTCDateTime(now()->getTimestamp() * 1000);
1358                $user->save();
1359                $added_users_count++;
1360            } catch (\Exception $e) {
1361                $this->error("Failed to process user {$user->email}" . $e->getMessage());
1362                $failed_users[] = [
1363                    'user_id' => $user->id,
1364                    'email' => $user->email,
1365                    'error' => $e->getMessage(),
1366                ];
1367                $failed_users_count++;
1368            }
1369
1370            $totalUsers--;
1371            $this->output->write("\rRemaining users: " . $totalUsers . " | Percentage: " . round(($totalUsers / count($users)) * 100, 2) . "%", false);
1372        }
1373        $this->output->writeln('');
1374
1375        if ($userInfoDispatcher) {
1376            UserInfo::setEventDispatcher($userInfoDispatcher);
1377        }
1378        if ($userDispatcher) {
1379            User::setEventDispatcher($userDispatcher);
1380        }
1381        if ($dailyDispatcher) {
1382            FlyMsgUserDailyUsage::setEventDispatcher($dailyDispatcher);
1383        }
1384
1385        $totalDurationInMinutes = now()->diffInMinutes($totalTimeStartAt);
1386        $totalDurationInSeconds = now()->diffInSeconds($totalTimeStartAt);
1387
1388        Log::info("fixUserAccountCreationDate completed", [
1389            'completed_users_count' => $added_users_count,
1390            'total_duration_in_minutes' => $totalDurationInMinutes,
1391            'total_duration_in_seconds' => $totalDurationInSeconds,
1392            'failed_users_count' => $failed_users_count,
1393            'failed_users' => $failed_users,
1394        ]);
1395
1396        $this->info("fixUserAccountCreationDate completed");
1397        $this->info("Total duration in minutes: {$totalDurationInMinutes}");
1398        $this->info("Total duration in seconds: {$totalDurationInSeconds}");
1399        $this->info("Completed users: {$added_users_count}");
1400        $this->info("Failed users: {$failed_users_count}");
1401    }
1402
1403    private function fixUserUpdatedAt()
1404    {
1405        $this->info("fixUserUpdatedAt started");
1406        $totalTimeStartAt = now();
1407
1408        ini_set('memory_limit', '-1');
1409
1410        $failed_users = [];
1411        $failed_users_count = 0;
1412        $added_users_count = 0;
1413
1414        $users = UserInfo::where('user_updated_at', '$type', 'string')->get();
1415
1416        $totalUsers = count($users);
1417        $this->info("Processing " . $totalUsers . " users");
1418
1419        $userInfoDispatcher = UserInfo::getEventDispatcher();
1420        UserInfo::unsetEventDispatcher();
1421        $userDispatcher = User::getEventDispatcher();
1422        User::unsetEventDispatcher();
1423        $dailyDispatcher = FlyMsgUserDailyUsage::getEventDispatcher();
1424        FlyMsgUserDailyUsage::unsetEventDispatcher();
1425
1426        foreach ($users as $user) {
1427            try {
1428                $carbonDate = Carbon::parse($user->user_updated_at);
1429                $user->user_updated_at = new UTCDateTime($carbonDate->getTimestamp() * 1000);
1430                $user->last_update_usage_at = new UTCDateTime(now()->getTimestamp() * 1000);
1431                $user->save();
1432                $added_users_count++;
1433            } catch (\Exception $e) {
1434                $this->error("Failed to process user {$user->email}" . $e->getMessage());
1435                $failed_users[] = [
1436                    'user_id' => $user->id,
1437                    'email' => $user->email,
1438                    'error' => $e->getMessage(),
1439                ];
1440                $failed_users_count++;
1441            }
1442
1443            $totalUsers--;
1444            $this->output->write("\rRemaining users: " . $totalUsers . " | Percentage: " . round(($totalUsers / count($users)) * 100, 2) . "%", false);
1445        }
1446        $this->output->writeln('');
1447
1448        if ($userInfoDispatcher) {
1449            UserInfo::setEventDispatcher($userInfoDispatcher);
1450        }
1451        if ($userDispatcher) {
1452            User::setEventDispatcher($userDispatcher);
1453        }
1454        if ($dailyDispatcher) {
1455            FlyMsgUserDailyUsage::setEventDispatcher($dailyDispatcher);
1456        }
1457
1458        $totalDurationInMinutes = now()->diffInMinutes($totalTimeStartAt);
1459        $totalDurationInSeconds = now()->diffInSeconds($totalTimeStartAt);
1460
1461        Log::info("fixUserUpdatedAt completed", [
1462            'completed_users_count' => $added_users_count,
1463            'total_duration_in_minutes' => $totalDurationInMinutes,
1464            'total_duration_in_seconds' => $totalDurationInSeconds,
1465            'failed_users_count' => $failed_users_count,
1466            'failed_users' => $failed_users,
1467        ]);
1468
1469        $this->info("fixUserUpdatedAt completed");
1470        $this->info("Total duration in minutes: {$totalDurationInMinutes}");
1471        $this->info("Total duration in seconds: {$totalDurationInSeconds}");
1472        $this->info("Completed users: {$added_users_count}");
1473        $this->info("Failed users: {$failed_users_count}");
1474    }
1475
1476    private function fixUserCreatedAt()
1477    {
1478        $this->info("fixUserCreatedAt started");
1479        $totalTimeStartAt = now();
1480
1481        ini_set('memory_limit', '-1');
1482
1483        $failed_users = [];
1484        $failed_users_count = 0;
1485        $added_users_count = 0;
1486
1487        $users = UserInfo::where('user_created_at', '$type', 'string')->get();
1488
1489        $totalUsers = count($users);
1490        $this->info("Processing " . $totalUsers . " users");
1491
1492        $userInfoDispatcher = UserInfo::getEventDispatcher();
1493        UserInfo::unsetEventDispatcher();
1494        $userDispatcher = User::getEventDispatcher();
1495        User::unsetEventDispatcher();
1496        $dailyDispatcher = FlyMsgUserDailyUsage::getEventDispatcher();
1497        FlyMsgUserDailyUsage::unsetEventDispatcher();
1498
1499        foreach ($users as $user) {
1500            try {
1501                $carbonDate = Carbon::parse($user->user_created_at);
1502                $user->user_created_at = new UTCDateTime($carbonDate->getTimestamp() * 1000);
1503                $user->last_update_usage_at = new UTCDateTime(now()->getTimestamp() * 1000);
1504                $user->save();
1505                $added_users_count++;
1506            } catch (\Exception $e) {
1507                $this->error("Failed to process user {$user->email}" . $e->getMessage());
1508                $failed_users[] = [
1509                    'user_id' => $user->id,
1510                    'email' => $user->email,
1511                    'error' => $e->getMessage(),
1512                ];
1513                $failed_users_count++;
1514            }
1515
1516            $totalUsers--;
1517            $this->output->write("\rRemaining users: " . $totalUsers . " | Percentage: " . round(($totalUsers / count($users)) * 100, 2) . "%", false);
1518        }
1519        $this->output->writeln('');
1520
1521        if ($userInfoDispatcher) {
1522            UserInfo::setEventDispatcher($userInfoDispatcher);
1523        }
1524        if ($userDispatcher) {
1525            User::setEventDispatcher($userDispatcher);
1526        }
1527        if ($dailyDispatcher) {
1528            FlyMsgUserDailyUsage::setEventDispatcher($dailyDispatcher);
1529        }
1530
1531        $totalDurationInMinutes = now()->diffInMinutes($totalTimeStartAt);
1532        $totalDurationInSeconds = now()->diffInSeconds($totalTimeStartAt);
1533
1534        Log::info("fixUserCreatedAt completed", [
1535            'completed_users_count' => $added_users_count,
1536            'total_duration_in_minutes' => $totalDurationInMinutes,
1537            'total_duration_in_seconds' => $totalDurationInSeconds,
1538            'failed_users_count' => $failed_users_count,
1539            'failed_users' => $failed_users,
1540        ]);
1541
1542        $this->info("fixUserCreatedAt completed");
1543        $this->info("Total duration in minutes: {$totalDurationInMinutes}");
1544        $this->info("Total duration in seconds: {$totalDurationInSeconds}");
1545        $this->info("Completed users: {$added_users_count}");
1546        $this->info("Failed users: {$failed_users_count}");
1547    }
1548
1549    private function fixUserLastLogin()
1550    {
1551        $this->info("fixUserLastLogin started");
1552        $totalTimeStartAt = now();
1553
1554        ini_set('memory_limit', '-1');
1555
1556        $failed_users = [];
1557        $failed_users_count = 0;
1558        $added_users_count = 0;
1559
1560        $users = UserInfo::where('last_login', '$type', 'string')->get();
1561
1562        $totalUsers = count($users);
1563        $this->info("Processing " . $totalUsers . " users");
1564
1565        $userInfoDispatcher = UserInfo::getEventDispatcher();
1566        UserInfo::unsetEventDispatcher();
1567        $userDispatcher = User::getEventDispatcher();
1568        User::unsetEventDispatcher();
1569        $dailyDispatcher = FlyMsgUserDailyUsage::getEventDispatcher();
1570        FlyMsgUserDailyUsage::unsetEventDispatcher();
1571
1572        foreach ($users as $user) {
1573            try {
1574                $carbonDate = Carbon::parse($user->last_login);
1575                $user->last_login = new UTCDateTime($carbonDate->getTimestamp() * 1000);
1576                $user->last_update_usage_at = new UTCDateTime(now()->getTimestamp() * 1000);
1577                $user->save();
1578                $added_users_count++;
1579            } catch (\Exception $e) {
1580                $this->error("Failed to process user {$user->email}" . $e->getMessage());
1581                $failed_users[] = [
1582                    'user_id' => $user->id,
1583                    'email' => $user->email,
1584                    'error' => $e->getMessage(),
1585                ];
1586                $failed_users_count++;
1587            }
1588
1589            $totalUsers--;
1590            $this->output->write("\rRemaining users: " . $totalUsers . " | Percentage: " . round(($totalUsers / count($users)) * 100, 2) . "%", false);
1591        }
1592        $this->output->writeln('');
1593
1594        if ($userInfoDispatcher) {
1595            UserInfo::setEventDispatcher($userInfoDispatcher);
1596        }
1597        if ($userDispatcher) {
1598            User::setEventDispatcher($userDispatcher);
1599        }
1600        if ($dailyDispatcher) {
1601            FlyMsgUserDailyUsage::setEventDispatcher($dailyDispatcher);
1602        }
1603
1604        $totalDurationInMinutes = now()->diffInMinutes($totalTimeStartAt);
1605        $totalDurationInSeconds = now()->diffInSeconds($totalTimeStartAt);
1606
1607        Log::info("fixUserLastLogin completed", [
1608            'completed_users_count' => $added_users_count,
1609            'total_duration_in_minutes' => $totalDurationInMinutes,
1610            'total_duration_in_seconds' => $totalDurationInSeconds,
1611            'failed_users_count' => $failed_users_count,
1612            'failed_users' => $failed_users,
1613        ]);
1614
1615        $this->info("fixUserLastLogin completed");
1616        $this->info("Total duration in minutes: {$totalDurationInMinutes}");
1617        $this->info("Total duration in seconds: {$totalDurationInSeconds}");
1618        $this->info("Completed users: {$added_users_count}");
1619        $this->info("Failed users: {$failed_users_count}");
1620    }
1621
1622    private function cleanShortcutHtml($html)
1623    {
1624        if (empty($html)) {
1625            return '';
1626        }
1627
1628        $dom = new \DOMDocument();
1629        // Suppress warnings for malformed HTML
1630        @$dom->loadHTML('<?xml encoding="utf-8" ?>' . $html);
1631
1632        $xpath = new \DOMXPath($dom);
1633
1634        // Remove elements with style containing "display: none"
1635        $hiddenElements = $xpath->query('//*[@style[contains(., "display: none")]]');
1636        foreach ($hiddenElements as $element) {
1637            $element->parentNode->removeChild($element);
1638        }
1639
1640        // Remove elements with class "wsc-element"
1641        $wscElements = $xpath->query('//*[contains(concat(" ", normalize-space(@class), " "), " wsc-element ")]');
1642        foreach ($wscElements as $element) {
1643            $element->parentNode->removeChild($element);
1644        }
1645
1646        // Remove "fms-fly-app" elements
1647        $flyMsgElements = $dom->getElementsByTagName('fms-fly-app');
1648        // The list is live, so we need to iterate backwards or create a temporary array
1649        $nodesToRemove = [];
1650        foreach ($flyMsgElements as $node) {
1651            $nodesToRemove[] = $node;
1652        }
1653        foreach ($nodesToRemove as $node) {
1654            $node->parentNode->removeChild($node);
1655        }
1656
1657        // Get the HTML of the body content
1658        $body = $dom->getElementsByTagName('body')->item(0);
1659        $newHtml = '';
1660        if ($body) {
1661            foreach ($body->childNodes as $child) {
1662                $newHtml .= $dom->saveHTML($child);
1663            }
1664        }
1665
1666        return trim($newHtml);
1667    }
1668}