Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.22% covered (danger)
0.22%
1 / 457
4.76% covered (danger)
4.76%
1 / 21
CRAP
0.00% covered (danger)
0.00%
0 / 1
AdminUsersService
0.22% covered (danger)
0.22%
1 / 457
4.76% covered (danger)
4.76%
1 / 21
19057.26
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
 getUsersPaginated
0.00% covered (danger)
0.00%
0 / 116
0.00% covered (danger)
0.00%
0 / 1
702
 deleteUsers
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
42
 unassignUsers
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
42
 deleteInvitation
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
30
 delete
0.00% covered (danger)
0.00%
0 / 25
0.00% covered (danger)
0.00%
0 / 1
2
 unassign
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
42
 deleteUser
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
6
 unassignUser
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
6
 deactivateUsers
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
20
 deactivateUser
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 1
72
 deactivateUserBulk
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
56
 deactivateInvitedUser
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
6
 deleteInvitedUser
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 moveUsersToGroup
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
20
 moveUserToGroup
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
20
 moveInvitationUserToGroup
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 acceptMoveToInvitation
0.00% covered (danger)
0.00%
0 / 40
0.00% covered (danger)
0.00%
0 / 1
90
 acceptUserInvitation
0.00% covered (danger)
0.00%
0 / 81
0.00% covered (danger)
0.00%
0 / 1
702
 rejectUserInvitation
0.00% covered (danger)
0.00%
0 / 44
0.00% covered (danger)
0.00%
0 / 1
240
 createUserForInvitationLogin
