Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 5878
0.00% covered (danger)
0.00%
0 / 87
CRAP
0.00% covered (danger)
0.00%
0 / 1
Quotations
0.00% covered (danger)
0.00%
0 / 5878
0.00% covered (danger)
0.00%
0 / 87
2130140
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
20
 create_quotation
0.00% covered (danger)
0.00%
0 / 79
0.00% covered (danger)
0.00%
0 / 1
110
 currency
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 send_approval_notification
0.00% covered (danger)
0.00%
0 / 121
0.00% covered (danger)
0.00%
0 / 1
552
 send_approval_margin_notification
0.00% covered (danger)
0.00%
0 / 106
0.00% covered (danger)
0.00%
0 / 1
272
 approve_quotation
0.00% covered (danger)
0.00%
0 / 38
0.00% covered (danger)
0.00%
0 / 1
240
 send_approved_notification
0.00% covered (danger)
0.00%
0 / 98
0.00% covered (danger)
0.00%
0 / 1
110
 reject_quotation
0.00% covered (danger)
0.00%
0 / 38
0.00% covered (danger)
0.00%
0 / 1
240
 send_rejected_notification
0.00% covered (danger)
0.00%
0 / 98
0.00% covered (danger)
0.00%
0 / 1
110
 update_quotation
0.00% covered (danger)
0.00%
0 / 416
0.00% covered (danger)
0.00%
0 / 1
16002
 compareArrays
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
42
 isEmpty
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
20
 convertValue
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
56
 callDeleteQuotation
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
2
 get_quotation
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
6
 get_quotation_log
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 send_notification
0.00% covered (danger)
0.00%
0 / 62
0.00% covered (danger)
0.00%
0 / 1
42
 delete_quotation
0.00% covered (danger)
0.00%
0 / 48
0.00% covered (danger)
0.00%
0 / 1
132
 getBlacklistEmails
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
2
 list_quotations
0.00% covered (danger)
0.00%
0 / 394
0.00% covered (danger)
0.00%
0 / 1
18090
 get_dates
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
12
 list_quotation_analytics_by_source
0.00% covered (danger)
0.00%
0 / 121
0.00% covered (danger)
0.00%
0 / 1
1722
 list_quotation_analytics_send_budgets
0.00% covered (danger)
0.00%
0 / 47
0.00% covered (danger)
0.00%
0 / 1
380
 list_quotation_analytics_track_budgets
0.00% covered (danger)
0.00%
0 / 120
0.00% covered (danger)
0.00%
0 / 1
1332
 list_quotation_analytics_types_budgets
0.00% covered (danger)
0.00%
0 / 122
0.00% covered (danger)
0.00%
0 / 1
1056
 download_quotations
0.00% covered (danger)
0.00%
0 / 22
0.00% covered (danger)
0.00%
0 / 1
342
 download_quotations_csv
n/a
0 / 0
n/a
0 / 0
1
 bulk_upload
0.00% covered (danger)
0.00%
0 / 35
0.00% covered (danger)
0.00%
0 / 1
30
 list_bulk_upload
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
12
 delete_number
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
6
 get_number
0.00% covered (danger)
0.00%
0 / 39
0.00% covered (danger)
0.00%
0 / 1
132
 get_years
0.00% covered (danger)
0.00%
0 / 34
0.00% covered (danger)
0.00%
0 / 1
12
 human_filesize
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 get_files
0.00% covered (danger)
0.00%
0 / 128
0.00% covered (danger)
0.00%
0 / 1
1806
 download_file
0.00% covered (danger)
0.00%
0 / 39
0.00% covered (danger)
0.00%
0 / 1
56
 delete_file
0.00% covered (danger)
0.00%
0 / 21
0.00% covered (danger)
0.00%
0 / 1
30
 send_email_to_client
0.00% covered (danger)
0.00%
0 / 315
0.00% covered (danger)
0.00%
0 / 1
6162
 send_email_follow_ups
0.00% covered (danger)
0.00%
0 / 422
0.00% covered (danger)
0.00%
0 / 1
9312
 create_sender_identity
0.00% covered (danger)
0.00%
0 / 38
0.00% covered (danger)
0.00%
0 / 1
72
 get_sender_identity
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
20
 get_all_sender_identity
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
6
 delete_sender_identity
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
20
 create_template
0.00% covered (danger)
0.00%
0 / 54
0.00% covered (danger)
0.00%
0 / 1
72
 get_email_files
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
20
 download_email_template_file
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
20
 delete_email_template_file
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
12
 update_email_template_order
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
12
 update_email_template
0.00% covered (danger)
0.00%
0 / 43
0.00% covered (danger)
0.00%
0 / 1
90
 delete_template
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
6
 get_email_template
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
12
 update_sender_identity
0.00% covered (danger)
0.00%
0 / 34
0.00% covered (danger)
0.00%
0 / 1
20
 resend_verification
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
12
 list_quotation_analytics_by_performance
0.00% covered (danger)
0.00%
0 / 35
0.00% covered (danger)
0.00%
0 / 1
30
 list_orders_update_logs
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
12
 list_g3w_orders_update_logs
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
6
 list_g3w_orders_failed
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 1
42
 update_budget_status_rejected_manual
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
12
 update_budget_status_rejected
0.00% covered (danger)
0.00%
0 / 55
0.00% covered (danger)
0.00%
0 / 1
110
 bulk_update_quotation
0.00% covered (danger)
0.00%
0 / 32
0.00% covered (danger)
0.00%
0 / 1
30
 move_budget_and_job
0.00% covered (danger)
0.00%
0 / 58
0.00% covered (danger)
0.00%
0 / 1
30
 list_quotation_analytics_by_types_of_budgets_created_per_week
0.00% covered (danger)
0.00%
0 / 194
0.00% covered (danger)
0.00%
0 / 1
3782
 preview_file
0.00% covered (danger)
0.00%
0 / 25
0.00% covered (danger)
0.00%
0 / 1
20
 get_past_added_quotation
0.00% covered (danger)
0.00%
0 / 28
0.00% covered (danger)
0.00%
0 / 1
30
 send_acceptance_notification
0.00% covered (danger)
0.00%
0 / 76
0.00% covered (danger)
0.00%
0 / 1
156
 get_total_quotations_by_budget_status
0.00% covered (danger)
0.00%
0 / 63
0.00% covered (danger)
0.00%
0 / 1
90
 sendgrid_webhook_receiver
0.00% covered (danger)
0.00%
0 / 35
0.00% covered (danger)
0.00%
0 / 1
42
 isEmailValid
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 list_email_status
0.00% covered (danger)
0.00%
0 / 20
0.00% covered (danger)
0.00%
0 / 1
30
 list_quotation_analytics_commercial
0.00% covered (danger)
0.00%
0 / 187
0.00% covered (danger)
0.00%
0 / 1
2970
 clear_open_data
0.00% covered (danger)
0.00%
0 / 26
0.00% covered (danger)
0.00%
0 / 1
30
 list_quotation_analytics_order_size
0.00% covered (danger)
0.00%
0 / 195
0.00% covered (danger)
0.00%
0 / 1
4422
 send_email_template_preview
0.00% covered (danger)
0.00%
0 / 107
0.00% covered (danger)
0.00%
0 / 1
306
 list_quotation_analytics_by_types_of_budgets_company_per_week
0.00% covered (danger)
0.00%
0 / 191
0.00% covered (danger)
0.00%
0 / 1
3782
 request_permission_commercial
0.00% covered (danger)
0.00%
0 / 68
0.00% covered (danger)
0.00%
0 / 1
72
 confirm_update_commercial
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
12
 calculateEmailRequestSize
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
56
 list_quotation_analytics_commercial_productivity
0.00% covered (danger)
0.00%
0 / 234
0.00% covered (danger)
0.00%
0 / 1
4422
 list_quotations_deleted
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
12
 delete_sengrid
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
20
 download_productivity_commercial
0.00% covered (danger)
0.00%
0 / 379
0.00% covered (danger)
0.00%
0 / 1
2450
 update_commercial_numbers
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
2
 list_quotation_analytics_by_service_type
0.00% covered (danger)
0.00%
0 / 167
0.00% covered (danger)
0.00%
0 / 1
1260
 getIdsFromInternalQuoteIds
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 checkQuotationExistByInternalQuoteId
0.00% covered (danger)
0.00%
0 / 22
0.00% covered (danger)
0.00%
0 / 1
72
 addUpdateLog
0.00% covered (danger)
0.00%
0 / 82
0.00% covered (danger)
0.00%
0 / 1
2070
 setSolicitudDuplicity
0.00% covered (danger)
0.00%
0 / 21
0.00% covered (danger)
0.00%
0 / 1
20
 getQuoteIdOfDuplicityById
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
12
 download_s3_files
0.00% covered (danger)
0.00%
0 / 45
0.00% covered (danger)
0.00%
0 / 1
72
1<?php
2
3namespace App\Http\Controllers;
4
5use App\Models\StructureData;
6use App\Models\TblBlockedDomains;
7use App\Models\TblBudgetStatus;
8use App\Models\TblBudgetTypeGroups;
9use App\Models\TblBudgetTypes;
10use App\Models\TblBulkUpload;
11use App\Models\TblBusinessGoals;
12use App\Models\TblCcAcceptanceNotifications;
13use App\Models\TblCcBcc;
14use App\Models\TblCompanies;
15use App\Models\TblCompanyEmails;
16use App\Models\TblCompanyUsers;
17use App\Models\TblCustomerTypes;
18use App\Models\TblEmailConfiguration;
19use App\Models\TblEmailFiles;
20use App\Models\TblFiles;
21use App\Models\TblFollowUpLogs;
22use App\Models\TblG3WOrdersUpdateLogs;
23use App\Models\TblLastFollowUpDate;
24use App\Models\TblNotifications;
25use App\Models\TblOngoingJobs;
26use App\Models\TblOrdersUpdateLogs;
27use App\Models\TblProjectTypes;
28use App\Models\TblQuotations;
29use App\Models\TblQuotationsLog;
30use App\Models\TblSegments;
31use App\Models\TblSendgridWebhook;
32use App\Models\TblSources;
33use App\Models\TblToAcceptanceNotifications;
34use App\Models\TblUsers;
35use App\Models\TblVisitTypeGroups;
36use App\Models\TblWorkflowQuestions;
37use Illuminate\Http\Request;
38use Illuminate\Support\Facades\App;
39use Illuminate\Support\Facades\Cache;
40use Illuminate\Support\Facades\DB;
41use Illuminate\Support\Facades\File;
42use Illuminate\Support\Facades\Log;
43use Illuminate\Support\Facades\Response;
44use Illuminate\Support\Facades\Storage;
45use PhpOffice\PhpSpreadsheet\IOFactory;
46use PhpOffice\PhpSpreadsheet\Spreadsheet;
47use SendGrid\Mail\Mail;
48use ZipArchive;
49
50class Quotations extends Controller
51{
52    private $locale;
53
54    private $userId;
55
56    private $region;
57
58    private $companyIds;
59
60    private $companyId;
61
62    public function __construct()
63    {
64        $this->locale = @getallheaders()['Locale-ID'];
65        $this->userId = @getallheaders()['User-ID'];
66        $this->region = @getallheaders()['Region'];
67
68        App::setLocale($this->locale);
69
70        $this->companyIds = [];
71
72        if ($this->region != null && $this->region != '' && $this->region != 'All') {
73            $this->region = urldecode($this->region);
74
75            $query = 'SELECT
76                        b.company_id
77                    FROM
78                        tbl_company_users a
79                        LEFT JOIN tbl_companies b ON a.company_id = b.company_id
80                    WHERE
81                        a.user_id = ?
82                        AND b.region = ?';
83
84            $this->companyIds = DB::select($query, [intval($this->userId), $this->region]);
85
86            $this->companyIds = collect($this->companyIds)->pluck('company_id')->toArray();
87        } else {
88            $this->companyIds = TblCompanyUsers::where('user_id', $this->userId)->pluck('company_id')->all();
89        }
90
91        $this->companyId = implode(',', $this->companyIds);
92    }
93
94    public function create_quotation(Request $request)
95    {
96
97        try {
98
99            $data = $request->all();
100            $data['updated_at'] = date('Y-m-d H:i:s');
101
102            if (isset($data['request_date']) && isset($data['issue_date'])) {
103                $requestDate = strtotime($data['request_date']);
104                $issueDate = strtotime($data['issue_date']);
105                $dateDiff = $issueDate - $requestDate;
106                $data['duration'] = round($dateDiff / (60 * 60 * 24));
107            }
108
109            $r = new Request([
110                'created_by' => $data['created_by'],
111            ]);
112
113            $result = $this->get_number($r, @$data['company_id']);
114            $id = $result->original['id'];
115
116            $files = $request->file('files');
117            if ($files) {
118                $uploadedFiles = [];
119
120                foreach ($files as $file) {
121                    $filename = time().'_'.$file->getClientOriginalName();
122                    $fileSize = $file->getSize();
123                    // $fileContent = file_get_contents($file->getRealPath());
124                    // $fileHash = hash('sha256', $fileContent);
125
126                    $s3path = Storage::disk('s3')->putFileAs(
127                        'uploads',
128                        $file,
129                        $filename,
130                        [
131                            'ContentType' => $file->getMimeType(),
132                        ]
133                    );
134
135                    TblFiles::create(
136                        [
137                            'quotation_id' => $id,
138                            'original_name' => $file->getClientOriginalName(),
139                            'filename' => $filename,
140                            'uploaded_by' => $data['updated_by'],
141                            // 'file' => $fileContent,
142                            'file_size' => $file->getSize(),
143                            // 'file_hash' => $fileHash,
144                            'mime_type' => $file->getMimeType(),
145                            'uploaded_at' => now(),
146                        ]
147                    );
148
149                    // $this->addUpdateLog($id, $data['updated_by'], "upload_attachment", null, $filename, 4);
150                }
151            }
152
153            $query = 'SELECT COUNT(*) as count FROM tbl_files WHERE quotation_id = ?';
154            $fileCount = DB::select($query, [$id])[0]->count;
155
156            $data['has_attachment'] = $fileCount > 0 ? 1 : 0;
157
158            $data = array_diff_key($data, array_flip(['files', '_token', 'otros_campos_no_necesarios']));
159
160            $data['for_add'] = 0;
161            TblQuotations::where('id', $id)->update($data);
162
163            $result = TblQuotations::where('id', $id)->first();
164
165            if ($result->budget_status_id == 6) {
166                $data = [
167                    'id' => $result->id ?? null,
168                    'client' => $result->client ?? null,
169                    'email' => $result->email ?? null,
170                    'phone_number' => $result->phone_number ?? null,
171                    'last_follow_up_comment' => $result->last_follow_up_comment ?? null,
172                    'quote_id' => $result->quote_id ?? null,
173                    'request_date' => date('Y-m-d'),
174                    'updated_by' => 'IA',
175                    'user_id' => $result->getAttribute('user_id') ?? null,
176                    'commercial' => $result->commercial ?? null,
177                    'budget_status_id' => $result->budget_status_id ?? null,
178                    'internal_quote_id' => $result->internal_quote_id ?? null,
179                ];
180
181                $ch = curl_init('https://2lsarnb35o6evhgwmfedrsxk3i0lqzzq.lambda-url.eu-west-2.on.aws/checkduplicate');
182                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
183                curl_setopt($ch, CURLOPT_POST, true);
184                curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
185                curl_setopt($ch, CURLOPT_HTTPHEADER, [
186                    'Content-Type: application/json',
187                ]);
188
189                $response = curl_exec($ch);
190                $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
191
192                if (curl_errno($ch)) {
193                    error_log('Error en cURL: '.curl_error($ch));
194                }
195
196                curl_close($ch);
197            }
198
199            $logCategory = $result->budget_status_id == 6 ? 0 : 2;
200            $this->addUpdateLog($result->id, $result->getAttribute('user_id'), 'create_quotation', null, null, $logCategory);
201            Cache::flush();
202
203            return response(['message' => 'OK', 'data' => $result]);
204
205        } catch (\Exception $e) {
206            /** @disregard P1014 */
207            $e->exceptionCode = 'CREATE_QUOTATION_EXCEPTION';
208            report($e);
209
210            return response(['message' => 'KO', 'error' => $e->getMessage()]);
211        }
212
213    }
214
215    public function currency($amount, $withEuro = '')
216    {
217
218        if ($withEuro != null) {
219            $withEuro = ' â‚¬';
220        }
221
222        return number_format($amount, 2, ',', '.').$withEuro;
223    }
224
225    public function send_approval_notification($amount, $budgetTypeId, $customerTypeId, $minimumOrderSize, $quoteId, $id, $companyName, $createdBy, $userId, $action, $commercialEmail, $companyId, $endpoint, $isQuestion, $questionIdsNo, $n, $locale = null)
226    {
227
228        if (! is_null($locale)) {
229            $this->locale = $locale;
230        }
231
232        if ($action != 1) {
233            if ($this->locale == 'es') {
234                $action = 'actualizado';
235            } else {
236                $action = 'updated';
237            }
238
239        } else {
240            if ($this->locale == 'es') {
241                $action = 'creado';
242            } else {
243                $action = 'created';
244            }
245        }
246
247        $fendpoint = '';
248
249        if ($endpoint == 'orders') {
250            if ($this->locale == 'es') {
251                $fendpoint = 'presupuesto';
252            } else {
253                $fendpoint = 'budget';
254            }
255
256        } else {
257            if ($this->locale == 'es') {
258                $fendpoint = 'trabajo';
259            } else {
260                $fendpoint = 'job';
261            }
262        }
263
264        $user = TblUsers::where('id', $userId)->first();
265
266        $query = "SELECT
267                    a.approver_id,
268                    a.user_id,
269                    b.name,
270                    b.email
271                FROM
272                    tbl_approvers a
273                    INNER JOIN tbl_users b ON a.user_id = b.id
274                WHERE a.company_id = {$companyId}
275                ";
276
277        if ($n == 3) {
278            $query = "SELECT
279                        a.approver_id,
280                        a.user_id,
281                        u.name,
282                        u.email
283                    FROM tbl_approvers a
284                    INNER JOIN tbl_users u ON a.user_id = u.id
285                    WHERE a.company_id = {$companyId}
286
287                    UNION ALL
288
289                    SELECT
290                        c.approver_id,
291                        c.user_id,
292                        u2.name,
293                        u2.email
294                    FROM tbl_approvers_v2 c
295                    INNER JOIN tbl_users u2 ON c.user_id = u2.id
296                    WHERE c.company_id = {$companyId}";
297        }
298
299        $approvers = DB::select($query);
300
301        if (count($approvers) > 0) {
302            $amount = $this->currency($amount, 1);
303            $minimumOrderSize = $this->currency($minimumOrderSize, 1);
304
305            $budgetType = TblBudgetTypes::where('budget_type_id', $budgetTypeId)->first();
306            $clientType = TblCustomerTypes::where('customer_type_id', $customerTypeId)->first();
307
308            $imgpath = File::get('fireservicetitan.png');
309            $base64 = 'data:image/png;base64,'.base64_encode($imgpath);
310
311            $subject = __('language.send_approval_notification.subject');
312            $subject = str_replace('{{type}}', $budgetType->name, $subject);
313            $subject = str_replace('{{amount}}', $amount, $subject);
314            $subject = str_replace('{{endpoint}}', ucfirst($fendpoint), $subject);
315
316            $url = env('URL')."{$endpoint}/{$id}?company_id={$companyId}";
317            $href = "<a href='{$url}'>{$quoteId}</a>";
318            $cc = false;
319            foreach ($approvers as $item) {
320
321                $toEmail = $item->email;
322
323                $body = __('language.send_approval_notification.body_hello');
324                $body = str_replace('{{approver}}', $item->name, $body);
325
326                $body .= __('language.send_approval_notification.body_message');
327                $body = str_replace('{{endpoint}}', $fendpoint, $body);
328                $body = str_replace('{{creator}}', $createdBy, $body);
329                $body = str_replace('{{action}}', $action, $body);
330                $body = str_replace('{{company}}', $companyName, $body);
331                $body = str_replace('{{type}}', $budgetType->name, $body);
332                $body = str_replace('{{amount}}', $amount, $body);
333                $body = str_replace('{{quote_id}}', $href, $body);
334
335                if ($isQuestion == 1) {
336                    $body .= __('language.send_approval_notification.note_question');
337                } else {
338                    $body .= __('language.send_approval_notification.note');
339                }
340
341                $body = str_replace('{{company}}', $companyName, $body);
342                $body = str_replace('{{client_type}}', $clientType->name, $body);
343                $body = str_replace('{{project_type}}', $budgetType->name, $body);
344                $body = str_replace('{{amount}}', $minimumOrderSize, $body);
345
346                if ($isQuestion == 1) {
347                    if ($questionIdsNo) {
348                        $questions = TblWorkflowQuestions::whereIn('question_id', $questionIdsNo)->where('company_id', $companyId)->get();
349
350                        if ($questions->isNotEmpty()) {
351                            $ul = '<ul>';
352                            $li = '';
353                            foreach ($questions as $item) {
354                                $li .= "<li>{$item->question}</li>";
355                            }
356                            $ul .= $li.'</ul><br><br>';
357                            $body .= $ul;
358                        }
359                    }
360                }
361
362                $content = $body;
363
364                $body .= '<p>Fire Service Titan</p>';
365                $body .= "<img src='cid:fireservicetitan' style='height: 45px;' />";
366
367                $html = '<!DOCTYPE html>';
368                $html .= '<html>';
369                $html .= '<head>';
370                $html .= '<meta charset="UTF-8">';
371                $html .= '<meta name="viewport" content="width=device-width, initial-scale=1.0">';
372                $html .= '</head>';
373                $html .= '<body>';
374                $html .= $body;
375                $html .= '</body>';
376                $html .= '</html>';
377
378                if ($toEmail != null) {
379                    $email = new \SendGrid\Mail\Mail;
380
381                    if (env('SENDGRID_STAGING')) {
382                        $toEmail = $user->email;
383                        $item->user_id = $userId;
384                    }
385
386                    if ($cc == false) {
387                        $cc = true;
388                        if ($user->email != $toEmail) {
389                            if ($user->email != $commercialEmail && $commercialEmail != null) {
390                                $email->addBcc($user->email);
391                                $email->addBcc($commercialEmail);
392                            } else {
393                                $email->addBcc($user->email);
394                            }
395                        }
396                    }
397
398                    $email->setFrom('fire@fire.es', 'Fire Service Titan');
399                    $email->setSubject($subject);
400                    $email->addTo($toEmail);
401                    $email->addContent('text/html', $html);
402
403                    $email->addAttachment(
404                        $imgpath,
405                        'image/png',
406                        'fireservicetitan.png',
407                        'inline',
408                        'fireservicetitan'
409                    );
410
411                    $sendgrid = new \SendGrid(env('SENDGRID_API_KEY'));
412
413                    $response = $sendgrid->send($email);
414                    if ($response->statusCode() == 202) {
415                        Log::channel('email_log')->info('ID:'.$quoteId.' : '.$toEmail.' - APPROVAL EMAIL NOTIFICATION SENT');
416
417                        $this->addUpdateLog($id, $userId, 'send_approval_notification', null, null, 5);
418
419                        TblNotifications::create(
420                            [
421                                'user_id' => $item->user_id,
422                                'content' => $content,
423                                'is_open' => 1,
424                                'created_by' => 'System',
425                                'link' => $url,
426                            ]
427                        );
428                    } else {
429                        $error = true;
430                        Log::channel('email_log')->error('ID:'.$quoteId.' : '.$toEmail.' - '.$response->body());
431                    }
432                }
433
434            }
435        }
436    }
437
438    public function send_approval_margin_notification($amount, $budgetTypeId, $customerTypeId, $minimumMargin, $quoteId, $id, $companyName, $createdBy, $userId, $action, $commercialEmail, $invoiceMargin, $companyId, $endpoint, $locale = null)
439    {
440
441        if ($action != 1) {
442            if ($this->locale == 'es') {
443                $action = 'actualizado';
444            } else {
445                $action = 'updated';
446            }
447
448        } else {
449            if ($this->locale == 'es') {
450                $action = 'creado';
451            } else {
452                $action = 'created';
453            }
454        }
455
456        $fendpoint = '';
457
458        if ($endpoint == 'orders') {
459            if ($this->locale == 'es') {
460                $fendpoint = 'presupuesto';
461            } else {
462                $fendpoint = 'budget';
463            }
464
465        } else {
466            if ($this->locale == 'es') {
467                $fendpoint = 'trabajo';
468            } else {
469                $fendpoint = 'job';
470            }
471        }
472
473        $invoiceMargin = number_format($invoiceMargin, 2);
474        $minimumMargin = number_format($minimumMargin, 2);
475
476        $user = TblUsers::where('id', $userId)->first();
477
478        $query = "SELECT
479                    a.approver_id,
480                    a.user_id,
481                    b.name,
482                    b.email
483                FROM
484                    tbl_approvers a
485                    INNER JOIN tbl_users b ON a.user_id = b.id
486                WHERE a.company_id = {$companyId}
487                ";
488
489        $approvers = DB::select($query);
490
491        if (count($approvers) > 0) {
492
493            $amount = $this->currency($amount, 1);
494
495            $budgetType = TblBudgetTypes::where('budget_type_id', $budgetTypeId)->first();
496            $clientType = TblCustomerTypes::where('customer_type_id', $customerTypeId)->first();
497
498            $imgpath = File::get('fireservicetitan.png');
499            $base64 = 'data:image/png;base64,'.base64_encode($imgpath);
500
501            $subject = __('language.send_approval_margin_notification.subject');
502            $subject = str_replace('{{type}}', $budgetType->name, $subject);
503            $subject = str_replace('{{amount}}', $amount, $subject);
504            $subject = str_replace('{{margin}}', $invoiceMargin, $subject);
505            $subject = str_replace('{{endpoint}}', ucfirst($fendpoint), $subject);
506
507            $url = env('URL')."{$endpoint}/{$id}?company_id={$companyId}";
508            $href = "<a href='{$url}'>{$quoteId}</a>";
509            $cc = false;
510            foreach ($approvers as $item) {
511
512                $toEmail = $item->email;
513
514                $body = __('language.send_approval_margin_notification.body_hello');
515                $body = str_replace('{{approver}}', $item->name, $body);
516
517                $body .= __('language.send_approval_margin_notification.body_message');
518                $body = str_replace('{{endpoint}}', $fendpoint, $body);
519                $body = str_replace('{{creator}}', $createdBy, $body);
520                $body = str_replace('{{action}}', $action, $body);
521                $body = str_replace('{{company}}', $companyName, $body);
522                $body = str_replace('{{type}}', $budgetType->name, $body);
523                $body = str_replace('{{amount}}', $amount, $body);
524                $body = str_replace('{{quote_id}}', $href, $body);
525                $body = str_replace('{{margin}}', $invoiceMargin, $body);
526
527                $body .= __('language.send_approval_margin_notification.note');
528                $body = str_replace('{{company}}', $companyName, $body);
529                $body = str_replace('{{client_type}}', $clientType->name, $body);
530                $body = str_replace('{{project_type}}', $budgetType->name, $body);
531                $body = str_replace('{{margin}}', $minimumMargin, $body);
532
533                $content = $body;
534
535                $body .= '<p>Fire Service Titan</p>';
536                $body .= "<img src='cid:fireservicetitan' style='height: 45px;' />";
537
538                $html = '<!DOCTYPE html>';
539                $html .= '<html>';
540                $html .= '<head>';
541                $html .= '<meta charset="UTF-8">';
542                $html .= '<meta name="viewport" content="width=device-width, initial-scale=1.0">';
543                $html .= '</head>';
544                $html .= '<body>';
545                $html .= $body;
546                $html .= '</body>';
547                $html .= '</html>';
548
549                if ($toEmail != null) {
550                    $email = new \SendGrid\Mail\Mail;
551
552                    if (env('SENDGRID_STAGING')) {
553                        $toEmail = $user->email;
554                        $item->user_id = $userId;
555                    }
556
557                    if ($cc == false) {
558                        $cc = true;
559
560                        if ($user->email != $toEmail) {
561                            if ($user->email != $commercialEmail && $commercialEmail != null) {
562                                $email->addBcc($user->email);
563                                $email->addBcc($commercialEmail);
564                            } else {
565                                $email->addBcc($user->email);
566                            }
567                        }
568                    }
569
570                    $email->setFrom('fire@fire.es', 'Fire Service Titan');
571                    $email->setSubject($subject);
572                    $email->addTo($toEmail);
573                    $email->addContent('text/html', $html);
574
575                    $email->addAttachment(
576                        $imgpath,
577                        'image/png',
578                        'fireservicetitan.png',
579                        'inline',
580                        'fireservicetitan'
581                    );
582
583                    $sendgrid = new \SendGrid(env('SENDGRID_API_KEY'));
584
585                    $response = $sendgrid->send($email);
586                    if ($response->statusCode() == 202) {
587                        Log::channel('email_log')->info('ID:'.$quoteId.' : '.$toEmail.' - MARGIN APPROVAL EMAIL NOTIFICATION SENT');
588
589                        $this->addUpdateLog($quoteId, $userId, 'send_approval_margin_notification', null, null, 5);
590
591                        TblNotifications::create(
592                            [
593                                'user_id' => $item->user_id,
594                                'content' => $content,
595                                'is_open' => 1,
596                                'created_by' => 'System',
597                                'link' => $url,
598                            ]
599                        );
600                    } else {
601                        $error = true;
602                        Log::channel('email_log')->error('ID:'.$quoteId.' : '.$toEmail.' - '.$response->body());
603                    }
604                }
605
606            }
607        }
608    }
609
610    public function approve_quotation($id)
611    {
612
613        try {
614
615            $id = intval($id);
616
617            $result = TblQuotations::where('id', $id)->first();
618            $company = TblCompanies::where('company_id', $result->company_id)->first();
619            $budgetType = TblBudgetTypes::where('budget_type_id', $result->budget_type_id)->first();
620
621            if ($result->created_by != $result->commercial) {
622                $creatorAndCommercial = [$result->created_by, $result->commercial];
623                foreach ($creatorAndCommercial as $name) {
624                    $user = TblUsers::where('name', $name)->first();
625                    if ($user) {
626                        $this->send_approved_notification($user->id, $user->name, $user->email, $company->name, $budgetType->name, $result->amount, $id, $result->quote_id, $company->company_id, 'orders');
627                    }
628                }
629            } else {
630                $user = TblUsers::where('name', $result->created_by)->first();
631                if ($user) {
632                    $this->send_approved_notification($user->id, $user->name, $user->email, $company->name, $budgetType->name, $result->amount, $id, $result->quote_id, $company->company_id, 'orders');
633                }
634            }
635
636            if ($result->for_approval == 3) {
637                $result = TblQuotations::where('id', $id)->first();
638
639                $approved = 0;
640                $rejected = 0;
641
642                if ($result->approved_by !== null) {
643                    $approved++;
644                }
645                if ($result->approved_by_v2 !== null) {
646                    $approved++;
647                }
648
649                if ($result->rejected_by !== null) {
650                    $rejected++;
651                }
652                if ($result->rejected_by_v2 !== null) {
653                    $rejected++;
654                }
655
656                if ($approved === 2) {
657                    TblQuotations::where('id', $id)->update(['for_approval' => null]);
658                } elseif ($rejected >= 1 && ($approved + $rejected) === 2) {
659                    TblQuotations::where('id', $id)->update(['for_approval' => null]);
660                }
661            } elseif ($result->for_approval == 1) {
662                TblQuotations::where('id', $id)->update(['for_approval' => null]);
663            }
664
665            $this->addUpdateLog($id, $user->id, 'approve_quotation', null, null, 5);
666
667            Cache::flush();
668
669            return response(['message' => 'OK']);
670
671        } catch (\Exception $e) {
672            /** @disregard P1014 */
673            $e->exceptionCode = 'APPROVE_QUOTATION_EXCEPTION';
674            report($e);
675
676            return response(['message' => 'KO', 'error' => $e->getMessage()]);
677        }
678
679    }
680
681    public function send_approved_notification($userId, $username, $email, $companyName, $budgetType, $amount, $id, $quoteId, $companyId, $endpoint)
682    {
683
684        $fendpoint = '';
685
686        if ($endpoint == 'orders') {
687            if ($this->locale == 'es') {
688                $fendpoint = 'presupuesto';
689            } else {
690                $fendpoint = 'budget';
691            }
692
693        } else {
694            if ($this->locale == 'es') {
695                $fendpoint = 'trabajo';
696            } else {
697                $fendpoint = 'job';
698            }
699        }
700
701        $query = "SELECT
702                    u.id AS user_id,
703                    u.name,
704                    u.email,
705                    u.sender_email,
706                    CASE
707                        WHEN a.user_id IS NOT NULL AND c.user_id IS NOT NULL THEN 'both'
708                        WHEN a.user_id IS NOT NULL THEN 'approvers'
709                        WHEN c.user_id IS NOT NULL THEN 'approvers_v2'
710                        ELSE 'none'
711                    END AS exists_in
712                FROM tbl_users u
713                LEFT JOIN tbl_approvers a
714                    ON u.id = a.user_id AND a.company_id = {$companyId}
715                LEFT JOIN tbl_approvers_v2 c
716                    ON u.id = c.user_id AND c.company_id = {$companyId}
717                WHERE u.id = {$this->userId}";
718
719        $user = DB::select($query);
720
721        $user = $user[0] ?? null;
722
723        $toEmail = $email;
724
725        $amount = $this->currency($amount, 1);
726
727        $imgpath = File::get('fireservicetitan.png');
728        $base64 = 'data:image/png;base64,'.base64_encode($imgpath);
729
730        $url = env('URL')."{$endpoint}/{$id}?company_id={$companyId}";
731        $href = "<a href='{$url}'>{$quoteId}</a>";
732
733        $body = __('language.send_approved_notification.body_hello');
734        $body = str_replace('{{creator}}', $username, $body);
735
736        $body .= __('language.send_approved_notification.body_message');
737        $body = str_replace('{{approver}}', $user->name, $body);
738        $body = str_replace('{{company}}', $companyName, $body);
739        $body = str_replace('{{type}}', $budgetType, $body);
740        $body = str_replace('{{amount}}', $amount, $body);
741        $body = str_replace('{{quote_id}}', $href, $body);
742        $body = str_replace('{{endpoint}}', $fendpoint, $body);
743
744        $content = $body;
745
746        $body .= '<p>Fire Service Titan</p>';
747        $body .= "<img src='cid:fireservicetitan' style='height: 45px;' />";
748
749        $html = '<!DOCTYPE html>';
750        $html .= '<html>';
751        $html .= '<head>';
752        $html .= '<meta charset="UTF-8">';
753        $html .= '<meta name="viewport" content="width=device-width, initial-scale=1.0">';
754        $html .= '</head>';
755        $html .= '<body>';
756        $html .= $body;
757        $html .= '</body>';
758        $html .= '</html>';
759
760        $subject = __('language.send_approved_notification.subject');
761        $subject = str_replace('{{quote_id}}', $quoteId, $subject);
762        $subject = str_replace('{{endpoint}}', ucfirst($fendpoint), $subject);
763
764        if ($toEmail != null) {
765            $email = new \SendGrid\Mail\Mail;
766
767            if (env('SENDGRID_STAGING')) {
768                $toEmail = $user->email;
769                $userId = $this->userId;
770            }
771
772            $email->setFrom('fire@fire.es', 'Fire Service Titan');
773            $email->setSubject($subject);
774            $email->addTo($toEmail);
775            $email->addContent('text/html', $html);
776
777            $email->addAttachment(
778                $imgpath,
779                'image/png',
780                'fireservicetitan.png',
781                'inline',
782                'fireservicetitan'
783            );
784
785            $sendgrid = new \SendGrid(env('SENDGRID_API_KEY'));
786
787            $response = $sendgrid->send($email);
788            if ($response->statusCode() == 202) {
789                Log::channel('email_log')->info('ID:'.$quoteId.' : '.$toEmail.' - APPROVED EMAIL NOTIFICATION SENT');
790                $this->addUpdateLog($id, $userId, 'send_approved_notification', null, null, 5);
791
792                if ($endpoint == 'orders') {
793                    if ($user->exists_in == 'approvers') {
794                        TblQuotations::where('id', $id)->update(
795                            [
796                                'approved_at' => date('Y-m-d H:i:s'),
797                                'approved_by' => $user->name,
798                            ]
799                        );
800                    } elseif ($user->exists_in == 'approvers_v2') {
801                        TblQuotations::where('id', $id)->update(
802                            [
803                                'approved_at_v2' => date('Y-m-d H:i:s'),
804                                'approved_by_v2' => $user->name,
805                            ]
806                        );
807                    }
808                } else {
809                    TblOngoingJobs::where('id', $id)->update(
810                        [
811                            'approved_at' => date('Y-m-d H:i:s'),
812                            'approved_by' => $user->name,
813                        ]
814                    );
815                }
816
817                TblNotifications::create(
818                    [
819                        'user_id' => $userId,
820                        'content' => $content,
821                        'is_open' => 1,
822                        'created_by' => 'System',
823                        'link' => $url,
824                    ]
825                );
826            } else {
827                $error = true;
828                Log::channel('email_log')->error('ID:'.$quoteId.' : '.$toEmail.' - '.$response->body());
829            }
830        }
831
832    }
833
834    public function reject_quotation($id)
835    {
836
837        try {
838
839            $id = intval($id);
840
841            $result = TblQuotations::where('id', $id)->first();
842            $company = TblCompanies::where('company_id', $result->company_id)->first();
843            $budgetType = TblBudgetTypes::where('budget_type_id', $result->budget_type_id)->first();
844
845            if ($result->created_by != $result->commercial) {
846                $creatorAndCommercial = [$result->created_by, $result->commercial];
847                foreach ($creatorAndCommercial as $name) {
848                    $user = TblUsers::where('name', $name)->first();
849                    if ($user) {
850                        $this->send_rejected_notification($user->id, $user->name, $user->email, $company->name, $budgetType->name, $result->amount, $id, $result->quote_id, $company->company_id, 'orders');
851                    }
852                }
853            } else {
854                $user = TblUsers::where('name', $result->created_by)->first();
855                if ($user) {
856                    $this->send_rejected_notification($user->id, $user->name, $user->email, $company->name, $budgetType->name, $result->amount, $id, $result->quote_id, $company->company_id, 'orders');
857                }
858            }
859
860            if ($result->for_approval == 3) {
861                $result = TblQuotations::where('id', $id)->first();
862
863                $approved = 0;
864                $rejected = 0;
865
866                if ($result->approved_by !== null) {
867                    $approved++;
868                }
869                if ($result->approved_by_v2 !== null) {
870                    $approved++;
871                }
872
873                if ($result->rejected_by !== null) {
874                    $rejected++;
875                }
876                if ($result->rejected_by_v2 !== null) {
877                    $rejected++;
878                }
879
880                if ($approved === 2) {
881                    TblQuotations::where('id', $id)->update(['for_approval' => null]);
882                } elseif ($rejected >= 1 && ($approved + $rejected) === 2) {
883                    TblQuotations::where('id', $id)->update(['for_approval' => null]);
884                }
885            } elseif ($result->for_approval == 1) {
886                TblQuotations::where('id', $id)->update(['for_approval' => null]);
887            }
888
889            $this->addUpdateLog($id, $user->id, 'reject_quotation', null, null, 5);
890
891            Cache::flush();
892
893            return response(['message' => 'OK']);
894
895        } catch (\Exception $e) {
896            /** @disregard P1014 */
897            $e->exceptionCode = 'REJECT_QUOTATION_EXCEPTION';
898            report($e);
899
900            return response(['message' => 'KO', 'error' => $e->getMessage()]);
901        }
902
903    }
904
905    public function send_rejected_notification($userId, $username, $email, $companyName, $budgetType, $amount, $id, $quoteId, $companyId, $endpoint)
906    {
907
908        $fendpoint = '';
909
910        if ($endpoint == 'orders') {
911            if ($this->locale == 'es') {
912                $fendpoint = 'presupuesto';
913            } else {
914                $fendpoint = 'budget';
915            }
916
917        } else {
918            if ($this->locale == 'es') {
919                $fendpoint = 'trabajo';
920            } else {
921                $fendpoint = 'job';
922            }
923        }
924
925        $query = "SELECT
926                    u.id AS user_id,
927                    u.name,
928                    u.email,
929                    u.sender_email,
930                    CASE
931                        WHEN a.user_id IS NOT NULL AND c.user_id IS NOT NULL THEN 'both'
932                        WHEN a.user_id IS NOT NULL THEN 'approvers'
933                        WHEN c.user_id IS NOT NULL THEN 'approvers_v2'
934                        ELSE 'none'
935                    END AS exists_in
936                FROM tbl_users u
937                LEFT JOIN tbl_approvers a
938                    ON u.id = a.user_id AND a.company_id = {$companyId}
939                LEFT JOIN tbl_approvers_v2 c
940                    ON u.id = c.user_id AND c.company_id = {$companyId}
941                WHERE u.id = {$this->userId}";
942
943        $user = DB::select($query);
944
945        $user = $user[0] ?? null;
946
947        $toEmail = $email;
948        $amount = $this->currency($amount, 1);
949
950        $imgpath = File::get('fireservicetitan.png');
951        $base64 = 'data:image/png;base64,'.base64_encode($imgpath);
952
953        $url = env('URL')."{$endpoint}/{$id}?company_id={$companyId}";
954        $href = "<a href='{$url}'>{$quoteId}</a>";
955
956        $body = __('language.send_rejected_notification.body_hello');
957        $body = str_replace('{{creator}}', $username, $body);
958
959        $body .= __('language.send_rejected_notification.body_message');
960        $body = str_replace('{{approver}}', $user->name, $body);
961        $body = str_replace('{{company}}', $companyName, $body);
962        $body = str_replace('{{type}}', $budgetType, $body);
963        $body = str_replace('{{amount}}', $amount, $body);
964        $body = str_replace('{{quote_id}}', $href, $body);
965        $body = str_replace('{{endpoint}}', $fendpoint, $body);
966
967        $content = $body;
968
969        $body .= '<p>Fire Service Titan</p>';
970        $body .= "<img src='cid:fireservicetitan' style='height: 45px;' />";
971
972        $html = '<!DOCTYPE html>';
973        $html .= '<html>';
974        $html .= '<head>';
975        $html .= '<meta charset="UTF-8">';
976        $html .= '<meta name="viewport" content="width=device-width, initial-scale=1.0">';
977        $html .= '</head>';
978        $html .= '<body>';
979        $html .= $body;
980        $html .= '</body>';
981        $html .= '</html>';
982
983        $subject = __('language.send_rejected_notification.subject');
984        $subject = str_replace('{{quote_id}}', $quoteId, $subject);
985        $subject = str_replace('{{endpoint}}', ucfirst($fendpoint), $subject);
986
987        if ($toEmail != null) {
988            $email = new \SendGrid\Mail\Mail;
989
990            if (env('SENDGRID_STAGING')) {
991                $toEmail = $user->email;
992                $userId = $this->userId;
993            }
994
995            $email->setFrom('fire@fire.es', 'Fire Service Titan');
996            $email->setSubject($subject);
997            $email->addTo($toEmail);
998            $email->addContent('text/html', $html);
999
1000            $email->addAttachment(
1001                $imgpath,
1002                'image/png',
1003                'fireservicetitan.png',
1004                'inline',
1005                'fireservicetitan'
1006            );
1007
1008            $sendgrid = new \SendGrid(env('SENDGRID_API_KEY'));
1009
1010            $response = $sendgrid->send($email);
1011            if ($response->statusCode() == 202) {
1012                Log::channel('email_log')->info('ID:'.$quoteId.' : '.$toEmail.' - REJECTED EMAIL NOTIFICATION SENT');
1013                $this->addUpdateLog($id, $userId, 'send_rejected_notification', null, null, 5);
1014
1015                if ($endpoint == 'orders') {
1016
1017                    if ($user->exists_in == 'approvers') {
1018                        TblQuotations::where('id', $id)->update(
1019                            [
1020                                'rejected_at' => date('Y-m-d H:i:s'),
1021                                'rejected_by' => $user->name,
1022                            ]
1023                        );
1024                    } elseif ($user->exists_in == 'approvers_v2') {
1025                        TblQuotations::where('id', $id)->update(
1026                            [
1027                                'rejected_at_v2' => date('Y-m-d H:i:s'),
1028                                'rejected_by_v2' => $user->name,
1029                            ]
1030                        );
1031                    }
1032                } else {
1033                    TblOngoingJobs::where('id', $id)->update(
1034                        [
1035                            'rejected_at' => date('Y-m-d H:i:s'),
1036                            'rejected_by' => $user->name,
1037                        ]
1038                    );
1039                }
1040
1041                TblNotifications::create(
1042                    [
1043                        'user_id' => $userId,
1044                        'content' => $content,
1045                        'is_open' => 1,
1046                        'created_by' => 'System',
1047                        'link' => $url,
1048                    ]
1049                );
1050            } else {
1051                $error = true;
1052                Log::channel('email_log')->error('ID:'.$quoteId.' : '.$toEmail.' - '.$response->body());
1053            }
1054        }
1055
1056    }
1057
1058    public function update_quotation(Request $request, $id)
1059    {
1060        $approvalMinimumOrderSize = null;
1061        $approvalIsQuestion = null;
1062        $approvalQuestionIdsNo = null;
1063        $approvalN = null;
1064        $approvalMinimumMargin = null;
1065        $approvalId = null;
1066        $approvalForAdd = null;
1067        $approvalInvoiceMargin = null;
1068        $sendApprovalNotification = false;
1069        $sendApprovalMarginNotification = false;
1070        $needToSendReminder = false;
1071
1072        // try {
1073
1074        $data = $request->all();
1075        $id = intval($id);
1076        $userId = intval($data['user_id']);
1077        if (! TblQuotationsLog::where('quotation_id', $id)->exists()) {
1078            $categoryLog = $data['budget_status_id'] == 6 ? 0 : 2;
1079            $this->addUpdateLog($id, $data['user_id'], 'create_quotation', null, null, $categoryLog);
1080        }
1081        $forApproval = null;
1082        unset($data['user_id']);
1083
1084        $r = ['amount', 'order_number', 'budget_type_id', 'acceptance_date'];
1085        $job = [];
1086
1087        foreach ($data as $key => $value) {
1088            if ($value == 'null') {
1089                $data[$key] = null;
1090            }
1091
1092            if (in_array($key, $r)) {
1093                $job[$key] = $value;
1094            }
1095        }
1096
1097        $files = $request->file('files');
1098        unset($data['files']);
1099
1100        $internalFiles = $request->file('internal_files');
1101        unset($data['internal_files']);
1102
1103        $query = '
1104            SELECT
1105                SUM(CASE WHEN is_internal IS NULL THEN 1 ELSE 0 END) as external_count,
1106                SUM(CASE WHEN is_internal = 1 THEN 1 ELSE 0 END) as internal_count
1107            FROM tbl_files
1108            WHERE quotation_id = ?';
1109
1110        $counts = DB::select($query, [$id]);
1111        $fileCount = $counts[0]->external_count;
1112        $internalFileCount = $counts[0]->internal_count;
1113
1114        if ($fileCount > 0 || ! empty($files)) {
1115            $data['has_attachment'] = 1;
1116        }
1117
1118        if ($files) {
1119            $totalFiles = $fileCount + count($files);
1120            if ($totalFiles > 10) {
1121                return response(['message' => 'KO', 'error' => __('language.file_count_exceeded')]);
1122            }
1123        }
1124
1125        if ($internalFileCount > 0 || ! empty($internalFiles)) {
1126            $data['has_attachment'] = 1;
1127        }
1128
1129        if ($internalFiles) {
1130            $totalInternalFileCount = $internalFileCount + count($internalFiles);
1131            if ($totalInternalFileCount > 10) {
1132                return response(['message' => 'KO', 'error' => __('language.file_count_exceeded')]);
1133            }
1134        }
1135
1136        if (isset($data['request_date']) && isset($data['issue_date'])) {
1137            $requestDate = strtotime($data['request_date']);
1138            $issueDate = strtotime($data['issue_date']);
1139            $dateDiff = $issueDate - $requestDate;
1140            $data['duration'] = round($dateDiff / (60 * 60 * 24));
1141        }
1142
1143        $result = TblQuotations::where('id', $id)->first();
1144
1145        if ($result->quote_id != $data['quote_id']) {
1146
1147            $c = TblQuotations::where('quote_id', (string) $data['quote_id'])->where('company_id', $result->company_id)->count();
1148
1149            if ($c > 0) {
1150
1151                if ($result->for_add == 0) {
1152                    $latestBudget = TblQuotations::where('company_id', $result->company_id)->orderByRaw('CAST(quote_id AS DOUBLE) DESC')->first();
1153
1154                    $number = $latestBudget->quote_id;
1155                    $x = true;
1156
1157                    while ($x) {
1158
1159                        if (is_numeric(substr($number, -1))) {
1160                            $number++;
1161                        } else {
1162                            $number .= '1';
1163                        }
1164
1165                        $check = 0;
1166
1167                        $check = TblQuotations::where('company_id', $result->company_id)->where('quote_id', (string) $number)->count();
1168
1169                        if ($check == 0) {
1170                            $x = false;
1171                        }
1172                    }
1173
1174                    return response(['message' => 'KO', 'error' => 'quote_exists', 'number' => $number]);
1175                }
1176
1177                return response(['message' => 'KO', 'error' => 'quote_exists']);
1178            }
1179        }
1180
1181        $action = 0;
1182        if ($result->created_by == null || $result->for_add == 1) {
1183            $action = 1;
1184            $data['created_by'] = $data['updated_by'];
1185            $data['for_add'] = 0;
1186        }
1187
1188        $company = TblCompanies::where('company_id', $result->company_id)->first();
1189        $commercial = TblUsers::where('name', $data['commercial'])->first();
1190        $status = TblBudgetStatus::where('budget_status_id', $data['budget_status_id'])->first();
1191
1192        // $checkQuotation = TblQuotations::where(function($query) use ($data, $result) {
1193        //     $query->where('internal_quote_id', $data['internal_quote_id'])
1194        //         ->orWhere('internal_quote_id', 'O-25/'.$data['internal_quote_id']);
1195        // })
1196        //     ->where('company_id', $result->company_id)
1197        //     ->first();
1198
1199        // if($checkQuotation) {
1200        //     $url = "orders/" . $checkQuotation->id . "?company_id=" . $checkQuotation->company_id;
1201        //     return response([
1202        //         'message' => 'KO',
1203        //         'error' => "Presupuesto ya creado. Puedes verlo <a href='$url' target='_blank'>aquí</a>."
1204        //     ]);
1205        // }
1206
1207        $limitReminderEmails = $company->limit_reminder_emails ?? 3;
1208
1209        if ($result->total_sent == $limitReminderEmails) {
1210            $data['total_sent'] = 0;
1211        }
1212
1213        if ($result->budget_status_id != $data['budget_status_id'] || $result->commercial != $data['commercial']) {
1214            if ($data['budget_status_id'] == 12) {
1215                if ($company && $commercial) {
1216                    $inProgressCount = TblQuotations::where('budget_status_id', 12)->where('company_id', $result->company_id)->where('commercial', $data['commercial'])->count();
1217                    if ($company->process_limit <= $inProgressCount) {
1218                        return response(['message' => 'KO', 'error' => 'in_progress', 'limit' => $company->process_limit]);
1219                    }
1220                } else {
1221                    return response(['message' => 'KO', 'error' => 'in_progress', 'limit' => 0]);
1222                }
1223            }
1224        }
1225
1226        $sendNotification = false;
1227        if ($result->commercial != $data['commercial']) {
1228            if (! empty($commercial)) {
1229                $createdByX = ($result->created_by == null) ? $data['created_by'] : $result->created_by;
1230                if ($createdByX != $data['commercial']) {
1231                    $action = 0;
1232                    $sendNotification = true;
1233                }
1234            }
1235        }
1236
1237        if (isset($data['amount']) || isset($data['budget_type_id']) || isset($data['customer_type_id']) || isset($data['invoice_margin']) || isset($data['question_enabled'])) {
1238            if ($company) {
1239
1240                $n = 0;
1241                $invoiceMargin = 0;
1242                $minimumMargin = 0;
1243                $minimumOrderSize = 0;
1244
1245                if ($result->amount != $data['amount'] ||
1246                    $result->budget_type_id != $data['budget_type_id'] ||
1247                    $result->customer_type_id != $data['customer_type_id'] ||
1248                    $result->invoice_margin != $data['invoice_margin']
1249                ) {
1250                    $project = TblProjectTypes::where('company_id', $company->company_id)->where('budget_type_id', $data['budget_type_id'])->first();
1251                    $customerTypeIds = [];
1252
1253                    if ($project) {
1254                        if (! empty($project->customer_type_ids)) {
1255                            $customerTypeIds = array_map('intval', explode(',', $project->customer_type_ids));
1256                        }
1257                        if ($project->minimum_order_size != null && in_array($data['customer_type_id'], $customerTypeIds)) {
1258                            if ($data['amount'] >= $project->minimum_order_size) {
1259                                $data['for_approval'] = 1;
1260                                $n = 1;
1261                            }
1262                        }
1263                        $minimumOrderSize = $project->minimum_order_size;
1264
1265                        if ($project->minimum_order_size_v2 != null && in_array($data['customer_type_id'], $customerTypeIds)) {
1266                            if ($data['amount'] >= $project->minimum_order_size_v2) {
1267                                $data['for_approval'] = 1;
1268                                if ($n == 1) {
1269                                    $data['for_approval'] = 3;
1270                                    $n = 3;
1271                                }
1272                            }
1273                        }
1274
1275                    } else {
1276                        if (! empty($company->customer_type_ids)) {
1277                            $customerTypeIds = array_map('intval', explode(',', $company->customer_type_ids));
1278                        }
1279                        if ($company->minimum_order_size != null && in_array($data['customer_type_id'], $customerTypeIds)) {
1280                            if ($data['amount'] >= $company->minimum_order_size) {
1281                                $data['for_approval'] = 1;
1282                                $n = 1;
1283                            }
1284                        }
1285                        $minimumOrderSize = $company->minimum_order_size;
1286
1287                        if ($company->minimum_order_size_v2 != null && in_array($data['customer_type_id'], $customerTypeIds)) {
1288                            if ($data['amount'] >= $company->minimum_order_size_v2) {
1289                                $data['for_approval'] = 1;
1290                                if ($n == 1) {
1291                                    $data['for_approval'] = 3;
1292                                    $n = 3;
1293                                }
1294                            }
1295                        }
1296                    }
1297
1298                    if ($data['budget_margin_enabled'] > 0) {
1299                        $costOfLabor = $data['cost_of_labor'];
1300                        $totalCostOfJob = $data['total_cost_of_job'];
1301
1302                        if ($totalCostOfJob > 0) {
1303                            $invoiceMargin = $data['invoice_margin'] ?? 0;
1304                        }
1305
1306                        $minimumMargin = $company->minimum_margin;
1307                        if (! empty($company->customer_type_ids)) {
1308                            $customerTypeIds = array_map('intval', explode(',', $company->customer_type_ids));
1309                        }
1310
1311                        if ($project) {
1312                            $minimumMargin = $project->minimum_margin;
1313                            $minimumOrderSize = $project->minimum_order_size;
1314                            if (! empty($project->customer_type_ids)) {
1315                                $customerTypeIds = array_map('intval', explode(',', $project->customer_type_ids));
1316                            }
1317                        }
1318
1319                        if ($invoiceMargin < $minimumMargin && $invoiceMargin != null && $invoiceMargin != 0) {
1320                            if (in_array($data['customer_type_id'], $customerTypeIds)) {
1321                                $data['for_approval'] = 1;
1322                                $n = 2;
1323                            }
1324                        }
1325                    }
1326                }
1327
1328                $isQuestion = 0;
1329                $questionIdsNo = [];
1330                if (isset($data['question_enabled'])) {
1331                    if ($data['question_ids_no'] != $result->question_ids_no
1332                        || $data['budget_type_id'] != $result->budget_type_id
1333                        || $data['customer_type_id'] != $result->customer_type_id
1334                        || $data['amount'] != $result->amount) {
1335                        if ($data['question_enabled'] > 0 && $n == 0) {
1336                            if (! empty($data['question_ids_no'])) {
1337                                $questionIdsNo = array_map('intval', explode(',', $data['question_ids_no']));
1338
1339                                if ($company->workflow_budget_size != null) {
1340                                    if ($data['amount'] >= $company->workflow_budget_size) {
1341                                        $isQuestion = 1;
1342                                        $data['for_approval'] = 1;
1343                                        $n = 1;
1344                                    }
1345                                }
1346                                $minimumOrderSize = $company->workflow_budget_size;
1347
1348                            }
1349                        }
1350                    }
1351                }
1352
1353                if ($n == 1 || $n == 3) {
1354                    $sendApprovalNotification = true;
1355                    $approvalMinimumOrderSize = $minimumOrderSize;
1356                    $approvalId = $result->id;
1357                    $approvalForAdd = $result->for_add;
1358                    $approvalIsQuestion = $isQuestion;
1359                    $approvalQuestionIdsNo = $questionIdsNo;
1360                    $approvalN = $n;
1361                }
1362
1363                if ($n == 2) {
1364                    $sendApprovalMarginNotification = true;
1365                    $approvalMinimumMargin = $minimumMargin;
1366                    $approvalId = $result->id;
1367                    $approvalForAdd = $result->for_add;
1368                    $approvalInvoiceMargin = $invoiceMargin;
1369                }
1370            }
1371        }
1372
1373        $data['updated_at'] = date('Y-m-d H:i:s');
1374        $job['updated_at'] = $data['updated_at'];
1375
1376        $data['g3w_warning'] = 0;
1377
1378        if ($result->for_add == 1) {
1379            TblCompanies::where('company_id', $result->company_id)->update(['last_id' => $data['quote_id'], 'before_last_id' => $data['quote_id']]);
1380        }
1381
1382        $forApproval = @$data['for_approval'] ?? null;
1383
1384        if ($forApproval != null) {
1385            $data['approved_at'] = null;
1386            $data['approved_by'] = null;
1387            $data['rejected_at'] = null;
1388            $data['rejected_by'] = null;
1389            $data['approved_at_v2'] = null;
1390            $data['approved_by_v2'] = null;
1391            $data['rejected_at_v2'] = null;
1392            $data['rejected_by_v2'] = null;
1393        }
1394
1395        $actualQuotationValue = TblQuotations::where('id', $id)->first();
1396
1397        $differences = $this->compareArrays($data, $actualQuotationValue);
1398        $primaryAprovalsFields = ['budget_type_id', 'customer_type_id', 'budget_margin_enabled', 'amount', 'invoice_margin', 'margin_for_the_company', 'margin_on_invoice_per_day_per_worker', 'gross_margin'];
1399
1400        if (is_null($actualQuotationValue->customer_type_id)) {
1401            $needToSendReminder = true;
1402        }
1403
1404        foreach ($differences as $field => $value) {
1405            if (in_array($field, $primaryAprovalsFields)) {
1406                $needToSendReminder = true;
1407            }
1408            $statusId = $data['budget_status_id'] ?? $actualQuotationValue->budget_status_id;
1409            $categoryLog = $statusId == 6 ? 1 : 4;
1410            $this->addUpdateLog($id, $userId, $field, $value['oldData'], $value['newData'], $categoryLog);
1411        }
1412
1413        // check if the quotation are a solicitud and the user write the internal quote id
1414
1415        $budgetRequest = TblQuotations::where('id', $id)->first();
1416
1417        if (
1418            ($budgetRequest->budget_status_id == 6 || $budgetRequest->budget_status_id == 8)
1419            && (! is_null($data['internal_quote_id'] ?? null) && $data['internal_quote_id'] !== '')
1420            && (TblQuotations::where('internal_quote_id', $data['internal_quote_id'])
1421                ->where('company_id', $company->company_id)
1422                ->whereNotIn('budget_status_id', [6, 8])
1423                ->exists())
1424            && ($id !== '')
1425        ) {
1426            $createdAt = $budgetRequest->created_at;
1427            $lastFollowUpComment = $budgetRequest->last_follow_up_comment;
1428
1429            TblQuotations::where('id', $id)->first()->update(['internal_quote_id', $data['internal_quote_id']]);
1430
1431            $solicitudLogs = TblQuotationsLog::where('quotation_id', $id)->get();
1432
1433            $budget = TblQuotations::where('internal_quote_id', $data['internal_quote_id'])->where('company_id', $company->company_id)->first();
1434            TblFiles::where('quotation_id', $id)->where('is_internal', 1)->update(['quotation_id' => $budget->id]);
1435
1436            $this->callDeleteQuotation($id, $company->company_id, $userId, $data['updated_by']);
1437
1438            $id = $budget->id;
1439
1440            $dataToChange = array_intersect_key($data, array_flip([
1441                'internal_quote_id',
1442                'client',
1443                'phone_number',
1444                'email',
1445                'source_id',
1446                'created_by',
1447                'updated_by',
1448                'updated_at',
1449                'request_date',
1450                'last_follow_up_comment',
1451            ]));
1452
1453            if ($data['phone_number'] === null || $data['phone_number'] === '' || empty($dataToChange['phone_number'])) {
1454                unset($dataToChange['phone_number']);
1455            }
1456
1457            $dataToChange['budget_status_id'] = $budget->budget_status_id;
1458            $dataToChange['created_at'] = $createdAt;
1459            $dataToChange['last_follow_up_comment'] = $budget->last_follow_up_comment."\n".$lastFollowUpComment;
1460
1461            $data['g3w_warning'] = 0;
1462
1463            if (
1464                in_array($budget->budget_status_id, [13, 14]) ||
1465                ! $dataToChange['source_id'] ||
1466                (! $budget->budget_type_id || $budget->budget_type_id == 16) ||
1467                empty(trim($dataToChange['client'])) ||
1468                empty(trim($dataToChange['email']))
1469            ) {
1470                $data['g3w_warning'] = 1;
1471            }
1472
1473            TblQuotations::where('id', $id)->update($dataToChange);
1474
1475            if ($solicitudLogs->isNotEmpty()) {
1476                $nuevosLogs = array_map(function ($log) use ($budget) {
1477                    unset($log['id']);
1478                    $log['quotation_id'] = $budget->id;
1479
1480                    return $log;
1481                }, $solicitudLogs->toArray());
1482
1483            }
1484
1485        } else {
1486            TblQuotations::where('id', $id)->update($data);
1487        }
1488
1489        TblOngoingJobs::where('quotation_id', $id)->update($job);
1490
1491        $this->update_commercial_numbers($result->company_id);
1492
1493        if ($result->budget_status_id != $data['budget_status_id']
1494            && $data['budget_status_id'] == 3) {
1495            $this->send_acceptance_notification($result->id, $result->company_id, $userId, $data['updated_by']);
1496
1497            TblQuotations::where('id', $id)->update(
1498                [
1499                    'accepted_at' => $data['updated_at'],
1500                    'accepted_by' => $data['updated_by'],
1501                ]
1502            );
1503        }
1504
1505        if ($files) {
1506
1507            $uploadedFiles = [];
1508            $i = 0;
1509
1510            $combinedFilesSize = 0;
1511            foreach ($files as $file) {
1512                $i++;
1513                $origFilename = $file->getClientOriginalName();
1514                $filename = $result->id.'-'.$result->company_id.'-FC'.time().'-'.$origFilename;
1515
1516                $combinedFilesSize = $combinedFilesSize + $file->getSize();
1517
1518                if ($combinedFilesSize > 25000000) {
1519                    return response(['message' => 'KO', 'error' => __('language.file_size_exceeded')]);
1520                }
1521
1522                if (in_array($origFilename, $uploadedFiles)) {
1523                    $origFilename = $origFilename.$i;
1524                }
1525
1526                // $fileContent = file_get_contents($file->getRealPath());
1527                // $fileHash = hash('sha256', $fileContent);
1528
1529                $s3path = Storage::disk('s3')->putFileAs(
1530                    'uploads',
1531                    $file,
1532                    $filename,
1533                    [
1534                        'ContentType' => $file->getMimeType(),
1535                    ]
1536                );
1537
1538                TblFiles::create(
1539                    [
1540                        'quotation_id' => $id,
1541                        'original_name' => $origFilename,
1542                        'filename' => $filename,
1543                        'uploaded_by' => $data['updated_by'],
1544                        // 'file' => $fileContent,
1545                        'file_size' => $file->getSize(),
1546                        // 'file_hash' => $fileHash,
1547                        'mime_type' => $file->getMimeType(),
1548                        'uploaded_at' => now(),
1549                    ]
1550                );
1551                $this->addUpdateLog($id, $data['updated_by'], 'upload_attachment', null, $filename, 4);
1552
1553                $uploadedFiles[] = $file->getClientOriginalName();
1554            }
1555        }
1556
1557        if ($internalFiles) {
1558
1559            $uploadedFiles = [];
1560            $i = 0;
1561
1562            $combinedFilesSize = 0;
1563            foreach ($internalFiles as $file) {
1564                $i++;
1565                $origFilename = $file->getClientOriginalName();
1566                $filename = $result->id.'-'.$result->company_id.'-FI'.time().'-'.$origFilename;
1567
1568                $combinedFilesSize = $combinedFilesSize + $file->getSize();
1569
1570                if ($combinedFilesSize > 25000000) {
1571                    return response(['message' => 'KO', 'error' => __('language.file_size_exceeded')]);
1572                }
1573
1574                if (in_array($origFilename, $uploadedFiles)) {
1575                    $origFilename = $origFilename.$i;
1576                }
1577
1578                // $fileContent = file_get_contents($file->getRealPath());
1579                // $fileHash = hash('sha256', $fileContent);
1580
1581                $s3path = Storage::disk('s3')->putFileAs(
1582                    'uploads',
1583                    $file,
1584                    $filename,
1585                    [
1586                        'ContentType' => $file->getMimeType(),
1587                    ]
1588                );
1589
1590                TblFiles::create(
1591                    [
1592                        'quotation_id' => $id,
1593                        'original_name' => $origFilename,
1594                        'filename' => $filename,
1595                        'uploaded_by' => $data['updated_by'],
1596                        // 'file' => $fileContent,
1597                        'file_size' => $file->getSize(),
1598                        // 'file_hash' => $fileHash,
1599                        'mime_type' => $file->getMimeType(),
1600                        'uploaded_at' => now(),
1601                        'is_internal' => 1,
1602                    ]
1603                );
1604                $this->addUpdateLog($id, $data['updated_by'], 'upload_attachment', null, $filename, 4);
1605
1606                $uploadedFiles[] = $file->getClientOriginalName();
1607            }
1608        }
1609
1610        $query = "SELECT
1611                        a.id,
1612                        a.quote_id,
1613                        a.company_id,
1614                        b.name company_name,
1615                        a.client,
1616                        c.name client_type,
1617                        c.customer_type_id,
1618                        a.request_date,
1619                        a.visit_date,
1620                        a.issue_date,
1621                        a.acceptance_date,
1622                        a.internal_quote_id,
1623                        DATE_FORMAT(a.request_date, '%d/%m/%Y') request_date_translate,
1624                        DATE_FORMAT(a.issue_date, '%d/%m/%Y') issue_date_translate,
1625                        DATE_FORMAT(a.acceptance_date, '%d/%m/%Y') acceptance_date_translate,
1626                        DATE_FORMAT(a.last_follow_up_date, '%d/%m/%Y') last_follow_up_date_translate,
1627                        -- DATEDIFF(a.issue_date, a.request_date) duration,
1628                        a.phone_number,
1629                        a.email,
1630                        a.duration,
1631                        a.order_number,
1632                        d.name 'type',
1633                        d.budget_type_id,
1634                        e.name 'status',
1635                        e.budget_status_id,
1636                        f.name source,
1637                        f.source_id,
1638                        a.amount,
1639                        g.name reason_for_not_following_up,
1640                        a.reason_for_not_following_up_id,
1641                        a.reason_for_rejection_id,
1642                        a.last_follow_up_date,
1643                        a.last_follow_up_comment,
1644                        CASE WHEN a.reason_for_rejection_id IS NULL THEN a.reason_for_rejection ELSE h.name END reason_for_rejection,
1645                        a.commercial,
1646                        a.created_by,
1647                        a.created_at,
1648                        a.updated_by,
1649                        a.for_approval,
1650                        a.box_work_g3w,
1651                        a.people_assigned_to_the_job,
1652                        a.duration_of_job_in_days,
1653                        a.estimated_cost_of_materials,
1654                        a.budget_margin_enabled,
1655                        a.question_enabled,
1656                        a.cost_of_labor,
1657                        a.total_cost_of_job,
1658                        CASE WHEN a.budget_margin_enabled > 0 THEN a.invoice_margin ELSE NULL END invoice_margin,
1659                        CASE WHEN a.budget_margin_enabled > 0 THEN a.margin_for_the_company ELSE NULL END margin_for_the_company,
1660                        a.margin_on_invoice_per_day_per_worker,
1661                        a.revenue_per_date_per_worked,
1662                        a.commission_cost,
1663                        a.commission_pct,
1664                        a.gross_margin,
1665                        a.labor_percentage,
1666                        a.question_ids,
1667                        a.question_ids_no,
1668                        a.approved_at,
1669                        a.approved_by,
1670                        a.rejected_at,
1671                        a.rejected_by,
1672                        a.approved_at_v2,
1673                        a.approved_by_v2,
1674                        a.rejected_at_v2,
1675                        a.rejected_by_v2,
1676                        a.accepted_at,
1677                        a.accepted_by,
1678                        a.is_validated,
1679                        a.resource_id,
1680                        a.x_status,
1681                        a.likehood,
1682                        a.updated_at
1683                    FROM
1684                        tbl_quotations a
1685                        LEFT JOIN tbl_companies b ON a.company_id = b.company_id
1686                        LEFT JOIN tbl_customer_types c ON a.customer_type_id = c.customer_type_id
1687                        LEFT JOIN tbl_budget_types d ON a.budget_type_id = d.budget_type_id
1688                        LEFT JOIN tbl_budget_status e ON a.budget_status_id = e.budget_status_id
1689                        LEFT JOIN tbl_sources f ON a.source_id = f.source_id
1690                        LEFT JOIN tbl_reason_for_not_following_up g ON a.reason_for_not_following_up_id = g.reason_for_not_following_up_id
1691                        LEFT JOIN tbl_reason_for_rejection h ON a.reason_for_rejection_id = h.reason_for_rejection_id
1692                    WHERE a.id = {$id}";
1693
1694        $result = DB::select($query);
1695
1696        if ($sendNotification) {
1697            $this->send_notification(
1698                $commercial->email,
1699                $userId,
1700                $data['quote_id'],
1701                $id,
1702                $status->name,
1703                $commercial->id,
1704                $company->name,
1705                0,
1706                $company->company_id,
1707                $data['internal_quote_id']
1708            );
1709        }
1710
1711        if ($sendApprovalNotification && $needToSendReminder) {
1712            $this->send_approval_notification(
1713                $data['amount'],
1714                $data['budget_type_id'],
1715                $data['customer_type_id'],
1716                $approvalMinimumOrderSize,
1717                $data['quote_id'],
1718                $approvalId,
1719                $company->name,
1720                @$data['created_by'] ?? @$data['updated_by'],
1721                $userId,
1722                $approvalForAdd,
1723                $commercial ? $commercial->email : null,
1724                $company->company_id,
1725                'orders',
1726                $approvalIsQuestion,
1727                $approvalQuestionIdsNo,
1728                $approvalN
1729            );
1730        }
1731
1732        if ($sendApprovalMarginNotification && $needToSendReminder) {
1733            $this->send_approval_margin_notification(
1734                $data['amount'],
1735                $data['budget_type_id'],
1736                $data['customer_type_id'],
1737                $approvalMinimumMargin,
1738                $data['quote_id'],
1739                $approvalId,
1740                $company->name,
1741                @$data['created_by'] ?? @$data['updated_by'],
1742                $userId,
1743                $approvalForAdd,
1744                $commercial ? $commercial->email : null,
1745                $approvalInvoiceMargin,
1746                $company->company_id,
1747                'orders'
1748            );
1749        }
1750
1751        if (isset($result['budget_status_id']) && $result['budget_status_id'] == 6) {
1752            $data = [
1753                'id' => $result['id'] ?? null,
1754                'client' => $result['client'] ?? null,
1755                'email' => $result['email'] ?? null,
1756                'phone_number' => $result['phone_number'] ?? null,
1757                'last_follow_up_comment' => $result['last_follow_up_comment'] ?? null,
1758                'quote_id' => $result['quote_id'] ?? null,
1759                'request_date' => date('Y-m-d'),
1760                'updated_by' => 'IA',
1761                'user_id' => $result['user_id'] ?? null,
1762                'commercial' => $result['commercial'] ?? null,
1763                'budget_status_id' => $result['budget_status_id'],
1764                'internal_quote_id' => $result['internal_quote_id'] ?? null,
1765            ];
1766
1767            $ch = curl_init('https://2lsarnb35o6evhgwmfedrsxk3i0lqzzq.lambda-url.eu-west-2.on.aws/checkduplicate');
1768            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
1769            curl_setopt($ch, CURLOPT_POST, true);
1770            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
1771            curl_setopt($ch, CURLOPT_HTTPHEADER, [
1772                'Content-Type: application/json',
1773            ]);
1774
1775            $response = curl_exec($ch);
1776            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
1777
1778            if (curl_errno($ch)) {
1779                error_log('Error en cURL: '.curl_error($ch));
1780            }
1781
1782            curl_close($ch);
1783        }
1784
1785        Cache::flush();
1786
1787        return response(['message' => 'OK', 'data' => $result, 'for_approval' => $forApproval]);
1788
1789        // } catch (\Exception $e) {
1790        //     return response(['message' => 'KO', 'error' => $e->getMessage()]);
1791        // }
1792
1793    }
1794
1795    private function compareArrays($data, $quotations)
1796    {
1797        $differences = [];
1798        $attributes = $quotations->getAttributes();
1799
1800        foreach ($data as $field => $valueData) {
1801            if (array_key_exists($field, $attributes)) {
1802                $valueQuotations = $quotations->$field;
1803
1804                $valueData = $this->convertValue($valueData);
1805                $valueQuotations = $this->convertValue($valueQuotations);
1806
1807                if ($valueData !== $valueQuotations) {
1808                    if ($this->isEmpty($valueData) && $this->isEmpty($valueQuotations)) {
1809                        continue;
1810                    }
1811
1812                    $differences[$field] = [
1813                        'newData' => $valueData,
1814                        'oldData' => $valueQuotations,
1815                    ];
1816                }
1817            }
1818        }
1819
1820        return $differences;
1821    }
1822
1823    private function isEmpty($value): bool
1824    {
1825        return is_null($value) || $value === '' || $value === 0 || $value === '0';
1826    }
1827
1828    private function convertValue($value)
1829    {
1830        if ($value === null) {
1831            return null;
1832        }
1833
1834        if (is_numeric($value)) {
1835            return (int) $value;
1836        }
1837
1838        if ($value === 'NULL' || $value === 'null') {
1839            return null;
1840        }
1841
1842        if (is_string($value)) {
1843            if (preg_match('/^(\d{4}-\d{2}-\d{2})( \d{2}:\d{2}:\d{2})?$/', $value, $matches)) {
1844                return $matches[1];
1845            }
1846        }
1847
1848        return $value;
1849    }
1850
1851    protected function callDeleteQuotation($id, $company_id, $userId, $user)
1852    {
1853        $request = new \Illuminate\Http\Request([
1854            'company_id' => $company_id,
1855            'user_id' => $userId,
1856            'updated_by' => $user,
1857            'ids' => [$id],
1858            'filterModel' => [],
1859            'sortModel' => [],
1860            'searchText' => '',
1861            'ids_not_in' => [],
1862        ]);
1863
1864        return $this->delete_quotation($request, true);
1865    }
1866
1867    public function get_quotation($id)
1868    {
1869
1870        try {
1871
1872            $id = intval($id);
1873
1874            $query = "SELECT
1875                        a.id,
1876                        a.quote_id,
1877                        a.company_id,
1878                        b.name company_name,
1879                        a.client,
1880                        c.name client_type,
1881                        c.customer_type_id,
1882                        s.name segment,
1883                        s.segment_id,
1884                        a.request_date,
1885                        a.visit_date,
1886                        a.issue_date,
1887                        a.acceptance_date,
1888                        a.internal_quote_id,
1889                        DATE_FORMAT(a.request_date, '%d/%m/%Y') request_date_translate,
1890                        DATE_FORMAT(a.issue_date, '%d/%m/%Y') issue_date_translate,
1891                        DATE_FORMAT(a.acceptance_date, '%d/%m/%Y') acceptance_date_translate,
1892                        DATE_FORMAT(a.last_follow_up_date, '%d/%m/%Y') last_follow_up_date_translate,
1893                        a.phone_number,
1894                        a.email,
1895                        a.duration,
1896                        a.order_number,
1897                        d.name 'type',
1898                        d.budget_type_id,
1899                        e.name 'status',
1900                        e.budget_status_id,
1901                        f.name source,
1902                        f.source_id,
1903                        a.amount,
1904                        g.name reason_for_not_following_up,
1905                        a.reason_for_not_following_up_id,
1906                        a.reason_for_rejection_id,
1907                        a.last_follow_up_date,
1908                        a.last_follow_up_comment,
1909                        CASE WHEN a.reason_for_rejection_id IS NULL THEN a.reason_for_rejection ELSE h.name END reason_for_rejection,
1910                        a.commercial,
1911                        a.created_by,
1912                        a.created_at,
1913                        a.updated_by,
1914                        a.updated_at,
1915                        a.for_approval,
1916                        a.box_work_g3w,
1917                        a.people_assigned_to_the_job,
1918                        a.duration_of_job_in_days,
1919                        a.estimated_cost_of_materials,
1920                        a.budget_margin_enabled,
1921                        a.question_enabled,
1922                        a.cost_of_labor,
1923                        a.total_cost_of_job,
1924                        CASE WHEN a.budget_margin_enabled > 0 THEN a.invoice_margin ELSE NULL END invoice_margin,
1925                        CASE WHEN a.budget_margin_enabled > 0 THEN a.margin_for_the_company ELSE NULL END margin_for_the_company,
1926                        a.margin_on_invoice_per_day_per_worker,
1927                        a.revenue_per_date_per_worked,
1928                        a.commission_cost,
1929                        a.commission_pct,
1930                        a.gross_margin,
1931                        a.labor_percentage,
1932                        a.question_ids,
1933                        a.question_ids_no,
1934                        a.approved_at,
1935                        a.approved_by,
1936                        a.rejected_at,
1937                        a.rejected_by,
1938                        a.approved_at_v2,
1939                        a.approved_by_v2,
1940                        a.rejected_at_v2,
1941                        a.rejected_by_v2,
1942                        a.accepted_at,
1943                        a.accepted_by,
1944                        a.is_validated,
1945                        a.resource_id,
1946                        a.sync_import,
1947                        a.sync_import_edited,
1948                        a.g3w_warning,
1949                        a.g3w_warning_fields,
1950                        a.id_solicitud_duplicity,
1951                        a.x_status
1952                    FROM
1953                        tbl_quotations a
1954                        LEFT JOIN tbl_companies b ON a.company_id = b.company_id
1955                        LEFT JOIN tbl_customer_types c ON a.customer_type_id = c.customer_type_id
1956                        LEFT JOIN tbl_segments s ON a.segment_id = s.segment_id
1957                        LEFT JOIN tbl_budget_types d ON a.budget_type_id = d.budget_type_id
1958                        LEFT JOIN tbl_budget_status e ON a.budget_status_id = e.budget_status_id
1959                        LEFT JOIN tbl_sources f ON a.source_id = f.source_id
1960                        LEFT JOIN tbl_reason_for_not_following_up g ON a.reason_for_not_following_up_id = g.reason_for_not_following_up_id
1961                        LEFT JOIN tbl_reason_for_rejection h ON a.reason_for_rejection_id = h.reason_for_rejection_id
1962                    WHERE a.id = {$id}
1963                    AND a.company_id IN ({$this->companyId})";
1964
1965            $result = DB::select($query);
1966
1967            Cache::flush();
1968
1969            return response(['message' => 'OK', 'data' => $result]);
1970
1971        } catch (\Exception $e) {
1972            /** @disregard P1014 */
1973            $e->exceptionCode = 'GET_QUOTATION_EXCEPTION';
1974            report($e);
1975
1976            return response(['message' => 'KO', 'error' => $e->getMessage()]);
1977        }
1978    }
1979
1980    public function get_quotation_log($id)
1981    {
1982        return TblQuotationsLog::where('quotation_id', $id)->get();
1983    }
1984
1985    public function send_notification($toEmail, $userId, $quoteId, $id, $status, $sendUserId, $companyName, $action, $companyId, $g3wQuoteId)
1986    {
1987
1988        $user = TblUsers::where('id', $userId)->first();
1989
1990        $imgpath = File::get('fireservicetitan.png');
1991
1992        $url = env('URL')."orders/{$id}?company_id={$companyId}";
1993        $href = "<a href='{$url}'>{$quoteId}</a>";
1994
1995        $body = '';
1996        $subject = '';
1997
1998        if ($g3wQuoteId) {
1999            $quoteId = $quoteId." - G3W #{$g3wQuoteId}";
2000        }
2001
2002        if ($action == 1) {
2003            $body = __('language.email_notification.body_created');
2004            $body = str_replace('{{creator}}', $user->name, $body);
2005            $subject = str_replace('{{quote_id}}', $quoteId, __('language.email_notification.subject_created'));
2006        } else {
2007            $body = __('language.email_notification.body_assigned');
2008            $body = str_replace('{{assignee}}', $user->name, $body);
2009            $subject = str_replace('{{quote_id}}', $quoteId, __('language.email_notification.subject_assigned'));
2010        }
2011
2012        $body = str_replace('{{quote_id}}', $href, $body);
2013        $body = str_replace('{{company}}', $companyName, $body);
2014        $body = str_replace('{{status}}', $status, $body);
2015
2016        $content = $body;
2017
2018        $body .= '<p>Fire Service Titan</p>';
2019        $body .= "<img src='cid:fireservicetitan' style='height: 45px;' />";
2020
2021        $html = '<!DOCTYPE html>';
2022        $html .= '<html>';
2023        $html .= '<head>';
2024        $html .= '<meta charset="UTF-8">';
2025        $html .= '<meta name="viewport" content="width=device-width, initial-scale=1.0">';
2026        $html .= '</head>';
2027        $html .= '<body>';
2028        $html .= $body;
2029        $html .= '</body>';
2030        $html .= '</html>';
2031
2032        if ($toEmail != null) {
2033            $email = new \SendGrid\Mail\Mail;
2034
2035            if (env('SENDGRID_STAGING')) {
2036                $toEmail = $user->email;
2037            }
2038
2039            $email->setFrom('fire@fire.es', 'Fire Service Titan');
2040            $email->setSubject($subject);
2041            $email->addTo($toEmail);
2042            $email->addContent('text/html', $html);
2043
2044            $email->addAttachment(
2045                $imgpath,
2046                'image/png',
2047                'fireservicetitan.png',
2048                'inline',
2049                'fireservicetitan'
2050            );
2051
2052            $sendgrid = new \SendGrid(env('SENDGRID_API_KEY'));
2053
2054            $response = $sendgrid->send($email);
2055            if ($response->statusCode() == 202) {
2056                Log::channel('email_log')->info('ID:'.$quoteId.' : '.$status.' : '.$toEmail.' - EMAIL NOTIFICATION SENT');
2057                $this->addUpdateLog($id, $sendUserId, 'send_notification', null, null, 5);
2058
2059                TblNotifications::create(
2060                    [
2061                        'user_id' => $sendUserId,
2062                        'content' => $content,
2063                        'is_open' => 1,
2064                        'created_by' => 'System',
2065                        'link' => $url,
2066                    ]
2067                );
2068            } else {
2069                $error = true;
2070                Log::channel('email_log')->error('ID:'.$quoteId.' : '.$status.' : '.$toEmail.' - '.$response->body());
2071            }
2072        }
2073
2074    }
2075
2076    public function delete_quotation(Request $request, $isFromDeleteCall = false)
2077    {
2078
2079        try {
2080
2081            $data = $request->all();
2082            $result = [];
2083
2084            if (count($data['ids']) > 1) {
2085                $u = TblUsers::where('id', $data['user_id'])->first();
2086
2087                if ($u->role_id != 1) {
2088                    return response(['message' => 'KO', 'error' => 'more_than_one']);
2089                }
2090            }
2091
2092            $r = new Request([
2093                'filterModel' => $data['filterModel'],
2094                'sortModel' => $data['sortModel'],
2095                'start' => 0,
2096                'end' => 999999999,
2097                'company_id' => $data['company_id'],
2098                'user_id' => $data['user_id'],
2099                'ids' => $data['ids'],
2100                'searchText' => $data['searchText'],
2101                'ids_not_in' => $data['ids_not_in'],
2102            ]);
2103
2104            $d = [];
2105
2106            $result = $this->list_quotations($r);
2107            $result = $result->original['data'];
2108
2109            $outputArray = [];
2110
2111            foreach ($result as $item) {
2112                if (isset($item->id)) {
2113                    $outputArray[] = $item->id;
2114                }
2115            }
2116
2117            $ids = implode(',', $outputArray);
2118
2119            if ($outputArray) {
2120
2121                TblQuotations::whereIn('id', $outputArray)->update(
2122                    [
2123                        'updated_at' => date('Y-m-d H:i:s'),
2124                        'updated_by' => $data['updated_by'],
2125                        'for_add' => $isFromDeleteCall ? 2 : ($data['for_add'] ?? 0),
2126                        'reason_id' => (isset($data['reason_id']) ? $data['reason_id'] : null),
2127                        'reason_for_deletion' => (isset($data['reason_for_deletion']) ? $data['reason_for_deletion'] : null),
2128                    ]
2129                );
2130
2131                $query = "INSERT INTO tbl_quotations_deleted
2132                        SELECT * FROM tbl_quotations WHERE id IN ({$ids})";
2133
2134                DB::select($query);
2135
2136                TblQuotations::whereIn('id', $outputArray)->delete();
2137                TblFiles::whereIn('quotation_id', $outputArray)->delete();
2138            }
2139
2140            foreach ($outputArray as $id) {
2141                $this->addUpdateLog($id, $data['user_id'], 'delete', null, null, 6);
2142            }
2143
2144            Cache::flush();
2145
2146            return response(['message' => 'OK', 'data' => $result]);
2147
2148        } catch (\Exception $e) {
2149            /** @disregard P1014 */
2150            $e->exceptionCode = 'DELETE_QUOTATION_EXCEPTION';
2151            report($e);
2152
2153            return response(['message' => 'KO', 'error' => $e->getMessage()]);
2154        }
2155
2156    }
2157
2158    public function getBlacklistEmails()
2159    {
2160        return [
2161            "no\.no",
2162            "tiene\.email",
2163            "test\.com",
2164            "no\.tiene",
2165            "prueba\.com",
2166            "nomail@nomail\.com",
2167            "notiene@notiene\.notiene",
2168        ];
2169    }
2170
2171    public function list_quotations(Request $request)
2172    {
2173
2174        // try {
2175
2176        $data = $request->all();
2177        $companyId = intval($data['company_id']);
2178        $userId = intval($data['user_id']);
2179        $filter = $data['filterModel'];
2180        $sort = $data['sortModel'];
2181        $result = [];
2182        $subquery = '';
2183        $where = '';
2184        $having = '';
2185        $orderBy = '';
2186        $start = intval($data['start']);
2187        $end = intval($data['end']);
2188        $totalRowCount = 0;
2189        $withFilters = '';
2190        $logFilter = @$data['log_filter'];
2191        $isInvalidEmail = (isset($data['invalid_email']) && $data['invalid_email'] == 1);
2192        $isFollowUp = (isset($data['is_follow_up']) && $data['is_follow_up'] == 1);
2193
2194        $filterType = [
2195            'contains' => "LIKE '%[value]%'",
2196            'notContains' => "NOT LIKE '%[value]%'",
2197            'equals' => "= '[value]'",
2198            'notEqual' => "<> '[value]'",
2199            'startsWith' => "LIKE '[value]%'",
2200            'endsWith' => "LIKE '%[value]'",
2201            'blank' => 'IS NULL',
2202            'notBlank' => 'IS NOT NULL',
2203            'lessThan' => '< [value]',
2204            'lessThanOrEqual' => '<= [value]',
2205            'greaterThan' => '> [value]',
2206            'greaterThanOrEqual' => '>= [value]',
2207            'inRange' => 'BETWEEN [value1] AND [value2]',
2208            'in' => 'IN ([value])',
2209        ];
2210
2211        /*if(isset($data['internal_quote_id']) && count($data['internal_quote_id']) > 0){
2212            $internalIds = implode(",", $data['internal_quote_id']);
2213            $where = " AND a.internal_quote_id IN ({$internalIds}) ";
2214        }*/
2215
2216        if (isset($data['ids']) && count($data['ids']) > 0) {
2217            $quoteIds = implode(',', $data['ids']);
2218            $where .= " AND a.id IN ({$quoteIds}";
2219        }
2220
2221        if (isset($data['ids_not_in']) && count($data['ids_not_in']) > 0) {
2222            $quoteIds = implode(',', $data['ids_not_in']);
2223            $where .= " AND a.id NOT IN ({$quoteIds}";
2224        }
2225
2226        $lasLeftJoin = '';
2227        $whereBlocked = '';
2228
2229        if (isset($data['last_follow_up_date']) && ! empty($data['last_follow_up_date'])) {
2230            if ($data['last_follow_up_date'] == 1) {
2231
2232                $lasLeftJoin = " LEFT JOIN (
2233                        SELECT
2234                          a.id,
2235                          SUBSTRING_INDEX(
2236                            SUBSTRING_INDEX(a.email, ',', n.digit + 1),
2237                            ',',
2238                            -1
2239                          ) AS email_domain
2240                        FROM
2241                          tbl_quotations a
2242                          INNER JOIN (
2243                            SELECT
2244                              0 AS digit
2245                            UNION ALL
2246                            SELECT
2247                              1
2248                            UNION ALL
2249                            SELECT
2250                              2
2251                            UNION ALL
2252                            SELECT
2253                              3
2254                            UNION ALL
2255                            SELECT
2256                              4
2257                            UNION ALL
2258                            SELECT
2259                              5
2260                            UNION ALL
2261                            SELECT
2262                              6
2263                            UNION ALL
2264                            SELECT
2265                              7
2266                            UNION ALL
2267                            SELECT
2268                              8
2269                            UNION ALL
2270                            SELECT
2271                              9
2272                          ) n ON LENGTH(
2273                            REPLACE(a.email, ',', '')
2274                          ) <= LENGTH(a.email)- n.digit
2275                          GROUP BY a.id
2276                      ) temp ON a.id = temp.id ";
2277
2278                $whereBlocked = " AND a.last_follow_up_date < NOW()
2279                            AND a.budget_status_id IN (2)
2280                            AND a.email IS NOT NULL
2281                            AND a.email <> ''
2282                            AND NOT EXISTS (
2283                                SELECT
2284                                1
2285                                FROM
2286                                tbl_blocked_domains bd
2287                                WHERE
2288                                temp.email_domain LIKE CONCAT('%', bd.domain, '%')
2289                                AND bd.company_id = a.company_id
2290                            )
2291                            AND a.last_follow_up_date IS NOT NULL
2292                            AND a.reason_for_not_following_up_id IS NULL
2293                            AND a.last_follow_up_date > 0
2294                            AND a.total_sent < b.limit_reminder_emails
2295                            AND a.for_add = 0 ";
2296            }
2297        }
2298
2299        if (isset($data['visit_date']) && ! empty($data['visit_date'])) {
2300            if ($data['visit_date'] == 1) {
2301                $where = " AND DATE_FORMAT(a.visit_date, '%Y-%m-%d') <= DATE_FORMAT(NOW(), '%Y-%m-%d') ";
2302            }
2303        }
2304
2305        if ($companyId != 0) {
2306            $where .= " AND a.company_id = {$companyId} ";
2307        } elseif ($this->companyId) {
2308            $where .= " AND a.company_id IN ({$this->companyId}";
2309        }
2310
2311        $matchScoreCol = '';
2312        $matchScoreOrderBy = '';
2313
2314        if (isset($data['searchText']) && $data['searchText'] != null) {
2315
2316            $availableParameters = [
2317                'a.quote_id',
2318                'a.internal_quote_id',
2319                'a.box_work_g3w',
2320                's.name',
2321                'b.name',
2322                'a.client',
2323                'c.name',
2324                'a.phone_number',
2325                'a.email',
2326                'a.order_number',
2327                'a.request_date',
2328                'a.issue_date',
2329                'a.acceptance_date',
2330                'a.created_at',
2331                'a.updated_at',
2332                'a.rejected_at',
2333                'a.accepted_at',
2334                'd.name',
2335                'e.name',
2336                'f.name',
2337                'a.amount',
2338                'g.name',
2339                'a.last_follow_up_comment',
2340                'a.x_status',
2341                'h.name',
2342                'a.commercial',
2343                'a.user_commercial_by_g3w',
2344                'a.user_create_by_g3w',
2345                'a.created_by',
2346                'a.updated_by',
2347                'a.approved_by',
2348                'a.rejected_by',
2349                'a.accepted_by',
2350                'a.sync_import',
2351                'a.sync_import_edited',
2352                'a.g3w_warning',
2353            ];
2354
2355            $searchText = addslashes($data['searchText']);
2356            $searchTextArray = explode(' ', $searchText);
2357
2358            $searchArray = [];
2359            $splitSearchArray = [];
2360            $matchScoreArray = [];
2361            $sc = 1;
2362            foreach ($availableParameters as $field) {
2363                if ($field == 'a.client' || $field == 'a.amount' || $field == 'a.created_at') {
2364                    $sc = 3;
2365                } elseif ($field == 'a.acceptance_date') {
2366                    $sc = 2;
2367                } else {
2368                    $sc = 1;
2369                }
2370
2371                $l = "{$field} LIKE '%{$searchText}%'";
2372                if ($field == 'a.last_follow_up_comment') {
2373                    $l = "{$field} = '{$searchText}'";
2374                } else {
2375
2376                    $d = "IFNULL((LENGTH(LOWER({$field})) - LENGTH(REPLACE(LOWER({$field}), LOWER('{$searchText}'), ''))) / LENGTH(LOWER('{$searchText}')), 0) * {$sc}";
2377
2378                    if (count($searchTextArray) > 1) {
2379                        foreach ($searchTextArray as $word) {
2380                            if (! is_numeric($word)) {
2381                                $d .= " + IFNULL((LENGTH(LOWER({$field})) - LENGTH(REPLACE(LOWER({$field}), LOWER('{$word}'), ''))) / LENGTH(LOWER('{$word}')), 0) * {$sc}";
2382                            }
2383                        }
2384                    }
2385
2386                    array_push($matchScoreArray, $d);
2387                }
2388
2389                if (is_numeric($searchText)) {
2390                    array_push($searchArray, "({$l} OR {$field} = CAST('{$searchText}' AS UNSIGNED))");
2391                } else {
2392                    array_push($searchArray, "({$l} OR DATE_FORMAT({$field}, '%d/%m/%Y') = DATE_FORMAT(STR_TO_DATE('{$searchText}', '%d/%m/%Y'), '%d/%m/%Y'))");
2393                }
2394
2395                if (count($searchTextArray) > 1) {
2396                    foreach ($searchTextArray as $word) {
2397
2398                        $l = "{$field} LIKE '%{$word}%'";
2399                        if ($field == 'a.last_follow_up_comment') {
2400                            $l = "{$field} = '{$word}'";
2401                        }
2402
2403                        if (is_numeric($word)) {
2404                            array_push($splitSearchArray, "{$l} OR {$field} = CAST('{$word}' AS UNSIGNED)");
2405                        } else {
2406                            array_push($splitSearchArray, "{$l} OR DATE_FORMAT({$field}, '%d/%m/%Y') = DATE_FORMAT(STR_TO_DATE('{$word}', '%d/%m/%Y'), '%d/%m/%Y')");
2407                        }
2408                    }
2409                }
2410
2411                $sc = 1;
2412            }
2413
2414            if (count($splitSearchArray) > 0) {
2415                $splitSearchArray = implode(' OR ', $splitSearchArray);
2416                $splitSearchArray = " OR ({$splitSearchArray}";
2417            } else {
2418                $splitSearchArray = '';
2419            }
2420
2421            $searchArray = implode(' OR ', $searchArray);
2422            $matchScoreArray = implode(',', $matchScoreArray);
2423            $matchScoreCol = ", GREATEST({$matchScoreArray}) match_score";
2424            $matchScoreOrderBy = 'match_score DESC,';
2425            $where .= " AND ({$searchArray} {$splitSearchArray})";
2426        }
2427
2428        if (count($sort) > 0) {
2429            $field = $sort[0]['colId'];
2430            $sortBy = $sort[0]['sort'];
2431
2432            if (strpos($field, 'translate') !== false) {
2433                $field = str_replace('_translate', '', $field);
2434            } else {
2435                if ($field == 'client_type') {
2436                    $field = 'c.name';
2437                } elseif ($field == 'segment') {
2438                    $field = 's.name';
2439                } elseif ($field == 'type') {
2440                    $field = 'd.name';
2441                } elseif ($field == 'status') {
2442                    $field = 'e.name';
2443                } elseif ($field == 'source') {
2444                    $field = 'g.name';
2445                } elseif ($field == 'reason_for_not_following_up') {
2446                    $field = 'g.name';
2447                } elseif ($field == 'reason_for_rejection') {
2448                    $field = 'h.name';
2449                } elseif ($field == 'amount') {
2450                    $field = 'CAST(a.amount AS DOUBLE)';
2451                } elseif ($field == 'duration') {
2452                    $field = 'CAST(a.duration AS DOUBLE)';
2453                } elseif ($field == 'quote_id' || $field == 'internal_quote_id') {
2454                    $field = "CAST(a.{$field} AS DOUBLE)";
2455                } elseif ($field == 'company_name') {
2456                    $field = 'b.name';
2457                }
2458
2459            }
2460
2461            if ($matchScoreOrderBy) {
2462                $matchScoreOrderBy = ', match_score DESC';
2463            }
2464
2465            $orderBy = " ORDER BY {$field} {$sortBy} {$matchScoreOrderBy}";
2466        } else {
2467            $orderBy = " ORDER BY {$matchScoreOrderBy} a.id DESC";
2468        }
2469
2470        foreach ($filter as $key => $data) {
2471            if (strpos($key, 'translate') !== false) {
2472
2473                $field = str_replace('_translate', '', $key);
2474                if ($field == 'created_at') {
2475                    $field = 'a.created_at';
2476                } elseif ($field == 'last_follow_up_date') {
2477                    $field = 'a.last_follow_up_date';
2478                } elseif ($field == 'issue_date') {
2479                    $field = 'a.issue_date';
2480                } elseif ($field == 'request_date') {
2481                    $field = 'a.request_date';
2482                } elseif ($field == 'acceptance_date') {
2483                    $field = 'a.acceptance_date';
2484                } elseif ($field == 'internal_quote_id') {
2485                    $field = 'a.internal_quote_id';
2486                }
2487
2488                $whereDates = '';
2489                $z = 0;
2490
2491                if (isset($data['filters']) && ! empty($data['filters'])) {
2492                    $yearsMonths = [];
2493                    $yearsWeeks = [];
2494                    $yearsMW = [];
2495                    foreach ($data['filters'] as $yearKey => $yearData) {
2496
2497                        if ($yearData['isChecked']) {
2498
2499                            if ($yearData['isCheckedAllMonths'] && $yearData['isCheckedAllWeeks']) {
2500                                if ($z > 0) {
2501                                    $whereDates .= " OR YEAR($field) = {$yearKey} ";
2502                                } else {
2503                                    $whereDates .= " YEAR($field) = {$yearKey} ";
2504                                }
2505                            } else {
2506
2507                                if ($yearData['isCheckedAllWeeks']) {
2508                                    for ($i = 0; $i < count($yearData['weeks']); $i++) {
2509                                        if ($yearData['weeks'][$i]['isChecked']) {
2510                                            array_push($yearsMW, " YEARWEEK({$field}, 1) = '{$yearKey}{$yearData['weeks'][$i]['value']}");
2511                                        }
2512                                    }
2513                                }
2514
2515                                if ($yearData['isCheckedAllMonths']) {
2516                                    for ($i = 0; $i < count($yearData['months']); $i++) {
2517                                        if ($yearData['months'][$i]['isChecked']) {
2518                                            array_push($yearsMW, " DATE_FORMAT({$field}, '%Y%m') = '{$yearKey}{$yearData['months'][$i]['value']}");
2519                                        }
2520                                    }
2521                                }
2522
2523                                if (! $yearsMW) {
2524                                    if (! $yearData['isCheckedAllMonths']) {
2525                                        if ($z > 0) {
2526                                            $whereDates .= " OR YEAR($field) = {$yearKey} ";
2527                                        } else {
2528                                            $whereDates .= " YEAR($field) = {$yearKey} ";
2529                                        }
2530                                    }
2531                                }
2532                            }
2533
2534                            $z++;
2535                        }
2536
2537                    }
2538
2539                    if ($yearsMW) {
2540                        $whereDates .= implode(' OR ', $yearsMW);
2541                    }
2542                }
2543
2544                $whereDataUptoToday = '';
2545                if (isset($data['isDataUptoToday'])) {
2546                    if ($data['isDataUptoToday']) {
2547                        $whereDates = '';
2548                        $whereDataUptoToday .= " AND {$field} < NOW() AND {$field} > 0 ";
2549                    }
2550                }
2551
2552                $whereBlanks = '';
2553                if (isset($data['isBlanks'])) {
2554                    if ($data['isBlanks']) {
2555                        $conj = 'OR';
2556                        if ($whereDates == '') {
2557                            $conj = '';
2558                        }
2559                        $whereBlanks .= " {$conj} {$field} IS NULL ";
2560                    } else {
2561                        $conj = 'AND';
2562                        if ($whereDates == '') {
2563                            $conj = '';
2564                        }
2565                        $whereBlanks .= " {$conj} {$field} IS NOT NULL ";
2566                    }
2567                }
2568
2569                $where .= " AND ({$whereDates} {$whereBlanks} {$whereDataUptoToday}";
2570            } else {
2571                if ($data['filterType'] == 'number') {
2572                    if (array_key_exists('operator', $data)) {
2573                        if ($data['condition1']['type'] != 'blank' && $data['condition2']['type'] != 'notBlank') {
2574                            $data['condition1']['filter'] = addslashes($data['condition1']['filter']);
2575                            $data['condition2']['filter'] = addslashes($data['condition2']['filter']);
2576
2577                            if ($data['condition1']['type'] == 'inRange') {
2578                                $data['condition1']['filterTo'] = addslashes($data['condition1']['filterTo']);
2579                                $inRange = str_replace('[value1]', $data['condition1']['filter'], $filterType['inRange']);
2580                                $val1 = str_replace('[value2]', $data['condition1']['filterTo'], $inRange);
2581                            } else {
2582                                $val1 = str_replace('[value]', $data['condition1']['filter'], $filterType[$data['condition1']['type']]);
2583                            }
2584
2585                            if ($data['condition2']['type'] == 'inRange') {
2586                                $data['condition2']['filterTo'] = addslashes($data['condition2']['filterTo']);
2587                                $inRange = str_replace('[value1]', $data['condition2']['filter'], $filterType['inRange']);
2588                                $val2 = str_replace('[value2]', $data['condition2']['filterTo'], $inRange);
2589                            } else {
2590                                $val2 = str_replace('[value]', $data['condition2']['filter'], $filterType[$data['condition2']['type']]);
2591                            }
2592
2593                        } else {
2594                            $val1 = $filterType[$data['condition1']['type']];
2595                            $val2 = $filterType[$data['condition2']['type']];
2596                        }
2597
2598                        $where .= " AND a.{$key} {$val1} {$data['operator']} a.{$key} {$val2} ";
2599                    } else {
2600                        if ($data['type'] != 'blank' && $data['type'] != 'notBlank') {
2601                            $data['filter'] = addslashes($data['filter']);
2602
2603                            if ($data['type'] == 'inRange') {
2604                                $data['filterTo'] = addslashes($data['filterTo']);
2605                                $inRange = str_replace('[value1]', $data['filter'], $filterType['inRange']);
2606                                $val = str_replace('[value2]', $data['filterTo'], $inRange);
2607                            } else {
2608                                $val = str_replace('[value]', $data['filter'], $filterType[$data['type']]);
2609                            }
2610                        } else {
2611                            $val = $filterType[$data['type']];
2612                        }
2613
2614                        $where .= " AND a.{$key} {$val} ";
2615                    }
2616                }
2617
2618                if ($data['filterType'] == 'text') {
2619                    if ($key == 'id') {
2620                        continue;
2621                    }
2622
2623                    if (array_key_exists('operator', $data)) {
2624                        $val1 = '';
2625                        $val2 = '';
2626                        if ($data['condition1']['type'] != 'blank' && $data['condition2']['type'] != 'notBlank') {
2627                            $data['condition1']['filter'] = addslashes($data['condition1']['filter']);
2628                            $val1 = str_replace('[value]', $data['condition1']['filter'], $filterType[$data['condition1']['type']]);
2629                        }
2630
2631                        if ($data['condition2']['type'] != 'blank' && $data['condition2']['type'] != 'notBlank') {
2632                            $data['condition2']['filter'] = addslashes($data['condition2']['filter']);
2633                            $val2 = str_replace('[value]', $data['condition2']['filter'], $filterType[$data['condition2']['type']]);
2634                        }
2635
2636                        $where .= " AND {$key} {$val1} {$data['operator']} {$key} {$val2} ";
2637                    } else {
2638
2639                        $type = $data['type'];
2640                        $filter = $data['filter'];
2641
2642                        if (($type === 'in' || $type === 'contains') && strpos($filter, ',') !== false) {
2643                            $values = explode(',', $filter);
2644                            $escaped = array_map('addslashes', $values);
2645                            $val = "IN ('".implode("','", $escaped)."')";
2646                        } elseif ($type !== 'blank' && $type !== 'notBlank') {
2647                            $data['filter'] = addslashes($data['filter']);
2648                            $val = str_replace('[value]', $data['filter'], $filterType[$type]);
2649                        } else {
2650                            $val = $filterType[$type];
2651                        }
2652
2653                        $where .= " AND {$key} {$val} ";
2654
2655                    }
2656                }
2657
2658                if ($data['filterType'] == 'set') {
2659                    $statusName = $key;
2660
2661                    if ($key == 'client_type') {
2662                        $statusName = 'c.name';
2663                    } elseif ($key == 'segment') {
2664                        $statusName = 's.name';
2665                    } elseif ($key == 'type') {
2666                        $statusName = 'd.name';
2667                    } elseif ($key == 'status') {
2668                        $statusName = 'e.name';
2669                    } elseif ($key == 'source') {
2670                        $statusName = 'f.name';
2671                    } elseif ($key == 'reason_for_not_following_up') {
2672                        $statusName = 'g.name';
2673                    } elseif ($key == 'reason_for_rejection') {
2674                        $statusName = 'h.name';
2675                    } elseif ($key == 'created_by') {
2676                        $statusName = 'a.created_by';
2677                    } elseif ($key == 'has_attachment') {
2678                        $statusName = 'a.has_attachment';
2679                        if ($data['values']) {
2680                            foreach ($data['values'] as $k => $v) {
2681                                if ($v == 'No') {
2682                                    $data['values'][$k] = 0;
2683                                } else {
2684                                    $data['values'][$k] = 1;
2685                                }
2686                            }
2687                        }
2688                    } elseif ($key == 'for_approval') {
2689                        $statusName = 'a.for_approval';
2690                        if ($data['values']) {
2691                            foreach ($data['values'] as $k => $v) {
2692                                if ($v == 'No') {
2693                                    $data['values'][$k] = 0;
2694                                } else {
2695                                    $data['values'][$k] = 1;
2696                                }
2697                            }
2698                        }
2699                    } elseif ($key == 'sync_import') {
2700                        $statusName = 'a.sync_import';
2701                        if ($data['values']) {
2702                            foreach ($data['values'] as $k => $v) {
2703                                if ($v == 'Manual') {
2704                                    $data['values'][$k] = 0;
2705                                } else {
2706                                    $data['values'][$k] = 1;
2707                                }
2708                            }
2709                        }
2710                    } elseif ($key == 'g3w_warning') {
2711                        $statusName = 'a.g3w_warning';
2712                        if ($data['values']) {
2713                            foreach ($data['values'] as $k => $v) {
2714                                if ($v == 'No') {
2715                                    $data['values'][$k] = 0;
2716                                } else {
2717                                    $data['values'][$k] = 1;
2718                                }
2719                            }
2720                        }
2721                    } elseif ($key == 'company_name') {
2722                        $statusName = 'b.name';
2723                    }
2724
2725                    $val = implode("','", $data['values']);
2726
2727                    if (in_array(null, $data['values'], true)) {
2728                        $where .= " AND ({$statusName} IN ('{$val}') OR {$statusName} IS NULL) ";
2729                    } else {
2730                        $where .= " AND {$statusName} IN ('{$val}') ";
2731                    }
2732                }
2733            }
2734        }
2735
2736        $whereSendToClient = $where;
2737
2738        $offset = $start;
2739        $limit = $end - $start;
2740
2741        $subquery = ",(SELECT can_write FROM tbl_company_users WHERE company_id = a.company_id AND user_id = {$userId}) can_write";
2742
2743        // Quotations accepted without acceptance_date
2744        // Quotations with state "No encontrado" or "Estado no reconocido en FST"
2745        // Quotations with not comercial in out database
2746        // Phone number on null
2747        // Source on null
2748        // Client name on null
2749        // Budget Type on null
2750        if (isset($data['g3w_warning'])) {
2751            $g3w_warning = $data['g3w_warning'] == 'No' ? 0 : 1;
2752            /*$where .= "
2753            AND a.sync_import = 1
2754                AND (
2755                    a.budget_status_id IN (13, 14)
2756                    OR (
2757                        a.commercial IS NULL
2758                        OR NOT EXISTS (
2759                            SELECT 1 FROM tbl_users u WHERE u.name = a.commercial
2760                        )
2761                        OR a.phone_number IS NULL
2762                        OR a.source_id IS NULL
2763                        OR a.budget_type_id IS NULL
2764                        OR (a.client IS NULL OR TRIM(a.client) = '')
2765                        OR (a.email IS NULL OR TRIM(a.email) = '')
2766                    )
2767                )
2768             ";*/
2769            $where .= '
2770                AND (a.sync_import = 1 OR a.sync_import_edited = 1)
2771                AND a.g3w_warning = '.$g3w_warning;
2772        }
2773
2774        if ($isInvalidEmail) {
2775            $blacklist = implode('|', $this->getBlacklistEmails());
2776
2777            $where = "                
2778                AND 
2779                (
2780                    a.x_status IN ('Error','Error - Bounce','Error - Spam')
2781                    OR (
2782                        a.email IS NULL 
2783                        OR TRIM(a.email) = '' 
2784                        OR a.email NOT REGEXP '[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}'
2785                        OR a.email REGEXP '($blacklist)'
2786                    )
2787                ) 
2788                AND a.budget_status_id IN(1, 2, 11, 17, 21)";
2789        }
2790
2791        if ($isFollowUp) {
2792            $blacklist = implode('|', $this->getBlacklistEmails());
2793
2794            $where .= "
2795                AND (
2796                    a.email IS NOT NULL 
2797                    AND TRIM(a.email) != '' 
2798                    AND a.email REGEXP '[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}'
2799                    AND a.email NOT REGEXP '($blacklist)'
2800                )";
2801        }
2802
2803        $query = "SELECT
2804                        a.id,
2805                        a.quote_id,
2806                        a.internal_quote_id,
2807                        a.company_id,
2808                        b.name company_name,
2809                        a.client,
2810                        c.name client_type,
2811                        c.customer_type_id,
2812                        s.name segment,
2813                        s.segment_id,
2814                        a.request_date,
2815                        a.visit_date,
2816                        a.issue_date,
2817                        a.acceptance_date,
2818                        a.internal_quote_id,
2819                        DATE_FORMAT(a.request_date, '%d/%m/%Y') request_date_translate,
2820                        DATE_FORMAT(a.issue_date, '%d/%m/%Y') issue_date_translate,
2821                        DATE_FORMAT(a.acceptance_date, '%d/%m/%Y') acceptance_date_translate,
2822                        DATE_FORMAT(a.last_follow_up_date, '%d/%m/%Y') last_follow_up_date_translate,
2823                        DATE_FORMAT(a.created_at, '%d/%m/%Y') created_at_translate,
2824                        DATE_FORMAT(a.accepted_at, '%d/%m/%Y') accepted_at_translate,
2825                        a.phone_number,
2826                        a.email,
2827                        a.duration,
2828                        a.order_number,
2829                        d.name 'type',
2830                        d.budget_type_id,
2831                        e.name 'status',
2832                        e.budget_status_id,
2833                        f.name as source,
2834                        f.source_id,
2835                        a.amount,
2836                        g.name reason_for_not_following_up,
2837                        a.reason_for_not_following_up_id,
2838                        a.reason_for_rejection_id,
2839                        a.last_follow_up_date,
2840                        a.last_follow_up_comment,
2841                        CASE WHEN a.reason_for_rejection_id IS NULL THEN a.reason_for_rejection ELSE h.name END reason_for_rejection,
2842                        a.commercial,
2843                        a.user_commercial_by_g3w,
2844                        a.user_create_by_g3w,
2845                        a.created_by,
2846                        a.created_at,
2847                        a.updated_by,
2848                        a.updated_at,
2849                        a.total_sent,
2850                        a.has_attachment,
2851                        a.for_approval,
2852                        a.box_work_g3w,
2853                        a.people_assigned_to_the_job,
2854                        a.duration_of_job_in_days,
2855                        a.estimated_cost_of_materials,
2856                        a.budget_margin_enabled,
2857                        a.question_enabled,
2858                        a.cost_of_labor,
2859                        a.total_cost_of_job,
2860                        CASE WHEN a.budget_margin_enabled > 0 THEN a.invoice_margin ELSE NULL END invoice_margin,
2861                        CASE WHEN a.budget_margin_enabled > 0 THEN a.margin_for_the_company ELSE NULL END margin_for_the_company,
2862                        a.margin_on_invoice_per_day_per_worker,
2863                        a.revenue_per_date_per_worked,
2864                        a.commission_cost,
2865                        a.commission_pct,
2866                        a.gross_margin,
2867                        a.labor_percentage,
2868                        a.question_ids,
2869                        a.question_ids_no,
2870                        a.approved_at,
2871                        a.approved_by,
2872                        a.rejected_at,
2873                        a.rejected_by,
2874                        a.approved_at_v2,
2875                        a.approved_by_v2,
2876                        a.rejected_at_v2,
2877                        a.rejected_by_v2,
2878                        a.accepted_at,
2879                        a.accepted_by,
2880                        a.is_validated,
2881                        a.resource_id,
2882                        a.x_status,
2883                        a.likehood,
2884                        a.sync_import,
2885                        a.sync_import_edited,
2886                        a.g3w_warning,
2887                        a.g3w_warning_fields,
2888                        a.id_solicitud_duplicity,
2889                        SUBSTRING_INDEX(a.email, '@', -1) domain
2890                        {$matchScoreCol}
2891                        {$subquery}
2892                    FROM
2893                        tbl_quotations a
2894                        LEFT JOIN tbl_companies b ON a.company_id = b.company_id
2895                        LEFT JOIN tbl_customer_types c ON a.customer_type_id = c.customer_type_id
2896                        LEFT JOIN tbl_segments s ON a.segment_id = s.segment_id
2897                        LEFT JOIN tbl_budget_types d ON a.budget_type_id = d.budget_type_id
2898                        LEFT JOIN tbl_budget_status e ON a.budget_status_id = e.budget_status_id
2899                        LEFT JOIN tbl_sources f ON a.source_id = f.source_id
2900                        LEFT JOIN tbl_reason_for_not_following_up g ON a.reason_for_not_following_up_id = g.reason_for_not_following_up_id
2901                        LEFT JOIN tbl_reason_for_rejection h ON a.reason_for_rejection_id = h.reason_for_rejection_id
2902                        {$lasLeftJoin}
2903                    WHERE a.for_add = 0 {$where} {$whereBlocked}
2904                    GROUP BY a.id
2905                    {$orderBy}
2906                    LIMIT {$offset}{$limit}
2907                    ";
2908        // return $query;
2909        $value = Cache::get(base64_encode($query));
2910
2911        if (! $value) {
2912            $result = DB::select($query);
2913
2914            Cache::put(base64_encode($query), $result, 600);
2915        } else {
2916            $result = $value;
2917        }
2918
2919        $totalQuery = "SELECT
2920                            COUNT(a.id) totalRowCount,
2921                            SUM(CAST(a.amount AS DECIMAL(10,2))) totalAmount
2922                        FROM
2923                            tbl_quotations a
2924                            LEFT JOIN tbl_companies b ON a.company_id = b.company_id
2925                            LEFT JOIN tbl_customer_types c ON a.customer_type_id = c.customer_type_id
2926                            LEFT JOIN tbl_segments s ON a.segment_id = s.segment_id
2927                            LEFT JOIN tbl_budget_types d ON a.budget_type_id = d.budget_type_id
2928                            LEFT JOIN tbl_budget_status e ON a.budget_status_id = e.budget_status_id
2929                            LEFT JOIN tbl_sources f ON a.source_id = f.source_id
2930                            LEFT JOIN tbl_reason_for_not_following_up g ON a.reason_for_not_following_up_id = g.reason_for_not_following_up_id
2931                            LEFT JOIN tbl_reason_for_rejection h ON a.reason_for_rejection_id = h.reason_for_rejection_id
2932                            {$lasLeftJoin}
2933                        WHERE a.for_add = 0
2934                        {$where} {$whereBlocked}";
2935
2936        $value = Cache::get(base64_encode($totalQuery));
2937
2938        if (! $value) {
2939            $countQuery = DB::select($totalQuery);
2940
2941            Cache::put(base64_encode($totalQuery), $countQuery, 600);
2942        } else {
2943            $countQuery = $value;
2944        }
2945
2946        $totalToFollowUpQuery = "SELECT
2947                                        COUNT(DISTINCT a.id) totalRowCount
2948                                    FROM
2949                                        tbl_quotations a
2950                                    LEFT JOIN tbl_companies b ON a.company_id = b.company_id
2951                                    LEFT JOIN tbl_customer_types c ON a.customer_type_id = c.customer_type_id
2952                                    LEFT JOIN tbl_segments s ON a.segment_id = s.segment_id
2953                                    LEFT JOIN tbl_budget_types d ON a.budget_type_id = d.budget_type_id
2954                                    LEFT JOIN tbl_budget_status e ON a.budget_status_id = e.budget_status_id
2955                                    LEFT JOIN tbl_sources f ON a.source_id = f.source_id
2956                                    LEFT JOIN tbl_reason_for_not_following_up g ON a.reason_for_not_following_up_id = g.reason_for_not_following_up_id
2957                                    LEFT JOIN tbl_reason_for_rejection h ON a.reason_for_rejection_id = h.reason_for_rejection_id
2958                                    LEFT JOIN (
2959                                        SELECT
2960                                        a.id,
2961                                        SUBSTRING_INDEX(
2962                                            SUBSTRING_INDEX(a.email, ',', n.digit + 1),
2963                                            ',',
2964                                            -1
2965                                        ) AS email_domain
2966                                        FROM
2967                                        tbl_quotations a
2968                                        INNER JOIN (
2969                                            SELECT
2970                                            0 AS digit
2971                                            UNION ALL
2972                                            SELECT
2973                                            1
2974                                            UNION ALL
2975                                            SELECT
2976                                            2
2977                                            UNION ALL
2978                                            SELECT
2979                                            3
2980                                            UNION ALL
2981                                            SELECT
2982                                            4
2983                                            UNION ALL
2984                                            SELECT
2985                                            5
2986                                            UNION ALL
2987                                            SELECT
2988                                            6
2989                                            UNION ALL
2990                                            SELECT
2991                                            7
2992                                            UNION ALL
2993                                            SELECT
2994                                            8
2995                                            UNION ALL
2996                                            SELECT
2997                                            9
2998                                        ) n ON LENGTH(
2999                                            REPLACE(a.email, ',', '')
3000                                        ) <= LENGTH(a.email)- n.digit
3001                                        GROUP BY a.id
3002                                    ) temp ON a.id = temp.id
3003                                    WHERE
3004                                    a.last_follow_up_date < NOW()
3005                                    AND a.budget_status_id IN (2)
3006                                    AND a.email IS NOT NULL
3007                                    AND a.email <> ''
3008                                    AND NOT EXISTS (
3009                                        SELECT
3010                                        1
3011                                        FROM
3012                                        tbl_blocked_domains bd
3013                                        WHERE
3014                                        temp.email_domain LIKE CONCAT('%', bd.domain, '%')
3015                                        AND bd.company_id = a.company_id
3016                                    )
3017                                    AND a.last_follow_up_date IS NOT NULL
3018                                    AND a.reason_for_not_following_up_id IS NULL
3019                                    AND a.last_follow_up_date > 0
3020                                    AND a.total_sent < b.limit_reminder_emails
3021                                    AND a.for_add = 0
3022                                    {$where}";
3023
3024        $value = Cache::get(base64_encode($totalToFollowUpQuery));
3025
3026        if (! $value) {
3027            $countToFollowUpQuery = DB::select($totalToFollowUpQuery);
3028
3029            Cache::put(base64_encode($totalToFollowUpQuery), $countToFollowUpQuery, 600);
3030        } else {
3031            $countToFollowUpQuery = $value;
3032        }
3033
3034        $query = "SELECT
3035                            COUNT(1) as count,
3036                            SUM(a.amount) as total_amount
3037                        FROM tbl_quotations a
3038                        LEFT JOIN tbl_companies b ON a.company_id = b.company_id
3039                        LEFT JOIN tbl_customer_types c ON a.customer_type_id = c.customer_type_id
3040                        LEFT JOIN tbl_segments s ON a.segment_id = s.segment_id
3041                        LEFT JOIN tbl_budget_types d ON a.budget_type_id = d.budget_type_id
3042                        LEFT JOIN tbl_budget_status e ON a.budget_status_id = e.budget_status_id
3043                        LEFT JOIN tbl_sources f ON a.source_id = f.source_id
3044                        LEFT JOIN tbl_reason_for_not_following_up g ON a.reason_for_not_following_up_id = g.reason_for_not_following_up_id
3045                        LEFT JOIN tbl_reason_for_rejection h ON a.reason_for_rejection_id = h.reason_for_rejection_id
3046                        WHERE a.budget_status_id = 11
3047                        AND a.email IS NOT NULL
3048                        {$whereSendToClient}
3049                        ";
3050
3051        $value = Cache::get(base64_encode($query));
3052
3053        if (! $value) {
3054            $totalSendToClient = DB::select($query);
3055
3056            Cache::put(base64_encode($query), $totalSendToClient, 600);
3057        } else {
3058            $totalSendToClient = $value;
3059        }
3060
3061        return response([
3062            'message' => 'OK',
3063            'data' => $result,
3064            'totalAmount' => $countQuery[0]->totalAmount,
3065            'totalRowCount' => $countQuery[0]->totalRowCount,
3066            'totalToFollowUpRowCount' => $countToFollowUpQuery[0]->totalRowCount,
3067            'totalSendToClient' => $totalSendToClient[0]->count,
3068            'totalSendToClientAmount' => $totalSendToClient[0]->total_amount,
3069        ]);
3070
3071        // } catch (\Exception $e) {
3072        //     return response(['message' => 'KO', 'error' => $e->getMessage()]);
3073        // }
3074
3075    }
3076
3077    public function get_dates(Request $request)
3078    {
3079
3080        try {
3081
3082            $data = $request->all();
3083            $companyId = intval($data['company_id']);
3084
3085            $where = '';
3086            if ($companyId != 0) {
3087                $where = " AND a.company_id = {$companyId} ";
3088            } else {
3089                $where = " AND a.company_id IN ({$this->companyId})";
3090            }
3091
3092            $query = "SELECT
3093                        DATE_FORMAT(a.request_date, '%d/%m/%Y') request_date_translate,
3094                        DATE_FORMAT(a.issue_date, '%d/%m/%Y') issue_date_translate,
3095                        DATE_FORMAT(a.acceptance_date, '%d/%m/%Y') acceptance_date_translate,
3096                        DATE_FORMAT(a.last_follow_up_date, '%d/%m/%Y') last_follow_up_date_translate,
3097                        DATE_FORMAT(a.created_at, '%d/%m/%Y') created_at_translate,
3098                        DATE_FORMAT(a.accepted_at, '%d/%m/%Y') accepted_at_translate
3099                    FROM tbl_quotations a
3100                    WHERE a.for_add = 0 {$where}";
3101
3102            $result = DB::select($query);
3103
3104            return response([
3105                'message' => 'OK',
3106                'data' => $result,
3107            ]);
3108
3109        } catch (\Exception $e) {
3110            /** @disregard P1014 */
3111            $e->exceptionCode = 'GET_DATES_EXCEPTION';
3112            report($e);
3113
3114            return response(['message' => 'KO', 'error' => $e->getMessage()]);
3115        }
3116
3117    }
3118
3119    public function list_quotation_analytics_by_source(Request $request)
3120    {
3121
3122        try {
3123
3124            $data = $request->all();
3125            $companyId = intval($data['company_id']);
3126
3127            $where = '';
3128            $whereYear = '';
3129
3130            $dateLflArray = [];
3131            $companyIds = $this->companyIds;
3132
3133            if ($companyId != 0) {
3134                $companyIds = [$companyId];
3135            }
3136
3137            $field = 'issue_date';
3138
3139            if (isset($data['years']) && $data['years'] != null) {
3140
3141                if (count($data['years']) > 0) {
3142                    foreach ($data['years'] as $year) {
3143                        if (isset($data['week']) && $data['week'] != null) {
3144                            $w = sprintf('%02d', $data['week']);
3145                            $whereYear .= " AND YEARWEEK(q.issue_date, 1) = '{$year}{$w}'";
3146                        } else {
3147                            $whereYear .= " AND YEAR(q.issue_date) = {$year}";
3148                        }
3149                    }
3150                }
3151            }
3152
3153            foreach ($companyIds as $v) {
3154
3155                $lflWhere = " AND q.company_id = {$v} ";
3156
3157                $query = "SELECT
3158                            CONCAT(
3159                                DATE_FORMAT((SELECT MIN(q.{$field}) FROM tbl_quotations q WHERE q.{$field} IS NOT NULL {$lflWhere}), '%c/%e/'), YEAR({$field}),
3160                                ' - ',
3161                                DATE_FORMAT((SELECT MAX(q.{$field}) FROM tbl_quotations q WHERE q.{$field} IS NOT NULL {$lflWhere}), '%c/%e/'), YEAR({$field})
3162                            ) AS date_like,
3163                            YEAR(q.{$field}) 'year',
3164                            DATE_FORMAT((SELECT MIN(q.{$field}) FROM tbl_quotations q WHERE q.{$field} IS NOT NULL {$lflWhere}), '%m-%d') AS min_date_like,
3165                            DATE_FORMAT((SELECT MAX(q.{$field}) FROM tbl_quotations q WHERE q.{$field} IS NOT NULL {$lflWhere}), '%m-%d') AS max_date_like,
3166                            {$v} 'company_id'
3167                        FROM
3168                            tbl_quotations q
3169                        WHERE
3170                            q.{$field} IS NOT NULL
3171                            AND q.for_add = 0
3172                            {$lflWhere}
3173                            {$whereYear}
3174                        GROUP BY YEAR(q.{$field})
3175                        ORDER BY YEAR(q.{$field}) DESC";
3176
3177                $dateLike = DB::select($query);
3178
3179                $dateLflArray[$v] = $dateLike;
3180            }
3181
3182            $whereAcceptanceDate = 'q.acceptance_date IS NOT NULL ';
3183
3184            $isFy = true;
3185
3186            if (isset($data['issue_year_ytd']) && $data['issue_year_ytd'] != null && $data['issue_year_ytd'] == true) {
3187                $isFy = false;
3188                $ytdArray = [];
3189                $ytdAcceptanceArray = [];
3190                $lflCompanyIds = [];
3191                $lflCompanyIdsAcc = [];
3192                foreach ($dateLflArray as $k => $v) {
3193                    foreach ($dateLflArray[$k] as $item) {
3194                        $year = $item->year;
3195                        $now = date('m-d');
3196                        array_push($ytdAcceptanceArray, "DATE_FORMAT(q.acceptance_date, '%Y-%m-%d') BETWEEN '{$year}-01-01' AND '{$year}-{$now}' AND YEAR(q.acceptance_date) = YEAR(issue_date)");
3197                        array_push($ytdArray, "DATE_FORMAT(q.{$field}, '%Y-%m-%d') BETWEEN '{$year}-01-01' AND '{$year}-{$now}'");
3198                    }
3199
3200                    $ytdArray = implode(' OR ', $ytdArray);
3201                    array_push($lflCompanyIds, "q.company_id = {$k} AND ({$ytdArray})");
3202                    $ytdArray = [];
3203
3204                    $ytdAcceptanceArray = implode(' OR ', $ytdAcceptanceArray);
3205                    array_push($lflCompanyIdsAcc, "q.company_id = {$k} AND ({$ytdAcceptanceArray})");
3206                    $ytdAcceptanceArray = [];
3207                }
3208
3209                $lflCompanyIds = implode(' OR ', $lflCompanyIds);
3210                $where .= " AND ({$lflCompanyIds}";
3211
3212                $lflCompanyIdsAcc = implode(' OR ', $lflCompanyIdsAcc);
3213                $whereAcceptanceDate .= " AND ({$lflCompanyIdsAcc}";
3214            }
3215
3216            if (isset($data['issue_year_lfl']) && $data['issue_year_lfl'] != null && $data['issue_year_lfl'] == true) {
3217                $isFy = false;
3218                $lflArray = [];
3219                $ytdAcceptanceArray = [];
3220                $lflCompanyIds = [];
3221                $lflCompanyIdsAcc = [];
3222                foreach ($dateLflArray as $k => $v) {
3223                    foreach ($dateLflArray[$k] as $item) {
3224                        $year = $item->year;
3225                        $min_date_like = $item->min_date_like;
3226                        $max_date_like = $item->max_date_like;
3227                        array_push($ytdAcceptanceArray, "DATE_FORMAT(q.acceptance_date, '%Y-%m-%d') BETWEEN LEAST('{$year}-{$min_date_like}', '{$year}-{$max_date_like}') AND GREATEST('{$year}-{$min_date_like}', '{$year}-{$max_date_like}') AND YEAR(q.acceptance_date) = YEAR(issue_date)");
3228                        array_push($lflArray, "DATE_FORMAT(q.{$field}, '%Y-%m-%d') BETWEEN LEAST('{$year}-{$min_date_like}', '{$year}-{$max_date_like}') AND GREATEST('{$year}-{$min_date_like}', '{$year}-{$max_date_like}')");
3229                    }
3230
3231                    $lflArray = implode(' OR ', $lflArray);
3232                    array_push($lflCompanyIds, "q.company_id = {$k} AND ({$lflArray})");
3233                    $lflArray = [];
3234
3235                    $ytdAcceptanceArray = implode(' OR ', $ytdAcceptanceArray);
3236                    array_push($lflCompanyIdsAcc, "q.company_id = {$k} AND ({$ytdAcceptanceArray})");
3237                    $ytdAcceptanceArray = [];
3238                }
3239
3240                $lflCompanyIds = implode(' OR ', $lflCompanyIds);
3241                $where .= " AND ({$lflCompanyIds}";
3242
3243                $lflCompanyIdsAcc = implode(' OR ', $lflCompanyIdsAcc);
3244                $whereAcceptanceDate .= " AND ({$lflCompanyIdsAcc}";
3245            }
3246
3247            if ($isFy) {
3248                if ($companyId != 0) {
3249                    $where .= " AND q.company_id = {$companyId} ";
3250                } else {
3251                    $where .= " AND q.company_id IN ({$this->companyId})";
3252                }
3253            }
3254
3255            if (isset($data['source']) && $data['source'] != null) {
3256                $where .= " AND s.name = '{$data['source']}'";
3257            }
3258
3259            if (isset($data['month']) && $data['month'] != null) {
3260                $where .= " AND MONTH(q.issue_date) = '{$data['month']}'";
3261            }
3262
3263            if (isset($data['commercial']) && $data['commercial'] != null) {
3264                $where .= " AND q.commercial = '{$data['commercial']}'";
3265            }
3266
3267            if (isset($data['created_by']) && $data['created_by'] != null) {
3268                $where .= " AND q.created_by = '{$data['created_by']}'";
3269            }
3270
3271            if (isset($data['budget_type']) && $data['budget_type'] != null) {
3272                $where .= " AND bt.budget_type_id = {$data['budget_type']}";
3273            }
3274
3275            if (isset($data['budget_type_group']) && $data['budget_type_group'] != null) {
3276                $where .= " AND bt.budget_type_group_id = {$data['budget_type_group']}";
3277            }
3278
3279            if (isset($data['budget_status']) && $data['budget_status'] != null) {
3280                $where .= " AND bs.budget_status_id = {$data['budget_status']}";
3281            }
3282
3283            if (isset($data['client_type']) && $data['client_type'] != null) {
3284                $where .= " AND ct.customer_type_id = {$data['client_type']}";
3285            }
3286
3287            if (isset($data['segment_id']) && $data['segment_id'] != null) {
3288                $where .= " AND q.segment_id = {$data['segment_id']}";
3289            }
3290
3291            $query = "SELECT
3292                        YEAR(DATE_ADD(q.issue_date, INTERVAL - WEEKDAY(q.issue_date) DAY)) AS 'year',
3293                        LPAD(MONTH(DATE_ADD(q.issue_date, INTERVAL - WEEKDAY(q.issue_date) DAY)), 2, 0) AS 'month',
3294                        LPAD(WEEK(DATE_ADD(q.issue_date, INTERVAL - WEEKDAY(q.issue_date) DAY)), 2, 0) AS 'week',
3295                        DATE_FORMAT(DATE_ADD(q.issue_date, INTERVAL - WEEKDAY(q.issue_date) DAY), '%W, %M %e') issue_date,
3296                        COUNT(
3297                            CASE WHEN q.issue_date IS NOT NULL
3298                            THEN 1 END
3299                        ) AS totalIssue,
3300                        GROUP_CONCAT(
3301                            CASE WHEN q.issue_date IS NOT NULL
3302                            THEN q.id END
3303                        ) AS groupConcatIds,
3304                        SUM(
3305                            CASE WHEN q.issue_date IS NOT NULL THEN q.amount END
3306                        ) AS revenueIssue,
3307                        COUNT(
3308                            CASE WHEN {$whereAcceptanceDate} AND bs.name = 'Aceptado' THEN 1 END
3309                        ) AS totalAcceptance,
3310                        SUM(
3311                            CASE WHEN {$whereAcceptanceDate} AND bs.name = 'Aceptado' THEN q.amount END
3312                        ) AS revenueAcceptance,
3313                        SUM(
3314                            CASE WHEN {$whereAcceptanceDate} AND bs.name = 'Aceptado' THEN q.amount END
3315                        ) / SUM(
3316                            CASE WHEN q.issue_date IS NOT NULL THEN q.amount END
3317                        ) * 100 AS revenueAcceptanceIssuedPercentage,
3318                        COUNT(
3319                            CASE WHEN bs.name = 'Rechazado' THEN 1 END
3320                        ) AS totalRejected,
3321                        SUM(
3322                            CASE WHEN bs.name = 'Rechazado' THEN q.amount END
3323                        ) AS revenueRejected,
3324                        COUNT(
3325                            CASE WHEN bs.name = 'Rechazado - automaticamente' THEN 1 END
3326                        ) AS totalRejectedAutomatic,
3327                        SUM(
3328                            CASE WHEN bs.name = 'Rechazado - automaticamente' THEN q.amount END
3329                        ) AS revenueRejectedAutomatic
3330                    FROM
3331                        tbl_quotations q
3332                        LEFT JOIN tbl_sources s ON s.source_id = q.source_id
3333                        LEFT JOIN tbl_budget_status bs ON bs.budget_status_id = q.budget_status_id
3334                        LEFT JOIN tbl_budget_types bt ON q.budget_type_id = bt.budget_type_id
3335                        LEFT JOIN tbl_customer_types ct ON q.customer_type_id = ct.customer_type_id
3336                    WHERE
3337                        q.issue_date IS NOT NULL
3338                        AND q.budget_type_id != 7
3339                        AND q.budget_type_id IS NOT NULL
3340                        AND q.for_add = 0
3341                        AND q.amount REGEXP '^[0-9]+\\.?[0-9]*$' = 1
3342                        {$where}
3343                        {$whereYear}                        
3344                    GROUP BY
3345                        YEAR(DATE_ADD(q.issue_date, INTERVAL - WEEKDAY(q.issue_date) DAY)),
3346                        MONTH(DATE_ADD(q.issue_date, INTERVAL - WEEKDAY(q.issue_date) DAY)),
3347                        WEEK(DATE_ADD(q.issue_date, INTERVAL - WEEKDAY(q.issue_date) DAY)) WITH ROLLUP
3348                    ORDER BY
3349                        YEAR DESC,
3350                        MONTH ASC,
3351                        WEEK ASC,
3352                        DATE_FORMAT(q.issue_date, '%e') ASC";
3353            // return $query;
3354            $value = Cache::get(base64_encode($query));
3355
3356            if (! $value) {
3357                $result = DB::select($query);
3358
3359                Cache::put(base64_encode($query), $result, 600);
3360            } else {
3361                $result = $value;
3362            }
3363
3364            return response([
3365                'message' => 'OK',
3366                'data' => $result,
3367            ]);
3368
3369        } catch (\Exception $e) {
3370            /** @disregard P1014 */
3371            $e->exceptionCode = 'LIST_QUOTATION_ANALYTICS_BY_SOURCE_EXCEPTION';
3372            report($e);
3373
3374            return response(['message' => 'KO', 'error' => $e->getMessage()]);
3375        }
3376    }
3377
3378    public function list_quotation_analytics_send_budgets(Request $request)
3379    {
3380
3381        try {
3382
3383            $data = $request->all();
3384            $companyId = intval($data['company_id']);
3385
3386            $where = '';
3387            $whereYear = '';
3388
3389            if ($companyId != 0) {
3390                $where = " AND q.company_id = {$companyId} ";
3391            } else {
3392                $where = " AND q.company_id IN ({$this->companyId}";
3393            }
3394
3395            if (isset($data['budget_type_group']) && $data['budget_type_group'] != null) {
3396                $where .= " AND bt.budget_type_group_id = {$data['budget_type_group']}";
3397            }
3398
3399            if (isset($data['budget_status']) && $data['budget_status'] != null) {
3400                $where .= " AND bs.budget_status_id = {$data['budget_status']}";
3401            }
3402
3403            if (isset($data['years']) && $data['years'] != null) {
3404                $years = implode(',', $data['years']);
3405                if (count($data['years']) > 0) {
3406                    $whereYear = " AND YEAR(q.issue_date) IN ({$years})";
3407                }
3408            }
3409
3410            $query = "SELECT
3411                            YEAR(q.issue_date) AS 'year',
3412                            MONTH(q.issue_date) AS 'month',
3413                            SUM(
3414                                CASE WHEN MONTH(request_date) = MONTH(issue_date) THEN 1 ELSE 0 END
3415                            ) totalRequest,
3416                            COUNT(
3417                                CASE WHEN q.issue_date IS NOT NULL THEN 1 END
3418                            ) AS totalIssue,
3419                            GROUP_CONCAT(
3420                                CASE WHEN q.issue_date IS NOT NULL
3421                                THEN q.id END
3422                            ) AS groupConcatIds,
3423                            SUM(
3424                                CASE WHEN MONTH(request_date) = MONTH(issue_date) THEN 1 ELSE 0 END
3425                            ) /
3426                            COUNT(
3427                                CASE WHEN q.issue_date IS NOT NULL THEN 1 END
3428                            ) * 100 issuePercentage,
3429                            AVG(
3430                                COALESCE(q.duration, 0)
3431                            ) AS averageDurationIssue,
3432                            COALESCE(
3433                                AVG(
3434                                    CASE WHEN bt.name = 'Mantenimiento' THEN COALESCE(q.duration, 0) ELSE NULL END
3435                                ), 0
3436                            ) AS averageDurationMaintenance,
3437                            COALESCE(
3438                                AVG(
3439                                    CASE WHEN bt.name = 'Nuevos' THEN COALESCE(q.duration, 0) ELSE NULL END
3440                                ), 0
3441                            ) AS averageDurationNew,
3442                            COALESCE(
3443                                AVG(
3444                                    CASE WHEN bt.name = 'Correctivos' THEN COALESCE(q.duration, 0) ELSE NULL END
3445                                ), 0
3446                            ) AS averageDurationCorretive,
3447                            COALESCE(
3448                                AVG(
3449                                    CASE WHEN bt.name = 'Anomalías' THEN COALESCE(q.duration, 0) ELSE NULL END
3450                                ), 0
3451                            ) AS averageDurationAnomalies,
3452                            COALESCE(
3453                                AVG(
3454                                    CASE WHEN bt.name = 'Precios Unitarios' THEN COALESCE(q.duration, 0) ELSE NULL END
3455                                ), 0
3456                            ) AS averageDurationUnitPrice,
3457                            COALESCE(
3458                                AVG(
3459                                    CASE WHEN bt.name = 'Instalaciones' THEN COALESCE(q.duration, 0) ELSE NULL END
3460                                ), 0
3461                            ) AS averageDurationFacilities,
3462                            COALESCE(
3463                                AVG(
3464                                    CASE WHEN bt.name = 'Alquiler' THEN COALESCE(q.duration, 0) ELSE NULL END
3465                                ), 0
3466                            ) AS averageDurationRent,
3467                            COALESCE(
3468                                AVG(
3469                                    CASE WHEN bt.name = 'OCA visita' THEN COALESCE(q.duration, 0) ELSE NULL END
3470                                ), 0
3471                            ) AS averageDurationOCA,
3472                            COALESCE(
3473                                AVG(
3474                                    CASE WHEN bt.name = 'Retirada y gestion de residuos' THEN COALESCE(q.duration, 0) ELSE NULL END
3475                                ), 0
3476                            ) AS averageDurationWRM,
3477                            COALESCE(
3478                                AVG(
3479                                    CASE WHEN bt.name = 'Formación' THEN COALESCE(q.duration, 0) ELSE NULL END
3480                                ), 0
3481                            ) AS averageDurationTraining,
3482                            COALESCE(
3483                                AVG(
3484                                    CASE WHEN bt.name = 'Anomalías de facilities' THEN COALESCE(q.duration, 0) ELSE NULL END
3485                                ), 0
3486                            ) AS averageDurationFacilityAnomalies
3487                        FROM
3488                            tbl_quotations q
3489                            LEFT JOIN tbl_budget_types bt ON q.budget_type_id = bt.budget_type_id
3490                            LEFT JOIN tbl_budget_type_groups btg ON bt.budget_type_id = btg.budget_type_id
3491                        WHERE
3492                            q.issue_date IS NOT NULL
3493                            AND q.budget_type_id != 7
3494                            AND q.budget_type_id IS NOT NULL
3495                            AND q.for_add = 0
3496                            AND q.amount REGEXP '^[0-9]+\\.?[0-9]*$' = 1
3497                            {$where}
3498                            {$whereYear}
3499                        GROUP BY
3500                            YEAR(q.issue_date),
3501                            MONTH(q.issue_date) WITH ROLLUP
3502                        ORDER BY
3503                            YEAR(q.issue_date) DESC,
3504                            MONTH(q.issue_date) ASC";
3505
3506            $sendBudgets = [];
3507            $sendBudgetsTotals = [];
3508
3509            $value = Cache::get(base64_encode($query));
3510
3511            if (! $value) {
3512                $result = DB::select($query);
3513
3514                Cache::put(base64_encode($query), $result, 600);
3515            } else {
3516                $result = $value;
3517            }
3518
3519            if (count($result) > 0) {
3520                for ($i = 0; $i < count($result); $i++) {
3521
3522                    if ($result[$i]->year == null && $result[$i]->month == null) {
3523                        $result[$i]->month = 'totalGeneral';
3524                        $sendBudgetsTotals['totalGeneral'] = $result[$i];
3525
3526                        continue;
3527                    } elseif ($result[$i]->month == null && $result[$i]->year != null) {
3528                        if (count($data['years']) > 0 || $whereYear == '') {
3529                            $result[$i]->month = 'totalSub';
3530                        } else {
3531                            continue;
3532                        }
3533                    } else {
3534                        $result[$i]->month = sprintf('%02d', $result[$i]->month);
3535                    }
3536
3537                    $sendBudgets[$result[$i]->year][$result[$i]->month] = $result[$i];
3538                }
3539            }
3540
3541            return response([
3542                'message' => 'OK',
3543                'data' => $sendBudgets,
3544                'totals' => $sendBudgetsTotals,
3545            ]);
3546
3547        } catch (\Exception $e) {
3548            /** @disregard P1014 */
3549            $e->exceptionCode = 'LIST_QUOTATION_ANALYTICS_EXCEPTION';
3550            report($e);
3551
3552            return response(['message' => 'KO', 'error' => $e->getMessage()]);
3553        }
3554    }
3555
3556    public function list_quotation_analytics_track_budgets(Request $request)
3557    {
3558
3559        try {
3560
3561            $data = $request->all();
3562            $companyId = intval($data['company_id']);
3563
3564            $where = '';
3565            $whereYear = '';
3566            $isBetween = false;
3567
3568            $dateLflArray = [];
3569            $companyIds = $this->companyIds;
3570
3571            if ($companyId != 0) {
3572                $companyIds = [$companyId];
3573            }
3574
3575            if (isset($data['years']) && $data['years'] != null) {
3576                $years = implode(',', $data['years']);
3577                if (count($data['years']) > 0) {
3578                    $whereYear = " AND YEAR(q.issue_date) IN ({$years})";
3579                }
3580            }
3581
3582            $field = 'issue_date';
3583
3584            foreach ($companyIds as $v) {
3585
3586                $lflWhere = " AND q.company_id = {$v} ";
3587
3588                $query = "SELECT
3589                            CONCAT(
3590                                DATE_FORMAT((SELECT MIN(q.{$field}) FROM tbl_quotations q WHERE q.{$field} IS NOT NULL {$lflWhere}), '%c/%e/'), YEAR({$field}),
3591                                ' - ',
3592                                DATE_FORMAT((SELECT MAX(q.{$field}) FROM tbl_quotations q WHERE q.{$field} IS NOT NULL {$lflWhere}), '%c/%e/'), YEAR({$field})
3593                            ) AS date_like,
3594                            YEAR(q.{$field}) 'year',
3595                            DATE_FORMAT((SELECT MIN(q.{$field}) FROM tbl_quotations q WHERE q.{$field} IS NOT NULL {$lflWhere}), '%m-%d') AS min_date_like,
3596                            DATE_FORMAT((SELECT MAX(q.{$field}) FROM tbl_quotations q WHERE q.{$field} IS NOT NULL {$lflWhere}), '%m-%d') AS max_date_like,
3597                            {$v} 'company_id'
3598                        FROM
3599                            tbl_quotations q
3600                        WHERE
3601                            q.{$field} IS NOT NULL
3602                            AND q.for_add = 0
3603                            {$lflWhere}
3604                            {$whereYear}
3605                        GROUP BY YEAR(q.{$field})
3606                        ORDER BY YEAR(q.{$field}) DESC";
3607
3608                $dateLike = DB::select($query);
3609
3610                $dateLflArray[$v] = $dateLike;
3611            }
3612
3613            $whereAcceptanceDate = 'q.acceptance_date IS NOT NULL ';
3614
3615            $isFy = true;
3616
3617            if (isset($data['issue_year_ytd']) && $data['issue_year_ytd'] != null && $data['issue_year_ytd'] == true) {
3618                $isFy = false;
3619                $ytdArray = [];
3620                $ytdAcceptanceArray = [];
3621                $lflCompanyIds = [];
3622                $lflCompanyIdsAcc = [];
3623                foreach ($dateLflArray as $k => $v) {
3624                    foreach ($dateLflArray[$k] as $item) {
3625                        $year = $item->year;
3626                        $now = date('m-d');
3627                        array_push($ytdAcceptanceArray, "DATE_FORMAT(q.acceptance_date, '%Y-%m-%d') BETWEEN '{$year}-01-01' AND '{$year}-{$now}' AND YEAR(q.acceptance_date) = YEAR(issue_date)");
3628                        array_push($ytdArray, "DATE_FORMAT(q.{$field}, '%Y-%m-%d') BETWEEN '{$year}-01-01' AND '{$year}-{$now}'");
3629                    }
3630
3631                    $ytdArray = implode(' OR ', $ytdArray);
3632                    array_push($lflCompanyIds, "q.company_id = {$k} AND ({$ytdArray})");
3633                    $ytdArray = [];
3634
3635                    $ytdAcceptanceArray = implode(' OR ', $ytdAcceptanceArray);
3636                    array_push($lflCompanyIdsAcc, "q.company_id = {$k} AND ({$ytdAcceptanceArray})");
3637                    $ytdAcceptanceArray = [];
3638                }
3639
3640                $lflCompanyIds = implode(' OR ', $lflCompanyIds);
3641                $where .= " AND ({$lflCompanyIds}";
3642
3643                $lflCompanyIdsAcc = implode(' OR ', $lflCompanyIdsAcc);
3644                $whereAcceptanceDate .= " AND ({$lflCompanyIdsAcc}";
3645            }
3646
3647            if (isset($data['issue_year_lfl']) && $data['issue_year_lfl'] != null && $data['issue_year_lfl'] == true) {
3648                $isFy = false;
3649                $lflArray = [];
3650                $ytdAcceptanceArray = [];
3651                $lflCompanyIds = [];
3652                $lflCompanyIdsAcc = [];
3653                foreach ($dateLflArray as $k => $v) {
3654                    foreach ($dateLflArray[$k] as $item) {
3655                        $year = $item->year;
3656                        $min_date_like = $item->min_date_like;
3657                        $max_date_like = $item->max_date_like;
3658                        array_push($ytdAcceptanceArray, "DATE_FORMAT(q.acceptance_date, '%Y-%m-%d') BETWEEN LEAST('{$year}-{$min_date_like}', '{$year}-{$max_date_like}') AND GREATEST('{$year}-{$min_date_like}', '{$year}-{$max_date_like}') AND YEAR(q.acceptance_date) = YEAR(issue_date)");
3659                        array_push($lflArray, "DATE_FORMAT(q.{$field}, '%Y-%m-%d') BETWEEN LEAST('{$year}-{$min_date_like}', '{$year}-{$max_date_like}') AND GREATEST('{$year}-{$min_date_like}', '{$year}-{$max_date_like}')");
3660                    }
3661
3662                    $lflArray = implode(' OR ', $lflArray);
3663                    array_push($lflCompanyIds, "q.company_id = {$k} AND ({$lflArray})");
3664                    $lflArray = [];
3665
3666                    $ytdAcceptanceArray = implode(' OR ', $ytdAcceptanceArray);
3667                    array_push($lflCompanyIdsAcc, "q.company_id = {$k} AND ({$ytdAcceptanceArray})");
3668                    $ytdAcceptanceArray = [];
3669                }
3670
3671                $lflCompanyIds = implode(' OR ', $lflCompanyIds);
3672                $where .= " AND ({$lflCompanyIds}";
3673
3674                $lflCompanyIdsAcc = implode(' OR ', $lflCompanyIdsAcc);
3675                $whereAcceptanceDate .= " AND ({$lflCompanyIdsAcc}";
3676            }
3677
3678            if ($isFy) {
3679                if ($companyId != 0) {
3680                    $where .= " AND q.company_id = {$companyId} ";
3681                } else {
3682                    $where .= " AND q.company_id IN ({$this->companyId})";
3683                }
3684            }
3685
3686            if (isset($data['source']) && $data['source'] != null) {
3687                $where .= " AND s.name = '{$data['source']}'";
3688            }
3689
3690            if (isset($data['commercial']) && $data['commercial'] != null) {
3691                $where .= " AND q.commercial = '{$data['commercial']}'";
3692            }
3693
3694            if (isset($data['created_by']) && $data['created_by'] != null) {
3695                $where .= " AND q.created_by = '{$data['created_by']}'";
3696            }
3697
3698            if (isset($data['budget_type']) && $data['budget_type'] != null) {
3699                $where .= " AND bt.budget_type_id = {$data['budget_type']}";
3700            }
3701
3702            if (isset($data['budget_type_group']) && $data['budget_type_group'] != null) {
3703                $where .= " AND bt.budget_type_group_id = {$data['budget_type_group']}";
3704            }
3705
3706            if (isset($data['budget_status']) && $data['budget_status'] != null) {
3707                $where .= " AND bs.budget_status_id = {$data['budget_status']}";
3708            }
3709
3710            if (isset($data['client_type']) && $data['client_type'] != null) {
3711                $where .= " AND ct.customer_type_id = {$data['client_type']}";
3712            }
3713
3714            if (isset($data['segment_id']) && $data['segment_id'] != null) {
3715                $where .= " AND q.segment_id = {$data['segment_id']}";
3716            }
3717
3718            $query = "SELECT
3719                            YEAR(DATE_ADD(q.issue_date, INTERVAL - WEEKDAY(q.issue_date) DAY)) AS 'year',
3720                            LPAD(MONTH(DATE_ADD(q.issue_date, INTERVAL - WEEKDAY(q.issue_date) DAY)), 2, 0) AS 'month',
3721                            LPAD(WEEK(DATE_ADD(q.issue_date, INTERVAL - WEEKDAY(q.issue_date) DAY)), 2, 0) AS 'week',
3722                            DATE_FORMAT(DATE_ADD(q.issue_date, INTERVAL - WEEKDAY(q.issue_date) DAY), '%W, %M %e') issue_date,
3723                            COUNT(
3724                                CASE WHEN q.issue_date IS NOT NULL
3725                                THEN 1 END
3726                            ) AS totalIssue,
3727                            GROUP_CONCAT(
3728                                CASE WHEN q.issue_date IS NOT NULL
3729                                THEN q.id END
3730                            ) AS groupConcatIds,
3731                            COUNT(
3732                                CASE WHEN {$whereAcceptanceDate}
3733                                AND bs.name = 'Aceptado' THEN 1 END) totalAccept,
3734                            COUNT(
3735                                CASE WHEN q.acceptance_date IS NOT NULL
3736                                AND {$whereAcceptanceDate}
3737                                AND bs.name = 'Aceptado'
3738                                AND DATEDIFF(q.acceptance_date, q.issue_date) <= 10 THEN 1 END
3739                            ) / COUNT(
3740                                CASE WHEN q.issue_date IS NOT NULL
3741                                THEN 1 END
3742                            ) * 100 AS percentageOfacceptanceLessThan10,
3743                            COUNT(
3744                                CASE WHEN q.acceptance_date IS NOT NULL
3745                                AND {$whereAcceptanceDate}
3746                                AND bs.name = 'Aceptado'
3747                                AND DATEDIFF(q.acceptance_date, q.issue_date) > 10
3748                                AND DATEDIFF(q.acceptance_date, q.issue_date) < 30 THEN 1 END
3749                            ) / COUNT(
3750                                CASE WHEN q.issue_date IS NOT NULL
3751                                THEN 1 END
3752                            ) * 100 AS percentageOfacceptanceLessThan30,
3753                            COUNT(
3754                                CASE WHEN q.acceptance_date IS NOT NULL
3755                                AND {$whereAcceptanceDate}
3756                                AND bs.name = 'Aceptado'
3757                                AND DATEDIFF(q.acceptance_date, q.issue_date) >= 30 THEN 1 END
3758                            ) / COUNT(
3759                                CASE WHEN q.issue_date IS NOT NULL
3760                                THEN 1 END
3761                            ) * 100 AS percentageOfacceptanceMoreThan30,
3762                            COUNT(CASE WHEN
3763                                {$whereAcceptanceDate} THEN 1 END
3764                            ) / COUNT(
3765                                CASE WHEN q.issue_date IS NOT NULL
3766                                THEN 1 END
3767                            ) * 100 acceptedPercentage,
3768                            COALESCE(
3769                                AVG(
3770                                    CASE WHEN q.issue_date IS NOT NULL
3771                                    AND q.acceptance_date IS NOT NULL
3772                                    AND {$whereAcceptanceDate}
3773                                    AND bs.name = 'Aceptado'
3774                                    THEN DATEDIFF(q.acceptance_date, q.issue_date) ELSE NULL END
3775                                ), 0
3776                            )
3777                            AS averageAcceptedDuration,
3778                            COALESCE(
3779                                AVG(
3780                                    CASE WHEN q.issue_date IS NOT NULL
3781                                    AND q.request_date IS NOT NULL
3782                                    THEN DATEDIFF(q.issue_date, q.request_date) ELSE NULL END
3783                                ), 0
3784                            )
3785                            AS averageRequestedDays
3786                        FROM
3787                            tbl_quotations q
3788                            LEFT JOIN tbl_budget_types bt ON q.budget_type_id = bt.budget_type_id
3789                            LEFT JOIN tbl_budget_status bs ON bs.budget_status_id = q.budget_status_id
3790                            LEFT JOIN tbl_sources s ON s.source_id = q.source_id
3791                            LEFT JOIN tbl_customer_types ct ON q.customer_type_id = ct.customer_type_id
3792                        WHERE
3793                            q.issue_date IS NOT NULL
3794                            AND q.budget_type_id != 7
3795                            AND q.budget_type_id IS NOT NULL
3796                            AND q.for_add = 0
3797                            AND q.amount REGEXP '^[0-9]+\\.?[0-9]*$' = 1
3798                            {$where}
3799                            {$whereYear}
3800                        GROUP BY
3801                            YEAR(DATE_ADD(q.issue_date, INTERVAL - WEEKDAY(q.issue_date) DAY)),
3802                            MONTH(DATE_ADD(q.issue_date, INTERVAL - WEEKDAY(q.issue_date) DAY)),
3803                            WEEK(DATE_ADD(q.issue_date, INTERVAL - WEEKDAY(q.issue_date) DAY)) WITH ROLLUP
3804                        ORDER BY
3805                            YEAR DESC,
3806                            MONTH ASC,
3807                            WEEK ASC,
3808                            DATE_FORMAT(q.issue_date, '%e') ASC";
3809
3810            $value = Cache::get(base64_encode($query));
3811
3812            if (! $value) {
3813                $result = DB::select($query);
3814
3815                Cache::put(base64_encode($query), $result, 600);
3816            } else {
3817                $result = $value;
3818            }
3819
3820            return response([
3821                'message' => 'OK',
3822                'data' => $result,
3823            ]);
3824
3825        } catch (\Exception $e) {
3826            /** @disregard P1014 */
3827            $e->exceptionCode = 'LIST_QUOTATION_ANALYTICS_TRACK_BUDGETS_EXCEPTION';
3828            report($e);
3829
3830            return response(['message' => 'KO', 'error' => $e->getMessage()]);
3831        }
3832    }
3833
3834    public function list_quotation_analytics_types_budgets(Request $request)
3835    {
3836
3837        try {
3838
3839            $data = $request->all();
3840            $companyId = intval($data['company_id']);
3841
3842            $where = '';
3843            $whereYear = '';
3844            $isBetween = false;
3845
3846            $dateLflArray = [];
3847            $companyIds = $this->companyIds;
3848
3849            if ($companyId != 0) {
3850                $companyIds = [$companyId];
3851            }
3852
3853            if (isset($data['years']) && $data['years'] != null) {
3854                $years = implode(',', $data['years']);
3855                if (count($data['years']) > 0) {
3856                    $whereYear = " AND YEAR(q.issue_date) IN ({$years})";
3857                }
3858            }
3859
3860            $field = 'issue_date';
3861
3862            foreach ($companyIds as $v) {
3863
3864                $lflWhere = " AND q.company_id = {$v} ";
3865
3866                $query = "SELECT
3867                            CONCAT(
3868                                DATE_FORMAT((SELECT MIN(q.{$field}) FROM tbl_quotations q WHERE q.{$field} IS NOT NULL {$lflWhere}), '%c/%e/'), YEAR({$field}),
3869                                ' - ',
3870                                DATE_FORMAT((SELECT MAX(q.{$field}) FROM tbl_quotations q WHERE q.{$field} IS NOT NULL {$lflWhere}), '%c/%e/'), YEAR({$field})
3871                            ) AS date_like,
3872                            YEAR(q.{$field}) 'year',
3873                            DATE_FORMAT((SELECT MIN(q.{$field}) FROM tbl_quotations q WHERE q.{$field} IS NOT NULL {$lflWhere}), '%m-%d') AS min_date_like,
3874                            DATE_FORMAT((SELECT MAX(q.{$field}) FROM tbl_quotations q WHERE q.{$field} IS NOT NULL {$lflWhere}), '%m-%d') AS max_date_like,
3875                            {$v} 'company_id'
3876                        FROM
3877                            tbl_quotations q
3878                        WHERE
3879                            q.{$field} IS NOT NULL
3880                            AND q.for_add = 0
3881                            {$lflWhere}
3882                            {$whereYear}
3883                        GROUP BY YEAR(q.{$field})
3884                        ORDER BY YEAR(q.{$field}) DESC";
3885
3886                $dateLike = DB::select($query);
3887
3888                $dateLflArray[$v] = $dateLike;
3889            }
3890
3891            $whereAcceptanceDate = 'q.acceptance_date IS NOT NULL ';
3892
3893            $isFy = true;
3894
3895            if (isset($data['issue_year_ytd']) && $data['issue_year_ytd'] != null && $data['issue_year_ytd'] == true) {
3896                $isFy = false;
3897                $ytdArray = [];
3898                $ytdAcceptanceArray = [];
3899                $lflCompanyIds = [];
3900                $lflCompanyIdsAcc = [];
3901                foreach ($dateLflArray as $k => $v) {
3902                    foreach ($dateLflArray[$k] as $item) {
3903                        $year = $item->year;
3904                        $now = date('m-d');
3905                        array_push($ytdAcceptanceArray, "DATE_FORMAT(q.acceptance_date, '%Y-%m-%d') BETWEEN '{$year}-01-01' AND '{$year}-{$now}' AND YEAR(q.acceptance_date) = YEAR(issue_date)");
3906                        array_push($ytdArray, "DATE_FORMAT(q.{$field}, '%Y-%m-%d') BETWEEN '{$year}-01-01' AND '{$year}-{$now}'");
3907                    }
3908
3909                    $ytdArray = implode(' OR ', $ytdArray);
3910                    array_push($lflCompanyIds, "q.company_id = {$k} AND ({$ytdArray})");
3911                    $ytdArray = [];
3912
3913                    $ytdAcceptanceArray = implode(' OR ', $ytdAcceptanceArray);
3914                    array_push($lflCompanyIdsAcc, "q.company_id = {$k} AND ({$ytdAcceptanceArray})");
3915                    $ytdAcceptanceArray = [];
3916                }
3917
3918                $lflCompanyIds = implode(' OR ', $lflCompanyIds);
3919                $where .= " AND ({$lflCompanyIds}";
3920
3921                $lflCompanyIdsAcc = implode(' OR ', $lflCompanyIdsAcc);
3922                $whereAcceptanceDate .= " AND ({$lflCompanyIdsAcc}";
3923            }
3924
3925            if (isset($data['issue_year_lfl']) && $data['issue_year_lfl'] != null && $data['issue_year_lfl'] == true) {
3926                $isFy = false;
3927                $lflArray = [];
3928                $ytdAcceptanceArray = [];
3929                $lflCompanyIds = [];
3930                $lflCompanyIdsAcc = [];
3931                foreach ($dateLflArray as $k => $v) {
3932                    foreach ($dateLflArray[$k] as $item) {
3933                        $year = $item->year;
3934                        $min_date_like = $item->min_date_like;
3935                        $max_date_like = $item->max_date_like;
3936                        array_push($ytdAcceptanceArray, "DATE_FORMAT(q.acceptance_date, '%Y-%m-%d') BETWEEN LEAST('{$year}-{$min_date_like}', '{$year}-{$max_date_like}') AND GREATEST('{$year}-{$min_date_like}', '{$year}-{$max_date_like}') AND YEAR(q.acceptance_date) = YEAR(issue_date)");
3937                        array_push($lflArray, "DATE_FORMAT(q.{$field}, '%Y-%m-%d') BETWEEN LEAST('{$year}-{$min_date_like}', '{$year}-{$max_date_like}') AND GREATEST('{$year}-{$min_date_like}', '{$year}-{$max_date_like}')");
3938                    }
3939
3940                    $lflArray = implode(' OR ', $lflArray);
3941                    array_push($lflCompanyIds, "q.company_id = {$k} AND ({$lflArray})");
3942                    $lflArray = [];
3943
3944                    $ytdAcceptanceArray = implode(' OR ', $ytdAcceptanceArray);
3945                    array_push($lflCompanyIdsAcc, "q.company_id = {$k} AND ({$ytdAcceptanceArray})");
3946                    $ytdAcceptanceArray = [];
3947                }
3948
3949                $lflCompanyIds = implode(' OR ', $lflCompanyIds);
3950                $where .= " AND ({$lflCompanyIds}";
3951
3952                $lflCompanyIdsAcc = implode(' OR ', $lflCompanyIdsAcc);
3953                $whereAcceptanceDate .= " AND ({$lflCompanyIdsAcc}";
3954            }
3955
3956            if ($isFy) {
3957                if ($companyId != 0) {
3958                    $where .= " AND q.company_id = {$companyId} ";
3959                } else {
3960                    $where .= " AND q.company_id IN ({$this->companyId})";
3961                }
3962            }
3963
3964            if (isset($data['budget_status']) && $data['budget_status'] != null) {
3965                $where .= " AND bs.budget_status_id = {$data['budget_status']}";
3966            }
3967
3968            if (isset($data['segment_id']) && $data['segment_id'] != null) {
3969                $where .= " AND q.segment_id = {$data['segment_id']}";
3970            }
3971
3972            $query = "SELECT
3973                            YEAR(q.issue_date) AS 'year',
3974                            bt.name,
3975                            COUNT(
3976                                CASE WHEN q.issue_date IS NOT NULL
3977                                THEN 1 END
3978                            ) AS totalIssue,
3979                            GROUP_CONCAT(
3980                                CASE WHEN q.issue_date IS NOT NULL
3981                                THEN q.id END
3982                            ) AS groupConcatIds,
3983                            COUNT(CASE WHEN {$whereAcceptanceDate} AND bs.name = 'Aceptado' THEN 1 END) totalAccept,
3984                            COUNT(
3985                                CASE WHEN q.acceptance_date IS NOT NULL
3986                                AND {$whereAcceptanceDate}
3987                                AND bs.name = 'Aceptado'
3988                                AND DATEDIFF(q.acceptance_date, q.issue_date) < 10 THEN 1 END
3989                            ) / COUNT(
3990                                CASE WHEN q.issue_date IS NOT NULL
3991                                THEN 1 END
3992                            ) * 100 AS percentageOfacceptanceLessThan10,
3993                            COUNT(
3994                                CASE WHEN q.acceptance_date IS NOT NULL
3995                                AND {$whereAcceptanceDate}
3996                                AND bs.name = 'Aceptado'
3997                                AND DATEDIFF(q.acceptance_date, q.issue_date) > 10
3998                                AND DATEDIFF(q.acceptance_date, q.issue_date) < 30 THEN 1 END
3999                            ) / COUNT(
4000                                CASE WHEN q.issue_date IS NOT NULL
4001                                THEN 1 END
4002                            ) * 100 AS percentageOfacceptanceLessThan30,
4003                            COUNT(
4004                                CASE WHEN q.acceptance_date IS NOT NULL
4005                                AND {$whereAcceptanceDate}
4006                                AND bs.name = 'Aceptado'
4007                                AND DATEDIFF(q.acceptance_date, q.issue_date) > 30 THEN 1 END
4008                            ) / COUNT(
4009                                CASE WHEN q.issue_date IS NOT NULL
4010                                THEN 1 END
4011                            ) * 100 AS percentageOfacceptanceMoreThan30,
4012                            COUNT(CASE WHEN {$whereAcceptanceDate} THEN 1 END) / COUNT(
4013                                CASE WHEN q.issue_date IS NOT NULL
4014                                THEN 1 END
4015                            ) * 100 acceptedPercentage,
4016                            COALESCE(
4017                                AVG(
4018                                    CASE WHEN q.issue_date IS NOT NULL
4019                                    AND q.acceptance_date IS NOT NULL
4020                                    AND {$whereAcceptanceDate}
4021                                    AND bs.name = 'Aceptado'
4022                                    THEN DATEDIFF(q.acceptance_date, q.issue_date) ELSE NULL END
4023                                ), 0
4024                            )
4025                            AS averageAcceptedDuration,
4026                            COALESCE(
4027                                AVG(
4028                                    CASE WHEN q.issue_date IS NOT NULL
4029                                    AND q.request_date IS NOT NULL
4030                                    AND q.issue_date > q.request_date
4031                                    THEN DATEDIFF(q.issue_date, q.request_date) ELSE NULL END
4032                                ), 0
4033                            )
4034                            AS averageRequestedDays
4035                        FROM
4036                            tbl_quotations q
4037                            LEFT JOIN tbl_budget_types bt ON q.budget_type_id = bt.budget_type_id
4038                            LEFT JOIN tbl_budget_status bs ON bs.budget_status_id = q.budget_status_id
4039                        WHERE
4040                            q.issue_date IS NOT NULL
4041                            AND q.budget_type_id != 7
4042                            AND q.budget_type_id IS NOT NULL
4043                            AND q.for_add = 0
4044                            AND q.amount REGEXP '^[0-9]+\\.?[0-9]*$' = 1
4045                            {$where}
4046                            {$whereYear}
4047                        GROUP BY
4048                            YEAR(q.issue_date),
4049                            bt.name WITH ROLLUP";
4050
4051            $value = Cache::get(base64_encode($query));
4052
4053            if (! $value) {
4054                $result = DB::select($query);
4055
4056                Cache::put(base64_encode($query), $result, 600);
4057            } else {
4058                $result = $value;
4059            }
4060
4061            $typesBudgets = [];
4062            $typesBudgetsTotals = [];
4063
4064            if (count($result) > 0) {
4065                for ($i = 0; $i < count($result); $i++) {
4066
4067                    if ($result[$i]->year == null && $result[$i]->name == null) {
4068                        $result[$i]->name = 'totalGeneral';
4069                        $typesBudgetsTotals['totalGeneral'] = $result[$i];
4070
4071                        continue;
4072                    } elseif ($result[$i]->name == null && $result[$i]->year != null) {
4073                        if (count($data['years']) > 0 || $whereYear == '') {
4074                            $result[$i]->name = 'totalSub';
4075                        } else {
4076                            continue;
4077                        }
4078                    }
4079
4080                    $typesBudgets[$result[$i]->year][$result[$i]->name] = $result[$i];
4081                }
4082            }
4083
4084            return response([
4085                'message' => 'OK',
4086                'data' => $typesBudgets,
4087                'totals' => $typesBudgetsTotals,
4088            ]);
4089
4090        } catch (\Exception $e) {
4091            /** @disregard P1014 */
4092            $e->exceptionCode = 'LIST_QUOTATION_ANALYTICS_TYPES_BUDGETS_EXCEPTION';
4093            report($e);
4094
4095            return response(['message' => 'KO', 'error' => $e->getMessage()]);
4096        }
4097    }
4098
4099    public function download_quotations(Request $request)
4100    {
4101        ini_set('max_execution_time', 123456);
4102        $data = $request->all();
4103        $companyId = intval($data['company_id']);
4104        $userId = intval($data['user_id']);
4105
4106        $where = '';
4107
4108        $query = "SELECT
4109                b.name
4110            FROM tbl_users a
4111            LEFT JOIN tbl_roles b
4112                ON a.role_id = b.role_id
4113            WHERE a.id = {$userId}";
4114
4115        $role = DB::select($query);
4116
4117        $r = new Request([
4118            'filterModel' => $data['filterModel'],
4119            'sortModel' => $data['sortModel'],
4120            'start' => 0,
4121            'end' => 999999999,
4122            'company_id' => $data['company_id'],
4123            'user_id' => $data['user_id'],
4124            'ids' => $data['ids'],
4125            'searchText' => $data['searchText'],
4126            'ids_not_in' => $data['ids_not_in'],
4127        ]);
4128
4129        $result = $this->list_quotations($r);
4130
4131        $result = $result->original['data'];
4132
4133        return response(['data' => $result]);
4134
4135        $chunkSize = 1000;
4136        $total = count($result);
4137
4138        $spreadsheet = new Spreadsheet;
4139        $worksheet = new \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet($spreadsheet, 'Inputs');
4140        $spreadsheet->addSheet($worksheet, 0);
4141        $col = range('A', 'Z');
4142
4143        for ($i = 0; $i < 26; $i++) {
4144            $worksheet->getColumnDimension($col[$i])->setAutoSize(true);
4145            if ($i != 1) {
4146                $worksheet->getStyle($col[$i])
4147                    ->getAlignment()
4148                    ->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
4149            }
4150        }
4151
4152        $worksheet->getColumnDimension('AB')->setAutoSize(true);
4153        $worksheet->getStyle('AB')
4154            ->getAlignment()
4155            ->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
4156
4157        $l = 1;
4158        $worksheet->setCellValue('A'.$l, __('language.ID'));
4159        $worksheet->setCellValue('B'.$l, __('language.INTERNAL_ID'));
4160        $worksheet->setCellValue('C'.$l, __('language.CLIENT'));
4161        $worksheet->setCellValue('D'.$l, __('language.AMOUNT'));
4162        $worksheet->setCellValue('E'.$l, __('language.INVOICE_MARGIN'));
4163        $worksheet->setCellValue('F'.$l, __('language.MARGIN_FOR_THE_COMPANY'));
4164        $worksheet->setCellValue('G'.$l, __('language.TYPE'));
4165        $worksheet->setCellValue('H'.$l, __('language.STATUS'));
4166        $worksheet->setCellValue('I'.$l, __('language.CREATED_BY'));
4167        $worksheet->setCellValue('J'.$l, __('language.COMMERCIAL'));
4168        $worksheet->setCellValue('K'.$l, __('language.CREATED_AT'));
4169        $worksheet->setCellValue('L'.$l, __('language.ACCEPTANCE_DATE'));
4170        $worksheet->setCellValue('M'.$l, __('language.REQUEST_DATE'));
4171        $worksheet->setCellValue('N'.$l, __('language.ISSUE_DATE'));
4172        $worksheet->setCellValue('O'.$l, __('language.DURATION'));
4173        $worksheet->setCellValue('P'.$l, __('language.CLIENT_TYPE'));
4174        $worksheet->setCellValue('Q'.$l, __('language.SEGMENT'));
4175        $worksheet->setCellValue('R'.$l, __('language.LIKEHOOD'));
4176        $worksheet->setCellValue('S'.$l, __('language.SOURCE'));
4177        $worksheet->setCellValue('T'.$l, __('language.LAST_FOLLOW_UP_DATE'));
4178        $worksheet->setCellValue('U'.$l, __('language.REASON_FOR_NOT_FOLLOWING_UP'));
4179        $worksheet->setCellValue('V'.$l, __('language.REASON_FOR_REJECTION'));
4180        $worksheet->setCellValue('W'.$l, __('language.EMAIL'));
4181        $worksheet->setCellValue('X'.$l, __('language.EMAIL_STATUS'));
4182        $worksheet->setCellValue('Y'.$l, __('language.PHONE_NUMBER'));
4183        $worksheet->setCellValue('Z'.$l, __('language.ORDER_NUMBER'));
4184        $worksheet->setCellValue('AA'.$l, __('language.BOX_WORK_G3W'));
4185        $worksheet->setCellValue('AB'.$l, __('language.APPROVAL_REQUIRED'));
4186        $worksheet->setCellValue('AC'.$l, __('language.FILES_COUNT'));
4187        $worksheet->setCellValue('AD'.$l, __('language.ACCEPTED_BY'));
4188        $worksheet->setCellValue('AE'.$l, __('language.ACCEPTED_AT'));
4189        $worksheet->setCellValue('AF'.$l, 'Origen');
4190        $worksheet->setCellValue('AG'.$l, 'Origen Edit');
4191        $worksheet->setCellValue('AH'.$l, __('language.G3W_WARNING'));
4192        $worksheet->setCellValue('AI'.$l, __('language.COMPANY_NAME'));
4193
4194        $styleArray = [
4195            'font' => [
4196                'bold' => true,
4197            ],
4198        ];
4199
4200        $worksheet->getStyle('A1:AH1')
4201            ->getFill()
4202            ->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
4203            ->getStartColor()
4204            ->setARGB('523779');
4205
4206        $worksheet->getStyle('A1:AH1')
4207            ->getFont()
4208            ->getColor()
4209            ->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_WHITE);
4210
4211        $worksheet->getStyle('A1:AH1')->applyFromArray($styleArray);
4212
4213        $worksheet->getStyle('K:K')
4214            ->getNumberFormat()
4215            ->setFormatCode(\PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_DATE_YYYYMMDDSLASH);
4216
4217        $worksheet->getStyle('L:L')
4218            ->getNumberFormat()
4219            ->setFormatCode(\PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_DATE_YYYYMMDDSLASH);
4220
4221        $worksheet->getStyle('M:M')
4222            ->getNumberFormat()
4223            ->setFormatCode(\PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_DATE_YYYYMMDDSLASH);
4224
4225        $worksheet->getStyle('N:N')
4226            ->getNumberFormat()
4227            ->setFormatCode(\PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_DATE_YYYYMMDDSLASH);
4228
4229        $worksheet->getStyle('T:T')
4230            ->getNumberFormat()
4231            ->setFormatCode(\PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_DATE_YYYYMMDDSLASH);
4232
4233        $worksheet->getStyle('AE:AE')
4234            ->getNumberFormat()
4235            ->setFormatCode(\PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_DATE_YYYYMMDDSLASH);
4236
4237        $l = 2;
4238
4239        for ($offset = 0; $offset < $total; $offset += $chunkSize) {
4240            $chunkEnd = min($offset + $chunkSize, $total);
4241
4242            for ($i = $offset; $i < $chunkEnd; $i++) {
4243                if ($result[$i]->request_date) {
4244                    $result[$i]->request_date = \PhpOffice\PhpSpreadsheet\Shared\Date::PHPToExcel($result[$i]->request_date);
4245                }
4246
4247                if ($result[$i]->issue_date) {
4248                    $result[$i]->issue_date = \PhpOffice\PhpSpreadsheet\Shared\Date::PHPToExcel($result[$i]->issue_date);
4249                }
4250
4251                if ($result[$i]->acceptance_date) {
4252                    $result[$i]->acceptance_date = \PhpOffice\PhpSpreadsheet\Shared\Date::PHPToExcel($result[$i]->acceptance_date);
4253                }
4254
4255                if ($result[$i]->last_follow_up_date) {
4256                    $result[$i]->last_follow_up_date = \PhpOffice\PhpSpreadsheet\Shared\Date::PHPToExcel($result[$i]->last_follow_up_date);
4257                }
4258
4259                if ($result[$i]->created_at) {
4260                    $result[$i]->created_at = \PhpOffice\PhpSpreadsheet\Shared\Date::PHPToExcel($result[$i]->created_at);
4261                }
4262
4263                if ($result[$i]->accepted_at) {
4264                    $result[$i]->accepted_at = \PhpOffice\PhpSpreadsheet\Shared\Date::PHPToExcel($result[$i]->accepted_at);
4265                }
4266
4267                $worksheet->setCellValue('A'.$l, $result[$i]->quote_id);
4268                $worksheet->setCellValue('B'.$l, $result[$i]->internal_quote_id);
4269                $worksheet->setCellValue('C'.$l, $result[$i]->client);
4270                $worksheet->setCellValue('D'.$l, $result[$i]->amount);
4271                $worksheet->setCellValue('E'.$l, $result[$i]->invoice_margin);
4272                $worksheet->setCellValue('F'.$l, $result[$i]->margin_for_the_company);
4273                $worksheet->setCellValue('G'.$l, $result[$i]->type);
4274                $worksheet->setCellValue('H'.$l, $result[$i]->status);
4275                $worksheet->setCellValue('I'.$l, $result[$i]->created_by);
4276                $worksheet->setCellValue('J'.$l, $result[$i]->commercial);
4277                $worksheet->setCellValue('K'.$l, $result[$i]->created_at);
4278                $worksheet->setCellValue('L'.$l, $result[$i]->acceptance_date);
4279                $worksheet->setCellValue('M'.$l, $result[$i]->request_date);
4280                $worksheet->setCellValue('N'.$l, $result[$i]->issue_date);
4281                $worksheet->setCellValue('O'.$l, '=DATEDIF(J'.$l.',K'.$l.',"d")');
4282                $worksheet->setCellValue('P'.$l, $result[$i]->client_type);
4283                $worksheet->setCellValue('Q'.$l, $result[$i]->segment);
4284                $worksheet->setCellValue('R'.$l, $result[$i]->likehood);
4285                $worksheet->setCellValue('S'.$l, $result[$i]->source);
4286                $worksheet->setCellValue('T'.$l, $result[$i]->last_follow_up_date);
4287                $worksheet->setCellValue('U'.$l, $result[$i]->reason_for_not_following_up);
4288                $worksheet->setCellValue('V'.$l, $result[$i]->reason_for_rejection);
4289                $worksheet->setCellValue('W'.$l, $result[$i]->email);
4290                $worksheet->setCellValue('X'.$l, $result[$i]->x_status);
4291                $worksheet->setCellValue('Y'.$l, $result[$i]->phone_number);
4292                $worksheet->setCellValue('Z'.$l, $result[$i]->order_number);
4293                $worksheet->setCellValue('AA'.$l, $result[$i]->box_work_g3w);
4294                $worksheet->setCellValue('AB'.$l, ($result[$i]->for_approval == 1 || $result[$i]->for_approval == 3) ? __('language.YES') : __('language.NO'));
4295                $worksheet->setCellValue('AC'.$l, $result[$i]->has_attachment == 1 ? __('language.YES') : __('language.NO'));
4296                $worksheet->setCellValue('AD'.$l, $result[$i]->accepted_by);
4297                $worksheet->setCellValue('AE'.$l, $result[$i]->accepted_at);
4298                $worksheet->setCellValue('AF'.$l, $result[$i]->sync_import == 1 ? 'G3W' : 'Manual');
4299                $worksheet->setCellValue('AG'.$l, $result[$i]->sync_import_edited == 1 ? 'G3W' : 'Manual');
4300                $worksheet->setCellValue('AH'.$l, $result[$i]->g3w_warning == 1 ? 'Sí' : 'No');
4301                $worksheet->setCellValue('AI'.$l, $result[$i]->company_name);
4302                $l++;
4303            }
4304
4305            gc_collect_cycles();
4306        }
4307
4308        if ($role[0]->name == 'Regular') {
4309            $worksheet->removeColumn('D');
4310            $worksheet->removeColumn('W');
4311            $worksheet->removeColumn('X');
4312        }
4313
4314        $writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
4315        $writer->setPreCalculateFormulas(false);
4316
4317        ob_start();
4318        $writer->save('php://output');
4319        $file = ob_get_contents();
4320        ob_end_clean();
4321
4322        return response($file);
4323    }
4324
4325    public function download_quotations_csv($filename, $data) {}
4326
4327    public function bulk_upload(Request $request)
4328    {
4329
4330        try {
4331
4332            $data = $request->all();
4333            $file = $request->file('file');
4334            $exte = 'Xlsx';
4335            $companyId = $data['company_id'];
4336
4337            if ($file->getMimeType() == 'application/vnd.ms-excel') {
4338                $exte = 'Xls';
4339            }
4340
4341            $destination_path = env('BULK_UPLOAD_FILE_DESTINATION', 'E:/bulk_upload/');
4342            $filename = $file->getClientOriginalName();
4343
4344            if (file_exists($destination_path.$filename)) {
4345                $filename = pathinfo($filename, PATHINFO_FILENAME).'-'.uniqid().'.'.pathinfo($filename, PATHINFO_EXTENSION);
4346            }
4347
4348            $file->move($destination_path, $filename);
4349
4350            TblBulkUpload::create(
4351                [
4352                    'company_id' => $companyId,
4353                    'filename' => $filename,
4354                    'status' => 'Uploading...',
4355                    'is_running' => 1,
4356                    'uploaded_by' => $data['created_by'],
4357                ]
4358            );
4359
4360            $command = "php BulkUploadQuotations.php '{$data['created_by']}' '{$exte}' '{$destination_path}' '{$filename}{$companyId}";
4361            exec($command.' > /dev/null &');
4362
4363            $query = '';
4364            $isRunning = 0;
4365
4366            if ($companyId == 0) {
4367                $query = 'SELECT * FROM tbl_bulk_upload ORDER BY started_at DESC';
4368                $isRunning = TblBulkUpload::where('is_running', 1)->count();
4369            } else {
4370                $query = "SELECT * FROM tbl_bulk_upload WHERE company_id = {$companyId} ORDER BY started_at DESC";
4371                $isRunning = TblBulkUpload::where('is_running', 1)->where('company_id', $companyId)->count();
4372            }
4373
4374            $result = DB::select($query);
4375
4376            return response(['message' => 'OK', 'data' => $result, 'is_running' => $isRunning]);
4377
4378        } catch (\Exception $e) {
4379            /** @disregard P1014 */
4380            $e->exceptionCode = 'BULK_UPLOAD_QUOTATIONS_EXCEPTION';
4381            report($e);
4382
4383            return response(['message' => 'KO', 'error' => $e->getMessage()]);
4384        }
4385    }
4386
4387    public function list_bulk_upload($companyId)
4388    {
4389
4390        try {
4391
4392            $companyId = intval($companyId);
4393            $query = '';
4394            $isRunning = 0;
4395
4396            if ($companyId == 0) {
4397                $query = 'SELECT * FROM tbl_bulk_upload ORDER BY started_at DESC';
4398                $isRunning = TblBulkUpload::where('is_running', 1)->count();
4399            } else {
4400                $query = "SELECT * FROM tbl_bulk_upload WHERE company_id = {$companyId} ORDER BY started_at DESC";
4401                $isRunning = TblBulkUpload::where('is_running', 1)->where('company_id', $companyId)->count();
4402            }
4403
4404            $result = DB::select($query);
4405
4406            return response(['message' => 'OK', 'data' => $result, 'is_running' => $isRunning]);
4407
4408        } catch (\Exception $e) {
4409            /** @disregard P1014 */
4410            $e->exceptionCode = 'LIST_BULK_UPLOAD_EXCEPTION';
4411            report($e);
4412
4413            return response(['message' => 'KO', 'error' => $e->getMessage()]);
4414        }
4415
4416    }
4417
4418    public function delete_number(Request $request, $id)
4419    {
4420
4421        try {
4422
4423            $id = intval($id);
4424            $data = $request->all();
4425
4426            $r = TblQuotations::where('id', $id)->first();
4427            $updatedAt = date('Y-m-d H:i:s');
4428            $query = "INSERT INTO tbl_quotations_deleted (id, quote_id, company_id, for_add, created_by, updated_by, updated_at)
4429                        SELECT id, quote_id, company_id, 1, created_by, '{$data['updated_by']}', '{$updatedAt}' FROM tbl_quotations WHERE id = {$id}";
4430
4431            DB::select($query);
4432
4433            TblQuotations::where('id', $id)->delete();
4434
4435            $latestBudget = TblQuotations::where('company_id', $r->company_id)->orderByRaw('id DESC')->value('quote_id');
4436
4437            $query = "UPDATE tbl_companies SET last_id = '{$latestBudget}' WHERE company_id = {$r->company_id}";
4438            DB::select($query);
4439
4440            return response(['message' => 'OK']);
4441
4442        } catch (\Exception $e) {
4443            /** @disregard P1014 */
4444            $e->exceptionCode = 'DELETE_QUOTATION_EXCEPTION';
4445            report($e);
4446
4447            return response(['message' => 'KO', 'error' => $e->getMessage()]);
4448        }
4449
4450    }
4451
4452    public function get_number(Request $request, $companyId, $n = null)
4453    {
4454
4455        try {
4456
4457            $companyId = intval($companyId);
4458            $data = $request->all();
4459            $latestBudget = [];
4460            $number = 0;
4461            $beforeLastId = null;
4462
4463            $x = true;
4464
4465            if ($companyId == 0) {
4466                $latestBudget = TblQuotations::orderByRaw('CAST(quote_id AS DOUBLE) DESC')->value('quote_id');
4467            } else {
4468                $latestBudget = TblCompanies::where('company_id', $companyId)->value('last_id');
4469
4470                if ($latestBudget == null) {
4471                    $latestBudget = TblQuotations::where('company_id', $companyId)->orderByRaw('id DESC')->value('quote_id');
4472                    $beforeLastId = $latestBudget;
4473                }
4474            }
4475
4476            $number = $latestBudget;
4477
4478            while ($x) {
4479
4480                if (is_numeric(substr($number, -1))) {
4481                    $number++;
4482                } else {
4483                    $number .= '1';
4484                }
4485
4486                $check = 0;
4487
4488                if ($companyId == 0) {
4489                    $check = TblQuotations::where('quote_id', (string) $number)->count();
4490                } else {
4491                    $check = TblQuotations::where('company_id', $companyId)->where('quote_id', (string) $number)->count();
4492                }
4493
4494                if ($check == 0) {
4495                    $x = false;
4496                }
4497            }
4498
4499            $result = null;
4500
4501            if ($n == null) {
4502                $result = TblQuotations::create(['quote_id' => $number, 'company_id' => $companyId, 'for_add' => 1, 'created_by' => $data['created_by']]);
4503            }
4504
4505            if ($beforeLastId == null) {
4506                $beforeLastId = $number;
4507            }
4508
4509            $query = "UPDATE tbl_companies SET last_id = '{$number}', before_last_id = CASE WHEN before_last_id IS NULL THEN '{$beforeLastId}' ELSE before_last_id END WHERE company_id = {$companyId}";
4510            DB::select($query);
4511
4512            return response([
4513                'message' => 'OK',
4514                'number' => $number,
4515                'id' => ($result != null) ? $result->id : null,
4516            ]);
4517
4518        } catch (\Exception $e) {
4519            /** @disregard P1014 */
4520            $e->exceptionCode = 'GET_NUMBER_EXCEPTION';
4521            report($e);
4522
4523            return response(['message' => 'KO', 'error' => $e->getMessage()]);
4524        }
4525
4526    }
4527
4528    public function get_years(Request $request)
4529    {
4530
4531        try {
4532
4533            $data = $request->all();
4534            $companyId = intval($data['company_id']);
4535            $where = '';
4536
4537            if ($companyId != 0) {
4538                $where = " AND company_id = {$companyId} ";
4539            } else {
4540                $where = " AND company_id IN ({$this->companyId}";
4541            }
4542
4543            $query = "SELECT
4544                        CONCAT(
4545                            DATE_FORMAT((SELECT MIN(issue_date) FROM tbl_quotations WHERE issue_date IS NOT NULL {$where}), '%c/%e/'), YEAR(issue_date),
4546                            ' - ',
4547                            DATE_FORMAT((SELECT MAX(issue_date) FROM tbl_quotations WHERE issue_date IS NOT NULL {$where}), '%c/%e/'), YEAR(issue_date)
4548                        ) AS date_like,
4549                        YEAR(issue_date) 'year'
4550                        FROM tbl_quotations
4551                        WHERE issue_date IS NOT NULL {$where}
4552                        GROUP BY YEAR(issue_date)
4553                        ORDER BY YEAR(issue_date) DESC";
4554
4555            $issueDate = DB::select($query);
4556
4557            $query = "SELECT
4558                        CONCAT(
4559                            DATE_FORMAT((SELECT MIN(created_at) FROM tbl_quotations WHERE created_at IS NOT NULL {$where}), '%c/%e/'), YEAR(created_at),
4560                            ' - ',
4561                            DATE_FORMAT((SELECT MAX(created_at) FROM tbl_quotations WHERE created_at IS NOT NULL {$where}), '%c/%e/'), YEAR(created_at)
4562                        ) AS date_like,
4563                        YEAR(created_at) 'year'
4564                        FROM tbl_quotations
4565                        WHERE created_at IS NOT NULL {$where}
4566                        GROUP BY YEAR(created_at)
4567                        ORDER BY YEAR(created_at) DESC";
4568
4569            $createdAt = DB::select($query);
4570
4571            $query = "SELECT
4572                        CONCAT(
4573                            DATE_FORMAT((SELECT MIN(acceptance_date) FROM tbl_quotations WHERE acceptance_date IS NOT NULL {$where}), '%c/%e/'), YEAR(acceptance_date),
4574                            ' - ',
4575                            DATE_FORMAT((SELECT MAX(acceptance_date) FROM tbl_quotations WHERE acceptance_date IS NOT NULL {$where}), '%c/%e/'), YEAR(acceptance_date)
4576                        ) AS date_like,
4577                        YEAR(acceptance_date) 'year'
4578                        FROM tbl_quotations
4579                        WHERE acceptance_date IS NOT NULL {$where}
4580                        GROUP BY YEAR(acceptance_date)
4581                        ORDER BY YEAR(acceptance_date) DESC";
4582
4583            $acceptanceDate = DB::select($query);
4584
4585            return response([
4586                'message' => 'OK',
4587                'data' => $issueDate,
4588                'created_at' => $createdAt,
4589                'acceptance_date' => $acceptanceDate,
4590            ]);
4591
4592        } catch (\Exception $e) {
4593            /** @disregard P1014 */
4594            $e->exceptionCode = 'GET_YEARS_EXCEPTION';
4595            report($e);
4596
4597            return response(['message' => 'KO', 'error' => $e->getMessage()]);
4598        }
4599
4600    }
4601
4602    public function human_filesize($bytes, $decimals = 2)
4603    {
4604        $size = ['B', 'KB', 'MB'];
4605
4606        $factor = (int) floor((strlen($bytes) - 1) / 3);
4607
4608        return number_format($bytes / pow(1024, $factor), 2, ',', '.').$size[$factor];
4609    }
4610
4611    public function get_files($quoteId)
4612    {
4613
4614        try {
4615
4616            $quoteId = intval($quoteId);
4617
4618            $quoteId = (int) $quoteId;
4619            $query = '
4620            SELECT
4621                file_id,
4622                quotation_id,
4623                quote_id,
4624                original_name,
4625                filename,
4626                uploaded_by,
4627                uploaded_at,
4628                is_internal,
4629                file_size,
4630                file_hash,
4631                mime_type
4632            FROM tbl_files
4633            WHERE quotation_id = ?
4634            AND is_internal IS NULL';
4635
4636            $result = DB::select($query, [$quoteId]);
4637
4638            foreach ($result as $file) {
4639                if ($file->file_size > 0) {
4640                    $file->filesize = $this->human_filesize($file->file_size);
4641                } else {
4642                    $path = 'uploads/'.$file->filename;
4643
4644                    if (Storage::disk('s3')->exists($path)) {
4645                        $fileSizeBytes = Storage::disk('s3')->size($path);
4646                    } else {
4647                        $fileSizeBytes = 0;
4648                    }
4649
4650                    $file->filesize = $this->human_filesize($fileSizeBytes);
4651                }
4652
4653                $file->original_name = $file->original_name." ({$file->filesize})";
4654            }
4655
4656            $query = '
4657            SELECT
4658                file_id,
4659                quotation_id,
4660                quote_id,
4661                original_name,
4662                filename,
4663                uploaded_by,
4664                uploaded_at,
4665                is_internal,
4666                file_size,
4667                file_hash,
4668                mime_type
4669            FROM tbl_files
4670            WHERE quotation_id = ?
4671            AND is_internal = 1';
4672
4673            $internal = DB::select($query, [$quoteId]);
4674
4675            foreach ($internal as $file) {
4676                if ($file->file_size > 0) {
4677                    $file->filesize = $this->human_filesize($file->file_size);
4678                } else {
4679                    $path = 'uploads/'.$file->filename;
4680
4681                    if (Storage::disk('s3')->exists($path)) {
4682                        $fileSizeBytes = Storage::disk('s3')->size($path);
4683                    } else {
4684                        $fileSizeBytes = 0;
4685                    }
4686
4687                    $file->filesize = $this->human_filesize($fileSizeBytes);
4688                }
4689
4690                $file->original_name = $file->original_name." ({$file->filesize})";
4691            }
4692
4693            $job = TblOngoingJobs::where('quotation_id', $quoteId)->first();
4694            $order = TblQuotations::where('id', $quoteId)->first();
4695
4696            $emails = explode(',', str_replace(' ', '', $order->email));
4697
4698            $sendGrid = TblSendgridWebhook::where('quotation_id', $quoteId)->where('x_message_id', $order->x_message_id)->first();
4699
4700            $uniqueEvents = [];
4701            $currentEvents = [];
4702            $status = 2;
4703
4704            $xStatus = 'processed';
4705
4706            if ($sendGrid) {
4707                $emailErrors = ['deferred', 'bounce', 'dropped', 'spamreport', 'invalid'];
4708                $events = json_decode($sendGrid->json_body, true);
4709                $xMessageId = $sendGrid->x_message_id;
4710                $isDelivered = 0;
4711                $isProcessed = 0;
4712                $isError = 0;
4713
4714                foreach ($emails as $email) {
4715
4716                    $emailEvents = array_filter($events, fn ($event) => strtolower($event['email']) === strtolower($email));
4717
4718                    $statuses = array_unique(array_column($emailEvents, 'event'));
4719                    $eventCount = count($statuses);
4720
4721                    if ($eventCount === 1 && in_array('processed', $statuses)) {
4722                        $xStatus = 'processed';
4723                    }
4724
4725                    if ($eventCount == 2) {
4726                        if (in_array('processed', $statuses) && in_array('delivered', $statuses)) {
4727                            $xStatus = 'delivered';
4728                        }
4729
4730                        foreach ($emailErrors as $e) {
4731                            if (in_array('processed', $statuses) && in_array($e, $statuses)) {
4732                                $xStatus = $e;
4733                            }
4734                        }
4735
4736                    } elseif ($eventCount > 2) {
4737                        if (in_array('processed', $statuses) && in_array('delivered', $statuses)) {
4738                            $xStatus = 'delivered';
4739                        }
4740
4741                        if ($xStatus != 'delivered') {
4742                            foreach ($emailErrors as $e) {
4743                                if (in_array('processed', $statuses) && in_array($e, $statuses)) {
4744                                    $xStatus = $e;
4745                                }
4746                            }
4747                        }
4748                    }
4749
4750                    if ($xStatus == 'processed') {
4751                        $isProcessed++;
4752                    } elseif ($xStatus == 'delivered') {
4753                        $isDelivered++;
4754                    } else {
4755                        $isError++;
4756                    }
4757
4758                    foreach ($emailEvents as $event) {
4759                        $key = strtolower($event['email']).'|'.$event['event'];
4760                        if (! isset($uniqueEvents[$key])) {
4761                            $uniqueEvents[$key] = $event;
4762                        }
4763                    }
4764                }
4765
4766                if ($uniqueEvents) {
4767                    foreach (array_values($uniqueEvents) as $d) {
4768                        $d['created_at'] = date('Y-m-d H:i:s', $d['timestamp']);
4769
4770                        if (isset($d['response'])) {
4771                            $d['error'] = $d['response'];
4772                        }
4773
4774                        if (isset($d['reason'])) {
4775                            $d['error'] = $d['reason'];
4776                        }
4777
4778                        array_push($currentEvents, $d);
4779                    }
4780                }
4781
4782                if (count($emails) == $isDelivered) {
4783                    $status = 1;
4784                    $xStatus = 'Completed';
4785                } elseif ($isProcessed > 0) {
4786                    $status = 2;
4787                    $xStatus = 'Processing';
4788                } elseif ($isError > 0) {
4789                    $status = 3;
4790
4791                    if ($xStatus == 'bounce') {
4792                        $xStatus = 'Error - Bounce';
4793                    } else {
4794                        $xStatus = 'Error';
4795                    }
4796                }
4797            }
4798
4799            $z = 0;
4800
4801            if ($order->x_status != $xStatus) {
4802                TblQuotations::where('id', $order->id)->update(
4803                    [
4804                        'x_status' => $xStatus,
4805                    ]
4806                );
4807                $z = 1;
4808                Cache::flush();
4809            }
4810
4811            if (empty($currentEvents)) {
4812                $status = 0;
4813            }
4814
4815            $followUpLogs = TblFollowUpLogs::where('quotation_id', $quoteId)->orderBy('created_at', 'desc')->get();
4816
4817            $projectTypes = TblProjectTypes::where('company_id', $order->company_id)->get();
4818
4819            $sendgridFollowUpLogs = [];
4820
4821            if ($order->y_message_id) {
4822                $sendgridFollowUpLogs = TblSendgridWebhook::where('x_message_id', $order->y_message_id)->first();
4823
4824                if ($sendgridFollowUpLogs) {
4825                    $sendgridFollowUpLogs = json_decode($sendgridFollowUpLogs->json_body, true);
4826                    foreach ($sendgridFollowUpLogs as &$item) {
4827                        $item['created_at'] = date('Y-m-d H:i:s', $item['timestamp']);
4828                    }
4829                }
4830            }
4831
4832            return response([
4833                'message' => 'OK',
4834                'data' => $result,
4835                'followUpLogs' => $followUpLogs,
4836                'sendgridFollowUpLogs' => $sendgridFollowUpLogs,
4837                'internal' => $internal,
4838                'projectTypes' => $projectTypes,
4839                'currentEvents' => [
4840                    'status' => $status,
4841                    'email' => $currentEvents,
4842                    $uniqueEvents,
4843                    $xStatus,
4844                ],
4845                'job' => $job,
4846                'isUpdated' => $z,
4847            ]);
4848
4849        } catch (\Exception $e) {
4850            /** @disregard P1014 */
4851            $e->exceptionCode = 'GET_FILES_EXCEPTION';
4852            report($e);
4853
4854            return response(['message' => 'KO', 'error' => $e->getMessage()]);
4855        }
4856
4857    }
4858
4859    public function download_file($fileId)
4860    {
4861        try {
4862            $fileId = intval($fileId);
4863            $file = TblFiles::where('file_id', $fileId)->first();
4864
4865            if (! $file) {
4866                return response()->json([
4867                    'message' => 'KO',
4868                    'error' => 'Archivo no encontrado',
4869                ], 404);
4870            }
4871
4872            if (! is_null($file->file_hash) && ! empty($file->file)) {
4873                $fileContent = $file->file;
4874                $mimeType = $file->mime_type ?? 'application/octet-stream';
4875                $filename = $file->original_name ?? $file->filename ?? 'download';
4876
4877                return response($fileContent)
4878                    ->header('Content-Type', $mimeType)
4879                    ->header('Content-Disposition', 'attachment; filename="'.$filename.'"')
4880                    ->header('Content-Length', strlen($fileContent))
4881                    ->header('Cache-Control', 'no-cache, no-store, must-revalidate');
4882
4883            } else {
4884                $filePath = Storage::disk('s3')->get('uploads/'.$file->filename);
4885                // $filePath = storage_path('app/public/uploads/' . $file->filename);
4886
4887                if (! Storage::disk('s3')->exists('uploads/'.$file->filename)) {
4888                    return response()->json([
4889                        'message' => 'KO',
4890                        'error' => 'Archivo físico no encontrado: '.$file->filename,
4891                    ], 404);
4892                }
4893
4894                $fileSize = filesize($filePath);
4895                $mimeType = mime_content_type($filePath) ?: 'application/octet-stream';
4896                $filename = $file->original_name ?? $file->filename;
4897
4898                $fileContent = file_get_contents($filePath);
4899
4900                return response($fileContent)
4901                    ->header('Content-Type', $mimeType)
4902                    ->header('Content-Disposition', 'attachment; filename="'.$filename.'"')
4903                    ->header('Content-Length', $fileSize)
4904                    ->header('Cache-Control', 'no-cache, no-store, must-revalidate');
4905            }
4906
4907        } catch (\Exception $e) {
4908            /** @disregard P1014 */
4909            $e->exceptionCode = 'DOWNLOAD_FILE_EXCEPTION';
4910            report($e);
4911            \Log::error('Error downloading file: '.$e->getMessage());
4912
4913            return response()->json([
4914                'message' => 'KO',
4915                'error' => 'Error interno del servidor: '.$e->getMessage(),
4916            ], 500);
4917        }
4918    }
4919
4920    public function delete_file($fileId)
4921    {
4922
4923        try {
4924
4925            $fileId = intval($fileId);
4926            $file = TblFiles::where('file_id', $fileId)->first();
4927            $result = TblFiles::where('file_id', $fileId)->first();
4928
4929            if ($result) {
4930                TblFiles::where('file_id', $fileId)->delete();
4931                $path = storage_path('app/public/uploads/'.$result->filename);
4932                Storage::disk('public')->delete('uploads/'.$result->filename);
4933
4934                if (! env('SENDGRID_STAGING')) {
4935                    Storage::disk('s3')->delete('uploads/'.$result->filename);
4936                }
4937            }
4938
4939            $fileCount = TblFiles::where('quotation_id', $file->quotation_id)->count();
4940            $data = [];
4941            if ($fileCount > 0) {
4942                $data['has_attachment'] = 1;
4943            } else {
4944                $data['has_attachment'] = 0;
4945            }
4946
4947            TblQuotations::where('quote_id', $file->quote_id)->update($data);
4948
4949            $this->addUpdateLog($file->quote_id, 'user', 'delete_attachment', $file->filename, null, 4);
4950
4951            return response(['message' => 'OK']);
4952
4953        } catch (\Exception $e) {
4954            /** @disregard P1014 */
4955            $e->exceptionCode = 'DELETE_FILE_EXCEPTION';
4956            report($e);
4957
4958            return response(['message' => 'KO', 'error' => $e->getMessage()]);
4959        }
4960    }
4961
4962    public function send_email_to_client(Request $request)
4963    {
4964
4965        ini_set('max_execution_time', 0);
4966
4967        try {
4968
4969            $data = $request->all();
4970
4971            // $id = addslashes($data['id']);
4972            $userId = addslashes($data['user_id']);
4973            $companyId = addslashes($data['company_id']);
4974
4975            $isResend = null;
4976
4977            if (isset($data['is_resend'])) {
4978                $isResend = 1;
4979                unset($data['is_resend']);
4980            }
4981
4982            $where = '';
4983            $emailTemplateId = $data['email_template_id'];
4984            unset($data['email_template_id']);
4985
4986            $emailTemplates = [];
4987
4988            if (isset($data['html'])) {
4989                $emailTemplates = array_column($data['html'], null, 'id');
4990            }
4991
4992            $emailTemplate = TblEmailConfiguration::whereIn('id', $emailTemplateId)->get()->keyBy('company_id');
4993
4994            $emailCompany = [];
4995
4996            $result = [];
4997
4998            if ($companyId == 0) {
4999                $indexes = $emailTemplate->keys();
5000
5001                $emailCompany = TblCompanies::whereIn('company_id', $indexes)->get()->keyBy('company_id');
5002                $limit = 21;
5003
5004                foreach ($emailCompany as $item) {
5005                    $r = new Request([
5006                        'filterModel' => $data['filterModel'],
5007                        'sortModel' => $data['sortModel'],
5008                        'start' => 0,
5009                        'end' => 999999999,
5010                        'company_id' => $data['company_id'],
5011                        'user_id' => $data['user_id'],
5012                        'ids' => $data['ids'],
5013                        'searchText' => $data['searchText'],
5014                        'ids_not_in' => $data['ids_not_in'],
5015                    ]);
5016
5017                    $listQuotations = $this->list_quotations($r);
5018                    $d = $listQuotations->original['data'];
5019
5020                    if ($item->limit_send != null) {
5021                        $limit = $item->limit_send;
5022                    }
5023                    $l = 0;
5024                    for ($i = 0; $i < count($d); $i++) {
5025                        if ($d[$i]->email != null
5026                            && ($d[$i]->budget_status_id == 11 || $isResend == 1)
5027                            && $item->company_id == $d[$i]->company_id
5028                        ) {
5029                            if ($l == $limit) {
5030                                break;
5031                            }
5032                            array_push($result, $d[$i]);
5033                            $l++;
5034                        }
5035                    }
5036                }
5037            } else {
5038
5039                $emailCompany = TblCompanies::where('company_id', $companyId)->get()->keyBy('company_id');
5040
5041                $limit = 21;
5042
5043                if ($emailCompany[$companyId]->limit_send != null) {
5044                    $limit = $emailCompany[$companyId]->limit_send;
5045                }
5046
5047                $r = new Request([
5048                    'filterModel' => $data['filterModel'],
5049                    'sortModel' => $data['sortModel'],
5050                    'start' => 0,
5051                    'end' => 999999999,
5052                    'company_id' => $data['company_id'],
5053                    'user_id' => $data['user_id'],
5054                    'ids' => $data['ids'],
5055                    'searchText' => $data['searchText'],
5056                    'ids_not_in' => $data['ids_not_in'],
5057                ]);
5058
5059                $listQuotations = $this->list_quotations($r);
5060                $d = $listQuotations->original['data'];
5061                $l = 0;
5062                for ($i = 0; $i < count($d); $i++) {
5063                    if ($d[$i]->email != null && ($d[$i]->budget_status_id == 11 || $isResend == 1)) {
5064                        if ($l == $limit) {
5065                            break;
5066                        }
5067                        array_push($result, $d[$i]);
5068                        $l++;
5069                    }
5070                }
5071            }
5072
5073            if (count($result) == 0) {
5074                return response(['message' => 'OK', $d ?? []]);
5075            }
5076
5077            $user = TblUsers::where('id', $userId)->first();
5078            $error = false;
5079
5080            $availableParameters = [
5081                'quote_id',
5082                'company_id',
5083                'client',
5084                'client_type',
5085                'phone_number',
5086                'email',
5087                'issue_date',
5088                'request_date',
5089                'duration',
5090                'invoice_number',
5091                'type',
5092                'acceptance_date',
5093                'status',
5094                'source',
5095                'amount',
5096                'reason_for_not_following_up',
5097                'last_follow_up_date',
5098                'last_follow_up_comment',
5099                'reason_for_rejection_id',
5100                'reason_for_rejection',
5101                'commercial',
5102                'created_at',
5103                'created_by',
5104                'updated_at',
5105                'updated_by',
5106            ];
5107
5108            $dateParameters = [
5109                'issue_date',
5110                'request_date',
5111                'acceptance_date',
5112                'last_follow_up_date',
5113                'created_at',
5114                'updated_at',
5115            ];
5116
5117            if ($this->locale == 'es') {
5118                setlocale(LC_ALL, 'es_ES', 'Spanish_Spain', 'Spanish');
5119            }
5120
5121            if ($this->locale == 'es') {
5122                setlocale(LC_ALL, 'es_ES', 'Spanish_Spain', 'Spanish');
5123            }
5124
5125            $sentItems = [];
5126
5127            for ($i = 0; $i < count($result); $i++) {
5128
5129                $body = $emailTemplate[$result[$i]->company_id]->html;
5130                if (isset($data['html']) && ! empty($data['html'])) {
5131                    $body = $emailTemplates[$result[$i]->company_id]['html'];
5132                }
5133                $subject = $emailTemplate[$result[$i]->company_id]->subject;
5134                $commercialUser = $result[$i]->commercial;
5135
5136                if ($result[$i]->email != null) {
5137
5138                    if (env('SENDGRID_STAGING')) {
5139                        $toEmail = $user->email;
5140                    } else {
5141                        $toEmail = $result[$i]->email;
5142                    }
5143
5144                    preg_match_all('/{{(.*?)}}/', $body, $matches);
5145
5146                    $parameters = $matches[1];
5147
5148                    foreach ($parameters as $parameter) {
5149
5150                        if (in_array($parameter, $dateParameters)) {
5151                            if ($result[$i]->{$parameter}) {
5152                                $result[$i]->{$parameter} = iconv('ISO-8859-2', 'UTF-8', strftime('%A, %B %d, %Y', strtotime($result[$i]->{$parameter})));
5153                            }
5154                        }
5155
5156                        if (in_array($parameter, $availableParameters)) {
5157                            $body = str_replace('{{'.$parameter.'}}', $result[$i]->{$parameter}, $body);
5158                        }
5159                    }
5160
5161                    preg_match_all('/{{(.*?)}}/', $subject, $matches);
5162
5163                    $parameters = $matches[1];
5164
5165                    foreach ($parameters as $parameter) {
5166
5167                        if (in_array($parameter, $dateParameters)) {
5168                            if ($result[$i]->{$parameter}) {
5169                                $result[$i]->{$parameter} = iconv('ISO-8859-2', 'UTF-8', strftime('%A, %B %d, %Y', strtotime($result[$i]->{$parameter})));
5170                            }
5171                        }
5172
5173                        if (in_array($parameter, $availableParameters)) {
5174                            $subject = str_replace('{{'.$parameter.'}}', $result[$i]->{$parameter}, $subject);
5175                        }
5176                    }
5177
5178                    $email = new \SendGrid\Mail\Mail;
5179                    $templateFiles = TblEmailFiles::where('email_template_id', $emailTemplate[$result[$i]->company_id]->id)->orderBy('order', 'asc')->get();
5180
5181                    foreach ($templateFiles as $item) {
5182                        $f = storage_path('app/public/uploads/'.$item->filename);
5183
5184                        if (file_exists($f)) {
5185                            $imgpath = file_get_contents($f);
5186                            $base64 = 'data:image/png;base64,'.base64_encode($imgpath);
5187                            $mimeType = mime_content_type($f);
5188
5189                            $email->addAttachment(
5190                                $imgpath,
5191                                $mimeType,
5192                                str_replace(' ', '', $item->original_name),
5193                                'inline',
5194                                str_replace(' ', '', $item->original_name),
5195                            );
5196
5197                            $body .= "<img src='cid:{$item->original_name}' style='height: 45px; padding-right: 6px' />";
5198                        } else {
5199                            Log::channel('email_failed_log')->error('File not found: '.$f);
5200                        }
5201                    }
5202
5203                    $html = '<!DOCTYPE html>';
5204                    $html .= '<html>';
5205                    $html .= '<head>';
5206                    $html .= '<meta charset="UTF-8">';
5207                    $html .= '<meta name="viewport" content="width=device-width, initial-scale=1.0">';
5208                    $html .= '</head>';
5209                    $html .= '<body>';
5210                    $html .= $body;
5211                    $html .= '</body>';
5212                    $html .= '</html>';
5213
5214                    if ($toEmail != null) {
5215
5216                        $toEmail = explode(',', $toEmail);
5217                        $toEmail = array_map('trim', $toEmail);
5218
5219                        $companyEmail = null;
5220
5221                        $queryUsers = "SELECT sender_email AS from_email, `name` AS from_name FROM tbl_users WHERE sender_enabled = 1 AND response_id IS NOT NULL AND verified = 1 AND `name` = '{$commercialUser}'";
5222                        $commercialEmail = DB::select($queryUsers);
5223
5224                        if (count($commercialEmail) > 0) {
5225                            $companyEmail = $commercialEmail[0];
5226                        } else {
5227                            if ($emailTemplate[$result[$i]->company_id]->from_id != null) {
5228                                $companyEmail = TblCompanyEmails::where('id', $emailTemplate[$result[$i]->company_id]->from_id)->first();
5229                            } else {
5230                                $companyEmail = TblCompanyEmails::where('is_active', 1)->where('verified', 1)->where('company_id', $result[$i]->company_id)->first();
5231                            }
5232                        }
5233
5234                        if (! $companyEmail) {
5235                            return response(['message' => 'KO', 'error' => __('language.no_active_verified_sender')]);
5236                        }
5237
5238                        $ccBcc = TblCcBcc::where('company_id', $result[$i]->company_id)->get();
5239
5240                        $email->setFrom($companyEmail->from_email, $companyEmail->from_name);
5241                        $email->setSubject($subject);
5242
5243                        foreach ($toEmail as $clientEmail) {
5244                            $isValid = $this->isEmailValid($clientEmail);
5245                            if ($isValid) {
5246                                $email->addTo($clientEmail);
5247                            }
5248                        }
5249
5250                        if (env('SENDGRID_STAGING')) {
5251
5252                        } else {
5253                            if (! in_array($user->email, $toEmail)) {
5254                                $email->addCc($user->email);
5255                            }
5256
5257                            if (count($ccBcc) > 0) {
5258                                foreach ($ccBcc as $data) {
5259                                    if (! in_array($data->email, $toEmail) && $user->email != $data->email) {
5260                                        $email->addBcc($data->email);
5261                                    }
5262                                }
5263                            }
5264                        }
5265
5266                        $email->addContent('text/html', $html);
5267                        $sendgrid = new \SendGrid(env('SENDGRID_API_KEY'));
5268
5269                        $files = TblFiles::where('quotation_id', $result[$i]->id)->where('is_internal', null)->get();
5270                        $requestSize = $this->calculateEmailRequestSize($email);
5271
5272                        foreach ($files as $key => $value) {
5273                            $fileContent = null;
5274                            $fileSize = 0;
5275                            $fileName = null;
5276
5277                            if (Storage::disk('s3')->exists('uploads/'.$files[$key]->filename)) {
5278                                $fileContent = Storage::disk('s3')->get('uploads/'.$files[$key]->filename);
5279                                $fileSize = (int) ceil(strlen($fileContent) / 1048576);
5280                                $fileName = $files[$key]->original_name;
5281                            } elseif ($files[$key]->getAttribute('file')) {
5282                                $fileContent = $files[$key]->getAttribute('file');
5283
5284                                if (is_string($fileContent) && base64_decode($fileContent, true)) {
5285                                    $fileContent = base64_decode($fileContent);
5286                                }
5287
5288                                $fileSize = strlen($fileContent) / 1048576;
5289                                $fileSize = (int) ceil($fileSize);
5290                                $fileName = $files[$key]->original_name ?: $files[$key]->getAttribute('file_name') ?: 'file';
5291                            }
5292
5293                            if ($fileContent && $fileSize > 0) {
5294                                if ($requestSize + $fileSize < 25) {
5295                                    $attachment = new \SendGrid\Mail\Attachment;
5296                                    $attachment->setFilename($fileName);
5297                                    $attachment->setDisposition('attachment');
5298
5299                                    $attachment->setContent(base64_encode($fileContent));
5300
5301                                    $email->addAttachment($attachment);
5302                                    $requestSize = $this->calculateEmailRequestSize($email);
5303                                }
5304                            }
5305                        }
5306
5307                        $sentWithBackup = false;
5308                        $response = $sendgrid->send($email);
5309
5310                        if (env('SENDGRID_BLOCK') === true) {
5311
5312                            Log::warning("SendGrid failed with status {$response->statusCode()}. Initiating Failover...");
5313                            try {
5314                                \Illuminate\Support\Facades\Mail::mailer('resend')->send([], [], function ($message) use ($html, $companyEmail, $toEmail, $subject, $files, $user, $ccBcc) {
5315                                    $message->from($companyEmail->from_email, $companyEmail->from_name)
5316                                        ->to($toEmail)
5317                                        ->subject($subject);
5318
5319                                    $message->setBody($html, 'text/html');
5320
5321                                    $message->cc($user->email);
5322
5323                                    foreach ($ccBcc as $bcc) {
5324                                        $message->bcc($bcc->email);
5325                                    }
5326
5327                                    foreach ($files as $file) {
5328                                        if (Storage::disk('s3')->exists('uploads/'.$file->filename)) {
5329                                            $content = Storage::disk('s3')->get('uploads/'.$file->filename);
5330                                            $message->attachData($content, $file->original_name);
5331                                        } elseif ($file->file) {
5332                                            $content = $file->file;
5333                                            if (is_string($content) && base64_decode($content, true)) {
5334                                                $content = base64_decode($content);
5335                                            }
5336                                            $message->attachData($content, $file->original_name ?: 'archivo.pdf');
5337                                        }
5338                                    }
5339                                });
5340
5341                                $sentWithBackup = true;
5342                            } catch (\Exception $backupException) {
5343                                $sentWithBackup = false;
5344                                Log::error('Backup server also failed: '.$backupException->getMessage());
5345                            }
5346
5347                            if (! $sentWithBackup) {
5348                                throw new \Exception("SendGrid failed with status {$response->statusCode()}. Backup server also failed: ".$backupException->getMessage());
5349                            }
5350
5351                        }
5352
5353                        if (($response->statusCode() == 202 || $sentWithBackup) && ! env('SENDGRID_BLOCK')) {
5354                            $messageId = null;
5355
5356                            if ($response->headers()) {
5357                                foreach ($response->headers() as $header) {
5358                                    if (strpos(strtolower($header), 'x-message-id:') === 0) {
5359                                        $messageId = trim(substr($header, strpos($header, ':') + 1));
5360                                        break;
5361                                    }
5362                                }
5363                            }
5364
5365                            $sentItems[$result[$i]->company_id][] = $result[$i]->id;
5366
5367                            $comment = 'Se ha enviado la orden por correo electrónico manualmente al cliente el '.date('Y-m-d H:i:s').' por el usuario '.$user->name;
5368                            $result[$i]->last_follow_up_comment = $result[$i]->last_follow_up_comment."\n".$comment;
5369
5370                            TblQuotations::where('id', $result[$i]->id)->update(
5371                                [
5372                                    'last_follow_up_comment' => $result[$i]->last_follow_up_comment,
5373                                    'budget_status_id' => 2,
5374                                    'x_message_id' => $messageId,
5375                                    'x_status' => 'Processing',
5376                                    'updated_by' => $user->name,
5377                                    'updated_at' => date('Y-m-d H:i:s'),
5378                                ]
5379                            );
5380
5381                            $jsonBody = [];
5382
5383                            foreach ($toEmail as $clientEmail) {
5384                                $isValid = $this->isEmailValid($clientEmail);
5385                                $eventStatus = 'processed';
5386                                $eventResponse = '';
5387                                if (! $isValid) {
5388                                    $eventStatus = 'invalid';
5389                                    $eventResponse = 'Invalid email address';
5390                                }
5391
5392                                array_push(
5393                                    $jsonBody,
5394                                    [
5395                                        'email' => $clientEmail,
5396                                        'event' => $eventStatus,
5397                                        'sg_message_id' => $messageId,
5398                                        'smtp-id' => $messageId,
5399                                        'timestamp' => strtotime(date('Y-m-d H:i:s')),
5400                                        'response' => $eventResponse,
5401                                    ]
5402                                );
5403                            }
5404
5405                            TblSendgridWebhook::create(
5406                                [
5407                                    'quotation_id' => $result[$i]->id,
5408                                    'type' => 'sendToClient',
5409                                    'json_body' => json_encode($jsonBody),
5410                                    'x_message_id' => $messageId,
5411                                ]
5412                            );
5413
5414                            Log::channel('email_log')->info("[RS-{$requestSize}] ID:".$result[$i]->id.' - EMAIL MANUALLY SENT');
5415                            $this->addUpdateLog($result[$i]->id, $userId, 'send_email_to_client', null, null, 5);
5416                        } else {
5417                            $error = true;
5418                            Log::channel('email_failed_log')->error("[RS-{$requestSize}] ID:".$result[$i]->id.' - '.$response->body());
5419                        }
5420                    }
5421                }
5422            }
5423
5424            $this->update_commercial_numbers($companyId);
5425
5426            Cache::flush();
5427
5428            foreach ($sentItems as $k => $v) {
5429                $sentItems[$k] = [
5430                    'total' => count($sentItems[$k]),
5431                    'company' => $emailCompany[$k]->name,
5432                    'limit' => $emailCompany[$k]->limit_send,
5433                ];
5434            }
5435
5436            $totalSent = array_values($sentItems);
5437
5438            return response(['message' => 'OK', 'data' => $totalSent]);
5439
5440        } catch (\Exception $e) {
5441            /** @disregard P1014 */
5442            $e->exceptionCode = 'SEND_EMAIL_TO_CLIENT_EXCEPTION';
5443            report($e);
5444            Log::channel('email_failed_log')->error($e->getMessage());
5445
5446            return response(['message' => 'KO', 'error' => $e->getMessage()]);
5447        }
5448
5449    }
5450
5451    public function send_email_follow_ups(Request $request, $automaticSendLimit = null)
5452    {
5453
5454        $currentQuotationId = null;
5455        ini_set('max_execution_time', 0);
5456
5457        try {
5458
5459            $data = $request->all();
5460
5461            $startedAt = date('Y-m-d H:i:s');
5462            $toEmail = '';
5463            $userId = addslashes($data['user_id']);
5464            $companyId = addslashes($data['company_id']);
5465            $emailTemplateId = $data['email_template_id'];
5466            unset($data['email_template_id']);
5467
5468            $emailTemplates = [];
5469
5470            if (isset($data['html']) && ! empty($data['html'])) {
5471                $emailTemplates = array_column($data['html'], null, 'id');
5472            }
5473
5474            $emailTemplate = TblEmailConfiguration::whereIn('id', $emailTemplateId)->get()->keyBy('company_id');
5475
5476            $limit = 0;
5477
5478            $blockedDomains = [];
5479            $workingDays = 10;
5480            $limitReminderEmails = 3;
5481            $emailCompany = [];
5482
5483            $result = [];
5484
5485            if ($companyId == 0) {
5486                $indexes = $emailTemplate->keys();
5487
5488                $emailCompany = TblCompanies::whereIn('company_id', $indexes)->get()->keyBy('company_id');
5489
5490                foreach ($emailCompany as $item) {
5491                    $limit = 20;
5492
5493                    $r = new Request([
5494                        'filterModel' => $data['filterModel'],
5495                        'sortModel' => $data['sortModel'],
5496                        'start' => 0,
5497                        'end' => 999999999,
5498                        'company_id' => $data['company_id'],
5499                        'user_id' => $data['user_id'],
5500                        'ids' => $data['ids'],
5501                        'searchText' => $data['searchText'],
5502                        'ids_not_in' => $data['ids_not_in'],
5503                        'last_follow_up_date' => 1,
5504                    ]);
5505
5506                    if ($item->limit_send != null) {
5507                        $limit = $item->limit_send;
5508                    }
5509
5510                    $listQuotations = $this->list_quotations($r);
5511                    $d = $listQuotations->original['data'];
5512                    if ($automaticSendLimit != null) {
5513                        $limit = $automaticSendLimit;
5514                    }
5515
5516                    $l = 0;
5517                    for ($i = 0; $i < count($d); $i++) {
5518                        if ($d[$i]->email != null
5519                            && $d[$i]->budget_status_id == 2
5520                            && $d[$i]->reason_for_not_following_up_id == null
5521                            && $d[$i]->total_sent < $limitReminderEmails
5522                            && $d[$i]->last_follow_up_date != null
5523                            && $d[$i]->last_follow_up_date < date('Y-m-d H:i:s')
5524                            && $d[$i]->last_follow_up_date > 0
5525                            && $item->company_id == $d[$i]->company_id
5526                        ) {
5527
5528                            if ($l == $limit) {
5529                                break;
5530                            }
5531                            array_push($result, $d[$i]);
5532                            $l++;
5533                        }
5534                    }
5535
5536                }
5537            } else {
5538
5539                $emailCompany = TblCompanies::where('company_id', $companyId)->get()->keyBy('company_id');
5540                $workingDays = $emailCompany[$companyId]->last_follow_up_date ?? 10;
5541                $limitReminderEmails = $emailCompany[$companyId]->limit_reminder_emails ?? 3;
5542
5543                if ($emailCompany[$companyId]->limit_send != null) {
5544                    $limit = $emailCompany[$companyId]->limit_send;
5545                }
5546
5547                $r = new Request([
5548                    'filterModel' => $data['filterModel'],
5549                    'sortModel' => $data['sortModel'],
5550                    'start' => 0,
5551                    'end' => 999999999,
5552                    'company_id' => $data['company_id'],
5553                    'user_id' => $data['user_id'],
5554                    'ids' => $data['ids'],
5555                    'searchText' => $data['searchText'],
5556                    'ids_not_in' => $data['ids_not_in'],
5557                    'last_follow_up_date' => 1,
5558                ]);
5559
5560                $listQuotations = $this->list_quotations($r);
5561                $d = $listQuotations->original['data'];
5562
5563                if ($automaticSendLimit != null) {
5564                    $limit = $automaticSendLimit;
5565                }
5566
5567                $l = 0;
5568                for ($i = 0; $i < count($d); $i++) {
5569                    if ($d[$i]->email != null
5570                        && $d[$i]->budget_status_id == 2
5571                        && $d[$i]->reason_for_not_following_up_id == null
5572                        && $d[$i]->total_sent < $limitReminderEmails
5573                        && $d[$i]->last_follow_up_date != null
5574                        && $d[$i]->last_follow_up_date < date('Y-m-d H:i:s')
5575                        && $d[$i]->last_follow_up_date > 0
5576                    ) {
5577                        if ($l == $limit) {
5578                            break;
5579                        }
5580                        array_push($result, $d[$i]);
5581                        $l++;
5582                    }
5583                }
5584            }
5585
5586            if (count($result) == 0) {
5587                return response(['message' => 'OK']);
5588            }
5589
5590            $user = TblUsers::where('id', $userId)->first();
5591            $error = false;
5592
5593            $sentBy = $user->name;
5594
5595            $availableParameters = [
5596                'quote_id',
5597                'company_id',
5598                'client',
5599                'client_type',
5600                'phone_number',
5601                'email',
5602                'issue_date',
5603                'request_date',
5604                'duration',
5605                'invoice_number',
5606                'type',
5607                'acceptance_date',
5608                'status',
5609                'source',
5610                'amount',
5611                'reason_for_not_following_up',
5612                'last_follow_up_date',
5613                'last_follow_up_comment',
5614                'reason_for_rejection_id',
5615                'reason_for_rejection',
5616                'commercial',
5617                'created_at',
5618                'created_by',
5619                'updated_at',
5620                'updated_by',
5621            ];
5622
5623            $dateParameters = [
5624                'issue_date',
5625                'request_date',
5626                'acceptance_date',
5627                'last_follow_up_date',
5628                'created_at',
5629                'updated_at',
5630            ];
5631
5632            if ($this->locale == 'es') {
5633                setlocale(LC_ALL, 'es_ES', 'Spanish_Spain', 'Spanish');
5634            }
5635
5636            $totalSent = 0;
5637            $totalSentIds = [];
5638            $totalFailedIds = [];
5639            $totalErrorIds = [];
5640            $currentQuotationId = null;
5641
5642            $sentItems = [];
5643
5644            for ($i = 0; $i < count($result); $i++) {
5645                $budgetTypeId = $result[$i]->budget_type_id;
5646                $currentQuotationId = $result[$i]->quote_id;
5647                $body = $emailTemplate[$result[$i]->company_id]->html;
5648                if (isset($data['html']) && ! empty($data['html'])) {
5649                    $body = $emailTemplates[$result[$i]->company_id]['html'];
5650                }
5651                $subject = $emailTemplate[$result[$i]->company_id]->subject;
5652                $commercialUser = $result[$i]->commercial;
5653
5654                $blockedDomains = TblBlockedDomains::where('company_id', $result[$i]->company_id)->pluck('domain')->toArray();
5655
5656                if (env('SENDGRID_STAGING')) {
5657                    $toEmail = $user->email;
5658                } else {
5659                    $toEmail = $result[$i]->email;
5660                }
5661
5662                preg_match_all('/{{(.*?)}}/', $body, $matches);
5663
5664                $parameters = $matches[1];
5665
5666                foreach ($parameters as $parameter) {
5667
5668                    if (in_array($parameter, $dateParameters)) {
5669                        if ($result[$i]->{$parameter}) {
5670                            $result[$i]->{$parameter} = iconv('ISO-8859-2', 'UTF-8', strftime('%A, %B %d, %Y', strtotime($result[$i]->{$parameter})));
5671                        }
5672                    }
5673
5674                    if (in_array($parameter, $availableParameters)) {
5675                        $body = str_replace('{{'.$parameter.'}}', $result[$i]->{$parameter}, $body);
5676                    }
5677                }
5678
5679                preg_match_all('/{{(.*?)}}/', $subject, $matches);
5680
5681                $parameters = $matches[1];
5682
5683                foreach ($parameters as $parameter) {
5684
5685                    if (in_array($parameter, $dateParameters)) {
5686                        if ($result[$i]->{$parameter}) {
5687                            $result[$i]->{$parameter} = iconv('ISO-8859-2', 'UTF-8', strftime('%A, %B %d, %Y', strtotime($result[$i]->{$parameter})));
5688                        }
5689                    }
5690
5691                    if (in_array($parameter, $availableParameters)) {
5692                        $subject = str_replace('{{'.$parameter.'}}', $result[$i]->{$parameter}, $subject);
5693                    }
5694                }
5695
5696                $email = new \SendGrid\Mail\Mail;
5697
5698                $templateFiles = TblEmailFiles::where('email_template_id', $emailTemplate[$result[$i]->company_id]->id)->orderBy('order', 'asc')->get();
5699
5700                foreach ($templateFiles as $item) {
5701                    $f = storage_path('app/public/uploads/'.$item->filename);
5702
5703                    if (file_exists($f)) {
5704                        $imgpath = file_get_contents($f);
5705                        $base64 = 'data:image/png;base64,'.base64_encode($imgpath);
5706                        $mimeType = mime_content_type($f);
5707
5708                        $email->addAttachment(
5709                            $imgpath,
5710                            $mimeType,
5711                            str_replace(' ', '', $item->original_name),
5712                            'inline',
5713                            str_replace(' ', '', $item->original_name),
5714                        );
5715
5716                        $body .= "<img src='cid:{$item->original_name}' style='height: 45px; padding-right: 6px' />";
5717                    } else {
5718                        Log::channel('email_failed_log')->error('File not found: '.$f);
5719                    }
5720                }
5721
5722                $html = '<!DOCTYPE html>';
5723                $html .= '<html>';
5724                $html .= '<head>';
5725                $html .= '<meta charset="UTF-8">';
5726                $html .= '<meta name="viewport" content="width=device-width, initial-scale=1.0">';
5727                $html .= '</head>';
5728                $html .= '<body>';
5729                $html .= $body;
5730                $html .= '</body>';
5731                $html .= '</html>';
5732
5733                if ($automaticSendLimit != null) {
5734                    $sentBy = 'System';
5735                }
5736
5737                if ($toEmail != null) {
5738
5739                    $toEmail = explode(',', $toEmail);
5740                    $toEmail = array_map('trim', $toEmail);
5741
5742                    $companyEmail = null;
5743
5744                    $queryUsers = "SELECT sender_email AS from_email, `name` AS from_name FROM tbl_users WHERE sender_enabled = 1 AND response_id IS NOT NULL AND verified = 1 AND `name` = '{$commercialUser}'";
5745                    $commercialEmail = DB::select($queryUsers);
5746
5747                    if (count($commercialEmail) > 0) {
5748                        $companyEmail = $commercialEmail[0];
5749                    } else {
5750                        if ($emailTemplate[$result[$i]->company_id]->from_id != null) {
5751                            $companyEmail = TblCompanyEmails::where('id', $emailTemplate[$result[$i]->company_id]->from_id)->first();
5752                        } else {
5753                            $companyEmail = TblCompanyEmails::where('is_active', 1)->where('verified', 1)->where('company_id', $result[$i]->company_id)->first();
5754                        }
5755                    }
5756
5757                    if (! $companyEmail) {
5758                        return response(['message' => 'KO', 'error' => __('language.no_active_verified_sender')]);
5759                    }
5760
5761                    $ccBcc = TblCcBcc::where('company_id', $result[$i]->company_id)->get();
5762
5763                    $email->setFrom($companyEmail->from_email, $companyEmail->from_name);
5764                    $email->setSubject($subject);
5765
5766                    $s = 0;
5767                    $addTo = [];
5768                    foreach ($toEmail as $clientEmail) {
5769                        $isValid = $this->isEmailValid($clientEmail);
5770                        if ($isValid) {
5771                            $domain = substr($clientEmail, strpos($clientEmail, '@') + 1);
5772
5773                            if (! in_array($domain, $blockedDomains)) {
5774                                $email->addTo($clientEmail);
5775                                array_push($addTo, $clientEmail);
5776                                $s++;
5777                            }
5778                        } else {
5779                            TblFollowUpLogs::create(
5780                                [
5781                                    'quotation_id' => $result[$i]->id,
5782                                    'email' => $clientEmail,
5783                                    'sent_by' => $sentBy,
5784                                    'status' => 'Invalid email',
5785                                ]
5786                            );
5787                        }
5788                    }
5789
5790                    if ($s == 0) {
5791                        array_push($totalFailedIds, $result[$i]->id);
5792                        Log::channel('email_failed_log')->error($s.'ID:'.$result[$i]->id.' - '.json_encode($toEmail));
5793
5794                        continue;
5795                    }
5796
5797                    if (env('SENDGRID_STAGING')) {
5798
5799                    } else {
5800                        if (count($ccBcc) > 0) {
5801                            foreach ($ccBcc as $data) {
5802                                if (! in_array($data->email, $toEmail)) {
5803                                    $email->addBcc($data->email);
5804                                }
5805                            }
5806                        }
5807                    }
5808
5809                    $email->addContent('text/html', $html);
5810
5811                    $sendgrid = new \SendGrid(env('SENDGRID_API_KEY'));
5812
5813                    $files = TblFiles::where('quotation_id', $result[$i]->id)->where('is_internal', null)->get();
5814                    $requestSize = $this->calculateEmailRequestSize($email);
5815
5816                    foreach ($files as $key => $value) {
5817                        if ($files[$key]->filename && Storage::disk('s3')->exists('uploads/'.$files[$key]->filename)) {
5818
5819                            $fileContent = Storage::disk('s3')->get('uploads/'.$files[$key]->filename);
5820                            $fileSize = strlen($fileContent) / 1048576;
5821                            $fileSize = (int) ceil($fileSize);
5822
5823                            $originalName = $files[$key]->original_name ?: basename($files[$key]->filename);
5824                        } elseif ($files[$key]->getAttribute('file')) {
5825                            $fileContent = $files[$key]->getAttribute('file');
5826
5827                            if (is_string($fileContent) && base64_decode($fileContent, true)) {
5828                                $fileContent = base64_decode($fileContent);
5829                            }
5830
5831                            $fileSize = strlen($fileContent) / 1048576;
5832                            $fileSize = (int) ceil($fileSize);
5833
5834                            $originalName = $files[$key]->original_name ?: ($files[$key]->getAttribute('file_name') ?: 'file');
5835                        } else {
5836                            continue;
5837                        }
5838
5839                        if ($fileSize > 0) {
5840                            if ($requestSize + $fileSize < 25) {
5841                                $attachment = new \SendGrid\Mail\Attachment;
5842                                $attachment->setFilename($originalName);
5843                                $attachment->setDisposition('attachment');
5844
5845                                $attachment->setContent(base64_encode($fileContent));
5846
5847                                if ($files[$key]->mime_type) {
5848                                    $attachment->setType($files[$key]->mime_type);
5849                                }
5850
5851                                $email->addAttachment($attachment);
5852                                $requestSize = $this->calculateEmailRequestSize($email);
5853                            } else {
5854                                Log::warning('File omitted due to size limit: '.$originalName);
5855                            }
5856                        }
5857                    }
5858
5859                    $sentWithBackup = false;
5860                    $response = $sendgrid->send($email);
5861
5862                    if (env('SENDGRID_BLOCK') === true) {
5863
5864                        Log::warning("SendGrid failed with status {$response->statusCode()}. Initiating Failover...");
5865                        try {
5866                            \Illuminate\Support\Facades\Mail::mailer('smtp_backup')->send([], [], function ($message) use ($html, $companyEmail, $toEmail, $subject, $files, $user, $ccBcc) {
5867                                $message->from($companyEmail->from_email, $companyEmail->from_name)
5868                                    ->to($toEmail)
5869                                    ->subject($subject);
5870
5871                                $message->setBody($html, 'text/html');
5872
5873                                $message->cc($user->email);
5874
5875                                foreach ($ccBcc as $bcc) {
5876                                    $message->bcc($bcc->email);
5877                                }
5878
5879                                foreach ($files as $file) {
5880                                    if (Storage::disk('s3')->exists('uploads/'.$file->filename)) {
5881                                        $content = Storage::disk('s3')->get('uploads/'.$file->filename);
5882                                        $message->attachData($content, $file->original_name);
5883                                    } elseif ($file->file) {
5884                                        $content = $file->file;
5885                                        if (is_string($content) && base64_decode($content, true)) {
5886                                            $content = base64_decode($content);
5887                                        }
5888                                        $message->attachData($content, $file->original_name ?: 'archivo.pdf');
5889                                    }
5890                                }
5891                            });
5892
5893                            $sentWithBackup = true;
5894                        } catch (\Exception $backupException) {
5895                            $sentWithBackup = false;
5896                            Log::error('Backup server also failed: '.$backupException->getMessage());
5897                        }
5898
5899                        if (! $sentWithBackup) {
5900                            throw new \Exception("SendGrid failed with status {$response->statusCode()}. Backup server also failed: ".$backupException->getMessage());
5901                        }
5902
5903                    }
5904
5905                    if (($response->statusCode() == 202 || $sentWithBackup) && ! env('SENDGRID_BLOCK')) {
5906
5907                        $messageId = null;
5908
5909                        foreach ($response->headers() as $header) {
5910                            if (strpos(strtolower($header), 'x-message-id:') === 0) {
5911                                $messageId = trim(substr($header, strpos($header, ':') + 1));
5912                                break;
5913                            }
5914                        }
5915
5916                        $lastFollowUp = TblLastFollowUpDate::where('company_id', $companyId)->where('budget_type_id', $budgetTypeId)->first();
5917                        $workingDaysN = $workingDays;
5918
5919                        if ($companyId == 0) {
5920                            $workingDaysN = $emailCompany[$result[$i]->company_id]->last_follow_up_date ?? 10;
5921                        }
5922
5923                        if ($lastFollowUp != null) {
5924                            if ($lastFollowUp->last_follow_up_date) {
5925                                $workingDaysN = $lastFollowUp->last_follow_up_date;
5926                            }
5927                        }
5928
5929                        $comment = 'Email automático enviado el '.date('Y-m-d H:i:s').' por usuario '.$sentBy;
5930                        $result[$i]->last_follow_up_comment = $result[$i]->last_follow_up_comment."\n".$comment;
5931                        $date = strtotime("{$workingDaysN} weekdays");
5932                        $result[$i]->last_follow_up_date = date('Y-m-d H:i:s', $date);
5933                        $totalSentQ = $result[$i]->total_sent + 1;
5934
5935                        array_push($totalSentIds, $result[$i]->id);
5936                        $sentItems[$result[$i]->company_id][] = $result[$i]->id;
5937
5938                        foreach ($addTo as $addToEmail) {
5939                            TblFollowUpLogs::create(
5940                                [
5941                                    'quotation_id' => $result[$i]->id,
5942                                    'email' => $addToEmail,
5943                                    'sent_by' => $sentBy,
5944                                    'status' => 'OK',
5945                                ]
5946                            );
5947                            $this->addUpdateLog($result[$i]->id, $userId, 'send_email_follow_up', null, null, 5);
5948                        }
5949
5950                        if ($totalSentQ >= $limitReminderEmails) {
5951                            $result[$i]->reason_for_not_following_up_id = 3;
5952                            $result[$i]->last_follow_up_date = null;
5953                        }
5954
5955                        TblQuotations::where('id', $result[$i]->id)->update(
5956                            [
5957                                'last_follow_up_comment' => $result[$i]->last_follow_up_comment,
5958                                'last_follow_up_date' => $result[$i]->last_follow_up_date,
5959                                'total_sent' => $result[$i]->total_sent + 1,
5960                                'y_message_id' => $messageId,
5961                                'y_status' => 'Processing',
5962                                'reason_for_not_following_up_id' => $result[$i]->reason_for_not_following_up_id,
5963                                'updated_by' => $sentBy,
5964                                'updated_at' => date('Y-m-d H:i:s'),
5965                            ]
5966                        );
5967
5968                        $jsonBody = [];
5969
5970                        foreach ($toEmail as $clientEmail) {
5971                            $isValid = $this->isEmailValid($clientEmail);
5972                            $eventStatus = 'processed';
5973                            $eventResponse = '';
5974                            if (! $isValid) {
5975                                $eventStatus = 'invalid';
5976                                $eventResponse = 'Invalid email address';
5977                            }
5978
5979                            array_push(
5980                                $jsonBody,
5981                                [
5982                                    'email' => $clientEmail,
5983                                    'event' => $eventStatus,
5984                                    'sg_message_id' => $messageId,
5985                                    'smtp-id' => $messageId,
5986                                    'timestamp' => strtotime(date('Y-m-d H:i:s')),
5987                                    'response' => $eventResponse,
5988                                ]
5989                            );
5990                        }
5991
5992                        TblSendgridWebhook::create(
5993                            [
5994                                'quotation_id' => $result[$i]->id,
5995                                'type' => 'followUps',
5996                                'json_body' => json_encode($jsonBody),
5997                                'x_message_id' => $messageId,
5998                            ]
5999                        );
6000
6001                        Log::channel('email_log')->info("[RS-{$requestSize}] ID:".$result[$i]->id.' - EMAIL SENT');
6002                        $totalSent++;
6003                        $workingDays = 10;
6004                    } else {
6005                        $error = true;
6006                        array_push($totalErrorIds, $result[$i]->id);
6007                        Log::channel('email_failed_log')->error("[RS-{$requestSize}] ID:".$result[$i]->id.' - '.$response->body());
6008
6009                        foreach ($addTo as $addToEmail) {
6010                            TblFollowUpLogs::create(
6011                                [
6012                                    'quotation_id' => $result[$i]->id,
6013                                    'email' => $addToEmail,
6014                                    'sent_by' => $sentBy,
6015                                    'status' => $response->body(),
6016                                ]
6017                            );
6018                        }
6019                    }
6020
6021                    $body = '';
6022                    $subject = '';
6023                }
6024            }
6025
6026            Cache::flush();
6027
6028            Log::channel('send_email_follow_ups')->info(
6029                json_encode(
6030                    [
6031                        'success' => $totalSentIds,
6032                        'failed' => $totalFailedIds,
6033                        'error' => $totalErrorIds,
6034                    ]
6035                )
6036            );
6037
6038            $this->update_commercial_numbers($companyId);
6039
6040            if ($error) {
6041                return response(['message' => 'KO']);
6042            } else {
6043
6044                if ($automaticSendLimit != null) {
6045                    TblOrdersUpdateLogs::create(
6046                        [
6047                            'company_id' => $companyId,
6048                            'to_process' => 'Orders',
6049                            'status' => 'success',
6050                            'follow_ups_affected_rows' => $totalSent,
6051                            'processed_by' => $sentBy,
6052                            'started_at' => $startedAt,
6053                            'ended_at' => date('Y-m-d H:i:s'),
6054                        ]
6055                    );
6056                }
6057
6058                foreach ($sentItems as $k => $v) {
6059                    $sentItems[$k] = [
6060                        'total' => count($sentItems[$k]),
6061                        'company' => $emailCompany[$k]->name,
6062                        'limit' => $emailCompany[$k]->limit_send,
6063                    ];
6064                }
6065
6066                $totalSent = array_values($sentItems);
6067
6068                return response(['message' => 'OK', 'data' => $totalSent]);
6069            }
6070
6071        } catch (\Throwable $e) {
6072            /** @disregard P1014 */
6073            $e->exceptionCode = 'SEND_EMAIL_FOLLOW_UPS_EXCEPTION';
6074            report($e);
6075            Log::channel('email_failed_log')->error($e->getMessage());
6076
6077            return response(['message' => 'KO', 'error' => $e->getMessage(), 'quotation_id' => $currentQuotationId]);
6078        }
6079    }
6080
6081    public function create_sender_identity(Request $request)
6082    {
6083
6084        $data = $request->all();
6085        try {
6086
6087            $sData = $data;
6088            $companyId = $data['company_id'];
6089            $createdBy = $data['created_by'];
6090            unset($data['company_id']);
6091            unset($data['created_by']);
6092
6093            $sender = TblCompanyEmails::where('from_email', $data['from_email'])->where('verified', 1)->count();
6094
6095            if ($sender > 0) {
6096                TblCompanyEmails::create($sData);
6097
6098                return response(['message' => 'OK', 'data' => $data, 'is_verified' => 'yes']);
6099            }
6100
6101            $sendgrid = new \SendGrid(env('SENDGRID_API_KEY'));
6102            $data['reply_to'] = $data['from_email'];
6103            $data['reply_to_name'] = $data['from_name'];
6104            $requestBody = $data;
6105            $error = false;
6106
6107            // @phpstan-ignore-next-line
6108            $response = $sendgrid->client->verified_senders()->post($requestBody);
6109
6110            $x = json_decode($response->body());
6111
6112            if ($response->statusCode() == 201 || is_numeric(@$x->id)) {
6113
6114                $data['company_id'] = $companyId;
6115                $data['created_by'] = $createdBy;
6116                $data['response_id'] = $x->id;
6117                TblCompanyEmails::create($data);
6118                Log::channel('email_log')->info('EMAIL: '.$data['from_email'].' - VERIFICATION SENT');
6119            } else {
6120                $error = true;
6121                Log::channel('email_log')->error('REQUEST BODY: - '.$response->body());
6122            }
6123
6124            $response = json_decode($response->body());
6125
6126            if ($error) {
6127                if ($response->errors[0]->message == 'already exists' && $response->errors[0]->field == 'from_email') {
6128                    TblCompanyEmails::create($sData);
6129
6130                    return response(['message' => 'OK', 'data' => $data, 'is_verified' => 'yes']);
6131                }
6132
6133                $errMessage = $response->errors[0]->field.': '.$response->errors[0]->message;
6134
6135                return response(['message' => 'KO', 'error' => $errMessage]);
6136            } else {
6137                return response(['message' => 'OK', 'data' => $response, 'is_verified' => 'no']);
6138            }
6139
6140        } catch (\Exception $e) {
6141            /** @disregard P1014 */
6142            $e->exceptionCode = 'CREATE_SENDER_IDENTITY_EXCEPTION';
6143            report($e);
6144            Log::channel('email_log')->error('EMAIL:'.$data['from_email'].' - '.$e->getMessage());
6145
6146            return response(['message' => 'KO', 'error' => $e->getMessage()]);
6147        }
6148    }
6149
6150    public function get_sender_identity($companyId)
6151    {
6152
6153        try {
6154
6155            $companyId = intval($companyId);
6156
6157            $sendgrid = new \SendGrid(env('SENDGRID_API_KEY'));
6158
6159            // @phpstan-ignore-next-line
6160            $response = $sendgrid->client->verified_senders()->get();
6161
6162            if ($response->statusCode() == 200) {
6163                $x = json_decode($response->body())->results;
6164
6165                foreach ($x as $item) {
6166                    TblCompanyEmails::where('from_email', $item->from_email)->update([
6167                        'verified' => $item->verified,
6168                        'reply_to' => $item->reply_to,
6169                        'response_id' => $item->id,
6170                    ]);
6171                }
6172            }
6173
6174            $companyEmails = TblCompanyEmails::where('company_id', $companyId)->get();
6175
6176            return response(['message' => 'OK', 'data' => $companyEmails]);
6177
6178        } catch (\Exception $e) {
6179            /** @disregard P1014 */
6180            $e->exceptionCode = 'GET_SENDER_IDENTITY_EXCEPTION';
6181            report($e);
6182
6183            return response(['message' => 'KO', 'error' => $e->getMessage()]);
6184        }
6185    }
6186
6187    public function get_all_sender_identity($companyId)
6188    {
6189
6190        try {
6191
6192            $companyId = intval($companyId);
6193
6194            $query = "SELECT
6195                        id,
6196                        response_id,
6197                        nickname,
6198                        CONCAT(nickname, ' - ', from_email) from_email,
6199                        from_name,
6200                        reply_to,
6201                        reply_to_name,
6202                        address,
6203                        address2,
6204                        state,
6205                        city,
6206                        country,
6207                        zip,
6208                        verified,
6209                        locked,
6210                        is_active,
6211                        created_by,
6212                        created_at,
6213                        updated_by,
6214                        updated_at
6215                    FROM
6216                        tbl_company_emails
6217                    WHERE
6218                        company_id != {$companyId}
6219                        AND from_email NOT IN (
6220                        SELECT
6221                            from_email
6222                        FROM
6223                            tbl_company_emails
6224                        WHERE
6225                            company_id = {$companyId}
6226                        )
6227                    ";
6228
6229            $companyEmails = DB::select($query);
6230
6231            return response(['message' => 'OK', 'data' => $companyEmails]);
6232
6233        } catch (\Exception $e) {
6234            /** @disregard P1014 */
6235            $e->exceptionCode = 'GET_ALL_SENDER_IDENTITY_EXCEPTION';
6236            report($e);
6237
6238            return response(['message' => 'KO', 'error' => $e->getMessage()]);
6239        }
6240    }
6241
6242    public function delete_sender_identity(Request $request)
6243    {
6244
6245        try {
6246
6247            $data = $request->all();
6248            $responseId = addslashes($data['response_id']);
6249            $id = addslashes($data['id']);
6250
6251            $sender = TblCompanyEmails::where('response_id', $responseId)->count();
6252
6253            if ($sender > 1) {
6254                TblCompanyEmails::where('id', $id)->delete();
6255            } else {
6256                $sendgrid = new \SendGrid(env('SENDGRID_API_KEY'));
6257
6258                $response = $sendgrid->client->verified_senders()->_($responseId)->delete();
6259
6260                if ($response->statusCode() == 204) {
6261                    TblCompanyEmails::where('response_id', $responseId)->delete();
6262                }
6263            }
6264
6265            return response(['message' => 'OK']);
6266
6267        } catch (\Exception $e) {
6268            /** @disregard P1014 */
6269            $e->exceptionCode = 'DELETE_SENDER_IDENTITY_EXCEPTION';
6270            report($e);
6271
6272            return response(['message' => 'KO', 'error' => $e->getMessage()]);
6273        }
6274    }
6275
6276    public function create_template(Request $request)
6277    {
6278
6279        try {
6280
6281            $data = $request->all();
6282
6283            $files = $request->file('files');
6284            unset($data['files']);
6285
6286            if ($files) {
6287                $totalFileCount = count($files);
6288                if ($totalFileCount > 2) {
6289                    return response(['message' => 'KO', 'error' => __('language.file_count_exceeded')]);
6290                }
6291            }
6292
6293            $result = TblEmailConfiguration::create($data);
6294            $id = $result->id;
6295
6296            $directory = 'public/uploads';
6297            $origFilename = 'fireservicetitan.png';
6298            $file = 'public/uploads/fireservicetitan.png';
6299
6300            $sourcePath = public_path($origFilename);
6301            $destinationPath = 'public/uploads/'.$origFilename;
6302
6303            $filename = $id.'-EI'.time().'-'.$origFilename;
6304
6305            Storage::putFileAs($directory, new \Illuminate\Http\File($sourcePath), $filename);
6306            Storage::disk('google')->put($filename, file_get_contents(storage_path().'/app/public/uploads/'.$filename));
6307
6308            TblEmailFiles::create(
6309                [
6310                    'email_template_id' => $id,
6311                    'original_name' => $origFilename,
6312                    'filename' => $filename,
6313                    'uploaded_by' => $data['created_by'],
6314                ]
6315            );
6316
6317            if ($files) {
6318
6319                $uploadedFiles = [];
6320                $i = 0;
6321
6322                $combinedFilesSize = 0;
6323
6324                foreach ($files as $file) {
6325                    $i++;
6326
6327                    $origFilename = str_replace(' ', '', $file->getClientOriginalName());
6328
6329                    $filename = $id.'-EI'.time().'-'.$origFilename;
6330
6331                    $combinedFilesSize = $combinedFilesSize + $file->getSize();
6332
6333                    if ($combinedFilesSize > 25000000) {
6334                        return response(['message' => 'KO', 'error' => __('language.file_size_exceeded')]);
6335                    }
6336
6337                    Storage::putFileAs($directory, $file, $filename);
6338                    Storage::disk('google')->put($filename, file_get_contents(storage_path().'/app/public/uploads/'.$filename));
6339
6340                    if (in_array($origFilename, $uploadedFiles)) {
6341                        $origFilename = $origFilename.$i;
6342                    }
6343
6344                    TblEmailFiles::create(
6345                        [
6346                            'email_template_id' => $id,
6347                            'original_name' => $origFilename,
6348                            'filename' => $filename,
6349                            'uploaded_by' => $data['created_by'],
6350                        ]
6351                    );
6352
6353                    $uploadedFiles[] = $file->getClientOriginalName();
6354                }
6355            }
6356
6357            return response(['message' => 'OK']);
6358
6359        } catch (\Exception $e) {
6360            /** @disregard P1014 */
6361            $e->exceptionCode = 'CREATE_TEMPLATE_EXCEPTION';
6362            report($e);
6363
6364            return response(['message' => 'KO', 'error' => $e->getMessage()]);
6365        }
6366    }
6367
6368    public function get_email_files($emailTemplateId)
6369    {
6370
6371        try {
6372
6373            $emailTemplateId = addslashes($emailTemplateId);
6374
6375            $result = TblEmailFiles::where('email_template_id', $emailTemplateId)->orderBy('order', 'asc')->get();
6376
6377            foreach ($result as $key => $value) {
6378                $path = storage_path('app/public/uploads/'.$result[$key]->filename);
6379
6380                if (File::exists($path)) {
6381                    $fileSizeBytes = File::size($path);
6382                    $result[$key]->setAttribute('filesize', $this->human_filesize($fileSizeBytes));
6383                    $result[$key]->original_name = $result[$key]->original_name." ({$result[$key]->getAttribute('filesize')})";
6384                    $result[$key]->setAttribute('img', 'data:image/png;base64,'.base64_encode(file_get_contents($path)));
6385                }
6386            }
6387
6388            return response(['message' => 'OK', 'data' => $result]);
6389
6390        } catch (\Exception $e) {
6391            /** @disregard P1014 */
6392            $e->exceptionCode = 'GET_EMAIL_FILES_EXCEPTION';
6393            report($e);
6394
6395            return response(['message' => 'KO', 'error' => $e->getMessage()]);
6396        }
6397    }
6398
6399    public function download_email_template_file($fileId)
6400    {
6401
6402        try {
6403
6404            $fileId = addslashes($fileId);
6405
6406            $result = TblEmailFiles::where('file_id', $fileId)->first();
6407
6408            if ($result) {
6409                $path = storage_path('app/public/uploads/'.$result->filename);
6410
6411                if (! Storage::disk('public')->exists('uploads/'.$result->filename)) {
6412                    return response(['message' => 'KO']);
6413                }
6414
6415                return response()->download($path);
6416            }
6417
6418            return response(['message' => 'KO']);
6419
6420        } catch (\Exception $e) {
6421            /** @disregard P1014 */
6422            $e->exceptionCode = 'DOWNLOAD_EMAIL_TEMPLATE_FILE_EXCEPTION';
6423            report($e);
6424
6425            return response(['message' => 'KO', 'error' => $e->getMessage()]);
6426        }
6427
6428    }
6429
6430    public function delete_email_template_file($fileId)
6431    {
6432
6433        try {
6434
6435            $fileId = addslashes($fileId);
6436            $file = TblEmailFiles::where('file_id', $fileId)->first();
6437            $result = TblEmailFiles::where('file_id', $fileId)->first();
6438
6439            if ($result) {
6440                TblEmailFiles::where('file_id', $fileId)->delete();
6441                $path = storage_path('app/public/uploads/'.$result->filename);
6442                Storage::disk('public')->delete('uploads/'.$result->filename);
6443            }
6444
6445            return response(['message' => 'OK']);
6446
6447        } catch (\Exception $e) {
6448            /** @disregard P1014 */
6449            $e->exceptionCode = 'DELETE_EMAIL_TEMPLATE_FILE_EXCEPTION';
6450            report($e);
6451
6452            return response(['message' => 'KO', 'error' => $e->getMessage()]);
6453        }
6454    }
6455
6456    public function update_email_template_order(Request $request, $id)
6457    {
6458
6459        try {
6460
6461            $id = intval($id);
6462            $data = $request->all();
6463
6464            foreach ($data as $item) {
6465                TblEmailFiles::where('file_id', $item['file_id'])->update(['order' => $item['order']]);
6466            }
6467
6468        } catch (\Exception $e) {
6469            /** @disregard P1014 */
6470            $e->exceptionCode = 'UPDATE_EMAIL_TEMPLATE_ORDER_EXCEPTION';
6471            report($e);
6472
6473            return response(['message' => 'KO', 'error' => $e->getMessage()]);
6474        }
6475
6476    }
6477
6478    public function update_email_template(Request $request, $id)
6479    {
6480
6481        try {
6482
6483            $data = $request->all();
6484
6485            $id = intval($id);
6486
6487            $files = $request->file('files');
6488            unset($data['files']);
6489
6490            $fileCount = TblEmailFiles::where('email_template_id', $id)->count();
6491
6492            if ($files) {
6493                $totalFileCount = $fileCount + count($files);
6494                if ($totalFileCount > 3) {
6495                    return response(['message' => 'KO', 'error' => __('language.file_count_exceeded')]);
6496                }
6497            }
6498
6499            if (isset($data['cron_default'])) {
6500                TblEmailConfiguration::where('company_id', $data['company_id'])->where('cron_default', 1)->update(['cron_default' => 0]);
6501            }
6502
6503            $data['updated_at'] = date('Y-m-d H:i:s');
6504            TblEmailConfiguration::where('id', $id)->update($data);
6505
6506            if ($files) {
6507
6508                $directory = 'public/uploads';
6509                $uploadedFiles = [];
6510                $i = 0;
6511
6512                $combinedFilesSize = 0;
6513                foreach ($files as $file) {
6514                    $i++;
6515                    $origFilename = str_replace(' ', '', $file->getClientOriginalName());
6516                    $filename = $id.'-EI'.time().'-'.$origFilename;
6517
6518                    $combinedFilesSize = $combinedFilesSize + $file->getSize();
6519
6520                    if ($combinedFilesSize > 25000000) {
6521                        return response(['message' => 'KO', 'error' => __('language.file_size_exceeded')]);
6522                    }
6523
6524                    Storage::putFileAs($directory, $file, $filename);
6525                    Storage::disk('google')->put($filename, file_get_contents(storage_path().'/app/public/uploads/'.$filename));
6526
6527                    if (in_array($origFilename, $uploadedFiles)) {
6528                        $origFilename = $origFilename.$i;
6529                    }
6530
6531                    TblEmailFiles::create(
6532                        [
6533                            'email_template_id' => $id,
6534                            'original_name' => $origFilename,
6535                            'filename' => $filename,
6536                            'uploaded_by' => $data['updated_by'],
6537                        ]
6538                    );
6539
6540                    $uploadedFiles[] = $file->getClientOriginalName();
6541                }
6542            }
6543
6544            return response(['message' => 'OK']);
6545
6546        } catch (\Exception $e) {
6547            /** @disregard P1014 */
6548            $e->exceptionCode = 'UPDATE_EMAIL_TEMPLATE_EXCEPTION';
6549            report($e);
6550
6551            return response(['message' => 'KO', 'error' => $e->getMessage()]);
6552        }
6553
6554    }
6555
6556    public function delete_template($id)
6557    {
6558
6559        try {
6560
6561            $id = intval($id);
6562
6563            TblEmailConfiguration::where('id', $id)->delete();
6564
6565            return response(['message' => 'OK']);
6566
6567        } catch (\Exception $e) {
6568            /** @disregard P1014 */
6569            $e->exceptionCode = 'DELETE_TEMPLATE_EXCEPTION';
6570            report($e);
6571
6572            return response(['message' => 'KO', 'error' => $e->getMessage()]);
6573        }
6574
6575    }
6576
6577    public function get_email_template($companyId)
6578    {
6579
6580        try {
6581
6582            $companyId = intval($companyId);
6583
6584            $where = '';
6585            if ($companyId != 0) {
6586                $where = " a.company_id = {$companyId} ";
6587            } else {
6588                $where = " a.company_id IN ({$this->companyId}";
6589            }
6590
6591            $query = "SELECT
6592                        a.id,
6593                        a.from_id,
6594                        CASE
6595                            WHEN a.type = 'followUps' THEN 'Follow-ups'
6596                            WHEN a.type = 'sendToClient' THEN 'Send to client'
6597                        END types,
6598                        (SELECT from_email FROM tbl_company_emails WHERE id = a.from_id) from_email,
6599                        a.name,
6600                        b.name company_name,
6601                        b.company_id,
6602                        a.subject,
6603                        a.html,
6604                        a.is_active,
6605                        a.type,
6606                        a.created_by,
6607                        a.created_at,
6608                        a.updated_by,
6609                        a.updated_at,
6610                        a.cron_default
6611                    FROM tbl_email_configuration a
6612                    LEFT JOIN tbl_companies b
6613                        ON b.company_id = a.company_id
6614                    WHERE {$where}
6615                    ORDER BY a.id DESC";
6616
6617            $result = DB::select($query);
6618
6619            return response(['message' => 'OK', 'data' => $result]);
6620
6621        } catch (\Exception $e) {
6622            /** @disregard P1014 */
6623            $e->exceptionCode = 'GET_EMAIL_TEMPLATE_EXCEPTION';
6624            report($e);
6625
6626            return response(['message' => 'KO', 'error' => $e->getMessage()]);
6627        }
6628
6629    }
6630
6631    public function update_sender_identity(Request $request, $responseId)
6632    {
6633
6634        try {
6635
6636            $data = $request->all();
6637            $companyId = $data['company_id'];
6638            $updatedBy = $data['updated_by'];
6639            $active = $data['is_active'];
6640            $id = addslashes($data['id']);
6641            unset($data['id']);
6642            unset($data['company_id']);
6643            unset($data['updated_by']);
6644            unset($data['is_active']);
6645
6646            $sendgrid = new \SendGrid(env('SENDGRID_API_KEY'));
6647            $data['reply_to'] = $data['from_email'];
6648            $data['reply_to_name'] = $data['from_name'];
6649            $requestBody = $data;
6650            $error = false;
6651
6652            $response = $sendgrid->client->verified_senders()->_($responseId)->patch($requestBody);
6653
6654            if ($response->statusCode() == 200) {
6655                $x = json_decode($response->body());
6656
6657                $data['updated_by'] = $updatedBy;
6658                $data['updated_at'] = date('Y-m-d H:i:s');
6659                $data['is_active'] = $active;
6660
6661                TblCompanyEmails::where('company_id', $companyId)->update(['is_active' => 0]);
6662                TblCompanyEmails::where('id', $id)->update($data);
6663
6664                Log::channel('email_log')->info('EMAIL: '.$data['from_email'].' - UPDATED');
6665            } else {
6666                $error = true;
6667                Log::channel('email_log')->error('REQUEST BODY: - '.$response->body());
6668            }
6669
6670            $response = json_decode($response->body());
6671
6672            if ($error) {
6673                $errMessage = @$response->errors[0]->field.': '.@$response->errors[0]->message;
6674
6675                return response(['message' => 'KO', 'error' => $errMessage]);
6676            } else {
6677                return response(['message' => 'OK', 'data' => $response]);
6678            }
6679
6680        } catch (\Exception $e) {
6681            /** @disregard P1014 */
6682            $e->exceptionCode = 'UPDATE_SENDER_IDENTITY_EXCEPTION';
6683            report($e);
6684
6685            return response(['message' => 'KO', 'error' => $e->getMessage()]);
6686        }
6687
6688    }
6689
6690    public function resend_verification($id)
6691    {
6692
6693        try {
6694
6695            $id = intval($id);
6696
6697            $sendgrid = new \SendGrid(env('SENDGRID_API_KEY'));
6698
6699            $response = $sendgrid->client->verified_senders()->resend()->_($id)->post();
6700
6701            if ($response->statusCode() == 204) {
6702                return response(['message' => 'OK']);
6703            } else {
6704                $response = json_decode($response->body());
6705                $errMessage = $response->errors[0]->error_id.': '.$response->errors[0]->message;
6706
6707                return response(['message' => 'KO', 'error' => $errMessage]);
6708            }
6709
6710        } catch (\Exception $e) {
6711            /** @disregard P1014 */
6712            $e->exceptionCode = 'RESEND_VERIFICATION_EXCEPTION';
6713            report($e);
6714
6715            return response(['message' => 'KO', 'error' => $e->getMessage()]);
6716        }
6717    }
6718
6719    public function list_quotation_analytics_by_performance(Request $request)
6720    {
6721
6722        try {
6723
6724            $data = $request->all();
6725            $companyId = addslashes($data['company_id']);
6726            $where = '';
6727
6728            if ($companyId != 0) {
6729                $where .= " AND company_id = {$companyId} AND for_add = 0 ";
6730            } else {
6731                $where .= " AND company_id IN ({$this->companyId}) AND for_add = 0 ";
6732            }
6733
6734            if (isset($data['budget_status']) && $data['budget_status'] != null) {
6735                $where .= " AND bs.budget_status_id = {$data['budget_status']}";
6736            }
6737
6738            $latestYear = TblQuotations::max(DB::raw('YEAR(issue_date)'));
6739            $md = date('m-d');
6740
6741            $query = "SELECT
6742                        q.years,
6743                        q.totalIssue,
6744                        (q.total_acceptance_percentage - q.totalAcceptancePercentage) / q.totalAcceptancePercentage * 100 totalAcceptancePercentage,
6745                        q.totalAccept
6746                    FROM
6747                        (
6748                        SELECT
6749                            YEAR(a.issue_date) years,
6750                            (b.total_issued - COUNT(a.issue_date)) / COUNT(a.issue_date) * 100 totalIssue,
6751                            COUNT(
6752                                CASE WHEN a.acceptance_date IS NOT NULL
6753                                AND DATE_FORMAT(a.acceptance_date, '%Y-%m-%d') BETWEEN CONCAT(YEAR(a.acceptance_date), '-01-01')
6754                                AND CONCAT(YEAR(a.acceptance_date), '-{$md}')
6755                                AND YEAR(a.acceptance_date) = YEAR(a.issue_date)
6756                                AND a.budget_status_id = 3 THEN 1 END
6757                            ) / COUNT(a.issue_date) * 100 totalAcceptancePercentage,
6758                            b.total_acceptance_percentage,
6759                            (b.total_acceptance -
6760                                COUNT(
6761                                    CASE WHEN a.acceptance_date IS NOT NULL
6762                                    AND DATE_FORMAT(a.acceptance_date, '%Y-%m-%d') BETWEEN CONCAT(YEAR(a.acceptance_date), '-01-01')
6763                                    AND CONCAT(YEAR(a.acceptance_date), '-{$md}')
6764                                    AND YEAR(a.acceptance_date) = YEAR(a.issue_date)
6765                                    AND a.budget_status_id = 3 THEN 1 END)
6766                                    ) / COUNT(
6767                                            CASE WHEN a.acceptance_date IS NOT NULL
6768                                            AND DATE_FORMAT(a.acceptance_date, '%Y-%m-%d') BETWEEN CONCAT(YEAR(a.acceptance_date), '-01-01')
6769                                            AND CONCAT(YEAR(a.acceptance_date), '-{$md}')
6770                                            AND YEAR(a.acceptance_date) = YEAR(a.issue_date)
6771                                            AND a.budget_status_id = 3 THEN 1 END
6772                            ) * 100 totalAccept
6773                        FROM
6774                            tbl_quotations a
6775                            JOIN (
6776                            SELECT
6777                                YEAR(issue_date) current_year,
6778                                COUNT(issue_date) total_issued,
6779                                COUNT(
6780                                    CASE WHEN acceptance_date IS NOT NULL
6781                                    AND DATE_FORMAT(acceptance_date, '%Y-%m-%d') BETWEEN CONCAT(YEAR(acceptance_date), '-01-01')
6782                                    AND CONCAT(YEAR(acceptance_date), '-{$md}')
6783                                    AND YEAR(acceptance_date) = YEAR(issue_date)
6784                                    AND budget_status_id = 3 THEN 1 END
6785                                ) total_acceptance,
6786                                COUNT(
6787                                    CASE WHEN acceptance_date IS NOT NULL
6788                                    AND DATE_FORMAT(acceptance_date, '%Y-%m-%d') BETWEEN CONCAT(YEAR(acceptance_date), '-01-01')
6789                                    AND CONCAT(YEAR(acceptance_date), '-{$md}')
6790                                    AND YEAR(acceptance_date) = YEAR(issue_date)
6791                                    AND budget_status_id = 3 THEN 1 END
6792                                ) / COUNT(issue_date) * 100 total_acceptance_percentage
6793                            FROM
6794                                tbl_quotations
6795                            WHERE
6796                                issue_date IS NOT NULL
6797                                AND YEAR(issue_date) = {$latestYear}
6798                                AND DATE_FORMAT(issue_date, '%Y-%m-%d') BETWEEN CONCAT(YEAR(issue_date), '-01-01')
6799                                AND CONCAT(YEAR(issue_date), '-{$md}')
6800                                {$where}
6801                            GROUP by
6802                                1
6803                            ) b
6804                        WHERE
6805                            a.issue_date IS NOT NULL
6806                            AND a.budget_type_id != 7
6807                            AND a.budget_type_id IS NOT NULL
6808                            AND {$latestYear} > YEAR(a.issue_date)
6809                            AND DATE_FORMAT(a.issue_date, '%Y-%m-%d') BETWEEN CONCAT(YEAR(a.issue_date), '-01-01')
6810                            AND CONCAT(YEAR(a.issue_date), '-{$md}')
6811                        GROUP BY
6812                            1
6813                        ORDER BY
6814                            YEAR(issue_date) DESC
6815                        ) q
6816                    ";
6817
6818            $resultYtd = DB::select($query);
6819
6820            $query = "SELECT
6821                        YEAR(issue_date) years,
6822                        COUNT(issue_date) totalIssue,
6823                        COUNT(
6824                            CASE WHEN acceptance_date IS NOT NULL
6825                            AND DATE_FORMAT(acceptance_date, '%Y-%m-%d') BETWEEN CONCAT(YEAR(acceptance_date), '-01-01')
6826                            AND CONCAT(YEAR(acceptance_date), '-{$md}')
6827                            AND YEAR(acceptance_date) = YEAR(issue_date)
6828                            AND budget_status_id = 3 THEN 1 END
6829                        ) totalAccept,
6830                        COUNT(
6831                            CASE WHEN acceptance_date IS NOT NULL
6832                            AND DATE_FORMAT(acceptance_date, '%Y-%m-%d') BETWEEN CONCAT(YEAR(acceptance_date), '-01-01')
6833                            AND CONCAT(YEAR(acceptance_date), '-{$md}')
6834                            AND YEAR(acceptance_date) = YEAR(issue_date)
6835                            AND budget_status_id = 3 THEN 1 END
6836                        ) / COUNT(issue_date) * 100 totalAcceptancePercentage
6837                    FROM
6838                        tbl_quotations
6839                    WHERE
6840                        issue_date IS NOT NULL
6841                        AND budget_type_id != 7
6842                        AND budget_type_id IS NOT NULL
6843                        AND DATE_FORMAT(issue_date, '%Y-%m-%d') BETWEEN CONCAT(YEAR(issue_date), '-01-01')
6844                        AND CONCAT(YEAR(issue_date), '-{$md}')
6845                        {$where}
6846                    GROUP BY
6847                        1
6848                    ORDER BY
6849                        YEAR(issue_date) DESC
6850                    ";
6851
6852            $resultYears = DB::select($query);
6853
6854            return response(['message' => 'OK', 'ytdData' => $resultYtd, 'yearsData' => $resultYears]);
6855
6856        } catch (\Exception $e) {
6857            /** @disregard P1014 */
6858            $e->exceptionCode = 'LIST_QUOTATION_ANALYTICS_BY_PERFORMANCE_EXCEPTION';
6859            report($e);
6860
6861            return response(['message' => 'KO', 'error' => $e->getMessage()]);
6862        }
6863    }
6864
6865    public function list_orders_update_logs($companyId)
6866    {
6867
6868        try {
6869
6870            $where = '';
6871
6872            if ($companyId != 0) {
6873                $where .= " a.company_id = {$companyId}";
6874            } else {
6875                $where .= " a.company_id IN ({$this->companyId})";
6876            }
6877
6878            $query = "SELECT
6879                        a.id,
6880                        b.name company,
6881                        a.to_process,
6882                        a.rejected_affected_rows,
6883                        a.for_add_deleted_affected_rows,
6884                        a.month_change_affected_rows,
6885                        a.follow_ups_affected_rows,
6886                        a.sync_succesfull,
6887                        a.sync_error,
6888                        a.sync_error_message,
6889                        a.sync_success_ids,
6890                        a.cleared_email_errors,
6891                        a.remaining_email_errors,
6892                        CASE
6893                            WHEN a.rejected_affected_rows IS NOT NULL THEN a.rejected_affected_rows
6894                            WHEN a.for_add_deleted_affected_rows IS NOT NULL THEN a.for_add_deleted_affected_rows
6895                            WHEN a.month_change_affected_rows IS NOT NULL THEN a.month_change_affected_rows
6896                            WHEN a.follow_ups_affected_rows IS NOT NULL THEN a.follow_ups_affected_rows
6897                        END totals,
6898                        a.status,
6899                        a.processed_by,
6900                        a.started_at,
6901                        a.ended_at,
6902                        a.rejected_automatically_ids
6903                    FROM `tbl_orders_update_logs` a
6904                    LEFT JOIN tbl_companies b
6905                        ON a.company_id = b.company_id
6906                    WHERE {$where}
6907                    ORDER BY started_at DESC";
6908
6909            $result = DB::select($query);
6910
6911            return response(['message' => 'OK', 'data' => $result]);
6912
6913        } catch (\Exception $e) {
6914            /** @disregard P1014 */
6915            $e->exceptionCode = 'LIST_ORDERS_UPDATE_LOGS_EXCEPTION';
6916            report($e);
6917
6918            return response(['message' => 'KO', 'error' => $e->getMessage()]);
6919        }
6920
6921    }
6922
6923    public function list_g3w_orders_update_logs($companyId)
6924    {
6925
6926        try {
6927            $result = TblG3WOrdersUpdateLogs::where('company_id', $companyId)
6928                ->where('processed_by', 'System')
6929                ->get();
6930
6931            return response(['message' => 'OK', 'data' => $result]);
6932
6933        } catch (\Exception $e) {
6934            /** @disregard P1014 */
6935            $e->exceptionCode = 'LIST_G3W_ORDERS_UPDATE_LOGS_EXCEPTION';
6936            report($e);
6937
6938            return response(['message' => 'KO', 'error' => $e->getMessage()]);
6939        }
6940
6941    }
6942
6943    public function list_g3w_orders_failed($companyId)
6944    {
6945        try {
6946            $logs = TblG3WOrdersUpdateLogs::where('company_id', $companyId)
6947                ->where('sync_error', '>', 0)
6948                ->get();
6949
6950            $individualErrors = [];
6951
6952            foreach ($logs as $log) {
6953                $errorIds = json_decode($log->sync_error_ids);
6954                $errorMessages = preg_split('/(?=Error (sincronizando|actualizando) el presupuesto)/', $log->sync_error_message, -1, PREG_SPLIT_NO_EMPTY);
6955
6956                if (is_array($errorIds)) {
6957                    foreach ($errorIds as $index => $id) {
6958                        $rawMsg = isset($errorMessages[$index]) ? $errorMessages[$index] : 'Error desconocido';
6959                        $cleanMsg = trim(preg_replace('/.*?el presupuesto \d+:/i', '', $rawMsg));
6960                        $cleanMsg = rtrim($cleanMsg, ',');
6961
6962                        $individualErrors[] = [
6963                            'quote_id' => $id,
6964                            'status' => 'Failed',
6965                            'started_at' => $log->started_at,
6966                            'ended_at' => $log->ended_at,
6967                            'reason' => $cleanMsg,
6968                            'log_id' => $log->id,
6969                        ];
6970                    }
6971                }
6972            }
6973
6974            return response(['message' => 'OK', 'data' => $individualErrors]);
6975
6976        } catch (\Exception $e) {
6977            report($e);
6978
6979            return response(['message' => 'KO', 'error' => $e->getMessage()]);
6980        }
6981    }
6982
6983    public function update_budget_status_rejected_manual(Request $request)
6984    {
6985
6986        try {
6987
6988            $data = $request->all();
6989
6990            $update = $this->update_budget_status_rejected($data['company_id'], $data['processed_by']);
6991
6992            if ($update) {
6993                return response(['message' => 'OK']);
6994            } else {
6995                return response(['message' => 'KO']);
6996            }
6997
6998        } catch (\Exception $e) {
6999            /** @disregard P1014 */
7000            $e->exceptionCode = 'UPDATE_BUDGET_STATUS_REJECTED_MANUAL_EXCEPTION';
7001            report($e);
7002
7003            return response(['message' => 'KO', 'error' => $e->getMessage()]);
7004        }
7005    }
7006
7007    public function update_budget_status_rejected($companyId = null, $processedBy = 'System')
7008    {
7009
7010        $startedAt = date('Y-m-d H:i:s');
7011        try {
7012            $companyId = intval($companyId);
7013            $where = '';
7014
7015            $budgetTypes = TblBudgetTypes::get();
7016
7017            if (count($budgetTypes) > 0) {
7018
7019                $companies = [];
7020
7021                if ($companyId != 0) {
7022                    $companies = TblCompanies::where('company_id', $companyId)->get();
7023                    $where = "AND company_id = {$companyId}";
7024                } else {
7025                    $companies = TblCompanies::get();
7026                }
7027
7028                for ($i = 0; $i < count($budgetTypes); $i++) {
7029
7030                    $days = $budgetTypes[$i]->duration;
7031                    $id = $budgetTypes[$i]->budget_type_id;
7032
7033                    if (! $days) {
7034                        continue;
7035                    }
7036
7037                    for ($c = 0; $c < count($companies); $c++) {
7038                        $companyId = $companies[$c]->company_id;
7039
7040                        $query = "SELECT
7041                                    GROUP_CONCAT(id) ids
7042                                FROM
7043                                    tbl_quotations
7044                                WHERE
7045                                    budget_type_id = {$id}
7046                                AND budget_status_id IN (1, 2, 11)
7047                                AND DATEDIFF(NOW(), issue_date) >= {$days}
7048                                AND for_add = 0
7049                                {$where}";
7050
7051                        $result = DB::select($query);
7052
7053                        if (count($result) > 0) {
7054
7055                            $ids = $result[0]->ids;
7056
7057                            if ($ids != null || $ids != '') {
7058                                $query = "UPDATE
7059                                            tbl_quotations
7060                                        SET
7061                                            budget_status_id = 7
7062                                        WHERE
7063                                            id IN ({$ids})";
7064
7065                                DB::select($query);
7066
7067                                TblOrdersUpdateLogs::create(
7068                                    [
7069                                        'company_id' => $companyId,
7070                                        'to_process' => 'Orders',
7071                                        'status' => 'success',
7072                                        'rejected_automatically_ids' => $ids,
7073                                        'processed_by' => $processedBy,
7074                                        'started_at' => $startedAt,
7075                                        'ended_at' => date('Y-m-d H:i:s'),
7076                                    ]
7077                                );
7078                            }
7079                        }
7080                    }
7081                }
7082            }
7083
7084            Cache::flush();
7085
7086            return response(['message' => 'OK']);
7087
7088        } catch (\Exception $e) {
7089            /** @disregard P1014 */
7090            $e->exceptionCode = 'UPDATE_BUDGET_STATUS_REJECTED_MANUAL_EXCEPTION';
7091            report($e);
7092
7093            TblOrdersUpdateLogs::create(
7094                [
7095                    'company_id' => $companyId,
7096                    'to_process' => 'Orders',
7097                    'status' => $e->getMessage(),
7098                    'processed_by' => $processedBy,
7099                    'started_at' => $startedAt,
7100                    'ended_at' => date('Y-m-d H:i:s'),
7101                ]
7102            );
7103
7104            return response(['message' => 'KO', 'error' => $e->getMessage()]);
7105        }
7106
7107    }
7108
7109    public function bulk_update_quotation(Request $request)
7110    {
7111
7112        // try {
7113
7114        $data = $request->all();
7115
7116        $r = new Request([
7117            'filterModel' => $data['filterModel'],
7118            'sortModel' => $data['sortModel'],
7119            'start' => 0,
7120            'end' => 999999999,
7121            'company_id' => $data['company_id'],
7122            'user_id' => $data['user_id'],
7123            'ids' => $data['ids'],
7124            'searchText' => $data['searchText'],
7125            'ids_not_in' => $data['ids_not_in'],
7126        ]);
7127
7128        $listQuotations = $this->list_quotations($r);
7129        $d = $listQuotations->original['data'];
7130
7131        if (count($d) > 0) {
7132            if (isset($data['last_follow_up_date']) && $data['last_follow_up_date'] == 1) {
7133                unset($data['last_follow_up_date']);
7134            }
7135            // unset($data['last_follow_up_date']);
7136            unset($data['filterModel']);
7137            unset($data['sortModel']);
7138            unset($data['start']);
7139            unset($data['end']);
7140            unset($data['company_id']);
7141            unset($data['user_id']);
7142            unset($data['ids']);
7143            unset($data['searchText']);
7144            unset($data['ids_not_in']);
7145
7146            $result = [];
7147            for ($i = 0; $i < count($d); $i++) {
7148                array_push($result, $d[$i]->id);
7149            }
7150
7151            TblQuotations::whereIn('id', $result)->update($data);
7152
7153            Cache::flush();
7154        }
7155
7156        return response(['message' => 'OK', $data]);
7157
7158        // } catch (\Exception $e) {
7159        //     return response(['message' => 'KO', 'error' => $e->getMessage()]);
7160        // }
7161
7162    }
7163
7164    public function move_budget_and_job(Request $request)
7165    {
7166
7167        try {
7168
7169            $data = $request->all();
7170            $id = addslashes($data['id']);
7171            $companyId = addslashes($data['company_id']);
7172
7173            unset($data['id']);
7174            unset($data['company_id']);
7175
7176            $budget = TblQuotations::where('id', $id)->first();
7177
7178            $quotationId = $budget->id;
7179            $companyIdJob = $budget->company_id;
7180
7181            $query = "SELECT
7182                        COUNT(1) total
7183                    FROM tbl_company_users a
7184                    LEFT JOIN tbl_users b
7185                        ON a.user_id = b.id
7186                    WHERE a.company_id = {$companyId}
7187                    AND b.name = '{$budget->commercial}'
7188                    ORDER BY b.name ASC";
7189
7190            $result = DB::select($query);
7191
7192            $commercial = $budget->commercial;
7193
7194            if ($result[0]->total == 0) {
7195                $commercial = $data['created_by'];
7196            }
7197
7198            $r = new Request([
7199                'created_by' => $commercial,
7200            ]);
7201
7202            $result = $this->get_number($r, $companyId, 1);
7203            $newNumber = $result->original['number'];
7204
7205            TblQuotations::where('id', $id)->update(
7206                [
7207                    'quote_id' => $newNumber,
7208                    'company_id' => $companyId,
7209                    'from_company_id' => $budget->company_id,
7210                    'commercial' => $commercial,
7211                ]
7212            );
7213
7214            $job = TblOngoingJobs::where('quotation_id', $quotationId)->first();
7215
7216            $jobId = null;
7217
7218            if ($job) {
7219                $jobId = $job->id;
7220
7221                $query = "SELECT
7222                            COUNT(1) total
7223                        FROM tbl_company_users a
7224                        LEFT JOIN tbl_users b
7225                            ON a.user_id = b.id
7226                        WHERE a.company_id = {$companyId}
7227                        AND b.name = '{$job->responsible_for_work}'
7228                        ORDER BY b.name ASC";
7229
7230                $result = DB::select($query);
7231
7232                $responsibleForWork = $job->responsible_for_work;
7233
7234                if ($result[0]->total == 0) {
7235                    $responsibleForWork = $data['created_by'];
7236                }
7237
7238                TblOngoingJobs::where('quotation_id', $id)->update(
7239                    [
7240                        'quote_id' => $newNumber,
7241                        'company_id' => $companyId,
7242                        'responsible_for_work' => $responsibleForWork,
7243                    ]
7244                );
7245            }
7246
7247            Cache::flush();
7248
7249            return response([
7250                'message' => 'OK',
7251                'quotation_id' => $quotationId,
7252                'job_id' => $jobId,
7253            ]);
7254
7255        } catch (\Exception $e) {
7256            /** @disregard P1014 */
7257            $e->exceptionCode = 'MOVE_BUDGET_AND_JOB_EXCEPTION';
7258            report($e);
7259
7260            return response(['message' => 'KO', 'error' => $e->getMessage()]);
7261        }
7262    }
7263
7264    public function list_quotation_analytics_by_types_of_budgets_created_per_week(Request $request)
7265    {
7266
7267        try {
7268
7269            $data = $request->all();
7270            $companyId = addslashes($data['company_id']);
7271            $field = $data['field'];
7272
7273            $where = '';
7274            $whereYear = '';
7275            $dateLflArray = [];
7276            $companyIds = $this->companyIds;
7277
7278            if ($companyId != 0) {
7279                $companyIds = [$companyId];
7280            }
7281
7282            $acc = '';
7283            if ($field == 'acceptance_date') {
7284                $acc = ' AND q.acceptance_date IS NOT NULL ';
7285                // $field = 'created_at';
7286
7287                if (@$data['data_to_display'] == 4) {
7288                    $field = 'created_at';
7289                    $where .= ' AND YEAR(q.created_at) = YEAR(q.issue_date)';
7290                }
7291            } else {
7292                $field = 'created_at';
7293                $where .= ' AND YEAR(q.created_at) = YEAR(q.issue_date)';
7294            }
7295
7296            if (isset($data['years']) && $data['years'] != null) {
7297
7298                if (count($data['years']) > 0) {
7299                    foreach ($data['years'] as $year) {
7300                        if (isset($data['week']) && $data['week'] != null) {
7301                            $w = sprintf('%02d', $data['week']);
7302                            $whereYear .= " AND YEARWEEK(q.{$field}, 1) = '{$year}{$w}'";
7303                        } else {
7304                            $whereYear .= " AND YEAR(q.{$field}) = {$year}";
7305                        }
7306                    }
7307                }
7308            }
7309
7310            foreach ($companyIds as $v) {
7311
7312                $lflWhere = " AND q.company_id = {$v} ";
7313
7314                $query = "SELECT
7315                            CONCAT(
7316                                DATE_FORMAT((SELECT MIN(q.{$field}) FROM tbl_quotations q WHERE q.{$field} IS NOT NULL {$lflWhere}), '%c/%e/'), YEAR({$field}),
7317                                ' - ',
7318                                DATE_FORMAT((SELECT MAX(q.{$field}) FROM tbl_quotations q WHERE q.{$field} IS NOT NULL {$lflWhere}), '%c/%e/'), YEAR({$field})
7319                            ) AS date_like,
7320                            YEAR(q.{$field}) 'year',
7321                            DATE_FORMAT((SELECT MIN(q.{$field}) FROM tbl_quotations q WHERE q.{$field} IS NOT NULL {$lflWhere}), '%m-%d') AS min_date_like,
7322                            DATE_FORMAT((SELECT MAX(q.{$field}) FROM tbl_quotations q WHERE q.{$field} IS NOT NULL {$lflWhere}), '%m-%d') AS max_date_like,
7323                            {$v} 'company_id'
7324                        FROM
7325                            tbl_quotations q
7326                        WHERE
7327                            q.{$field} IS NOT NULL
7328                            AND q.for_add = 0
7329                            {$lflWhere}
7330                            {$whereYear}
7331                        GROUP BY YEAR(q.{$field})
7332                        ORDER BY YEAR(q.{$field}) DESC";
7333
7334                $dateLike = DB::select($query);
7335
7336                $dateLflArray[$v] = $dateLike;
7337            }
7338
7339            $isFy = true;
7340
7341            if (isset($data['ytd']) && $data['ytd'] != null && $data['ytd'] == true) {
7342                $isFy = false;
7343                $ytdArray = [];
7344                $ytdAcceptanceArray = [];
7345                $lflCompanyIds = [];
7346                foreach ($dateLflArray as $k => $v) {
7347                    foreach ($dateLflArray[$k] as $item) {
7348                        $year = $item->year;
7349                        $now = date('m-d');
7350                        array_push($ytdArray, "DATE_FORMAT(q.{$field}, '%Y-%m-%d') BETWEEN '{$year}-01-01' AND '{$year}-{$now}'");
7351                    }
7352
7353                    $ytdArray = implode(' OR ', $ytdArray);
7354                    array_push($lflCompanyIds, "q.company_id = {$k} AND ({$ytdArray})");
7355                    $ytdArray = [];
7356                }
7357
7358                $lflCompanyIds = implode(' OR ', $lflCompanyIds);
7359                $where .= " AND ({$lflCompanyIds}";
7360            }
7361
7362            if (isset($data['lfl']) && $data['lfl'] != null && $data['lfl'] == true) {
7363                $isFy = false;
7364                $lflArray = [];
7365                $ytdAcceptanceArray = [];
7366                $lflCompanyIds = [];
7367                foreach ($dateLflArray as $k => $v) {
7368                    foreach ($dateLflArray[$k] as $item) {
7369                        $year = $item->year;
7370                        $min_date_like = $item->min_date_like;
7371                        $max_date_like = $item->max_date_like;
7372                        array_push($lflArray, "DATE_FORMAT(q.{$field}, '%Y-%m-%d') BETWEEN LEAST('{$year}-{$min_date_like}', '{$year}-{$max_date_like}') AND GREATEST('{$year}-{$min_date_like}', '{$year}-{$max_date_like}')");
7373                    }
7374
7375                    $lflArray = implode(' OR ', $lflArray);
7376                    array_push($lflCompanyIds, "q.company_id = {$k} AND ({$lflArray})");
7377                    $lflArray = [];
7378                }
7379
7380                $lflCompanyIds = implode(' OR ', $lflCompanyIds);
7381                $where .= " AND ({$lflCompanyIds}";
7382            }
7383
7384            if ($isFy) {
7385                if ($companyId != 0) {
7386                    $where .= " AND q.company_id = {$companyId} ";
7387                } else {
7388                    $where .= " AND q.company_id IN ({$this->companyId})";
7389                }
7390            }
7391
7392            if (isset($data['source']) && $data['source'] != null) {
7393                $where .= " AND s.name = '{$data['source']}'";
7394            }
7395
7396            if (isset($data['month']) && $data['month'] != null) {
7397                $where .= " AND MONTH(q.{$field}) = '{$data['month']}'";
7398            }
7399
7400            if (isset($data['commercial']) && $data['commercial'] != null) {
7401                $where .= " AND q.commercial = '{$data['commercial']}'";
7402            }
7403
7404            if (isset($data['created_by']) && $data['created_by'] != null) {
7405                $where .= " AND q.created_by = '{$data['created_by']}'";
7406            }
7407
7408            if (isset($data['budget_type']) && $data['budget_type'] != null) {
7409                $where .= " AND bt.budget_type_id = {$data['budget_type']}";
7410            }
7411
7412            if (isset($data['budget_type_group']) && $data['budget_type_group'] != null) {
7413                $where .= " AND bt.budget_type_group_id = {$data['budget_type_group']}";
7414            }
7415
7416            if (isset($data['budget_status']) && $data['budget_status'] != null) {
7417                $where .= " AND bs.budget_status_id = {$data['budget_status']}";
7418            }
7419
7420            if (isset($data['client_type']) && $data['client_type'] != null) {
7421                $where .= " AND ct.customer_type_id = {$data['client_type']}";
7422            }
7423
7424            if (isset($data['segment_id']) && $data['segment_id'] != null) {
7425                $where .= " AND q.segment_id = {$data['segment_id']}";
7426            }
7427
7428            $col = '1';
7429
7430            if (isset($data['data_to_display']) && $data['data_to_display'] != null) {
7431                if ($data['data_to_display'] == 1) {
7432                    $col = '1';
7433                }
7434
7435                if ($data['data_to_display'] == 2) {
7436                    $col = 'q.amount';
7437                }
7438            }
7439
7440            $budgetTypes = TblBudgetTypes::orderByRaw('ISNULL(priority), priority ASC')->get();
7441            $cols = '';
7442            foreach ($budgetTypes as $item) {
7443                if ($item->name == '' || $item->name == null) {
7444                    $cols .= ",COALESCE(SUM(CASE WHEN bt.name IS NULL {$acc} THEN {$col} ELSE 0 END), 0) AS 'Otros'";
7445                } else {
7446                    $cols .= ",COALESCE(SUM(CASE WHEN bt.name = '{$item->name}{$acc} THEN {$col} ELSE 0 END), 0) AS '{$item->name}'";
7447                }
7448            }
7449
7450            $budgetTypeGroups = TblBudgetTypeGroups::orderByRaw('ISNULL(priority), priority ASC')->get();
7451
7452            $colsGroups = ",COALESCE(SUM(CASE WHEN bt.name IS NULL {$acc} THEN {$col} END), 0) AS Otros";
7453
7454            foreach ($budgetTypeGroups as $item) {
7455                $budgetTypeGroupName = str_replace(' ', '', $item->name).$item->budget_type_group_id;
7456                $colsGroups .= ",GROUP_CONCAT(CASE WHEN (bt.budget_type_group_id = {$item->budget_type_group_id} OR bt.name IS NULL) {$acc} THEN q.id END) AS 'groupConcatIds{$budgetTypeGroupName}'";
7457                $colsGroups .= ",COALESCE(SUM(CASE WHEN (bt.budget_type_group_id = {$item->budget_type_group_id} OR bt.name IS NULL) {$acc} THEN {$col} END), 0) AS '{$budgetTypeGroupName}'";
7458            }
7459
7460            $colsGroups .= ",COALESCE(SUM(CASE WHEN (bt.budget_type_group_id IS NOT NULL OR bt.name IS NULL) {$acc} THEN {$col} END), 0) AS total";
7461
7462            $col = $colsGroups.$cols;
7463
7464            if (@$data['data_to_display'] == 3) {
7465
7466                $cols = '';
7467                foreach ($budgetTypes as $item) {
7468                    if ($item->name == '' || $item->name == null) {
7469                        $cols .= ",COALESCE(
7470                                        SUM(CASE WHEN bt.name IS NULL {$acc} THEN q.amount ELSE 0 END) /
7471                                        SUM(CASE WHEN bt.name IS NULL {$acc} THEN 1 ELSE 0 END) * 100 , 0
7472                                    ) AS 'Otros'";
7473                    } else {
7474                        $cols .= ",COALESCE(
7475                                        SUM(CASE WHEN bt.name = '{$item->name}{$acc} THEN q.amount ELSE 0 END) /
7476                                        SUM(CASE WHEN bt.name = '{$item->name}{$acc} THEN 1 ELSE 0 END), 0
7477                                    ) AS '{$item->name}'";
7478                    }
7479                }
7480
7481                $colsGroups = ",COALESCE(
7482                                (SUM(CASE WHEN bt.name IS NULL {$acc} THEN q.amount END)) /
7483                                (SUM(CASE WHEN bt.name IS NULL {$acc} THEN 1 END))
7484                            , 0) Otros";
7485
7486                foreach ($budgetTypeGroups as $item) {
7487                    $budgetTypeGroupName = str_replace(' ', '', $item->name).$item->budget_type_group_id;
7488                    $colsGroups .= ",GROUP_CONCAT(CASE WHEN (bt.budget_type_group_id = {$item->budget_type_group_id} OR bt.name IS NULL) {$acc} THEN q.id END) AS 'groupConcatIds{$budgetTypeGroupName}'";
7489                    $colsGroups .= ",COALESCE(
7490                                        (SUM(CASE WHEN (bt.budget_type_group_id = {$item->budget_type_group_id} OR bt.name IS NULL) {$acc} THEN q.amount END)) /
7491                                        (SUM(CASE WHEN (bt.budget_type_group_id = {$item->budget_type_group_id} OR bt.name IS NULL) {$acc} THEN 1 END))
7492                                    , 0) '{$budgetTypeGroupName}'";
7493                }
7494
7495                $colsGroups .= ",COALESCE(
7496                                    (SUM(CASE WHEN (bt.budget_type_group_id IS NOT NULL OR bt.name IS NULL) {$acc} THEN q.amount END)) /
7497                                    (SUM(CASE WHEN (bt.budget_type_group_id IS NOT NULL OR bt.name IS NULL) {$acc} THEN 1 END))
7498                                , 0) total";
7499
7500                $col = $colsGroups.$cols;
7501            }
7502
7503            if (@$data['data_to_display'] == 4) {
7504
7505                $cols = '';
7506
7507                foreach ($budgetTypes as $item) {
7508
7509                    if ($item->name == '' || $item->name == null) {
7510                        $cols .= ",COALESCE(
7511                                        SUM(CASE WHEN bt.name IS NULL AND q.acceptance_date IS NOT NULL THEN 1 ELSE 0 END) /
7512                                        SUM(CASE WHEN bt.name IS NULL AND q.created_at IS NOT NULL THEN 1 ELSE 0 END) * 100 , 0
7513                                ) AS 'Otros'";
7514                    } else {
7515                        $cols .= ", COALESCE(
7516                                        SUM(CASE WHEN bt.name = '{$item->name}' AND q.acceptance_date IS NOT NULL THEN 1 END) /
7517                                        SUM(CASE WHEN bt.name = '{$item->name}' AND q.created_at IS NOT NULL THEN 1 END) * 100, 0
7518                                ) AS '{$item->name}'";
7519                    }
7520                }
7521
7522                $colsGroups = ',COALESCE(
7523                                    (SUM(CASE WHEN bt.name IS NULL AND q.acceptance_date IS NOT NULL THEN 1 END)) /
7524                                    (SUM(CASE WHEN bt.name IS NULL AND q.created_at IS NOT NULL THEN 1 END)) * 100
7525                                    , 0) Otros';
7526
7527                foreach ($budgetTypeGroups as $item) {
7528                    $budgetTypeGroupName = str_replace(' ', '', $item->name).$item->budget_type_group_id;
7529                    $colsGroups .= ",GROUP_CONCAT(CASE WHEN (bt.budget_type_group_id = {$item->budget_type_group_id} OR bt.name IS NULL) {$acc} THEN q.id END) AS 'groupConcatIds{$budgetTypeGroupName}'";
7530                    $colsGroups .= ",COALESCE(
7531                                        (SUM(CASE WHEN (bt.budget_type_group_id = {$item->budget_type_group_id} OR bt.name IS NULL) AND q.acceptance_date IS NOT NULL THEN 1 END)) /
7532                                        (SUM(CASE WHEN (bt.budget_type_group_id = {$item->budget_type_group_id} OR bt.name IS NULL) AND q.created_at IS NOT NULL THEN 1 END)) * 100
7533                                    , 0) '{$budgetTypeGroupName}'";
7534                }
7535
7536                $colsGroups .= ',COALESCE(
7537                                    (SUM(CASE WHEN (bt.budget_type_group_id IS NOT NULL OR bt.name IS NULL) AND q.acceptance_date IS NOT NULL THEN 1 END)) /
7538                                    (SUM(CASE WHEN (bt.budget_type_group_id IS NOT NULL OR bt.name IS NULL) AND q.created_at IS NOT NULL THEN 1 END)) * 100
7539                                    , 0) total';
7540
7541                $col = $colsGroups.$cols;
7542            }
7543
7544            $query = "SELECT
7545                            YEAR(DATE_ADD(q.{$field}, INTERVAL - WEEKDAY(q.{$field}) DAY)) AS 'year',
7546                            LPAD(MONTH(DATE_ADD(q.{$field}, INTERVAL - WEEKDAY(q.{$field}) DAY)), 2, 0) AS 'month',
7547                            LPAD(WEEK(DATE_ADD(q.{$field}, INTERVAL - WEEKDAY(q.{$field}) DAY)), 2, 0) AS 'week',
7548                            DATE_FORMAT(DATE_ADD(q.{$field}, INTERVAL - WEEKDAY(q.{$field}) DAY), '%W, %M %e') 'namedate',
7549                            GROUP_CONCAT(CASE WHEN (bt.budget_type_group_id IS NOT NULL OR bt.name IS NULL) {$acc} THEN q.id END) groupConcatIds
7550                            {$col}
7551                        FROM
7552                            tbl_quotations q
7553                            LEFT JOIN tbl_sources s ON s.source_id = q.source_id
7554                            LEFT JOIN tbl_budget_status bs ON bs.budget_status_id = q.budget_status_id
7555                            LEFT JOIN tbl_budget_types bt ON q.budget_type_id = bt.budget_type_id
7556                            LEFT JOIN tbl_budget_type_groups btg ON bt.budget_type_group_id = btg.budget_type_group_id
7557                            LEFT JOIN tbl_customer_types ct ON q.customer_type_id = ct.customer_type_id
7558                        WHERE
7559                            q.{$field} IS NOT NULL
7560                            AND q.for_add = 0
7561                            AND q.budget_type_id IS NOT NULL
7562                            AND q.budget_type_id != 7
7563                            AND q.amount REGEXP '^[0-9]+\\.?[0-9]*$' = 1                            
7564                            {$where}
7565                            {$whereYear}
7566                        GROUP BY
7567                            YEAR(DATE_ADD(q.{$field}, INTERVAL - WEEKDAY(q.{$field}) DAY)),
7568                            MONTH(DATE_ADD(q.{$field}, INTERVAL - WEEKDAY(q.{$field}) DAY)),
7569                            WEEK(DATE_ADD(q.{$field}, INTERVAL - WEEKDAY(q.{$field}) DAY)) WITH ROLLUP
7570                        ORDER BY
7571                            YEAR DESC,
7572                            MONTH ASC,
7573                            WEEK ASC,
7574                            DATE_FORMAT(q.{$field}, '%e') ASC";
7575            // return $query;
7576            $result = DB::select($query);
7577
7578            $query = "SELECT
7579                        btg.budget_type_group_id,
7580                        btg.name,
7581                        (
7582                            SELECT
7583                                GROUP_CONCAT(COALESCE(bt.name, '') ORDER BY ISNULL(bt.priority), bt.priority ASC SEPARATOR '|')
7584                            FROM
7585                                tbl_budget_types bt
7586                            WHERE
7587                                bt.budget_type_group_id = btg.budget_type_group_id
7588                        ) budget_types
7589                        FROM
7590                            tbl_budget_type_groups btg
7591                        ORDER BY
7592                            ISNULL(btg.priority),
7593                            btg.priority ASC";
7594
7595            $budgetTypeGroups = DB::select($query);
7596
7597            foreach ($budgetTypeGroups as $item) {
7598                $item->group_key_name = str_replace(' ', '', $item->name).$item->budget_type_group_id;
7599                $item->budget_types = explode('|', $item->budget_types);
7600            }
7601
7602            return response([
7603                'message' => 'OK',
7604                'data' => $result,
7605                'budgetTypeGroups' => $budgetTypeGroups,
7606            ]);
7607
7608        } catch (\Exception $e) {
7609            /** @disregard P1014 */
7610            $e->exceptionCode = 'LIST_QUOTATION_ANALYTICS_BY_TYPES_OF_BUDGETS_CREATED_PER_WEEK_EXCEPTION';
7611            report($e);
7612
7613            return response(['message' => 'KO', 'error' => $e->getMessage()]);
7614        }
7615    }
7616
7617    public function preview_file($id)
7618    {
7619
7620        try {
7621
7622            $file = TblFiles::where('file_id', $id)->first();
7623
7624            if (! $file) {
7625                return response()->json([
7626                    'message' => 'KO',
7627                    'error' => __('language.file_not_found'),
7628                ], 404);
7629            }
7630
7631            if (! Storage::disk('s3')->exists('uploads/'.$file->filename)) {
7632                return response()->json(['message' => 'File not found'], 404);
7633            }
7634
7635            $url = Storage::disk('s3')->temporaryUrl(
7636                'uploads/'.$file->filename,
7637                now()->addMinutes(5)
7638            );
7639
7640            return response()->json([
7641                'filename' => $file->filename,
7642                'url' => $url,
7643                'uploaded_by' => $file->uploaded_by,
7644                'uploaded_at' => $file->uploaded_at,
7645            ]);
7646
7647        } catch (\Exception $e) {
7648            /** @disregard P1014 */
7649            $e->exceptionCode = 'PREVIEW_FILE_EXCEPTION';
7650            report($e);
7651
7652            return response()->json([
7653                'message' => 'KO',
7654                'error' => $e->getMessage(),
7655            ], 500);
7656        }
7657    }
7658
7659    public function get_past_added_quotation(Request $request)
7660    {
7661
7662        try {
7663
7664            $data = $request->all();
7665            $keyword = addslashes($data['keyword']);
7666            $result = [];
7667
7668            if (! empty($keyword)) {
7669                $array = explode(' ', $keyword);
7670
7671                $where = '';
7672
7673                $availableParameters = ['client', 'email'];
7674
7675                $searchTextArray = explode(' ', $keyword);
7676
7677                $searchArray = [];
7678                $matchScoreArray = [];
7679                foreach ($availableParameters as $field) {
7680                    foreach ($searchTextArray as $word) {
7681                        array_push($searchArray, "({$field} LIKE '%{$word}%')");
7682                        array_push($matchScoreArray, "CASE WHEN {$field} LIKE '%{$word}%' THEN 1 ELSE 0 END");
7683                    }
7684                }
7685
7686                $searchArray = implode(' OR ', $searchArray);
7687                $matchScoreArray = implode(' + ', $matchScoreArray);
7688                $matchScoreCol = "({$matchScoreArray})";
7689                $where .= " AND ({$searchArray}";
7690
7691                $query = "SELECT
7692                            id,
7693                            client,
7694                            segment_id,
7695                            CONCAT(`client`, ' - ', email) `client_email`,
7696                            email,
7697                            phone_number,
7698                            customer_type_id,
7699                            {$matchScoreCol} match_score
7700                        FROM tbl_quotations
7701                        WHERE for_add = 0
7702                        AND email IS NOT NULL AND phone_number IS NOT NULL
7703                        {$where}
7704                        GROUP BY client, email
7705                        ORDER BY match_score DESC, client ASC
7706                        ";
7707
7708                $result = DB::select($query);
7709            }
7710
7711            return response(['message' => 'OK', 'data' => $result]);
7712
7713        } catch (\Exception $e) {
7714            /** @disregard P1014 */
7715            $e->exceptionCode = 'GET_PAST_ADDED_QUOTATION_EXCEPTION';
7716            report($e);
7717
7718            return response(['message' => 'KO', 'error' => $e->getMessage()]);
7719        }
7720    }
7721
7722    public function send_acceptance_notification($quotationId, $companyId, $userId, $updatedBy)
7723    {
7724
7725        $budget = TblQuotations::where('id', $quotationId)->first();
7726
7727        if ($budget != null) {
7728            $to = TblToAcceptanceNotifications::where('company_id', $companyId)->get();
7729            $cc = TblCcAcceptanceNotifications::where('company_id', $companyId)->get();
7730
7731            if (count($to) > 0 && count($cc) > 0) {
7732
7733                $company = TblCompanies::where('company_id', $companyId)->first();
7734
7735                $quoteId = $budget->quote_id;
7736                $amount = $this->currency($budget->amount, 1);
7737
7738                $url = env('URL')."orders/{$quotationId}?company_id={$companyId}";
7739                $href = "<a href='{$url}'>{$quoteId}</a>";
7740
7741                $imgpath = File::get('fireservicetitan.png');
7742                $base64 = 'data:image/png;base64,'.base64_encode($imgpath);
7743
7744                $body = __('language.send_acceptance_notification.body_hello');
7745                $body .= __('language.send_acceptance_notification.body_message');
7746
7747                $body = str_replace('{{client}}', $budget->client, $body);
7748                $body = str_replace('{{username}}', $updatedBy, $body);
7749                $body = str_replace('{{company}}', $company->name, $body);
7750                $body = str_replace('{{amount}}', $amount, $body);
7751                $body = str_replace('{{quote_id}}', $href, $body);
7752
7753                $body .= '<p>Fire Service Titan</p>';
7754                $body .= "<img src='cid:fireservicetitan' style='height: 45px;' />";
7755
7756                $html = '<!DOCTYPE html>';
7757                $html .= '<html>';
7758                $html .= '<head>';
7759                $html .= '<meta charset="UTF-8">';
7760                $html .= '<meta name="viewport" content="width=device-width, initial-scale=1.0">';
7761                $html .= '</head>';
7762                $html .= '<body>';
7763                $html .= $body;
7764                $html .= '</body>';
7765                $html .= '</html>';
7766
7767                $subject = __('language.send_acceptance_notification.subject');
7768                $subject = str_replace('{{quote_id}}', $quoteId, $subject);
7769
7770                $email = new \SendGrid\Mail\Mail;
7771
7772                $user = TblUsers::where('id', $userId)->first();
7773
7774                if (env('SENDGRID_STAGING')) {
7775                    $email->addTo($user->email);
7776                } else {
7777
7778                    $emails = [];
7779
7780                    foreach ($to as $item) {
7781                        if (! in_array($item->email, $emails)) {
7782                            array_push($emails, $item->email);
7783                            $email->addTo($item->email);
7784                        }
7785                    }
7786
7787                    foreach ($cc as $item) {
7788                        if (! in_array($item->email, $emails)) {
7789                            array_push($emails, $item->email);
7790                            $email->addCc($item->email);
7791                        }
7792                    }
7793
7794                    $email->addCc($user->email);
7795                    array_push($emails, $user->email);
7796
7797                    $ccUser = TblUsers::where('name', $budget->commercial)->first();
7798
7799                    if ($ccUser) {
7800                        if (! in_array($ccUser->email, $emails)) {
7801                            $email->addCc($ccUser->email);
7802                        }
7803                    }
7804                }
7805
7806                $email->setFrom('fire@fire.es', 'Fire Service Titan');
7807                $email->setSubject($subject);
7808                $email->addContent('text/html', $html);
7809
7810                $email->addAttachment(
7811                    $imgpath,
7812                    'image/png',
7813                    'fireservicetitan.png',
7814                    'inline',
7815                    'fireservicetitan'
7816                );
7817
7818                $sendgrid = new \SendGrid(env('SENDGRID_API_KEY'));
7819
7820                $response = $sendgrid->send($email);
7821                if ($response->statusCode() == 202) {
7822                    $this->addUpdateLog($quotationId, $userId, 'send_acceptance_notification', null, null, 5);
7823                    $comment = 'Email de aprobación automática enviada al equipo de opearciones el '.date('Y-m-d H:i:s');
7824                    $budget->last_follow_up_comment = $budget->last_follow_up_comment."\n".$comment;
7825
7826                    TblQuotations::where('id', $quotationId)->update(
7827                        [
7828                            'last_follow_up_comment' => $budget->last_follow_up_comment,
7829                        ]
7830                    );
7831
7832                    Log::channel('email_log')->info('ID:'.$quoteId.' - ACCEPTANCE EMAIL NOTIFICATION SENT');
7833                } else {
7834                    $error = true;
7835                    Log::channel('email_log')->error('ID:'.$quoteId.' - '.$response->body());
7836                }
7837
7838            }
7839        }
7840    }
7841
7842    public function get_total_quotations_by_budget_status(Request $request)
7843    {
7844
7845        try {
7846
7847            $data = $request->all();
7848
7849            $companyId = addslashes($data['company_id']);
7850
7851            $where = '';
7852
7853            if ($companyId != 0) {
7854                $where = " AND a.company_id = {$companyId} ";
7855            } else {
7856                $where = " AND a.company_id IN ({$this->companyId}";
7857            }
7858
7859            $user = null;
7860
7861            if (isset($data['commercial'])) {
7862                if ($data['commercial'] != 'All') {
7863                    $user = TblUsers::where('name', $data['commercial'])->first();
7864                }
7865            } else {
7866                $user = TblUsers::where('id', $this->userId)->first();
7867            }
7868
7869            $totalPendingFollowUps = 0;
7870            $totalRequestAndVisit = 0;
7871            $totalError = 0;
7872            $totalG3WError = 0;
7873            $totalSendToClient = 0;
7874
7875            $d = false;
7876
7877            if ($user != null) {
7878                $where .= " AND a.commercial = '{$user->name}";
7879                $d = true;
7880            }
7881
7882            if ($data['commercial'] == 'All') {
7883                $d = true;
7884            }
7885
7886            if ($d) {
7887                $blacklist = implode('|', $this->getBlacklistEmails());
7888                $query = "SELECT
7889                            COUNT(DISTINCT a.id) total
7890                        FROM
7891                            tbl_quotations a
7892                            LEFT JOIN (
7893                                SELECT
7894                                a.id,
7895                                SUBSTRING_INDEX(
7896                                    SUBSTRING_INDEX(a.email, ',', n.digit + 1),
7897                                    ',',
7898                                    -1
7899                                ) AS email_domain
7900                                FROM
7901                                tbl_quotations a
7902                                INNER JOIN (
7903                                    SELECT
7904                                    0 AS digit
7905                                    UNION ALL
7906                                    SELECT
7907                                    1
7908                                    UNION ALL
7909                                    SELECT
7910                                    2
7911                                    UNION ALL
7912                                    SELECT
7913                                    3
7914                                    UNION ALL
7915                                    SELECT
7916                                    4
7917                                    UNION ALL
7918                                    SELECT
7919                                    5
7920                                    UNION ALL
7921                                    SELECT
7922                                    6
7923                                    UNION ALL
7924                                    SELECT
7925                                    7
7926                                    UNION ALL
7927                                    SELECT
7928                                    8
7929                                    UNION ALL
7930                                    SELECT
7931                                    9
7932                                ) n ON LENGTH(
7933                                    REPLACE(a.email, ',', '')
7934                                ) <= LENGTH(a.email)- n.digit
7935                                GROUP BY a.id
7936                            ) temp ON a.id = temp.id
7937                            LEFT JOIN tbl_companies b
7938                                ON a.company_id = b.company_id
7939                        WHERE
7940                            a.last_follow_up_date < NOW()
7941                            AND a.budget_status_id IN (2)
7942                            AND a.email IS NOT NULL
7943                            AND a.email <> ''
7944                            AND NOT EXISTS (
7945                                SELECT
7946                                1
7947                                FROM
7948                                tbl_blocked_domains bd
7949                                WHERE
7950                                temp.email_domain LIKE CONCAT('%', bd.domain, '%')
7951                                AND bd.company_id = a.company_id
7952                            )
7953                            AND a.last_follow_up_date IS NOT NULL
7954                            AND a.reason_for_not_following_up_id IS NULL
7955                            AND a.last_follow_up_date > 0
7956                            AND a.total_sent < b.limit_reminder_emails
7957                            AND (
7958                                a.email IS NOT NULL 
7959                                AND TRIM(a.email) != '' 
7960                                AND a.email REGEXP '[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}'
7961                                AND a.email NOT REGEXP '($blacklist)'
7962                            )
7963                            AND a.for_add = 0 {$where}";
7964
7965                $result = DB::select($query);
7966
7967                $totalPendingFollowUps = $result[0]->total;
7968
7969                $query = "SELECT
7970                                COUNT(1) total
7971                            FROM
7972                                tbl_quotations a
7973                            WHERE
7974                                a.budget_status_id IN (6, 8, 12)
7975                                AND a.for_add = 0
7976                                {$where}
7977                            ";
7978
7979                $result = DB::select($query);
7980
7981                $totalRequestAndVisit = $result[0]->total;
7982
7983                $blacklist = implode('|', $this->getBlacklistEmails());
7984
7985                $query = "SELECT
7986                                COUNT(1) total
7987                            FROM
7988                                tbl_quotations a
7989                            WHERE
7990                                a.for_add = 0 AND
7991                                (
7992                                    a.x_status IN ('Error','Error - Bounce','Error - Spam')
7993                                    OR (
7994                                        a.email IS NULL 
7995                                        OR TRIM(a.email) = '' 
7996                                        OR a.email NOT REGEXP '[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}'
7997                                        OR a.email REGEXP '(no\.no|tiene\.email|test\.com|no\.tiene|prueba\.com|nomail@nomail\.com|notiene@notiene\.notiene)'
7998                                    )
7999                                ) 
8000                                AND a.budget_status_id IN(1, 2, 11, 17, 21)
8001                                    {$where}
8002                            ";
8003
8004                $result = DB::select($query);
8005
8006                $totalError = $result[0]->total;
8007
8008                $query = "SELECT
8009                                COUNT(1) total
8010                                FROM
8011                                    tbl_quotations a
8012                                WHERE
8013                                    a.g3w_warning = 1
8014                                    AND a.for_add = 0
8015                                    {$where}
8016                                ";
8017
8018                $result = DB::select($query);
8019
8020                $totalG3WError = $result[0]->total;
8021
8022                $query = "SELECT
8023                                COUNT(1) total
8024                                FROM
8025                                    tbl_quotations a
8026                                WHERE
8027                                    a.budget_status_id = (SELECT budget_status_id FROM tbl_budget_status WHERE name = 'Validado')
8028                                    AND a.total_sent = 0
8029                                    AND a.for_add = 0
8030                                    {$where}
8031                                ";
8032
8033                $result = DB::select($query);
8034
8035                $totalSendToClient = $result[0]->total;
8036            }
8037
8038            return response([
8039                'message' => 'OK',
8040                'userId' => ($user) ? $user->id : null,
8041                'totalPendingFollowUps' => $totalPendingFollowUps,
8042                'totalRequestAndVisit' => $totalRequestAndVisit,
8043                'totalError' => $totalError,
8044                'totalG3WError' => $totalG3WError,
8045                'totalSendToClient' => $totalSendToClient,
8046            ]);
8047
8048        } catch (\Exception $e) {
8049            /** @disregard P1014 */
8050            $e->exceptionCode = 'GET_TOTAL_QUPTATIONS_BY_BUDGET_STATUS_EXCEPTION';
8051            report($e);
8052
8053            return response(['message' => 'KO', 'error' => $e->getMessage()]);
8054        }
8055
8056    }
8057
8058    public function sendgrid_webhook_receiver(Request $request)
8059    {
8060
8061        try {
8062
8063            $data = $request->all();
8064
8065            $jsonBody = [];
8066            $order = [];
8067            $orderEmails = [];
8068
8069            Log::channel('email_log')->info('WEBHOOK: '.json_encode($data));
8070
8071            $quoteId = null;
8072
8073            foreach ($data as $item) {
8074                $matches = explode('.', $item['sg_message_id']);
8075                $messageId = $matches[0];
8076
8077                Log::channel('email_log')->info('MESSAGE-ID: '.$messageId);
8078
8079                $result = TblSendgridWebhook::where('x_message_id', $messageId)->first();
8080                $quoteId = $result->quotation_id;
8081                Log::channel('email_log')->info('SENDGRID-BODY: '.json_encode($result));
8082
8083                if (empty($order)) {
8084                    $order = TblQuotations::where('x_message_id', $messageId)->first();
8085                    $quoteId = $order->id;
8086                    // if(env('SENDGRID_STAGING')){
8087                    //     $user = TblUsers::where('name', $order->updated_by)->first();
8088
8089                    //     $orderEmails = array($user->email);
8090                    // }else{
8091                    $orderEmails = explode(',', $order->email);
8092                    // }
8093                }
8094
8095                // if(in_array($item['email'], $orderEmails)){
8096                if ($result->json_body == null) {
8097                    array_push($jsonBody, $item);
8098                } else {
8099                    $jsonBody = json_decode($result->json_body);
8100                    array_push($jsonBody, $item);
8101                }
8102                // }
8103
8104                Log::channel('email_log')->info('JSON-BODY: '.json_encode($jsonBody));
8105
8106                TblSendgridWebhook::where('x_message_id', $messageId)->update(
8107                    [
8108                        'json_body' => json_encode($jsonBody),
8109                        'updated_at' => date('Y-m-d H:i:s'),
8110                    ]
8111                );
8112
8113                if ($quoteId != null) {
8114                    $this->get_files($quoteId);
8115                }
8116
8117                Cache::flush();
8118            }
8119
8120        } catch (\Exception $e) {
8121            /** @disregard P1014 */
8122            $e->exceptionCode = 'SENDGRID_WEBHOOK_RECEIVER_EXCEPTION';
8123            report($e);
8124
8125            return response(['message' => 'KO', 'error' => $e->getMessage()]);
8126        }
8127
8128    }
8129
8130    public function isEmailValid($email)
8131    {
8132        // Regular expression pattern for email validation
8133        $pattern = '/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/';
8134
8135        // Check if the email matches the pattern
8136        if (preg_match($pattern, $email)) {
8137            return true; // Valid email
8138        } else {
8139            return false; // Invalid email
8140        }
8141    }
8142
8143    public function list_email_status($companyId)
8144    {
8145        try {
8146            $params = [];
8147
8148            if ($companyId != 0) {
8149                $where = ' company_id = ? ';
8150                $params[] = $companyId;
8151            } else {
8152                $ids = is_string($this->companyId) ? explode(',', $this->companyId) : $this->companyId;
8153                $ids = array_filter((array) $ids);
8154
8155                if (empty($ids)) {
8156                    return response(['message' => 'OK', 'data' => []]);
8157                }
8158
8159                $placeholders = implode(',', array_fill(0, count($ids), '?'));
8160                $where = " company_id IN ($placeholders";
8161                $params = array_values($ids);
8162            }
8163
8164            $query = "SELECT DISTINCT x_status FROM tbl_quotations WHERE {$where} AND x_status IS NOT NULL";
8165            $result = DB::select($query, $params);
8166
8167            return response([
8168                'message' => 'OK',
8169                'data' => $result,
8170            ]);
8171
8172        } catch (\Exception $e) {
8173            report($e);
8174
8175            return response(['message' => 'KO', 'error' => $e->getMessage()], 500);
8176        }
8177    }
8178
8179    public function list_quotation_analytics_commercial(Request $request)
8180    {
8181
8182        try {
8183
8184            $data = $request->all();
8185            $companyId = addslashes($data['company_id']);
8186            $field = $data['field'];
8187
8188            $where = '';
8189            $whereYear = '';
8190            $dateLflArray = [];
8191            $companyIds = $this->companyIds;
8192            $whereQ = '';
8193
8194            $acc = '';
8195            if ($field == 'acceptance_date') {
8196                $acc = ' AND q.acceptance_date IS NOT NULL ';
8197                // $field = 'created_at';
8198
8199                if (@$data['data_to_display'] == 4) {
8200                    $field = 'created_at';
8201                    $where .= ' AND YEAR(q.created_at) = YEAR(q.issue_date)';
8202                    $whereQ .= ' AND YEAR(q.created_at) = YEAR(q.issue_date)';
8203                }
8204            } else {
8205                $field = 'created_at';
8206                $where .= ' AND YEAR(q.created_at) = YEAR(q.issue_date)';
8207                $whereQ .= ' AND YEAR(q.created_at) = YEAR(q.issue_date)';
8208            }
8209
8210            if (isset($data['years']) && $data['years'] != null) {
8211                $years = implode(',', $data['years']);
8212                if (count($data['years']) > 0) {
8213                    $whereYear = " AND YEAR(q.{$field}) IN ({$years})";
8214                }
8215            }
8216
8217            if ($companyId != 0) {
8218                $companyIds = [$companyId];
8219            }
8220
8221            foreach ($companyIds as $v) {
8222
8223                $lflWhere = " AND q.company_id = {$v} ";
8224
8225                $query = "SELECT
8226                            CONCAT(
8227                                DATE_FORMAT((SELECT MIN(q.{$field}) FROM tbl_quotations q WHERE q.{$field} IS NOT NULL {$lflWhere}), '%c/%e/'), YEAR({$field}),
8228                                ' - ',
8229                                DATE_FORMAT((SELECT MAX(q.{$field}) FROM tbl_quotations q WHERE q.{$field} IS NOT NULL {$lflWhere}), '%c/%e/'), YEAR({$field})
8230                            ) AS date_like,
8231                            YEAR(q.{$field}) 'year',
8232                            DATE_FORMAT((SELECT MIN(q.{$field}) FROM tbl_quotations q WHERE q.{$field} IS NOT NULL {$lflWhere}), '%m-%d') AS min_date_like,
8233                            DATE_FORMAT((SELECT MAX(q.{$field}) FROM tbl_quotations q WHERE q.{$field} IS NOT NULL {$lflWhere}), '%m-%d') AS max_date_like,
8234                            {$v} 'company_id'
8235                        FROM
8236                            tbl_quotations q
8237                        WHERE
8238                            q.{$field} IS NOT NULL
8239                            AND q.for_add = 0
8240                            {$lflWhere}
8241                            {$whereYear}
8242                        GROUP BY YEAR(q.{$field})
8243                        ORDER BY YEAR(q.{$field}) DESC";
8244
8245                $dateLike = DB::select($query);
8246
8247                $dateLflArray[$v] = $dateLike;
8248            }
8249
8250            $isFy = true;
8251
8252            if (isset($data['ytd']) && $data['ytd'] != null && $data['ytd'] == true) {
8253                $isFy = false;
8254                $ytdArray = [];
8255                $ytdAcceptanceArray = [];
8256                $lflCompanyIds = [];
8257                foreach ($dateLflArray as $k => $v) {
8258                    foreach ($dateLflArray[$k] as $item) {
8259                        $year = $item->year;
8260                        $now = date('m-d');
8261                        array_push($ytdArray, "DATE_FORMAT(q.{$field}, '%Y-%m-%d') BETWEEN '{$year}-01-01' AND '{$year}-{$now}'");
8262                    }
8263
8264                    $ytdArray = implode(' OR ', $ytdArray);
8265                    array_push($lflCompanyIds, "q.company_id = {$k} AND ({$ytdArray})");
8266                    $ytdArray = [];
8267                }
8268
8269                $lflCompanyIds = implode(' OR ', $lflCompanyIds);
8270                $where .= " AND ({$lflCompanyIds}";
8271                $whereQ .= " AND ({$lflCompanyIds}";
8272            }
8273
8274            if (isset($data['lfl']) && $data['lfl'] != null && $data['lfl'] == true) {
8275                $isFy = false;
8276                $lflArray = [];
8277                $ytdAcceptanceArray = [];
8278                $lflCompanyIds = [];
8279                foreach ($dateLflArray as $k => $v) {
8280                    foreach ($dateLflArray[$k] as $item) {
8281                        $year = $item->year;
8282                        $min_date_like = $item->min_date_like;
8283                        $max_date_like = $item->max_date_like;
8284                        array_push($lflArray, "DATE_FORMAT(q.{$field}, '%Y-%m-%d') BETWEEN LEAST('{$year}-{$min_date_like}', '{$year}-{$max_date_like}') AND GREATEST('{$year}-{$min_date_like}', '{$year}-{$max_date_like}')");
8285                    }
8286
8287                    $lflArray = implode(' OR ', $lflArray);
8288                    array_push($lflCompanyIds, "q.company_id = {$k} AND ({$lflArray})");
8289                    $lflArray = [];
8290                }
8291
8292                $lflCompanyIds = implode(' OR ', $lflCompanyIds);
8293                $where .= " AND ({$lflCompanyIds}";
8294                $whereQ .= " AND ({$lflCompanyIds}";
8295            }
8296
8297            if ($isFy) {
8298                if ($companyId != 0) {
8299                    $where .= " AND q.company_id = {$companyId} ";
8300                    $whereQ .= " AND q.company_id = {$companyId} ";
8301                } else {
8302                    $where .= " AND q.company_id IN ({$this->companyId})";
8303                    $whereQ .= " AND q.company_id IN ({$this->companyId})";
8304                }
8305            }
8306
8307            if (isset($data['source']) && $data['source'] != null) {
8308                $where .= " AND s.name = '{$data['source']}'";
8309            }
8310
8311            if (isset($data['month']) && $data['month'] != null) {
8312                $where .= " AND MONTH(q.{$field}) = '{$data['month']}'";
8313            }
8314
8315            if (isset($data['week']) && $data['week'] != null) {
8316                $where .= " AND WEEK(q.{$field}) = '{$data['week']}'";
8317            }
8318
8319            if (isset($data['commercial']) && $data['commercial'] != null) {
8320                $where .= " AND q.commercial = '{$data['commercial']}'";
8321            }
8322
8323            if (isset($data['created_by']) && $data['created_by'] != null) {
8324                $where .= " AND q.created_by = '{$data['created_by']}'";
8325            }
8326
8327            if (isset($data['budget_type']) && $data['budget_type'] != null) {
8328                $where .= " AND bt.budget_type_id = {$data['budget_type']}";
8329            }
8330
8331            if (isset($data['budget_type_group']) && $data['budget_type_group'] != null) {
8332                $where .= " AND bt.budget_type_group_id = {$data['budget_type_group']}";
8333            }
8334
8335            if (isset($data['budget_status']) && $data['budget_status'] != null) {
8336                $where .= " AND bs.budget_status_id = {$data['budget_status']}";
8337            }
8338
8339            if (isset($data['client_type']) && $data['client_type'] != null) {
8340                $where .= " AND ct.customer_type_id = {$data['client_type']}";
8341            }
8342
8343            if (isset($data['segment_id']) && $data['segment_id'] != null) {
8344                $where .= " AND q.segment_id = {$data['segment_id']}";
8345            }
8346
8347            $col = '1';
8348
8349            if (isset($data['data_to_display']) && $data['data_to_display'] != null) {
8350                if ($data['data_to_display'] == 1) {
8351                    $col = '1';
8352                }
8353
8354                if ($data['data_to_display'] == 2) {
8355                    $col = 'q.amount';
8356                }
8357            }
8358
8359            $query = "SELECT
8360                        q.commercial 'name',
8361                        COUNT(q.commercial) totalCommercial
8362                    FROM tbl_quotations q
8363                    WHERE
8364                        q.for_add = 0
8365                        AND q.{$field} IS NOT NULL
8366                        {$whereQ}
8367                    GROUP BY q.commercial
8368                    HAVING COUNT(q.commercial) > 0
8369                    ORDER BY totalCommercial DESC";
8370
8371            $resultCommercials = DB::select($query);
8372
8373            $now = TblQuotations::whereIn('company_id', $this->companyIds)->orderBy($field, 'DESC')->value($field);
8374            $weekNumber = date('W', strtotime($now));
8375            $thisWeek = date('Y-m-d', strtotime($now.' - '.(date('N', strtotime($now)) - 1).' days'));
8376
8377            $query = "SELECT
8378                        q.commercial 'name',
8379                        COUNT(q.commercial) totalCommercial
8380                    FROM tbl_quotations q
8381                    WHERE
8382                        q.for_add = 0
8383                        AND q.{$field} IS NOT NULL
8384                        AND YEARWEEK(q.{$field}, 1) = YEARWEEK(NOW(), 1)
8385                        {$whereQ}
8386                    GROUP BY q.commercial
8387                    HAVING COUNT(q.commercial) > 0
8388                    ORDER BY totalCommercial DESC";
8389
8390            $resultCommercialsOrder = DB::select($query);
8391
8392            $namesToRemove = [];
8393
8394            foreach ($resultCommercialsOrder as $item) {
8395                $namesToRemove[$item->name] = true;
8396            }
8397
8398            $resultArray = [];
8399            foreach ($resultCommercials as $item) {
8400                if (! isset($namesToRemove[$item->name])) {
8401                    $resultArray[] = $item;
8402                }
8403            }
8404
8405            $resultCommercials = array_merge($resultCommercialsOrder, $resultArray);
8406
8407            $cols = '';
8408
8409            $colsGroupConcatIds = '';
8410
8411            foreach ($resultCommercials as $item) {
8412                $cols .= ",COALESCE(
8413                    SUM(
8414                        CASE WHEN q.commercial = '{$item->name}{$acc} THEN {$col} ELSE 0 END
8415                    ), 0
8416                ) '{$item->name}'";
8417
8418                $colsGroupConcatIds .= ",GROUP_CONCAT(CASE WHEN q.commercial = '{$item->name}{$acc} THEN q.id END) 'groupConcatIds-{$item->name}'";
8419            }
8420
8421            $cols .= ",COALESCE(
8422                SUM(
8423                    CASE WHEN q.commercial IS NOT NULL {$acc} THEN {$col} ELSE 0 END
8424                ), 0
8425            ) total";
8426
8427            if (@$data['data_to_display'] == 3) {
8428
8429                $cols = '';
8430
8431                foreach ($resultCommercials as $item) {
8432                    $cols .= ",COALESCE(
8433                        (
8434                            SUM(CASE WHEN q.commercial = '{$item->name}{$acc} THEN q.amount END)
8435                        ) /
8436                        (
8437                            SUM(CASE WHEN q.commercial = '{$item->name}{$acc} THEN 1 END)
8438                        )
8439                    , 0) '{$item->name}'";
8440                }
8441
8442                $cols .= ",COALESCE(
8443                    (
8444                        SUM(CASE WHEN q.commercial IS NOT NULL {$acc} THEN q.amount END)
8445                    ) /
8446                    (
8447                        SUM(CASE WHEN q.commercial IS NOT NULL {$acc} THEN 1 END)
8448                    )
8449                , 0) total";
8450            }
8451
8452            if (@$data['data_to_display'] == 4) {
8453
8454                $cols = '';
8455
8456                foreach ($resultCommercials as $item) {
8457                    $cols .= ",COALESCE(
8458                        (
8459                            SUM(CASE WHEN q.commercial = '{$item->name}' AND q.acceptance_date IS NOT NULL THEN 1 END)
8460                        ) /
8461                        (
8462                            SUM(CASE WHEN q.commercial = '{$item->name}' AND q.created_at IS NOT NULL THEN 1 END)
8463                        ) * 100
8464                    , 0) '{$item->name}'";
8465                }
8466
8467                $cols .= ',COALESCE(
8468                    (
8469                        SUM(CASE WHEN q.commercial IS NOT NULL AND q.acceptance_date IS NOT NULL THEN 1 END)
8470                    ) /
8471                    (
8472                        SUM(CASE WHEN q.commercial IS NOT NULL AND q.created_at IS NOT NULL THEN 1 END)
8473                    ) * 100
8474                , 0) total';
8475            }
8476
8477            $query = "SELECT
8478                            YEAR(DATE_ADD(q.{$field}, INTERVAL - WEEKDAY(q.{$field}) DAY)) AS 'year',
8479                            LPAD(MONTH(DATE_ADD(q.{$field}, INTERVAL - WEEKDAY(q.{$field}) DAY)), 2, 0) AS 'month',
8480                            LPAD(WEEK(DATE_ADD(q.{$field}, INTERVAL - WEEKDAY(q.{$field}) DAY)), 2, 0) AS 'week',
8481                            DATE_FORMAT(DATE_ADD(q.{$field}, INTERVAL - WEEKDAY(q.{$field}) DAY), '%W, %M %e') 'namedate',
8482                            GROUP_CONCAT(
8483                                CASE WHEN q.{$field} IS NOT NULL
8484                                THEN q.id END
8485                            ) AS groupConcatIds
8486                            {$colsGroupConcatIds}
8487                            {$cols}
8488                        FROM
8489                            tbl_quotations q
8490                            LEFT JOIN tbl_sources s ON s.source_id = q.source_id
8491                            LEFT JOIN tbl_budget_status bs ON bs.budget_status_id = q.budget_status_id
8492                            LEFT JOIN tbl_budget_types bt ON q.budget_type_id = bt.budget_type_id
8493                            LEFT JOIN tbl_budget_type_groups btg ON bt.budget_type_group_id = btg.budget_type_group_id
8494                            LEFT JOIN tbl_customer_types ct ON q.customer_type_id = ct.customer_type_id
8495                        WHERE
8496                            q.{$field} IS NOT NULL
8497                            AND q.for_add = 0
8498                            AND q.budget_type_id != 7
8499                            AND q.budget_type_id IS NOT NULL
8500                            AND q.amount REGEXP '^[0-9]+\\.?[0-9]*$' = 1
8501                            {$where}
8502                            {$whereYear}
8503                        GROUP BY
8504                            YEAR(DATE_ADD(q.{$field}, INTERVAL - WEEKDAY(q.{$field}) DAY)),
8505                            MONTH(DATE_ADD(q.{$field}, INTERVAL - WEEKDAY(q.{$field}) DAY)),
8506                            WEEK(DATE_ADD(q.{$field}, INTERVAL - WEEKDAY(q.{$field}) DAY)) WITH ROLLUP
8507                        ORDER BY
8508                            YEAR DESC,
8509                            MONTH ASC,
8510                            WEEK ASC,
8511                            DATE_FORMAT(q.{$field}, '%e') ASC";
8512
8513            $value = Cache::get(base64_encode($query));
8514
8515            if (! $value) {
8516                $result = DB::select($query);
8517
8518                Cache::put(base64_encode($query), $result, 600);
8519            } else {
8520                $result = $value;
8521            }
8522
8523            return response([
8524                'message' => 'OK',
8525                'data' => $result,
8526                'commercials' => $resultCommercials,
8527            ]);
8528
8529        } catch (\Exception $e) {
8530            /** @disregard P1014 */
8531            $e->exceptionCode = 'LIST_QUOTATION_ANALYTICS_COMMERCIAL_EXCEPTION';
8532            report($e);
8533
8534            return response(['message' => 'KO', 'error' => $e->getMessage()]);
8535        }
8536    }
8537
8538    public function clear_open_data($companyId)
8539    {
8540
8541        try {
8542
8543            $companyIds = [$companyId];
8544            if ($companyId == 0) {
8545                $companyIds = $this->companyIds;
8546            }
8547
8548            $user = TblUsers::where('id', $this->userId)->first();
8549
8550            if (count($companyIds) > 0) {
8551
8552                foreach ($companyIds as $id) {
8553                    $startedAt = date('Y-m-d H:i:s');
8554                    $affectedRows = DB::delete("DELETE FROM tbl_quotations WHERE company_id = {$id} AND for_add = 1 AND DATE_FORMAT(created_at, '%Y-%m-%d') != DATE_FORMAT(NOW(), '%Y-%m-%d')");
8555
8556                    TblOrdersUpdateLogs::create(
8557                        [
8558                            'company_id' => $id,
8559                            'to_process' => 'Orders',
8560                            'status' => 'success',
8561                            'for_add_deleted_affected_rows' => $affectedRows,
8562                            'processed_by' => $user->name,
8563                            'started_at' => $startedAt,
8564                            'ended_at' => date('Y-m-d H:i:s'),
8565                        ]
8566                    );
8567                }
8568            }
8569
8570            return response([
8571                'message' => 'OK',
8572            ]);
8573
8574        } catch (\Exception $e) {
8575            /** @disregard P1014 */
8576            $e->exceptionCode = 'CLEAR_OPEN_DATA_EXCEPTION';
8577            report($e);
8578
8579            return response(['message' => 'KO', 'error' => $e->getMessage()]);
8580        }
8581
8582    }
8583
8584    public function list_quotation_analytics_order_size(Request $request)
8585    {
8586
8587        try {
8588
8589            $data = $request->all();
8590            $companyId = addslashes($data['company_id']);
8591            $field = $data['field'];
8592
8593            $where = '';
8594            $dateLflArray = [];
8595            $whereYear = '';
8596            $companyIds = $this->companyIds;
8597
8598            if ($field == 'acceptance_date') {
8599                if (@$data['data_to_display'] == 4) {
8600                    $field = 'created_at';
8601                    $where .= ' AND YEAR(q.created_at) = YEAR(q.issue_date)';
8602                }
8603            } else {
8604                $field = 'created_at';
8605                $where .= ' AND YEAR(q.created_at) = YEAR(q.issue_date)';
8606            }
8607
8608            if (isset($data['years']) && $data['years'] != null) {
8609                $years = implode(',', $data['years']);
8610                if (count($data['years']) > 0) {
8611                    $whereYear = " AND YEAR(q.{$field}) IN ({$years})";
8612                }
8613            }
8614
8615            if ($companyId != 0) {
8616                $companyIds = [$companyId];
8617            }
8618
8619            foreach ($companyIds as $v) {
8620
8621                $lflWhere = " AND q.company_id = {$v} ";
8622
8623                $query = "SELECT
8624                            CONCAT(
8625                                DATE_FORMAT((SELECT MIN(q.{$field}) FROM tbl_quotations q WHERE q.{$field} IS NOT NULL {$lflWhere}), '%c/%e/'), YEAR({$field}),
8626                                ' - ',
8627                                DATE_FORMAT((SELECT MAX(q.{$field}) FROM tbl_quotations q WHERE q.{$field} IS NOT NULL {$lflWhere}), '%c/%e/'), YEAR({$field})
8628                            ) AS date_like,
8629                            YEAR(q.{$field}) 'year',
8630                            DATE_FORMAT((SELECT MIN(q.{$field}) FROM tbl_quotations q WHERE q.{$field} IS NOT NULL {$lflWhere}), '%m-%d') AS min_date_like,
8631                            DATE_FORMAT((SELECT MAX(q.{$field}) FROM tbl_quotations q WHERE q.{$field} IS NOT NULL {$lflWhere}), '%m-%d') AS max_date_like,
8632                            {$v} 'company_id'
8633                        FROM
8634                            tbl_quotations q
8635                        WHERE
8636                            q.{$field} IS NOT NULL
8637                            AND q.for_add = 0
8638                            {$lflWhere}
8639                            {$whereYear}
8640                        GROUP BY YEAR(q.{$field})
8641                        ORDER BY YEAR(q.{$field}) DESC";
8642
8643                $dateLike = DB::select($query);
8644
8645                $dateLflArray[$v] = $dateLike;
8646            }
8647
8648            $isFy = true;
8649
8650            if (isset($data['ytd']) && $data['ytd'] != null && $data['ytd'] == true) {
8651                $isFy = false;
8652                $ytdArray = [];
8653                $ytdAcceptanceArray = [];
8654                $lflCompanyIds = [];
8655                foreach ($dateLflArray as $k => $v) {
8656                    foreach ($dateLflArray[$k] as $item) {
8657                        $year = $item->year;
8658                        $now = date('m-d');
8659                        array_push($ytdArray, "DATE_FORMAT(q.{$field}, '%Y-%m-%d') BETWEEN '{$year}-01-01' AND '{$year}-{$now}'");
8660                    }
8661
8662                    $ytdArray = implode(' OR ', $ytdArray);
8663                    array_push($lflCompanyIds, "q.company_id = {$k} AND ({$ytdArray})");
8664                    $ytdArray = [];
8665                }
8666
8667                $lflCompanyIds = implode(' OR ', $lflCompanyIds);
8668                $where .= " AND ({$lflCompanyIds}";
8669            }
8670
8671            if (isset($data['lfl']) && $data['lfl'] != null && $data['lfl'] == true) {
8672                $isFy = false;
8673                $lflArray = [];
8674                $ytdAcceptanceArray = [];
8675                $lflCompanyIds = [];
8676                foreach ($dateLflArray as $k => $v) {
8677                    foreach ($dateLflArray[$k] as $item) {
8678                        $year = $item->year;
8679                        $min_date_like = $item->min_date_like;
8680                        $max_date_like = $item->max_date_like;
8681                        array_push($lflArray, "DATE_FORMAT(q.{$field}, '%Y-%m-%d') BETWEEN LEAST('{$year}-{$min_date_like}', '{$year}-{$max_date_like}') AND GREATEST('{$year}-{$min_date_like}', '{$year}-{$max_date_like}')");
8682                    }
8683
8684                    $lflArray = implode(' OR ', $lflArray);
8685                    array_push($lflCompanyIds, "q.company_id = {$k} AND ({$lflArray})");
8686                    $lflArray = [];
8687                }
8688
8689                $lflCompanyIds = implode(' OR ', $lflCompanyIds);
8690                $where .= " AND ({$lflCompanyIds}";
8691            }
8692
8693            if ($isFy) {
8694                if ($companyId != 0) {
8695                    $where .= " AND q.company_id = {$companyId} ";
8696                } else {
8697                    $where .= " AND q.company_id IN ({$this->companyId})";
8698                }
8699            }
8700
8701            if (isset($data['source']) && $data['source'] != null) {
8702                $where .= " AND s.name = '{$data['source']}'";
8703            }
8704
8705            if (isset($data['source']) && $data['source'] != null) {
8706                $where .= " AND s.name = '{$data['source']}'";
8707            }
8708
8709            if (isset($data['commercial']) && $data['commercial'] != null) {
8710                $where .= " AND q.commercial = '{$data['commercial']}'";
8711            }
8712
8713            if (isset($data['created_by']) && $data['created_by'] != null) {
8714                $where .= " AND q.created_by = '{$data['created_by']}'";
8715            }
8716
8717            if (isset($data['budget_type']) && $data['budget_type'] != null) {
8718                $where .= " AND bt.budget_type_id = {$data['budget_type']}";
8719            }
8720
8721            if (isset($data['budget_type_group']) && $data['budget_type_group'] != null) {
8722                $where .= " AND bt.budget_type_group_id = {$data['budget_type_group']}";
8723            }
8724
8725            if (isset($data['budget_status']) && $data['budget_status'] != null) {
8726                $where .= " AND bs.budget_status_id = {$data['budget_status']}";
8727            }
8728
8729            if (isset($data['client_type']) && $data['client_type'] != null) {
8730                $where .= " AND ct.customer_type_id = {$data['client_type']}";
8731            }
8732
8733            if (isset($data['segment_id']) && $data['segment_id'] != null) {
8734                $where .= " AND q.segment_id = {$data['segment_id']}";
8735            }
8736
8737            $col = 'q.one';
8738
8739            if (isset($data['data_to_display']) && $data['data_to_display'] != null) {
8740                if ($data['data_to_display'] == 1) {
8741                    $col = 'q.one';
8742                }
8743
8744                if ($data['data_to_display'] == 2) {
8745                    $col = 'q.amount';
8746                }
8747            }
8748
8749            if ((isset($data['start_date']) && $data['start_date'] != null) && isset($data['end_date']) && $data['end_date'] != null) {
8750                $where .= " AND q.{$field} BETWEEN '{$data['start_date']}' AND '{$data['end_date']}";
8751            } elseif ((isset($data['start_date']) && $data['start_date'] == null || $data['start_date'] == '') && isset($data['end_date']) && $data['end_date'] != null) {
8752                $where .= " AND q.{$field} = '{$data['end_date']}";
8753            }
8754
8755            $whereQ = $where;
8756
8757            $sortBy = [
8758                0 => 'q.amount < 100',
8759                1 => 'q.amount BETWEEN 100 AND 500',
8760                2 => 'q.amount BETWEEN 500 AND 2000',
8761                3 => 'q.amount BETWEEN 2000 AND 10000',
8762                4 => 'q.amount BETWEEN 10000 AND 30000',
8763                5 => 'q.amount BETWEEN 30000 AND 100000',
8764                6 => 'q.amount BETWEEN 100000 AND 999999999999',
8765            ];
8766
8767            $query = "SELECT
8768                        q.commercial 'name',
8769                        COUNT(q.commercial) totalCommercial
8770                    FROM tbl_quotations q
8771                    LEFT JOIN tbl_sources s ON s.source_id = q.source_id
8772                    LEFT JOIN tbl_budget_status bs ON bs.budget_status_id = q.budget_status_id
8773                    LEFT JOIN tbl_budget_types bt ON q.budget_type_id = bt.budget_type_id
8774                    LEFT JOIN tbl_customer_types ct ON q.customer_type_id = ct.customer_type_id
8775                    WHERE
8776                        q.for_add = 0
8777                        AND q.{$field} IS NOT NULL                        
8778                        AND q.budget_type_id != 7
8779                        AND q.budget_type_id IS NOT NULL
8780                        {$whereQ}
8781                        {$whereYear}
8782                    GROUP BY q.commercial
8783                    HAVING COUNT(q.commercial) > 0
8784                    ORDER BY totalCommercial DESC";
8785
8786            $resultCommercials = DB::select($query);
8787
8788            if (isset($data['sort_by'])) {
8789                if ($data['sort_by'] != 7) {
8790                    $s = $sortBy[$data['sort_by']];
8791                    $whereQ .= " AND {$s} ";
8792                }
8793            }
8794
8795            $num = 'COUNT(1)';
8796
8797            if (@$data['data_to_display'] == 2) {
8798                $num = 'SUM(q.amount)';
8799            }
8800
8801            if (@$data['data_to_display'] == 3) {
8802                $num = 'SUM(q.amount) / COUNT(1)';
8803            }
8804
8805            if (@$data['data_to_display'] == 4) {
8806                $num = '(SUM(CASE WHEN q.acceptance_date IS NOT NULL THEN 1 ELSE 0 END) / COUNT(q.created_at) * 100)';
8807            }
8808
8809            $query = "SELECT
8810                    q.commercial 'name',
8811                    COUNT(q.commercial) totalCommercial,
8812                    {$num} num
8813                FROM tbl_quotations q
8814                LEFT JOIN tbl_sources s ON s.source_id = q.source_id
8815                LEFT JOIN tbl_budget_status bs ON bs.budget_status_id = q.budget_status_id
8816                LEFT JOIN tbl_budget_types bt ON q.budget_type_id = bt.budget_type_id
8817                LEFT JOIN tbl_customer_types ct ON q.customer_type_id = ct.customer_type_id
8818                WHERE
8819                    q.for_add = 0
8820                    AND q.{$field} IS NOT NULL                    
8821                    AND q.budget_type_id != 7
8822                    AND q.budget_type_id IS NOT NULL
8823                    {$whereQ}
8824                    {$whereYear}
8825                GROUP BY q.commercial
8826                HAVING COUNT(q.commercial) > 0
8827                ORDER BY num DESC";
8828
8829            $resultCommercialsOrder = DB::select($query);
8830
8831            foreach ($resultCommercialsOrder as $item) {
8832                $namesToRemove[$item->name] = true;
8833            }
8834
8835            $resultArray = [];
8836            foreach ($resultCommercials as $item) {
8837                if (! isset($namesToRemove[$item->name])) {
8838                    $resultArray[] = $item;
8839                }
8840            }
8841
8842            $resultCommercials = array_merge($resultCommercialsOrder, $resultArray);
8843
8844            $cols = '';
8845
8846            $colsGroupConcatIds = '';
8847
8848            foreach ($resultCommercials as $item) {
8849                $cols .= ",COALESCE(
8850                    SUM(
8851                        CASE WHEN q.commercial = '{$item->name}' THEN {$col} ELSE 0 END
8852                    ), 0
8853                ) '{$item->name}'";
8854
8855                $colsGroupConcatIds .= ",GROUP_CONCAT(CASE WHEN q.commercial = '{$item->name}' THEN q.id END) 'groupConcatIds-{$item->name}'";
8856            }
8857
8858            $cols .= ",COALESCE(
8859                SUM(
8860                    CASE WHEN q.commercial IS NOT NULL THEN {$col} ELSE 0 END
8861                ), 0
8862            ) total";
8863
8864            $range = "CASE
8865                        WHEN amount < 100 THEN '< 100€'
8866                        WHEN amount BETWEEN 100 AND 500 THEN '100€ - 500€'
8867                        WHEN amount BETWEEN 500 AND 2000 THEN '500€ - 2k€'
8868                        WHEN amount BETWEEN 2000 AND 10000 THEN '2k€ - 10k€'
8869                        WHEN amount BETWEEN 10000 AND 30000 THEN '10k€ - 30k€'
8870                        WHEN amount BETWEEN 30000 AND 100000 THEN '30k€ - 100k€'
8871                        WHEN amount BETWEEN 100000 AND 999999999999 THEN '> 100k€'
8872                    END AS amount_range";
8873
8874            if (@$data['data_to_display'] == 3) {
8875
8876                $range = "CASE
8877                            WHEN SUM(amount) / COUNT(1) < 100 THEN '< 100€'
8878                            WHEN SUM(amount) / COUNT(1) BETWEEN 100 AND 500 THEN '100€ - 500€'
8879                            WHEN SUM(amount) / COUNT(1) BETWEEN 500 AND 2000 THEN '500€ - 2k€'
8880                            WHEN SUM(amount) / COUNT(1) BETWEEN 2000 AND 10000 THEN '2k€ - 10k€'
8881                            WHEN SUM(amount) / COUNT(1) BETWEEN 10000 AND 30000 THEN '10k€ - 30k€'
8882                            WHEN SUM(amount) / COUNT(1) BETWEEN 30000 AND 100000 THEN '30k€ - 100k€'
8883                            WHEN SUM(amount) / COUNT(1) BETWEEN 100000 AND 999999999999 THEN '> 100k€'
8884                        END AS amount_range";
8885
8886                $cols = '';
8887
8888                foreach ($resultCommercials as $item) {
8889                    $cols .= ",COALESCE(
8890                        (
8891                            SUM(CASE WHEN q.commercial = '{$item->name}' THEN q.amount END)
8892                        ) /
8893                        (
8894                            SUM(CASE WHEN q.commercial = '{$item->name}' THEN q.one END)
8895                        )
8896                    , 0) '{$item->name}'";
8897                }
8898
8899                $cols .= ',COALESCE(
8900                    (
8901                        SUM(CASE WHEN q.commercial IS NOT NULL THEN q.amount END)
8902                    ) /
8903                    (
8904                        SUM(CASE WHEN q.commercial IS NOT NULL THEN q.one END)
8905                    )
8906                , 0) total';
8907            }
8908
8909            if (@$data['data_to_display'] == 4) {
8910
8911                $cols = '';
8912
8913                foreach ($resultCommercials as $item) {
8914                    $cols .= ",COALESCE(
8915                        (
8916                            SUM(CASE WHEN q.commercial = '{$item->name}' THEN q.acceptanceDate END)
8917                        ) /
8918                        (
8919                            SUM(CASE WHEN q.commercial = '{$item->name}' THEN q.createdAt END)
8920                        ) * 100
8921                    , 0) '{$item->name}'";
8922                }
8923
8924                $cols .= ',COALESCE(
8925                    (
8926                        SUM(CASE WHEN q.commercial IS NOT NULL THEN q.acceptanceDate END)
8927                    ) /
8928                    (
8929                        SUM(CASE WHEN q.commercial IS NOT NULL THEN q.createdAt END)
8930                    ) * 100
8931                , 0) total';
8932            }
8933
8934            $query = "WITH amount_ranges AS (
8935                            SELECT '< 100€' AS amount_range
8936                            UNION ALL SELECT '100€ - 500€'
8937                            UNION ALL SELECT '500€ - 2k€'
8938                            UNION ALL SELECT '2k€ - 10k€'
8939                            UNION ALL SELECT '10k€ - 30k€'
8940                            UNION ALL SELECT '30k€ - 100k€'
8941                            UNION ALL SELECT '> 100k€'
8942                        )
8943
8944                        SELECT
8945                            ar.amount_range,
8946                             GROUP_CONCAT(
8947                                q.id
8948                            ) AS groupConcatIds
8949                            {$colsGroupConcatIds}
8950                            {$cols}
8951                        FROM
8952                            amount_ranges ar
8953                        LEFT JOIN (
8954                            SELECT
8955                                commercial,
8956                                GROUP_CONCAT(
8957                                    CASE WHEN q.{$field} IS NOT NULL THEN id END
8958                                ) id,
8959                                amount AS amount,
8960                                COUNT(CASE WHEN q.created_at IS NOT NULL THEN 1 END) createdAt,
8961                                COUNT(CASE WHEN q.acceptance_date IS NOT NULL THEN 1 END) acceptanceDate,
8962                                COUNT(1) AS one,
8963                                {$range}
8964                            FROM
8965                                tbl_quotations q
8966                                LEFT JOIN tbl_sources s ON s.source_id = q.source_id
8967                                LEFT JOIN tbl_budget_status bs ON bs.budget_status_id = q.budget_status_id
8968                                LEFT JOIN tbl_budget_types bt ON q.budget_type_id = bt.budget_type_id
8969                                LEFT JOIN tbl_customer_types ct ON q.customer_type_id = ct.customer_type_id
8970                            WHERE
8971                                q.{$field} IS NOT NULL
8972                                AND q.for_add = 0                                
8973                                AND q.budget_type_id != 7
8974                                AND q.budget_type_id IS NOT NULL
8975                                AND q.amount REGEXP '^[0-9]+\\.?[0-9]*$' = 1
8976                                {$where}
8977                                {$whereYear}
8978                            GROUP BY
8979                                commercial,
8980                                id
8981                        ) AS q ON ar.amount_range = q.amount_range
8982                        GROUP BY
8983                            ar.amount_range WITH ROLLUP
8984                        ORDER BY
8985                            CASE
8986                                WHEN ar.amount_range = '< 100€' THEN 1
8987                                WHEN ar.amount_range = '100€ - 500€' THEN 2
8988                                WHEN ar.amount_range = '500€ - 2k€' THEN 3
8989                                WHEN ar.amount_range = '2k€ - 10k€' THEN 4
8990                                WHEN ar.amount_range = '10k€ - 30k€' THEN 5
8991                                WHEN ar.amount_range = '30k€ - 100k€' THEN 6
8992                                ELSE 7
8993                            END";
8994
8995            $value = Cache::get(base64_encode($query));
8996
8997            if (! $value) {
8998                $result = DB::select($query);
8999
9000                Cache::put(base64_encode($query), $result, 600);
9001            } else {
9002                $result = $value;
9003            }
9004
9005            return response([
9006                'message' => 'OK',
9007                'data' => $result,
9008                'commercials' => $resultCommercials,
9009            ]);
9010
9011        } catch (\Exception $e) {
9012            /** @disregard P1014 */
9013            $e->exceptionCode = 'LIST_QUOTATION_ANALYTICS_COMMERCIAL_EXCEPTION';
9014            report($e);
9015
9016            return response(['message' => 'KO', 'error' => $e->getMessage()]);
9017        }
9018
9019    }
9020
9021    public function send_email_template_preview($emailTemplateId)
9022    {
9023
9024        try {
9025
9026            $emailTemplateId = addslashes($emailTemplateId);
9027
9028            $emailTemplate = TblEmailConfiguration::where('id', $emailTemplateId)->first();
9029
9030            $user = TblUsers::where('id', $this->userId)->first();
9031            $error = false;
9032
9033            $toEmail = $user->email;
9034
9035            $availableParameters = [
9036                'quote_id',
9037                'company_id',
9038                'client',
9039                'client_type',
9040                'phone_number',
9041                'email',
9042                'issue_date',
9043                'request_date',
9044                'duration',
9045                'invoice_number',
9046                'type',
9047                'acceptance_date',
9048                'status',
9049                'source',
9050                'amount',
9051                'reason_for_not_following_up',
9052                'last_follow_up_date',
9053                'last_follow_up_comment',
9054                'reason_for_rejection_id',
9055                'reason_for_rejection',
9056                'commercial',
9057                'created_at',
9058                'created_by',
9059                'updated_at',
9060                'updated_by',
9061            ];
9062
9063            $dateParameters = [
9064                'issue_date',
9065                'request_date',
9066                'acceptance_date',
9067                'last_follow_up_date',
9068                'created_at',
9069                'updated_at',
9070            ];
9071
9072            if ($this->locale == 'es') {
9073                setlocale(LC_ALL, 'es_ES', 'Spanish_Spain', 'Spanish');
9074            }
9075
9076            if ($this->locale == 'es') {
9077                setlocale(LC_ALL, 'es_ES', 'Spanish_Spain', 'Spanish');
9078            }
9079
9080            $body = $emailTemplate->html;
9081            $subject = $emailTemplate->subject;
9082
9083            preg_match_all('/{{(.*?)}}/', $body, $matches);
9084
9085            $parameters = $matches[1];
9086
9087            $result = TblQuotations::where('for_add', 0)->whereIn('company_id', $this->companyIds)->first();
9088
9089            foreach ($parameters as $parameter) {
9090
9091                if (in_array($parameter, $dateParameters)) {
9092                    if ($result->{$parameter}) {
9093                        $result->{$parameter} = iconv('ISO-8859-2', 'UTF-8', strftime('%A, %B %d, %Y', strtotime($result->{$parameter})));
9094                    }
9095                }
9096
9097                if (in_array($parameter, $availableParameters)) {
9098                    $body = str_replace('{{'.$parameter.'}}', $result->{$parameter}, $body);
9099                }
9100            }
9101
9102            preg_match_all('/{{(.*?)}}/', $subject, $matches);
9103
9104            $parameters = $matches[1];
9105
9106            foreach ($parameters as $parameter) {
9107
9108                if (in_array($parameter, $dateParameters)) {
9109                    if ($result->{$parameter}) {
9110                        $result->{$parameter} = iconv('ISO-8859-2', 'UTF-8', strftime('%A, %B %d, %Y', strtotime($result->{$parameter})));
9111                    }
9112                }
9113
9114                if (in_array($parameter, $availableParameters)) {
9115                    $subject = str_replace('{{'.$parameter.'}}', $result->{$parameter}, $subject);
9116                }
9117            }
9118
9119            $email = new \SendGrid\Mail\Mail;
9120
9121            $templateFiles = TblEmailFiles::where('email_template_id', $emailTemplateId)->orderBy('order', 'asc')->get();
9122
9123            foreach ($templateFiles as $item) {
9124                $f = storage_path('app/public/uploads/'.$item->filename);
9125                $imgpath = file_get_contents($f);
9126                $mimeType = mime_content_type($f);
9127
9128                $email->addAttachment(
9129                    $imgpath,
9130                    $mimeType,
9131                    str_replace(' ', '', $item->original_name),
9132                    'inline',
9133                    str_replace(' ', '', $item->original_name),
9134                );
9135
9136                $body .= "<img src='cid:{$item->original_name}' style='height: 45px; padding-right: 6px' />";
9137            }
9138
9139            $html = '<!DOCTYPE html>';
9140            $html .= '<html>';
9141            $html .= '<head>';
9142            $html .= '<meta charset="UTF-8">';
9143            $html .= '<meta name="viewport" content="width=device-width, initial-scale=1.0">';
9144            $html .= '</head>';
9145            $html .= '<body>';
9146            $html .= $body;
9147            $html .= '</body>';
9148            $html .= '</html>';
9149
9150            if ($toEmail != null) {
9151
9152                $companyEmail = null;
9153
9154                if ($emailTemplate->from_id != null) {
9155                    $companyEmail = TblCompanyEmails::where('id', $emailTemplate->from_id)->first();
9156                } else {
9157                    $companyEmail = TblCompanyEmails::where('is_active', 1)->where('verified', 1)->where('company_id', $result->company_id)->first();
9158                }
9159
9160                if (! $companyEmail) {
9161                    return response(['message' => 'KO', 'error' => __('language.no_active_verified_sender')]);
9162                }
9163
9164                $email->setFrom($companyEmail->from_email, $companyEmail->from_name);
9165                $email->setSubject($subject);
9166                $email->addTo($toEmail);
9167                $email->addContent('text/html', $html);
9168
9169                $sendgrid = new \SendGrid(env('SENDGRID_API_KEY'));
9170
9171                $response = $sendgrid->send($email);
9172                if ($response->statusCode() == 202) {
9173                    return response(['message' => 'OK']);
9174                }
9175            }
9176
9177            return response(['message' => 'KO']);
9178
9179        } catch (\Exception $e) {
9180            /** @disregard P1014 */
9181            $e->exceptionCode = 'SEND_EMAIL_TEMPLATE_EXCEPTION';
9182            report($e);
9183
9184            return response(['message' => 'KO', 'error' => $e->getMessage()]);
9185        }
9186
9187    }
9188
9189    public function list_quotation_analytics_by_types_of_budgets_company_per_week(Request $request)
9190    {
9191
9192        try {
9193
9194            $data = $request->all();
9195            $companyId = addslashes($data['company_id']);
9196            $field = $data['field'];
9197
9198            $where = '';
9199            $whereYear = '';
9200            $dateLflArray = [];
9201            $companyIds = $this->companyIds;
9202
9203            $acc = '';
9204            if ($field == 'acceptance_date') {
9205                $acc = ' AND q.acceptance_date IS NOT NULL ';
9206                // $field = 'created_at';
9207
9208                if (@$data['data_to_display'] == 4) {
9209                    $field = 'created_at';
9210                    $where .= ' AND YEAR(q.created_at) = YEAR(q.issue_date)';
9211                }
9212            } else {
9213                $field = 'created_at';
9214                $where .= ' AND YEAR(q.created_at) = YEAR(q.issue_date)';
9215            }
9216
9217            if ($companyId != 0) {
9218                $companyIds = [$companyId];
9219            }
9220
9221            if (isset($data['years']) && $data['years'] != null) {
9222
9223                if (count($data['years']) > 0) {
9224                    foreach ($data['years'] as $year) {
9225                        if (isset($data['week']) && $data['week'] != null) {
9226                            $w = sprintf('%02d', $data['week']);
9227                            $whereYear .= " AND YEARWEEK(q.{$field}, 1) = '{$year}{$w}'";
9228                        } else {
9229                            $whereYear .= " AND YEAR(q.{$field}) = {$year}";
9230                        }
9231                    }
9232                }
9233            }
9234
9235            foreach ($companyIds as $v) {
9236
9237                $lflWhere = " AND q.company_id = {$v} ";
9238
9239                $query = "SELECT
9240                            CONCAT(
9241                                DATE_FORMAT((SELECT MIN(q.{$field}) FROM tbl_quotations q WHERE q.{$field} IS NOT NULL {$lflWhere}), '%c/%e/'), YEAR({$field}),
9242                                ' - ',
9243                                DATE_FORMAT((SELECT MAX(q.{$field}) FROM tbl_quotations q WHERE q.{$field} IS NOT NULL {$lflWhere}), '%c/%e/'), YEAR({$field})
9244                            ) AS date_like,
9245                            YEAR(q.{$field}) 'year',
9246                            DATE_FORMAT((SELECT MIN(q.{$field}) FROM tbl_quotations q WHERE q.{$field} IS NOT NULL {$lflWhere}), '%m-%d') AS min_date_like,
9247                            DATE_FORMAT((SELECT MAX(q.{$field}) FROM tbl_quotations q WHERE q.{$field} IS NOT NULL {$lflWhere}), '%m-%d') AS max_date_like,
9248                            {$v} 'company_id'
9249                        FROM
9250                            tbl_quotations q
9251                        WHERE
9252                            q.{$field} IS NOT NULL
9253                            AND q.for_add = 0
9254                            {$lflWhere}
9255                            {$whereYear}
9256                        GROUP BY YEAR(q.{$field})
9257                        ORDER BY YEAR(q.{$field}) DESC";
9258
9259                $dateLike = DB::select($query);
9260
9261                $dateLflArray[$v] = $dateLike;
9262            }
9263
9264            $isFy = true;
9265
9266            if (isset($data['ytd']) && $data['ytd'] != null && $data['ytd'] == true) {
9267                $isFy = false;
9268                $ytdArray = [];
9269                $ytdAcceptanceArray = [];
9270                $lflCompanyIds = [];
9271                foreach ($dateLflArray as $k => $v) {
9272                    foreach ($dateLflArray[$k] as $item) {
9273                        $year = $item->year;
9274                        $now = date('m-d');
9275                        array_push($ytdArray, "DATE_FORMAT(q.{$field}, '%Y-%m-%d') BETWEEN '{$year}-01-01' AND '{$year}-{$now}'");
9276                    }
9277
9278                    $ytdArray = implode(' OR ', $ytdArray);
9279                    array_push($lflCompanyIds, "q.company_id = {$k} AND ({$ytdArray})");
9280                    $ytdArray = [];
9281                }
9282
9283                $lflCompanyIds = implode(' OR ', $lflCompanyIds);
9284                $where .= " AND ({$lflCompanyIds}";
9285            }
9286
9287            if (isset($data['lfl']) && $data['lfl'] != null && $data['lfl'] == true) {
9288                $isFy = false;
9289                $lflArray = [];
9290                $ytdAcceptanceArray = [];
9291                $lflCompanyIds = [];
9292                foreach ($dateLflArray as $k => $v) {
9293                    foreach ($dateLflArray[$k] as $item) {
9294                        $year = $item->year;
9295                        $min_date_like = $item->min_date_like;
9296                        $max_date_like = $item->max_date_like;
9297                        array_push($lflArray, "DATE_FORMAT(q.{$field}, '%Y-%m-%d') BETWEEN LEAST('{$year}-{$min_date_like}', '{$year}-{$max_date_like}') AND GREATEST('{$year}-{$min_date_like}', '{$year}-{$max_date_like}')");
9298                    }
9299
9300                    $lflArray = implode(' OR ', $lflArray);
9301                    array_push($lflCompanyIds, "q.company_id = {$k} AND ({$lflArray})");
9302                    $lflArray = [];
9303                }
9304
9305                $lflCompanyIds = implode(' OR ', $lflCompanyIds);
9306                $where .= " AND ({$lflCompanyIds}";
9307            }
9308
9309            if ($isFy) {
9310                if ($companyId != 0) {
9311                    $where .= " AND q.company_id = {$companyId} ";
9312                } else {
9313                    $where .= " AND q.company_id IN ({$this->companyId})";
9314                }
9315            }
9316
9317            if (isset($data['source']) && $data['source'] != null) {
9318                $where .= " AND s.name = '{$data['source']}'";
9319            }
9320
9321            if (isset($data['month']) && $data['month'] != null) {
9322                $where .= " AND MONTH(q.{$field}) = '{$data['month']}'";
9323            }
9324
9325            if (isset($data['commercial']) && $data['commercial'] != null) {
9326                $where .= " AND q.commercial = '{$data['commercial']}'";
9327            }
9328
9329            if (isset($data['created_by']) && $data['created_by'] != null) {
9330                $where .= " AND q.created_by = '{$data['created_by']}'";
9331            }
9332
9333            if (isset($data['budget_type']) && $data['budget_type'] != null) {
9334                $where .= " AND bt.budget_type_id = {$data['budget_type']}";
9335            }
9336
9337            if (isset($data['budget_type_group']) && $data['budget_type_group'] != null) {
9338                $where .= " AND bt.budget_type_group_id = {$data['budget_type_group']}";
9339            }
9340
9341            if (isset($data['budget_status']) && $data['budget_status'] != null) {
9342                $where .= " AND bs.budget_status_id = {$data['budget_status']}";
9343            }
9344
9345            if (isset($data['client_type']) && $data['client_type'] != null) {
9346                $where .= " AND ct.customer_type_id = {$data['client_type']}";
9347            }
9348
9349            if (isset($data['segment_id']) && $data['segment_id'] != null) {
9350                $where .= " AND q.segment_id = {$data['segment_id']}";
9351            }
9352
9353            $col = '1';
9354
9355            if (isset($data['data_to_display']) && $data['data_to_display'] != null) {
9356                if ($data['data_to_display'] == 1) {
9357                    $col = '1';
9358                }
9359
9360                if ($data['data_to_display'] == 2) {
9361                    $col = 'q.amount';
9362                }
9363            }
9364
9365            $budgetTypes = TblBudgetTypes::orderByRaw('ISNULL(priority), priority ASC')->get();
9366            $cols = '';
9367            foreach ($budgetTypes as $item) {
9368                if ($item->name == '' || $item->name == null) {
9369                    $cols .= ",COALESCE(SUM(CASE WHEN bt.name IS NULL {$acc} THEN {$col} ELSE 0 END), 0) AS 'Otros'";
9370                } else {
9371                    $cols .= ",COALESCE(SUM(CASE WHEN bt.name = '{$item->name}{$acc} THEN {$col} ELSE 0 END), 0) AS '{$item->name}'";
9372                }
9373            }
9374
9375            $budgetTypeGroups = TblBudgetTypeGroups::orderByRaw('ISNULL(priority), priority ASC')->get();
9376
9377            $colsGroups = ",COALESCE(SUM(CASE WHEN bt.name IS NULL {$acc} THEN {$col} END), 0) AS Otros";
9378
9379            foreach ($budgetTypeGroups as $item) {
9380                $budgetTypeGroupName = str_replace(' ', '', $item->name).$item->budget_type_group_id;
9381                $colsGroups .= ",GROUP_CONCAT(CASE WHEN (bt.budget_type_group_id = {$item->budget_type_group_id} OR bt.name IS NULL) {$acc} THEN q.id END) AS 'groupConcatIds{$budgetTypeGroupName}'";
9382                $colsGroups .= ",COALESCE(SUM(CASE WHEN (bt.budget_type_group_id = {$item->budget_type_group_id} OR bt.name IS NULL) {$acc} THEN {$col} END), 0) AS '{$budgetTypeGroupName}'";
9383            }
9384
9385            $colsGroups .= ",COALESCE(SUM(CASE WHEN (bt.budget_type_group_id IS NOT NULL OR bt.name IS NULL) {$acc} THEN {$col} END), 0) AS total";
9386
9387            $col = $colsGroups.$cols;
9388
9389            if (@$data['data_to_display'] == 3) {
9390
9391                $cols = '';
9392                foreach ($budgetTypes as $item) {
9393                    if ($item->name == '' || $item->name == null) {
9394                        $cols .= ",COALESCE(
9395                                        SUM(CASE WHEN bt.name IS NULL {$acc} THEN q.amount ELSE 0 END) /
9396                                        SUM(CASE WHEN bt.name IS NULL {$acc} THEN 1 ELSE 0 END) * 100
9397                                    , 0) AS 'Otros'";
9398                    } else {
9399                        $cols .= ", COALESCE(
9400                                        SUM(CASE WHEN bt.name = '{$item->name}{$acc} THEN q.amount ELSE 0 END) /
9401                                        SUM(CASE WHEN bt.name = '{$item->name}{$acc} THEN 1 ELSE 0 END)
9402                                    , 0) AS '{$item->name}'";
9403                    }
9404                }
9405
9406                $colsGroups = ",COALESCE(
9407                                (SUM(CASE WHEN bt.name IS NULL {$acc} THEN q.amount END)) /
9408                                (SUM(CASE WHEN bt.name IS NULL {$acc} THEN 1 END))
9409                            , 0) Otros";
9410
9411                foreach ($budgetTypeGroups as $item) {
9412                    $budgetTypeGroupName = str_replace(' ', '', $item->name).$item->budget_type_group_id;
9413                    $colsGroups .= ",GROUP_CONCAT(CASE WHEN (bt.budget_type_group_id = {$item->budget_type_group_id} OR bt.name IS NULL) {$acc} THEN q.id END) AS 'groupConcatIds{$budgetTypeGroupName}'";
9414                    $colsGroups .= ",COALESCE(
9415                                        (SUM(CASE WHEN (bt.budget_type_group_id = {$item->budget_type_group_id} OR bt.name IS NULL) {$acc} THEN q.amount END)) /
9416                                        (SUM(CASE WHEN (bt.budget_type_group_id = {$item->budget_type_group_id} OR bt.name IS NULL) {$acc} THEN 1 END))
9417                                    , 0) '{$budgetTypeGroupName}'";
9418                }
9419
9420                $colsGroups .= ",COALESCE(
9421                                    (SUM(CASE WHEN (bt.budget_type_group_id IS NOT NULL OR bt.name IS NULL) {$acc} THEN q.amount END)) /
9422                                    (SUM(CASE WHEN (bt.budget_type_group_id IS NOT NULL OR bt.name IS NULL) {$acc} THEN 1 END))
9423                                , 0) total";
9424
9425                $col = $colsGroups.$cols;
9426            }
9427
9428            if (@$data['data_to_display'] == 4) {
9429
9430                $cols = '';
9431
9432                foreach ($budgetTypes as $item) {
9433
9434                    if ($item->name == '' || $item->name == null) {
9435                        $cols .= ",COALESCE(
9436                                        SUM(CASE WHEN bt.name IS NULL AND q.acceptance_date IS NOT NULL THEN 1 ELSE 0 END) /
9437                                        SUM(CASE WHEN bt.name IS NULL AND q.created_at IS NOT NULL THEN 1 ELSE 0 END) * 100
9438                                    , 0) AS 'Otros'";
9439                    } else {
9440                        $cols .= ", COALESCE(
9441                                        SUM(CASE WHEN bt.name = '{$item->name}' AND q.acceptance_date IS NOT NULL THEN 1 END) /
9442                                        SUM(CASE WHEN bt.name = '{$item->name}' AND q.created_at IS NOT NULL THEN 1 END) * 100
9443                                    , 0) AS '{$item->name}'";
9444                    }
9445                }
9446
9447                $colsGroups = ',COALESCE(
9448                                    (SUM(CASE WHEN bt.name IS NULL AND q.acceptance_date IS NOT NULL THEN 1 END)) /
9449                                    (SUM(CASE WHEN bt.name IS NULL AND q.created_at IS NOT NULL THEN 1 END)) * 100
9450                                , 0) Otros';
9451
9452                foreach ($budgetTypeGroups as $item) {
9453                    $budgetTypeGroupName = str_replace(' ', '', $item->name).$item->budget_type_group_id;
9454                    $colsGroups .= ",GROUP_CONCAT(CASE WHEN (bt.budget_type_group_id = {$item->budget_type_group_id} OR bt.name IS NULL) {$acc} THEN q.id END) AS 'groupConcatIds{$budgetTypeGroupName}'";
9455                    $colsGroups .= ",COALESCE(
9456                                        (SUM(CASE WHEN (bt.budget_type_group_id = {$item->budget_type_group_id} OR bt.name IS NULL) AND q.acceptance_date IS NOT NULL THEN 1 END)) /
9457                                        (SUM(CASE WHEN (bt.budget_type_group_id = {$item->budget_type_group_id} OR bt.name IS NULL) AND q.created_at IS NOT NULL THEN 1 END)) * 100
9458                                    , 0) '{$budgetTypeGroupName}'";
9459                }
9460
9461                $colsGroups .= ',COALESCE(
9462                                    (SUM(CASE WHEN (bt.budget_type_group_id IS NOT NULL OR bt.name IS NULL) AND q.acceptance_date IS NOT NULL THEN 1 END)) /
9463                                    (SUM(CASE WHEN (bt.budget_type_group_id IS NOT NULL OR bt.name IS NULL) AND q.created_at IS NOT NULL THEN 1 END)) * 100
9464                                    , 0) total';
9465
9466                $col = $colsGroups.$cols;
9467            }
9468
9469            $query = "SELECT
9470                            YEAR(DATE_ADD(q.{$field}, INTERVAL - WEEKDAY(q.{$field}) DAY)) AS 'year',
9471                            LPAD(MONTH(DATE_ADD(q.{$field}, INTERVAL - WEEKDAY(q.{$field}) DAY)), 2, 0) AS 'month',
9472                            q.company_id,
9473                            c.name 'companyName',
9474                            GROUP_CONCAT(CASE WHEN (bt.budget_type_group_id IS NOT NULL OR bt.name IS NULL) {$acc} THEN q.id END) groupConcatIds
9475                            {$col}
9476                        FROM
9477                            tbl_quotations q
9478                            LEFT JOIN tbl_sources s ON s.source_id = q.source_id
9479                            LEFT JOIN tbl_budget_status bs ON bs.budget_status_id = q.budget_status_id
9480                            LEFT JOIN tbl_budget_types bt ON q.budget_type_id = bt.budget_type_id
9481                            LEFT JOIN tbl_budget_type_groups btg ON bt.budget_type_group_id = btg.budget_type_group_id
9482                            LEFT JOIN tbl_customer_types ct ON q.customer_type_id = ct.customer_type_id
9483                            LEFT JOIN tbl_companies c ON q.company_id = c.company_id
9484                        WHERE
9485                            q.{$field} IS NOT NULL
9486                            AND q.for_add = 0
9487                            AND q.budget_type_id != 7
9488                            AND q.budget_type_id IS NOT NULL
9489                            AND q.amount REGEXP '^[0-9]+\\.?[0-9]*$' = 1                            
9490                            {$where}
9491                            {$whereYear}
9492                        GROUP BY
9493                            YEAR(DATE_ADD(q.{$field}, INTERVAL - WEEKDAY(q.{$field}) DAY)),
9494                            MONTH(DATE_ADD(q.{$field}, INTERVAL - WEEKDAY(q.{$field}) DAY)),
9495                            q.company_id WITH ROLLUP
9496                        ORDER BY
9497                            YEAR DESC,
9498                            MONTH ASC,
9499                            q.company_id ASC,
9500                            DATE_FORMAT(q.{$field}, '%e') ASC";
9501
9502            $result = DB::select($query);
9503
9504            $query = "SELECT
9505                        btg.budget_type_group_id,
9506                        btg.name,
9507                        (
9508                            SELECT
9509                                GROUP_CONCAT(COALESCE(bt.name, '') ORDER BY ISNULL(bt.priority), bt.priority ASC SEPARATOR '|')
9510                            FROM
9511                                tbl_budget_types bt
9512                            WHERE
9513                                bt.budget_type_group_id = btg.budget_type_group_id
9514                        ) budget_types
9515                        FROM
9516                            tbl_budget_type_groups btg
9517                        ORDER BY
9518                            ISNULL(btg.priority),
9519                            btg.priority ASC";
9520
9521            $budgetTypeGroups = DB::select($query);
9522
9523            foreach ($budgetTypeGroups as $item) {
9524                $item->group_key_name = str_replace(' ', '', $item->name).$item->budget_type_group_id;
9525                $item->budget_types = explode('|', $item->budget_types);
9526            }
9527
9528            return response([
9529                'message' => 'OK',
9530                'data' => $result,
9531                'budgetTypeGroups' => $budgetTypeGroups,
9532            ]);
9533
9534        } catch (\Exception $e) {
9535            /** @disregard P1014 */
9536            $e->exceptionCode = 'LIST_QUOTATION_ANALYTICS_BY_TYPES_OF_BUDGETS_COMPANT_PER_WEEK_EXCEPTION';
9537            report($e);
9538
9539            return response(['message' => 'KO', 'error' => $e->getMessage()]);
9540        }
9541    }
9542
9543    public function request_permission_commercial(Request $request)
9544    {
9545
9546        try {
9547
9548            $data = $request->all();
9549
9550            $id = addslashes($data['id']);
9551            $requestedBy = $data['requested_by'];
9552            $body = '';
9553
9554            $result = TblQuotations::where('id', $id)->first();
9555
9556            $subject = __('language.request_permission_commercial.subject');
9557            $subject = str_replace('{{quote_id}}', $result->quote_id, $subject);
9558            $subject = str_replace('{{username}}', $requestedBy, $subject);
9559
9560            $email = new \SendGrid\Mail\Mail;
9561
9562            $imgpath = File::get('fireservicetitan.png');
9563
9564            $email->addAttachment(
9565                $imgpath,
9566                'image/png',
9567                'fireservicetitan.png',
9568                'inline',
9569                'fireservicetitan'
9570            );
9571
9572            $url = env('URL')."orders/{$id}?company_id={$result->company_id}";
9573            $href = "<a href='{$url}'>{$result->quote_id}</a>";
9574
9575            $user = TblUsers::where('name', $requestedBy)->first();
9576
9577            $urlClick = env('URL')."update?confirm_request={$id}&requested_by={$user->id}&quote_id={$result->quote_id}";
9578            $company = TblCompanies::where('company_id', $result->company_id)->first();
9579
9580            $body .= __('language.request_permission_commercial.body_hello');
9581            $body .= __('language.request_permission_commercial.body_message');
9582
9583            $amount = $this->currency($result->amount, 1);
9584
9585            $body = str_replace('{{commercial}}', $result->commercial, $body);
9586            $body = str_replace('{{company}}', $company->name, $body);
9587            $body = str_replace('{{client}}', $result->client, $body);
9588            $body = str_replace('{{amount}}', $amount, $body);
9589            $body = str_replace('{{quote_id}}', $href, $body);
9590            $body = str_replace('{{click}}', $urlClick, $body);
9591            $body = str_replace('{{username}}', $requestedBy, $body);
9592
9593            $body .= '<p>Fire Service Titan</p>';
9594            $body .= "<img src='cid:fireservicetitan' style='height: 45px;' />";
9595
9596            $html = '<!DOCTYPE html>';
9597            $html .= '<html>';
9598            $html .= '<head>';
9599            $html .= '<meta charset="UTF-8">';
9600            $html .= '<meta name="viewport" content="width=device-width, initial-scale=1.0">';
9601            $html .= '</head>';
9602            $html .= '<body>';
9603            $html .= $body;
9604            $html .= '</body>';
9605            $html .= '</html>';
9606
9607            $user = TblUsers::where('id', $this->userId)->first();
9608
9609            if (env('SENDGRID_STAGING')) {
9610                $email->addTo($user->email);
9611            } else {
9612                $email->addTo('luis.collar@fire.es');
9613
9614                $user = TblUsers::where('name', $result->created_by)->first();
9615                if ($user && $user->email != 'luis.collar@fire.es') {
9616                    $email->addTo($user->email);
9617                }
9618
9619                if ($result->created_by != $result->commercial) {
9620                    $user = TblUsers::where('name', $result->commercial)->first();
9621                    if ($user->email != 'luis.collar@fire.es') {
9622                        $email->addTo($user->email);
9623                    }
9624                }
9625            }
9626
9627            $email->setFrom('titan@fire.es');
9628            $email->setSubject($subject);
9629
9630            $email->addContent('text/html', $html);
9631
9632            $sendgrid = new \SendGrid(env('SENDGRID_API_KEY'));
9633
9634            $response = $sendgrid->send($email);
9635            if ($response->statusCode() == 202) {
9636                return response(['message' => 'OK']);
9637            }
9638
9639            $this->addUpdateLog($id, $requestedBy, 'request_permission_commercial', null, null, 4);
9640
9641            return response(['message' => 'KO']);
9642
9643        } catch (\Exception $e) {
9644            /** @disregard P1014 */
9645            $e->exceptionCode = 'REQUEST_PERMISSION_EXCEPTION';
9646            report($e);
9647
9648            return response(['message' => 'KO', 'error' => $e->getMessage()]);
9649        }
9650
9651    }
9652
9653    public function confirm_update_commercial(Request $request)
9654    {
9655
9656        try {
9657            sleep(3);
9658            $data = $request->all();
9659            $id = addslashes($data['id']);
9660            $userId = addslashes($data['requested_by']);
9661
9662            $user = TblUsers::where('id', $userId)->first();
9663
9664            if ($user) {
9665
9666                TblQuotations::where('id', $data['id'])->update(
9667                    [
9668                        'commercial' => $user->name,
9669                        'updated_at' => date('Y-m-d H:i:s'),
9670                    ]
9671                );
9672
9673            } else {
9674                return response(['message' => 'KO', 'error' => 'invalid_user']);
9675            }
9676
9677            return response(['message' => 'OK']);
9678
9679        } catch (\Exception $e) {
9680            /** @disregard P1014 */
9681            $e->exceptionCode = 'CONFIRM_UPDATE_COMMERCIAL_EXCEPTION';
9682            report($e);
9683
9684            return response(['message' => 'KO', 'error' => $e->getMessage()]);
9685        }
9686    }
9687
9688    public function calculateEmailRequestSize(Mail $email)
9689    {
9690
9691        $size = 0;
9692
9693        // Add size of 'from', 'to', 'subject', 'content'
9694        $from = $email->getFrom();
9695        $size += strlen(json_encode([
9696            'from' => $from->getEmail().' '.$from->getName(),
9697            'subject' => $email->getSubject(),
9698        ]));
9699
9700        // Add size of 'to' (recipients)
9701        $personalizations = $email->getPersonalizations() ?? [];
9702        foreach ($personalizations as $personalization) {
9703            foreach ($personalization->getTos() as $to) {
9704                $size += strlen($to->getEmail().' '.$to->getName());
9705            }
9706        }
9707
9708        // Add size of content
9709        foreach ($email->getContents() as $content) {
9710            $size += strlen($content->getValue());
9711        }
9712
9713        // Add size of attachments (if any)
9714
9715        if ($email->getAttachments() != null && $email->getAttachments() != '') {
9716            foreach ($email->getAttachments() as $attachment) {
9717                $size += strlen($attachment->getContent()); // Base64 encoded size
9718                $size += strlen($attachment->getFilename());
9719                $size += strlen($attachment->getType());
9720            }
9721        }
9722
9723        $sizeInMegabytes = $size / 1048576; // 1 MB = 1,048,576 bytes
9724
9725        return (int) ceil($sizeInMegabytes);
9726    }
9727
9728    public function list_quotation_analytics_commercial_productivity(Request $request)
9729    {
9730
9731        // try {
9732
9733        $data = $request->all();
9734        $companyId = addslashes($data['company_id']);
9735
9736        $where = '';
9737        $whereYear = '';
9738        $whereVisit = '';
9739
9740        $dateLflArray = [];
9741        $companyIds = $this->companyIds;
9742
9743        if ($companyId != 0) {
9744            $companyIds = [$companyId];
9745        }
9746
9747        $field = 'issue_date';
9748
9749        if (isset($data['years']) && $data['years'] != null) {
9750            $years = implode(',', $data['years']);
9751            if (count($data['years']) > 0) {
9752                $whereYear = " AND YEAR(q.{$field}) IN ({$years})";
9753            }
9754        }
9755
9756        foreach ($companyIds as $v) {
9757
9758            $lflWhere = " AND q.company_id = {$v} ";
9759
9760            $query = "SELECT
9761                            CONCAT(
9762                                DATE_FORMAT((SELECT MIN(q.{$field}) FROM tbl_quotations q WHERE q.{$field} IS NOT NULL {$lflWhere}), '%c/%e/'), YEAR({$field}),
9763                                ' - ',
9764                                DATE_FORMAT((SELECT MAX(q.{$field}) FROM tbl_quotations q WHERE q.{$field} IS NOT NULL {$lflWhere}), '%c/%e/'), YEAR({$field})
9765                            ) AS date_like,
9766                            YEAR(q.{$field}) 'year',
9767                            DATE_FORMAT((SELECT MIN(q.{$field}) FROM tbl_quotations q WHERE q.{$field} IS NOT NULL {$lflWhere}), '%m-%d') AS min_date_like,
9768                            DATE_FORMAT((SELECT MAX(q.{$field}) FROM tbl_quotations q WHERE q.{$field} IS NOT NULL {$lflWhere}), '%m-%d') AS max_date_like,
9769                            {$v} 'company_id'
9770                        FROM
9771                            tbl_quotations q
9772                        WHERE
9773                            q.{$field} IS NOT NULL
9774                            AND q.for_add = 0
9775                            {$lflWhere}
9776                            {$whereYear}
9777                        GROUP BY YEAR(q.{$field})
9778                        ORDER BY YEAR(q.{$field}) DESC";
9779
9780            $dateLike = DB::select($query);
9781
9782            if (count($dateLike) > 0) {
9783                $dateLflArray[$v] = $dateLike;
9784            }
9785        }
9786
9787        $whereAcceptanceDate = '';
9788
9789        if (isset($data['source']) && $data['source'] != null) {
9790            $where .= " AND s.name = '{$data['source']}'";
9791        }
9792
9793        if (isset($data['month']) && $data['month'] != null) {
9794            $where .= " AND MONTH(q.created_at) = '{$data['month']}'";
9795        }
9796
9797        if (isset($data['week']) && $data['week'] != null) {
9798            $where .= " AND WEEK(q.created_at) = '{$data['week']}'";
9799        }
9800
9801        if (isset($data['commercial']) && $data['commercial'] != null) {
9802            $commercial = implode("','", $data['commercial']);
9803            if (count($data['commercial']) > 0) {
9804                $where .= " AND q.commercial IN ('{$commercial}') ";
9805                $whereVisit .= " AND q.commercial IN ('{$commercial}') ";
9806            }
9807        }
9808
9809        if (isset($data['created_by']) && $data['created_by'] != null) {
9810            $created_by = implode("','", $data['created_by']);
9811            if (count($data['created_by']) > 0) {
9812                $where .= " AND q.created_by IN ('{$created_by}')";
9813            }
9814        }
9815
9816        if (isset($data['budget_type']) && $data['budget_type'] != null) {
9817            $where .= " AND bt.budget_type_id = {$data['budget_type']}";
9818        }
9819
9820        if (isset($data['budget_type_group']) && $data['budget_type_group'] != null) {
9821            $budgetTypeGroupIds = implode(',', $data['budget_type_group']);
9822            if (count($data['budget_type_group']) > 0) {
9823                $where .= " AND bt.budget_type_group_id IN ({$budgetTypeGroupIds})";
9824            }
9825        }
9826
9827        if (isset($data['budget_status']) && $data['budget_status'] != null) {
9828            $where .= " AND bs.budget_status_id = {$data['budget_status']}";
9829        }
9830
9831        if (isset($data['client_type']) && $data['client_type'] != null) {
9832            $where .= " AND ct.customer_type_id = {$data['client_type']}";
9833        }
9834
9835        if (isset($data['segment_id']) && $data['segment_id'] != null) {
9836            $where .= " AND q.segment_id = {$data['segment_id']}";
9837        }
9838
9839        if (isset($data['role_id']) && $data['role_id'] != null) {
9840            $roleId = implode(',', $data['role_id']);
9841            if (count($data['role_id']) > 0) {
9842                $where .= " AND r.role_id IN ({$roleId})";
9843                $whereVisit .= " AND r.role_id IN ({$roleId}";
9844            }
9845        }
9846
9847        $groupByFilter = 2;
9848        if (isset($data['group_by']) && $data['group_by'] != null) {
9849            $groupByFilter = $data['group_by'];
9850        }
9851
9852        $groupBy = '1, 2, 3, q.commercial, budget_type';
9853
9854        if ($groupByFilter == 1) {
9855            $groupBy = '1, q.commercial, 2, 3, budget_type';
9856        }
9857
9858        if ($groupByFilter == 3) {
9859            $groupBy = '1, budget_type, q.commercial, 2, 3';
9860        }
9861
9862        $aggregatedBy = 1;
9863        $aggregatedCol = "LPAD(q.month, 2, 0) AS 'month', LPAD(q.week, 2, 0) AS 'week', ";
9864        $aggregatedByCalc = ' / 4';
9865        if (isset($data['aggregated_by']) && $data['aggregated_by'] != null) {
9866            $aggregatedBy = $data['aggregated_by'];
9867            if ($data['aggregated_by'] == 1) {
9868
9869                $groupBy = '1, 2, 3, q.commercial, budget_type';
9870
9871                if ($groupByFilter == 1) {
9872                    $groupBy = '1, q.commercial, 2, 3, budget_type';
9873                }
9874
9875                if ($groupByFilter == 3) {
9876                    $groupBy = '1, budget_type, q.commercial, 2, 3';
9877                }
9878
9879                $aggregatedCol = "LPAD(q.month, 2, 0) AS 'month', LPAD(q.week, 2, 0) AS 'week', ";
9880            } elseif ($data['aggregated_by'] == 2) {
9881                $groupBy = '1, 2, q.commercial, budget_type';
9882
9883                if ($groupByFilter == 1) {
9884                    $groupBy = '1, q.commercial, 2, budget_type';
9885                }
9886
9887                if ($groupByFilter == 3) {
9888                    $groupBy = '1, budget_type, q.commercial, 2';
9889                }
9890
9891                $aggregatedCol = "LPAD(q.month, 2, 0) AS 'month', NULL AS 'week',";
9892                $aggregatedByCalc = '';
9893            } elseif ($data['aggregated_by'] == 3) {
9894                $groupBy = '1, q.commercial, budget_type';
9895
9896                if ($groupByFilter == 3) {
9897                    $groupBy = '1, budget_type, q.commercial';
9898                }
9899
9900                $aggregatedCol = "NULL AS 'month', NULL AS 'week',";
9901                $aggregatedByCalc = ' * 12';
9902            }
9903        }
9904
9905        $whereAcceptanceDate = $where;
9906        $whereCreatedAt = $where;
9907
9908        $isFy = true;
9909
9910        if ($companyId != 0) {
9911            $where .= " AND q.company_id = {$companyId} ";
9912            $whereCreatedAt .= " AND q.company_id = {$companyId} ";
9913            $whereAcceptanceDate .= " AND q.company_id = {$companyId} ";
9914            $whereVisit .= " AND q.company_id = {$companyId} ";
9915        } else {
9916            $where .= " AND q.company_id IN ({$this->companyId}";
9917            $whereCreatedAt .= " AND q.company_id IN ({$this->companyId}";
9918            $whereAcceptanceDate .= " AND q.company_id IN ({$this->companyId}";
9919            $whereVisit .= " AND q.company_id IN ({$this->companyId}";
9920        }
9921
9922        if (isset($data['campaign']) && $data['campaign'] != null) {
9923            $campaign = implode("','", $data['campaign']);
9924            if (count($data['campaign']) > 0) {
9925                $whereVisit .= " AND q.campaign IN ('{$campaign}')";
9926            }
9927        }
9928
9929        if (isset($data['ytd']) && $data['ytd'] != null && $data['ytd'] == true) {
9930            $isFy = false;
9931            $now = date('m-d');
9932
9933            $where .= " AND q.{$field} BETWEEN DATE_FORMAT(q.{$field}, '%Y-01-01') AND DATE_FORMAT(q.{$field}, '%Y-{$now}') ";
9934            $whereCreatedAt .= " AND q.created_at BETWEEN DATE_FORMAT(q.created_at, '%Y-01-01') AND DATE_FORMAT(q.created_at, '%Y-{$now}') ";
9935            $whereAcceptanceDate .= " AND q.acceptance_date BETWEEN DATE_FORMAT(q.acceptance_date, '%Y-01-01') AND DATE_FORMAT(q.acceptance_date, '%Y-{$now}') ";
9936            $whereVisit .= " AND q.visit_date BETWEEN DATE_FORMAT(q.visit_date, '%Y-01-01') AND DATE_FORMAT(q.visit_date, '%Y-{$now}') ";
9937        }
9938
9939        if (isset($data['lfl']) && $data['lfl'] != null && $data['lfl'] == true) {
9940            $isFy = false;
9941            $lflArray = [];
9942            $ytdAcceptanceArray = [];
9943            $lflCompanyIds = [];
9944            $lflCompanyIdsAcc = [];
9945            foreach ($dateLflArray as $k => $v) {
9946                foreach ($dateLflArray[$k] as $item) {
9947                    $year = $item->year;
9948                    $min_date_like = $item->min_date_like;
9949                    $max_date_like = $item->max_date_like;
9950                    array_push($lflArray, "DATE_FORMAT(q.{$field}, '%Y-%m-%d') BETWEEN LEAST('{$year}-{$min_date_like}', '{$year}-{$max_date_like}') AND GREATEST('{$year}-{$min_date_like}', '{$year}-{$max_date_like}')");
9951                    array_push($ytdAcceptanceArray, "DATE_FORMAT(q.acceptance_date, '%Y-%m-%d') BETWEEN LEAST('{$year}-{$min_date_like}', '{$year}-{$max_date_like}') AND GREATEST('{$year}-{$min_date_like}', '{$year}-{$max_date_like}')");
9952                }
9953
9954                $lflArray = implode(' OR ', $lflArray);
9955                array_push($lflCompanyIds, "q.company_id = {$k} AND ({$lflArray})");
9956                $lflArray = [];
9957
9958                $ytdAcceptanceArray = implode(' OR ', $ytdAcceptanceArray);
9959                array_push($lflCompanyIdsAcc, "q.company_id = {$k} AND ({$ytdAcceptanceArray})");
9960                $ytdAcceptanceArray = [];
9961            }
9962
9963            $lflCompanyIds = implode(' OR ', $lflCompanyIds);
9964            $where .= " AND ({$lflCompanyIds}";
9965
9966            $lflCompanyIdsAcc = implode(' OR ', $lflCompanyIdsAcc);
9967            $whereAcceptanceDate .= " AND ({$lflCompanyIdsAcc}";
9968        }
9969
9970        $orderBy = 'CASE WHEN q.commercial IS NULL OR q.budget_type IS NULL THEN q.priority END DESC, q.priority ASC,';
9971
9972        if (isset($data['order_by'])) {
9973            $col = $data['order_by']['column'];
9974            $sort = $data['order_by']['sort'];
9975
9976            if (! empty($sort) || $sort != null) {
9977                $orderBy = "CASE WHEN q.commercial IS NULL OR q.budget_type IS NULL THEN {$col} END DESC, {$col} {$sort},";
9978            }
9979        }
9980
9981        $visitTypes = TblVisitTypeGroups::orderByRaw('ISNULL(priority), priority ASC')->get();
9982
9983        $visitCols = '';
9984        $visitMainTableCols = '';
9985        $visitSubMainTableCols = '';
9986        $visitSubTableCols = '';
9987        $visitMainCols = '';
9988
9989        $visitCall = ['Visita', 'Llamada'];
9990
9991        foreach ($visitCall as $value) {
9992            foreach ($visitTypes as $item) {
9993                $visitTypeNames = $value.$item->visit_type_group_id;
9994                $visitCols .= ",COUNT(CASE WHEN q.visit_date IS NOT NULL AND v.visit_type_group_id = {$item->visit_type_group_id} AND q.visit_call = '{$value}' THEN 1 END) AS 'total{$visitTypeNames}'";
9995                $visitCols .= ",GROUP_CONCAT(CASE WHEN q.visit_date IS NOT NULL AND v.visit_type_group_id = {$item->visit_type_group_id} AND q.visit_call = '{$value}' THEN q.id END) AS 'groupConcatIds{$visitTypeNames}'";
9996                $visitMainTableCols .= ",COALESCE(SUM(q.total{$visitTypeNames}), 0) AS 'total{$visitTypeNames}'";
9997                $visitMainTableCols .= ",GROUP_CONCAT(q.groupConcatIds{$visitTypeNames})  AS 'groupConcatIds{$visitTypeNames}'";
9998                $visitSubMainTableCols .= ",q.total{$visitTypeNames}";
9999                $visitSubMainTableCols .= ",q.groupConcatIds{$visitTypeNames}";
10000                $visitSubTableCols .= ",0 AS total{$visitTypeNames}";
10001                $visitSubTableCols .= ",NULL AS groupConcatIds{$visitTypeNames}";
10002                $visitMainCols .= ",COALESCE(SUM(q.total{$visitTypeNames}), 0) total{$visitTypeNames}";
10003                $visitMainCols .= ",GROUP_CONCAT(q.groupConcatIds{$visitTypeNames}) groupConcatIds{$visitTypeNames}";
10004            }
10005        }
10006
10007        $businessGoalsDefault = TblBusinessGoals::where('is_default', 1)->where('budget_type_group_id', 999999999)->first();
10008
10009        $businessGoalsDefault->issue_objective = $businessGoalsDefault->issue_objective ?? 1;
10010        $businessGoalsDefault->acceptance_objective = $businessGoalsDefault->acceptance_objective ?? 1;
10011        $businessGoalsDefault->new_objective = $businessGoalsDefault->new_objective ?? 1;
10012        $businessGoalsDefault->is_amount = $businessGoalsDefault->is_amount ?? 1;
10013
10014        $gO = '';
10015
10016        if ($groupByFilter != 3) {
10017            $gO = "ORDER BY
10018                        1 DESC,
10019                        2 ASC,
10020                        3 ASC,
10021                        q.commercial ASC,
10022                        {$orderBy}
10023                        DATE_FORMAT(q.namedate, '%e') ASC";
10024        } else {
10025            $gO = 'ORDER BY
10026                        1 DESC,
10027                        2 ASC,
10028                        3 ASC,
10029                        budget_type ASC,
10030                        q.commercial ASC';
10031        }
10032
10033        $query = "WITH business_goal_objective_users AS (
10034                        SELECT
10035                            bg.user_id,
10036                            bg.issue_objective,
10037                            bg.acceptance_objective,
10038                            bg.new_objective,
10039                            bg.is_amount
10040                        FROM tbl_business_goals bg
10041                        WHERE bg.budget_type_group_id = 999999999
10042                    ), business_goal_objective_roles AS (
10043                        SELECT
10044                            bg.role_id,
10045                            bg.issue_objective,
10046                            bg.acceptance_objective,
10047                            bg.new_objective,
10048                            bg.is_amount
10049                        FROM tbl_business_goals bg
10050                        WHERE bg.budget_type_group_id = 999999999
10051                    )
10052
10053                    SELECT
10054                        q.year,
10055                        {$aggregatedCol}
10056                        q.namedate created_at,
10057                        q.commercial,
10058                        q.budget_type,
10059                        COALESCE(SUM(q.issue_date), 0) totalIssue,
10060                        COALESCE(SUM(q.created_at), 0) totalCreatedAt,
10061                        GROUP_CONCAT(q.groupConcatIds) groupConcatIds,
10062                        CASE
10063                            WHEN SUM(q.is_amountIssue) > 0 THEN
10064                                (SUM(q.revenueIssue) / NULLIF(SUM(q.issueObjective), 0)) * 100
10065                            ELSE
10066                                (SUM(q.issue_date) / NULLIF(SUM(q.issueObjective), 0)) * 100
10067                        END AS totalIssueObjective,
10068                        CASE
10069                            WHEN (CASE
10070                                WHEN SUM(q.is_amountIssue) > 0 THEN
10071                                    (SUM(q.revenueIssue) / NULLIF(SUM(q.issueObjective), 0)) * 100
10072                                ELSE
10073                                    (SUM(q.issue_date) / NULLIF(SUM(q.issueObjective), 0)) * 100
10074                            END) BETWEEN 1 AND 70 THEN 'text-danger'
10075                            WHEN (CASE
10076                                WHEN SUM(q.is_amountIssue) > 0 THEN
10077                                    (SUM(q.revenueIssue) / NULLIF(SUM(q.issueObjective), 0)) * 100
10078                                ELSE
10079                                    (SUM(q.issue_date) / NULLIF(SUM(q.issueObjective), 0)) * 100
10080                            END) BETWEEN 70 AND 90 THEN 'text-warning'
10081                        END textIssueColor,
10082                        SUM(q.revenueIssue) revenueIssue,
10083                        CASE
10084                            WHEN SUM(q.is_amountIssue) > 0 THEN
10085                                (SUM(q.revenueIssue) / NULLIF(SUM(q.issueObjectiveMonthly), 0)) * 100
10086                            ELSE
10087                                (SUM(q.issue_date) / NULLIF(SUM(q.issueObjectiveMonthly), 0)) * 100
10088                        END AS totalIssueObjectiveMonthly,
10089                        CASE
10090                            WHEN SUM(q.is_amountIssue) > 0 THEN
10091                                (SUM(q.revenueIssue) / NULLIF(SUM(q.issueObjectiveYearly), 0)) * 100
10092                            ELSE
10093                                (SUM(q.issue_date) / NULLIF(SUM(q.issueObjectiveYearly), 0)) * 100
10094                        END AS totalIssueObjectiveYearly,
10095                        COALESCE(SUM(q.acceptance_date), 0) totalAcceptance,
10096                        GROUP_CONCAT(q.groupConcatCreatedAtIds) groupConcatCreatedAtIds,
10097                        SUM(q.totalIssueLessThan5) AS totalIssueLessThan5,
10098                        GROUP_CONCAT(q.groupConcatIdsIssueLessThan5) AS groupConcatIdsIssueLessThan5,
10099                        GROUP_CONCAT(q.groupConcatAcceptanceIds) groupConcatAcceptanceIds,
10100                        CASE
10101                            WHEN SUM(q.is_amountAcceptance) > 0 THEN
10102                                (SUM(q.revenueAcceptance) / NULLIF(SUM(q.acceptanceObjective), 0)) * 100
10103                            ELSE
10104                                (SUM(q.acceptance_date) / NULLIF(SUM(q.acceptanceObjective), 0)) * 100
10105                        END AS totalAcceptanceObjective,
10106                        CASE
10107                            WHEN SUM(q.is_amountAcceptance) > 0 THEN
10108                                (SUM(q.revenueAcceptance) / NULLIF(SUM(q.acceptanceObjectiveMonthly), 0)) * 100
10109                            ELSE
10110                                (SUM(q.acceptance_date) / NULLIF(SUM(q.acceptanceObjectiveMonthly), 0)) * 100
10111                        END AS totalAcceptanceObjectiveMonthly,
10112                        CASE
10113                            WHEN SUM(q.is_amountAcceptance) > 0 THEN
10114                                (SUM(q.revenueAcceptance) / NULLIF(SUM(q.acceptanceObjectiveYearly), 0)) * 100
10115                            ELSE
10116                                (SUM(q.acceptance_date) / NULLIF(SUM(q.acceptanceObjectiveYearly), 0)) * 100
10117                        END AS totalAcceptanceObjectiveYearly,
10118                        CASE
10119                            WHEN (CASE
10120                                WHEN SUM(q.is_amountAcceptance) > 0 THEN
10121                                    (SUM(q.revenueAcceptance) / NULLIF(SUM(q.acceptanceObjective), 0)) * 100
10122                                ELSE
10123                                    (SUM(q.acceptance_date) / NULLIF(SUM(q.acceptanceObjective), 0)) * 100
10124                            END) BETWEEN 1 AND 70 THEN 'text-danger'
10125                            WHEN (CASE
10126                                WHEN SUM(q.is_amountAcceptance) > 0 THEN
10127                                    (SUM(q.revenueAcceptance) / NULLIF(SUM(q.acceptanceObjective), 0)) * 100
10128                                ELSE
10129                                    (SUM(q.acceptance_date) / NULLIF(SUM(q.acceptanceObjective), 0)) * 100
10130                            END) BETWEEN 70 AND 90 THEN 'text-warning'
10131                        END textAcceptanceColor,
10132                        SUM(q.revenueAcceptance) revenueAcceptance,
10133                        COALESCE(SUM(q.totalRejected), 0) totalRejected,
10134                        GROUP_CONCAT(q.groupConcatRejectedIds) groupConcatRejectedIds,
10135                        SUM(q.revenueRejected) revenueRejected,
10136                        COALESCE(SUM(q.totalNew)) totalNew,
10137                        GROUP_CONCAT(q.groupConcatNewIds) groupConcatNewIds,
10138                        CASE
10139                            WHEN SUM(q.is_amountNew) > 0 THEN
10140                                (SUM(q.revenueNew) / NULLIF(SUM(q.newObjective), 0)) * 100
10141                            ELSE
10142                                (SUM(q.totalNew) / NULLIF(SUM(q.newObjective), 0)) * 100
10143                        END AS totalNewObjective,
10144                        CASE
10145                            WHEN SUM(q.is_amountNew) > 0 THEN
10146                                (SUM(q.revenueNew) / NULLIF(SUM(q.newObjectiveMonthly), 0)) * 100
10147                            ELSE
10148                                (SUM(q.totalNew) / NULLIF(SUM(q.newObjectiveMonthly), 0)) * 100
10149                        END AS totalNewObjectiveMonthly,
10150                        CASE
10151                            WHEN SUM(q.is_amountNew) > 0 THEN
10152                                (SUM(q.revenueNew) / NULLIF(SUM(q.newObjectiveYearly), 0)) * 100
10153                            ELSE
10154                                (SUM(q.totalNew) / NULLIF(SUM(q.newObjectiveYearly), 0)) * 100
10155                        END AS totalNewObjectiveYearly,
10156                        CASE
10157                            WHEN (CASE
10158                                WHEN SUM(q.is_amountNew) > 0 THEN
10159                                    (SUM(q.revenueNew) / NULLIF(SUM(q.newObjective), 0)) * 100
10160                                ELSE
10161                                    (SUM(q.totalNew) / NULLIF(SUM(q.newObjective), 0)) * 100
10162                            END) BETWEEN 1 AND 70 THEN 'text-danger'
10163                            WHEN (CASE
10164                                WHEN SUM(q.is_amountNew) > 0 THEN
10165                                    (SUM(q.revenueNew) / NULLIF(SUM(q.newObjective), 0)) * 100
10166                                ELSE
10167                                    (SUM(q.totalNew) / NULLIF(SUM(q.newObjective), 0)) * 100
10168                            END) BETWEEN 70 AND 90 THEN 'text-warning'
10169                        END textNewColor,
10170                        SUM(q.revenueNew) revenueNew,
10171                        COALESCE(SUM(q.totalVisit), 0) totalVisit,
10172                        GROUP_CONCAT(q.groupConcatVisitIds) groupConcatVisitIds,
10173                        COALESCE(SUM(q.totalCall), 0) totalCall,
10174                        GROUP_CONCAT(q.groupConcatCallIds) groupConcatCallIds,
10175                        SUM(q.is_amountIssue) AS is_amountIssue,
10176                        SUM(q.is_amountNew) AS is_amountNew,
10177                        SUM(q.is_amountAcceptance) AS is_amountAcceptance,
10178                        SUM(q.issueObjective) AS issueObjective,
10179                        SUM(q.issueObjectiveMonthly) AS issueObjectiveMonthly,
10180                        SUM(q.issueObjectiveYearly) AS issueObjectiveYearly,
10181                        SUM(q.newObjective) AS newObjective,
10182                        SUM(q.newObjectiveMonthly) AS newObjectiveMonthly,
10183                        SUM(q.newObjectiveYearly) AS newObjectiveYearly,
10184                        SUM(q.acceptanceObjective) AS acceptanceObjective,
10185                        SUM(q.acceptanceObjectiveMonthly) AS acceptanceObjectiveMonthly,
10186                        SUM(q.acceptanceObjectiveYearly) AS acceptanceObjectiveYearly
10187                        {$visitMainCols}
10188                    FROM
10189                    (
10190                        SELECT
10191                            q.year,
10192                            q.month,
10193                            q.week,
10194                            q.namedate,
10195                            SUM(q.issue_date) AS issue_date,
10196                            q.acceptance_date,
10197                            q.created_at,
10198                            q.commercial,
10199                            q.budget_type,
10200                            GROUP_CONCAT(q.groupConcatIds) AS groupConcatIds,
10201                            CASE
10202                                WHEN q.is_amountIssue > 0 THEN
10203                                    SUM(q.revenueIssue / q.issueObjective) * 100
10204                                ELSE
10205                                    SUM(q.issue_date / q.issueObjective) * 100
10206                                END
10207                            AS totalIssueObjective,
10208                            CASE
10209                                WHEN q.is_amountIssue > 0 THEN
10210                                    SUM(q.revenueIssue / q.issueObjectiveMonthly) * 100
10211                                ELSE
10212                                    SUM(q.issue_date / q.issueObjectiveMonthly) * 100
10213                                END
10214                            AS totalIssueObjectiveMonthly,
10215                            CASE
10216                                WHEN q.is_amountIssue > 0 THEN
10217                                    SUM(q.revenueIssue / q.issueObjectiveYearly) * 100
10218                                ELSE
10219                                    SUM(q.issue_date / q.issueObjectiveYearly) * 100
10220                                END
10221                            AS totalIssueObjectiveYearly,
10222                            SUM(q.revenueIssue) revenueIssue,
10223                            GROUP_CONCAT(q.groupConcatCreatedAtIds) AS groupConcatCreatedAtIds,
10224                            SUM(q.totalIssueLessThan5) totalIssueLessThan5,
10225                            GROUP_CONCAT(q.groupConcatIdsIssueLessThan5) groupConcatIdsIssueLessThan5,
10226                            GROUP_CONCAT(q.groupConcatAcceptanceIds) AS groupConcatAcceptanceIds,
10227                            SUM(q.acceptanceObjective) totalAcceptanceObjective,
10228                            SUM(q.acceptanceObjectiveMonthly) totalAcceptanceObjectiveMonthly,
10229                            SUM(q.acceptanceObjectiveYearly) totalAcceptanceObjectiveYearly,
10230                            q.revenueAcceptance,
10231                            SUM(q.totalRejected) AS totalRejected,
10232                            GROUP_CONCAT(q.groupConcatRejectedIds) AS groupConcatRejectedIds,
10233                            SUM(q.revenueRejected) revenueRejected,
10234                            SUM(q.totalNew) AS totalNew,
10235                            GROUP_CONCAT(q.groupConcatNewIds) AS groupConcatNewIds,
10236                            CASE
10237                                WHEN q.is_amountNew > 0 THEN
10238                                    SUM(q.revenueNew / q.newObjective) * 100
10239                                ELSE
10240                                    SUM(q.totalNew / q.newObjective) * 100
10241                                END
10242                            AS totalNewObjective,
10243                             CASE
10244                                WHEN q.is_amountNew > 0 THEN
10245                                    SUM(q.revenueNew / q.newObjectiveMonthly) * 100
10246                                ELSE
10247                                    SUM(q.totalNew / q.newObjectiveMonthly) * 100
10248                                END
10249                            AS totalNewObjectiveMonthly,
10250                             CASE
10251                                WHEN q.is_amountNew > 0 THEN
10252                                    SUM(q.revenueNew / q.newObjectiveYearly) * 100
10253                                ELSE
10254                                    SUM(q.totalNew / q.newObjectiveYearly) * 100
10255                                END
10256                            AS totalNewObjectiveYearly,
10257                            SUM(q.revenueNew) revenueNew,
10258                            q.totalVisit,
10259                            q.groupConcatVisitIds,
10260                            q.totalCall,
10261                            q.groupConcatCallIds,
10262                            q.priority,
10263                            SUM(q.is_amountIssue) AS is_amountIssue,
10264                            SUM(q.is_amountNew) AS is_amountNew,
10265                            SUM(q.is_amountAcceptance) AS is_amountAcceptance,
10266                            SUM(q.issueObjective) AS issueObjective,
10267                            SUM(q.issueObjectiveMonthly) AS issueObjectiveMonthly,
10268                            SUM(q.issueObjectiveYearly) AS issueObjectiveYearly,
10269                            SUM(q.newObjective) AS newObjective,
10270                            SUM(q.newObjectiveMonthly) AS newObjectiveMonthly,
10271                            SUM(q.newObjectiveYearly) AS newObjectiveYearly,
10272                            SUM(q.acceptanceObjective) AS acceptanceObjective,
10273                            SUM(q.acceptanceObjectiveMonthly) AS acceptanceObjectiveMonthly,
10274                            SUM(q.acceptanceObjectiveYearly) AS acceptanceObjectiveYearly
10275                            {$visitSubMainTableCols}
10276                        FROM (
10277                            SELECT
10278                                YEAR(DATE_ADD(q.issue_date, INTERVAL - WEEKDAY(q.issue_date) DAY)) 'year',
10279                                MONTH(DATE_ADD(q.issue_date, INTERVAL - WEEKDAY(q.issue_date) DAY)) 'month',
10280                                WEEK(DATE_ADD(q.issue_date, INTERVAL - WEEKDAY(q.issue_date) DAY)) 'week',
10281                                DATE_FORMAT(DATE_ADD(q.issue_date, INTERVAL - WEEKDAY(q.issue_date) DAY), '%W, %M %e') namedate,
10282                                COUNT(CASE WHEN q.issue_date IS NOT NULL THEN 1 END) issue_date,
10283                                0 acceptance_date,
10284                                0 created_at,
10285                                q.commercial,
10286                                btg.name budget_type,
10287                                GROUP_CONCAT(CASE WHEN q.issue_date IS NOT NULL THEN q.id END) AS groupConcatIds,
10288
10289                                SUM(CASE WHEN q.issue_date IS NOT NULL THEN q.amount END) AS revenueIssue,
10290                                NULL groupConcatCreatedAtIds,
10291                                0 totalIssueLessThan5,
10292                                NULL groupConcatIdsIssueLessThan5,
10293                                NULL groupConcatAcceptanceIds,
10294
10295                                0 revenueAcceptance,
10296                                COUNT(CASE WHEN bs.name = 'Rechazado' THEN 1 END) AS totalRejected,
10297                                GROUP_CONCAT(DISTINCT CASE WHEN bs.name = 'Rechazado' THEN q.id END) AS groupConcatRejectedIds,
10298                                COALESCE(SUM(CASE WHEN bs.name = 'Rechazado' THEN q.amount END), 0) AS revenueRejected,
10299                                COUNT(CASE WHEN ct.name = 'Nuevo' THEN 1 END) AS totalNew,
10300                                GROUP_CONCAT(DISTINCT CASE WHEN ct.name = 'Nuevo' THEN q.id END) AS groupConcatNewIds,
10301
10302                                COALESCE(SUM(CASE WHEN ct.name = 'Nuevo' THEN q.amount END), 0) revenueNew,
10303                                0 totalVisit,
10304                                NULL groupConcatVisitIds,
10305                                0 totalCall,
10306                                NULL groupConcatCallIds,
10307                                btg.priority,
10308                                CAST(
10309                                    CASE
10310                                        WHEN bg.issue_objective IS NOT NULL THEN bg.is_amount
10311                                        WHEN bgou.issue_objective IS NOT NULL THEN bgou.is_amount
10312                                        WHEN bg1.issue_objective IS NOT NULL THEN bg1.is_amount
10313                                        WHEN bgor.issue_objective IS NOT NULL THEN bgor.is_amount
10314                                        WHEN bgde.issue_objective IS NOT NULL THEN bgde.is_amount
10315                                        WHEN bg.issue_objective IS NULL AND bg1.issue_objective IS NULL THEN {$businessGoalsDefault->is_amount}
10316                                    END
10317                                AS DOUBLE) AS is_amountIssue,
10318                                CAST(
10319                                    CASE
10320                                        WHEN bg.new_objective IS NOT NULL THEN bg.is_amount
10321                                        WHEN bgou.new_objective IS NOT NULL THEN bgou.is_amount
10322                                        WHEN bg1.new_objective IS NOT NULL THEN bg1.is_amount
10323                                        WHEN bgor.new_objective IS NOT NULL THEN bgor.is_amount
10324                                        WHEN bgde.new_objective IS NOT NULL THEN bgde.is_amount
10325                                        WHEN bg.new_objective IS NULL AND bg1.new_objective IS NULL THEN {$businessGoalsDefault->is_amount}
10326                                    END
10327                                AS DOUBLE) AS is_amountNew,
10328                                0 is_amountAcceptance,
10329                                CAST(
10330                                    CASE
10331                                        WHEN bg.issue_objective IS NOT NULL THEN bg.issue_objective
10332                                        WHEN bgou.issue_objective IS NOT NULL THEN bgou.issue_objective
10333                                        WHEN bg1.issue_objective IS NOT NULL THEN bg1.issue_objective
10334                                        WHEN bgor.issue_objective IS NOT NULL THEN bgor.issue_objective
10335                                        WHEN bgde.issue_objective IS NOT NULL THEN bgde.issue_objective
10336                                        WHEN bg.issue_objective IS NULL AND bg1.issue_objective IS NULL THEN {$businessGoalsDefault->issue_objective}
10337                                    END {$aggregatedByCalc}
10338                                AS DOUBLE) AS issueObjective,
10339                                CAST(
10340                                    CASE
10341                                        WHEN bg.issue_objective IS NOT NULL THEN bg.issue_objective
10342                                        WHEN bgou.issue_objective IS NOT NULL THEN bgou.issue_objective
10343                                        WHEN bg1.issue_objective IS NOT NULL THEN bg1.issue_objective
10344                                        WHEN bgor.issue_objective IS NOT NULL THEN bgor.issue_objective
10345                                        WHEN bgde.issue_objective IS NOT NULL THEN bgde.issue_objective
10346                                        WHEN bg.issue_objective IS NULL AND bg1.issue_objective IS NULL THEN {$businessGoalsDefault->issue_objective}
10347                                    END
10348                                AS DOUBLE) AS issueObjectiveMonthly,
10349                                CAST(
10350                                    CASE
10351                                        WHEN bg.issue_objective IS NOT NULL THEN bg.issue_objective
10352                                        WHEN bgou.issue_objective IS NOT NULL THEN bgou.issue_objective
10353                                        WHEN bg1.issue_objective IS NOT NULL THEN bg1.issue_objective
10354                                        WHEN bgor.issue_objective IS NOT NULL THEN bgor.issue_objective
10355                                        WHEN bgde.issue_objective IS NOT NULL THEN bgde.issue_objective
10356                                        WHEN bg.issue_objective IS NULL AND bg1.issue_objective IS NULL THEN {$businessGoalsDefault->issue_objective}
10357                                    END * 12
10358                                AS DOUBLE) AS issueObjectiveYearly,
10359                                CAST(
10360                                    CASE
10361                                        WHEN bg.new_objective IS NOT NULL THEN bg.new_objective
10362                                        WHEN bgou.new_objective IS NOT NULL THEN bgou.new_objective
10363                                        WHEN bg1.new_objective IS NOT NULL THEN bg1.new_objective
10364                                        WHEN bgor.new_objective IS NOT NULL THEN bgor.new_objective
10365                                        WHEN bgde.new_objective IS NOT NULL THEN bgde.new_objective
10366                                        WHEN bg.new_objective IS NULL AND bg1.new_objective IS NULL THEN {$businessGoalsDefault->new_objective}
10367                                    END {$aggregatedByCalc}
10368                                AS DOUBLE) AS newObjective,
10369                                CAST(
10370                                    CASE
10371                                        WHEN bg.new_objective IS NOT NULL THEN bg.new_objective
10372                                        WHEN bgou.new_objective IS NOT NULL THEN bgou.new_objective
10373                                        WHEN bg1.new_objective IS NOT NULL THEN bg1.new_objective
10374                                        WHEN bgor.new_objective IS NOT NULL THEN bgor.new_objective
10375                                        WHEN bgde.new_objective IS NOT NULL THEN bgde.new_objective
10376                                        WHEN bg.new_objective IS NULL AND bg1.new_objective IS NULL THEN {$businessGoalsDefault->new_objective}
10377                                    END
10378                                AS DOUBLE) AS newObjectiveMonthly,
10379                                CAST(
10380                                    CASE
10381                                        WHEN bg.new_objective IS NOT NULL THEN bg.new_objective
10382                                        WHEN bgou.new_objective IS NOT NULL THEN bgou.new_objective
10383                                        WHEN bg1.new_objective IS NOT NULL THEN bg1.new_objective
10384                                        WHEN bgor.new_objective IS NOT NULL THEN bgor.new_objective
10385                                        WHEN bgde.new_objective IS NOT NULL THEN bgde.new_objective
10386                                        WHEN bg.new_objective IS NULL AND bg1.new_objective IS NULL THEN {$businessGoalsDefault->new_objective}
10387                                    END * 12
10388                                AS DOUBLE) AS newObjectiveYearly,
10389                                0 acceptanceObjective,
10390                                0 acceptanceObjectiveMonthly,
10391                                0 acceptanceObjectiveYearly
10392                                {$visitSubTableCols}
10393                            FROM
10394                            tbl_quotations q
10395                                LEFT JOIN tbl_sources s ON s.source_id = q.source_id
10396                                LEFT JOIN tbl_budget_status bs ON bs.budget_status_id = q.budget_status_id
10397                                LEFT JOIN tbl_budget_types bt ON q.budget_type_id = bt.budget_type_id
10398                                LEFT JOIN tbl_budget_type_groups btg ON btg.budget_type_group_id = bt.budget_type_group_id
10399                                LEFT JOIN tbl_customer_types ct ON q.customer_type_id = ct.customer_type_id
10400                                LEFT JOIN tbl_users u ON q.commercial = u.name
10401                                LEFT JOIN tbl_roles r ON u.role_id = r.role_id
10402                                LEFT JOIN tbl_business_goals bg ON bg.budget_type_group_id = btg.budget_type_group_id AND bg.user_id = u.id
10403                                LEFT JOIN tbl_business_goals bg1 ON bg1.budget_type_group_id = btg.budget_type_group_id AND bg1.role_id = r.role_id
10404                                LEFT JOIN tbl_business_goals bgde ON bgde.budget_type_group_id = btg.budget_type_group_id AND bgde.is_default = 1
10405                                LEFT JOIN business_goal_objective_users bgou ON bgou.user_id = u.id
10406                                LEFT JOIN business_goal_objective_roles bgor ON bgor.role_id = r.role_id
10407                            WHERE
10408                                q.budget_type_id != 7
10409                                AND q.budget_type_id IS NOT NULL
10410                                AND q.for_add = 0
10411                                AND q.amount REGEXP '^[0-9]+\\.?[0-9]*$' = 1
10412                                AND bt.include = 1
10413                                AND (q.commercial IS NOT NULL AND q.commercial != '')
10414                                {$where}
10415                                {$whereYear}
10416                            GROUP BY
10417                                {$groupBy}
10418                        ) q
10419                        GROUP BY
10420                            {$groupBy} WITH ROLLUP
10421
10422                        UNION ALL
10423
10424                        SELECT
10425                            q.year,
10426                            q.month,
10427                            q.week,
10428                            q.namedate,
10429                            q.issue_date,
10430                            SUM(q.acceptance_date) AS acceptance_date,
10431                            q.created_at,
10432                            q.commercial,
10433                            q.budget_type,
10434                            q.groupConcatIds,
10435                            q.issueObjective totalIssueObjective,
10436                            q.issueObjectiveMonthly totalIssueObjectiveMonthly,
10437                            q.issueObjectiveYearly totalIssueObjectiveYearly,
10438                            q.revenueIssue,
10439                            q.groupConcatCreatedAtIds,
10440                            q.totalIssueLessThan5,
10441                            q.groupConcatIdsIssueLessThan5,
10442                            GROUP_CONCAT(q.groupConcatAcceptanceIds) AS groupConcatAcceptanceIds,
10443                            CASE
10444                                WHEN q.is_amountAcceptance > 0 THEN
10445                                    SUM(q.revenueAcceptance / q.acceptanceObjective) * 100
10446                                ELSE
10447                                    SUM(q.acceptance_date / q.acceptanceObjective) * 100
10448                                END
10449                            AS totalAcceptanceObjective,
10450                            CASE
10451                                WHEN q.is_amountAcceptance > 0 THEN
10452                                    SUM(q.revenueAcceptance / q.acceptanceObjectiveMonthly) * 100
10453                                ELSE
10454                                    SUM(q.acceptance_date / q.acceptanceObjectiveMonthly) * 100
10455                                END
10456                            AS totalAcceptanceObjectiveMonthly,
10457                            CASE
10458                                WHEN q.is_amountAcceptance > 0 THEN
10459                                    SUM(q.revenueAcceptance / q.acceptanceObjectiveYearly) * 100
10460                                ELSE
10461                                    SUM(q.acceptance_date / q.acceptanceObjectiveYearly) * 100
10462                                END
10463                            AS totalAcceptanceObjectiveYearly,
10464                            SUM(q.revenueAcceptance) revenueAcceptance,
10465                            q.totalRejected,
10466                            q.groupConcatRejectedIds,
10467                            q.revenueRejected,
10468                            q.totalNew,
10469                            q.groupConcatNewIds,
10470                            q.newObjective totalNewObjective,
10471                            q.newObjectiveMonthly totalNewObjectiveMonthly,
10472                            q.newObjectiveYearly totalNewObjectiveYearly,
10473                            q.revenueNew,
10474                            q.totalVisit,
10475                            q.groupConcatVisitIds,
10476                            q.totalCall,
10477                            q.groupConcatCallIds,
10478                            q.priority,
10479                            SUM(q.is_amountIssue) AS is_amountIssue,
10480                            q.is_amountNew,
10481                            q.is_amountAcceptance,
10482                            SUM(q.issueObjective) AS issueObjective,
10483                            SUM(q.issueObjectiveMonthly) AS issueObjectiveMonthly,
10484                            SUM(q.issueObjectiveYearly) AS issueObjectiveYearly,
10485                            SUM(q.newObjective) AS newObjective,
10486                            SUM(q.newObjectiveMonthly) AS newObjectiveMonthly,
10487                            SUM(q.newObjectiveYearly) AS newObjectiveYearly,
10488                            SUM(q.acceptanceObjective) AS acceptanceObjective,
10489                            SUM(q.acceptanceObjectiveMonthly) AS acceptanceObjectiveMonthly,
10490                            SUM(q.acceptanceObjectiveYearly) AS acceptanceObjectiveYearly
10491                            {$visitSubMainTableCols}
10492                        FROM (
10493                            SELECT
10494                                YEAR(DATE_ADD(q.acceptance_date, INTERVAL - WEEKDAY(q.acceptance_date) DAY)) 'year',
10495                                MONTH(DATE_ADD(q.acceptance_date, INTERVAL - WEEKDAY(q.acceptance_date) DAY)) 'month',
10496                                WEEK(DATE_ADD(q.acceptance_date, INTERVAL - WEEKDAY(q.acceptance_date) DAY)) 'week',
10497                                DATE_FORMAT(DATE_ADD(q.acceptance_date, INTERVAL - WEEKDAY(q.acceptance_date) DAY), '%W, %M %e') namedate,
10498                                0 issue_date,
10499                                COUNT(CASE WHEN q.acceptance_date IS NOT NULL THEN 1 END) acceptance_date,
10500                                0 created_at,
10501                                q.commercial,
10502                                btg.name budget_type,
10503                                NULL groupConcatIds,
10504
10505                                0 revenueIssue,
10506                                NULL groupConcatCreatedAtIds,
10507                                0 totalIssueLessThan5,
10508                                NULL groupConcatIdsIssueLessThan5,
10509                                GROUP_CONCAT(CASE WHEN q.acceptance_date IS NOT NULL THEN q.id END) AS groupConcatAcceptanceIds,
10510
10511                                COALESCE(SUM(CASE WHEN q.acceptance_date IS NOT NULL THEN q.amount END), 0) AS revenueAcceptance,
10512                                0 totalRejected,
10513                                NULL groupConcatRejectedIds,
10514                                0 revenueRejected,
10515                                0 totalNew,
10516                                NULL groupConcatNewIds,
10517                                NULL totalNewObjective,
10518                                NULL totalNewObjectiveMonthly,
10519                                NULL totalNewObjectiveYearly,
10520                                0 revenueNew,
10521                                0 totalVisit,
10522                                NULL groupConcatVisitIds,
10523                                0 totalCall,
10524                                NULL groupConcatCallIds,
10525                                btg.priority,
10526                                0 is_amountIssue,
10527                                0 is_amountNew,
10528                                CAST(
10529                                    CASE
10530                                        WHEN bg.acceptance_objective IS NOT NULL THEN bg.is_amount
10531                                        WHEN bgou.acceptance_objective IS NOT NULL THEN bgou.is_amount
10532                                        WHEN bg1.acceptance_objective IS NOT NULL THEN bg1.is_amount
10533                                        WHEN bgor.acceptance_objective IS NOT NULL THEN bgor.is_amount
10534                                        WHEN bgde.acceptance_objective IS NOT NULL THEN bgde.is_amount
10535                                        WHEN bg.acceptance_objective IS NULL AND bg1.acceptance_objective IS NULL THEN {$businessGoalsDefault->is_amount}
10536                                    END
10537                                AS DOUBLE) AS is_amountAcceptance,
10538                                0 issueObjective,
10539                                0 issueObjectiveMonthly,
10540                                0 issueObjectiveYearly,
10541                                0 newObjective,
10542                                0 newObjectiveMonthly,
10543                                0 newObjectiveYearly,
10544                                CAST(
10545                                    CASE
10546                                        WHEN bg.acceptance_objective IS NOT NULL THEN bg.acceptance_objective
10547                                        WHEN bgou.acceptance_objective IS NOT NULL THEN bgou.acceptance_objective
10548                                        WHEN bg1.acceptance_objective IS NOT NULL THEN bg1.acceptance_objective
10549                                        WHEN bgor.acceptance_objective IS NOT NULL THEN bgor.acceptance_objective
10550                                        WHEN bgde.acceptance_objective IS NOT NULL THEN bgde.acceptance_objective
10551                                        WHEN bg.acceptance_objective IS NULL AND bg1.acceptance_objective IS NULL THEN {$businessGoalsDefault->acceptance_objective}
10552                                    END {$aggregatedByCalc}
10553                                AS DOUBLE) AS acceptanceObjective,
10554                                CAST(
10555                                    CASE
10556                                        WHEN bg.acceptance_objective IS NOT NULL THEN bg.acceptance_objective
10557                                        WHEN bgou.acceptance_objective IS NOT NULL THEN bgou.acceptance_objective
10558                                        WHEN bg1.acceptance_objective IS NOT NULL THEN bg1.acceptance_objective
10559                                        WHEN bgor.acceptance_objective IS NOT NULL THEN bgor.acceptance_objective
10560                                        WHEN bgde.acceptance_objective IS NOT NULL THEN bgde.acceptance_objective
10561                                        WHEN bg.acceptance_objective IS NULL AND bg1.acceptance_objective IS NULL THEN {$businessGoalsDefault->acceptance_objective}
10562                                    END
10563                                AS DOUBLE) AS acceptanceObjectiveMonthly,
10564                                CAST(
10565                                    CASE
10566                                        WHEN bg.acceptance_objective IS NOT NULL THEN bg.acceptance_objective
10567                                        WHEN bgou.acceptance_objective IS NOT NULL THEN bgou.acceptance_objective
10568                                        WHEN bg1.acceptance_objective IS NOT NULL THEN bg1.acceptance_objective
10569                                        WHEN bgor.acceptance_objective IS NOT NULL THEN bgor.acceptance_objective
10570                                        WHEN bgde.acceptance_objective IS NOT NULL THEN bgde.acceptance_objective
10571                                        WHEN bg.acceptance_objective IS NULL AND bg1.acceptance_objective IS NULL THEN {$businessGoalsDefault->acceptance_objective}
10572                                    END * 12
10573                                AS DOUBLE) AS acceptanceObjectiveYearly
10574                                {$visitSubTableCols}
10575                            FROM
10576                            tbl_quotations q
10577                                LEFT JOIN tbl_sources s ON s.source_id = q.source_id
10578                                LEFT JOIN tbl_budget_status bs ON bs.budget_status_id = q.budget_status_id
10579                                LEFT JOIN tbl_budget_types bt ON q.budget_type_id = bt.budget_type_id
10580                                LEFT JOIN tbl_budget_type_groups btg ON btg.budget_type_group_id = bt.budget_type_group_id
10581                                LEFT JOIN tbl_customer_types ct ON q.customer_type_id = ct.customer_type_id
10582                                LEFT JOIN tbl_users u ON q.commercial = u.name
10583                                LEFT JOIN tbl_roles r ON u.role_id = r.role_id
10584                                LEFT JOIN tbl_business_goals bg ON bg.budget_type_group_id = btg.budget_type_group_id AND bg.user_id = u.id
10585                                LEFT JOIN tbl_business_goals bg1 ON bg1.budget_type_group_id = btg.budget_type_group_id AND bg1.role_id = r.role_id
10586                                LEFT JOIN tbl_business_goals bgde ON bgde.budget_type_group_id = btg.budget_type_group_id AND bgde.is_default = 1
10587                                LEFT JOIN business_goal_objective_users bgou ON bgou.user_id = u.id
10588                                LEFT JOIN business_goal_objective_roles bgor ON bgor.role_id = r.role_id
10589                            WHERE
10590                                q.budget_type_id != 7
10591                                AND q.budget_type_id IS NOT NULL
10592                                AND q.for_add = 0
10593                                AND q.amount REGEXP '^[0-9]+\\.?[0-9]*$' = 1
10594                                AND bt.include = 1
10595                                AND (q.commercial IS NOT NULL AND q.commercial != '')
10596                                {$whereAcceptanceDate}
10597                                {$whereYear}
10598                            GROUP BY
10599                                {$groupBy}
10600                        ) q
10601                        GROUP BY
10602                            {$groupBy} WITH ROLLUP
10603
10604                        UNION ALL
10605
10606                        SELECT
10607                            q.year,
10608                            q.month,
10609                            q.week,
10610                            q.namedate,
10611                            q.issue_date,
10612                            q.acceptance_date,
10613                            SUM(q.created_at) AS created_at,
10614                            q.commercial,
10615                            q.budget_type,
10616                            q.groupConcatIds,
10617                            q.issueObjective totalIssueObjective,
10618                            q.issueObjectiveMonthly totalIssueObjectiveMonthly,
10619                            q.issueObjectiveYearly totalIssueObjectiveYearly,
10620                            q.revenueIssue,
10621                            GROUP_CONCAT(q.groupConcatCreatedAtIds) AS groupConcatCreatedAtIds,
10622                            SUM(q.totalIssueLessThan5) AS totalIssueLessThan5,
10623                            GROUP_CONCAT(q.groupConcatIdsIssueLessThan5) AS groupConcatIdsIssueLessThan5,
10624                            NULL groupConcatAcceptanceIds,
10625                            0 totalAcceptanceObjective,
10626                            0 totalAcceptanceObjectiveMonthly,
10627                            0 totalAcceptanceObjectiveYearly,
10628                            SUM(q.revenueAcceptance) revenueAcceptance,
10629                            q.totalRejected,
10630                            q.groupConcatRejectedIds,
10631                            q.revenueRejected,
10632                            q.totalNew,
10633                            q.groupConcatNewIds,
10634                            q.newObjective totalNewObjective,
10635                            q.newObjectiveMonthly totalNewObjectiveMonthly,
10636                            q.newObjectiveYearly totalNewObjectiveYearly,
10637                            q.revenueNew,
10638                            q.totalVisit,
10639                            q.groupConcatVisitIds,
10640                            q.totalCall,
10641                            q.groupConcatCallIds,
10642                            q.priority,
10643                            SUM(q.is_amountIssue) AS is_amountIssue,
10644                            q.is_amountNew,
10645                            q.is_amountAcceptance,
10646                            SUM(q.issueObjective) AS issueObjective,
10647                            SUM(q.issueObjectiveMonthly) AS issueObjectiveMonthly,
10648                            SUM(q.issueObjectiveYearly) AS issueObjectiveYearly,
10649                            SUM(q.newObjective) AS newObjective,
10650                            SUM(q.newObjectiveMonthly) AS newObjectiveMonthly,
10651                            SUM(q.newObjectiveYearly) AS newObjectiveYearly,
10652                            SUM(q.acceptanceObjective) AS acceptanceObjective,
10653                            SUM(q.acceptanceObjectiveMonthly) AS acceptanceObjectiveMonthly,
10654                            SUM(q.acceptanceObjectiveYearly) AS acceptanceObjectiveYearly
10655                            {$visitSubMainTableCols}
10656                        FROM (
10657                            SELECT
10658                                YEAR(DATE_ADD(q.created_at, INTERVAL - WEEKDAY(q.created_at) DAY)) 'year',
10659                                MONTH(DATE_ADD(q.created_at, INTERVAL - WEEKDAY(q.created_at) DAY)) 'month',
10660                                WEEK(DATE_ADD(q.created_at, INTERVAL - WEEKDAY(q.created_at) DAY)) 'week',
10661                                DATE_FORMAT(DATE_ADD(q.created_at, INTERVAL - WEEKDAY(q.created_at) DAY), '%W, %M %e') namedate,
10662                                0 issue_date,
10663                                0 acceptance_date,
10664                                COUNT(CASE WHEN q.created_at IS NOT NULL THEN 1 END) created_at,
10665                                q.commercial,
10666                                btg.name budget_type,
10667                                NULL groupConcatIds,
10668
10669                                0 revenueIssue,
10670                                GROUP_CONCAT(CASE WHEN q.created_at IS NOT NULL THEN q.id END) AS groupConcatCreatedAtIds,
10671                                COUNT(CASE WHEN ABS(DATEDIFF(q.created_at, q.issue_date)) < 5 THEN 1 END) AS totalIssueLessThan5,
10672                                GROUP_CONCAT(CASE WHEN ABS(DATEDIFF(q.created_at, q.issue_date)) < 5 THEN q.id END) AS groupConcatIdsIssueLessThan5,
10673                                NULL groupConcatAcceptanceIds,
10674
10675                                0 AS revenueAcceptance,
10676                                0 totalRejected,
10677                                NULL groupConcatRejectedIds,
10678                                0 revenueRejected,
10679                                0 totalNew,
10680                                NULL groupConcatNewIds,
10681                                NULL totalNewObjective,
10682                                NULL totalNewObjectiveMonthly,
10683                                NULL totalNewObjectiveYearly,
10684                                0 revenueNew,
10685                                0 totalVisit,
10686                                NULL groupConcatVisitIds,
10687                                0 totalCall,
10688                                NULL groupConcatCallIds,
10689                                btg.priority,
10690                                0 is_amountIssue,
10691                                0 is_amountNew,
10692                                0 is_amountAcceptance,
10693                                0 issueObjective,
10694                                0 issueObjectiveMonthly,
10695                                0 issueObjectiveYearly,
10696                                0 newObjective,
10697                                0 newObjectiveMonthly,
10698                                0 newObjectiveYearly,
10699                                0 acceptanceObjective,
10700                                0 acceptanceObjectiveMonthly,
10701                                0 acceptanceObjectiveYearly
10702                                {$visitSubTableCols}
10703                            FROM
10704                            tbl_quotations q
10705                                LEFT JOIN tbl_sources s ON s.source_id = q.source_id
10706                                LEFT JOIN tbl_budget_status bs ON bs.budget_status_id = q.budget_status_id
10707                                LEFT JOIN tbl_budget_types bt ON q.budget_type_id = bt.budget_type_id
10708                                LEFT JOIN tbl_budget_type_groups btg ON btg.budget_type_group_id = bt.budget_type_group_id
10709                                LEFT JOIN tbl_customer_types ct ON q.customer_type_id = ct.customer_type_id
10710                                LEFT JOIN tbl_users u ON q.commercial = u.name
10711                                LEFT JOIN tbl_roles r ON u.role_id = r.role_id
10712                            WHERE
10713                                q.budget_type_id != 7
10714                                AND q.budget_type_id IS NOT NULL
10715                                AND q.for_add = 0
10716                                AND q.amount REGEXP '^[0-9]+\\.?[0-9]*$' = 1
10717                                AND bt.include = 1
10718                                AND (q.commercial IS NOT NULL AND q.commercial != '')
10719                                {$whereCreatedAt}
10720                                {$whereYear}
10721                            GROUP BY
10722                                {$groupBy}
10723                        ) q
10724                        GROUP BY
10725                            {$groupBy} WITH ROLLUP
10726
10727                        UNION ALL
10728
10729                        SELECT
10730                            YEAR(DATE_ADD(q.visit_date, INTERVAL - WEEKDAY(q.visit_date) DAY)) YEAR,
10731                            MONTH(DATE_ADD(q.visit_date, INTERVAL - WEEKDAY(q.visit_date) DAY)) MONTH,
10732                            WEEK(DATE_ADD(q.visit_date, INTERVAL - WEEKDAY(q.visit_date) DAY)) WEEK,
10733                            DATE_FORMAT(DATE_ADD(visit_date, INTERVAL - WEEKDAY(q.visit_date) DAY), '%W, %M %e') namedate,
10734                            0 issue_date,
10735                            0 acceptance_date,
10736                            0 created_at,
10737                            commercial,
10738                            NULL budget_type,
10739                            NULL groupConcatIds,
10740                            NULL totalIssueObjective,
10741                            NULL totalIssueObjectiveMonthly,
10742                            NULL totalIssueObjectiveYearly,
10743                            0 revenueIssue,
10744                            NULL groupConcatCreatedAtIds,
10745                            0 totalIssueLessThan5,
10746                            NULL groupConcatIdsIssueLessThan5,
10747                            NULL groupConcatAcceptanceIds,
10748                            NULL totalAcceptanceObjective,NULL totalAcceptanceObjectiveMonthly,
10749                            NULL totalAcceptanceObjectiveYearly,
10750                            0 revenueAcceptance,
10751                            0 totalRejected,
10752                            NULL groupConcatRejectedIds,
10753                            0 revenueRejected,
10754                            0 totalNew,
10755                            NULL groupConcatNewIds,
10756                            NULL totalNewObjective,NULL totalNewObjectiveMonthly,
10757                            NULL totalNewObjectiveYearly,
10758                            0 revenueNew,
10759                            COUNT(CASE WHEN q.visit_date IS NOT NULL AND q.visit_call = 'Visita' THEN 1 END) totalVisit,
10760                            GROUP_CONCAT(CASE WHEN q.visit_date IS NOT NULL AND q.visit_call = 'Visita' THEN q.id END) AS groupConcatVisitIds,
10761                            COUNT(CASE WHEN q.visit_date IS NOT NULL AND q.visit_call = 'Llamada' THEN 1 END) totalCall,
10762                            GROUP_CONCAT(CASE WHEN q.visit_date IS NOT NULL AND q.visit_call = 'Llamada' THEN q.id END) AS groupConcatCallIds,
10763                            0 priority,
10764                            0 is_amountIssue,
10765                            0 is_amountNew,
10766                            0 is_amountAcceptance,
10767                            0 issueObjective,
10768                            0 issueObjectiveMonthly,
10769                            0 issueObjectiveYearly,
10770                            0 newObjective,
10771                            0 newObjectiveMontly,
10772                            0 newObjectiveYearly,
10773                            0 acceptanceObjective,
10774                            0 acceptanceObjectiveMonthly,
10775                            0 acceptanceObjectiveYearly
10776                            {$visitCols}
10777                        FROM
10778                            tbl_pipelines q
10779                        LEFT JOIN tbl_users u ON q.commercial = u.name
10780                        LEFT JOIN tbl_roles r ON u.role_id = r.role_id
10781                        LEFT JOIN tbl_visit_types v ON q.visit_type_id = v.visit_type_id
10782                        WHERE q.visit_date IS NOT NULL
10783                            {$whereVisit}
10784                        GROUP BY
10785                            {$groupBy}
10786                             WITH ROLLUP
10787                    ) q
10788                    WHERE
10789                        q.year NOT IN (2021, 2022)
10790                    GROUP BY
10791                        {$groupBy}
10792                    {$gO}";
10793
10794        $value = Cache::get(base64_encode($query));
10795
10796        if (! $value) {
10797            $result = DB::select($query);
10798
10799            $structureData = new StructureData;
10800            $result = $structureData->parse($result, $groupByFilter, $aggregatedBy);
10801
10802            Cache::put(base64_encode($query), $result, 600);
10803        } else {
10804            $result = $value;
10805        }
10806
10807        return response([
10808            'message' => 'OK',
10809            'data' => $result,
10810        ]);
10811
10812        // } catch (\Exception $e) {
10813        //     return response(['message' => 'KO', 'error' => $e->getMessage()]);
10814        // }
10815    }
10816
10817    public function list_quotations_deleted($companyId)
10818    {
10819
10820        try {
10821
10822            $companyId = intval($companyId);
10823            $where = '';
10824
10825            if ($companyId != 0) {
10826                $where = " a.company_id = {$companyId} ";
10827            } else {
10828                $where = " a.company_id IN ({$this->companyId})";
10829            }
10830
10831            $query = "SELECT
10832                        a.id,
10833                        a.quote_id,
10834                        a.company_id,
10835                        b.name company_name,
10836                        a.created_by,
10837                        a.updated_by,
10838                        a.updated_at,
10839                        a.for_add,
10840                        c.name reason,
10841                        a.reason_for_deletion
10842                    FROM tbl_quotations_deleted a
10843                    LEFT JOIN tbl_companies b
10844                        ON a.company_id = b.company_id
10845                    LEFT JOIN tbl_reasons c
10846                        ON a.reason_id = c.reason_id
10847                    WHERE {$where}
10848                    ORDER BY a.updated_at DESC";
10849
10850            $result = DB::select($query);
10851
10852            return response([
10853                'message' => 'OK',
10854                'data' => $result,
10855            ]);
10856        } catch (\Exception $e) {
10857            /** @disregard P1014 */
10858            $e->exceptionCode = 'LIST_QUOTATIONS_DELETED_EXCEPTION';
10859            report($e);
10860
10861            return response(['message' => 'KO', 'error' => $e->getMessage()]);
10862        }
10863    }
10864
10865    public function delete_sengrid($id)
10866    {
10867
10868        try {
10869
10870            $id = intval($id);
10871
10872            $order = TblQuotations::where('id', $id)->first();
10873
10874            if ($order) {
10875                if ($order->x_message_id != null) {
10876                    TblSendgridWebhook::where('quotation_id', $id)->where('x_message_id', $order->x_message_id)->delete();
10877
10878                    TblQuotations::where('id', $id)->update(
10879                        [
10880                            'x_message_id' => null,
10881                            'x_status' => null,
10882                        ]
10883                    );
10884
10885                    Cache::flush();
10886                }
10887            }
10888
10889            return response([
10890                'message' => 'OK',
10891            ]);
10892
10893        } catch (\Exception $e) {
10894            /** @disregard P1014 */
10895            $e->exceptionCode = 'DELETE_SENDGRID_EXCEPTION';
10896            report($e);
10897
10898            return response(['message' => 'KO', 'error' => $e->getMessage()]);
10899        }
10900    }
10901
10902    public function download_productivity_commercial(Request $request)
10903    {
10904
10905        try {
10906
10907            ini_set('max_execution_time', 123456);
10908
10909            $data = $request->all();
10910
10911            $result = $this->list_quotation_analytics_commercial_productivity($request);
10912            $result = $result->original['data'];
10913
10914            $spreadsheet = new Spreadsheet;
10915            $worksheet = new \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet($spreadsheet, 'Inputs');
10916            $spreadsheet->addSheet($worksheet, 0);
10917            $col = range('A', 'Z');
10918
10919            for ($i = 0; $i < 26; $i++) {
10920                $worksheet->getColumnDimension($col[$i])->setAutoSize(true);
10921                if ($i != 1) {
10922                    $worksheet->getStyle($col[$i])
10923                        ->getAlignment()
10924                        ->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
10925                }
10926            }
10927
10928            $l = 1;
10929            $worksheet->setCellValue('A'.$l, 'Años');
10930
10931            if ($data['group_by'] == 1) {
10932                $worksheet->setCellValue('B'.$l, 'Comercials');
10933                $worksheet->setCellValue('C'.$l, 'Meses');
10934                $worksheet->setCellValue('D'.$l, 'Semanas');
10935            } else {
10936                $worksheet->setCellValue('B'.$l, 'Meses');
10937                $worksheet->setCellValue('C'.$l, 'Semanas');
10938                $worksheet->setCellValue('D'.$l, 'Comercials');
10939            }
10940
10941            $worksheet->setCellValue('E'.$l, 'Categorías de presupuesto');
10942            $worksheet->setCellValue('F'.$l, 'Presupuestos emitidos (#)');
10943            $worksheet->setCellValue('G'.$l, 'Presupuestos emitidos (€)');
10944            $worksheet->setCellValue('H'.$l, 'Presupuestos emitidos (Objetivo)');
10945            $worksheet->setCellValue('I'.$l, 'Presupuestos aceptados (#)');
10946            $worksheet->setCellValue('J'.$l, 'Presupuestos aceptados (€)');
10947            $worksheet->setCellValue('K'.$l, 'Presupuestos aceptados (Objetivo)');
10948            $worksheet->setCellValue('L'.$l, 'Presupuestos rechazados (#)');
10949            $worksheet->setCellValue('M'.$l, 'Presupuestos rechazados (€)');
10950            $worksheet->setCellValue('N'.$l, 'Presupuestos emitidos a nuevos clientes (#)');
10951            $worksheet->setCellValue('O'.$l, 'Presupuestos emitidos a nuevos clientes (€)');
10952            $worksheet->setCellValue('P'.$l, 'Presupuestos emitidos a nuevos clientes (Objetivo)');
10953            $worksheet->setCellValue('Q'.$l, 'Venta (Llamada #)');
10954            $worksheet->setCellValue('R'.$l, 'Venta (Visita #)');
10955            $worksheet->setCellValue('S'.$l, 'Servicio (Llamada #)');
10956            $worksheet->setCellValue('T'.$l, 'Servicio (Visita #)');
10957
10958            $l++;
10959
10960            foreach ($result as $item) {
10961
10962                $worksheet->setCellValue('A'.$l, $item['year']);
10963                $worksheet->setCellValue('F'.$l, $item['totalIssue']);
10964                $worksheet->setCellValue('G'.$l, $item['revenueIssue']);
10965                $worksheet->setCellValue('H'.$l, '-');
10966
10967                $worksheet->setCellValue('I'.$l, $item['totalAcceptance']);
10968                $worksheet->setCellValue('J'.$l, $item['revenueAcceptance']);
10969                $worksheet->setCellValue('K'.$l, '-');
10970
10971                $worksheet->setCellValue('L'.$l, $item['totalRejected']);
10972                $worksheet->setCellValue('M'.$l, $item['revenueRejected']);
10973
10974                $worksheet->setCellValue('N'.$l, $item['totalNew']);
10975                $worksheet->setCellValue('O'.$l, $item['revenueNew']);
10976                $worksheet->setCellValue('P'.$l, '-');
10977
10978                $worksheet->setCellValue('Q'.$l, $item['totalLlamada1']);
10979                $worksheet->setCellValue('R'.$l, $item['totalVisita1']);
10980
10981                $worksheet->setCellValue('S'.$l, $item['totalLlamada2']);
10982                $worksheet->setCellValue('T'.$l, $item['totalVisita2']);
10983
10984                $l++;
10985
10986                if ($data['group_by'] == 1) {
10987
10988                    if (count($item['commercials']) > 0) {
10989
10990                        foreach ($item['commercials'] as $c) {
10991                            $worksheet->setCellValue('A'.$l, $item['year']);
10992
10993                            $worksheet->setCellValue('B'.$l, $c['commercial']);
10994                            $worksheet->setCellValue('F'.$l, $c['totalIssue']);
10995                            $worksheet->setCellValue('G'.$l, $c['revenueIssue']);
10996                            $worksheet->setCellValue('H'.$l, $c['totalIssueObjectiveYearly']);
10997
10998                            $worksheet->setCellValue('I'.$l, $c['totalAcceptance']);
10999                            $worksheet->setCellValue('J'.$l, $c['revenueAcceptance']);
11000                            $worksheet->setCellValue('K'.$l, $c['totalAcceptanceObjectiveYearly']);
11001
11002                            $worksheet->setCellValue('L'.$l, $c['totalRejected']);
11003                            $worksheet->setCellValue('M'.$l, $c['revenueRejected']);
11004
11005                            $worksheet->setCellValue('N'.$l, $c['totalNew']);
11006                            $worksheet->setCellValue('O'.$l, $c['revenueNew']);
11007                            $worksheet->setCellValue('P'.$l, $c['totalNewObjectiveYearly']);
11008
11009                            $worksheet->setCellValue('Q'.$l, $c['totalLlamada1']);
11010                            $worksheet->setCellValue('R'.$l, $c['totalVisita1']);
11011
11012                            $worksheet->setCellValue('S'.$l, $c['totalLlamada2']);
11013                            $worksheet->setCellValue('T'.$l, $c['totalVisita2']);
11014                            $l++;
11015
11016                            if (isset($c['budget_types']) && count($c['budget_types']) > 0) {
11017                                foreach ($c['budget_types'] as $b) {
11018                                    $worksheet->setCellValue('A'.$l, $item['year']);
11019                                    $worksheet->setCellValue('B'.$l, $c['commercial']);
11020
11021                                    $worksheet->setCellValue('E'.$l, $b['name']);
11022                                    $worksheet->setCellValue('F'.$l, $b['totalIssue']);
11023                                    $worksheet->setCellValue('G'.$l, $b['revenueIssue']);
11024                                    $worksheet->setCellValue('H'.$l, $b['totalIssueObjective']);
11025
11026                                    $worksheet->setCellValue('I'.$l, $b['totalAcceptance']);
11027                                    $worksheet->setCellValue('J'.$l, $b['revenueAcceptance']);
11028                                    $worksheet->setCellValue('K'.$l, $b['totalAcceptanceObjective']);
11029
11030                                    $worksheet->setCellValue('L'.$l, $b['totalRejected']);
11031                                    $worksheet->setCellValue('M'.$l, $b['revenueRejected']);
11032
11033                                    $worksheet->setCellValue('N'.$l, $b['totalNew']);
11034                                    $worksheet->setCellValue('O'.$l, $b['revenueNew']);
11035                                    $worksheet->setCellValue('P'.$l, $b['totalNewObjective']);
11036
11037                                    $worksheet->setCellValue('Q'.$l, $b['totalLlamada1']);
11038                                    $worksheet->setCellValue('R'.$l, $b['totalVisita1']);
11039
11040                                    $worksheet->setCellValue('S'.$l, $b['totalLlamada2']);
11041                                    $worksheet->setCellValue('T'.$l, $b['totalVisita2']);
11042                                    $l++;
11043                                }
11044                            }
11045
11046                            if (isset($c['months']) && count($c['months']) > 0) {
11047                                foreach ($c['months'] as $m) {
11048                                    $worksheet->setCellValue('A'.$l, $item['year']);
11049                                    $worksheet->setCellValue('B'.$l, $c['commercial']);
11050
11051                                    $worksheet->setCellValue('C'.$l, $m['month']);
11052                                    $worksheet->setCellValue('F'.$l, $m['totalIssue']);
11053                                    $worksheet->setCellValue('G'.$l, $m['revenueIssue']);
11054                                    $worksheet->setCellValue('H'.$l, $m['totalIssueObjectiveMonthly']);
11055
11056                                    $worksheet->setCellValue('I'.$l, $m['totalAcceptance']);
11057                                    $worksheet->setCellValue('J'.$l, $m['revenueAcceptance']);
11058                                    $worksheet->setCellValue('K'.$l, $m['totalAcceptanceObjectiveMonthly']);
11059
11060                                    $worksheet->setCellValue('L'.$l, $m['totalRejected']);
11061                                    $worksheet->setCellValue('M'.$l, $m['revenueRejected']);
11062
11063                                    $worksheet->setCellValue('N'.$l, $m['totalNew']);
11064                                    $worksheet->setCellValue('O'.$l, $m['revenueNew']);
11065                                    $worksheet->setCellValue('P'.$l, $m['totalNewObjectiveMonthly']);
11066
11067                                    $worksheet->setCellValue('Q'.$l, $m['totalLlamada1']);
11068                                    $worksheet->setCellValue('R'.$l, $m['totalVisita1']);
11069
11070                                    $worksheet->setCellValue('S'.$l, $m['totalLlamada2']);
11071                                    $worksheet->setCellValue('T'.$l, $m['totalVisita2']);
11072                                    $l++;
11073
11074                                    if (isset($m['weeks']) && count(@$m['weeks']) > 0 && count(@$m['weeks']) != 1) {
11075                                        foreach ($m['weeks'] as $w) {
11076                                            $worksheet->setCellValue('A'.$l, $item['year']);
11077                                            $worksheet->setCellValue('B'.$l, $c['commercial']);
11078                                            $worksheet->setCellValue('C'.$l, $m['month']);
11079
11080                                            $worksheet->setCellValue('D'.$l, $w['created_at']);
11081                                            $worksheet->setCellValue('F'.$l, $w['totalIssue']);
11082                                            $worksheet->setCellValue('G'.$l, $w['revenueIssue']);
11083                                            $worksheet->setCellValue('H'.$l, $w['totalIssueObjective']);
11084
11085                                            $worksheet->setCellValue('I'.$l, $w['totalAcceptance']);
11086                                            $worksheet->setCellValue('J'.$l, $w['revenueAcceptance']);
11087                                            $worksheet->setCellValue('K'.$l, $w['totalAcceptanceObjective']);
11088
11089                                            $worksheet->setCellValue('L'.$l, $w['totalRejected']);
11090                                            $worksheet->setCellValue('M'.$l, $w['revenueRejected']);
11091
11092                                            $worksheet->setCellValue('N'.$l, $w['totalNew']);
11093                                            $worksheet->setCellValue('O'.$l, $w['revenueNew']);
11094                                            $worksheet->setCellValue('P'.$l, $w['totalNewObjective']);
11095
11096                                            $worksheet->setCellValue('Q'.$l, $w['totalLlamada1']);
11097                                            $worksheet->setCellValue('R'.$l, $w['totalVisita1']);
11098
11099                                            $worksheet->setCellValue('S'.$l, $w['totalLlamada2']);
11100                                            $worksheet->setCellValue('T'.$l, $w['totalVisita2']);
11101                                            $l++;
11102
11103                                            if (count($w['budget_types']) > 0) {
11104                                                foreach ($w['budget_types'] as $b) {
11105                                                    $worksheet->setCellValue('A'.$l, $item['year']);
11106                                                    $worksheet->setCellValue('B'.$l, $c['commercial']);
11107                                                    $worksheet->setCellValue('C'.$l, $m['month']);
11108
11109                                                    $worksheet->setCellValue('E'.$l, $b['name']);
11110                                                    $worksheet->setCellValue('F'.$l, $b['totalIssue']);
11111                                                    $worksheet->setCellValue('G'.$l, $b['revenueIssue']);
11112                                                    $worksheet->setCellValue('H'.$l, $b['totalIssueObjective']);
11113
11114                                                    $worksheet->setCellValue('I'.$l, $b['totalAcceptance']);
11115                                                    $worksheet->setCellValue('J'.$l, $b['revenueAcceptance']);
11116                                                    $worksheet->setCellValue('K'.$l, $b['totalAcceptanceObjective']);
11117
11118                                                    $worksheet->setCellValue('L'.$l, $b['totalRejected']);
11119                                                    $worksheet->setCellValue('M'.$l, $b['revenueRejected']);
11120
11121                                                    $worksheet->setCellValue('N'.$l, $b['totalNew']);
11122                                                    $worksheet->setCellValue('O'.$l, $b['revenueNew']);
11123                                                    $worksheet->setCellValue('P'.$l, $b['totalNewObjective']);
11124
11125                                                    $worksheet->setCellValue('Q'.$l, $b['totalLlamada1']);
11126                                                    $worksheet->setCellValue('R'.$l, $b['totalVisita1']);
11127
11128                                                    $worksheet->setCellValue('S'.$l, $b['totalLlamada2']);
11129                                                    $worksheet->setCellValue('T'.$l, $b['totalVisita2']);
11130                                                    $l++;
11131                                                }
11132                                            }
11133                                        }
11134                                    } elseif (isset($m['weeks']) && count(@$m['weeks']) == 1) {
11135                                        foreach ($m['weeks'] as $w) {
11136                                            if (count($w['budget_types']) > 0) {
11137                                                foreach ($w['budget_types'] as $b) {
11138                                                    $worksheet->setCellValue('A'.$l, $item['year']);
11139                                                    $worksheet->setCellValue('B'.$l, $c['commercial']);
11140                                                    $worksheet->setCellValue('C'.$l, $m['month']);
11141
11142                                                    $worksheet->setCellValue('E'.$l, $b['name']);
11143                                                    $worksheet->setCellValue('F'.$l, $b['totalIssue']);
11144                                                    $worksheet->setCellValue('G'.$l, $b['revenueIssue']);
11145                                                    $worksheet->setCellValue('H'.$l, $b['totalIssueObjective']);
11146
11147                                                    $worksheet->setCellValue('I'.$l, $b['totalAcceptance']);
11148                                                    $worksheet->setCellValue('J'.$l, $b['revenueAcceptance']);
11149                                                    $worksheet->setCellValue('K'.$l, $b['totalAcceptanceObjective']);
11150
11151                                                    $worksheet->setCellValue('L'.$l, $b['totalRejected']);
11152                                                    $worksheet->setCellValue('M'.$l, $b['revenueRejected']);
11153
11154                                                    $worksheet->setCellValue('N'.$l, $b['totalNew']);
11155                                                    $worksheet->setCellValue('O'.$l, $b['revenueNew']);
11156                                                    $worksheet->setCellValue('P'.$l, $b['totalNewObjective']);
11157
11158                                                    $worksheet->setCellValue('Q'.$l, $b['totalLlamada1']);
11159                                                    $worksheet->setCellValue('R'.$l, $b['totalVisita1']);
11160
11161                                                    $worksheet->setCellValue('S'.$l, $b['totalLlamada2']);
11162                                                    $worksheet->setCellValue('T'.$l, $b['totalVisita2']);
11163                                                    $l++;
11164                                                }
11165                                            }
11166                                        }
11167
11168                                    }
11169                                }
11170                            }
11171                        }
11172                    }
11173                } else {
11174
11175                    if (isset($item['months']) && count($item['months']) > 0) {
11176                        foreach ($item['months'] as $m) {
11177                            $worksheet->setCellValue('A'.$l, $item['year']);
11178                            $worksheet->setCellValue('B'.$l, $m['month']);
11179                            $worksheet->setCellValue('F'.$l, $m['totalIssue']);
11180                            $worksheet->setCellValue('G'.$l, $m['revenueIssue']);
11181                            $worksheet->setCellValue('H'.$l, '-');
11182
11183                            $worksheet->setCellValue('I'.$l, $m['totalAcceptance']);
11184                            $worksheet->setCellValue('J'.$l, $m['revenueAcceptance']);
11185                            $worksheet->setCellValue('K'.$l, '-');
11186
11187                            $worksheet->setCellValue('L'.$l, $m['totalRejected']);
11188                            $worksheet->setCellValue('M'.$l, $m['revenueRejected']);
11189
11190                            $worksheet->setCellValue('N'.$l, $m['totalNew']);
11191                            $worksheet->setCellValue('O'.$l, $m['revenueNew']);
11192                            $worksheet->setCellValue('P'.$l, '-');
11193
11194                            $worksheet->setCellValue('Q'.$l, $m['totalLlamada1']);
11195                            $worksheet->setCellValue('R'.$l, $m['totalVisita1']);
11196
11197                            $worksheet->setCellValue('S'.$l, $m['totalLlamada2']);
11198                            $worksheet->setCellValue('T'.$l, $m['totalVisita2']);
11199                            $l++;
11200
11201                            if (isset($m['weeks']) && count(@$m['weeks']) > 0) {
11202                                foreach ($m['weeks'] as $w) {
11203                                    $worksheet->setCellValue('A'.$l, $item['year']);
11204                                    $worksheet->setCellValue('B'.$l, $m['month']);
11205
11206                                    $worksheet->setCellValue('C'.$l, $w['created_at']);
11207                                    $worksheet->setCellValue('F'.$l, $w['totalIssue']);
11208                                    $worksheet->setCellValue('G'.$l, $w['revenueIssue']);
11209                                    $worksheet->setCellValue('H'.$l, '-');
11210
11211                                    $worksheet->setCellValue('I'.$l, $w['totalAcceptance']);
11212                                    $worksheet->setCellValue('J'.$l, $w['revenueAcceptance']);
11213                                    $worksheet->setCellValue('K'.$l, '-');
11214
11215                                    $worksheet->setCellValue('L'.$l, $w['totalRejected']);
11216                                    $worksheet->setCellValue('M'.$l, $w['revenueRejected']);
11217
11218                                    $worksheet->setCellValue('N'.$l, $w['totalNew']);
11219                                    $worksheet->setCellValue('O'.$l, $w['revenueNew']);
11220                                    $worksheet->setCellValue('P'.$l, '-');
11221
11222                                    $worksheet->setCellValue('Q'.$l, $w['totalLlamada1']);
11223                                    $worksheet->setCellValue('R'.$l, $w['totalVisita1']);
11224
11225                                    $worksheet->setCellValue('S'.$l, $w['totalLlamada2']);
11226                                    $worksheet->setCellValue('T'.$l, $w['totalVisita2']);
11227                                    $l++;
11228
11229                                    if (count($w['commercials']) > 0) {
11230                                        foreach ($w['commercials'] as $c) {
11231                                            $worksheet->setCellValue('A'.$l, $item['year']);
11232                                            $worksheet->setCellValue('B'.$l, $m['month']);
11233
11234                                            $worksheet->setCellValue('D'.$l, $c['commercial']);
11235                                            $worksheet->setCellValue('F'.$l, $c['totalIssue']);
11236                                            $worksheet->setCellValue('G'.$l, $c['revenueIssue']);
11237                                            $worksheet->setCellValue('H'.$l, $c['totalIssueObjective']);
11238
11239                                            $worksheet->setCellValue('I'.$l, $c['totalAcceptance']);
11240                                            $worksheet->setCellValue('J'.$l, $c['revenueAcceptance']);
11241                                            $worksheet->setCellValue('K'.$l, $c['totalAcceptanceObjective']);
11242
11243                                            $worksheet->setCellValue('L'.$l, $c['totalRejected']);
11244                                            $worksheet->setCellValue('M'.$l, $c['revenueRejected']);
11245
11246                                            $worksheet->setCellValue('N'.$l, $c['totalNew']);
11247                                            $worksheet->setCellValue('O'.$l, $c['revenueNew']);
11248                                            $worksheet->setCellValue('P'.$l, $c['totalNewObjective']);
11249
11250                                            $worksheet->setCellValue('Q'.$l, $c['totalLlamada1']);
11251                                            $worksheet->setCellValue('R'.$l, $c['totalVisita1']);
11252
11253                                            $worksheet->setCellValue('S'.$l, $c['totalLlamada2']);
11254                                            $worksheet->setCellValue('T'.$l, $c['totalVisita2']);
11255                                            $l++;
11256
11257                                            if (count($c['budget_types']) > 0) {
11258                                                foreach ($c['budget_types'] as $b) {
11259                                                    $worksheet->setCellValue('A'.$l, $item['year']);
11260                                                    $worksheet->setCellValue('B'.$l, $m['month']);
11261                                                    $worksheet->setCellValue('D'.$l, $c['commercial']);
11262
11263                                                    $worksheet->setCellValue('E'.$l, $b['name']);
11264                                                    $worksheet->setCellValue('F'.$l, $b['totalIssue']);
11265                                                    $worksheet->setCellValue('G'.$l, $b['revenueIssue']);
11266                                                    $worksheet->setCellValue('H'.$l, $b['totalIssueObjective']);
11267
11268                                                    $worksheet->setCellValue('I'.$l, $b['totalAcceptance']);
11269                                                    $worksheet->setCellValue('J'.$l, $b['revenueAcceptance']);
11270                                                    $worksheet->setCellValue('K'.$l, $b['totalAcceptanceObjective']);
11271
11272                                                    $worksheet->setCellValue('L'.$l, $b['totalRejected']);
11273                                                    $worksheet->setCellValue('M'.$l, $b['revenueRejected']);
11274
11275                                                    $worksheet->setCellValue('N'.$l, $b['totalNew']);
11276                                                    $worksheet->setCellValue('O'.$l, $b['revenueNew']);
11277                                                    $worksheet->setCellValue('P'.$l, $b['totalNewObjective']);
11278
11279                                                    $worksheet->setCellValue('Q'.$l, $b['totalLlamada1']);
11280                                                    $worksheet->setCellValue('R'.$l, $b['totalVisita1']);
11281
11282                                                    $worksheet->setCellValue('S'.$l, $b['totalLlamada2']);
11283                                                    $worksheet->setCellValue('T'.$l, $b['totalVisita2']);
11284                                                    $l++;
11285                                                }
11286                                            }
11287                                        }
11288                                    }
11289                                }
11290                            }
11291
11292                            if (count($m['commercials']) > 0) {
11293                                foreach ($m['commercials'] as $c) {
11294                                    $worksheet->setCellValue('A'.$l, $item['year']);
11295                                    $worksheet->setCellValue('B'.$l, $m['month']);
11296
11297                                    $worksheet->setCellValue('D'.$l, $c['commercial']);
11298                                    $worksheet->setCellValue('F'.$l, $c['totalIssue']);
11299                                    $worksheet->setCellValue('G'.$l, $c['revenueIssue']);
11300                                    $worksheet->setCellValue('H'.$l, $c['totalIssueObjectiveYearly']);
11301
11302                                    $worksheet->setCellValue('I'.$l, $c['totalAcceptance']);
11303                                    $worksheet->setCellValue('J'.$l, $c['revenueAcceptance']);
11304                                    $worksheet->setCellValue('K'.$l, $c['totalAcceptanceObjectiveYearly']);
11305
11306                                    $worksheet->setCellValue('L'.$l, $c['totalRejected']);
11307                                    $worksheet->setCellValue('M'.$l, $c['revenueRejected']);
11308
11309                                    $worksheet->setCellValue('N'.$l, $c['totalNew']);
11310                                    $worksheet->setCellValue('O'.$l, $c['revenueNew']);
11311                                    $worksheet->setCellValue('P'.$l, $c['totalNewObjectiveYearly']);
11312
11313                                    $worksheet->setCellValue('Q'.$l, $c['totalLlamada1']);
11314                                    $worksheet->setCellValue('R'.$l, $c['totalVisita1']);
11315
11316                                    $worksheet->setCellValue('S'.$l, $c['totalLlamada2']);
11317                                    $worksheet->setCellValue('T'.$l, $c['totalVisita2']);
11318                                    $l++;
11319
11320                                    if (count($c['budget_types']) > 0) {
11321                                        foreach ($c['budget_types'] as $b) {
11322                                            $worksheet->setCellValue('A'.$l, $item['year']);
11323                                            $worksheet->setCellValue('B'.$l, $m['month']);
11324                                            $worksheet->setCellValue('D'.$l, $c['commercial']);
11325
11326                                            $worksheet->setCellValue('E'.$l, $b['name']);
11327                                            $worksheet->setCellValue('F'.$l, $b['totalIssue']);
11328                                            $worksheet->setCellValue('G'.$l, $b['revenueIssue']);
11329                                            $worksheet->setCellValue('H'.$l, $b['totalIssueObjective']);
11330
11331                                            $worksheet->setCellValue('I'.$l, $b['totalAcceptance']);
11332                                            $worksheet->setCellValue('J'.$l, $b['revenueAcceptance']);
11333                                            $worksheet->setCellValue('K'.$l, $b['totalAcceptanceObjective']);
11334
11335                                            $worksheet->setCellValue('L'.$l, $b['totalRejected']);
11336                                            $worksheet->setCellValue('M'.$l, $b['revenueRejected']);
11337
11338                                            $worksheet->setCellValue('N'.$l, $b['totalNew']);
11339                                            $worksheet->setCellValue('O'.$l, $b['revenueNew']);
11340                                            $worksheet->setCellValue('P'.$l, $b['totalNewObjective']);
11341
11342                                            $worksheet->setCellValue('Q'.$l, $b['totalLlamada1']);
11343                                            $worksheet->setCellValue('R'.$l, $b['totalVisita1']);
11344
11345                                            $worksheet->setCellValue('S'.$l, $b['totalLlamada2']);
11346                                            $worksheet->setCellValue('T'.$l, $b['totalVisita2']);
11347                                            $l++;
11348                                        }
11349                                    }
11350                                }
11351                            }
11352                        }
11353                    }
11354
11355                    if (count($item['commercials']) > 0) {
11356                        foreach ($item['commercials'] as $c) {
11357                            $worksheet->setCellValue('A'.$l, $item['year']);
11358
11359                            $worksheet->setCellValue('D'.$l, $c['commercial']);
11360                            $worksheet->setCellValue('F'.$l, $c['totalIssue']);
11361                            $worksheet->setCellValue('G'.$l, $c['revenueIssue']);
11362                            $worksheet->setCellValue('H'.$l, $c['totalIssueObjectiveYearly']);
11363
11364                            $worksheet->setCellValue('I'.$l, $c['totalAcceptance']);
11365                            $worksheet->setCellValue('J'.$l, $c['revenueAcceptance']);
11366                            $worksheet->setCellValue('K'.$l, $c['totalAcceptanceObjectiveYearly']);
11367
11368                            $worksheet->setCellValue('L'.$l, $c['totalRejected']);
11369                            $worksheet->setCellValue('M'.$l, $c['revenueRejected']);
11370
11371                            $worksheet->setCellValue('N'.$l, $c['totalNew']);
11372                            $worksheet->setCellValue('O'.$l, $c['revenueNew']);
11373                            $worksheet->setCellValue('P'.$l, $c['totalNewObjectiveYearly']);
11374
11375                            $worksheet->setCellValue('Q'.$l, $c['totalLlamada1']);
11376                            $worksheet->setCellValue('R'.$l, $c['totalVisita1']);
11377
11378                            $worksheet->setCellValue('S'.$l, $c['totalLlamada2']);
11379                            $worksheet->setCellValue('T'.$l, $c['totalVisita2']);
11380                            $l++;
11381
11382                            if (count($c['budget_types']) > 0) {
11383                                foreach ($c['budget_types'] as $b) {
11384                                    $worksheet->setCellValue('A'.$l, $item['year']);
11385                                    $worksheet->setCellValue('D'.$l, $c['commercial']);
11386
11387                                    $worksheet->setCellValue('E'.$l, $b['name']);
11388                                    $worksheet->setCellValue('F'.$l, $b['totalIssue']);
11389                                    $worksheet->setCellValue('G'.$l, $b['revenueIssue']);
11390                                    $worksheet->setCellValue('H'.$l, $b['totalIssueObjective']);
11391
11392                                    $worksheet->setCellValue('I'.$l, $b['totalAcceptance']);
11393                                    $worksheet->setCellValue('J'.$l, $b['revenueAcceptance']);
11394                                    $worksheet->setCellValue('K'.$l, $b['totalAcceptanceObjective']);
11395
11396                                    $worksheet->setCellValue('L'.$l, $b['totalRejected']);
11397                                    $worksheet->setCellValue('M'.$l, $b['revenueRejected']);
11398
11399                                    $worksheet->setCellValue('N'.$l, $b['totalNew']);
11400                                    $worksheet->setCellValue('O'.$l, $b['revenueNew']);
11401                                    $worksheet->setCellValue('P'.$l, $b['totalNewObjective']);
11402
11403                                    $worksheet->setCellValue('Q'.$l, $b['totalLlamada1']);
11404                                    $worksheet->setCellValue('R'.$l, $b['totalVisita1']);
11405
11406                                    $worksheet->setCellValue('S'.$l, $b['totalLlamada2']);
11407                                    $worksheet->setCellValue('T'.$l, $b['totalVisita2']);
11408                                    $l++;
11409                                }
11410                            }
11411                        }
11412                    }
11413                }
11414
11415                $l++;
11416            }
11417
11418            if ($data['group_by'] == 1) {
11419                if ($data['aggregated_by'] == 3) {
11420                    $worksheet->removeColumn('C');
11421                    $worksheet->removeColumn('C');
11422                } elseif ($data['aggregated_by'] == 2) {
11423                    $worksheet->removeColumn('D');
11424                }
11425            } else {
11426                if ($data['aggregated_by'] == 3) {
11427                    $worksheet->removeColumn('B');
11428                    $worksheet->removeColumn('B');
11429                } elseif ($data['aggregated_by'] == 2) {
11430                    $worksheet->removeColumn('C');
11431                }
11432            }
11433
11434            $writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
11435            ob_start();
11436            $writer->save('php://output');
11437            $file = ob_get_contents();
11438            ob_end_clean();
11439
11440            return response($file);
11441
11442        } catch (\Exception $e) {
11443            /** @disregard P1014 */
11444            $e->exceptionCode = 'DOWNLOAD_PRODUCTIVITY_COMMERCIAL_EXCEPTION';
11445            report($e);
11446
11447            return response(['message' => 'KO', 'error' => $e->getMessage()]);
11448        }
11449
11450    }
11451
11452    public function update_commercial_numbers($companyId)
11453    {
11454        $phpBinary = '/usr/bin/php';
11455
11456        $artisanPath = escapeshellarg(base_path('artisan'));
11457
11458        $command = sprintf(
11459            '%s %s update:commercial-numbers %s > /dev/null 2>&1 &',
11460            $phpBinary,
11461            $artisanPath,
11462            $companyId
11463        );
11464
11465        exec($command, $output, $returnVar);
11466    }
11467
11468    public function list_quotation_analytics_by_service_type(Request $request)
11469    {
11470
11471        try {
11472
11473            $data = $request->all();
11474            $companyId = addslashes($data['company_id']);
11475            $where = '';
11476
11477            if ($companyId != 0) {
11478                $where .= " AND c.company_id = {$companyId} ";
11479            } else {
11480                $where .= " AND c.company_id IN ({$this->companyId}";
11481            }
11482
11483            $col = '1';
11484
11485            if (isset($data['data_to_display']) && $data['data_to_display'] != null) {
11486                if ($data['data_to_display'] == 1) {
11487                    $col = '1';
11488                }
11489
11490                if ($data['data_to_display'] == 2) {
11491                    $col = 'q.amount';
11492                }
11493            }
11494
11495            if (isset($data['approvals'])) {
11496                $approvals = addslashes($data['approvals']);
11497
11498                if ($approvals == 2) {
11499                    $where .= ' AND q.for_approval != 1 ';
11500                }
11501
11502                if ($approvals == 3) {
11503                    $where .= ' AND q.for_approval > 0 ';
11504                }
11505
11506                if ($approvals == 4) {
11507                    $where .= ' AND q.approved_by IS NOT NULL';
11508                }
11509
11510                if ($approvals == 5) {
11511                    $where .= ' AND q.for_approval = 2 AND q.approved_by IS NULL';
11512                }
11513
11514                if ($approvals == 6) {
11515                    $where .= ' AND q.approved_by IS NOT NULL AND q.approved_by_v2 IS NOT NULL';
11516                }
11517
11518                if ($approvals == 7) {
11519                    $where .= ' AND q.for_approval = 3 AND q.approved_by IS NOT NULL AND q.approved_by_v2 IS NULL';
11520                }
11521
11522                if ($approvals == 8) {
11523                    $where .= ' AND q.for_approval = 3 AND q.approved_by IS NULL AND q.approved_by_v2 IS NOT NULL';
11524                }
11525
11526                if ($approvals == 9) {
11527                    $where .= ' AND q.for_approval = 3 AND q.approved_by IS NULL AND q.approved_by_v2 IS NULL';
11528                }
11529            }
11530
11531            if (isset($data['role_id']) && $data['role_id'] != null) {
11532                $roleIds = implode(',', $data['role_id']);
11533                if (count($data['role_id']) > 0) {
11534                    $where .= " AND u.role_id IN ({$roleIds}, 999999999)";
11535                }
11536            }
11537
11538            if (isset($data['client_type']) && $data['client_type'] != null) {
11539                $where .= " AND q.customer_type_id = {$data['client_type']}";
11540            }
11541
11542            $weekDay = '- WEEKDAY(q.date)';
11543
11544            if (isset($data['start_of_the_week']) && $data['start_of_the_week'] != null) {
11545                switch ($data['start_of_the_week']) {
11546                    case 0:
11547                        $weekDay = '- WEEKDAY(q.date)';
11548                        break;
11549                    case 1:
11550                        $weekDay = '(1 - WEEKDAY(q.date))';
11551                        break;
11552                    case 2:
11553                        $weekDay = '(2 - WEEKDAY(q.date))';
11554                        break;
11555                    case 3:
11556                        $weekDay = '(3 - WEEKDAY(q.date))';
11557                        break;
11558                    case 4:
11559                        $weekDay = '(4 - WEEKDAY(q.date))';
11560                        break;
11561                    default:
11562                        $weekDay = '- WEEKDAY(q.date)';
11563                        break;
11564                }
11565            }
11566
11567            $whereDates = '';
11568
11569            if ((isset($data['start_date']) && $data['start_date'] != null) && (isset($data['end_date']) && $data['end_date'] != null)) {
11570                $whereDates = " AND q.date BETWEEN '{$data['start_date']}' AND '{$data['end_date']}";
11571            }
11572
11573            $query = "SELECT
11574                        q.region,
11575                        YEAR(DATE_ADD(q.date, INTERVAL {$weekDay} DAY)) 'year',
11576                        LPAD(MONTH(DATE_ADD(q.date, INTERVAL {$weekDay} DAY)), 2, 0) 'month',
11577                        LPAD(WEEK(DATE_ADD(q.date, INTERVAL {$weekDay} DAY)), 2, 0) 'week',
11578                        DATE_FORMAT(DATE_ADD(q.date, INTERVAL {$weekDay} DAY), '%W, %M %e') namedate,
11579
11580                        GROUP_CONCAT(CASE WHEN q.date_type = 'issue' THEN q.id END) AS groupConcatIdsTotalEnviado,
11581                        COALESCE(SUM(CASE WHEN q.date_type = 'issue' THEN {$col} END), 0) AS totalIssueEnviado,
11582
11583                        GROUP_CONCAT(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 3 THEN q.id END) AS groupConcatIdsMantenimientoEnviado,
11584                        COALESCE(SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 3 THEN {$col} END), 0) totalMantenimientoEnviado,
11585                        COALESCE(SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 3 THEN {$col} END) / SUM(CASE WHEN q.date_type = 'issue' THEN {$col} END) * 100, 0) totalMantenimientoPercentageEnviado,
11586
11587                        GROUP_CONCAT(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 5 THEN q.id END) AS groupConcatIdsCorrectivosEnviado,
11588                        COALESCE(SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 5 THEN {$col} END), 0) totalCorrectivosEnviado,
11589                        COALESCE(SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 5 THEN {$col} END) / SUM(CASE WHEN q.date_type = 'issue' THEN {$col} END) * 100, 0) totalCorrectivosPercentageEnviado,
11590
11591                        GROUP_CONCAT(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 4 THEN q.id END) AS groupConcatIdsObrasEnviado,
11592                        COALESCE(SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 4 THEN {$col} END), 0) totalObrasEnviado,
11593                        COALESCE(SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 4 THEN {$col} END) / SUM(CASE WHEN q.date_type = 'issue' THEN {$col} END) * 100, 0) totalObrasPercentageEnviado,
11594
11595                        GROUP_CONCAT(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id IN (6, 7, 8) THEN q.id END) AS groupConcatIdsOtrosEnviado,
11596                        COALESCE(SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id IN (6, 7, 8) THEN {$col} END), 0) totalOtrosEnviado,
11597                        COALESCE(SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id IN (6, 7, 8) THEN {$col} END) / SUM(CASE WHEN q.date_type = 'issue' THEN {$col} END) * 100, 0) totalOtrosPercentageEnviado,
11598
11599                        GROUP_CONCAT(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id IN (6, 7, 8) THEN q.id END) AS groupConcatIdsOtrosEnviado,
11600                        COALESCE(SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id IN (6, 7, 8) THEN {$col} END), 0) totalOtrosEnviado,
11601                        COALESCE(SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id IN (6, 7, 8) THEN {$col} END) / SUM(CASE WHEN q.date_type = 'issue' THEN {$col} END) * 100, 0) totalOtrosPercentageEnviado,
11602
11603                        CASE
11604                            WHEN SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 4 AND q.budget_margin_enabled > 0 AND q.margin_for_the_company <> 0 THEN q.amount ELSE 0 END) = 0 THEN 0
11605                            ELSE SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 4 AND q.budget_margin_enabled > 0 AND q.margin_for_the_company <> 0 THEN q.s1 ELSE 0 END)
11606                                / SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 4 AND q.budget_margin_enabled > 0 AND q.margin_for_the_company <> 0 THEN q.amount ELSE 0 END)
11607                        END AS weightedAverageMarginForTheCompanyEnviado,
11608                        CASE
11609                            WHEN SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 4 AND q.budget_margin_enabled > 0 AND q.invoice_margin <> 0 THEN q.amount ELSE 0 END) = 0 THEN 0
11610                            ELSE SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 4 AND q.budget_margin_enabled > 0 AND q.invoice_margin <> 0 THEN q.s2 ELSE 0 END)
11611                                / SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 4 AND q.budget_margin_enabled > 0 AND q.invoice_margin <> 0 THEN q.amount ELSE 0 END)
11612                        END AS weightedAverageInvoiceEnviado,
11613
11614                        GROUP_CONCAT(CASE WHEN q.date_type = 'acceptance' THEN q.id END) AS groupConcatIdsTotalAceptado,
11615                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' THEN {$col} END), 0) AS totalIssueAceptado,
11616
11617                        GROUP_CONCAT(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 3 THEN q.id END) AS groupConcatIdsMantenimientoAceptado,
11618                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 3 THEN {$col} END), 0) totalMantenimientoAceptado,
11619                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 3 THEN {$col} END) / SUM(CASE WHEN q.date_type = 'acceptance' THEN {$col} END) * 100, 0) totalMantenimientoPercentageAceptado,
11620
11621                        GROUP_CONCAT(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 5 THEN q.id END) AS groupConcatIdsCorrectivosAceptado,
11622                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 5 THEN {$col} END), 0) totalCorrectivosAceptado,
11623                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 5 THEN {$col} END) / SUM(CASE WHEN q.date_type = 'acceptance' THEN {$col} END) * 100, 0) totalCorrectivosPercentageAceptado,
11624
11625                        GROUP_CONCAT(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 4 THEN q.id END) AS groupConcatIdsObrasAceptado,
11626                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 4 THEN {$col} END), 0) totalObrasAceptado,
11627                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 4 THEN {$col} END) / SUM(CASE WHEN q.date_type = 'acceptance' THEN {$col} END) * 100, 0) totalObrasPercentageAceptado,
11628
11629                        GROUP_CONCAT(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id IN (6, 7, 8) THEN q.id END) AS groupConcatIdsOtrosAceptado,
11630                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id IN (6, 7, 8) THEN {$col} END), 0) totalOtrosAceptado,
11631                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id IN (6, 7, 8) THEN {$col} END) / SUM(CASE WHEN q.date_type = 'acceptance' THEN {$col} END) * 100, 0) totalOtrosPercentageAceptado,
11632
11633                        CASE
11634                            WHEN SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 4 AND q.budget_margin_enabled > 0 AND q.margin_for_the_company <> 0 THEN q.amount ELSE 0 END) = 0 THEN 0
11635                            ELSE SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 4 AND q.budget_margin_enabled > 0 AND q.margin_for_the_company <> 0 THEN q.s1 ELSE 0 END)
11636                                / SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 4 AND q.budget_margin_enabled > 0 AND q.margin_for_the_company <> 0 THEN q.amount ELSE 0 END)
11637                        END AS weightedAverageMarginForTheCompanyAceptado,
11638                        CASE
11639                            WHEN SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 4 AND q.budget_margin_enabled > 0 AND q.invoice_margin <> 0 THEN q.amount ELSE 0 END) = 0 THEN 0
11640                            ELSE SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 4 AND q.budget_margin_enabled > 0 AND q.invoice_margin <> 0 THEN q.s2 ELSE 0 END)
11641                                / SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 4 AND q.budget_margin_enabled > 0 AND q.invoice_margin <> 0 THEN q.amount ELSE 0 END)
11642                        END AS weightedAverageInvoiceAceptado,
11643
11644                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' THEN 1 END) / SUM(CASE WHEN q.date_type = 'issue' THEN {$col} END) * 100, 0) totalIssuePercentage,
11645                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 3 THEN {$col} END) / SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 3 THEN {$col} END) * 100, 0) totalMantenimientoPercentage,
11646                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 5 THEN {$col} END) / SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 5 THEN {$col} END) * 100, 0) totalCorrectivosPercentage,
11647                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 4 THEN {$col} END) / SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 4 THEN {$col} END) * 100, 0) totalObrasPercentage,
11648                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id IN (6, 7, 8) THEN {$col} END) / SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id IN (6, 7, 8) THEN {$col} END) * 100 , 0) totalOtrosPercentage,
11649
11650                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.issue_date IS NOT NULL THEN {$col} END) / SUM(CASE WHEN q.date_type = 'issue' AND q.acceptance_date IS NOT NULL THEN {$col} END) * 100, 0) totalIssuePercentageLead,
11651                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.issue_date IS NOT NULL AND q.budget_type_group_id = 3 THEN {$col} END) / SUM(CASE WHEN q.date_type = 'issue' AND q.acceptance_date IS NOT NULL AND q.budget_type_group_id = 3 THEN {$col} END) * 100, 0) totalMantenimientoPercentageLead,
11652                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.issue_date IS NOT NULL AND q.budget_type_group_id = 5 THEN {$col} END) / SUM(CASE WHEN q.date_type = 'issue' AND q.acceptance_date IS NOT NULL AND q.budget_type_group_id = 5 THEN {$col} END) * 100, 0) totalCorrectivosPercentageLead,
11653                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.issue_date IS NOT NULL AND q.budget_type_group_id = 4 THEN {$col} END) / SUM(CASE WHEN q.date_type = 'issue' AND q.acceptance_date IS NOT NULL AND q.budget_type_group_id = 4 THEN {$col} END) * 100, 0) totalObrasPercentageLead,
11654                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.issue_date IS NOT NULL AND q.budget_type_group_id IN (6, 7, 8) THEN {$col} END) / SUM(CASE WHEN q.date_type = 'issue' AND q.acceptance_date IS NOT NULL AND q.budget_type_group_id IN (6, 7, 8) THEN {$col} END) * 100 , 0) totalOtrosPercentageLead
11655                    FROM
11656                    (
11657                        SELECT
11658                            c.region,
11659                            q.issue_date AS DATE,
11660                            'issue' AS date_type,
11661                            q.acceptance_date,
11662                            q.issue_date,
11663                            q.id,
11664                            q.margin_for_the_company,
11665                            CASE
11666                                WHEN bt.budget_type_group_id = 4
11667                                AND q.budget_margin_enabled > 0
11668                                AND q.budget_margin_enabled IS NOT NULL
11669                                AND q.margin_for_the_company <> 0
11670                            THEN q.margin_for_the_company * q.amount
11671                            END s1,
11672                            q.invoice_margin,
11673                            CASE
11674                                WHEN bt.budget_type_group_id = 4
11675                                AND q.budget_margin_enabled > 0
11676                                AND q.budget_margin_enabled IS NOT NULL
11677                                AND q.invoice_margin <> 0
11678                            THEN q.invoice_margin * q.amount
11679                            END s2,
11680                            q.budget_type_id,
11681                            q.budget_status_id,
11682                            q.amount,
11683                            bt.budget_type_group_id,
11684                            q.budget_margin_enabled
11685                        FROM
11686                            tbl_quotations q
11687                        JOIN tbl_companies c
11688                            ON c.company_id = q.company_id
11689                        LEFT JOIN tbl_budget_types bt
11690                            ON q.budget_type_id = bt.budget_type_id
11691                        LEFT JOIN tbl_users u
11692                            ON u.name = q.created_by
11693                        LEFT JOIN tbl_roles r
11694                            ON r.role_id = u.role_id
11695                        WHERE
11696                            q.issue_date IS NOT NULL
11697                            AND q.for_add = 0
11698                            AND q.amount REGEXP '^[0-9]+\\.?[0-9]*$' = 1
11699                            AND (q.commercial IS NOT NULL AND q.commercial != '')
11700                            AND q.budget_type_id != 7
11701                            AND q.budget_type_id IS NOT NULL
11702                            {$where}
11703
11704                        UNION ALL
11705
11706                        SELECT
11707                            c.region,
11708                            q.acceptance_date AS DATE,
11709                            'acceptance' AS date_type,
11710                            q.acceptance_date,
11711                            q.issue_date,
11712                            q.id,
11713                            q.margin_for_the_company,
11714                            CASE
11715                                WHEN bt.budget_type_group_id = 4
11716                                AND q.budget_margin_enabled > 0
11717                                AND q.budget_margin_enabled IS NOT NULL
11718                                AND q.margin_for_the_company > 0
11719                            THEN q.margin_for_the_company * q.amount
11720                            END s1,
11721                            q.invoice_margin,
11722                            CASE
11723                                WHEN bt.budget_type_group_id = 4
11724                                AND q.budget_margin_enabled <> 0
11725                                AND q.budget_margin_enabled IS NOT NULL
11726                                AND q.invoice_margin <> 0
11727                            THEN q.invoice_margin * q.amount
11728                            END s2,
11729                            q.budget_type_id,
11730                            q.budget_status_id,
11731                            q.amount,
11732                            bt.budget_type_group_id,
11733                            q.budget_margin_enabled
11734                        FROM
11735                            tbl_quotations q
11736                        JOIN tbl_companies c
11737                            ON c.company_id = q.company_id
11738                        LEFT JOIN tbl_budget_types bt
11739                            ON q.budget_type_id = bt.budget_type_id
11740                        LEFT JOIN tbl_users u
11741                            ON u.name = q.created_by
11742                        LEFT JOIN tbl_roles r
11743                            ON r.role_id = u.role_id
11744                        WHERE
11745                            q.acceptance_date IS NOT NULL
11746                            AND q.for_add = 0
11747                            AND q.budget_type_id IS NOT NULL
11748                            AND q.budget_type_id != 7
11749                            AND q.acceptance_date != '0000-00-00 00:00:00'
11750                            AND q.amount REGEXP '^[0-9]+\\.?[0-9]*$' = 1
11751                            {$where}
11752                    ) AS q
11753                    WHERE q.date != '0000-00-00 00:00:00' {$whereDates}
11754                    GROUP BY
11755                        q.region,
11756                        YEAR(DATE_ADD(q.date, INTERVAL {$weekDay} DAY)),
11757                        MONTH(DATE_ADD(q.date, INTERVAL {$weekDay} DAY)),
11758                        WEEK(DATE_ADD(q.date, INTERVAL {$weekDay} DAY)) WITH ROLLUP
11759                    ORDER BY
11760                        q.region IS NULL,
11761                        q.region,
11762                        CASE WHEN q.region IS NOT NULL
11763                            AND YEAR(DATE_ADD(q.date, INTERVAL {$weekDay} DAY)) IS NULL
11764                            AND MONTH(DATE_ADD(q.date, INTERVAL {$weekDay} DAY)) IS NULL
11765                            AND WEEK(DATE_ADD(q.date, INTERVAL {$weekDay} DAY)) IS NULL
11766                        THEN 0
11767                        ELSE 1 END,
11768                    YEAR DESC,
11769                    MONTH ASC,
11770                    WEEK ASC";
11771
11772            $value = Cache::get(base64_encode($query));
11773
11774            if (! $value) {
11775                $result = DB::select($query);
11776
11777                Cache::put(base64_encode($query), $result, 600);
11778            } else {
11779                $result = $value;
11780            }
11781
11782            $query = "SELECT
11783                        q.region,
11784                        YEAR(DATE_ADD(q.date, INTERVAL {$weekDay} DAY)) 'year',
11785                        LPAD(MONTH(DATE_ADD(q.date, INTERVAL {$weekDay} DAY)), 2, 0) 'month',
11786                        LPAD(WEEK(DATE_ADD(q.date, INTERVAL {$weekDay} DAY)), 2, 0) 'week',
11787                        DATE_FORMAT(DATE_ADD(q.date, INTERVAL {$weekDay} DAY), '%W, %M %e') namedate,
11788
11789                        GROUP_CONCAT(CASE WHEN q.date_type = 'issue' THEN q.id END) AS groupConcatIdsTotalEnviado,
11790                        COALESCE(SUM(CASE WHEN q.date_type = 'issue' THEN {$col} END), 0) AS totalIssueEnviado,
11791
11792                        GROUP_CONCAT(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 3 THEN q.id END) AS groupConcatIdsMantenimientoEnviado,
11793                        COALESCE(SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 3 THEN {$col} END), 0) totalMantenimientoEnviado,
11794                        COALESCE(SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 3 THEN {$col} END) / SUM(CASE WHEN q.date_type = 'issue' THEN {$col} END) * 100, 0) totalMantenimientoPercentageEnviado,
11795
11796                        GROUP_CONCAT(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 5 THEN q.id END) AS groupConcatIdsCorrectivosEnviado,
11797                        COALESCE(SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 5 THEN {$col} END), 0) totalCorrectivosEnviado,
11798                        COALESCE(SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 5 THEN {$col} END) / SUM(CASE WHEN q.date_type = 'issue' THEN {$col} END) * 100, 0) totalCorrectivosPercentageEnviado,
11799
11800                        GROUP_CONCAT(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 4 THEN q.id END) AS groupConcatIdsObrasEnviado,
11801                        COALESCE(SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 4 THEN {$col} END), 0) totalObrasEnviado,
11802                        COALESCE(SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 4 THEN {$col} END) / SUM(CASE WHEN q.date_type = 'issue' THEN {$col} END) * 100, 0) totalObrasPercentageEnviado,
11803
11804                        GROUP_CONCAT(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id IN (6, 7, 8) THEN q.id END) AS groupConcatIdsOtrosEnviado,
11805                        COALESCE(SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id IN (6, 7, 8) THEN {$col} END), 0) totalOtrosEnviado,
11806                        COALESCE(SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id IN (6, 7, 8) THEN {$col} END) / SUM(CASE WHEN q.date_type = 'issue' THEN {$col} END) * 100, 0) totalOtrosPercentageEnviado,
11807
11808                        CASE
11809                            WHEN SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 4 AND q.budget_margin_enabled > 0 AND q.margin_for_the_company <> 0 THEN q.amount ELSE 0 END) = 0 THEN 0
11810                            ELSE SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 4 AND q.budget_margin_enabled > 0 AND q.margin_for_the_company <> 0 THEN q.s1 ELSE 0 END)
11811                                / SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 4 AND q.budget_margin_enabled > 0 AND q.margin_for_the_company <> 0 THEN q.amount ELSE 0 END)
11812                        END AS weightedAverageMarginForTheCompanyEnviado,
11813                        CASE
11814                            WHEN SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 4 AND q.budget_margin_enabled > 0 AND q.invoice_margin <> 0 THEN q.amount ELSE 0 END) = 0 THEN 0
11815                            ELSE SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 4 AND q.budget_margin_enabled > 0 AND q.invoice_margin <> 0 THEN q.s2 ELSE 0 END)
11816                                / SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 4 AND q.budget_margin_enabled > 0 AND q.invoice_margin <> 0 THEN q.amount ELSE 0 END)
11817                        END AS weightedAverageInvoiceEnviado,
11818
11819                        GROUP_CONCAT(CASE WHEN q.date_type = 'acceptance' THEN q.id END) AS groupConcatIdsTotalAceptado,
11820                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' THEN {$col} END), 0) AS totalIssueAceptado,
11821
11822                        GROUP_CONCAT(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 3 THEN q.id END) AS groupConcatIdsMantenimientoAceptado,
11823                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 3 THEN {$col} END), 0) totalMantenimientoAceptado,
11824                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 3 THEN {$col} END) / SUM(CASE WHEN q.date_type = 'acceptance' THEN {$col} END) * 100, 0) totalMantenimientoPercentageAceptado,
11825
11826                        GROUP_CONCAT(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 5 THEN q.id END) AS groupConcatIdsCorrectivosAceptado,
11827                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 5 THEN {$col} END), 0) totalCorrectivosAceptado,
11828                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 5 THEN {$col} END) / SUM(CASE WHEN q.date_type = 'acceptance' THEN {$col} END) * 100, 0) totalCorrectivosPercentageAceptado,
11829
11830                        GROUP_CONCAT(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 4 THEN q.id END) AS groupConcatIdsObrasAceptado,
11831                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 4 THEN {$col} END), 0) totalObrasAceptado,
11832                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 4 THEN {$col} END) / SUM(CASE WHEN q.date_type = 'acceptance' THEN {$col} END) * 100, 0) totalObrasPercentageAceptado,
11833
11834                        GROUP_CONCAT(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id IN (6, 7, 8) THEN q.id END) AS groupConcatIdsOtrosAceptado,
11835                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id IN (6, 7, 8) THEN {$col} END), 0) totalOtrosAceptado,
11836                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id IN (6, 7, 8) THEN {$col} END) / SUM(CASE WHEN q.date_type = 'acceptance' THEN {$col} END) * 100, 0) totalOtrosPercentageAceptado,
11837
11838                        CASE
11839                            WHEN SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 4 AND q.budget_margin_enabled > 0 AND q.margin_for_the_company <> 0 THEN q.amount ELSE 0 END) = 0 THEN 0
11840                            ELSE SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 4 AND q.budget_margin_enabled > 0 AND q.margin_for_the_company <> 0 THEN q.s1 ELSE 0 END)
11841                                / SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 4 AND q.budget_margin_enabled > 0 AND q.margin_for_the_company <> 0 THEN q.amount ELSE 0 END)
11842                        END AS weightedAverageMarginForTheCompanyAceptado,
11843                        CASE
11844                            WHEN SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 4 AND q.budget_margin_enabled > 0 AND q.invoice_margin <> 0 THEN q.amount ELSE 0 END) = 0 THEN 0
11845                            ELSE SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 4 AND q.budget_margin_enabled > 0 AND q.invoice_margin <> 0 THEN q.s2 ELSE 0 END)
11846                                / SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 4 AND q.budget_margin_enabled > 0 AND q.invoice_margin <> 0 THEN q.amount ELSE 0 END)
11847                        END AS weightedAverageInvoiceAceptado,
11848
11849                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' THEN {$col} END) / SUM(CASE WHEN q.date_type = 'issue' THEN {$col} END) * 100, 0) totalIssuePercentage,
11850                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 3 THEN {$col} END) / SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 3 THEN {$col} END) * 100, 0) totalMantenimientoPercentage,
11851                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 5 THEN {$col} END) / SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 5 THEN {$col} END) * 100, 0) totalCorrectivosPercentage,
11852                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id = 4 THEN {$col} END) / SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id = 4 THEN {$col} END) * 100, 0) totalObrasPercentage,
11853                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.budget_type_group_id IN (6, 7, 8) THEN {$col} END) / SUM(CASE WHEN q.date_type = 'issue' AND q.budget_type_group_id IN (6, 7, 8) THEN {$col} END) * 100 , 0) totalOtrosPercentage,
11854
11855                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.issue_date IS NOT NULL THEN {$col} END) / SUM(CASE WHEN q.date_type = 'issue' AND q.acceptance_date IS NOT NULL THEN {$col} END) * 100, 0) totalIssuePercentageLead,
11856                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.issue_date IS NOT NULL AND q.budget_type_group_id = 3 THEN {$col} END) / SUM(CASE WHEN q.date_type = 'issue' AND q.acceptance_date IS NOT NULL AND q.budget_type_group_id = 3 THEN {$col} END) * 100, 0) totalMantenimientoPercentageLead,
11857                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.issue_date IS NOT NULL AND q.budget_type_group_id = 5 THEN {$col} END) / SUM(CASE WHEN q.date_type = 'issue' AND q.acceptance_date IS NOT NULL AND q.budget_type_group_id = 5 THEN {$col} END) * 100, 0) totalCorrectivosPercentageLead,
11858                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.issue_date IS NOT NULL AND q.budget_type_group_id = 4 THEN {$col} END) / SUM(CASE WHEN q.date_type = 'issue' AND q.acceptance_date IS NOT NULL AND q.budget_type_group_id = 4 THEN {$col} END) * 100, 0) totalObrasPercentageLead,
11859                        COALESCE(SUM(CASE WHEN q.date_type = 'acceptance' AND q.issue_date IS NOT NULL AND q.budget_type_group_id IN (6, 7, 8) THEN {$col} END) / SUM(CASE WHEN q.date_type = 'issue' AND q.acceptance_date IS NOT NULL AND q.budget_type_group_id IN (6, 7, 8) THEN {$col} END) * 100 , 0) totalOtrosPercentageLead
11860                    FROM
11861                    (
11862                        SELECT
11863                            'Total Grupo FIRE' region,
11864                            q.issue_date AS DATE,
11865                            'issue' AS date_type,
11866                            q.acceptance_date,
11867                            q.issue_date,
11868                            q.id,
11869                            q.margin_for_the_company,
11870                            CASE
11871                                WHEN bt.budget_type_group_id = 4
11872                                AND q.budget_margin_enabled > 0
11873                                AND q.budget_margin_enabled IS NOT NULL
11874                                AND q.margin_for_the_company <> 0
11875                            THEN q.margin_for_the_company * q.amount
11876                            END s1,
11877                            q.invoice_margin,
11878                            CASE
11879                                WHEN bt.budget_type_group_id = 4
11880                                AND q.budget_margin_enabled > 0
11881                                AND q.budget_margin_enabled IS NOT NULL
11882                                AND q.invoice_margin <> 0
11883                            THEN q.invoice_margin * q.amount
11884                            END s2,
11885                            q.budget_type_id,
11886                            q.budget_status_id,
11887                            q.amount,
11888                            bt.budget_type_group_id,
11889                            q.budget_margin_enabled
11890                        FROM
11891                            tbl_quotations q
11892                        JOIN tbl_companies c
11893                            ON c.company_id = q.company_id
11894                        LEFT JOIN tbl_budget_types bt
11895                            ON q.budget_type_id = bt.budget_type_id
11896                        LEFT JOIN tbl_users u
11897                            ON u.name = q.created_by
11898                        LEFT JOIN tbl_roles r
11899                            ON r.role_id = u.role_id
11900                        WHERE
11901                            q.issue_date IS NOT NULL
11902                            AND q.for_add = 0
11903                            AND q.amount REGEXP '^[0-9]+\\.?[0-9]*$' = 1
11904                            AND (q.commercial IS NOT NULL AND q.commercial != '')
11905                            AND q.budget_type_id != 7
11906                            AND q.budget_type_id IS NOT NULL
11907                            {$where}
11908
11909                        UNION ALL
11910
11911                        SELECT
11912                            'Total Grupo FIRE' region,
11913                            q.acceptance_date AS DATE,
11914                            'acceptance' AS date_type,
11915                            q.acceptance_date,
11916                            q.issue_date,
11917                            q.id,
11918                            q.margin_for_the_company,
11919                            CASE
11920                                WHEN bt.budget_type_group_id = 4
11921                                AND q.budget_margin_enabled > 0
11922                                AND q.budget_margin_enabled IS NOT NULL
11923                                AND q.margin_for_the_company <> 0
11924                            THEN q.margin_for_the_company * q.amount
11925                            END s1,
11926                            q.invoice_margin,
11927                            CASE
11928                                WHEN bt.budget_type_group_id = 4
11929                                AND q.budget_margin_enabled > 0
11930                                AND q.budget_margin_enabled IS NOT NULL
11931                                AND q.invoice_margin <> 0
11932                            THEN q.invoice_margin * q.amount
11933                            END s2,
11934                            q.budget_type_id,
11935                            q.budget_status_id,
11936                            q.amount,
11937                            bt.budget_type_group_id,
11938                            q.budget_margin_enabled
11939                        FROM
11940                            tbl_quotations q
11941                        JOIN tbl_companies c
11942                            ON c.company_id = q.company_id
11943                        LEFT JOIN tbl_budget_types bt
11944                            ON q.budget_type_id = bt.budget_type_id
11945                        LEFT JOIN tbl_users u
11946                            ON u.name = q.created_by
11947                        LEFT JOIN tbl_roles r
11948                            ON r.role_id = u.role_id
11949                        WHERE
11950                            q.acceptance_date IS NOT NULL
11951
11952                            AND q.for_add = 0
11953                            AND q.amount REGEXP '^[0-9]+\\.?[0-9]*$' = 1
11954                            AND (q.commercial IS NOT NULL AND q.commercial != '')
11955                            AND q.budget_type_id != 7
11956                            AND q.budget_type_id IS NOT NULL
11957                            {$where}
11958                    ) AS q
11959                    WHERE q.date != '0000-00-00 00:00:00' {$whereDates}
11960                    GROUP BY
11961                        q.region,
11962                        YEAR(DATE_ADD(q.date, INTERVAL {$weekDay} DAY)),
11963                        MONTH(DATE_ADD(q.date, INTERVAL {$weekDay} DAY)),
11964                        WEEK(DATE_ADD(q.date, INTERVAL {$weekDay} DAY)) WITH ROLLUP
11965                    ORDER BY
11966                        q.region IS NULL,
11967                        q.region,
11968                        CASE WHEN q.region IS NOT NULL
11969                            AND YEAR(DATE_ADD(q.date, INTERVAL {$weekDay} DAY)) IS NULL
11970                            AND MONTH(DATE_ADD(q.date, INTERVAL {$weekDay} DAY)) IS NULL
11971                            AND WEEK(DATE_ADD(q.date, INTERVAL {$weekDay} DAY)) IS NULL
11972                        THEN 0
11973                        ELSE 1 END,
11974                    YEAR DESC,
11975                    MONTH ASC,
11976                    WEEK ASC";
11977
11978            $totalGroupValue = Cache::get(base64_encode($query));
11979
11980            if (! $totalGroupValue) {
11981                $totalGroup = DB::select($query);
11982
11983                Cache::put(base64_encode($query), $totalGroup, 600);
11984            } else {
11985                $totalGroup = $totalGroupValue;
11986            }
11987
11988            array_pop($result);
11989            $merged = array_merge($result, $totalGroup);
11990
11991            return response([
11992                'message' => 'OK',
11993                'data' => $merged,
11994            ]);
11995
11996        } catch (\Exception $e) {
11997            /** @disregard P1014 */
11998            $e->exceptionCode = 'LIST_QUOTATIONS_ANALYTICS_BY_SERVICE_TYPE_EXCEPTION';
11999            report($e);
12000
12001            return response(['message' => 'KO', 'error' => $e->getMessage()]);
12002        }
12003
12004    }
12005
12006    public function getIdsFromInternalQuoteIds($ids)
12007    {
12008        $idsArray = array_filter(explode(',', $ids), 'is_numeric');
12009
12010        return TblQuotations::whereIn('internal_quote_id', $idsArray)
12011            ->pluck('id')
12012            ->toArray();
12013    }
12014
12015    public function checkQuotationExistByInternalQuoteId(Request $request)
12016    {
12017        try {
12018            $idsString = $request->all()['ids'];
12019            $ids = explode(',', $idsString);
12020            $region = urldecode(@getallheaders()['Region']);
12021            $company = TblCompanies::where('region', $region)->first();
12022
12023            if (! $company) {
12024                throw new \Exception('Region no encontrada');
12025            }
12026
12027            $companyId = $company->company_id;
12028
12029            $idsChecked = [];
12030
12031            foreach ($ids as $id) {
12032                $quote = TblQuotations::where('internal_quote_id', $id)->where('company_id', $companyId)->first();
12033                if (
12034                    ($companyId === 18 || $companyId === 22)
12035                    && ! $quote
12036                ) {
12037                    $quote = TblQuotations::where('internal_quote_id', $id)->whereIn('company_id', [18, 22])->first();
12038                }
12039                $idsChecked[$id] = $quote ? $quote->id : null;
12040            }
12041
12042            return response([
12043                'message' => 'OK',
12044                'data' => $idsChecked,
12045            ]);
12046
12047        } catch (\Exception $e) {
12048            /** @disregard P1014 */
12049            $e->exceptionCode = 'CHECK_QUOTATION_EXIST_BY_INTERNAL_QUOTE_ID_EXCEPTION';
12050            report($e);
12051
12052            return response(['message' => 'KO', 'error' => $e->getMessage()]);
12053        }
12054
12055    }
12056
12057    public function addUpdateLog($id, $userId, $field, $oldData, $newData, $category = 4)
12058    {
12059        $categoryOptions = [
12060            'Crear solicitud',
12061            'Modificacion de solicitud',
12062            'Creacion presupuesto',
12063            'Solicitud a presupuesto',
12064            'Modificacion de presupuesto',
12065            'Accion del presupuesto',
12066            'Eliminacion del presupuesto',
12067            'Convertir presupuesto a trabajo',
12068        ];
12069
12070        if ($field === 'amount') {
12071            $oldData = (float) $oldData;
12072            $newData = (float) $newData;
12073        }
12074
12075        if (
12076            ($oldData === $newData && ! is_null($oldData)) ||
12077            $field === 'updated_at' ||
12078            $field === 'created_at' ||
12079            $field === 'last_follow_up_comment' ||
12080            $field === 'reason_for_rejection_id' ||
12081            $field === 'for_add' ||
12082            $field === 'has_attachment' ||
12083            $field === 'question_ids' ||
12084            $field === 'question_ids_no' ||
12085            $field === 'x_message_id' ||
12086            $field === 'from_company_id' ||
12087            $field === 'type_by_g3w' ||
12088            $field === 'user_create_by_g3w' ||
12089            $field === 'user_commercial_by_g3w' ||
12090            $field === 'user_technical_by_g3w' ||
12091            $field === 'user_responsible_by_g3w' ||
12092            $field === 'resource_id' ||
12093            $field === 'y_message_id' ||
12094            $field === 'y_status' ||
12095            $field === 'sync_import_edited' ||
12096            $field === 'updated_by' ||
12097            $field === 'likehood' ||
12098            $field === 'g3w_warning' ||
12099            $field === 'gross_margin' ||
12100            $field === 'duration' ||
12101            ($field === 'budget_type_id' && is_null($oldData) && is_null($newData)) ||
12102            ($field === 'margin_on_invoice_per_day_per_worker' && $newData === 0)
12103        ) {
12104            return;
12105        }
12106
12107        $oldRegister = null;
12108        $newRegister = null;
12109
12110        if (! is_null($oldData) || ! is_null($newData)) {
12111            switch ($field) {
12112                case 'company_id':
12113                    $oldRegister = TblCompanies::where('company_id', $oldData)->first();
12114                    $newRegister = TblCompanies::where('company_id', $newData)->first();
12115                    break;
12116                case 'customer_type_id':
12117                    $oldRegister = TblCustomerTypes::where('customer_type_id', $oldData)->first();
12118                    $newRegister = TblCustomerTypes::where('customer_type_id', $newData)->first();
12119                    break;
12120                case 'segment_id':
12121                    $oldRegister = TblSegments::where('segment_id', $oldData)->first();
12122                    $newRegister = TblSegments::where('segment_id', $newData)->first();
12123                    break;
12124                case 'budget_type_id':
12125                    $oldRegister = TblBudgetTypes::where('budget_type_id', $oldData)->first();
12126                    $newRegister = TblBudgetTypes::where('budget_type_id', $newData)->first();
12127                    break;
12128                case 'budget_status_id':
12129                    $oldRegister = TblBudgetStatus::where('budget_status_id', $oldData)->first();
12130                    $newRegister = TblBudgetStatus::where('budget_status_id', $newData)->first();
12131                    break;
12132                case 'source_id':
12133                    $oldRegister = TblSources::where('source_id', $oldData)->first();
12134                    $newRegister = TblSources::where('source_id', $newData)->first();
12135                    break;
12136            }
12137        }
12138
12139        $finalOld = $oldRegister ? $oldRegister->name : ($oldData ?? 'N/A');
12140        $finalNew = $newRegister ? $newRegister->name : ($newData ?? 'N/A');
12141
12142        if (is_numeric($userId)) {
12143            $userObj = TblUsers::where('id', $userId)->first();
12144            $userName = $userObj ? $userObj->name : "Usuario desconocido ($userId)";
12145        } else {
12146            $userName = $userId;
12147        }
12148
12149        TblQuotationsLog::create([
12150            'category' => $categoryOptions[$category] ?? 'Otros',
12151            'quotation_id' => $id,
12152            'user' => $userName,
12153            'field' => $field,
12154            'old_value' => $finalOld,
12155            'new_value' => $finalNew,
12156        ]);
12157    }
12158
12159    public function setSolicitudDuplicity(Request $request)
12160    {
12161        try {
12162            $type = $request->all()['type'];
12163            $quoteId = $request->all()['quoteId'];
12164            $companyId = $request->all()['companyId'];
12165
12166            $quote = TblQuotations::where('quote_id', $quoteId)->where('company_id', $companyId)->first();
12167
12168            if (! $quote) {
12169                throw new \Exception('Quote no encontrada');
12170            }
12171
12172            $newIdSolicitudDuplicityValue = null;
12173
12174            if ($type === 'reject') {
12175                $quote->budget_status_id = 20;
12176                $newIdSolicitudDuplicityValue = 'R'.$quote->id_solicitud_duplicity;
12177            }
12178
12179            $this->addUpdateLog($quote->id, 'IA', 'id_solicitud_duplicity', $quote->id_solicitud_duplicity, $newIdSolicitudDuplicityValue);
12180
12181            $quote->id_solicitud_duplicity = $newIdSolicitudDuplicityValue;
12182
12183            $quote->save();
12184
12185            return response([
12186                'message' => 'OK',
12187                'data' => $quote,
12188            ]);
12189
12190        } catch (\Exception $e) {
12191            /** @disregard P1014 */
12192            $e->exceptionCode = 'SET_SOLICITUD_DUPLICITY_EXCEPTION';
12193            report($e);
12194
12195            return response(['message' => 'KO', 'error' => $e->getMessage()]);
12196        }
12197    }
12198
12199    public function getQuoteIdOfDuplicityById($id)
12200    {
12201        try {
12202            $quote = TblQuotations::where('id', $id)->first();
12203
12204            if (! $quote) {
12205                throw new \Exception('Quote no encontrada');
12206            }
12207
12208            return response([
12209                'message' => 'OK',
12210                'data' => $quote,
12211            ]);
12212
12213        } catch (\Exception $e) {
12214            /** @disregard P1014 */
12215            $e->exceptionCode = 'GET_QUOTE_ID_OF_DUPLICITY_BY_QUOTE_ID_EXCEPTION';
12216            report($e);
12217
12218            return response(['message' => 'KO', 'error' => $e->getMessage()]);
12219        }
12220    }
12221
12222    public function download_s3_files(Request $request)
12223    {
12224        ini_set('max_execution_time', 123456);
12225
12226        try {
12227            
12228            $data = $request->all();        
12229            $zipName = 'files_' . time() . '.zip';
12230
12231            $r = new Request([
12232                'filterModel' => $data['filterModel'],
12233                'sortModel' => $data['sortModel'],
12234                'start' => 0,
12235                'end' => 999999999,
12236                'company_id' => $data['company_id'],
12237                'user_id' => $data['user_id'],
12238                'ids' => $data['ids'],
12239                'searchText' => $data['searchText'],
12240                'ids_not_in' => $data['ids_not_in'],
12241            ]);
12242
12243            $result = $this->list_quotations($r);
12244            $result = $result->original['data'];
12245            $orderIds = array_column($result, 'id');
12246
12247            $files = TblFiles::whereIn('quotation_id', $orderIds)->where('is_internal', null)->get();
12248            if ($files->isEmpty()) {
12249                return response(['message' => 'KO', 'error' => 'No files found']);
12250            }
12251            
12252            $tempDir = storage_path('app/temp');
12253            
12254            if (!file_exists($tempDir)) {
12255                mkdir($tempDir, 0755, true);
12256            }
12257
12258            $zipPath = $tempDir . '/' . $zipName;
12259            
12260            $zip = new ZipArchive;
12261            if ($zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== TRUE) {
12262                return response(['message' => 'KO', 'error' => 'Could not create ZIP file']);
12263            }
12264
12265            foreach ($files as $file) {
12266                $filePath = 'uploads/' . $file->filename;
12267
12268                if (Storage::disk('s3')->exists($filePath)) {
12269                    $contents = Storage::disk('s3')->get($filePath);
12270                    $zip->addFromString(basename($filePath), $contents);
12271                }
12272            }
12273
12274            $zip->close();
12275
12276            if (!file_exists($zipPath)) {
12277                return response(['message' => 'KO', 'error' => 'ZIP file creation failed'], 500);
12278            }
12279            
12280            $content = file_get_contents($zipPath);
12281
12282            unlink($zipPath);
12283
12284            return response($content, 200, [
12285                'Content-Type' => 'application/zip',
12286                'Content-Disposition' => 'attachment; filename="'.$zipName.'"',
12287            ]);
12288        } catch (\Exception $e) {
12289            /** @disregard P1014 */
12290            $e->exceptionCode = 'DOWNLOAD_S3_FILES_EXCEPTION';
12291            report($e);            
12292            return response(['message' => 'KO', 'error' => $e->getMessage()]);
12293        }
12294    }
12295}