Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
1.61% covered (danger)
1.61%
2 / 124
20.00% covered (danger)
20.00%
1 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
SendEmailInvoiceNewCreditDays
1.61% covered (danger)
1.61%
2 / 124
20.00% covered (danger)
20.00%
1 / 5
1270.30
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 handle
0.00% covered (danger)
0.00%
0 / 70
0.00% covered (danger)
0.00%
0 / 1
812
 send_email
0.00% covered (danger)
0.00%
0 / 43
0.00% covered (danger)
0.00%
0 / 1
12
 isEmailValid
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 detectDelimiter
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3namespace App\Console\Commands;
4
5use App\Models\TblCustomerChangeComms;
6use App\Services\GestionaService;
7use App\Services\SendgridLogger;
8use Illuminate\Console\Command;
9use Illuminate\Support\Facades\File;
10use Illuminate\Support\Facades\Log;
11use SendGrid\Mail\Mail;
12
13class SendEmailInvoiceNewCreditDays extends Command
14{
15    /**
16     * The name and signature of the console command.
17     *
18     * @var string
19     */
20    protected $signature = 'send:invoice-new-credit-days {invoiceDate?}';
21
22    /**
23     * The console command description.
24     *
25     * @var string
26     */
27    protected $description = 'Send email invoice new credit days';
28
29    protected $gestionaService;
30
31    /**
32     * Create a new command instance.
33     *
34     * @return void
35     */
36    public function __construct(GestionaService $gestionaService)
37    {
38        parent::__construct();
39        $this->gestionaService = $gestionaService;
40    }
41
42    /**
43     * Execute the console command.
44     *
45     * @return int
46     */
47    public function handle()
48    {
49        try {
50
51            $invoiceDate = $this->argument('invoiceDate') ?? null;
52
53            if ($invoiceDate != null) {
54                $d = \DateTime::createFromFormat('Y-m-d', $invoiceDate);
55
56                if (! $d || $d->format('Y-m-d') !== $invoiceDate) {
57                    throw new \InvalidArgumentException('Invalid date format. Expected Y-m-d.');
58                }
59            } else {
60                $invoiceDate = date('Y-m-d', strtotime('-1 day'));
61            }
62            $logo = File::get(public_path('fireservicetitan.png'));
63
64            $regions = [
65                'Catalunya',
66                'Madrid',
67                'Andalucía',
68                'Baleares',
69                'Comunidad Valenciana',
70            ];
71
72            foreach ($regions as $region) {
73                $yesterdayInvoices = $this->gestionaService->request('get', 'factura/vence/'.$invoiceDate, $region, []);
74
75                if (! empty($yesterdayInvoices) && ! empty($yesterdayInvoices['facturas'])) {
76
77                    for ($i = 0; $i < count($yesterdayInvoices['facturas']); $i++) {
78
79                        $email = new Mail;
80
81                        $invoiceId = $yesterdayInvoices['facturas'][$i]['ID'];
82                        $dataInvoice = $this->gestionaService->request('get', 'factura/'.$invoiceId, $region, []);
83
84                        if (! empty($dataInvoice) && ! empty($dataInvoice['factura'])) {
85
86                            if (isset($dataInvoice['factura']['cod_cliente'])) {
87
88                                $clientCode = $dataInvoice['factura']['cod_cliente'];
89                                $result = TblCustomerChangeComms::where('client_code', $clientCode)->where('email_sent_at', null)->first();
90
91                                if ($result != null) {
92
93                                    $clientInvoiceResponse = $this->gestionaService->request('get', 'cliente/'.$result->client_code, $result->region, []);
94
95                                    if (! empty($clientInvoiceResponse) && ! empty($clientInvoiceResponse['cliente'])) {
96                                        $addTo = [];
97                                        $toEmail = [];
98
99                                        if (config('services.sendgrid.staging')) {
100                                            $toEmail = ['christian@ibventur.es'];
101                                        } else {
102
103                                            if (isset($clientInvoiceResponse['cliente']['email_facturacion'])) {
104                                                $toEmail = $clientInvoiceResponse['cliente']['email_facturacion'];
105                                            }
106
107                                            if (isset($clientInvoiceResponse['cliente']['email'])) {
108                                                $toEmail = $clientInvoiceResponse['cliente']['email'];
109                                            }
110
111                                        }
112
113                                        if (! empty($toEmail)) {
114                                            $delimiter = $this->detectDelimiter($toEmail);
115                                            $toEmail = explode($delimiter, $toEmail);
116                                            $toEmail = array_map('trim', $toEmail);
117
118                                            $invalidEmailCount = 0;
119
120                                            foreach ($toEmail as $clientEmail) {
121                                                $isValid = $this->isEmailValid($clientEmail);
122                                                if ($isValid) {
123                                                    if (! in_array($clientEmail, $addTo)) {
124                                                        array_push($addTo, $clientEmail);
125                                                        $email->addTo($clientEmail);
126                                                    }
127                                                } else {
128                                                    $invalidEmailCount++;
129                                                    Log::channel('cron_send_email_invoice_new_credit_days')->error("[$result->client_code]: Invalid email address $clientEmail");
130                                                }
131                                            }
132
133                                            if ($invalidEmailCount != count($toEmail)) {
134                                                $this->send_email($result->id, $result->client_code, $result->client_name, $result->credit_days, $logo, $addTo, $email);
135                                            }
136                                        }
137
138                                        if(!empty($toEmail)){
139                                            $delimiter = $this->detectDelimiter($toEmail);
140                                            $toEmail = explode($delimiter, $toEmail);
141                                            $toEmail = array_map('trim', $toEmail); 
142
143                                            $invalidEmailCount = 0;
144                                            
145                                            foreach ($toEmail as $clientEmail) {
146                                                $isValid = $this->isEmailValid($clientEmail);
147                                                if ($isValid) {                                                    
148                                                    if (! in_array($clientEmail, $addTo)) {
149                                                        array_push($addTo, $clientEmail);
150                                                        $email->addTo($clientEmail);
151                                                    }
152                                                } else {
153                                                    $invalidEmailCount++;
154                                                    Log::channel('cron_send_email_invoice_new_credit_days')->error("[$result->client_code]: Invalid email address $clientEmail");
155                                                }
156                                            }
157
158                                            if ($invalidEmailCount != count($toEmail)) {
159                                                $this->send_email($result->id, $result->client_code, $result->client_name, $result->credit_days, $logo, $addTo, $email);
160                                            }
161                                        }                                        
162                                    }
163                                }
164                            }
165                        }
166                    }
167                }
168            }
169
170        } catch (\Exception $e) {
171            Log::channel('cron_send_email_invoice_new_credit_days')->error($e->getMessage());
172
173            return 1;
174        }
175
176        return 0;
177    }
178
179    public function send_email($id, $clientCode, $clientName, $creditDays, $logo, $addTo, $email)
180    {
181
182        $body = "<p>Estimado {$clientName},</p></br>";
183        $body .= "<p>Le informamos de que, como parte de un proceso de revisión y mejora de nuestros procedimientos administrativos y de facturación, a partir del 01/03/2026 el plazo de vencimiento de las facturas emitidas a su nombre pasará a ser de {$creditDays} días, en sustitución del plazo actual.</p></br>";
184        $body .= '<p>Esta modificación tiene como objetivo homogeneizar y optimizar la gestión administrativa, sin que suponga ningún otro cambio al servicio que le ofrecemos habitualmente.</p></br>';
185        $body .= '<p>Muchas gracias.</p></br>';
186        $body .= '<p>Fire Service Titan</p>';
187        $body .= "<img src='cid:fireservicetitan' style='height: 45px;' />";
188
189        $html = '<!DOCTYPE html>';
190        $html .= '<html>';
191        $html .= '<head>';
192        $html .= '<meta charset="UTF-8">';
193        $html .= '<meta name="viewport" content="width=device-width, initial-scale=1.0">';
194        $html .= '</head>';
195        $html .= '<body>';
196        $html .= $body;
197        $html .= '</body>';
198        $html .= '</html>';
199
200        $email->setFrom('fire@fire.es', 'Fire Service Titan');
201        $email->setSubject('Condiciones comerciales Grupo Fire');
202        $email->addContent('text/html', $html);
203        $email->addCc('xavier.lopez@fire.es');
204
205        $email->addAttachment(
206            $logo,
207            'image/png',
208            'fireservicetitan.png',
209            'inline',
210            'fireservicetitan'
211        );
212
213        $sendgrid = new \SendGrid(config('services.sendgrid.api_key'));
214
215        try {
216            $response = $sendgrid->send($email);
217            SendgridLogger::log($email, $response);
218        } catch (\Throwable $sendException) {
219            SendgridLogger::logException($email, $sendException);
220            throw $sendException;
221        }
222
223        if ($response->statusCode() == 202) {
224            $addTo = json_encode($addTo);
225            TblCustomerChangeComms::where('id', $id)
226                ->update([
227                    'email_sent_at' => date('Y-m-d H:i:s'),
228                ]
229                );
230            Log::channel('cron_send_email_invoice_new_credit_days')->info("[SENT-OK] ID:$clientCode - $addTo");
231        } else {
232            $error = $response->body();
233            Log::channel('cron_send_email_invoice_new_credit_days')->error("[ERROR-SG] ID:$clientCode - $addTo - $error");
234        }
235    }
236
237    public function isEmailValid($email)
238    {
239        $pattern = '/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/';
240
241        if (preg_match($pattern, $email)) {
242            return true;
243        } else {
244            return false;
245        }
246    }
247
248    public function detectDelimiter($string)
249    {
250        $delimiters = [',', ';', '|'];
251        $counts = [];
252
253        foreach ($delimiters as $delimiter) {
254            $counts[$delimiter] = substr_count($string, $delimiter);
255        }
256
257        return array_search(max($counts), $counts);
258    }
259}