0.00% covered (danger)
0.00%
0 / 20
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace App\Http\Services\Admin\Users;
4
5use App\Actions\AccountCenter\Reporting\AccountCenterReporting;
6use App\Actions\Users\CancelUserPlanAction;
7use App\Actions\Users\UpdateUserPlanAction;
8use App\Events\User\Registered;
9use App\Exceptions\ExpectedException;
10use App\Http\Models\Admin\AdminUserInvitation;
11use App\Http\Models\Admin\Company;
12use App\Http\Models\Admin\CompanyGroup;
13use App\Http\Models\Admin\CompanyLicenses;
14use App\Http\Models\Auth\LinkedSocialAccount;
15use App\Http\Models\Auth\LoginHistory;
16use App\Http\Models\Auth\LogoutHistory;
17use App\Http\Models\Auth\Role;
18use App\Http\Models\Auth\User;
19use App\Http\Models\Plans;
20use App\Http\Models\UserInfo;
21use App\Http\Repositories\InstancyRepository;
22use App\Http\Repositories\InstancyUserDTO;
23use Carbon\Carbon;
24use Illuminate\Support\Facades\Queue;
25use App\Http\Models\UserPasswordReset;
26use App\Http\Services\InstancyServiceV2;
27use Illuminate\Support\Facades\Log;
28use MongoDB\BSON\UTCDateTime;
29use App\Jobs\Emails\DeactivateUserNotification;
30use App\Events\InstancyUserUpdate;
31use App\Http\Models\FlyMsgUserDailyUsage;
32use App\Services\Email\EmailService;
33
34class AdminUsersService extends AccountCenterReporting
35{
36    private string $cantDeactivateOwnAccount = "You cannot deactivate your own account.";
37    private string $cantDeleteOwnAccount = "You cannot delete your own account.";
38    private string $cantUnassignOwnAccount = "You cannot unassign your own account.";
39
40    public function __construct(
41        private CancelUserPlanAction $cancelUserPlanAction,
42        private InstancyRepository $instancyRepository,
43        private readonly UpdateUserPlanAction $updateUserPlanAction,
44        private readonly EmailService $emailService
45    ) {}
46
47    public function getUsersPaginated($filter, $deactivated, $perPage, $page, $categories, $sortBy, $sortOrder, $license_types, $account_status, $extensions)
48    {
49        $account_status = array_filter($account_status);
50        $license_types = array_filter($license_types);
51        $categories = array_filter($categories);
52
53        $usersQuery = UserInfo::select(
54            'user_id',
55            'first_name',
56            'last_name',
57            'full_name',
58            'status',
59            'is_invite',
60            'email',
61            'avatar',
62            'user_created_at',
63            'user_updated_at',
64            'status_date',
65            'company_id',
66            'company_name',
67            'group_id',
68            'group_name',
69            'subgroup_id',
70            'subgroup_name',
71            // 'sales_pro_team_manager',
72            'is_any_extension_installed',
73            'role_names',
74            'plan_name',
75            'created_at'
76        )->where('deleted_at', null);
77
78        if (filled($filter)) {
79            // $escapedFilter = preg_quote($filter, '/');
80            $usersQuery = $usersQuery->where(function ($query) use ($filter) {
81                $query->where('email', 'like', "%$filter%")
82                    ->orWhere('full_name', 'like', "%$filter$")
83                    ->orWhere('user_id', 'like', "%$filter$");
84            });
85        }
86
87        if (count($extensions) > 0) {
88            $string = str_replace('""', 'empty', $extensions[0]);
89            $extensions = array_map('intval', $extensions);
90            if (count($extensions) > 0) {
91                $extensions = array_map('boolval', $extensions);
92                $usersQuery = $usersQuery->whereIn('is_any_extension_installed', $extensions);
93            }
94        }
95
96        $deactivatedCompanies = Company::whereNotNull('deactivated_at')
97            ->pluck('id')
98            ->toArray();
99
100        if (count($account_status) > 0) {
101            $usersQuery = $usersQuery->whereIn('status', $account_status);
102        } elseif ($deactivated) {
103            $usersQuery = $usersQuery->where(function ($query) use ($deactivatedCompanies) {
104                $query->where('status', 'Deactivated')
105                    ->orWhereIn('company_id', $deactivatedCompanies);
106            });
107        } else {
108            $usersQuery = $usersQuery->where(function ($query) use ($deactivatedCompanies) {
109                $query->whereNull('deactivated_at')
110                    ->WhereNotIn('company_id', $deactivatedCompanies);
111            });
112
113            $usersQuery = $usersQuery->whereNotIn('status', ['Deactivated', 'Deleted']);
114        }
115
116        $emails = array_filter($categories, function ($category) {
117            return str_starts_with($category, '@') && $category !== 'all_individuals';
118        });
119
120        $companyIds = array_filter($categories, function ($category) {
121            return !str_starts_with($category, '@') && $category !== 'all_individuals';
122        });
123        $categoriesQuery = [];
124
125        if (in_array('all_individuals', $categories)) {
126            $categoriesQuery[] = function ($query) {
127                $query->whereNull('company_id')->where('email_domain_count', '>', 1);
128            };
129        } elseif (filled($emails) && count($emails) > 0) {
130            foreach ($emails as $email) {
131                $categoriesQuery[] = function ($query) use ($email) {
132                    $query->where('email_domain', $email)
133                        ->whereNull('company_id');
134                };
135            }
136        }
137
138        if (filled($companyIds) && count($companyIds) > 0) {
139            foreach ($companyIds as $companyId) {
140                $categoriesQuery[] = function ($query) use ($companyId) {
141                    $query->where('company_id', $companyId);
142                };
143            }
144        }
145
146        if (!empty($categoriesQuery)) {
147            $usersQuery = $usersQuery->where(function ($query) use ($categoriesQuery) {
148                foreach ($categoriesQuery as $filterQuery) {
149                    $query->orWhere($filterQuery);
150                }
151            });
152        }
153
154        if (count($license_types) > 0) {
155            $usersQuery = $usersQuery->whereIn('plan_id', $license_types);
156
157            $freemiumId = Plans::where('identifier', 'freemium')->first()?->_id;
158            if (in_array($freemiumId, $license_types)) {
159                $usersQuery = $usersQuery->orWhereNull('plan_id');
160            }
161        }
162
163        $skip = ($page - 1) * $perPage;
164        $take = $perPage;
165        $totalUsers = $usersQuery->count();
166        $currentPage = $skip / $take + 1;
167        $totalPages = ceil($totalUsers / $take);
168
169        if (!$sortBy) {
170            $sortBy = 'created_at';
171        }
172
173        if (!$sortOrder) {
174            $sortOrder = 'desc';
175        }
176
177        $sortOrder = $sortOrder == 'desc' ? -1 : 1;
178
179        $sortPipeline = match (true) {
180            $sortBy == 'name' => [
181                ['column' => 'first_name', 'direction' => $sortOrder == 1 ? 'asc' : 'desc'],
182                ['column' => 'last_name', 'direction' => $sortOrder == 1 ? 'asc' : 'desc'],
183                ['column' => 'created_at', 'direction' => 'desc'],
184            ],
185            default => [
186                ['column' => 'created_at', 'direction' => $sortOrder == 1 ? 'asc' : 'desc']
187            ],
188        };
189
190        foreach ($sortPipeline as $sort) {
191            $usersQuery->orderBy($sort['column'], $sort['direction']);
192        }
193
194        $users = $usersQuery->skip($skip)
195            ->take($perPage)
196            ->get();
197
198        return [
199            'users' => $users,
200            'total' => $totalUsers,
201            'total_pages' => $totalPages,
202            'current_page' => $currentPage,
203        ];
204    }
205
206    public function deleteUsers(array $userIds, $adminUser, ?string $company_id)
207    {
208        if (isset($userIds) && in_array($adminUser->id, $userIds)) {
209            throw new ExpectedException($this->cantDeleteOwnAccount);
210        }
211
212        $users = User::whereIn('_id', $userIds)->get();
213
214        foreach ($users as $user) {
215            $this->deleteUser($user, $adminUser, $company_id);
216        }
217
218        $invitations = AdminUserInvitation::whereIn('_id', $userIds)->get();
219
220        if (!empty($invitations)) {
221            foreach ($invitations as $invite) {
222                $this->deleteInvitation($invite);
223            }
224        }
225    }
226
227    public function unassignUsers(array $userIds, $adminUser, ?string $company_id)
228    {
229        if (isset($userIds) && in_array($adminUser->id, $userIds)) {
230            throw new ExpectedException($this->cantUnassignOwnAccount);
231        }
232
233        $users = User::whereIn('_id', $userIds)->get();
234
235        foreach ($users as $user) {
236            $this->unassignUser($user, $adminUser, $company_id);
237        }
238
239        $invitations = AdminUserInvitation::whereIn('_id', $userIds)->get();
240
241        if (!empty($invitations)) {
242            foreach ($invitations as $invite) {
243                $this->deleteInvitation($invite);
244            }
245        }
246    }
247
248    public function deleteInvitation(AdminUserInvitation $invitation)
249    {
250        $invitationSubPlan = $invitation->subscription("invitation");
251
252        $plan = (isset($invitationSubPlan->plan)) ? $invitationSubPlan->plan : '';
253
254        if ($invitation->company_id && $plan && $plan->identifier != Plans::FREEMIUM_IDENTIFIER) {
255            $invitationSubPlan->markAsCancelledOnlyInDB();
256        }
257
258        $invitation->delete();
259    }
260
261    public function delete($user)
262    {
263        $user->deleted_at = Carbon::now()->toDateTimeString();
264        $user->status = "Deleted";
265        $user->save();
266
267        $this->cancelUserPlanAction->execute($user);
268
269        $searchByIdEmail = ['email' => $user->email];
270
271        //force delete for below tables data for the user
272        AdminUserInvitation::where($searchByIdEmail)->forceDelete();
273        LinkedSocialAccount::where($searchByIdEmail)->forceDelete();
274        LoginHistory::where($searchByIdEmail)->forceDelete();
275        LogoutHistory::where($searchByIdEmail)->forceDelete();
276        UserPasswordReset::where($searchByIdEmail)->forceDelete();
277
278        $user->delete();
279
280        // soft delete the users table
281        $user->fill([
282            'first_name' => '',
283            'last_name' => '',
284            'avatar' => '',
285            'email' => "delete_from_flymsg_$user->email",
286            'password' => '',
287            'remember_token' => '',
288            'card_last_four' => '',
289            'card_brand' => '',
290            'team_id' => '',
291            'pm_last_four' => '',
292            'pm_type' => '',
293        ]);
294        $user->save();
295    }
296
297    public function unassign($user)
298    {
299        $userSub = $user->subscription("main");
300        if ($userSub) {
301            $plan = $userSub->plan;
302
303            if (isset($plan->identifier) && $plan->identifier != Plans::FREEMIUM_IDENTIFIER && $userSub->valid()) {
304                if ($user->company_id) {
305                    $userSub->markAsCancelledOnlyInDB();
306                } else {
307                    $userSub->markAsCanceled();
308                }
309            }
310        }
311        $instancyService = new InstancyServiceV2();
312        $instancyService->updateMembership($user->email, now()->toDateString());
313        $user->company_id = '';
314        $user->company_group_id = '';
315        $user->invited_to_company = null;
316        $user->invited_to_company_by_admin = null;
317        $user->status = "Active";
318        $user->save();
319    }
320
321    public function deleteUser(User $user, $adminUser)
322    {
323        if ($user->id == $adminUser->id) {
324            throw new ExpectedException($this->cantDeleteOwnAccount);
325        }
326
327        Log::info('Deleting user: ', [
328            'user' => $user->email,
329            'admin' => $adminUser->email,
330            'date' => Carbon::now()->toDateTimeString(),
331        ]);
332        $this->delete($user);
333    }
334
335    public function unassignUser(User $user, $adminUser)
336    {
337        if ($user->id == $adminUser->id) {
338            throw new ExpectedException($this->cantUnassignOwnAccount);
339        }
340
341        Log::info('Unassign user: ', [
342            'user' => $user->email,
343            'admin' => $adminUser->email,
344            'date' => Carbon::now()->toDateTimeString(),
345        ]);
346        $this->unassign($user);
347    }
348
349    public function deactivateUsers(array $userIds, string $adminUserId, ?string $company_id)
350    {
351        if (isset($userIds) && in_array($adminUserId, $userIds)) {
352            throw new ExpectedException($this->cantDeactivateOwnAccount);
353        }
354
355        $users = User::whereIn('_id', $userIds)->get();
356
357        foreach ($users as $user) {
358            $this->deactivateUser($user, $adminUserId, $company_id);
359        }
360    }
361
362    public function deactivateUser(User $user, string $adminUserId, ?string $company_id, $cancellation_date = null)
363    {
364        if ($user->id == $adminUserId) {
365            throw new ExpectedException($this->cantDeactivateOwnAccount);
366        }
367
368        $invitation = AdminUserInvitation::where('email', $user->email)->first();
369        if ($invitation) {
370            $invitation->forceDelete();
371        }
372
373        if ($user->status === 'Invited') {
374            $user->company_id = null;
375        }
376
377        $user->status = "Deactivated";
378        $user->deactivated_at = Carbon::now()->toDateTimeString();
379        if (!empty($cancellation_date)) {
380            $user->deactivated_at = $cancellation_date->toDateTimeString();
381        }
382
383        $user->company_group_id = null;
384        $user->save();
385
386        $admin = auth()->user();
387        $companyName = $admin->company->name;
388        $companyEmail = $admin->email;
389
390        if ($company_id) {
391            $company = Company::find($user->company_id);
392            $companyLicense = CompanyLicenses::where('company_id', $company->id)->first();
393            $community = $companyLicense->business_pro_enterprise_plus ?? [];
394            $isPro = in_array('yes_dedicated', $community) || in_array('yes_community', $community);
395
396            if ($isPro) {
397                DeactivateUserNotification::dispatch($user->email, $companyEmail, $companyName, $this->emailService)->delay(now()->addSeconds(2));
398            }
399        }
400
401        $this->cancelUserPlanAction->execute($user, true, $cancellation_date);
402    }
403
404    public function deactivateUserBulk(array $userIds, string $adminUserId, string $company_id)
405    {
406        if (isset($userIds) && in_array($adminUserId, $userIds)) {
407            throw new ExpectedException("You cannot deactivate your own account.");
408        }
409
410        $users = User::whereIn('_id', $userIds)->get();
411
412        // create the users ids array those available in users table
413        $existingUsers = User::whereIn('_id', $userIds)->pluck('_id')->toArray();
414
415        // users those not found in users table
416        $invitedUsers = array_diff($userIds, $existingUsers);
417
418        foreach ($users as $user) {
419            $this->deactivateUser($user, $adminUserId, empty($company_id) ? $user->company_id : $company_id);
420        }
421
422        // for the invited users those not yet registered
423        if (!empty($invitedUsers)) {
424            $invitedUsers = AdminUserInvitation::whereIn('_id', $invitedUsers)->get();
425            foreach ($invitedUsers as $invitedUser) {
426                $this->deleteInvitedUser($invitedUser);
427            }
428        }
429    }
430
431    public function deactivateInvitedUser(AdminUserInvitation $user, string $adminUserId)
432    {
433        if ($user->id == $adminUserId) {
434            throw new ExpectedException($this->cantDeactivateOwnAccount);
435        }
436
437        $user->status = "Deactivated";
438        $user->deactivated_at = Carbon::now()->toDateTimeString();
439        $user->company_group_id = null;
440        $user->save();
441    }
442
443    public function deleteInvitedUser(AdminUserInvitation $user)
444    {
445        $user->forceDelete();
446    }
447
448    public function moveUsersToGroup(array $usersId, ?CompanyGroup $group)
449    {
450        $users = User::whereIn('_id', $usersId)->get();
451
452        // create the users ids array those available in users table
453        $existingUsers = User::whereIn('_id', $usersId)->pluck('_id')->toArray();
454
455        // users those not found in users table
456        $invitedUsers = array_diff($usersId, $existingUsers);
457
458        // for main users those are active
459        foreach ($users as $user) {
460            $user = $this->moveUserToGroup($user, $group);
461        }
462
463        // for the invited users those not yet registered
464        if (!empty($invitedUsers)) {
465            $invitedUsers = AdminUserInvitation::whereIn('_id', $invitedUsers)->get();
466            foreach ($invitedUsers as $invitedUser) {
467                $invitedUser = $this->moveInvitationUserToGroup($invitedUser, $group);
468            }
469        }
470
471        return $users;
472    }
473
474    public function moveUserToGroup(User $user, ?CompanyGroup $group)
475    {
476        $user->company_group_id = $group ? $group->id : null;
477        $user->save();
478
479        if ($user->instancy_id) {
480            if ($group) {
481                $newGroup = $group->instancy_id;
482            } else {
483                $newGroup = $user->company->instancy_id;
484            }
485
486            $instancyUser = new InstancyUserDTO(
487                $user->instancy_id,
488                $newGroup,
489                $user->first_name,
490                $user->last_name,
491                $user->email,
492                $user->company->name,
493            );
494
495            //old code
496            //$this->instancyRepository->updateUser($instancyUser);
497            InstancyUserUpdate::dispatch($instancyUser);
498        }
499
500        return $user;
501    }
502
503    public function moveInvitationUserToGroup(AdminUserInvitation $user, ?CompanyGroup $group)
504    {
505        $user->company_group_id = $group ? $group->id : null;
506        $user->save();
507
508        return $user;
509    }
510
511    private function acceptMoveToInvitation(User $user, AdminUserInvitation $invitation)
512    {
513        $user->removeAllRoles();
514        $group_ids = [];
515
516        $planId = $invitation->plan_id;
517        $companyId = $invitation->company_id;
518        $roleName = $invitation->role_name;
519        $groupId = $invitation->company_group_id;
520        $subgroupId = $invitation->company_subgroup_id;
521        $hasCorporatePlan = $invitation->has_corporate_plan;
522        $plan = Plans::find($planId);
523        $companyLicense = CompanyLicenses::where('company_id', $companyId)
524            ->active()
525            ->first();
526
527        if (($roleName == Role::GROUP_ADMIN || $roleName = Role::REPORTING_ADMIN) && ($groupId || $subgroupId)) {
528            $group_ids = [$groupId] ?? [$subgroupId] ?? [];
529        }
530        $user->assignRole($roleName, $group_ids);
531
532        $user->company_id = $companyId;
533        $user->activation_date = Carbon::now()->toDateTimeString();
534        if (filled($groupId)) {
535            $user->company_group_id = $groupId;
536        }
537
538        if (filled($subgroupId)) {
539            $user->company_group_id = $subgroupId;
540        }
541        $user->status = "Active";
542        $user->unset('invited_to_company');
543        $user->unset('invited_to_company_by_admin');
544
545        FlyMsgUserDailyUsage::where('user_id', $user->id)
546            ->update([
547                'company_id' => $user->company_id,
548                'group_id'   => $user->company_group_id,
549                'user_status' => $user->status
550            ]);
551
552        $this->updateUserPlanAction->execute($user, $plan, $companyLicense->contract_end_date, $hasCorporatePlan);
553
554        if ($invitation) {
555            if ($invitation->reminder_job_id) {
556                Queue::forget($invitation->reminder_job_id);
557                $invitation->reminder_job_id = null;
558                $invitation->save();
559            }
560
561            $invitation->delete();
562        }
563
564        $user->save();
565
566        $user->refresh();
567        return $user;
568    }
569
570    public function acceptUserInvitation(User $user, ?string $company_id)
571    {
572        $invitation = AdminUserInvitation::where('email', $user->email)->withTrashed();
573
574        if ($company_id) {
575            $invitation = $invitation->where('company_id', $company_id);
576        }
577
578        $invitation = $invitation->first();
579
580        if ($invitation->move_assign) {
581            return $this->acceptMoveToInvitation($user, $invitation);
582        }
583
584        if ($invitation && $invitation->deleted_at && $company_id == $invitation->company_id) {
585            $user->unset('invited_to_company');
586            $user->unset('invited_to_company_by_admin');
587            $user->save();
588
589            FlyMsgUserDailyUsage::where('user_id', $user->id)
590                ->update([
591                    'company_id' => $user->company_id,
592                    'group_id'   => $user->company_group_id,
593                    'user_status' => $user->status,
594                ]);
595
596            return $user;
597        }
598
599        // if (!$invitation) {
600        //     throw new ExpectedException("Invitation not found");
601        // }
602
603        if ($invitation) {
604            $plan = Plans::find($invitation->plan_id);
605            if ($company_id && !$plan) {
606                throw new ExpectedException("The user was invited without a Plan. This shouldn't have happened.");
607            }
608
609            // Change the users plan to the invited one
610            $useSub = $user->subscription('main');
611
612            $changeSubscription = !filled($useSub) || ($useSub->stripe_plan != $plan->stripe_id);
613
614            if ($changeSubscription) {
615                if ($user->subscribed('main')) {
616                    $companyLicense = CompanyLicenses::where('company_id', $user->company_id)
617                        ->active()
618                        ->first();
619                    if (filled($useSub->ends_at) && ($useSub->ends_at == $companyLicense?->contract_end_date)) {
620                        $useSub->update([
621                            'stripe_status' => 'canceled',
622                            'ends_at' => Carbon::now()->toDateTimeString(),
623                        ]);
624                    } else {
625                        $useSub->cancel();
626                    }
627                } else {
628                    $subscription = $user->subscriptions()->latest()->first();
629                    if ($subscription) {
630                        $subscription->update([
631                            'ends_at' => Carbon::now()->toDateTimeString(),
632                            'stripe_status' => 'canceled',
633                        ]);
634                    }
635                }
636            }
637
638            $license = CompanyLicenses::where('company_id', $user->company_id)
639                ->active()
640                ->first();
641
642            if ($company_id && !$license) {
643                throw new ExpectedException("Failed to assign $plan. The company doesn't have any active licenses.");
644            }
645
646            if ($company_id && $changeSubscription) {
647                $user->subscriptions()->create([
648                    'name' => 'main',
649                    'stripe_status' => 'active',
650                    'stripe_plan' => $plan->stripe_id,
651                    'quantity' => "1",
652                    'ends_at' => $license->contract_end_date,
653                    'starts_at' => Carbon::now()->startOfDay()->toDateTimeString(),
654                ]);
655                $license->reduceCompanyLicenseCountForNewUsers($plan);
656            }
657        }
658
659        // Change the users status to Active
660        $user->status = "Active";
661        $user->activation_date = Carbon::now()->toDateTimeString();
662
663        if ($invitation) {
664            if ($invitation->company_group_id) {
665                $user->company_group_id = $invitation->company_group_id;
666            }
667            if ($invitation->company_subgroup_id) {
668                $user->company_group_id = $invitation->company_subgroup_id;
669            }
670        }
671
672        $user->unset('invited_to_company');
673        $user->unset('invited_to_company_by_admin');
674
675        FlyMsgUserDailyUsage::where('user_id', $user->id)
676            ->update([
677                'company_id' => $user->company_id,
678                'group_id'   => $user->company_group_id,
679                'user_status' => $user->status,
680            ]);
681
682        $user->save();
683
684        if ($invitation) {
685            if ($invitation->reminder_job_id) {
686                Queue::forget($invitation->reminder_job_id);
687                $invitation->reminder_job_id = null;
688                $invitation->save();
689            }
690
691            $invitation->delete();
692        }
693
694        if (isset($plan) && !empty($plan)) {
695            $user->plan = $plan;
696        }
697
698        $user->refresh();
699
700        return $user;
701    }
702
703    public function rejectUserInvitation(User $user, ?string $company_id)
704    {
705        $invitation = AdminUserInvitation::where('email', $user->email)->withTrashed();
706
707        if ($company_id) {
708            $invitation = $invitation->where('company_id', $company_id);
709        }
710
711        $invitation = $invitation->first();
712
713        if ($invitation) {
714            $plan = Plans::find($invitation->plan_id);
715
716            if ($plan) {
717                // Change the users plan to the invited one
718                $useSub = $user->subscription('main');
719
720                $changeSubscription = filled($useSub) && ($useSub->stripe_plan == $plan->stripe_id);
721
722                if ($changeSubscription) {
723                    $companyLicense = CompanyLicenses::where('company_id', $user->company_id)
724                        ->active()
725                        ->first();
726
727                    if ($user->subscribed('main')) {
728                        if (filled($useSub->ends_at) && ($useSub->ends_at == $companyLicense?->contract_end_date)) {
729                            $useSub->update([
730                                'stripe_status' => 'canceled',
731                                'ends_at' => Carbon::now()->toDateTimeString(),
732                            ]);
733                        } else {
734                            $useSub->cancel();
735                        }
736                    } else {
737                        $subscription = $user->subscriptions()->latest()->first();
738                        if ($subscription) {
739                            $subscription->update([
740                                'ends_at' => Carbon::now()->toDateTimeString(),
741                                'stripe_status' => 'canceled',
742                            ]);
743                        }
744                    }
745
746                    if ($changeSubscription && $companyLicense) {
747                        $companyLicense->restoreLicenseCountForDeletedUsers($plan);
748                    }
749                }
750            }
751        }
752
753        // Change the users status to Active
754        $user->status = "Active";
755        $user->unset('activation_date');
756        $user->unset('company_id');
757        $user->unset('company_group_id');
758        $user->unset('invited_to_company');
759        $user->unset('invited_to_company_by_admin');
760        $user->save();
761        // remove roles
762        $user->removeAllRoles();
763
764        if ($invitation) {
765            if ($invitation->reminder_job_id) {
766                Queue::forget($invitation->reminder_job_id);
767                $invitation->reminder_job_id = null;
768                $invitation->save();
769            }
770
771            if (!$invitation->deleted_at) {
772                $invitation->delete();
773            }
774        }
775
776        return $user;
777    }
778
779    public function createUserForInvitationLogin(AdminUserInvitation $invitation)
780    {
781        $user = new User();
782        $user->status = "Invited";
783        $user->email = $invitation->email;
784        $user->first_name = "";
785        $user->last_name = "";
786        $user->password = $invitation->password ?? $invitation->temp_password;
787        $user->temp_password = $invitation->password ?? $invitation->temp_password;
788        $user->company_id = $invitation->company_id;
789        $user->email_verified_at = new UTCDateTime(now()->getTimestamp() * 1000);
790        $user->onboardingv2_presented = true;
791
792        $user->save();
793
794        $data = [
795            "email" => $user->email,
796            "first_name" => $user->first_name,
797            "last_name" => $user->last_name,
798            "do_not_send_welcome_notification" => true
799        ];
800
801        Registered::dispatch($user, $data);
802
803        $user = $this->acceptUserInvitation($user, $invitation->company_id);
804
805        return $user;
806    }
807}