Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 148 |
|
0.00% |
0 / 13 |
CRAP | |
0.00% |
0 / 1 |
ProcessUserAsyncJob | |
0.00% |
0 / 148 |
|
0.00% |
0 / 13 |
1980 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
handle | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
12 | |||
backoff | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
created | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
updated | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
20 | |||
performAction | |
0.00% |
0 / 15 |
|
0.00% |
0 / 1 |
56 | |||
updateUserInfoForDailyUsage | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
20 | |||
validateUpdatedFieldsForDailyUsage | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
parseFieldsForDailyUsage | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
2 | |||
createOrUpdateUserInfo | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
12 | |||
validateUpdatedFields | |
0.00% |
0 / 20 |
|
0.00% |
0 / 1 |
2 | |||
parseFields | |
0.00% |
0 / 59 |
|
0.00% |
0 / 1 |
182 | |||
formatToCarbonDate | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
20 |
1 | <?php |
2 | |
3 | namespace App\Jobs; |
4 | |
5 | use App\Traits\ObjectMapper; |
6 | use Illuminate\Bus\Queueable; |
7 | use Illuminate\Contracts\Queue\ShouldQueue; |
8 | use Illuminate\Foundation\Bus\Dispatchable; |
9 | use Illuminate\Queue\InteractsWithQueue; |
10 | use Illuminate\Queue\SerializesModels; |
11 | |
12 | use App\Helpers\FlyMSGLogger; |
13 | use App\Http\Models\Admin\Company; |
14 | use App\Http\Models\Admin\CompanyGroup; |
15 | use App\Http\Models\Auth\User; |
16 | use App\Mail\BusinessProEnterpriseMail; |
17 | use App\Http\Models\Admin\CompanyLicenses; |
18 | use App\Http\Models\FlyMsgUserDailyUsage; |
19 | use App\Http\Models\UserInfo; |
20 | use App\Services\Email\EmailService; |
21 | use App\Services\UserInfo\SubscriptionService; |
22 | use Carbon\Carbon; |
23 | use MongoDB\BSON\UTCDateTime; |
24 | |
25 | class ProcessUserAsyncJob implements ShouldQueue |
26 | { |
27 | use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, ObjectMapper; |
28 | |
29 | public $tries = 5; |
30 | |
31 | public function __construct( |
32 | public User $user, |
33 | public string $action, |
34 | private readonly EmailService $emailService |
35 | ) {} |
36 | |
37 | public function handle(): void |
38 | { |
39 | if ($this->action === 'created') { |
40 | $this->created($this->user); |
41 | } elseif ($this->action === 'updated') { |
42 | $this->updated($this->user); |
43 | } |
44 | } |
45 | |
46 | public function backoff() |
47 | { |
48 | return [10, 30, 60, 120, 300]; |
49 | } |
50 | |
51 | private function created(User $user): void |
52 | { |
53 | $created = $user->toArray(); |
54 | |
55 | $parsedFields = $this->parseFields($created, $user); |
56 | |
57 | $this->createOrUpdateUserInfo($parsedFields); |
58 | } |
59 | |
60 | private function updated(User $user): void |
61 | { |
62 | $updated = $user->toArray(); |
63 | |
64 | if (!empty($updated)) { |
65 | $fields = $this->validateUpdatedFields($updated); |
66 | |
67 | if (!empty($fields)) { |
68 | $parsedFields = $this->parseFields($updated, $user); |
69 | |
70 | $this->createOrUpdateUserInfo($parsedFields); |
71 | } |
72 | |
73 | $dailyFields = $this->validateUpdatedFieldsForDailyUsage($updated); |
74 | |
75 | if (!empty($dailyFields)) { |
76 | $parsedFieldsForDailyUsage = $this->parseFieldsForDailyUsage($updated); |
77 | |
78 | $this->updateUserInfoForDailyUsage($parsedFieldsForDailyUsage, $user); |
79 | } |
80 | } |
81 | } |
82 | |
83 | private function performAction(User $authUser, User $user, string $action, string $businessProChoice = 'yes_dedicated') |
84 | { |
85 | if ($authUser->isAdmin() && filled($user->company)) { |
86 | try { |
87 | $companyLicense = CompanyLicenses::where('company_id', $user->company_id)->active()->first(); |
88 | |
89 | if ( |
90 | $companyLicense && |
91 | $companyLicense->business_pro_enterprise_plus && |
92 | in_array($businessProChoice, $companyLicense->business_pro_enterprise_plus) |
93 | ) { |
94 | $this->emailService->send( |
95 | config('romeo.support-email'), |
96 | new BusinessProEnterpriseMail($action, $user->company->name, $authUser->email, $user->email), |
97 | 'admin_user_has_been_added', |
98 | true, |
99 | null, |
100 | true |
101 | ); |
102 | } |
103 | } catch (\Exception $e) { |
104 | FlyMSGLogger::logError(__METHOD__, $e); |
105 | } |
106 | } |
107 | } |
108 | |
109 | private function updateUserInfoForDailyUsage(array $data, User $user) |
110 | { |
111 | if ($data['hubspot_id'] ?? null) { |
112 | FlyMsgUserDailyUsage::where('user_id', $user->id)->update(['hubspot_id' => $data['hubspot_id']]); |
113 | } |
114 | |
115 | if ($data['group_id'] ?? null) { |
116 | FlyMsgUserDailyUsage::where('user_id', $user->id)->where('company_id', $user->company_id)->update(['group_id' => $data['group_id']]); |
117 | } |
118 | |
119 | $category = $user->company_id ? 'corporate' : 'individuals'; |
120 | |
121 | FlyMsgUserDailyUsage::where('user_id', $user->id)->update(['category' => $category]); |
122 | } |
123 | |
124 | private function validateUpdatedFieldsForDailyUsage(array $updated): array |
125 | { |
126 | $hubspotFields = [ |
127 | 'id', |
128 | 'hubspot_id', |
129 | 'group_id' |
130 | ]; |
131 | |
132 | return array_filter($updated, fn($key) => in_array($key, $hubspotFields), ARRAY_FILTER_USE_KEY); |
133 | } |
134 | |
135 | private function parseFieldsForDailyUsage(array $fields): array |
136 | { |
137 | $map = [ |
138 | 'id' => ['rename' => 'user_id'], |
139 | 'company_id' => [], |
140 | 'group_id' => [], |
141 | 'hubspot_id' => [], |
142 | ]; |
143 | |
144 | return $this->mapObject($fields, $map); |
145 | } |
146 | |
147 | private function createOrUpdateUserInfo(array $data) |
148 | { |
149 | $userInfo = UserInfo::firstOrNew(['email' => $data['email']]); |
150 | |
151 | $user = User::find($data['user_id']); |
152 | |
153 | if (empty($userInfo->subscription_type) && !empty($user->email_verified_at)) { |
154 | $subscriptionService = new SubscriptionService(); |
155 | $props = $subscriptionService->initFreemiumSubscription($user->id); |
156 | $data = array_merge($data, $props); |
157 | } |
158 | |
159 | $userInfo->fill($data); |
160 | $userInfo->save(); |
161 | } |
162 | |
163 | private function validateUpdatedFields(array $updated): array |
164 | { |
165 | $hubspotFields = [ |
166 | 'first_name', |
167 | 'last_name', |
168 | 'email', |
169 | 'email_verified_at', |
170 | 'created_at', |
171 | 'updated_at', |
172 | 'id', |
173 | 'signup_source', |
174 | 'company_id', |
175 | 'company_group_id', |
176 | 'stripe_id', |
177 | 'status', |
178 | 'avatar', |
179 | 'hubspot_id', |
180 | 'instancy_id', |
181 | 'group_id', |
182 | 'heap_analytics_id' |
183 | ]; |
184 | |
185 | return array_filter($updated, fn($key) => in_array($key, $hubspotFields), ARRAY_FILTER_USE_KEY); |
186 | } |
187 | |
188 | private function parseFields(array $fields, User $user): array |
189 | { |
190 | $map = [ |
191 | 'first_name' => [], |
192 | 'last_name' => [], |
193 | 'email' => [], |
194 | 'signup_source' => [], |
195 | 'company_id' => [], |
196 | 'hubspot_id' => [], |
197 | 'instancy_id' => [], |
198 | 'avatar' => [], |
199 | 'status' => [], |
200 | 'heap_analytics_id' => [], |
201 | 'id' => ['rename' => 'user_id'], |
202 | 'company_group_id' => ['rename' => 'group_id'], |
203 | ]; |
204 | |
205 | $result = $this->mapObject($fields, $map); |
206 | |
207 | $result['user_id'] = $user->id; |
208 | |
209 | if (!empty($fields['first_name']) || !empty($fields['last_name'])) { |
210 | $result['full_name'] = $user->first_name . ' ' . $user->last_name; |
211 | } |
212 | |
213 | if (!empty($fields['stripe_id'])) { |
214 | $result['df_stripe_customer_id'] = $fields['stripe_id']; |
215 | $result['stripe_id'] = $fields['stripe_id']; |
216 | } |
217 | |
218 | if (!empty($fields['created_at'])) { |
219 | $carbonCreationDate = Carbon::parse($fields['created_at']); |
220 | $result['account_creation_date'] = new UTCDateTime($carbonCreationDate->getTimestamp() * 1000); |
221 | $result['user_created_at'] = new UTCDateTime($carbonCreationDate->getTimestamp() * 1000); |
222 | } |
223 | |
224 | if (!empty($fields['updated_at'])) { |
225 | $carbonUpdateDate = Carbon::parse($fields['updated_at']); |
226 | $result['user_updated_at'] = new UTCDateTime($carbonUpdateDate->getTimestamp() * 1000); |
227 | } |
228 | |
229 | if (!empty($fields['email_verified_at'])) { |
230 | $carbonDate = Carbon::createFromTimestamp($fields['email_verified_at']->toDateTime()->getTimestamp()); |
231 | $result['email_verified_at'] = new UTCDateTime($carbonDate->getTimestamp() * 1000); |
232 | } |
233 | |
234 | if (!empty($fields['email'])) { |
235 | $result['email_domain'] = strrchr($user->email, "@"); |
236 | $result['email_domain_count'] = UserInfo::where('email_domain', $result['email_domain'])->count(); |
237 | |
238 | $userInfoDispatcher = UserInfo::getEventDispatcher(); |
239 | UserInfo::unsetEventDispatcher(); |
240 | |
241 | UserInfo::where('email_domain', $result['email_domain'])->update(['email_domain_count' => $result['email_domain_count']]); |
242 | |
243 | if ($userInfoDispatcher) { |
244 | UserInfo::setEventDispatcher($userInfoDispatcher); |
245 | } |
246 | } |
247 | |
248 | if (!empty($fields['status'])) { |
249 | $result['status_date'] = now(); |
250 | } |
251 | |
252 | if (!empty($fields['company_id'])) { |
253 | $companyName = Company::find($fields['company_id'])->name; |
254 | $result['company'] = $companyName; |
255 | $result['company_name'] = $companyName; |
256 | } else { |
257 | $result['company'] = 'Individual'; |
258 | $result['company_name'] = 'Individual'; |
259 | } |
260 | |
261 | if (!empty($fields['company_group_id'])) { |
262 | $group = CompanyGroup::find($fields['company_group_id']); |
263 | $parentGroup = CompanyGroup::where('id', $group->parent_id)->first(); |
264 | |
265 | if ($parentGroup) { |
266 | $result['group_id'] = $parentGroup->id; |
267 | $result['group_name'] = $parentGroup->name; |
268 | $result['subgroup_id'] = $group->id; |
269 | $result['subgroup_name'] = $group->name; |
270 | } else { |
271 | $result['group_id'] = $group->id; |
272 | $result['group_name'] = $group->name; |
273 | } |
274 | } else { |
275 | $result['group_name'] = null; |
276 | } |
277 | |
278 | return $result; |
279 | } |
280 | |
281 | private function formatToCarbonDate($value): ?string |
282 | { |
283 | if ($value instanceof Carbon) { |
284 | return $value->toDateString(); |
285 | } |
286 | |
287 | try { |
288 | return Carbon::parse($value)->toDateString(); |
289 | } catch (\Exception $e) { |
290 | try { |
291 | return Carbon::createFromTimestampMs($value)->toDateString(); |
292 | } catch (\Exception $e) { |
293 | return null; |
294 | } |
295 | return null; |
296 | } |
297 | } |
298 | } |