Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.16% covered (danger)
0.16%
1 / 620
7.69% covered (danger)
7.69%
1 / 13
CRAP
0.00% covered (danger)
0.00%
0 / 1
UserInfoService
0.16% covered (danger)
0.16%
1 / 620
7.69% covered (danger)
7.69%
1 / 13
62448.07
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
 created
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
30
 updated
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
20
 pushItToHubspot
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
30
 validateHubspotUpdatedFields
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 parseToHubspotFields
0.00% covered (danger)
0.00%
0 / 73
0.00% covered (danger)
0.00%
0 / 1
182
 addExtension
0.00% covered (danger)
0.00%
0 / 29
0.00% covered (danger)
0.00%
0 / 1
30
 removeExtension
0.00% covered (danger)
0.00%
0 / 26
0.00% covered (danger)
0.00%
0 / 1
30
 processUser
0.00% covered (danger)
0.00%
0 / 404
0.00% covered (danger)
0.00%
0 / 1
37830
 parseUserTypeByRoleId
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 parseUserType
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
6
 formatToCarbonDate
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
90
 recalculateFlyCutUsage
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2
3namespace App\Services\UserInfo;
4
5use App\Http\Models\Admin\AdminUserInvitation;
6use App\Http\Models\Admin\Company;
7use App\Http\Models\Admin\CompanyGroup;
8use App\Http\Models\Auth\LoginHistory;
9use App\Http\Models\Auth\Role;
10use App\Http\Models\Auth\User;
11use App\Http\Models\Auth\UserRole;
12use App\Http\Models\FlyCutUsage;
13use App\Http\Models\HubspotProperties;
14use App\Http\Models\Parameter;
15use App\Http\Models\Plans;
16use App\Http\Models\Shortcut;
17use App\Http\Models\ShortcutCategory;
18use App\Http\Models\ShortcutSubCategoryLv1;
19use App\Http\Models\ShortcutSubCategoryLv2;
20use App\Http\Models\Subscription;
21use App\Http\Models\UserInfo;
22use App\Http\Services\HubspotServiceV2;
23use App\Http\Services\StatisticsService;
24use App\Traits\ObjectMapper;
25use Carbon\Carbon;
26use Illuminate\Support\Facades\Config;
27use Illuminate\Support\Facades\Http;
28use Illuminate\Support\Facades\Log;
29use MongoDB\BSON\UTCDateTime;
30
31class UserInfoService
32{
33    use ObjectMapper;
34
35    public function __construct(
36        private StatisticsService $statisticsService
37    ) {}
38
39    public function created(UserInfo $user): void
40    {
41        if (empty($user->subscription_type) && ! empty($user->email_verified_at)) {
42            $subscriptionService = new SubscriptionService;
43            $props = $subscriptionService->initFreemiumSubscription($user->user_id);
44            $user->update($props);
45            $user = $user->fresh();
46        }
47
48        $created = $user->toArray();
49
50        $hubspotFields = $this->validateHubspotUpdatedFields($created);
51
52        if (! empty($hubspotFields)) {
53            $dbUser = User::find($user->user_id);
54            $parsedHubspotFields = $this->parseToHubspotFields($hubspotFields, $dbUser);
55
56            $hubspotService = new HubspotServiceV2;
57
58            $realUser = User::find($user->user_id);
59            if (! $user->hubspot_id) {
60                $hubspotService->createHubspotProperties($realUser);
61
62                $realUser = $realUser->fresh();
63            }
64
65            $hubspotService->batchUpdate($realUser->hubspot_id, $parsedHubspotFields);
66            $realUser->user_info_id = $user->id;
67            $realUser->save();
68        }
69    }
70
71    public function updated(UserInfo $user): void
72    {
73        $updated = $user->getDirty();
74
75        if (! empty($updated)) {
76            $hubspotFields = $this->validateHubspotUpdatedFields($updated);
77
78            if (! empty($hubspotFields)) {
79                $dbUser = User::find($user->user_id);
80
81                $parsedHubspotFields = $this->parseToHubspotFields($hubspotFields, $dbUser);
82
83                $hubspotService = new HubspotServiceV2;
84
85                $realUser = User::find($user->user_id);
86                if (! $user->hubspot_id) {
87                    $hubspotService->createHubspotProperties($realUser);
88                    $realUser = $realUser->fresh();
89                }
90
91                $hubspotService->batchUpdate($realUser->hubspot_id, $parsedHubspotFields);
92                $realUser->user_info_id = $user->id;
93                $realUser->save();
94            }
95        }
96
97        Log::info('User Info updated: '.$user->email);
98    }
99
100    public function pushItToHubspot(string $userId, bool $safe = true)
101    {
102        $userInfo = UserInfo::where('user_id', $userId)->first();
103        $hpService = new HubspotServiceV2;
104
105        if ($userInfo) {
106            $created = $userInfo->toArray();
107            $hubspotFields = $this->validateHubspotUpdatedFields($created);
108
109            if (! empty($hubspotFields)) {
110                $user = User::withTrashed()->find($userId);
111
112                $parsedHubspotFields = $this->parseToHubspotFields($hubspotFields, $user);
113
114                if ($user) {
115                    if (! $user->hubspot_id) {
116                        $hpService->createHubspotProperties($user);
117
118                        $user = $user->fresh();
119                    }
120
121                    $hpService->sendToHusbpot($user->hubspot_id, $parsedHubspotFields, $safe);
122                }
123            }
124        }
125    }
126
127    public function validateHubspotUpdatedFields(array $updated): array
128    {
129        $parameter = Parameter::where('name', 'hubspot_fields_to_sync')->first();
130
131        $hubspotFields = $parameter->value;
132
133        return array_filter($updated, fn ($key) => in_array($key, $hubspotFields), ARRAY_FILTER_USE_KEY);
134    }
135
136    public function parseToHubspotFields(array $fields, User $user): array
137    {
138        $map = array_fill_keys(array_keys($fields), []);
139
140        $map['last_login'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
141        $map['account_creation_date'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
142        $map['flymsg_chrome_extension_installed__date_'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
143        $map['flymsg_chrome_extension_uninstalled__date_'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
144        $map['flymsg_edge_extension_installed__date_'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
145        $map['flymsg_edge_extension_uninstalled__date_'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
146        $map['clicked_help_last_date'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
147        $map['clicked_settings_last_date'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
148        $map['clicked_download_extension_last_date'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
149        $map['clicked_contact_sales_last_date'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
150        $map['freemium_subscription_start_date'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
151        $map['freemium_subscription_status_updated_on'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
152        $map['freemium_subscription_churn_date'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
153        $map['freemium_cancel_subscription_date'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
154        $map['starter_subscription_status_updated_on'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
155        $map['starter_subscription_start_date'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
156        $map['starter_subscription_expiration_date'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
157        $map['starter_cancel_subscription_date'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
158        $map['starter_subscription_churn_date'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
159        $map['growth_subscription_status_updated_on'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
160        $map['growth_subscription_start_date'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
161        $map['growth_subscription_expiration_date'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
162        $map['growth_cancel_subscription_date'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
163        $map['growth_subscription_churn_date'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
164        $map['trail_period_start_date'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
165        $map['trail_period_end_date'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
166        $map['trail_period_canceled_date'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
167        $map['professional_subscription_status_updated_on'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
168        $map['professional_subscription_start_date'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
169        $map['professional_subscription_expiration_date'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
170        $map['professional_cancel_subscription_date'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
171        $map['professional_subscription_churn_date'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
172        $map['sales_pro_teams_subscription_status_updated_on'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
173        $map['sales_pro_teams_subscription_start_date'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
174        $map['sales_pro_teams_subscription_expiration_date'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
175        $map['sales_pro_teams_cancel_subscription_date'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
176        $map['sales_pro_teams_subscription_churn_date'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
177        $map['last_date_user_used_a_flycut'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
178        $map['last_date_user_used_flyengage'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
179        $map['last_date_user_used_sentence_rewrite'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
180        $map['last_date_user_used_paragraph_rewrite'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
181        $map['last_date_user_used_flyposts'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
182        $map['number_of_categories_created_last_date'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
183        $map['number_of_flycuts_created_last_date'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
184        $map['number_of_flyplates_in_flycuts_last_date'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
185        $map['first_name'] = ['rename' => 'firstname'];
186        $map['last_name'] = ['rename' => 'lastname'];
187        $map['job_title'] = ['rename' => 'jobtitle'];
188        $map['user_id'] = ['rename' => 'flymsg_id'];
189        $map['total___of_times_flygrammar_is_used_summarized_monthly_by_user'] = ['rename' => 'total_of_times_flygrammar_is_used_summarized_monthly'];
190        $map['total___of_times_flygrammar_is_used_count'] = ['rename' => 'total_n_of_times_flygrammar_used'];
191        $map['last_date_user_used_flygrammar'] = ['transform' => fn ($value) => $this->formatToCarbonDate($value)];
192        $map['company_id'] = ['rename' => 'company', 'transform' => fn ($value) => $value ? Company::find($value)->name : null];
193        $map['is_chrome_extension_installed'] = ['rename' => 'flymsg_chrome_extension_installed', 'transform' => fn ($value) => $value ? 'Yes' : 'No'];
194        $map['is_chrome_extension_uninstalled'] = ['rename' => 'flymsg_chrome_extension_uninstalled', 'transform' => fn ($value) => $value ? 'Yes' : 'No'];
195        $map['is_edge_extension_installed'] = ['rename' => 'flymsg_edge_extension_installed', 'transform' => fn ($value) => $value ? 'Yes' : 'No'];
196        $map['is_edge_extension_uninstalled'] = ['rename' => 'flymsg_edge_extension_uninstalled', 'transform' => fn ($value) => $value ? 'Yes' : 'No'];
197        $map['which_browser_has_an_extension_been_installed_on'] = ['transform' => function () use ($fields) {
198            $browsers = [];
199            if (! empty($fields['is_chrome_extension_installed'] ?? null)) {
200                $browsers[] = 'Chrome';
201            }
202            if (! empty($fields['is_edge_extension_installed'] ?? null)) {
203                $browsers[] = 'Edge';
204            }
205
206            return implode(';', $browsers);
207        }];
208        $map['plan_id'] = ['rename' => 'subscription_type', 'transform' => fn ($value) => $value ? Plans::find($value)->hubspot_name : null];
209
210        $mappedObject = $this->mapObject($fields, $map);
211
212        if (! empty($fields['subscription_type']) && ($fields['subscription_type'] == 'Cancelled Account' || $fields['subscription_type'] == 'Deleted Profile from FlyMSG')) {
213            $mappedObject['subscription_type'] = $fields['subscription_type'];
214        }
215
216        if (empty($user->email_verified_at)) {
217            $mappedObject['subscription_type'] = 'Unverified';
218        }
219
220        return $mappedObject;
221    }
222
223    public function addExtension(UserInfo $userInfo, string $browser, $date)
224    {
225        $prop = 'is_'.$browser.'_extension_installed';
226
227        $userInfo->$prop = true;
228
229        $userInfo->is_any_extension_installed = true;
230        $userInfo->signed_into_flymsg_extension = 'Yes';
231
232        $browsers = [];
233        if ($userInfo->is_chrome_extension_installed) {
234            $browsers[] = 'Chrome';
235        }
236
237        if ($userInfo->is_edge_extension_installed) {
238            $browsers[] = 'Edge';
239        }
240        $userInfo->which_browser_has_an_extension_been_installed_on = implode(';', $browsers);
241        $userInfo->last_browser_used = ucfirst($browser);
242
243        $extensionInstalledProp = 'flymsg_'.$browser.'_extension_installed__date_';
244        $userInfo->$extensionInstalledProp = $date ? new UTCDateTime($date->timestamp * 1000) : now();
245
246        $extensionIsUninstalledProp = 'is_'.$browser.'_extension_uninstalled';
247        $extensionUninstalledDateProp = 'flymsg_'.$browser.'_extension_uninstalled__date_';
248
249        $userInfo->$extensionIsUninstalledProp = false;
250        $userInfo->$extensionUninstalledDateProp = null;
251
252        $userInfo->is_any_extension_uninstalled = $userInfo->is_edge_extension_uninstalled || $userInfo->is_chrome_extension_uninstalled;
253
254        return [
255            $prop => $userInfo->$prop,
256            'is_any_extension_installed' => $userInfo->is_any_extension_installed,
257            'signed_into_flymsg_extension' => $userInfo->signed_into_flymsg_extension,
258            'which_browser_has_an_extension_been_installed_on' => $userInfo->which_browser_has_an_extension_been_installed_on,
259            'last_browser_used' => $userInfo->last_browser_used,
260            $extensionInstalledProp => $userInfo->$extensionInstalledProp,
261            $extensionIsUninstalledProp => $userInfo->$extensionIsUninstalledProp,
262            $extensionUninstalledDateProp => $userInfo->$extensionUninstalledDateProp,
263            'is_any_extension_uninstalled' => $userInfo->is_any_extension_uninstalled,
264        ];
265    }
266
267    public function removeExtension(UserInfo $userInfo, string $browser, $date)
268    {
269        $prop = 'is_'.$browser.'_extension_uninstalled';
270        $userInfo->$prop = true;
271
272        $userInfo->is_any_extension_uninstalled = true;
273        $userInfo->signed_into_flymsg_extension = 'No';
274
275        $extensionUninstalledProp = 'flymsg_'.$browser.'_extension_uninstalled__date_';
276        $userInfo->$extensionUninstalledProp = $date ? new UTCDateTime($date->timestamp * 1000) : now();
277
278        $extensionIsInstalledProp = 'is_'.$browser.'_extension_installed';
279
280        $userInfo->$extensionIsInstalledProp = false;
281
282        $userInfo->is_any_extension_installed = $userInfo->is_edge_extension_installed || $userInfo->is_chrome_extension_installed;
283
284        $browsers = [];
285        if ($userInfo->is_chrome_extension_installed) {
286            $browsers[] = 'Chrome';
287        }
288
289        if ($userInfo->is_edge_extension_installed) {
290            $browsers[] = 'Edge';
291        }
292        $userInfo->which_browser_has_an_extension_been_installed_on = implode(';', $browsers);
293        $userInfo->last_browser_used = ucfirst($browser);
294
295        return [
296            $prop => $userInfo->$prop,
297            'is_any_extension_uninstalled' => $userInfo->is_any_extension_uninstalled,
298            'signed_into_flymsg_extension' => $userInfo->signed_into_flymsg_extension,
299            $extensionUninstalledProp => $userInfo->$extensionUninstalledProp,
300            $extensionIsInstalledProp => $userInfo->$extensionIsInstalledProp,
301            'is_any_extension_installed' => $userInfo->is_any_extension_installed,
302            'which_browser_has_an_extension_been_installed_on' => $userInfo->which_browser_has_an_extension_been_installed_on,
303            'last_browser_used' => $userInfo->last_browser_used,
304        ];
305    }
306
307    public function processUser(User $user): UserInfo
308    {
309        $subscriptionService = new SubscriptionService;
310
311        $user_info = UserInfo::firstOrNew(['user_id' => $user->id]);
312
313        // region Personal Data
314        $user_info->user_id = $user->id;
315        $user_info->first_name = $user->first_name;
316        $user_info->last_name = $user->last_name;
317        $user_info->full_name = $user->first_name.' '.$user->last_name;
318        $user_info->email = $user->email;
319
320        $user_info->account_creation_date = new UTCDateTime($user->created_at->timestamp * 1000);
321        $roles = $user->roles();
322
323        if (! in_array(Role::USER, $roles)) {
324            array_push($roles, Role::USER);
325        }
326        $user_info->user_type = implode(',', $roles);
327
328        $words_per_minute = $this->statisticsService->getWordsPerMinute($user);
329        $wage_per_hour = $this->statisticsService->getWagePerHour($user, now());
330        $user_info->typed_words_per_minute = $words_per_minute;
331        $user_info->wage_per_hour = $wage_per_hour;
332        $user_info->email_used_for_login = $user->email;
333        $user_info->signup_source = $user->signup_source;
334        $user_info->signin_source = $user->signup_source;
335        $last_login = LoginHistory::where('user_id', $user->id)->latest()->first();
336        if ($last_login) {
337            $user_info->last_login = new UTCDateTime($last_login->created_at->timestamp * 1000);
338        }
339        $user_info->status = $user->status ?? 'Active';
340        $account_status_date = match (true) {
341            ! is_null($user->deactivated_at) => $user->deactivated_at,
342            ! is_null($user->activation_date) => Carbon::parse($user->activation_date),
343            ! is_null($user->created_at) => $user->created_at,
344            $user->status == 'Invited' => AdminUserInvitation::where('email', $user->email)->first()?->updated_at,
345            default => null,
346        };
347        $user_info->status_date = new UTCDateTime($account_status_date->timestamp * 1000);
348        $user_info->user_created_at = new UTCDateTime($user->created_at->timestamp * 1000);
349        $user_info->user_updated_at = new UTCDateTime($user->updated_at->timestamp * 1000);
350        $user_info->company_id = $user->company_id;
351        $user_info->company_name = $user->company?->name;
352        $user_info->avatar = $user->avatar;
353        $user_info->hubspot_id = $user->hubspot_id;
354        $user_info->stripe_id = $user->stripe_id;
355        $user_info->instancy_id = $user->instancy_id;
356
357        if (! empty($user->company_group_id)) {
358            $group = CompanyGroup::where('id', $user->company_group_id)->first();
359            if ($group) {
360                $parentGroup = CompanyGroup::where('id', $group->parent_id)->first();
361
362                if ($parentGroup) {
363                    $user_info->group_id = $parentGroup->id;
364                    $user_info->group_name = $parentGroup->name;
365                    $user_info->subgroup_id = $user->company_group_id;
366                    $user_info->subgroup_name = $user->company_group?->name;
367                } else {
368                    $user_info->group_id = $user->company_group_id;
369                    $user_info->group_name = $user->company_group?->name;
370                }
371            } else {
372                $user_info->company_group_id = null;
373                $user_info->company_group_name = null;
374            }
375        }
376
377        $userRoles = UserRole::where('user_id', $user->id)->get();
378        $user_info->role_ids = implode(',', $userRoles->pluck('role_id')->toArray());
379        $user_info->role_names = implode(',', $userRoles->pluck('role.name')->toArray());
380        $user_info->is_invite = ! LoginHistory::where('user_id', $user->id)->exists();
381        $user_info->email_domain = explode('@', $user->email)[1];
382        $user_info->email_domain_count = User::where('email', 'like', '%'.$user_info->email_domain)->count();
383        // endregion
384
385        if (false) {
386            // region Items from HubspotProperties
387
388            $hubspotProperty = HubspotProperties::where('email', $user->email)->first();
389
390            // region Extension
391            $user_info->is_chrome_extension_installed = $hubspotProperty ? ($hubspotProperty->flymsg_chrome_extension_installed === 'Yes' && $hubspotProperty->flymsg_chrome_extension_uninstalled === 'No') : false;
392            $user_info->is_edge_extension_installed = $hubspotProperty ? ($hubspotProperty->flymsg_edge_extension_installed === 'Yes' && $hubspotProperty->flymsg_edge_extension_uninstalled === 'No') : false;
393
394            $user_info->is_any_extension_installed = $hubspotProperty ? (
395                ($hubspotProperty->flymsg_chrome_extension_installed === 'Yes' && $hubspotProperty->flymsg_chrome_extension_uninstalled === 'No') ||
396                ($hubspotProperty->flymsg_edge_extension_installed === 'Yes' && $hubspotProperty->flymsg_edge_extension_uninstalled === 'No')
397            ) : false;
398            $user_info->is_any_extension_uninstalled = $hubspotProperty ? (
399                ($hubspotProperty->flymsg_chrome_extension_installed === 'No' && $hubspotProperty->flymsg_chrome_extension_uninstalled === 'Yes') ||
400                ($hubspotProperty->flymsg_edge_extension_installed === 'No' && $hubspotProperty->flymsg_edge_extension_uninstalled === 'Yes')
401            ) : false;
402            $user_info->signed_into_flymsg_extension = $hubspotProperty ? $hubspotProperty->signed_into_flymsg_extension : 'No';
403            $user_info->which_browser_has_an_extension_been_installed_on = $hubspotProperty ? $hubspotProperty->which_browser_has_an_extension_been_installed_on : null;
404            $user_info->last_browser_used = $hubspotProperty ? ucfirst($hubspotProperty->last_browser_used) : null;
405            $user_info->is_chrome_extension_uninstalled = $hubspotProperty ? ($hubspotProperty->flymsg_chrome_extension_installed === 'No' && $hubspotProperty->flymsg_chrome_extension_uninstalled === 'Yes') : false;
406            $user_info->flymsg_chrome_extension_installed__date_ = $hubspotProperty ? new UTCDateTime(Carbon::parse($hubspotProperty->flymsg_chrome_extension_installed__date_)->timestamp * 1000) : null;
407            $user_info->flymsg_chrome_extension_uninstalled__date_ = $hubspotProperty ? new UTCDateTime(Carbon::parse($hubspotProperty->flymsg_chrome_extension_uninstalled__date_)->timestamp * 1000) : null;
408            $user_info->flymsg_extension_version_for_chrome = $hubspotProperty ? $hubspotProperty->flymsg_extension_version_for_chrome : null;
409            $user_info->is_edge_extension_uninstalled = $hubspotProperty ? ($hubspotProperty->flymsg_edge_extension_installed === 'No' && $hubspotProperty->flymsg_edge_extension_uninstalled === 'Yes') : false;
410            $user_info->flymsg_edge_extension_installed__date_ = $hubspotProperty ? new UTCDateTime(Carbon::parse($hubspotProperty->flymsg_edge_extension_installed__date_)->timestamp * 1000) : null;
411            $user_info->flymsg_edge_extension_uninstalled__date_ = $hubspotProperty ? new UTCDateTime(Carbon::parse($hubspotProperty->flymsg_edge_extension_uninstalled__date_)->timestamp * 1000) : null;
412            $user_info->flymsg_extension_version_for_edge = $hubspotProperty ? $hubspotProperty->flymsg_extension_version_for_edge : null;
413
414            if (empty($user_info->flymsg_chrome_extension_installed__date_) && empty($user_info->flymsg_chrome_extension_uninstalled__date_)) {
415                $props = [
416                    'is_chrome_extension_installed' => false,
417                    'signed_into_flymsg_extension' => 'No',
418                    'flymsg_chrome_extension_installed__date_' => null,
419                    'is_chrome_extension_uninstalled' => null,
420                    'flymsg_chrome_extension_uninstalled__date_' => null,
421                    'is_any_extension_uninstalled' => false,
422                ];
423                $user_info->fill($props);
424            } elseif ($user_info->flymsg_chrome_extension_installed__date_ && empty($user_info->flymsg_chrome_extension_uninstalled__date_)) {
425                $props = $this->addExtension($user_info, 'chrome', Carbon::instance($user_info->flymsg_chrome_extension_installed__date_->toDateTime()));
426                $user_info->fill($props);
427            } elseif ($user_info->flymsg_chrome_extension_uninstalled__date_ && empty($user_info->flymsg_chrome_extension_installed__date_)) {
428                $uninstallDate = Carbon::instance($user_info->flymsg_chrome_extension_uninstalled__date_->toDateTime());
429                $props = $this->addExtension($user_info, 'chrome', Carbon::instance($user_info->flymsg_chrome_extension_uninstalled__date_->toDateTime()));
430                $user_info->fill($props);
431                $props = $this->removeExtension($user_info, 'chrome', $uninstallDate);
432                $user_info->fill($props);
433            } elseif ($user_info->flymsg_chrome_extension_installed__date_ < $user_info->flymsg_chrome_extension_uninstalled__date_) {
434                $uninstallDate = Carbon::instance($user_info->flymsg_chrome_extension_uninstalled__date_->toDateTime());
435                $props = $this->addExtension($user_info, 'chrome', Carbon::instance($user_info->flymsg_chrome_extension_installed__date_->toDateTime()));
436                $user_info->fill($props);
437                $props = $this->removeExtension($user_info, 'chrome', $uninstallDate);
438                $user_info->fill($props);
439            } else {
440                $installDate = Carbon::instance($user_info->flymsg_chrome_extension_installed__date_->toDateTime());
441                $props = $this->removeExtension($user_info, 'chrome', Carbon::instance($user_info->flymsg_chrome_extension_uninstalled__date_->toDateTime()));
442                $user_info->fill($props);
443                $props = $this->addExtension($user_info, 'chrome', $installDate);
444                $user_info->fill($props);
445            }
446
447            if (empty($user_info->flymsg_edge_extension_installed__date_) && empty($user_info->flymsg_edge_extension_uninstalled__date_)) {
448                $props = [
449                    'is_edge_extension_installed' => false,
450                    'signed_into_flymsg_extension' => 'No',
451                    'flymsg_edge_extension_installed__date_' => null,
452                    'is_edge_extension_uninstalled' => null,
453                    'flymsg_edge_extension_uninstalled__date_' => null,
454                    'is_any_extension_uninstalled' => false,
455                ];
456                $user_info->fill($props);
457            } elseif ($user_info->flymsg_edge_extension_installed__date_ && empty($user_info->flymsg_edge_extension_uninstalled__date_)) {
458                $props = $this->addExtension($user_info, 'edge', Carbon::instance($user_info->flymsg_edge_extension_installed__date_->toDateTime()));
459                $user_info->fill($props);
460            } elseif ($user_info->flymsg_edge_extension_uninstalled__date_ && empty($user_info->flymsg_edge_extension_installed__date_)) {
461                $uninstallDate = Carbon::instance($user_info->flymsg_edge_extension_uninstalled__date_->toDateTime());
462                $props = $this->addExtension($user_info, 'edge', Carbon::instance($user_info->flymsg_edge_extension_uninstalled__date_->toDateTime()));
463                $user_info->fill($props);
464                $props = $this->removeExtension($user_info, 'edge', $uninstallDate);
465                $user_info->fill($props);
466            } elseif ($user_info->flymsg_edge_extension_installed__date_ < $user_info->flymsg_edge_extension_uninstalled__date_) {
467                $uninstallDate = Carbon::instance($user_info->flymsg_edge_extension_uninstalled__date_->toDateTime());
468                $props = $this->addExtension($user_info, 'edge', Carbon::instance($user_info->flymsg_edge_extension_installed__date_->toDateTime()));
469                $user_info->fill($props);
470                $props = $this->removeExtension($user_info, 'edge', $uninstallDate);
471                $user_info->fill($props);
472            } else {
473                $installDate = Carbon::instance($user_info->flymsg_edge_extension_installed__date_->toDateTime());
474                $props = $this->removeExtension($user_info, 'edge', Carbon::instance($user_info->flymsg_edge_extension_uninstalled__date_->toDateTime()));
475                $user_info->fill($props);
476                $props = $this->addExtension($user_info, 'edge', $installDate);
477                $user_info->fill($props);
478            }
479
480            // endregion
481
482            if ($hubspotProperty) {
483                if (! $user_info->df_stripe_customer_id && $hubspotProperty->df_stripe_customer_id) {
484                    $user_info->df_stripe_customer_id = $hubspotProperty->df_stripe_customer_id;
485                }
486                if (! $user_info->subscription_owner && $hubspotProperty->subscription_owner) {
487                    $user_info->subscription_owner = $hubspotProperty->subscription_owner;
488                }
489                if (! $user_info->billing_address_line_1 && $hubspotProperty->billing_address_line_1) {
490                    $user_info->billing_address_line_1 = $hubspotProperty->billing_address_line_1;
491                }
492                if (! $user_info->billing_address_line_2 && $hubspotProperty->billing_address_line_2) {
493                    $user_info->billing_address_line_2 = $hubspotProperty->billing_address_line_2;
494                }
495                if (! $user_info->billing_city && $hubspotProperty->billing_city) {
496                    $user_info->billing_city = $hubspotProperty->billing_city;
497                }
498                if (! $user_info->billing_state && $hubspotProperty->billing_state) {
499                    $user_info->billing_state = $hubspotProperty->billing_state;
500                }
501                if (! $user_info->billing_zip && $hubspotProperty->billing_zip) {
502                    $user_info->billing_zip = $hubspotProperty->billing_zip;
503                }
504                if (! $user_info->billing_country && $hubspotProperty->billing_country) {
505                    $user_info->billing_country = $hubspotProperty->billing_country;
506                }
507                if (! $user_info->number_of_completed_payments && $hubspotProperty->number_of_completed_payments) {
508                    $user_info->number_of_completed_payments = $hubspotProperty->number_of_completed_payments;
509                }
510                if (! $user_info->number_of_expected_payments && $hubspotProperty->number_of_expected_payments) {
511                    $user_info->number_of_expected_payments = $hubspotProperty->number_of_expected_payments;
512                }
513                if (! $user_info->payment_method && $hubspotProperty->payment_method) {
514                    $user_info->payment_method = $hubspotProperty->payment_method;
515                }
516                if (! $user_info->flymsg_last_product_purchased && $hubspotProperty->flymsg_last_product_purchased) {
517                    $user_info->flymsg_last_product_purchased = $hubspotProperty->flymsg_last_product_purchased;
518                }
519                if (! $user_info->last_total_invoice_amount && $hubspotProperty->last_total_invoice_amount) {
520                    $numberInfo = preg_replace('/[^0-9.]/', '', $hubspotProperty->last_total_invoice_amount);
521                    $user_info->last_total_invoice_amount = $numberInfo;
522                }
523                if (! $user_info->flymsg_total_sales && $hubspotProperty->flymsg_total_sales) {
524                    $user_info->flymsg_total_sales = $hubspotProperty->flymsg_total_sales;
525                }
526                if (! $user_info->coupon_name && $hubspotProperty->coupon_name) {
527                    $user_info->coupon_name = $hubspotProperty->coupon_name;
528                }
529                if (! $user_info->coupon_code && $hubspotProperty->coupon_code) {
530                    $user_info->coupon_code = $hubspotProperty->coupon_code;
531                }
532                if (! $user_info->coupon_type && $hubspotProperty->coupon_type) {
533                    $user_info->coupon_type = $hubspotProperty->coupon_type;
534                }
535                if (! $user_info->duration && $hubspotProperty->duration) {
536                    $user_info->duration = $hubspotProperty->duration;
537                }
538                if (! $user_info->coupon_value__discount_ && $hubspotProperty->coupon_value__discount_) {
539                    $user_info->coupon_value__discount_ = $hubspotProperty->coupon_value__discount_;
540                }
541                if (! $user_info->coupon_redemption_limits && $hubspotProperty->coupon_redemption_limits) {
542                    $user_info->coupon_redemption_limits = $hubspotProperty->coupon_redemption_limits;
543                }
544                if (! $user_info->productivity_problems && $hubspotProperty->productivity_problems) {
545                    $user_info->productivity_problems = $hubspotProperty->productivity_problems;
546                }
547                if (! $user_info->type_here_how_flymsg_will_help_you___ && $hubspotProperty->type_here_how_flymsg_will_help_you___) {
548                    $user_info->type_here_how_flymsg_will_help_you___ = $hubspotProperty->type_here_how_flymsg_will_help_you___;
549                }
550                if (! $user_info->flymsg_use_case && $hubspotProperty->flymsg_use_case) {
551                    $user_info->flymsg_use_case = $hubspotProperty->flymsg_use_case;
552                }
553                if (! $user_info->sign_out_reason && $hubspotProperty->sign_out_reason) {
554                    $user_info->sign_out_reason = $hubspotProperty->sign_out_reason;
555                }
556                if (! $user_info->sign_out_text && $hubspotProperty->sign_out_text) {
557                    $user_info->sign_out_text = $hubspotProperty->sign_out_text;
558                }
559            }
560            // endregion
561        }
562        // region Flymsg Simple Usage
563        $last_date_user_used_a_flycut = FlyCutUsage::where('user_id', $user->id)->where('feature', null)->orderBy('created_at', 'desc')->first();
564        if ($last_date_user_used_a_flycut) {
565            $user_info->last_date_user_used_a_flycut = new UTCDateTime($last_date_user_used_a_flycut->created_at->timestamp * 1000);
566        }
567        $last_date_user_used_a_flyengage = FlyCutUsage::where('user_id', $user->id)->where('feature', 'flyengage')->orderBy('created_at', 'desc')->first();
568        if ($last_date_user_used_a_flyengage) {
569            $user_info->last_date_user_used_flyengage = new UTCDateTime($last_date_user_used_a_flyengage->created_at->timestamp * 1000);
570        }
571        $last_date_user_used_a_sentence_rewrite = FlyCutUsage::where('user_id', $user->id)->where('feature', 'sentence_rewrite')->orderBy('created_at', 'desc')->first();
572        if ($last_date_user_used_a_sentence_rewrite) {
573            $user_info->last_date_user_used_sentence_rewrite = new UTCDateTime($last_date_user_used_a_sentence_rewrite->created_at->timestamp * 1000);
574        }
575        $last_date_user_used_a_paragraph_rewrite = FlyCutUsage::where('user_id', $user->id)->where('feature', 'paragraph_rewrite')->orderBy('created_at', 'desc')->first();
576        if ($last_date_user_used_a_paragraph_rewrite) {
577            $user_info->last_date_user_used_paragraph_rewrite = new UTCDateTime($last_date_user_used_a_paragraph_rewrite->created_at->timestamp * 1000);
578        }
579        $last_date_user_used_a_flypost = FlyCutUsage::where('user_id', $user->id)->where('feature', 'flypost')->orderBy('created_at', 'desc')->first();
580        if ($last_date_user_used_a_flypost) {
581            $user_info->last_date_user_used_flyposts = new UTCDateTime($last_date_user_used_a_flypost->created_at->timestamp * 1000);
582        }
583        $lastCategory = ShortcutCategory::where('user_id', $user->id)->latest()->first();
584        $lastSubCategoryLvl1 = ShortcutSubCategoryLv1::where('user_id', $user->id)->latest()->first();
585        $lastSubCategoryLvl2 = ShortcutSubCategoryLv2::where('user_id', $user->id)->latest()->first();
586
587        $number_of_categories_created_last_date = collect([$lastCategory, $lastSubCategoryLvl1, $lastSubCategoryLvl2])->max('created_at');
588        if ($number_of_categories_created_last_date) {
589            $user_info->number_of_categories_created_last_date = new UTCDateTime($number_of_categories_created_last_date->timestamp * 1000);
590        }
591        $user_info->number_of_categories_created_count = ShortcutCategory::where('user_id', $user->id)->count() +
592            ShortcutSubCategoryLv1::where('user_id', $user->id)->count() +
593            ShortcutSubCategoryLv2::where('user_id', $user->id)->count();
594
595        $number_of_flycuts_created_last_date = Shortcut::where('user_id', $user->id)->where('user_defined', true)->latest()->first();
596        if ($number_of_flycuts_created_last_date) {
597            $user_info->number_of_flycuts_created_last_date = new UTCDateTime($number_of_flycuts_created_last_date->created_at->timestamp * 1000);
598        }
599        $user_info->number_of_flycuts_created_count = Shortcut::where('user_id', $user->id)->where('user_defined', true)->count();
600
601        $number_of_flyplates_in_flycuts_last_date = Shortcut::where('user_id', $user->id)->where('user_defined', false)->latest()->first();
602        if ($number_of_flyplates_in_flycuts_last_date) {
603            $user_info->number_of_flyplates_in_flycuts_last_date = new UTCDateTime($number_of_flyplates_in_flycuts_last_date->created_at->timestamp * 1000);
604        }
605        $user_info->number_of_flyplates_in_flycuts_count = Shortcut::where('user_id', $user->id)->where('user_defined', false)->count();
606        // endregion
607
608        // region Licenses
609        // region Inactive Subscriptions
610        $inactiveSubscriptions = Subscription::where('user_id', $user->id)
611            ->where('stripe_status', '!=', 'active')
612            ->orderBy('created_at', 'asc')
613            ->get();
614        foreach ($inactiveSubscriptions as $subscription) {
615            $fields = $subscription->toArray();
616            $result = $subscriptionService->endSubscription($fields, $subscription);
617            $user_info->fill($result);
618        }
619        // endregion
620
621        // region Active Subscriptions
622        $activeSubscriptions = Subscription::where('user_id', $user->id)
623            ->where('stripe_status', 'active')
624            ->orderBy('created_at', 'asc')
625            ->get();
626
627        $haveActiveSubscription = false;
628
629        foreach ($activeSubscriptions as $subscription) {
630            $fields = $subscription->toArray();
631            $result = $subscriptionService->startSubscription($fields, $subscription);
632            $user_info->fill($result);
633            $haveActiveSubscription = true;
634        }
635
636        if (! $haveActiveSubscription) {
637            $user_info->fill($subscriptionService->initFreemiumSubscription($user->id));
638        }
639        // endregion
640        // endregion
641
642        if (false) {
643            // region Direct from Hubspot API
644            // => filled in by onboarding, not available in users table, try to load from hubspot
645
646            $accessToken = Config::get('hubspotconfig.access_token');
647            $url = 'https://api.hubapi.com/crm/v3/objects/contacts/search';
648
649            $data = [
650                'filterGroups' => [
651                    [
652                        'filters' => [
653                            [
654                                'propertyName' => 'email',
655                                'operator' => 'EQ',
656                                'value' => $user->email,
657                            ],
658                        ],
659                    ],
660                ],
661                'properties' => [
662                    'email',
663                    'job_role',
664                    'department',
665                    'jobtitle',
666                    'company',
667                    'phone',
668                    'linkedin_url',
669                    'clicked_help_last_date',
670                    'clicked_help_count',
671                    'clicked_settings_last_date',
672                    'clicked_settings_count',
673                    'clicked_download_extension_last_date',
674                    'clicked_download_extension_count',
675                    'clicked_contact_sales_last_date',
676                    'clicked_contact_sales_count',
677                    'df_stripe_customer_id',
678                    'subscription_owner',
679                    'billing_address_line_1',
680                    'billing_address_line_2',
681                    'billing_city',
682                    'billing_state',
683                    'billing_zip',
684                    'billing_country',
685                    'number_of_completed_payments',
686                    'number_of_expected_payments',
687                    'payment_method',
688                    'flymsg_last_product_purchased',
689                    'last_total_invoice_amount',
690                    'flymsg_total_sales',
691                    'coupon_name',
692                    'coupon_code',
693                    'coupon_type',
694                    'duration',
695                    'coupon_value__discount_',
696                    'coupon_redemption_limits',
697                    'productivity_problems',
698                    'type_here_how_flymsg_will_help_you___',
699                    'flymsg_use_case',
700                    'sign_out_reason',
701                    'sign_out_text',
702                ],
703                'limit' => 1,
704            ];
705
706            $response = Http::withHeaders([
707                'Authorization' => "Bearer {$accessToken}",
708                'Content-Type' => 'application/json',
709            ])->post($url, $data);
710
711            if ($response->successful()) {
712                $contact = $response->json('results.0');
713
714                if ($contact && ! empty($contact['properties'])) {
715                    if (! $user_info->job_role && ! empty($contact['properties']['job_role'])) {
716                        $user_info->job_role = $contact['properties']['job_role'];
717                    }
718
719                    if (! $user_info->department && ! empty($contact['properties']['department'])) {
720                        $user_info->department = $contact['properties']['department'];
721                    }
722
723                    if (! $user_info->job_title && ! empty($contact['properties']['jobtitle'])) {
724                        $user_info->job_title = $contact['properties']['jobtitle'];
725                    }
726
727                    if (! $user_info->company && ! empty($contact['properties']['company'])) {
728                        $user_info->company = $contact['properties']['company'];
729                    }
730
731                    if (! $user_info->phone && ! empty($contact['properties']['phone'])) {
732                        $user_info->phone = $contact['properties']['phone'];
733                    }
734
735                    if (! $user_info->linkedin_url && ! empty($contact['properties']['linkedin_url'])) {
736                        $user_info->linkedin_url = $contact['properties']['linkedin_url'];
737                    }
738
739                    if (! $user_info->clicked_help_last_date && ! empty($contact['properties']['clicked_help_last_date'])) {
740                        try {
741                            $user_info->clicked_help_last_date = new UTCDateTime(Carbon::parse($contact['properties']['clicked_help_last_date'])->timestamp * 1000);
742                        } catch (\Exception $e) {
743                            $user_info->clicked_help_last_date = $contact['properties']['clicked_help_last_date'];
744                        }
745                    }
746
747                    if (! $user_info->clicked_help_count && ! empty($contact['properties']['clicked_help_count'])) {
748                        $user_info->clicked_help_count = $contact['properties']['clicked_help_count'];
749                    }
750
751                    if (! $user_info->clicked_settings_last_date && ! empty($contact['properties']['clicked_settings_last_date'])) {
752                        try {
753                            $user_info->clicked_settings_last_date = new UTCDateTime(Carbon::parse($contact['properties']['clicked_settings_last_date'])->timestamp * 1000);
754                        } catch (\Exception $e) {
755                            $user_info->clicked_settings_last_date = $contact['properties']['clicked_settings_last_date'];
756                        }
757                    }
758
759                    if (! $user_info->clicked_settings_count && ! empty($contact['properties']['clicked_settings_count'])) {
760                        $user_info->clicked_settings_count = $contact['properties']['clicked_settings_count'];
761                    }
762
763                    if (! $user_info->clicked_download_extension_last_date && ! empty($contact['properties']['clicked_download_extension_last_date'])) {
764                        try {
765                            $user_info->clicked_download_extension_last_date = new UTCDateTime(Carbon::parse($contact['properties']['clicked_download_extension_last_date'])->timestamp * 1000);
766                        } catch (\Exception $e) {
767                            $user_info->clicked_download_extension_last_date = $contact['properties']['clicked_download_extension_last_date'];
768                        }
769                    }
770
771                    if (! $user_info->clicked_download_extension_count && ! empty($contact['properties']['clicked_download_extension_count'])) {
772                        $user_info->clicked_download_extension_count = $contact['properties']['clicked_download_extension_count'];
773                    }
774
775                    if (! $user_info->clicked_contact_sales_last_date && ! empty($contact['properties']['clicked_contact_sales_last_date'])) {
776                        try {
777                            $user_info->clicked_contact_sales_last_date = new UTCDateTime(Carbon::parse($contact['properties']['clicked_contact_sales_last_date'])->timestamp * 1000);
778                        } catch (\Exception $e) {
779                            $user_info->clicked_contact_sales_last_date = $contact['properties']['clicked_contact_sales_last_date'];
780                        }
781                    }
782
783                    if (! $user_info->clicked_contact_sales_count && ! empty($contact['properties']['clicked_contact_sales_count'])) {
784                        $user_info->clicked_contact_sales_count = $contact['properties']['clicked_contact_sales_count'];
785                    }
786
787                    if (! $user_info->df_stripe_customer_id && ! empty($contact['properties']['df_stripe_customer_id'])) {
788                        $user_info->df_stripe_customer_id = $contact['properties']['df_stripe_customer_id'];
789                    }
790
791                    if (! $user_info->subscription_owner && ! empty($contact['properties']['subscription_owner'])) {
792                        $user_info->subscription_owner = $contact['properties']['subscription_owner'];
793                    }
794
795                    if (! $user_info->billing_address_line_1 && ! empty($contact['properties']['billing_address_line_1'])) {
796                        $user_info->billing_address_line_1 = $contact['properties']['billing_address_line_1'];
797                    }
798
799                    if (! $user_info->billing_address_line_2 && ! empty($contact['properties']['billing_address_line_2'])) {
800                        $user_info->billing_address_line_2 = $contact['properties']['billing_address_line_2'];
801                    }
802
803                    if (! $user_info->billing_city && ! empty($contact['properties']['billing_city'])) {
804                        $user_info->billing_city = $contact['properties']['billing_city'];
805                    }
806
807                    if (! $user_info->billing_state && ! empty($contact['properties']['billing_state'])) {
808                        $user_info->billing_state = $contact['properties']['billing_state'];
809                    }
810
811                    if (! $user_info->billing_zip && ! empty($contact['properties']['billing_zip'])) {
812                        $user_info->billing_zip = $contact['properties']['billing_zip'];
813                    }
814
815                    if (! $user_info->billing_country && ! empty($contact['properties']['billing_country'])) {
816                        $user_info->billing_country = $contact['properties']['billing_country'];
817                    }
818
819                    if (! $user_info->number_of_completed_payments && ! empty($contact['properties']['number_of_completed_payments'])) {
820                        $user_info->number_of_completed_payments = $contact['properties']['number_of_completed_payments'];
821                    }
822
823                    if (! $user_info->number_of_expected_payments && ! empty($contact['properties']['number_of_expected_payments'])) {
824                        $user_info->number_of_expected_payments = $contact['properties']['number_of_expected_payments'];
825                    }
826
827                    if (! $user_info->payment_method && ! empty($contact['properties']['payment_method'])) {
828                        $user_info->payment_method = $contact['properties']['payment_method'];
829                    }
830
831                    if (! $user_info->flymsg_last_product_purchased && ! empty($contact['properties']['flymsg_last_product_purchased'])) {
832                        $user_info->flymsg_last_product_purchased = $contact['properties']['flymsg_last_product_purchased'];
833                    }
834
835                    if (! $user_info->last_total_invoice_amount && ! empty($contact['properties']['last_total_invoice_amount'])) {
836                        $numberInfo = preg_replace('/[^0-9.]/', '', $contact['properties']['last_total_invoice_amount']);
837                        $user_info->last_total_invoice_amount = $numberInfo;
838                    }
839
840                    if (! $user_info->flymsg_total_sales && ! empty($contact['properties']['flymsg_total_sales'])) {
841                        $user_info->flymsg_total_sales = $contact['properties']['flymsg_total_sales'];
842                    }
843
844                    if (! $user_info->coupon_name && ! empty($contact['properties']['coupon_name'])) {
845                        $user_info->coupon_name = $contact['properties']['coupon_name'];
846                    }
847
848                    if (! $user_info->coupon_code && ! empty($contact['properties']['coupon_code'])) {
849                        $user_info->coupon_code = $contact['properties']['coupon_code'];
850                    }
851
852                    if (! $user_info->coupon_type && ! empty($contact['properties']['coupon_type'])) {
853                        $user_info->coupon_type = $contact['properties']['coupon_type'];
854                    }
855
856                    if (! $user_info->duration && ! empty($contact['properties']['duration'])) {
857                        $user_info->duration = $contact['properties']['duration'];
858                    }
859
860                    if (! $user_info->coupon_value__discount_ && ! empty($contact['properties']['coupon_value__discount_'])) {
861                        $user_info->coupon_value__discount_ = $contact['properties']['coupon_value__discount_'];
862                    }
863
864                    if (! $user_info->coupon_redemption_limits && ! empty($contact['properties']['coupon_redemption_limits'])) {
865                        $user_info->coupon_redemption_limits = $contact['properties']['coupon_redemption_limits'];
866                    }
867
868                    if (! $user_info->productivity_problems && ! empty($contact['properties']['productivity_problems'])) {
869                        $user_info->productivity_problems = $contact['properties']['productivity_problems'];
870                    }
871
872                    if (! $user_info->type_here_how_flymsg_will_help_you___ && ! empty($contact['properties']['type_here_how_flymsg_will_help_you___'])) {
873                        $user_info->type_here_how_flymsg_will_help_you___ = $contact['properties']['type_here_how_flymsg_will_help_you___'];
874                    }
875
876                    if (! $user_info->flymsg_use_case && ! empty($contact['properties']['flymsg_use_case'])) {
877                        $user_info->flymsg_use_case = $contact['properties']['flymsg_use_case'];
878                    }
879
880                    if (! $user_info->sign_out_reason && ! empty($contact['properties']['sign_out_reason'])) {
881                        $user_info->sign_out_reason = $contact['properties']['sign_out_reason'];
882                    }
883
884                    if (! $user_info->sign_out_text && ! empty($contact['properties']['sign_out_text'])) {
885                        $user_info->sign_out_text = $contact['properties']['sign_out_text'];
886                    }
887
888                    Log::info("Contact found for email: {$user->email}", [
889                        'id' => $contact['id'],
890                        'properties' => $contact['properties'],
891                    ]);
892                }
893            }
894
895            // endregion
896        }
897
898        $user_info->save();
899
900        return $user_info->fresh();
901    }
902
903    private function parseUserTypeByRoleId(string $role_ids)
904    {
905        if (empty($role_ids)) {
906            return null;
907        }
908
909        $roles = Role::whereIn('id', explode(',', $role_ids))->get();
910
911        return $this->parseUserType($roles->pluck('name')->implode(','));
912    }
913
914    private function parseUserType(string $roles)
915    {
916        if (empty($roles)) {
917            return null;
918        }
919
920        $userRoles = explode(',', $roles);
921
922        return implode(';', array_map(function ($role) {
923            return match ($role) {
924                'Reporting Admin' => 'Reporting POC',
925                'Group Admin' => 'Group Admin Manager',
926                default => $role,
927            };
928        }, $userRoles));
929    }
930
931    private function formatToCarbonDate($value): ?string
932    {
933        if (empty($value)) {
934            return '';
935        }
936
937        if ($value instanceof Carbon) {
938            return $value->toDateString();
939        }
940
941        if ($value instanceof \MongoDB\BSON\UTCDateTime || (is_numeric($value) && strlen($value) >= 13)) {
942            try {
943                return Carbon::createFromTimestampMs($value)->toDateString();
944            } catch (\Exception $e) {
945                return null;
946            }
947        }
948
949        try {
950            return Carbon::parse($value)->toDateString();
951        } catch (\Exception $e) {
952            try {
953                return Carbon::createFromTimestamp($value)->toDateString();
954            } catch (\Exception $e) {
955                return null;
956            }
957        }
958    }
959
960    public function recalculateFlyCutUsage(string $userId)
961    {
962        $flyCutUsages = FlyCutUsage::where('user_id', $userId)->get();
963
964        foreach ($flyCutUsages as $flyCutUsage) {
965            try {
966                if ($flyCutUsage->user) {
967                    $timeSaved = $this->statisticsService->getTimeSaved($flyCutUsage->user, $flyCutUsage->characters_saved);
968                    $carbonDate = Carbon::createFromFormat('Y-m-d H:i:s', $flyCutUsage->created_at);
969                    $costSaved = $this->statisticsService->getCostSaved($flyCutUsage->user, $timeSaved, $carbonDate);
970                    $flyCutUsage->time_saved = $timeSaved;
971                    $flyCutUsage->cost_saved = $costSaved;
972                    $flyCutUsage->recalculated_wage_per_hour = true;
973                    $flyCutUsage->save();
974                }
975            } catch (\Exception $e) {
976                // error
977            }
978        }
979    }
980}