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