Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 209
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
ItvEmailReminders
0.00% covered (danger)
0.00%
0 / 209
0.00% covered (danger)
0.00%
0 / 5
812
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
 handle
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
6
 isEmailValid
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 email_reminders
0.00% covered (danger)
0.00%
0 / 121
0.00% covered (danger)
0.00%
0 / 1
272
 email_reminders_mileage
0.00% covered (danger)
0.00%
0 / 76
0.00% covered (danger)
0.00%
0 / 1
56
1<?php
2
3namespace App\Console\Commands;
4
5use App\Models\TblItv;
6use App\Models\TblUsers;
7use Illuminate\Console\Command;
8use Illuminate\Support\Facades\Cache;
9use Illuminate\Support\Facades\DB;
10use Illuminate\Support\Facades\Log;
11
12class ItvEmailReminders extends Command
13{
14    /**
15     * The name and signature of the console command.
16     *
17     * @var string
18     */
19    protected $signature = 'itv:reminders {duration} {is_booked}';
20
21    /**
22     * The console command description.
23     *
24     * @var string
25     */
26    protected $description = 'Email reminders before ITV required';
27
28    /**
29     * Create a new command instance.
30     *
31     * @return void
32     */
33    public function __construct()
34    {
35        parent::__construct();
36    }
37
38    /**
39     * Execute the console command.
40     *
41     * @return int
42     */
43    public function handle()
44    {
45        try {
46
47            $duration = $this->argument('duration');
48            $isBooked = $this->argument('is_booked');
49
50            $this->email_reminders($duration, $isBooked);
51            $this->email_reminders_mileage($duration);
52
53        } catch (\Exception $e) {
54            Log::channel('itv_reminders')->error($e->getMessage());
55        }
56
57        return 0;
58    }
59
60    public function isEmailValid($email)
61    {
62        // Regular expression pattern for email validation
63        $pattern = '/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/';
64
65        // Check if the email matches the pattern
66        if (preg_match($pattern, $email)) {
67            return true; // Valid email
68        } else {
69            return false; // Invalid email
70        }
71    }
72
73    public function email_reminders($duration, $isBooked)
74    {
75
76        $where = '';
77        $due = '';
78        $body = '';
79        $subjectM = __('language.itv_reminders.subject');
80        $footer = __('language.itv_reminders.body_message_footer');
81
82        if ($isBooked == 0) {
83            if ($duration == 30) {
84                $where = 'DATE(a.next_itv_date) = DATE_ADD(CURDATE(), INTERVAL 30 DAY)';
85                $due = __('language.itv_reminders.in_one_month');
86            } elseif ($duration == 15) {
87                $where = 'DATE(a.next_itv_date) = DATE_ADD(CURDATE(), INTERVAL 15 DAY)';
88                $due = __('language.itv_reminders.in_15_days');
89            } elseif ($duration == 1) {
90                $where = 'DATE(a.next_itv_date) = DATE_ADD(CURDATE(), INTERVAL 1 DAY)';
91                $due = __('language.itv_reminders.tomorrow');
92                $subjectM = __('language.itv_reminders.subject_urgent');
93                $footer = __('language.itv_reminders.body_message_footer_urgent');
94            } else {
95                return response(['message' => 'KO']);
96            }
97            $where .= ' AND a.is_due IS NULL ';
98        } elseif ($isBooked == 1) {
99            if ($duration == 7) {
100                $where = 'DATE(a.appointment_date) = DATE_ADD(CURDATE(), INTERVAL 7 DAY)';
101                $due = __('language.itv_reminders.app_7_days');
102                $subjectM = __('language.itv_reminders.subject_7_days');
103                $footer = __('language.itv_reminders.body_message_footer_appointment_urgent');
104            } elseif ($duration == 1) {
105                $where = 'DATE(a.appointment_date) = DATE_ADD(CURDATE(), INTERVAL 1 DAY)';
106                $due = __('language.itv_reminders.app_tomorrow');
107                $subjectM = __('language.itv_reminders.subject_tomorrow');
108                $footer = __('language.itv_reminders.body_message_footer_appointment_urgent');
109            } else {
110                return response(['message' => 'KO']);
111            }
112            $where .= ' AND a.is_due_appointment IS NULL ';
113        }
114
115        $query = "SELECT 
116                    a.id,
117                    a.region, 
118                    a.company_id,
119                    b.name company_name,
120                    a.registration_date,
121                    a.brand, 
122                    a.vehicle_type,
123                    a.license_plate,
124                    a.mileage,
125                    a.last_itv_date,
126                    a.next_itv_date,
127                    DATE_FORMAT(a.next_itv_date, '%d/%m/%Y') next_itv_date_translate,
128                    DATE_FORMAT(a.appointment_date, '%d/%m/%Y') appointment_date_translate,
129                    a.is_due_appointment,
130                    a.location,
131                    a.is_booked,
132                    a.appointment_time,
133                    a.appointment_date,
134                    a.mileage_threshold,
135                    a.driver,
136                    a.responsible_name,
137                    a.responsible_email,
138                    a.created_by,
139                    a.created_at,
140                    a.updated_by,
141                    a.updated_at,
142                    CASE
143                        WHEN DATEDIFF(a.next_itv_date, NOW()) <= 0 THEN 0
144                        WHEN DATEDIFF(a.next_itv_date, NOW()) <= 1 THEN 1
145                        WHEN DATEDIFF(a.next_itv_date, NOW()) <= 15 THEN 15
146                        WHEN DATEDIFF(a.next_itv_date, NOW()) <= 30 THEN 30
147                    ELSE NULL
148                    END AS next_itv_date_due,
149                    a.is_due,
150                    a.is_due_mileage,
151                    a.comments
152                FROM 
153                    tbl_itv a 
154                    LEFT JOIN tbl_companies b ON a.company_id = b.company_id
155                WHERE {$where}";
156
157        $result = DB::select($query);
158
159        $totalSent = 0;
160
161        if (count($result) > 0) {
162            $body = '';
163            $subject = '';
164
165            foreach ($result as $item) {
166
167                $email = new \SendGrid\Mail\Mail;
168
169                $user = TblUsers::where('name', $item->created_by)->first();
170                $email->addTo($user->email);
171
172                if ($user->email != $item->responsible_email) {
173                    $isValid = $this->isEmailValid($item->responsible_email);
174                    if ($isValid) {
175                        $email->addTo($item->responsible_email);
176                    } else {
177                        Log::channel('itv_reminders')->error('Invalid email: '.$item->responsible_email);
178
179                        continue;
180                    }
181                }
182
183                $subject = $subjectM;
184                $subject = str_replace('{{brand}}', $item->brand, $subject);
185                $subject = str_replace('{{license_plate}}', $item->license_plate, $subject);
186
187                $email->setFrom('fire@fire.es', 'Fire Service Titan');
188                $email->setSubject($subject);
189
190                $imgpath = \File::get(public_path('fireservicetitan.png'));
191
192                $email->addAttachment(
193                    $imgpath,
194                    'image/png',
195                    'fireservicetitan.png',
196                    'inline',
197                    'fireservicetitan'
198                );
199
200                $url = env('URL')."itv/{$item->id}";
201
202                $bodyHeaders = __('language.itv_reminders.body_message_header');
203
204                if ($isBooked == 1) {
205                    $bodyHeaders = __('language.itv_reminders.body_message_header_appointment');
206                }
207
208                $body .= __('language.itv_reminders.body_hello');
209                $body = str_replace('{{responsible_name}}', $item->responsible_name, $body);
210
211                $body .= $bodyHeaders;
212                $body = str_replace('{{duration}}', $due, $body);
213                $body = str_replace('{{click}}', $url, $body);
214
215                $body .= __('language.itv_reminders.body_vehicle');
216                $body = str_replace('{{vehicle}}', $item->brand, $body);
217
218                $body .= __('language.itv_reminders.body_license_plate');
219                $body = str_replace('{{license_plate}}', $item->license_plate, $body);
220
221                $body .= __('language.itv_reminders.body_vehicle_type');
222                $body = str_replace('{{vehicle_type}}', $item->vehicle_type, $body);
223
224                if ($isBooked == 1) {
225                    $body .= __('language.itv_reminders.body_appointment_date');
226                    $item->appointment_date_translate = date('d/m/Y', strtotime($item->appointment_date));
227                    $body = str_replace('{{appointment_date}}', $item->appointment_date_translate, $body);
228
229                    $body .= __('language.itv_reminders.body_appointment_time');
230                    $formattedTime = date('g:i A', strtotime($item->appointment_time));
231                    $body = str_replace('{{appointment_time}}', $formattedTime, $body);
232
233                    $body .= __('language.itv_reminders.body_location');
234                    $body = str_replace('{{location}}', $item->location, $body);
235                } else {
236                    $body .= __('language.itv_reminders.body_next_itv_date');
237                    $item->next_itv_date_translate = date('m/Y', strtotime($item->next_itv_date));
238                    $body = str_replace('{{next_itv_date}}', $item->next_itv_date_translate, $body);
239
240                    $body .= __('language.itv_reminders.body_driver');
241                    $body = str_replace('{{driver}}', $item->driver, $body);
242                }
243
244                $body .= $footer;
245
246                $body .= '<p>Fire Service Titan</p>';
247                $body .= "<img src='cid:fireservicetitan' style='height: 45px;' />";
248
249                $html = '<!DOCTYPE html>';
250                $html .= '<html>';
251                $html .= '<head>';
252                $html .= '<meta charset="UTF-8">';
253                $html .= '<meta name="viewport" content="width=device-width, initial-scale=1.0">';
254                $html .= '</head>';
255                $html .= '<body>';
256                $html .= $body;
257                $html .= '</body>';
258                $html .= '</html>';
259
260                $email->setFrom('titan@fire.es');
261                $email->setSubject($subject);
262
263                $email->addContent('text/html', $html);
264
265                $sendgrid = new \SendGrid(env('SENDGRID_API_KEY'));
266
267                $response = $sendgrid->send($email);
268                if ($response->statusCode() == 202) {
269                    $totalSent++;
270
271                    $toUpdate = ['is_due' => $duration, 'updated_by' => 'System', 'updated_at' => date('Y-m-d H:i:s')];
272
273                    if ($isBooked == 1) {
274                        $toUpdate = ['is_due_appointment' => $duration, 'updated_by' => 'System', 'updated_at' => date('Y-m-d H:i:s')];
275                    }
276
277                    TblItv::where('id', $item->id)->update($toUpdate);
278                    Log::channel('itv_reminders')->error("ITV[{$duration}] OK: ".$item->responsible_email);
279                } else {
280                    Log::channel('itv_reminders')->error("ITV[{$duration}] KO: ".$response->body());
281                }
282
283                $body = '';
284                $subject = '';
285            }
286        }
287
288        Cache::flush();
289
290        Log::channel('itv_reminders')->info("ITV[{$duration}]: TotalSent[{$totalSent}]");
291    }
292
293    public function email_reminders_mileage($duration)
294    {
295
296        $where = '';
297        $due = '';
298
299        if ($duration == 3000) {
300            $where = 'ABS(a.mileage - a.mileage_threshold) BETWEEN 1 AND 3000';
301        } else {
302            return response(['message' => 'KO']);
303        }
304
305        $query = "SELECT 
306                    a.id,
307                    a.region, 
308                    a.company_id,
309                    b.name company_name,
310                    a.registration_date,
311                    a.brand, 
312                    a.vehicle_type,
313                    a.license_plate,
314                    a.mileage,
315                    a.last_itv_date,
316                    a.next_itv_date,
317                    DATE_FORMAT(a.next_itv_date, '%d/%m/%Y') next_itv_date_translate,
318                    a.mileage_threshold,
319                    a.driver,
320                    a.responsible_name,
321                    a.responsible_email,
322                    a.created_by,
323                    a.created_at,
324                    a.updated_by,
325                    a.updated_at,
326                    CASE
327                        WHEN DATEDIFF(a.next_itv_date, NOW()) <= 0 THEN 0
328                        WHEN DATEDIFF(a.next_itv_date, NOW()) <= 1 THEN 1
329                        WHEN DATEDIFF(a.next_itv_date, NOW()) <= 15 THEN 15
330                        WHEN DATEDIFF(a.next_itv_date, NOW()) <= 30 THEN 30
331                    ELSE NULL
332                    END AS next_itv_date_due,
333                    a.is_due,
334                    a.is_due_mileage,
335                    a.comments
336                FROM 
337                    tbl_itv a 
338                    LEFT JOIN tbl_companies b ON a.company_id = b.company_id
339                WHERE {$where} AND a.is_due_mileage IS NULL";
340
341        $result = DB::select($query);
342
343        $totalSent = 0;
344
345        if (count($result) > 0) {
346            $body = '';
347            $subject = '';
348
349            foreach ($result as $item) {
350
351                $email = new \SendGrid\Mail\Mail;
352
353                $user = TblUsers::where('name', $item->created_by)->first();
354                $email->addTo($user->email);
355
356                if ($item->created_by != $item->responsible_name) {
357                    $isValid = $this->isEmailValid($item->responsible_email);
358                    if ($isValid) {
359                        $email->addTo($item->responsible_email);
360                    } else {
361                        Log::channel('itv_reminders')->error('Invalid email: '.$item->responsible_email);
362
363                        continue;
364                    }
365                }
366
367                $subject = __('language.itv_reminders_km.subject');
368                $subject = str_replace('{{brand}}', $item->brand, $subject);
369                $subject = str_replace('{{license_plate}}', $item->license_plate, $subject);
370
371                $email->setFrom('fire@fire.es', 'Fire Service Titan');
372                $email->setSubject($subject);
373
374                $imgpath = \File::get(public_path('fireservicetitan.png'));
375
376                $email->addAttachment(
377                    $imgpath,
378                    'image/png',
379                    'fireservicetitan.png',
380                    'inline',
381                    'fireservicetitan'
382                );
383
384                $url = env('URL')."itv/{$item->id}";
385
386                $body .= __('language.itv_reminders_km.body_hello');
387                $body = str_replace('{{responsible_name}}', $item->responsible_name, $body);
388
389                $body .= __('language.itv_reminders_km.body_message_header');
390                $body = str_replace('{{click}}', $url, $body);
391
392                $body .= __('language.itv_reminders_km.body_vehicle');
393                $body = str_replace('{{vehicle}}', $item->brand, $body);
394
395                $body .= __('language.itv_reminders_km.body_license_plate');
396                $body = str_replace('{{license_plate}}', $item->license_plate, $body);
397
398                $body .= __('language.itv_reminders_km.body_vehicle_type');
399                $body = str_replace('{{vehicle_type}}', $item->vehicle_type, $body);
400
401                $body .= __('language.itv_reminders_km.body_mileage');
402                $body = str_replace('{{mileage}}', number_format($item->mileage, 2, ',', '.'), $body);
403
404                $body .= __('language.itv_reminders_km.body_mileage_threshold');
405                $body = str_replace('{{mileage_threshold}}', number_format($item->mileage_threshold, 2, ',', '.'), $body);
406
407                $body .= __('language.itv_reminders_km.body_message_footer');
408
409                $body .= '<p>Fire Service Titan</p>';
410                $body .= "<img src='cid:fireservicetitan' style='height: 45px;' />";
411
412                $html = '<!DOCTYPE html>';
413                $html .= '<html>';
414                $html .= '<head>';
415                $html .= '<meta charset="UTF-8">';
416                $html .= '<meta name="viewport" content="width=device-width, initial-scale=1.0">';
417                $html .= '</head>';
418                $html .= '<body>';
419                $html .= $body;
420                $html .= '</body>';
421                $html .= '</html>';
422
423                $email->setFrom('titan@fire.es');
424                $email->setSubject($subject);
425
426                $email->addContent('text/html', $html);
427
428                $sendgrid = new \SendGrid(env('SENDGRID_API_KEY'));
429
430                $response = $sendgrid->send($email);
431                if ($response->statusCode() == 202) {
432                    $totalSent++;
433                    TblItv::where('id', $item->id)->update(['is_due_mileage' => $duration]);
434                    Log::channel('itv_reminders')->error("ITV[{$duration}] OK: ".$item->responsible_email);
435                }
436
437                $body = '';
438                $subject = '';
439            }
440        }
441
442        Cache::flush();
443
444        Log::channel('itv_reminders')->info("ITV[{$duration}]: TotalSent[{$totalSent}]");
445    }
446}