Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 1049
0.00% covered (danger)
0.00%
0 / 20
CRAP
0.00% covered (danger)
0.00%
0 / 1
OngoingJobs
0.00% covered (danger)
0.00%
0 / 1049
0.00% covered (danger)
0.00%
0 / 20
55932
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
20
 list_ongoing_jobs
0.00% covered (danger)
0.00%
0 / 248
0.00% covered (danger)
0.00%
0 / 1
4830
 approve_job
0.00% covered (danger)
0.00%
0 / 43
0.00% covered (danger)
0.00%
0 / 1
42
 reject_job
0.00% covered (danger)
0.00%
0 / 43
0.00% covered (danger)
0.00%
0 / 1
42
 move_to_ongoing_jobs
0.00% covered (danger)
0.00%
0 / 65
0.00% covered (danger)
0.00%
0 / 1
30
 send_mail
0.00% covered (danger)
0.00%
0 / 89
0.00% covered (danger)
0.00%
0 / 1
1056
 bulk_update_ongoing_job
0.00% covered (danger)
0.00%
0 / 34
0.00% covered (danger)
0.00%
0 / 1
20
 delete_ongoing_job
0.00% covered (danger)
0.00%
0 / 26
0.00% covered (danger)
0.00%
0 / 1
20
 download_ongoing_jobs
0.00% covered (danger)
0.00%
0 / 125
0.00% covered (danger)
0.00%
0 / 1
210
 update_ongoing_job
0.00% covered (danger)
0.00%
0 / 37
0.00% covered (danger)
0.00%
0 / 1
90
 get_dates
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
12
 get_job
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
6
 list_job_analytics
0.00% covered (danger)
0.00%
0 / 65
0.00% covered (danger)
0.00%
0 / 1
600
 get_years
0.00% covered (danger)
0.00%
0 / 22
0.00% covered (danger)
0.00%
0 / 1
12
 list_margin_jobs_analytics
0.00% covered (danger)
0.00%
0 / 136
0.00% covered (danger)
0.00%
0 / 1
1560
 get_total_jobs_in_red
0.00% covered (danger)
0.00%
0 / 32
0.00% covered (danger)
0.00%
0 / 1
12
 get_active_job_dates
