Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
10.53% covered (danger)
10.53%
8 / 76
42.86% covered (danger)
42.86%
3 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
SettingController
10.53% covered (danger)
10.53%
8 / 76
42.86% covered (danger)
42.86%
3 / 7
134.05
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
 update
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 details
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 generateJwt
0.00% covered (danger)
0.00%
0 / 30
0.00% covered (danger)
0.00%
0 / 1
2
 base64UrlEncode
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 updateCompany
0.00% covered (danger)
0.00%
0 / 23
0.00% covered (danger)
0.00%
0 / 1
20
 getCompanySettings
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2
3namespace App\Http\Controllers\v1;
4
5use App\Http\Controllers\Controller;
6use App\Http\Models\Setting;
7use App\Http\Requests\CompanySettingFormRequest;
8use App\Http\Requests\v1\Setting\UpdateUserSettingRequest;
9use App\Http\Services\StatisticsService;
10use App\Http\Services\UserSettingService;
11use Illuminate\Http\JsonResponse;
12use Illuminate\Http\Request;
13
14/**
15 * Setting Controller
16 *
17 * Manages user and company settings operations including retrieval and updates.
18 * User settings logic is delegated to UserSettingService.
19 */
20class SettingController extends Controller
21{
22    /**
23     * @param  UserSettingService  $userSettingService  Handles user settings business logic
24     * @param  StatisticsService  $statisticsService  For company settings defaults
25     */
26    public function __construct(
27        private UserSettingService $userSettingService,
28        private StatisticsService $statisticsService
29    ) {}
30
31    /**
32     * Update user settings.
33     *
34     * Updates the authenticated user's settings. When wage_per_hour changes,
35     * the service tracks the history automatically.
36     *
37     * @param  UpdateUserSettingRequest  $request  Validated settings data
38     * @return JsonResponse Boolean indicating success
39     *
40     * @response 200 true
41     */
42    public function update(UpdateUserSettingRequest $request): JsonResponse
43    {
44        $result = $this->userSettingService->update(
45            $request->user(),
46            $request->validated()
47        );
48
49        return response()->json($result);
50    }
51
52    /**
53     * Get merged user settings details.
54     *
55     * Returns the complete settings for the authenticated user, merging
56     * global defaults, user overrides, computed values, and company settings.
57     *
58     * @return JsonResponse The merged settings
59     *
60     * @response 200 {"result": {"wage_per_hour": 31.65, "words_per_minute": 40, ...}}
61     */
62    public function details(Request $request): JsonResponse
63    {
64        $result = $this->userSettingService->getDetails($request->user());
65
66        return response()->json($result);
67    }
68
69    /**
70     * Generate a JWT token for FlyPerks integration.
71     *
72     * @param  array<string, mixed>  $user  User data array
73     * @return string The generated JWT
74     */
75    public function generateJwt($user)
76    {
77        // Header
78        $header = json_encode([
79            'typ' => 'JWT',
80            'alg' => 'HS256',
81        ]);
82        $base64UrlHeader = $this->base64UrlEncode($header);
83
84        // Payload
85        $now = time();
86        $common = [
87            'iat' => $now,
88            'jti' => md5($now.rand()),
89        ];
90
91        $secret = 'GPn5ch5eLuyKXrtwDcesqkY8NQzYzDHm3HNdmTHAZ08=';
92        $companyExternalId = 1414;
93        $companyName = 'vengreso';
94        $companyWebsite = 'https://vengreso.com';
95
96        $user_attributes = [
97            'user_external_id' => $user['id'],
98            'user_email' => $user['email'],
99            'user_first_name' => $user['first_name'],
100            'user_last_name' => $user['last_name'],
101            'company_external_id' => $user['id'],
102            'company_name' => $companyName.'_'.$user['email'],
103            'company_website' => 'https://'.$companyName.$user['email'].'.com',
104        ];
105
106        $payload = json_encode(array_merge($common, $user_attributes));
107        $base64UrlPayload = $this->base64UrlEncode($payload);
108
109        // JWT
110        $message = $base64UrlHeader.'.'.$base64UrlPayload;
111        $signature = hash_hmac('sha256', $message, $secret, true);
112        $base64UrlSignature = $this->base64UrlEncode($signature);
113        $jwt = $base64UrlHeader.'.'.$base64UrlPayload.'.'.$base64UrlSignature;
114
115        return $jwt;
116    }
117
118    /**
119     * Base64 URL encode a string.
120     *
121     * @param  string  $text  The text to encode
122     * @return string The base64url encoded string
123     */
124    public function base64UrlEncode($text)
125    {
126        return str_replace(
127            ['+', '/', '='],
128            ['-', '_', ''],
129            base64_encode($text)
130        );
131    }
132
133    /**
134     * Update company settings.
135     *
136     * @param  CompanySettingFormRequest  $request  Validated company settings data
137     * @return JsonResponse The updated company settings
138     *
139     * @response 200 {"result": {...}}
140     */
141    public function updateCompany(CompanySettingFormRequest $request): JsonResponse
142    {
143        $data = $request->validated();
144        $companyId = $request->company_id;
145        $company = $request->company;
146        $searchArray = ['company_id' => $companyId];
147
148        $setting = Setting::updateOrCreate($searchArray, [
149            'company_id' => $companyId,
150        ]);
151
152        if (! empty($data['wage_per_hour'])) {
153            $currentWagePerHour = $this->statisticsService->getCompanyWagePerHour($companyId, now());
154
155            if ($setting) {
156                $data['wage_per_hour_history'] = $setting->wage_per_hour_history ?? [];
157            }
158
159            if (count($data['wage_per_hour_history']) == 0) {
160                $data['wage_per_hour_history'] = [[
161                    'wage_per_hour' => $currentWagePerHour,
162                    'date' => $company->created_at->format('Y-m-d H:i:s'),
163                ]];
164            }
165
166            $data['wage_per_hour_history'] = array_merge($data['wage_per_hour_history'], [[
167                'wage_per_hour' => $data['wage_per_hour'],
168                'date' => now()->format('Y-m-d H:i:s'),
169            ]]);
170        }
171
172        $setting->fill($data);
173        $setting->save();
174
175        return response()->json($setting->fresh());
176    }
177
178    /**
179     * Get company settings.
180     *
181     * @return JsonResponse The company settings merged with defaults
182     *
183     * @response 200 {"result": {...}}
184     */
185    public function getCompanySettings(Request $request): JsonResponse
186    {
187        $companyId = $request->company_id;
188        $settings = $this->statisticsService->getCompanyDefaultSetting();
189
190        $companySetting = Setting::where('company_id', $companyId)->first();
191
192        if ($companySetting) {
193            $settings = array_merge($settings, $companySetting->toArray());
194        }
195
196        if (! $settings['wage_per_hour']) {
197            $settings['wage_per_hour'] = $this->statisticsService->getCompanyDefaultSetting()['wage_per_hour'];
198        }
199
200        if (! $settings['words_per_minute']) {
201            $settings['words_per_minute'] = $this->statisticsService->getCompanyDefaultSetting()['words_per_minute'];
202        }
203
204        return response()->json($settings);
205    }
206}