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