0.00% covered (danger)
0.00%
0 / 26
0.00% covered (danger)
0.00%
0 / 1
12
 update_ongoing_jobs_month_change
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 update_ongoing_jobs_month_change_manual
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
12
 get_revenue_per_month
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3namespace App\Http\Controllers;
4
5use App\Models\TblBudgetTypes;
6use App\Models\TblCompanies;
7use App\Models\TblCompanyUsers;
8use App\Models\TblOngoingJobs;
9use App\Models\TblProjectTypes;
10use App\Models\TblQuotations;
11use App\Models\TblRevenuePerMonth;
12use App\Models\TblUsers;
13use Illuminate\Http\Request;
14use Illuminate\Support\Facades\App;
15use Illuminate\Support\Facades\Cache;
16use Illuminate\Support\Facades\DB;
17use PhpOffice\PhpSpreadsheet\IOFactory;
18use PhpOffice\PhpSpreadsheet\Spreadsheet;
19
20class OngoingJobs extends Controller
21{
22    private $quotationsController;
23
24    private $locale;
25
26    private $userId;
27
28    private $region;
29
30    private $companyIds;
31
32    private $companyId;
33
34    public function __construct(Quotations $quotationsController)
35    {
36        $this->quotationsController = $quotationsController;
37        $this->locale = @getallheaders()['Locale-ID'];
38        $this->userId = @getallheaders()['User-ID'];
39        $this->region = @getallheaders()['Region'];
40
41        App::setLocale($this->locale);
42
43        $this->companyIds = [];
44
45        if ($this->region != null && $this->region != '' && $this->region != 'All') {
46            $this->region = urldecode($this->region);
47
48            $query = 'SELECT 
49                        b.company_id
50                    FROM 
51                        tbl_company_users a 
52                        LEFT JOIN tbl_companies b ON a.company_id = b.company_id 
53                    WHERE 
54                        a.user_id = ?
55                        AND b.region = ?';
56
57            $this->companyIds = DB::select($query, [intval($this->userId), $this->region]);
58
59            $this->companyIds = collect($this->companyIds)->pluck('company_id')->toArray();
60        } else {
61            $this->companyIds = TblCompanyUsers::where('user_id', $this->userId)->pluck('company_id')->all();
62        }
63
64        $this->companyId = implode(',', $this->companyIds);
65    }
66
67    public function list_ongoing_jobs(Request $request)
68    {
69
70        try {
71
72            $data = $request->all();
73            $companyId = intval($data['company_id']);
74            $userId = intval($data['user_id']);
75            $filter = $data['filterModel'];
76            $sort = $data['sortModel'];
77            $result = [];
78            $subquery = '';
79            $where = '';
80            $having = '';
81            $orderBy = '';
82            $start = intval($data['start']);
83            $end = intval($data['end']);
84            $totalRowCount = 0;
85
86            $filterType = [
87                'contains' => "LIKE '%[value]%'",
88                'notContains' => "NOT LIKE '%[value]%'",
89                'equals' => "= '[value]'",
90                'notEqual' => "<> '[value]'",
91                'startsWith' => "LIKE '[value]%'",
92                'endsWith' => "LIKE '%[value]'",
93                'blank' => 'IS NULL',
94                'notBlank' => 'IS NOT NULL',
95                'lessThan' => '< [value]',
96                'lessThanOrEqual' => '<= [value]',
97                'greaterThan' => '> [value]',
98                'greaterThanOrEqual' => '>= [value]',
99                'inRange' => 'BETWEEN [value1] AND [value2]',
100            ];
101
102            if (isset($data['ids']) && count($data['ids']) > 0) {
103                $quoteIds = implode(',', $data['ids']);
104                $where = " a.id IN ({$quoteIds}";
105            }
106
107            if (isset($data['ids_not_in']) && count($data['ids_not_in']) > 0) {
108                $quoteIds = implode(',', $data['ids_not_in']);
109                $where = " a.id NOT IN ({$quoteIds}";
110            }
111
112            if ($companyId != 0) {
113                if ($where != '') {
114                    $where .= " AND a.company_id = {$companyId} ";
115                } else {
116                    $where .= " a.company_id = {$companyId} ";
117                }
118            } else {
119                if ($where != '') {
120                    $where .= " AND a.company_id IN ({$this->companyId}";
121                } else {
122                    $where .= " a.company_id IN ({$this->companyId}";
123                }
124            }
125
126            $where = "WHERE {$where}";
127
128            $matchScoreCol = '';
129            $matchScoreOrderBy = '';
130
131            if (isset($data['searchText']) && $data['searchText'] != null) {
132
133                $availableParameters = [
134                    'a.quotation_id',
135                    'c.name',
136                    's.name',
137                    'd.name',
138                    'a.quote_id',
139                    'a.company_id',
140                    'a.customer_type_id',
141                    'a.budget_type_id',
142                    'a.order_number',
143                    'a.client',
144                    'a.issue_date',
145                    'a.acceptance_date',
146                    'a.amount',
147                    'a.created_by',
148                    'a.created_at',
149                    'a.updated_by',
150                    'a.updated_at',
151                    'a.invoice_amount',
152                    'a.responsible_for_work',
153                    'a.expected_start_date_of_work',
154                    'a.actual_job_start_date',
155                    'a.actual_end_date',
156                    'a.expected_completion_date',
157                    'a.work_status_id',
158                    'e.name',
159                ];
160
161                $searchText = addslashes($data['searchText']);
162                $searchTextArray = explode(' ', $searchText);
163
164                $searchArray = [];
165                $splitSearchArray = [];
166                $matchScoreArray = [];
167                $sc = 1;
168                foreach ($availableParameters as $field) {
169                    if ($field == 'a.client' || $field == 'a.amount' || $field == 'a.created_at') {
170                        $sc = 3;
171                    } elseif ($field == 'a.acceptance_date') {
172                        $sc = 2;
173                    } else {
174                        $sc = 1;
175                    }
176
177                    $l = "{$field} LIKE '%{$searchText}%'";
178                    $d = "IFNULL((LENGTH(LOWER({$field})) - LENGTH(REPLACE(LOWER({$field}), LOWER('{$searchText}'), ''))) / LENGTH(LOWER('{$searchText}')), 0) * {$sc}";
179
180                    if (count($searchTextArray) > 1) {
181                        foreach ($searchTextArray as $word) {
182                            if (! is_numeric($word)) {
183                                $d .= " + IFNULL((LENGTH(LOWER({$field})) - LENGTH(REPLACE(LOWER({$field}), LOWER('{$word}'), ''))) / LENGTH(LOWER('{$word}')), 0) * {$sc}";
184                            }
185                        }
186                    }
187
188                    array_push($matchScoreArray, $d);
189
190                    if (is_numeric($searchText)) {
191                        array_push($searchArray, "({$l} OR {$field} = CAST('{$searchText}' AS UNSIGNED))");
192                    } else {
193                        array_push($searchArray, "({$l} OR DATE_FORMAT({$field}, '%d/%m/%Y') = DATE_FORMAT(STR_TO_DATE('{$searchText}', '%d/%m/%Y'), '%d/%m/%Y'))");
194                    }
195
196                    if (count($searchTextArray) > 1) {
197                        foreach ($searchTextArray as $word) {
198
199                            $l = "{$field} LIKE '%{$word}%'";
200
201                            if (is_numeric($word)) {
202                                array_push($splitSearchArray, "{$l} OR {$field} = CAST('{$word}' AS UNSIGNED)");
203                            } else {
204                                array_push($splitSearchArray, "{$l} OR DATE_FORMAT({$field}, '%d/%m/%Y') = DATE_FORMAT(STR_TO_DATE('{$word}', '%d/%m/%Y'), '%d/%m/%Y')");
205                            }
206                        }
207                    }
208
209                    $sc = 1;
210                }
211
212                if (count($splitSearchArray) > 0) {
213                    $splitSearchArray = implode(' OR ', $splitSearchArray);
214                    $splitSearchArray = " OR ({$splitSearchArray}";
215                } else {
216                    $splitSearchArray = '';
217                }
218
219                $searchArray = implode(' OR ', $searchArray);
220                $matchScoreArray = implode(',', $matchScoreArray);
221                $matchScoreCol = ", GREATEST({$matchScoreArray}) match_score";
222                $matchScoreOrderBy = 'match_score DESC,';
223                $where .= " AND ({$searchArray} {$splitSearchArray})";
224            }
225
226            if (count($sort) > 0) {
227                $field = $sort[0]['colId'];
228                $sortBy = $sort[0]['sort'];
229
230                if (strpos($field, 'translate') !== false) {
231                    $field = str_replace('_translate', '', $field);
232                } else {
233                    if ($field == 'client_type') {
234                        $field = 'c.name';
235                    } elseif ($field == 'segment') {
236                        $field = 's.name';
237                    } elseif ($field == 'type') {
238                        $field = 'd.name';
239                    } elseif ($field == 'amount') {
240                        $field = 'CAST(a.amount AS DOUBLE)';
241                    } elseif ($field == 'invoice_amount') {
242                        $field = 'CAST(a.invoice_amount AS DOUBLE)';
243                    } elseif ($field == 'quote_id') {
244                        $field = 'CAST(a.quote_id AS DOUBLE)';
245                    }
246                }
247
248                if ($matchScoreOrderBy) {
249                    $matchScoreOrderBy = ', match_score DESC';
250                }
251
252                $orderBy = " ORDER BY {$field} {$sortBy} {$matchScoreOrderBy}";
253            } else {
254                $orderBy = " ORDER BY {$matchScoreOrderBy} a.id DESC ";
255            }
256
257            foreach ($filter as $key => $data) {
258                if (strpos($key, 'translate') !== false) {
259
260                    $field = str_replace('_translate', '', $key);
261
262                    if ($field == 'created_at') {
263                        $field = 'a.created_at';
264                    }
265
266                    $whereDates = '';
267                    $z = 0;
268                    foreach ($data['filters'] as $yearKey => $yearData) {
269                        $yearsMonths = [];
270                        $yearsWeeks = [];
271
272                        if ($z > 0) {
273                            $whereDates .= " OR (YEAR($field) = {$yearKey} ";
274                        } else {
275                            $whereDates .= " (YEAR($field) = {$yearKey} ";
276                        }
277
278                        for ($i = 0; $i < count($yearData['months']); $i++) {
279                            if ($yearData['months'][$i]['isChecked']) {
280                                array_push($yearsMonths, $yearData['months'][$i]['value']);
281                            }
282                        }
283
284                        $yearsMonths = implode("','", $yearsMonths);
285                        $whereDates .= " AND (MONTH({$field}) IN ('{$yearsMonths}')";
286
287                        for ($i = 0; $i < count($yearData['weeks']); $i++) {
288                            if ($yearData['weeks'][$i]['isChecked']) {
289                                array_push($yearsWeeks, $yearData['weeks'][$i]['value']);
290                            }
291                        }
292
293                        $yearsWeeks = implode("','", $yearsWeeks);
294                        if ($yearsWeeks != '') {
295                            $whereDates .= " OR WEEK({$field}) IN ('{$yearsWeeks}') ";
296                        }
297
298                        $whereDates .= ')) ';
299                        $z++;
300                    }
301
302                    $where .= " AND ({$whereDates}";
303                } else {
304                    if ($data['filterType'] == 'number') {
305                        if (array_key_exists('operator', $data)) {
306                            if ($data['condition1']['type'] != 'blank' && $data['condition2']['type'] != 'notBlank') {
307                                $data['condition1']['filter'] = addslashes($data['condition1']['filter']);
308                                $data['condition2']['filter'] = addslashes($data['condition2']['filter']);
309
310                                if ($data['condition1']['type'] == 'inRange') {
311                                    $data['condition1']['filterTo'] = addslashes($data['condition1']['filterTo']);
312                                    $inRange = str_replace('[value1]', $data['condition1']['filter'], $filterType['inRange']);
313                                    $val1 = str_replace('[value2]', $data['condition1']['filterTo'], $inRange);
314                                } else {
315                                    $val1 = str_replace('[value]', $data['condition1']['filter'], $filterType[$data['condition1']['type']]);
316                                }
317
318                                if ($data['condition2']['type'] == 'inRange') {
319                                    $data['condition2']['filterTo'] = addslashes($data['condition2']['filterTo']);
320                                    $inRange = str_replace('[value1]', $data['condition2']['filter'], $filterType['inRange']);
321                                    $val2 = str_replace('[value2]', $data['condition2']['filterTo'], $inRange);
322                                } else {
323                                    $val2 = str_replace('[value]', $data['condition2']['filter'], $filterType[$data['condition2']['type']]);
324                                }
325
326                            } else {
327                                $val1 = $filterType[$data['condition1']['type']];
328                                $val2 = $filterType[$data['condition2']['type']];
329                            }
330
331                            $where .= " AND a.{$key} {$val1} {$data['operator']} a.{$key} {$val2} ";
332                        } else {
333                            if ($data['type'] != 'blank' && $data['type'] != 'notBlank') {
334                                $data['filter'] = addslashes($data['filter']);
335
336                                if ($data['type'] == 'inRange') {
337                                    $data['filterTo'] = addslashes($data['filterTo']);
338                                    $inRange = str_replace('[value1]', $data['filter'], $filterType['inRange']);
339                                    $val = str_replace('[value2]', $data['filterTo'], $inRange);
340                                } else {
341                                    $val = str_replace('[value]', $data['filter'], $filterType[$data['type']]);
342                                }
343                            } else {
344                                $val = $filterType[$data['type']];
345                            }
346
347                            $where .= " AND a.{$key} {$val} ";
348                        }
349                    }
350
351                    if ($data['filterType'] == 'text') {
352                        if (array_key_exists('operator', $data)) {
353                            $val1 = '';
354                            $val2 = '';
355                            if ($data['condition1']['type'] != 'blank' && $data['condition2']['type'] != 'notBlank') {
356                                $data['condition1']['filter'] = addslashes($data['condition1']['filter']);
357                                $val1 = str_replace('[value]', $data['condition1']['filter'], $filterType[$data['condition1']['type']]);
358                            }
359
360                            if ($data['condition2']['type'] != 'blank' && $data['condition2']['type'] != 'notBlank') {
361                                $data['condition2']['filter'] = addslashes($data['condition2']['filter']);
362                                $val2 = str_replace('[value]', $data['condition2']['filter'], $filterType[$data['condition2']['type']]);
363                            }
364
365                            $where .= " AND {$key} {$val1} {$data['operator']} {$key} {$val2} ";
366                        } else {
367                            if ($data['type'] != 'blank' && $data['type'] != 'notBlank') {
368                                $data['filter'] = addslashes($data['filter']);
369                                $val = str_replace('[value]', $data['filter'], $filterType[$data['type']]);
370                            } else {
371                                $val = $filterType[$data['type']];
372                            }
373
374                            $where .= " AND {$key} {$val} ";
375                        }
376                    }
377
378                    if ($data['filterType'] == 'set') {
379                        $statusName = $key;
380
381                        if ($key == 'client_type') {
382                            $statusName = 'c.name';
383                        } elseif ($key == 'segment') {
384                            $statusName = 's.name';
385                        } elseif ($key == 'type') {
386                            $statusName = 'd.name';
387                        } elseif ($key == 'work_status') {
388                            $statusName = 'e.name';
389                        } elseif ($key == 'created_by') {
390                            $statusName = 'a.created_by';
391                        }
392
393                        $val = implode("','", $data['values']);
394
395                        if (in_array(null, $data['values'], true)) {
396                            $where .= " AND ({$statusName} IN ('{$val}') OR {$statusName} IS NULL) ";
397                        } else {
398                            $where .= " AND {$statusName} IN ('{$val}') ";
399                        }
400                    }
401                }
402            }
403
404            $offset = $start;
405            $limit = $end - $start;
406
407            $subquery = ",(SELECT can_write FROM tbl_company_users WHERE company_id = a.company_id AND user_id = {$userId}) can_write";
408
409            $query = "SELECT 
410                        a.id,
411                        a.quotation_id, 
412                        b.name company_name, 
413                        c.name client_type,
414                        s.name segment,
415                        s.segment_id,
416                        d.name 'type',
417                        a.quote_id, 
418                        a.company_id,
419                        a.customer_type_id,
420                        a.budget_type_id,
421                        a.order_number,
422                        a.client,
423                        a.issue_date,
424                        a.acceptance_date, 
425                        DATE_FORMAT(a.issue_date, '%d/%m/%Y') issue_date_translate,
426                        DATE_FORMAT(a.acceptance_date, '%d/%m/%Y') acceptance_date_translate,
427                        a.amount, 
428                        a.created_by, 
429                        a.created_at,
430                        a.updated_by,
431                        a.updated_at,
432                        a.invoice_amount,
433                        a.responsible_for_work,
434                        a.expected_start_date_of_work,
435                        a.actual_job_start_date, 
436                        a.actual_end_date, 
437                        a.expected_completion_date, 
438                        a.comments,
439                        DATE_FORMAT(a.expected_start_date_of_work, '%d/%m/%Y') expected_start_date_of_work_translate,
440                        DATE_FORMAT(a.actual_job_start_date, '%d/%m/%Y') actual_job_start_date_translate,
441                        DATE_FORMAT(a.actual_end_date, '%d/%m/%Y') actual_end_date_translate,
442                        DATE_FORMAT(a.expected_completion_date, '%d/%m/%Y') expected_completion_date_translate,
443                        DATE_FORMAT(a.created_at, '%d/%m/%Y') created_at_translate,
444                        CASE 
445                            WHEN 
446                                DATE_FORMAT(a.expected_completion_date, '%Y-%m-%d') < DATE_FORMAT(NOW(), '%Y-%m-%d') AND a.work_status_id NOT IN (3, 5)
447                            THEN 1
448                            ELSE 0
449                        END is_red_expected_completion_date,
450                        CASE 
451                            WHEN 
452                                DATE_FORMAT(a.expected_start_date_of_work, '%Y-%m-%d') < DATE_FORMAT(NOW(), '%Y-%m-%d') AND a.work_status_id = 2
453                            THEN 1
454                            ELSE 0
455                        END is_red_expected_start_date_of_work,
456                        CASE 
457                            WHEN 
458                                DATE_FORMAT(a.expected_completion_date, '%Y-%m-%d') < DATE_FORMAT(NOW(), '%Y-%m-%d')
459                                AND a.work_status_id NOT IN (3, 5) 
460                            THEN 1
461                            ELSE 0
462                        END is_red,
463                        CASE 
464                            WHEN 
465                                (g.amount IS NULL OR g.amount = '')
466                                AND (a.pending_to_be_invoiced IS NOT NULL AND a.pending_to_be_invoiced <> '' AND a.pending_to_be_invoiced <> 0)
467                                AND DATE_FORMAT(NOW(), '%Y-%m-%d') BETWEEN DATE_FORMAT(CASE WHEN a.work_status_id = 3 OR a.work_status_id = 5 THEN a.actual_job_start_date ELSE a.expected_start_date_of_work END, '%Y-%m-%d') 
468                                AND DATE_FORMAT(CASE WHEN a.work_status_id = 3 OR a.work_status_id = 5 THEN a.actual_end_date ELSE a.expected_completion_date END , '%Y-%m-%d') 
469                            THEN 1
470                            ELSE 0
471                        END is_red_invoiced,
472                        a.work_status_id,
473                        e.name work_status,
474                        a.cost_for_client,
475                        a.people_assigned_to_the_job,
476                        a.duration_of_job_in_days,
477                        a.estimated_cost_of_materials,
478                        a.for_approval,
479                        a.cost_of_labor,
480                        a.total_cost_of_job,
481                        a.invoice_margin,
482                        a.margin_for_the_company,
483                        a.margin_on_invoice_per_day_per_worker,
484                        a.revenue_per_date_per_worked,
485                        a.gross_margin,
486                        a.labor_percentage,
487                        a.pending_to_be_invoiced,
488                        g.amount to_be_invoiced_this_month,
489                        a.to_be_invoiced_after_this_month,
490                        a.approved_at,
491                        a.approved_by
492                        {$matchScoreCol}
493                        {$subquery}
494                    FROM 
495                        tbl_ongoing_jobs a 
496                        LEFT JOIN tbl_companies b ON a.company_id = b.company_id
497                        LEFT JOIN tbl_customer_types c ON a.customer_type_id = c.customer_type_id
498                        LEFT JOIN tbl_segments s ON a.segment_id = s.segment_id
499                        LEFT JOIN tbl_budget_types d ON a.budget_type_id = d.budget_type_id
500                        LEFT JOIN tbl_work_status e ON a.work_status_id = e.work_status_id
501                        LEFT JOIN tbl_revenue_per_month g ON a.quotation_id = g.quotation_id AND g.month = MONTH(NOW()) AND g.year = YEAR(NOW())
502                    {$where}
503                    {$orderBy}
504                    LIMIT {$offset}{$limit}
505                    ";
506
507            $value = Cache::get(base64_encode($query));
508
509            if (! $value) {
510                $result = DB::select($query);
511
512                Cache::put(base64_encode($query), $result, 600);
513            } else {
514                $result = $value;
515            }
516
517            $totalQuery = "SELECT 
518                            COUNT(1) totalRowCount
519                        FROM 
520                            tbl_ongoing_jobs a 
521                            LEFT JOIN tbl_companies b ON a.company_id = b.company_id 
522                            LEFT JOIN tbl_customer_types c ON a.customer_type_id = c.customer_type_id 
523                            LEFT JOIN tbl_segments s ON a.segment_id = s.segment_id
524                            LEFT JOIN tbl_budget_types d ON a.budget_type_id = d.budget_type_id 
525                            LEFT JOIN tbl_work_status e ON a.work_status_id = e.work_status_id
526                        {$where}";
527
528            $value = Cache::get(base64_encode($totalQuery));
529
530            if (! $value) {
531                $countQuery = DB::select($totalQuery);
532
533                Cache::put(base64_encode($totalQuery), $countQuery, 600);
534            } else {
535                $countQuery = $value;
536            }
537
538            return response([
539                'message' => 'OK',
540                'data' => $result,
541                'totalRowCount' => $countQuery[0]->totalRowCount,
542            ]);
543
544        } catch (\Exception $e) {
545            /** @disregard P1014 */
546            $e->exceptionCode = 'LIST_ONGOING_JOBS_EXCEPTION';
547            report($e);
548
549            return response(['message' => 'KO', 'error' => $e->getMessage()]);
550        }
551    }
552
553    public function approve_job($id)
554    {
555
556        try {
557
558            $id = intval($id);
559
560            $result = TblOngoingJobs::where('id', $id)->first();
561            $company = TblCompanies::where('company_id', $result->company_id)->first();
562            $budgetType = TblBudgetTypes::where('budget_type_id', $result->budget_type_id)->first();
563
564            $order = new Quotations;
565
566            if ($result->created_by != $result->responsible_for_work) {
567                $creatorAndResponsibleForWork = [$result->created_by, $result->responsible_for_work];
568                foreach ($creatorAndResponsibleForWork as $name) {
569                    $user = TblUsers::where('name', $name)->first();
570                    if ($user) {
571                        $order->send_approved_notification(
572                            $user->id,
573                            $user->name,
574                            $user->email,
575                            $company->name,
576                            $budgetType->name,
577                            $result->amount,
578                            $id,
579                            $result->quote_id,
580                            $company->company_id,
581                            'ongoing-jobs'
582                        );
583                    }
584                }
585            } else {
586                $user = TblUsers::where('name', $result->created_by)->first();
587                if ($user) {
588                    $order->send_approved_notification(
589                        $user->id,
590                        $user->name,
591                        $user->email,
592                        $company->name,
593                        $budgetType->name,
594                        $result->amount,
595                        $id,
596                        $result->quote_id,
597                        $company->company_id,
598                        'ongoing-jobs'
599                    );
600                }
601            }
602
603            TblOngoingJobs::where('id', $id)->update(['for_approval' => null]);
604
605            Cache::flush();
606
607            return response(['message' => 'OK']);
608
609        } catch (\Exception $e) {
610            /** @disregard P1014 */
611            // @phpstan-ignore-next-line
612            $e->exceptionCode = 'APROVE_JOB_EXCEPTION';
613            report($e);
614
615            return response(['message' => 'KO', 'error' => $e->getMessage()]);
616        }
617
618    }
619
620    public function reject_job($id)
621    {
622
623        try {
624
625            $id = intval($id);
626
627            $result = TblOngoingJobs::where('id', $id)->first();
628            $company = TblCompanies::where('company_id', $result->company_id)->first();
629            $budgetType = TblBudgetTypes::where('budget_type_id', $result->budget_type_id)->first();
630
631            $order = new Quotations;
632
633            if ($result->created_by != $result->responsible_for_work) {
634                $creatorAndResponsibleForWork = [$result->created_by, $result->responsible_for_work];
635                foreach ($creatorAndResponsibleForWork as $name) {
636                    $user = TblUsers::where('name', $name)->first();
637                    if ($user) {
638                        $order->send_rejected_notification(
639                            $user->id,
640                            $user->name,
641                            $user->email,
642                            $company->name,
643                            $budgetType->name,
644                            $result->amount,
645                            $id,
646                            $result->quote_id,
647                            $company->company_id,
648                            'ongoing-jobs'
649                        );
650                    }
651
652                }
653            } else {
654                $user = TblUsers::where('name', $result->created_by)->first();
655                if ($user) {
656                    $order->send_rejected_notification(
657                        $user->id,
658                        $user->name,
659                        $user->email,
660                        $company->name,
661                        $budgetType->name,
662                        $result->amount,
663                        $id,
664                        $result->quote_id,
665                        $company->company_id,
666                        'ongoing-jobs'
667                    );
668                }
669            }
670
671            TblOngoingJobs::where('id', $id)->update(['for_approval' => 2]);
672
673            Cache::flush();
674
675            return response(['message' => 'OK']);
676
677        } catch (\Exception $e) {
678            /** @disregard P1014 */
679            $e->exceptionCode = 'REJECCT_JOB_EXCEPTION';
680            report($e);
681
682            return response(['message' => 'KO', 'error' => $e->getMessage()]);
683        }
684
685    }
686
687    public function move_to_ongoing_jobs(Request $request, $id)
688    {
689
690        try {
691
692            $id = intval($id);
693            $data = $request->all();
694            $userId = intval($data['user_id']);
695            unset($data['user_id']);
696
697            $jobId = null;
698
699            $ongoingJob = TblOngoingJobs::where('quotation_id', $id)->first();
700            $quotation = TblQuotations::where('id', $id)->first();
701
702            if (empty($quotation->acceptance_date)) {
703                $quotation->acceptance_date = date('Y-m-d H:i:s');
704
705                TblQuotations::where('id', $id)->update(
706                    [
707                        'acceptance_date' => $quotation->acceptance_date,
708                        'budget_status_id' => 3,
709                        'updated_at' => date('Y-m-d H:i:s'),
710                        'updated_by' => $data['created_by'],
711                    ]
712                );
713            }
714
715            $job = [
716                'quotation_id' => $id,
717                'quote_id' => $quotation->quote_id,
718                'company_id' => $quotation->company_id,
719                'customer_type_id' => $quotation->customer_type_id,
720                'segment_id' => $quotation->segment_id,
721                'budget_type_id' => $quotation->budget_type_id,
722                'order_number' => $quotation->order_number,
723                'client' => $quotation->client,
724                'issue_date' => $quotation->issue_date,
725                'acceptance_date' => $quotation->acceptance_date,
726                'amount' => $quotation->amount,
727                'cost_for_client' => $quotation->amount,
728                'comments' => $quotation->last_follow_up_comment,
729            ];
730
731            if ($quotation->budget_margin_enabled > 0) {
732                $job['people_assigned_to_the_job'] = $quotation->people_assigned_to_the_job;
733                $job['duration_of_job_in_days'] = $quotation->duration_of_job_in_days;
734                $job['estimated_cost_of_materials'] = $quotation->estimated_cost_of_materials;
735                $job['cost_of_labor'] = $quotation->cost_of_labor;
736                $job['total_cost_of_job'] = $quotation->total_cost_of_job;
737                $job['invoice_margin'] = $quotation->invoice_margin;
738                $job['margin_for_the_company'] = $quotation->margin_for_the_company;
739                $job['margin_on_invoice_per_day_per_worker'] = $quotation->margin_on_invoice_per_day_per_worker;
740                $job['revenue_per_date_per_worked'] = $quotation->revenue_per_date_per_worked;
741                $job['gross_margin'] = $quotation->gross_margin;
742                $job['labor_percentage'] = $quotation->labor_percentage;
743            }
744
745            $username = null;
746            $isAdd = 0;
747            if (empty($ongoingJob)) {
748                $isAdd = 1;
749                $job['created_by'] = $data['created_by'];
750                $job['to_be_invoiced_this_month'] = $quotation->amount;
751                $job['pending_to_be_invoiced'] = 0;
752                $job['to_be_invoiced_after_this_month'] = 0;
753
754                $result = TblOngoingJobs::create($job);
755                $jobId = $result->id;
756
757                // if(empty($quotation->approved_at)){
758                //     $this->send_mail($quotation, $job, $jobId, $userId, $isAdd, $data['created_by']);
759                // }
760            } else {
761                $jobId = $ongoingJob->id;
762                $job['updated_by'] = $data['created_by'];
763                $job['updated_at'] = date('Y-m-d H:i:s');
764                $result = TblOngoingJobs::where('id', $jobId)->update($job);
765
766                // if(empty($quotation->approved_at) || $ongoingJob->invoice_margin != $quotation->invoice_margin){
767                //     $this->send_mail($quotation, $job, $jobId, $userId, $isAdd, $data['created_by']);
768                // }
769            }
770
771            $this->quotationsController->addUpdateLog($id, $userId, 'move_to_ongoing_job', null, null, 4);
772
773            Cache::flush();
774
775            return response(['message' => 'OK', 'id' => $jobId]);
776
777        } catch (\Exception $e) {
778            /** @disregard P1014 */
779            $e->exceptionCode = 'MOVE_TO_ONGOING_JOB_EXCEPTION';
780            report($e);
781
782            return response(['message' => 'KO', 'error' => $e->getMessage()]);
783        }
784    }
785
786    public function send_mail($quotation, $data, $jobId, $userId, $isAdd, $createdBy)
787    {
788
789        $g = false;
790        if ($isAdd == 0) {
791            if (isset($data['cost_for_client']) || isset($data['budget_type_id']) || isset($data['customer_type_id']) || isset($data['invoice_margin'])) {
792                if ($data['cost_for_client'] != $quotation->cost_for_client || $data['budget_type_id'] != $quotation->budget_type_id
793                || $data['customer_type_id'] != $quotation->customer_type_id || $data['invoice_margin'] != $quotation->invoice_margin) {
794                    $g = true;
795                }
796            }
797        } else {
798            $g = true;
799        }
800
801        if ($g) {
802            $company = TblCompanies::where('company_id', $quotation->company_id)->first();
803
804            if ($company) {
805
806                $n = 0;
807                $invoiceMargin = 0;
808                $minimumMargin = 0;
809
810                $project = TblProjectTypes::where('company_id', $company->company_id)->where('budget_type_id', $data['budget_type_id'])->first();
811                $customerTypeIds = [];
812
813                if ($project) {
814                    if (! empty($project->customer_type_ids)) {
815                        $customerTypeIds = array_map('intval', explode(',', $project->customer_type_ids));
816                    }
817                    if ($project->minimum_order_size != null && in_array($data['customer_type_id'], $customerTypeIds)) {
818                        if ($data['cost_for_client'] >= $project->minimum_order_size) {
819                            $data['for_approval'] = 1;
820                            $n = 1;
821                        }
822                    }
823                } else {
824                    if (! empty($company->customer_type_ids)) {
825                        $customerTypeIds = array_map('intval', explode(',', $company->customer_type_ids));
826                    }
827                    if ($company->minimum_order_size != null && in_array($data['customer_type_id'], $customerTypeIds)) {
828                        if ($data['cost_for_client'] >= $company->minimum_order_size) {
829                            $data['for_approval'] = 1;
830                            $n = 1;
831                        }
832                    }
833                }
834
835                $costOfLabor = $data['cost_of_labor'] ?? 0;
836                $totalCostOfJob = $data['total_cost_of_job'] ?? 0;
837
838                if ($totalCostOfJob > 0) {
839                    $invoiceMargin = $data['invoice_margin'] ?? 0;
840                }
841
842                $project = TblProjectTypes::where('company_id', $quotation->company_id)->where('budget_type_id', $quotation->budget_type_id)->first();
843                $minimumMargin = $company->minimum_margin;
844                $minimumOrderSize = $company->minimum_order_size;
845
846                if (! empty($company->customer_type_ids)) {
847                    $customerTypeIds = array_map('intval', explode(',', $company->customer_type_ids));
848                }
849
850                if ($project) {
851                    $minimumMargin = $project->minimum_margin;
852                    $minimumOrderSize = $project->minimum_order_size;
853                    if (! empty($project->customer_type_ids)) {
854                        $customerTypeIds = array_map('intval', explode(',', $project->customer_type_ids));
855                    }
856                }
857
858                if ($invoiceMargin < $minimumMargin && $invoiceMargin != null && $invoiceMargin != 0) {
859                    if (in_array($data['customer_type_id'], $customerTypeIds)) {
860                        $data['for_approval'] = 1;
861                        $n = 2;
862                    }
863                }
864
865                $order = new Quotations;
866
867                if ($n == 1) {
868                    $order->send_approval_notification(
869                        $data['cost_for_client'],
870                        $quotation->budget_type_id,
871                        $quotation->customer_type_id,
872                        $minimumOrderSize,
873                        $quotation->quote_id,
874                        $jobId,
875                        $quotation->name,
876                        $createdBy,
877                        $userId,
878                        $isAdd,
879                        null,
880                        $company->company_id,
881                        'ongoing-jobs',
882                        0,
883                        null,
884                        $n
885                    );
886                }
887
888                if ($n == 2) {
889                    $order->send_approval_margin_notification(
890                        $data['cost_for_client'],
891                        $quotation->budget_type_id,
892                        $quotation->customer_type_id,
893                        $minimumMargin,
894                        $quotation->quote_id,
895                        $jobId,
896                        $company->name,
897                        $createdBy,
898                        $userId,
899                        $isAdd,
900                        null,
901                        $invoiceMargin,
902                        $company->company_id,
903                        'ongoing-jobs'
904                    );
905                }
906
907                if (isset($data['for_approval'])) {
908                    TblOngoingJobs::where('id', $jobId)->update(
909                        [
910                            'for_approval' => $data['for_approval'],
911                        ]
912                    );
913                }
914            }
915        }
916    }
917
918    public function bulk_update_ongoing_job(Request $request)
919    {
920
921        try {
922
923            $data = $request->all();
924
925            $r = new Request([
926                'filterModel' => $data['filterModel'],
927                'sortModel' => $data['sortModel'],
928                'start' => 0,
929                'end' => 999999999,
930                'company_id' => $data['company_id'],
931                'user_id' => $data['user_id'],
932                'ids' => $data['ids'],
933                'searchText' => $data['searchText'],
934                'ids_not_in' => $data['ids_not_in'],
935            ]);
936
937            $listOngoingJobs = $this->list_ongoing_jobs($r);
938            $d = $listOngoingJobs->original['data'];
939
940            if (count($d) > 0) {
941                unset($data['filterModel']);
942                unset($data['sortModel']);
943                unset($data['start']);
944                unset($data['end']);
945                unset($data['company_id']);
946                unset($data['user_id']);
947                unset($data['ids']);
948                unset($data['searchText']);
949                unset($data['ids_not_in']);
950
951                $result = [];
952                for ($i = 0; $i < count($d); $i++) {
953                    array_push($result, $d[$i]->id);
954                }
955
956                TblOngoingJobs::whereIn('id', $result)->update($data);
957
958                Cache::flush();
959            }
960
961            return response(['message' => 'OK', $data]);
962
963        } catch (\Exception $e) {
964            /** @disregard P1014 */
965            $e->exceptionCode = 'BULK_UPDATE_ONGOING_JOB_EXCEPTION';
966            report($e);
967
968            return response(['message' => 'KO', 'error' => $e->getMessage()]);
969        }
970
971    }
972
973    public function delete_ongoing_job(Request $request)
974    {
975
976        try {
977
978            $data = $request->all();
979            $result = [];
980
981            $r = new Request([
982                'filterModel' => $data['filterModel'],
983                'sortModel' => $data['sortModel'],
984                'start' => 0,
985                'end' => 999999999,
986                'company_id' => $data['company_id'],
987                'user_id' => $data['user_id'],
988                'ids' => $data['ids'],
989                'searchText' => $data['searchText'],
990                'ids_not_in' => $data['ids_not_in'],
991            ]);
992
993            $result = $this->list_ongoing_jobs($r);
994            $result = $result->original['data'];
995
996            $outputArray = [];
997
998            foreach ($result as $item) {
999                if (isset($item->id)) {
1000                    $outputArray[] = $item->id;
1001                }
1002            }
1003
1004            TblOngoingJobs::whereIn('id', $outputArray)->delete();
1005
1006            Cache::flush();
1007
1008            return response(['message' => 'OK', 'data' => $result]);
1009
1010        } catch (\Exception $e) {
1011            /** @disregard P1014 */
1012            $e->exceptionCode = 'DELETE_ONGOING_JOB_EXCEPTION';
1013            report($e);
1014
1015            return response(['message' => 'KO', 'error' => $e->getMessage()]);
1016        }
1017
1018    }
1019
1020    public function download_ongoing_jobs(Request $request)
1021    {
1022        ini_set('max_execution_time', 123456);
1023        $data = $request->all();
1024        $companyId = addslashes($data['company_id']);
1025        $userId = addslashes($data['user_id']);
1026
1027        $where = '';
1028        $n = 17;
1029
1030        if ($companyId) {
1031            $n = 16;
1032        }
1033
1034        $r = new Request([
1035            'filterModel' => $data['filterModel'],
1036            'sortModel' => $data['sortModel'],
1037            'start' => 0,
1038            'end' => 999999999,
1039            'company_id' => $data['company_id'],
1040            'user_id' => $data['user_id'],
1041            'ids' => $data['ids'],
1042            'searchText' => $data['searchText'],
1043            'ids_not_in' => $data['ids_not_in'],
1044        ]);
1045
1046        $result = $this->list_ongoing_jobs($r);
1047
1048        $spreadsheet = new Spreadsheet;
1049        $worksheet = new \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet($spreadsheet, 'Inputs');
1050        $spreadsheet->addSheet($worksheet, 0);
1051        $col = range('A', 'Z');
1052
1053        for ($i = 0; $i < 20; $i++) {
1054            $worksheet->getColumnDimension($col[$i])->setAutoSize(true);
1055            if ($i != 1) {
1056                $worksheet->getStyle($col[$i])
1057                    ->getAlignment()
1058                    ->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
1059            }
1060        }
1061
1062        $l = 1;
1063        $worksheet->setCellValue('A'.$l, __('language.ID'));
1064        $worksheet->setCellValue('B'.$l, __('language.CLIENT'));
1065        $worksheet->setCellValue('C'.$l, __('language.ISSUE_DATE'));
1066        $worksheet->setCellValue('D'.$l, __('language.ACCEPTANCE_DATE'));
1067        $worksheet->setCellValue('E'.$l, __('language.ORDER_NUMBER'));
1068        $worksheet->setCellValue('F'.$l, __('language.TYPE'));
1069        $worksheet->setCellValue('G'.$l, __('language.AMOUNT'));
1070        $worksheet->setCellValue('H'.$l, __('language.CREATED_BY'));
1071        $worksheet->setCellValue('I'.$l, __('language.RESPONSIBLE_FOR_WORK'));
1072        $worksheet->setCellValue('J'.$l, __('language.CLIENT_TYPE'));
1073        $worksheet->setCellValue('K'.$l, __('language.SEGMENT'));
1074        $worksheet->setCellValue('L'.$l, __('language.INVOICE_AMOUNT'));
1075        $worksheet->setCellValue('M'.$l, __('language.EXPECTED_START_DATE_OF_WORK'));
1076        $worksheet->setCellValue('N'.$l, __('language.ACTUAL_JOB_START_DATE'));
1077        $worksheet->setCellValue('O'.$l, __('language.ACTUAL_END_DATE'));
1078        $worksheet->setCellValue('P'.$l, __('language.EXPECTED_COMPLETION_DATE'));
1079        $worksheet->setCellValue('Q'.$l, __('language.CREATED_AT'));
1080
1081        $styleArray = [
1082            'font' => [
1083                'bold' => true,
1084            ],
1085        ];
1086
1087        $worksheet->getStyle('A1:'.(($n == 17) ? 'R1' : 'Q1'))
1088            ->getFill()
1089            ->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
1090            ->getStartColor()
1091            ->setARGB('523779');
1092
1093        $worksheet->getStyle('A1:'.(($n == 17) ? 'R1' : 'Q1'))
1094            ->getFont()
1095            ->getColor()
1096            ->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_WHITE);
1097
1098        $worksheet->getStyle('A1:Q1')->applyFromArray($styleArray);
1099
1100        $l = 2;
1101        $result = $result->original['data'];
1102
1103        for ($i = 0; $i < count($result); $i++) {
1104
1105            if ($result[$i]->issue_date) {
1106                $result[$i]->issue_date = \PhpOffice\PhpSpreadsheet\Shared\Date::PHPToExcel($result[$i]->issue_date);
1107            }
1108
1109            if ($result[$i]->acceptance_date) {
1110                $result[$i]->acceptance_date = \PhpOffice\PhpSpreadsheet\Shared\Date::PHPToExcel($result[$i]->acceptance_date);
1111            }
1112
1113            if ($result[$i]->expected_start_date_of_work) {
1114                $result[$i]->expected_start_date_of_work = \PhpOffice\PhpSpreadsheet\Shared\Date::PHPToExcel($result[$i]->expected_start_date_of_work);
1115            }
1116
1117            if ($result[$i]->actual_job_start_date) {
1118                $result[$i]->actual_job_start_date = \PhpOffice\PhpSpreadsheet\Shared\Date::PHPToExcel($result[$i]->actual_job_start_date);
1119            }
1120
1121            if ($result[$i]->actual_end_date) {
1122                $result[$i]->actual_end_date = \PhpOffice\PhpSpreadsheet\Shared\Date::PHPToExcel($result[$i]->actual_end_date);
1123            }
1124
1125            if ($result[$i]->expected_completion_date) {
1126                $result[$i]->expected_completion_date = \PhpOffice\PhpSpreadsheet\Shared\Date::PHPToExcel($result[$i]->expected_completion_date);
1127            }
1128
1129            if ($result[$i]->created_at) {
1130                $result[$i]->created_at = \PhpOffice\PhpSpreadsheet\Shared\Date::PHPToExcel($result[$i]->created_at);
1131            }
1132
1133            $worksheet->setCellValue('A'.$l, $result[$i]->quote_id);
1134            $worksheet->setCellValue('B'.$l, $result[$i]->client);
1135            $worksheet->setCellValue('C'.$l, $result[$i]->issue_date);
1136
1137            $worksheet->getStyle('C'.$l)
1138                ->getNumberFormat()
1139                ->setFormatCode(\PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_DATE_YYYYMMDDSLASH);
1140
1141            $worksheet->setCellValue('D'.$l, $result[$i]->acceptance_date);
1142
1143            $worksheet->getStyle('D'.$l)
1144                ->getNumberFormat()
1145                ->setFormatCode(\PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_DATE_YYYYMMDDSLASH);
1146
1147            $worksheet->setCellValue('E'.$l, $result[$i]->order_number);
1148            $worksheet->setCellValue('F'.$l, $result[$i]->type);
1149            $worksheet->setCellValue('G'.$l, $result[$i]->amount);
1150            $worksheet->setCellValue('H'.$l, $result[$i]->created_by);
1151            $worksheet->setCellValue('I'.$l, $result[$i]->responsible_for_work);
1152            $worksheet->setCellValue('J'.$l, $result[$i]->client_type);
1153            $worksheet->setCellValue('K'.$l, $result[$i]->segment);
1154            $worksheet->setCellValue('L'.$l, $result[$i]->invoice_amount);
1155            $worksheet->setCellValue('M'.$l, $result[$i]->expected_start_date_of_work);
1156
1157            $worksheet->getStyle('M'.$l)
1158                ->getNumberFormat()
1159                ->setFormatCode(\PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_DATE_YYYYMMDDSLASH);
1160
1161            $worksheet->setCellValue('N'.$l, $result[$i]->actual_job_start_date);
1162
1163            $worksheet->getStyle('N'.$l)
1164                ->getNumberFormat()
1165                ->setFormatCode(\PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_DATE_YYYYMMDDSLASH);
1166
1167            $worksheet->setCellValue('O'.$l, $result[$i]->actual_end_date);
1168
1169            $worksheet->getStyle('O'.$l)
1170                ->getNumberFormat()
1171                ->setFormatCode(\PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_DATE_YYYYMMDDSLASH);
1172
1173            $worksheet->setCellValue('P'.$l, $result[$i]->expected_completion_date);
1174
1175            $worksheet->getStyle('P'.$l)
1176                ->getNumberFormat()
1177                ->setFormatCode(\PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_DATE_YYYYMMDDSLASH);
1178
1179            $worksheet->setCellValue('Q'.$l, $result[$i]->created_at);
1180
1181            $worksheet->getStyle('Q'.$l)
1182                ->getNumberFormat()
1183                ->setFormatCode(\PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_DATE_YYYYMMDDSLASH);
1184
1185            $l++;
1186
1187        }
1188
1189        $writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
1190        ob_start();
1191        $writer->save('php://output');
1192        $file = ob_get_contents();
1193        ob_end_clean();
1194
1195        return response($file);
1196    }
1197
1198    public function update_ongoing_job(Request $request, $id)
1199    {
1200
1201        try {
1202
1203            $data = $request->all();
1204            $id = addslashes($id);
1205            $userId = addslashes($data['user_id']);
1206            unset($data['user_id']);
1207
1208            $r = ['amount', 'order_number', 'budget_type_id', 'acceptance_date'];
1209            $order = [];
1210
1211            foreach ($data as $key => $value) {
1212                if ($value == 'null') {
1213                    $data[$key] = null;
1214                }
1215
1216                if (in_array($key, $r)) {
1217                    $order[$key] = $value;
1218                }
1219            }
1220
1221            $data['updated_at'] = date('Y-m-d H:i:s');
1222            $order['updated_at'] = $data['updated_at'];
1223
1224            $revenuePerMonth = [];
1225            if (isset($data['revenue_per_month'])) {
1226                $revenuePerMonth = $data['revenue_per_month'];
1227                unset($data['revenue_per_month']);
1228            }
1229
1230            $quotation = TblOngoingJobs::where('id', $id)->first();
1231
1232            if (count($revenuePerMonth) > 0) {
1233                TblRevenuePerMonth::where('quotation_id', $quotation->quotation_id)->delete();
1234                for ($i = 0; $i < count($revenuePerMonth); $i++) {
1235                    unset($revenuePerMonth[$i]['duplicate']);
1236                    unset($revenuePerMonth[$i]['invoice_date']);
1237
1238                    $revenuePerMonth[$i]['created_by'] = $data['updated_by'];
1239                    $revenuePerMonth[$i]['quotation_id'] = $quotation->quotation_id;
1240
1241                    if (date('Yn') == $revenuePerMonth[$i]['year'].$revenuePerMonth[$i]['month']) {
1242                        $data['to_be_invoiced_this_month'] = $revenuePerMonth[$i]['amount'];
1243                    }
1244                }
1245                TblRevenuePerMonth::insert($revenuePerMonth);
1246            }
1247
1248            $result = TblOngoingJobs::where('id', $id)->update($data);
1249            TblQuotations::where('id', $quotation->quotation_id)->update($order);
1250
1251            $this->send_mail($quotation, $data, $id, $userId, 0, $data['updated_by']);
1252
1253            Cache::flush();
1254
1255            return response(['message' => 'OK', 'data' => $result]);
1256
1257        } catch (\Exception $e) {
1258            /** @disregard P1014 */
1259            $e->exceptionCode = 'UPDATE_ONGOING_JOB_EXCEPTION';
1260            report($e);
1261
1262            return response(['message' => 'KO', 'error' => $e->getMessage()]);
1263        }
1264    }
1265
1266    public function get_dates(Request $request)
1267    {
1268
1269        try {
1270
1271            $data = $request->all();
1272            $companyId = addslashes($data['company_id']);
1273
1274            $where = '';
1275            if ($companyId != 0) {
1276                $where = " a.company_id = {$companyId} ";
1277            } else {
1278                $where = " a.company_id IN ({$this->companyId}";
1279            }
1280
1281            $query = "SELECT
1282                        DATE_FORMAT(a.issue_date, '%d/%m/%Y') issue_date_translate,
1283                        DATE_FORMAT(a.acceptance_date, '%d/%m/%Y') acceptance_date_translate,
1284                        DATE_FORMAT(a.expected_start_date_of_work, '%d/%m/%Y') expected_start_date_of_work_translate,
1285                        DATE_FORMAT(a.actual_job_start_date, '%d/%m/%Y') actual_job_start_date_translate,
1286                        DATE_FORMAT(a.actual_end_date, '%d/%m/%Y') actual_end_date_translate,
1287                        DATE_FORMAT(a.expected_completion_date, '%d/%m/%Y') expected_completion_date_translate,
1288                        DATE_FORMAT(a.created_at, '%d/%m/%Y') created_at_translate
1289                    FROM tbl_ongoing_jobs a
1290                    WHERE {$where}";
1291
1292            $result = DB::select($query);
1293
1294            return response([
1295                'message' => 'OK',
1296                'data' => $result,
1297            ]);
1298
1299        } catch (\Exception $e) {
1300            /** @disregard P1014 */
1301            $e->exceptionCode = 'GET_DATES_EXCEPTION';
1302            report($e);
1303
1304            return response(['message' => 'KO', 'error' => $e->getMessage()]);
1305        }
1306
1307    }
1308
1309    public function get_job($jobId)
1310    {
1311
1312        try {
1313
1314            $jobId = addslashes($jobId);
1315
1316            $query = "SELECT 
1317                        a.id,
1318                        a.quotation_id, 
1319                        b.name company_name, 
1320                        c.name client_type,
1321                        s.name segment,
1322                        s.segment_id,
1323                        d.name 'type',
1324                        a.quote_id, 
1325                        a.company_id,
1326                        a.customer_type_id,
1327                        a.budget_type_id,
1328                        a.order_number,
1329                        a.client,
1330                        a.issue_date,
1331                        a.acceptance_date, 
1332                        DATE_FORMAT(a.issue_date, '%d/%m/%Y') issue_date_translate,
1333                        DATE_FORMAT(a.acceptance_date, '%d/%m/%Y') acceptance_date_translate,
1334                        a.amount, 
1335                        a.created_by, 
1336                        a.created_at,
1337                        a.updated_by,
1338                        a.updated_at,
1339                        a.invoice_amount,
1340                        a.responsible_for_work,
1341                        a.expected_start_date_of_work,
1342                        a.actual_job_start_date, 
1343                        a.actual_end_date, 
1344                        a.expected_completion_date, 
1345                        DATE_FORMAT(a.expected_start_date_of_work, '%d/%m/%Y') expected_start_date_of_work_translate,
1346                        DATE_FORMAT(a.actual_job_start_date, '%d/%m/%Y') actual_job_start_date_translate,
1347                        DATE_FORMAT(a.actual_end_date, '%d/%m/%Y') actual_end_date_translate,
1348                        DATE_FORMAT(a.expected_completion_date, '%d/%m/%Y') expected_completion_date_translate,
1349                        DATE_FORMAT(a.created_at, '%d/%m/%Y') created_at_translate,
1350                        a.work_status_id,
1351                        e.name work_status,
1352                        a.cost_for_client,
1353                        a.people_assigned_to_the_job,
1354                        a.duration_of_job_in_days,
1355                        a.estimated_cost_of_materials,
1356                        a.for_approval,
1357                        a.cost_of_labor,
1358                        a.total_cost_of_job,
1359                        a.invoice_margin,
1360                        a.margin_for_the_company,
1361                        a.margin_on_invoice_per_day_per_worker,
1362                        a.revenue_per_date_per_worked,
1363                        a.gross_margin,
1364                        a.labor_percentage,
1365                        a.pending_to_be_invoiced,
1366                        g.amount to_be_invoiced_this_month,
1367                        a.to_be_invoiced_after_this_month,
1368                        a.approved_at,
1369                        a.approved_by,
1370                        a.rejected_at,
1371                        a.rejected_by,
1372                        CASE 
1373                            WHEN 
1374                                (g.amount IS NULL OR g.amount = '')
1375                                AND (a.pending_to_be_invoiced IS NOT NULL AND a.pending_to_be_invoiced <> '' AND a.pending_to_be_invoiced <> 0)
1376                                AND DATE_FORMAT(NOW(), '%Y-%m-%d') BETWEEN DATE_FORMAT(CASE WHEN a.work_status_id = 3 OR a.work_status_id = 5 THEN a.actual_job_start_date ELSE a.expected_start_date_of_work END, '%Y-%m-%d') 
1377                                AND DATE_FORMAT(CASE WHEN a.work_status_id = 3 OR a.work_status_id = 5 THEN a.actual_end_date ELSE a.expected_completion_date END , '%Y-%m-%d') 
1378                            THEN 1
1379                            ELSE 0
1380                        END is_red_invoiced
1381                    FROM 
1382                        tbl_ongoing_jobs a 
1383                        LEFT JOIN tbl_companies b ON a.company_id = b.company_id
1384                        LEFT JOIN tbl_customer_types c ON a.customer_type_id = c.customer_type_id
1385                        LEFT JOIN tbl_segments s ON a.segment_id = s.segment_id
1386                        LEFT JOIN tbl_budget_types d ON a.budget_type_id = d.budget_type_id
1387                        LEFT JOIN tbl_work_status e ON a.work_status_id = e.work_status_id
1388                        LEFT JOIN tbl_revenue_per_month g ON a.quotation_id = g.quotation_id AND g.month = MONTH(NOW()) AND g.year = YEAR(NOW())
1389                    WHERE a.id = {$jobId}";
1390
1391            $result = DB::select($query);
1392
1393            Cache::flush();
1394
1395            return response(['message' => 'OK', 'data' => $result]);
1396
1397        } catch (\Exception $e) {
1398            /** @disregard P1014 */
1399            $e->exceptionCode = 'GET_JOB_EXCEPTION';
1400            report($e);
1401
1402            return response(['message' => 'KO', 'error' => $e->getMessage()]);
1403        }
1404    }
1405
1406    public function list_job_analytics(Request $request)
1407    {
1408
1409        try {
1410
1411            $data = $request->all();
1412            $companyId = addslashes($data['company_id']);
1413
1414            $where = '';
1415            $whereYears = '';
1416            $whereMonths = '';
1417
1418            if ($companyId != 0) {
1419                $where .= " AND company_id = {$companyId} ";
1420            } else {
1421                $where .= " AND company_id IN ({$this->companyId}";
1422            }
1423
1424            if (isset($data['start_years']) && $data['start_years'] != null) {
1425                $years = implode(',', $data['start_years']);
1426                if (count($data['start_years']) > 0) {
1427                    $whereYears = " AND YEAR(expected_start_date_of_work) IN ({$years})";
1428                }
1429            }
1430
1431            if (isset($data['start_months']) && $data['start_months'] != null) {
1432                $months = implode(',', $data['start_months']);
1433                if (count($data['start_months']) > 0) {
1434                    $whereMonths = " AND MONTH(expected_start_date_of_work) IN ({$months})";
1435                }
1436            }
1437
1438            if (isset($data['end_years']) && $data['end_years'] != null) {
1439                $years = implode(',', $data['end_years']);
1440                if (count($data['end_years']) > 0) {
1441                    $whereYears .= " AND YEAR(expected_completion_date) IN ({$years})";
1442                }
1443            }
1444
1445            if (isset($data['end_months']) && $data['end_months'] != null) {
1446                $months = implode(',', $data['end_months']);
1447                if (count($data['end_months']) > 0) {
1448                    $whereMonths .= " AND MONTH(expected_completion_date) IN ({$months})";
1449                }
1450            }
1451
1452            if (isset($data['responsible_for_work']) && $data['responsible_for_work'] != null) {
1453                $responsible = implode("','", $data['responsible_for_work']);
1454                if (count($data['responsible_for_work']) > 0) {
1455                    $where .= " AND a.responsible_for_work IN ('{$responsible}')";
1456                }
1457            }
1458
1459            if (isset($data['work_status_id']) && $data['work_status_id'] != null) {
1460                $work = implode(',', $data['work_status_id']);
1461                if (count($data['work_status_id']) > 0) {
1462                    $where .= " AND a.work_status_id IN ({$work})";
1463                }
1464            }
1465
1466            if (isset($data['budget_type_id']) && $data['budget_type_id'] != null) {
1467                $budget = implode(',', $data['budget_type_id']);
1468                if (count($data['budget_type_id']) > 0) {
1469                    $where .= " AND a.budget_type_id IN ({$budget})";
1470                }
1471            }
1472
1473            $query = "SELECT
1474                        YEAR 'year',
1475                        MONTH 'month',
1476                        WEEK 'week',
1477                        SUM(acceptance_date) AS totalApproved,
1478                        SUM(expected_start_date_of_work) AS totalJobsExpectedToStart,
1479                        SUM(expected_completion_date) AS totalJobsExpectedToFinalized,
1480                        SUM(actual_job_start_date) AS totalJobsStarted,
1481                        SUM(actual_end_date) AS totalJobsFinalized,
1482                        SUM(revenueExpected) AS revenueExpected,
1483                        SUM(realRevenue) AS realRevenue
1484                    FROM (
1485                        SELECT
1486                            YEAR(acceptance_date) AS YEAR,
1487                            MONTH(acceptance_date) AS MONTH,
1488                            WEEK(acceptance_date) AS WEEK,
1489                            COUNT(*) AS acceptance_date,
1490                            0 AS expected_start_date_of_work,
1491                            0 AS expected_completion_date,
1492                            0 AS actual_job_start_date,
1493                            0 AS actual_end_date,
1494                            0 AS revenueExpected,
1495                            0 AS realRevenue
1496                        FROM
1497                            tbl_ongoing_jobs
1498                        WHERE 
1499                            issue_date IS NOT NULL
1500                            {$where}
1501                            {$whereYears}
1502                            {$whereMonths}
1503                        GROUP BY
1504                            YEAR(acceptance_date),
1505                            MONTH(acceptance_date),
1506                            WEEK(acceptance_date)
1507                    
1508                        UNION ALL
1509
1510                        SELECT
1511                            YEAR(expected_start_date_of_work) AS YEAR,
1512                            MONTH(expected_start_date_of_work) AS MONTH,
1513                            WEEK(expected_start_date_of_work) AS WEEK,
1514                            0 AS acceptance_date,
1515                            COUNT(*) AS expected_start_date_of_work,
1516                            0 AS expected_completion_date,
1517                            0 AS actual_job_start_date,
1518                            0 AS actual_end_date,
1519                            0 AS revenueExpected,
1520                            0 AS realRevenue
1521                        FROM
1522                            tbl_ongoing_jobs
1523                        WHERE 
1524                            issue_date IS NOT NULL
1525                            {$where}
1526                            {$whereYears}
1527                            {$whereMonths}
1528                        GROUP BY
1529                            YEAR(expected_start_date_of_work),
1530                            MONTH(expected_start_date_of_work),
1531                            WEEK(expected_start_date_of_work)
1532                    
1533                        UNION ALL
1534                    
1535                        SELECT
1536                            YEAR(expected_completion_date) AS YEAR,
1537                            MONTH(expected_completion_date) AS MONTH,
1538                            WEEK(expected_completion_date) AS WEEK,
1539                            0 AS acceptance_date,
1540                            0 AS expected_start_date_of_work,
1541                            COUNT(*) AS expected_completion_date,
1542                            0 AS actual_job_start_date,
1543                            0 AS actual_end_date,
1544                            0 AS revenueExpected,
1545                            0 AS realRevenue
1546                        FROM
1547                            tbl_ongoing_jobs
1548                        WHERE 
1549                            issue_date IS NOT NULL
1550                            {$where}
1551                            {$whereYears}
1552                            {$whereMonths}
1553                        GROUP BY
1554                            YEAR(expected_completion_date),
1555                            MONTH(expected_completion_date),
1556                            WEEK(expected_completion_date)
1557                    
1558                        UNION ALL
1559                    
1560                        SELECT
1561                            YEAR(actual_job_start_date) AS YEAR,
1562                            MONTH(actual_job_start_date) AS MONTH,
1563                            WEEK(actual_job_start_date) AS WEEK,
1564                            0 AS acceptance_date,
1565                            0 AS expected_start_date_of_work,
1566                            0 AS expected_completion_date,
1567                            COUNT(*) AS actual_job_start_date,
1568                            0 AS actual_end_date,
1569                            0 AS revenueExpected,
1570                            0 AS realRevenue
1571                        FROM
1572                            tbl_ongoing_jobs
1573                        WHERE 
1574                            issue_date IS NOT NULL
1575                            {$where}
1576                            {$whereYears}
1577                            {$whereMonths}
1578                        GROUP BY
1579                            YEAR(actual_job_start_date),
1580                            MONTH(actual_job_start_date),
1581                            WEEK(actual_job_start_date)
1582                    
1583                        UNION ALL
1584                    
1585                        SELECT
1586                            YEAR(actual_end_date) AS YEAR,
1587                            MONTH(actual_end_date) AS MONTH,
1588                            WEEK(actual_end_date) AS WEEK,
1589                            0 AS acceptance_date,
1590                            0 AS expected_start_date_of_work,
1591                            0 AS expected_completion_date,
1592                            0 AS actual_job_start_date,
1593                            COUNT(*) AS actual_end_date,
1594                            0 AS revenueExpected,
1595                            0 AS realRevenue
1596                        FROM
1597                            tbl_ongoing_jobs
1598                        WHERE 
1599                            issue_date IS NOT NULL
1600                            {$where}
1601                            {$whereYears}
1602                            {$whereMonths}
1603                        GROUP BY
1604                            YEAR(actual_end_date),
1605                            MONTH(actual_end_date),
1606                            WEEK(actual_end_date)
1607                    
1608                        UNION ALL
1609                    
1610                        SELECT
1611                            YEAR(expected_completion_date) AS YEAR,
1612                            MONTH(expected_completion_date) AS MONTH,
1613                            WEEK(expected_completion_date) AS WEEK,
1614                            0 AS acceptance_date,
1615                            0 AS expected_start_date_of_work,
1616                            0 AS expected_completion_date,
1617                            0 AS actual_job_start_date,
1618                            0 AS actual_end_date,
1619                            SUM(CASE WHEN cost_for_client REGEXP '^[0-9]+\\.?[0-9]*$' = 1 THEN cost_for_client END) AS revenueExpected,
1620                            SUM(CASE WHEN invoice_amount REGEXP '^[0-9]+\\.?[0-9]*$' = 1 THEN invoice_amount END) AS realRevenue
1621                        FROM
1622                            tbl_ongoing_jobs
1623                        WHERE 
1624                            issue_date IS NOT NULL
1625                            {$where}
1626                            {$whereYears}
1627                            {$whereMonths}
1628                        GROUP BY
1629                            YEAR(expected_completion_date),
1630                            MONTH(expected_completion_date),
1631                            WEEK(expected_completion_date)
1632                    ) AS subquery
1633                    GROUP BY 
1634                        YEAR, 
1635                        MONTH, 
1636                        WEEK WITH ROLLUP
1637                    HAVING 
1638                        (YEAR IS NOT NULL OR MONTH IS NOT NULL OR WEEK IS NOT NULL)
1639                    ORDER BY
1640                        YEAR, MONTH, WEEK;
1641                    ";
1642
1643            $result = DB::select($query);
1644
1645            return response([
1646                'message' => 'OK',
1647                'data' => $result,
1648            ]);
1649
1650        } catch (\Exception $e) {
1651            /** @disregard P1014 */
1652            $e->exceptionCode = 'LIST_JOB_ANALYTICS_EXCEPTION';
1653            report($e);
1654
1655            return response(['message' => 'KO', 'error' => $e->getMessage()]);
1656        }
1657
1658    }
1659
1660    public function get_years(Request $request)
1661    {
1662
1663        try {
1664
1665            $data = $request->all();
1666            $companyId = addslashes($data['company_id']);
1667            $where = '';
1668
1669            if ($companyId != 0) {
1670                $where = " AND company_id = {$companyId} ";
1671            } else {
1672                $where = " AND company_id IN ({$this->companyId}";
1673            }
1674
1675            $query = "SELECT 
1676                            DISTINCT YEAR(acceptance_date) AS 'year' 
1677                        FROM 
1678                            tbl_ongoing_jobs 
1679                        WHERE 
1680                            acceptance_date IS NOT NULL 
1681                            {$where}
1682                        UNION 
1683                        SELECT 
1684                            DISTINCT YEAR(actual_job_start_date) AS 'year' 
1685                        FROM 
1686                            tbl_ongoing_jobs 
1687                        WHERE 
1688                            actual_job_start_date IS NOT NULL 
1689                            {$where}
1690                        UNION 
1691                        SELECT 
1692                            DISTINCT YEAR(expected_start_date_of_work) AS 'year' 
1693                        FROM 
1694                            tbl_ongoing_jobs 
1695                        WHERE 
1696                            expected_start_date_of_work IS NOT NULL 
1697                            {$where}
1698                        UNION 
1699                        SELECT 
1700                            DISTINCT YEAR(actual_end_date) AS 'year' 
1701                        FROM 
1702                            tbl_ongoing_jobs 
1703                        WHERE 
1704                            actual_end_date IS NOT NULL 
1705                            {$where}
1706                        UNION 
1707                        SELECT 
1708                            DISTINCT YEAR(expected_completion_date) AS 'year' 
1709                        FROM 
1710                            tbl_ongoing_jobs 
1711                        WHERE 
1712                            expected_completion_date IS NOT NULL 
1713                            {$where}
1714                        ORDER BY 
1715                            YEAR
1716                            ";
1717
1718            $result = DB::select($query);
1719
1720            return response([
1721                'message' => 'OK',
1722                'data' => $result,
1723            ]);
1724
1725        } catch (\Exception $e) {
1726            /** @disregard P1014 */
1727            $e->exceptionCode = 'GET_YEARS_EXCEPTION';
1728            report($e);
1729
1730            return response(['message' => 'KO', 'error' => $e->getMessage()]);
1731        }
1732
1733    }
1734
1735    public function list_margin_jobs_analytics(Request $request)
1736    {
1737
1738        try {
1739
1740            $data = $request->all();
1741            $companyId = addslashes($data['company_id']);
1742            $responsibleForWork = $data['user'];
1743            $where = '';
1744            $whereYear = '';
1745            $whereMonths = '';
1746
1747            if ($companyId != 0) {
1748                $where .= " AND a.company_id = {$companyId} ";
1749            } else {
1750                $where .= " AND a.company_id IN ({$this->companyId}";
1751            }
1752
1753            if (isset($data['start_years']) && $data['start_years'] != null) {
1754                $years = implode(',', $data['start_years']);
1755                if (count($data['start_years']) > 0) {
1756                    $whereYear = " AND YEAR(a.expected_start_date_of_work) IN ({$years})";
1757                }
1758            }
1759
1760            if (isset($data['start_months']) && $data['start_months'] != null) {
1761                $months = implode(',', $data['start_months']);
1762                if (count($data['start_months']) > 0) {
1763                    $whereMonths = " AND MONTH(a.expected_start_date_of_work) IN ({$months})";
1764                }
1765            }
1766
1767            if (isset($data['end_years']) && $data['end_years'] != null) {
1768                $years = implode(',', $data['end_years']);
1769                if (count($data['end_years']) > 0) {
1770                    $whereYear .= " AND YEAR(a.expected_completion_date) IN ({$years})";
1771                }
1772            }
1773
1774            if (isset($data['end_months']) && $data['end_months'] != null) {
1775                $months = implode(',', $data['end_months']);
1776                if (count($data['end_months']) > 0) {
1777                    $whereMonths .= " AND MONTH(a.expected_completion_date) IN ({$months})";
1778                }
1779            }
1780
1781            if (isset($data['responsible_for_work']) && $data['responsible_for_work'] != null) {
1782                $responsible = implode("','", $data['responsible_for_work']);
1783                if (count($data['responsible_for_work']) > 0) {
1784                    $where .= " AND a.responsible_for_work IN ('{$responsible}')";
1785                }
1786            }
1787
1788            if (isset($data['work_status_id']) && $data['work_status_id'] != null) {
1789                $work = implode(',', $data['work_status_id']);
1790                if (count($data['work_status_id']) > 0) {
1791                    $where .= " AND a.work_status_id IN ({$work})";
1792                }
1793            }
1794
1795            if (isset($data['budget_type_id']) && $data['budget_type_id'] != null) {
1796                $budget = implode(',', $data['budget_type_id']);
1797                if (count($data['budget_type_id']) > 0) {
1798                    $where .= " AND a.budget_type_id IN ({$budget})";
1799                }
1800            }
1801
1802            $whereInconsistent = '';
1803            if (isset($data['status']) && $data['status'] != null) {
1804                if ($data['status'] == 1) {
1805                    $whereInconsistent = " AND ((DATE_FORMAT(a.expected_start_date_of_work, '%Y-%m-%d') < DATE_FORMAT(NOW(), '%Y-%m-%d') AND a.work_status_id = 2
1806                        OR DATE_FORMAT(a.expected_completion_date, '%Y-%m-%d') < DATE_FORMAT(NOW(), '%Y-%m-%d') AND a.work_status_id NOT IN (3, 5))
1807                        ) AND (CASE WHEN a.responsible_for_work IS NULL THEN a.created_by ELSE a.responsible_for_work END) = '{$responsibleForWork}'";
1808                } elseif ($data['status'] == 2) {
1809                    $whereInconsistent = " AND ((g.amount IS NULL OR g.amount = '')
1810                        AND (CASE WHEN a.responsible_for_work IS NULL THEN a.created_by ELSE a.responsible_for_work END) = '{$responsibleForWork}'
1811                        AND DATE_FORMAT(NOW(), '%Y-%m-%d') BETWEEN DATE_FORMAT(CASE WHEN a.work_status_id = 3 OR a.work_status_id = 5 THEN a.actual_job_start_date ELSE a.expected_start_date_of_work END, '%Y-%m-%d') 
1812                        AND DATE_FORMAT(CASE WHEN a.work_status_id = 3 OR a.work_status_id = 5 THEN a.actual_end_date ELSE a.expected_completion_date END , '%Y-%m-%d') ) ";
1813                }
1814            }
1815
1816            $activeJobWhere = '';
1817            $activeJob = 0;
1818
1819            $activeStartDateColumn = 'CASE WHEN a.work_status_id IN (1,2,4) THEN expected_start_date_of_work ELSE actual_job_start_date END';
1820            $activeEndDateColumn = 'CASE WHEN a.work_status_id IN (1,2,4) THEN expected_completion_date ELSE actual_end_date END';
1821
1822            if (isset($data['active_year']) && $data['active_year'] != null) {
1823                $activeJobWhere = " AND {$data['active_year']} 
1824                    BETWEEN YEAR({$activeStartDateColumn}
1825                    AND YEAR({$activeEndDateColumn}";
1826                $activeJob++;
1827            }
1828
1829            $gMonth = 'MONTH(NOW())';
1830            $gYear = 'YEAR(NOW())';
1831
1832            if (isset($data['active_month']) && $data['active_month'] != null) {
1833                $gMonth = $data['active_month'];
1834                if (empty($data['active_year'])) {
1835                    $r = new Request([
1836                        'company_id' => $companyId,
1837                    ]);
1838                    $getYears = $this->get_years($r);
1839                    $years = $getYears->original['data'];
1840
1841                    $activeJobWhereArray = [];
1842                    foreach ($years as $k => $v) {
1843                        $activeJobWhere = " CONCAT('{$years[$k]->year}', '-', LPAD('{$data['active_month']}', 2, 0)) BETWEEN DATE_FORMAT({$activeStartDateColumn}, '%Y-%m') AND DATE_FORMAT({$activeEndDateColumn} , '%Y-%m') ";
1844                        array_push($activeJobWhereArray, $activeJobWhere);
1845                    }
1846
1847                    $activeJobWhere = implode(' OR ', $activeJobWhereArray);
1848                    $activeJobWhere = " AND ({$activeJobWhere}";
1849                }
1850
1851                $activeJob++;
1852            }
1853
1854            if ($activeJob == 2) {
1855                $gYear = $data['active_year'];
1856                $activeJobWhere = " AND CONCAT('{$data['active_year']}', '-', LPAD('{$data['active_month']}', 2, 0)) BETWEEN DATE_FORMAT({$activeStartDateColumn}, '%Y-%m') AND DATE_FORMAT({$activeEndDateColumn} , '%Y-%m') ";
1857            }
1858
1859            $where .= $activeJobWhere;
1860
1861            $query = "SELECT
1862                            a.id,
1863                            a.quotation_id, 
1864                            b.name company_name, 
1865                            c.name client_type,
1866                            s.name segment,
1867                            s.segment_id,
1868                            d.name 'type',
1869                            a.quote_id, 
1870                            a.company_id,
1871                            a.customer_type_id,
1872                            a.budget_type_id,
1873                            a.order_number,
1874                            a.client,
1875                            a.issue_date,
1876                            a.acceptance_date, 
1877                            DATE_FORMAT(a.issue_date, '%d/%m/%Y') issue_date_translate,
1878                            DATE_FORMAT(a.acceptance_date, '%d/%m/%Y') acceptance_date_translate,
1879                            a.amount, 
1880                            a.created_by, 
1881                            a.created_at,
1882                            a.updated_by,
1883                            a.updated_at,
1884                            a.invoice_amount,
1885                            a.responsible_for_work,
1886                            a.expected_start_date_of_work,
1887                            a.actual_job_start_date, 
1888                            a.actual_end_date, 
1889                            a.expected_completion_date, 
1890                            DATE_FORMAT(a.expected_start_date_of_work, '%d/%m/%Y') expected_start_date_of_work_translate,
1891                            DATE_FORMAT(a.actual_job_start_date, '%d/%m/%Y') actual_job_start_date_translate,
1892                            DATE_FORMAT(a.actual_end_date, '%d/%m/%Y') actual_end_date_translate,
1893                            DATE_FORMAT(a.expected_completion_date, '%d/%m/%Y') expected_completion_date_translate,
1894                            DATE_FORMAT(a.created_at, '%d/%m/%Y') created_at_translate,
1895                            a.work_status_id,
1896                            e.name work_status,
1897                            CASE 
1898                                WHEN 
1899                                DATE_FORMAT(a.expected_completion_date, '%Y-%m-%d') < DATE_FORMAT(NOW(), '%Y-%m-%d') AND a.work_status_id NOT IN (3, 5)
1900                                THEN 1
1901                                ELSE 0
1902                            END is_red_expected_completion_date,
1903                            CASE 
1904                                WHEN 
1905                                DATE_FORMAT(a.expected_start_date_of_work, '%Y-%m-%d') < DATE_FORMAT(NOW(), '%Y-%m-%d') AND a.work_status_id = 2
1906                                THEN 1
1907                                ELSE 0
1908                            END is_red_expected_start_date_of_work,
1909                            CASE 
1910                                WHEN 
1911                                    (g.amount IS NULL OR g.amount = '')
1912                                    AND (a.pending_to_be_invoiced IS NOT NULL AND a.pending_to_be_invoiced <> '' AND a.pending_to_be_invoiced <> 0)
1913                                    AND DATE_FORMAT(NOW(), '%Y-%m-%d') BETWEEN DATE_FORMAT(CASE WHEN a.work_status_id = 3 OR a.work_status_id = 5 THEN a.actual_job_start_date ELSE a.expected_start_date_of_work END, '%Y-%m-%d') 
1914                                    AND DATE_FORMAT(CASE WHEN a.work_status_id = 3 OR a.work_status_id = 5 THEN a.actual_end_date ELSE a.expected_completion_date END , '%Y-%m-%d') 
1915                                THEN 1
1916                                ELSE 0
1917                            END is_red_invoiced,
1918                            a.cost_for_client,
1919                            a.people_assigned_to_the_job,
1920                            a.duration_of_job_in_days,
1921                            a.estimated_cost_of_materials,
1922                            a.cost_of_labor,
1923                            a.total_cost_of_job,
1924                            a.invoice_margin,
1925                            a.margin_for_the_company,
1926                            a.margin_on_invoice_per_day_per_worker,
1927                            a.revenue_per_date_per_worked,
1928                            a.gross_margin,
1929                            a.labor_percentage,
1930                            a.pending_to_be_invoiced,
1931                            (SELECT amount FROM tbl_revenue_per_month WHERE quotation_id = a.quotation_id AND month = {$gMonth} AND year = {$gYear}) to_be_invoiced_this_month,
1932                            a.to_be_invoiced_after_this_month,
1933                            a.for_approval,
1934                            a.approved_at,
1935                            a.approved_by,
1936                            a.rejected_at,
1937                            a.rejected_by,
1938                            d.color,
1939                            e.color color_work_status,
1940                            CASE 
1941                                WHEN f.budget_type_id IS NULL THEN b.revenue_per_employee_per_day
1942                                ELSE f.revenue_per_employee_per_day
1943                            END revenue_per_employee_per_day,
1944                            CASE 
1945                                WHEN CAST(f.revenue_per_employee_per_day AS DOUBLE) > CAST(a.revenue_per_date_per_worked AS DOUBLE) AND f.budget_type_id IS NOT NULL THEN 1
1946                                WHEN CAST(b.revenue_per_employee_per_day AS DOUBLE) > CAST(a.revenue_per_date_per_worked AS DOUBLE) AND f.budget_type_id IS NULL THEN 1
1947                                ELSE 0
1948                            END is_below_benchmark
1949                        FROM tbl_ongoing_jobs a
1950                            LEFT JOIN tbl_companies b ON a.company_id = b.company_id
1951                            LEFT JOIN tbl_customer_types c ON a.customer_type_id = c.customer_type_id
1952                            LEFT JOIN tbl_segments s ON a.segment_id = s.segment_id
1953                            LEFT JOIN tbl_budget_types d ON a.budget_type_id = d.budget_type_id
1954                            LEFT JOIN tbl_work_status e ON a.work_status_id = e.work_status_id
1955                            LEFT JOIN tbl_project_types f ON a.budget_type_id = f.budget_type_id AND a.company_id = f.company_id
1956                            LEFT JOIN tbl_revenue_per_month g ON a.quotation_id = g.quotation_id AND g.month = MONTH(NOW()) AND g.year = YEAR(NOW())
1957                        WHERE a.issue_date 
1958                        AND a.expected_start_date_of_work IS NOT NULL
1959                        {$where}
1960                        {$whereYear}
1961                        {$whereMonths}
1962                        {$whereInconsistent}
1963                        ORDER BY a.client ASC";
1964
1965            $result = DB::select($query);
1966
1967            $durationOfJobInDays = 0;
1968            $peopleAssignedToTheJob = 0;
1969            $totaCostForClient = 0;
1970            $totalCostOfLabor = 0;
1971            $totalMaterialCosts = 0;
1972            $revenuePerDayPerWorked = 0;
1973            $toBeInvoiceIn = 0;
1974            $pAndD = 0;
1975
1976            foreach ($result as $item) {
1977                $durationOfJobInDays = $durationOfJobInDays + $item->duration_of_job_in_days;
1978                $peopleAssignedToTheJob = $peopleAssignedToTheJob + $item->people_assigned_to_the_job;
1979                $totaCostForClient = $totaCostForClient + $item->cost_for_client;
1980                $totalCostOfLabor = $totalCostOfLabor + $item->cost_of_labor;
1981                $totalMaterialCosts = $totalMaterialCosts + $item->estimated_cost_of_materials;
1982                $toBeInvoiceIn = $toBeInvoiceIn + $item->to_be_invoiced_this_month;
1983                $pAndD = $pAndD + ($item->people_assigned_to_the_job * $item->duration_of_job_in_days);
1984            }
1985
1986            $totalCostOfJob = $totalCostOfLabor + $totalMaterialCosts;
1987
1988            $invoiceMargin = 0;
1989            $grossMargin = 0;
1990            $laborPercentage = 0;
1991            $marginForTheCompany = 0;
1992            if ($totalCostOfJob > 0) {
1993                $invoiceMargin = ($totaCostForClient - $totalCostOfJob) / $totaCostForClient * 100;
1994                $grossMargin = ($totaCostForClient - $totalMaterialCosts) / $totaCostForClient * 100;
1995                $laborPercentage = ($totalCostOfLabor / $totaCostForClient) * 100;
1996
1997                $company = TblCompanies::where('company_id', $companyId)->first();
1998                if ($company) {
1999                    $marginForTheCompany = $invoiceMargin - $company->hours_per_worker_per_day_percentage;
2000                }
2001            }
2002
2003            if ($pAndD != 0) {
2004                $revenuePerDayPerWorked = $totaCostForClient / $pAndD;
2005            }
2006
2007            $resultTotal = [
2008                'durationOfJobInDays' => $durationOfJobInDays,
2009                'peopleAssignedToTheJob' => $peopleAssignedToTheJob,
2010                'totalCostForClient' => $totaCostForClient,
2011                'totalCostOfLabor' => $totalCostOfLabor,
2012                'totalMaterialCosts' => $totalMaterialCosts,
2013                'invoiceMargin' => $invoiceMargin,
2014                'marginForTheCompany' => $marginForTheCompany,
2015                'revenuePerDayPerWorked' => $revenuePerDayPerWorked,
2016                'toBeInvoiceIn' => $toBeInvoiceIn,
2017                'grossMargin' => $grossMargin,
2018                'laborPercentage' => $laborPercentage,
2019            ];
2020
2021            return response([
2022                'message' => 'OK',
2023                'data' => $result,
2024                'totals' => $resultTotal,
2025            ]);
2026
2027        } catch (\Exception $e) {
2028            /** @disregard P1014 */
2029            $e->exceptionCode = 'LIST_MARGIN_JOB_ANALYTICS_EXCEPTION';
2030            report($e);
2031
2032            return response(['message' => 'KO', 'error' => $e->getMessage()]);
2033        }
2034    }
2035
2036    public function get_total_jobs_in_red(Request $request)
2037    {
2038
2039        try {
2040
2041            $data = $request->all();
2042            $companyId = addslashes($data['company_id']);
2043            $responsibleForWork = $data['responsible_for_work'];
2044            $where = '';
2045
2046            if ($companyId != 0) {
2047                $where .= " AND a.company_id = {$companyId} ";
2048            } else {
2049                $where .= " AND a.company_id IN ({$this->companyId}";
2050            }
2051
2052            $query = "SELECT
2053                        COUNT(1) total
2054                    FROM tbl_ongoing_jobs a
2055                    WHERE 
2056                        a.expected_start_date_of_work IS NOT NULL
2057                        AND (
2058                            DATE_FORMAT(a.expected_start_date_of_work, '%Y-%m-%d') < DATE_FORMAT(NOW(), '%Y-%m-%d') AND a.work_status_id = 2
2059                            OR DATE_FORMAT(a.expected_completion_date, '%Y-%m-%d') < DATE_FORMAT(NOW(), '%Y-%m-%d') AND a.work_status_id NOT IN (3, 5)                            
2060                        )
2061                        AND (CASE WHEN responsible_for_work IS NULL THEN created_by ELSE responsible_for_work END) = '{$responsibleForWork}'
2062                        {$where}";
2063
2064            $result = DB::select($query);
2065
2066            $query = "SELECT
2067                        COUNT(1) total
2068                    FROM tbl_ongoing_jobs a
2069                    LEFT JOIN tbl_revenue_per_month g ON a.quotation_id = g.quotation_id AND g.month = MONTH(NOW()) AND g.year = YEAR(NOW())
2070                    WHERE 
2071                        a.expected_start_date_of_work IS NOT NULL
2072                        AND ((g.amount IS NULL OR g.amount = '')
2073                        AND (CASE WHEN responsible_for_work IS NULL THEN a.created_by ELSE responsible_for_work END) = '{$responsibleForWork}')
2074                        AND DATE_FORMAT(NOW(), '%Y-%m-%d') BETWEEN DATE_FORMAT(CASE WHEN a.work_status_id = 3 OR a.work_status_id = 5 THEN a.actual_job_start_date ELSE a.expected_start_date_of_work END, '%Y-%m-%d') 
2075                        AND DATE_FORMAT(CASE WHEN a.work_status_id = 3 OR a.work_status_id = 5 THEN a.actual_end_date ELSE a.expected_completion_date END , '%Y-%m-%d') 
2076                        {$where}";
2077
2078            $invoiced = DB::select($query);
2079
2080            $query = "SELECT COUNT(1) total FROM tbl_quotations a WHERE DATE_FORMAT(a.visit_date, '%Y-%m-%d') < DATE_FORMAT(NOW(), '%Y-%m-%d') AND a.commercial = '{$responsibleForWork}' AND a.budget_status_id = 8 {$where}";
2081            $countPastVisitDate = DB::select($query);
2082
2083            $query = "SELECT 
2084                            COUNT(1) total
2085                        FROM tbl_quotations a 
2086                        LEFT JOIN tbl_companies b ON a.company_id = b.company_id
2087                        LEFT JOIN (
2088                                    SELECT
2089                                    a.id,
2090                                    SUBSTRING_INDEX(
2091                                        SUBSTRING_INDEX(a.email, ',', n.digit + 1),
2092                                        ',',
2093                                        -1
2094                                    ) AS email_domain
2095                                    FROM
2096                                    tbl_quotations a
2097                                    INNER JOIN (
2098                                        SELECT
2099                                        0 AS digit
2100                                        UNION ALL
2101                                        SELECT
2102                                        1
2103                                        UNION ALL
2104                                        SELECT
2105                                        2
2106                                        UNION ALL
2107                                        SELECT
2108                                        3
2109                                        UNION ALL
2110                                        SELECT
2111                                        4
2112                                        UNION ALL
2113                                        SELECT
2114                                        5
2115                                        UNION ALL
2116                                        SELECT
2117                                        6
2118                                        UNION ALL
2119                                        SELECT
2120                                        7
2121                                        UNION ALL
2122                                        SELECT
2123                                        8
2124                                        UNION ALL
2125                                        SELECT
2126                                        9
2127                                    ) n ON LENGTH(
2128                                        REPLACE(a.email, ',', '')
2129                                    ) <= LENGTH(a.email)- n.digit
2130                                    GROUP BY a.id
2131                                ) temp ON a.id = temp.id
2132                        WHERE
2133                            a.last_follow_up_date < DATE_SUB(NOW(), INTERVAL 2 DAY)
2134                            AND a.budget_status_id IN (2)
2135                            AND a.email IS NOT NULL
2136                            AND a.email <> ''
2137                            AND NOT EXISTS (
2138                                SELECT
2139                                1
2140                                FROM
2141                                tbl_blocked_domains bd
2142                                WHERE
2143                                temp.email_domain LIKE CONCAT('%', bd.domain, '%')
2144                                AND bd.company_id = a.company_id
2145                            )
2146                            AND a.last_follow_up_date IS NOT NULL
2147                            AND a.reason_for_not_following_up_id IS NULL
2148                            AND a.last_follow_up_date > 0
2149                            AND a.total_sent < b.limit_reminder_emails
2150                            AND a.for_add = 0
2151                            AND a.commercial = '{$responsibleForWork}'
2152                            {$where}";
2153
2154            $countReminders = DB::select($query);
2155
2156            return response([
2157                'message' => 'OK',
2158                'data' => $result[0]->total,
2159                'invoiced' => $invoiced[0]->total,
2160                'totalPastVisitDate' => $countPastVisitDate[0]->total,
2161                'totalReminders' => $countReminders[0]->total,
2162            ]);
2163
2164        } catch (\Exception $e) {
2165            /** @disregard P1014 */
2166            $e->exceptionCode = 'GET_TOTAL_JOBS_IN_RED_EXCEPTION';
2167            report($e);
2168
2169            return response(['message' => 'KO', 'error' => $e->getMessage()]);
2170        }
2171    }
2172
2173    public function get_active_job_dates($companyId)
2174    {
2175
2176        try {
2177
2178            $companyId = addslashes($companyId);
2179            $where = '';
2180
2181            if ($companyId != 0) {
2182                $where .= " AND company_id = {$companyId} ";
2183            } else {
2184                $where .= " AND company_id IN ({$this->companyId}";
2185            }
2186
2187            $query = "SELECT 
2188                        DISTINCT years 
2189                    FROM 
2190                        (
2191                        SELECT 
2192                            YEAR(expected_start_date_of_work) AS years 
2193                        FROM 
2194                            tbl_ongoing_jobs 
2195                        WHERE 
2196                            expected_start_date_of_work IS NOT NULL 
2197                            {$where}
2198                        UNION 
2199                        SELECT 
2200                            YEAR(expected_completion_date) AS years 
2201                        FROM 
2202                            tbl_ongoing_jobs 
2203                        WHERE 
2204                            expected_completion_date IS NOT NULL
2205                            {$where}
2206                        ) AS combined_years 
2207                    ORDER BY 
2208                        years DESC
2209                    ";
2210
2211            $activeYears = DB::select($query);
2212
2213            $query = "SELECT 
2214                        DISTINCT months 
2215                    FROM 
2216                        (
2217                        SELECT 
2218                            MONTH(expected_start_date_of_work) AS months 
2219                        FROM 
2220                            tbl_ongoing_jobs 
2221                        WHERE 
2222                            expected_start_date_of_work IS NOT NULL 
2223                            {$where}
2224                        UNION 
2225                        SELECT 
2226                            MONTH(expected_completion_date) AS months 
2227                        FROM 
2228                            tbl_ongoing_jobs 
2229                        WHERE 
2230                            expected_completion_date IS NOT NULL
2231                            {$where}
2232                        ) AS combined_months
2233                    ORDER BY 
2234                        months ASC
2235                    ";
2236
2237            $activeMonths = DB::select($query);
2238
2239            return response([
2240                'message' => 'OK',
2241                'data' => [
2242                    'years' => $activeYears,
2243                    'months' => $activeMonths,
2244                ],
2245            ]);
2246
2247        } catch (\Exception $e) {
2248            /** @disregard P1014 */
2249            $e->exceptionCode = 'GET_ACTIVE_JOB_DATES_EXCEPTION';
2250            report($e);
2251
2252            return response(['message' => 'KO', 'error' => $e->getMessage()]);
2253        }
2254
2255    }
2256
2257    public function update_ongoing_jobs_month_change($companyId = null, $processedBy = 'System')
2258    {
2259
2260        return response(['message' => 'OK']);
2261
2262    }
2263
2264    public function update_ongoing_jobs_month_change_manual(Request $request)
2265    {
2266
2267        try {
2268
2269            $data = $request->all();
2270
2271            $update = $this->update_ongoing_jobs_month_change(addslashes($data['company_id']), $data['processed_by']);
2272
2273            if ($update) {
2274                return response(['message' => 'OK']);
2275            } else {
2276                return response(['message' => 'KO']);
2277            }
2278
2279        } catch (\Exception $e) {
2280            /** @disregard P1014 */
2281            $e->exceptionCode = 'UPDATE_ONGOING_JOB_MONTH_CHANGE_MANUAL_EXCEPTION';
2282            report($e);
2283
2284            return response(['message' => 'KO', 'error' => $e->getMessage()]);
2285        }
2286
2287    }
2288
2289    public function get_revenue_per_month($quotationId)
2290    {
2291
2292        try {
2293
2294            $quotationId = addslashes($quotationId);
2295
2296            $result = TblRevenuePerMonth::where('quotation_id', $quotationId)->orderBy('year', 'ASC')->orderBy('month', 'ASC')->get();
2297
2298            return response(['message' => 'OK', 'data' => $result]);
2299
2300        } catch (\Exception $e) {
2301            /** @disregard P1014 */
2302            $e->exceptionCode = 'GET_REVENUE_PER_MONTH_EXCEPTION';
2303            report($e);
2304
2305            return response(['message' => 'KO', 'error' => $e->getMessage()]);
2306        }
2307    }
2308}