Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 186
0.00% covered (danger)
0.00%
0 / 11
CRAP
0.00% covered (danger)
0.00%
0 / 1
UserController
0.00% covered (danger)
0.00%
0 / 186
0.00% covered (danger)
0.00%
0 / 11
2162
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 update
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
30
 details
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
2
 delete
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
2
 setHeapId
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 getUserBillingData
0.00% covered (danger)
0.00%
0 / 37
0.00% covered (danger)
0.00%
0 / 1
90
 patchOnboarding
0.00% covered (danger)
0.00%
0 / 20
0.00% covered (danger)
0.00%
0 / 1
56
 getOnboardingQuestions
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 storeOnboardingQuestionAnswers
0.00% covered (danger)
0.00%
0 / 63
0.00% covered (danger)
0.00%
0 / 1
306
 acceptCompanyInvitation
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 rejectCompanyInvitation
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace App\Http\Controllers\v1;
4
5use App\Http\Controllers\Controller;
6use App\Http\Models\Auth\User;
7use App\Http\Models\FlyGrammarLanguage;
8use App\Http\Models\OnboardingAnswer;
9use App\Http\Models\OnboardingQuestion;
10use App\Http\Models\Plans;
11use App\Http\Models\Setting;
12use App\Http\Models\UserInfo;
13use App\Http\Requests\UserFormRequest;
14use App\Http\Services\Admin\Users\AdminUsersService;
15use App\Http\Services\CacheInvalidationService;
16use Carbon\Carbon;
17use Illuminate\Http\JsonResponse;
18use Illuminate\Http\Request;
19use Illuminate\Support\Facades\Cache;
20use Illuminate\Support\Facades\Config;
21use Illuminate\Support\Facades\Log;
22
23class UserController extends Controller
24{
25    /**
26     * Create a new controller instance.
27     *
28     * @return void
29     */
30    public function __construct(
31        private AdminUsersService $adminUsersService,
32        private CacheInvalidationService $cacheInvalidationService,
33    ) {}
34
35    public function update(UserFormRequest $request)
36    {
37        $data = $request->validated();
38        $user = $request->user();
39        $userId = $user->getKey();
40
41        $result = User::where('_id', $userId)->update($data);
42        $userInfo = UserInfo::where('email', $user->email)->first();
43
44        if (! $userInfo) {
45            $userInfo = UserInfo::where('user_id', $userId)->first();
46        }
47
48        if (isset($data['title'])) {
49            $userInfo->job_title = $data['title'];
50        }
51
52        if (isset($data['company_name'])) {
53            $userInfo->company = $data['company_name'];
54        }
55
56        if (isset($data['phone_number'])) {
57            $userInfo->phone = $data['phone_number'];
58        }
59
60        $userInfo->save();
61
62        // Query-builder update above bypasses model events, so invalidate explicitly.
63        $this->cacheInvalidationService->invalidateUserCache($userId);
64
65        return response()->json((bool) $result);
66    }
67
68    public function details(Request $request)
69    {
70        $userId = $request->user()->getKey();
71        $cacheKey = 'user_details_'.$userId;
72        $result = Cache::remember($cacheKey, Config::get('cache.expiry'), function () use ($request) {
73            $userId = $request->user()->getKey();
74            $searchArray = ['_id' => $userId];
75            $result = User::where($searchArray)->first();
76            $result['is_poc'] = $result->isPOC();
77
78            $result['is_password_set'] = $result->isPasswordSet();
79
80            return $result;
81        });
82
83        return response()->json($result);
84    }
85
86    public function delete(Request $request): JsonResponse
87    {
88        Log::info('User delete request', [
89            'user' => $request->user()->email,
90            'ip' => $request->ip(),
91            'date' => Carbon::now()->toDateTimeString(),
92        ]);
93
94        // Notification::send($request->user(), new DeleteAccount);
95
96        $userId = $request->user()->getKey();
97        $user = User::where('_id', $userId)->first();
98
99        $this->adminUsersService->delete($user);
100
101        return response()->json(
102            data: [
103                'success' => true,
104                'message' => 'user deleted successfully',
105            ],
106            status: 200
107        );
108    }
109
110    public function setHeapId(Request $request, User $user): JsonResponse
111    {
112        if (isset($request->heap_analytics_id)) {
113            $user->heap_analytics_id = $request->heap_analytics_id;
114            $user->save();
115        }
116
117        return response()->json([], 201);
118    }
119
120    public function getUserBillingData(Request $request): JsonResponse
121    {
122        try {
123            $data = [];
124            $user = $request->user();
125
126            $data['payment_methods'] = $user->paymentMethods();
127            $data['default_payment_method'] = $user->defaultPaymentMethod();
128            $invoices = $user->invoices()->toArray();
129
130            foreach ($invoices as $key => $invoice) {
131                // Formating time.
132                $time_start = $invoice['status_transitions']['finalized_at'];
133                $d_start = new \DateTime(date('F jS, Y', $time_start));
134
135                // Setting intervel.
136                $last_index = $invoice['lines']['total_count'] - 1;
137                $interval = $invoice['lines']['data'][$last_index]['plan']['interval'];
138
139                if ($interval == 'year') {
140                    $interval = 'Annualy';
141                } else {
142                    $interval = 'Monthly';
143                }
144
145                // Billing reason.
146                $billing_reason = ucfirst($invoice['billing_reason']);
147                $billing_reason = str_replace('_', ' ', $billing_reason);
148
149                // Plan Name.
150                $plan_name = $invoice['lines']['data'][$last_index]['plan']['nickname'];
151
152                // Incase of null get the name from DB
153                if (! $plan_name) {
154                    $plan_id = $invoice['lines']['data'][$last_index]['plan']['id'];
155                    $plan = Plans::where('stripe_id', $plan_id)->first();
156                    if (isset($plan)) {
157                        $plan_name = $plan['title'];
158                    }
159                }
160
161                if (str_contains($plan_name, 'Growth')) {
162                    $plan_name = 'Growth';
163                }
164                if (str_contains($plan_name, 'Starter')) {
165                    $plan_name = 'Starter';
166                }
167                if (str_contains($plan_name, 'Sales')) {
168                    $plan_name = 'Sales Pro';
169                }
170
171                // End of Plan Name.
172                $data['invoices'][$key]['plan_name'] = $plan_name.' Plan';
173                $data['invoices'][$key]['billing_reason'] = $billing_reason;
174                $data['invoices'][$key]['interval'] = $interval;
175                $data['invoices'][$key]['status'] = $invoice['status'];
176                $data['invoices'][$key]['total'] = $invoice['total'] / 100 .' '.ucfirst($invoice['currency']);
177                $data['invoices'][$key]['invoice_pdf'] = $invoice['invoice_pdf'];
178                $data['invoices'][$key]['billing_date'] = $d_start->format('F j, Y');
179            }
180
181            return response()->json($data);
182        } catch (\Exception $e) {
183            return response()->json([], 422);
184        }
185    }
186
187    public function patchOnboarding(Request $request, User $user): JsonResponse
188    {
189        try {
190            $validated_data = $request->validate([
191                'step' => 'required|numeric',
192                'max_step' => 'required|numeric',
193                'tooltip_learning_resources_showed' => 'sometimes|boolean',
194                'onboardingv2_presented' => 'sometimes|boolean',
195            ]);
196
197            $step = $validated_data['step'];
198            $max_step = $validated_data['max_step'];
199
200            if (empty($user->onboardingv2_step) || $step > $user->onboardingv2_step) {
201                $user->onboardingv2_step = $step;
202            }
203
204            if ($step > $max_step) {
205                $user->onboardingv2_completed = true;
206            }
207
208            if (isset($validated_data['tooltip_learning_resources_showed'])) {
209                $user->tooltip_learning_resources_showed = $validated_data['tooltip_learning_resources_showed'];
210            }
211
212            if (isset($validated_data['onboardingv2_presented'])) {
213                $user->onboardingv2_presented = $validated_data['onboardingv2_presented'];
214            }
215
216            $user->save();
217
218            return response()->json($user);
219        } catch (\Exception $e) {
220            return response()->json([], 422);
221        }
222    }
223
224    /**
225     * [getOnboardingQuestions function to get onboarding process questions]
226     *
227     * @param  Request  $request  []
228     * @return [json] [list of all questions step wise]
229     */
230    public function getOnboardingQuestions(Request $request): JsonResponse
231    {
232        $user_onboarding = User::find(auth('api')->id());
233        $result['data'] = OnboardingQuestion::all();
234
235        $result['steps'] = [
236            'next_step' => $user_onboarding?->onboarding_step + 1,
237            'onboarding_percentage' => $user_onboarding?->onboarding_percentage ?? 0,
238        ];
239
240        return response()->json($result);
241    }
242
243    /**
244     * [storeOnboardingQuestionAnswers function to store onboarding process question answers]
245     *
246     * @param  Request  $request  []
247     * @return [json] [true/false]
248     */
249    public function storeOnboardingQuestionAnswers(Request $request): JsonResponse
250    {
251        $searchArray = [
252            'user_id' => $request->user_id,
253            'question_id' => $request->question_id,
254            'step' => $request->step,
255        ];
256
257        $userDetails = User::find($request->user_id);
258        if ($userDetails) {
259            $user_email = $userDetails['email'];
260        } else {
261            $user_email = $request->user()->email;
262        }
263
264        $userInfo = UserInfo::where('email', $user_email)->first();
265
266        $result = null;
267        if ($request->question_id) {
268            $existingAnswer = OnboardingAnswer::where($searchArray)->first();
269
270            if (! empty($existingAnswer)) {
271                $existingAnswer->answer = $request->answer;
272                $result = $existingAnswer->save();
273            } else {
274                $data = $request->all();
275                $data['next_step'] = $request->step + 1;
276                $result = OnboardingAnswer::create($data);
277            }
278
279            if ($request->step == 1) {
280                if ($request->question_index_id == 1) {
281                    $language = FlyGrammarLanguage::where('description', $request->answer)->first();
282
283                    if ($language) {
284                        $userInfo->fly_grammar_default_language = $language->value;
285                    } else {
286                        $userInfo->fly_grammar_default_language = 'auto';
287                    }
288
289                    $result = Setting::where('user_id', $request->user_id)->update([
290                        'fly_grammar_default_language' => $userInfo->fly_grammar_default_language,
291                    ]);
292                }
293
294                if ($request->question_index_id == 2) {
295                    $userInfo->department = $request->answer;
296                }
297
298                if ($request->question_index_id == 4) {
299                    $userInfo->flymsg_use_case = $request->answer;
300                }
301
302                if ($request->question_index_id == 3) {
303                    $userInfo->job_role = $request->answer;
304                }
305            }
306
307            if ($request->step == 2 && $request->question_index_id == 1) {
308                // get question details
309                $quesArray = [
310                    '_id' => $request->question_id,
311                ];
312
313                $question = OnboardingQuestion::where($quesArray)->first()->toArray();
314                $step2options = $question['questions'][1]['options'];
315                array_pop($step2options);
316
317                // parse the answer
318                $other_option_value = $productivity_problems_answer = '';
319                $is_other_option_exists = false;
320                $answer_options = json_decode($request->answer);
321                if (! empty($answer_options)) {
322                    foreach ($answer_options as $answer_option) {
323                        if (! in_array($answer_option, $step2options)) {
324                            $other_option_value = $answer_option;
325                            $is_other_option_exists = true;
326                        }
327                    }
328
329                    if ($is_other_option_exists) {
330                        array_pop($answer_options);
331                    }
332
333                    $productivity_problems_answer = implode(';', $answer_options);
334                }
335
336                $userInfo->productivity_problems = $productivity_problems_answer;
337                $userInfo->type_here_how_flymsg_will_help_you___ = $other_option_value;
338            }
339        }
340
341        $userInfo->save();
342
343        // Store onboarding status in the user document.
344        $userData['onboarding_step'] = $request->step;
345        $userData['onboarding_percentage'] = ((int) $request->step / 10) * 100; // 10 steps counts
346        if ($request->step == 10) {
347            $userData['onboarding'] = 'completed';
348            $userData['onboarding_percentage'] = 100;
349        }
350        $result = User::where('_id', $request->user_id)->update($userData);
351        $result = $userData;
352
353        return response()->json($result);
354    }
355
356    public function acceptCompanyInvitation(Request $request, User $user)
357    {
358        $validated_data = $request->validate([
359            'company_id' => 'required|string',
360        ]);
361
362        $company_id = $validated_data['company_id'];
363
364        $user = $this->adminUsersService->acceptUserInvitation($user, $company_id);
365
366        return response()->json($user->toArray());
367    }
368
369    public function rejectCompanyInvitation(Request $request, User $user)
370    {
371        $validated_data = $request->validate([
372            'company_id' => 'required|string',
373        ]);
374
375        $company_id = $validated_data['company_id'];
376
377        $user = $this->adminUsersService->rejectUserInvitation($user, $company_id);
378
379        return response()->json($user->toArray());
380    }
381}