Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 115
0.00% covered (danger)
0.00%
0 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
ClearEmailProcessing
0.00% covered (danger)
0.00%
0 / 115
0.00% covered (danger)
0.00%
0 / 2
1260
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 / 114
0.00% covered (danger)
0.00%
0 / 1
1190
1<?php
2
3namespace App\Console\Commands;
4
5use Illuminate\Console\Command;
6use Illuminate\Support\Facades\DB;
7use Illuminate\Support\Facades\Storage;
8use Illuminate\Support\Facades\Log;
9use Illuminate\Support\Facades\Http;
10use Illuminate\Support\Facades\Cache;
11use App\Models\TblSendgridWebhook;
12use App\Models\TblQuotations;
13
14class ClearEmailProcessing extends Command
15{
16    /**
17     * The name and signature of the console command.
18     *
19     * @var string
20     */
21    protected $signature = 'clear:email-processing';
22    
23
24    /**
25     * The console command description.
26     *
27     * @var string
28     */
29    protected $description = 'Clear email processing';
30
31    /**
32     * Create a new command instance.
33     *
34     * @return void
35     */
36    public function __construct()
37    {
38        parent::__construct();
39    }
40
41    /**
42     * Execute the console command.
43     *
44     * @return int
45     */
46    public function handle()
47    {
48        try {
49
50            $startedAt = date('Y-m-d H:i:s');
51
52            $query = "SELECT 
53                        id,
54                        email,
55                        x_message_id,
56                        x_status
57                    FROM tbl_quotations 
58                    WHERE (x_status IS NOT NULL AND x_status != 'Completed') 
59                    AND x_message_id IS NOT NULL";
60
61            $result = DB::select($query);
62
63            $emailErrors = array('deferred', 'bounce', 'dropped', 'spamreport', 'invalid');
64            
65            if(count($result) > 0){
66
67                $quoteIds = array();
68
69                for ($i = 0; $i < count($result); $i++) {                     
70                    $emails = explode(",", str_replace(" ", "", $result[$i]->email));
71                    $xMessageId = $result[$i]->x_message_id;
72                    $xOrderStatus = $result[$i]->x_status;
73
74                    $sendGrid = TblSendgridWebhook::where('x_message_id', $xMessageId)->first();
75
76                    if($sendGrid){
77
78                        $events = json_decode($sendGrid->json_body, true);
79                        $xStatus = "processed";
80                        $isProcessed = 0;
81                        $isDelivered = 0;
82                        $isError = 0;
83                        $eventsUpdated = false;
84
85                        foreach ($emails as $email) {
86
87                            $emailEvents = array_filter($events, fn($event) => strtolower($event['email']) === strtolower($email));
88
89                            $statuses = array_unique(array_column($emailEvents, 'event'));
90                            $eventCount = count($statuses);
91                            
92                            if ($eventCount === 1 && in_array('processed', $statuses)) {
93                                $xStatus = "processed";
94                            }
95                            
96                            if ($eventCount == 2) {
97                                if (in_array('processed', $statuses) && in_array('delivered', $statuses)) {
98                                    $xStatus = "delivered";
99                                }
100                                
101                                foreach ($emailErrors as $e) {
102                                    if (in_array('processed', $statuses) && in_array($e, $statuses)) {
103                                        $xStatus = $e;
104                                    }
105                                }
106                            }elseif($eventCount > 2){
107                                if (in_array('processed', $statuses) && in_array('delivered', $statuses)) {
108                                    $xStatus = "delivered";
109                                }
110                                                        
111                                if($xStatus != "delivered"){
112                                    foreach ($emailErrors as $e) {
113                                        if (in_array('processed', $statuses) && in_array($e, $statuses)) {
114                                            $xStatus = $e;
115                                            break;
116                                        }
117                                    }   
118                                }
119                            }
120                            
121                            if($xStatus == "processed"){
122                                $query = urlencode('msg_id LIKE "' . $xMessageId . '%" AND to_email IN ("' . $email .'")');                                
123                                $response = Http::withToken('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')
124                                    ->get("https://api.sendgrid.com/v3/messages?limit=10&query={$query}");
125                            
126                                $data = $response->json();
127                            
128                                if (!empty($data['messages'])) {
129                                    $xStatus = $data['messages'][0]['status'] ?? 'processed';
130
131                                    if($xStatus == "delivered"){                   
132                                        $data['messages'][0]['timestamp'] = strtotime($data['messages'][0]['last_event_time']);
133                                        unset($data['messages'][0]['last_event_time']);
134
135                                        $data['messages'][0]['email'] = $data['messages'][0]['to_email'];
136                                        unset($data['messages'][0]['to_email']);
137
138                                        $data['messages'][0]['event'] = $data['messages'][0]['status'];
139                                        unset($data['messages'][0]['status']);
140
141                                        $data['messages'][0]['click'] = $data['messages'][0]['clicks_count'];
142                                        unset($data['messages'][0]['clicks_count']);
143
144                                        $data['messages'][0]['open'] = $data['messages'][0]['opens_count'];
145                                        unset($data['messages'][0]['opens_count']);
146
147                                        array_push($events, $data['messages'][0]);
148                                        $eventsUpdated = true;
149                                    }
150                                }
151                            }
152
153                            if($xStatus == "processed"){
154                                $isProcessed++;
155                            }elseif($xStatus == "delivered"){
156                                $isDelivered++;                        
157                            }else{
158                                $isError++;
159                            }
160                        }
161
162                        if($eventsUpdated){
163                            TblSendgridWebhook::where('x_message_id', $xMessageId)->update(
164                                array(
165                                    'updated_at' => date('Y-m-d H:i:s'), 
166                                    'json_body' => json_encode($events)
167                                )
168                            );
169                        }
170
171                        if(count($emails) == $isDelivered){
172                            $xStatus = "Completed";
173                        }elseif($isProcessed > 0){
174                            $xStatus = "Processing";
175                        }elseif($isError > 0){                            
176                            if($xStatus == "bounce"){
177                                $xStatus = "Error - Bounce";
178                            }else{
179                                $xStatus = "Error";  
180                            }
181                        }
182
183                        if($xOrderStatus != $xStatus){
184                            TblQuotations::where('id', $result[$i]->id)->update(
185                                array(
186                                    'x_status' => $xStatus
187                                )
188                            );                            
189
190                            Log::channel('clear_email_processing')->info($xMessageId . ": OK");
191                        }                        
192                    }
193                }                
194
195                if(count($quoteIds) > 0){
196                    TblQuotations::whereIn('id', $quoteIds)->update(
197                        array(
198                            'x_status' => null,
199                            'x_message_id' => null
200                        )
201                    );
202
203                    TblSendgridWebhook::whereIn('quotation_id', $quoteIds)->delete();
204                }
205            }
206
207            $query = "SELECT 
208                        a.x_message_id
209                    FROM 
210                        tbl_quotations a 
211                    LEFT JOIN 
212                        tbl_sendgrid_webhook b 
213                        ON a.x_message_id = b.x_message_id 
214                    WHERE 
215                        a.x_status = 'Processing'
216                        AND a.x_status IS NOT NULL
217                        AND (b.updated_at < NOW() - INTERVAL 30 DAY OR b.x_message_id IS NULL)";
218
219            $result = DB::select($query);
220
221            $idsCollection = collect($result)->pluck('x_message_id');
222
223            $idsString = $idsCollection->map(function($id) {
224                                return "'" . $id . "'";
225                            })
226                            ->implode(',');
227
228            $totalCount = $idsCollection->count();
229
230            if($totalCount > 0){
231                $query = "DELETE FROM tbl_sendgrid_webhook
232                            WHERE x_message_id IN ({$idsString})";
233
234                $result = DB::select($query);
235
236                $query = "UPDATE tbl_quotations 
237                            SET x_message_id = NULL, x_status = NULL 
238                            WHERE x_message_id IN ({$idsString})";
239
240                $result = DB::select($query);
241            }            
242
243            TblQuotations::whereNull('x_message_id')->where('x_status', 'Processing')->update(['x_status' => null]);
244            
245            Cache::flush();
246
247        } catch (\Exception $e) {
248            Log::channel('clear_email_processing')->error($e->getMessage());
249        }
250    }    
251}