url_renderer = "http://devkedungdoro.aplikasi.web.id:3000/chart"; } function all($sdate,$edate) { // $sql = "SELECT project_name, sum(unit_amount) as s_hour // FROM one_support.odoo_timesheet // WHERE date_trx BETWEEN '{$sdate}' AND '{$edate}'"; // get total hour and employee between start and end date $sql = "SELECT COUNT(employee_name) as n_employee, IFNULL(SUM(s_hour), 0) as total FROM (SELECT employee_name, project_name, sum(unit_amount) as s_hour FROM one_support.odoo_timesheet WHERE date_trx BETWEEN '{$sdate}' AND '{$edate}' GROUP BY employee_name ) as x"; $qry = $this->db->query($sql); $this->check_error($qry, "get project_name"); $rows = $qry->result_array(); if (count($rows) == 0) { $this->chart_error("No data found"); } // get total weekdays between start and end date $sql_weekdays = "SELECT COUNT(day_code) as tot_weekday FROM (SELECT WEEKDAY(date_trx) as day_code FROM one_support.odoo_timesheet WHERE date_trx BETWEEN '{$sdate}' AND '{$edate}' GROUP BY date_trx ) as x WHERE x.day_code != 6 AND x.day_code != 5"; $wk_qry = $this->db->query($sql_weekdays); $this->check_error($wk_qry, "get project_name"); $row_wk = $wk_qry->result_array(); if (count($row_wk) == 0) { $this->chart_error("No data found"); } // calc percentage total hour / n_weekday * 8 * n_employee $week_hour = $row_wk[0]['tot_weekday'] * 8 * $rows[0]['n_employee']; $value = ($rows[0]['total'] / $week_hour) * 100; $formatted = number_format($value, 2, '.', ''); $option = [ 'series' => [ [ 'type' => 'gauge', 'max' => 150, 'splitNumber' => 15, 'radius' => '97%', 'center' => ['50%', '57%'], 'axisLine' => [ 'lineStyle' => [ 'width' => 25, 'color' => [ [0.2, '#27CF2F'], [0.8, '#37a2da'], [1, '#fd666d'] ] ] ], 'pointer' => [ 'itemStyle' => [ 'color' => 'auto' ] ], 'axisTick' => [ 'distance' => -30, 'length' => 8, 'lineStyle' => [ 'color' => '#fff', 'width' => 2 ] ], 'splitLine' => [ 'distance' => -30, 'length' => 30, 'lineStyle' => [ 'color' => '#fff', 'width' => 4 ] ], 'axisLabel' => [ 'color' => 'inherit', 'distance' => 40, 'fontSize' => 15 ], 'title' => [ 'offsetCenter' => [0, '55%'], 'fontSize' => 15, ], 'detail' => [ 'valueAnimation' => true, 'color' => 'inherit', 'formatter' => '{value} %', 'fontSize' => 18, 'offsetCenter' => ['0%', '70%'] ], 'data' => [ [ 'name' => 'Percent Hour', 'value' => $formatted, ] ] ] ] ]; // 3. encapsulate in config attribute and json encode $config = ["config" => $option]; $j_param = json_encode($config); header("Content-Type: image/png"); // 4. post to chart renderer echo $this->post($this->url_renderer, $j_param); } function project_group($sdate,$edate) { $sql = "SELECT project_name, sum(unit_amount) as s_hour FROM one_support.odoo_timesheet WHERE date_trx BETWEEN '{$sdate}' AND '{$edate}' GROUP BY project_name ORDER BY s_hour DESC"; $qry = $this->db->query($sql); $this->check_error($qry, "get project_name"); $rows = $qry->result_array(); if (count($rows) == 0) { $this->chart_error("No data found"); } $param = array( 'tooltip' => array( 'trigger' => 'item', 'formatter' => '{b}: {c} ({d}%)' ), 'legend' => array( 'orient' => 'vertical', 'right' => '10%', 'top' => 'center' ), 'series' => array( array( 'name' => 'Access From', 'type' => 'pie', 'radius' => '70%', 'center' => ['40%', '50%'], 'labelLine' => array( 'show' => false ), 'label' => array( 'show' => true, 'position' => 'inside', 'formatter' => '{d}%', 'backgroundColor' => 'rgba(0, 0, 0, 0.5)', 'borderRadius' => 5, 'padding' => 4, 'color' => '#fff' ), 'itemStyle' => array( 'normal' => array( 'shadowBlur' => 20, 'shadowOffsetX' => 0, 'shadowColor' => 'rgba(0, 0, 0, 0.5)' ) ), 'emphasis' => array( 'itemStyle' => array( 'shadowBlur' => 30, 'shadowOffsetX' => 0, 'shadowColor' => 'rgba(0, 0, 0, 0.7)' ) ), 'data' => array() ) ) ); $other_val = 0.0; for ($i = 0; $i < count($rows); $i++) { if ($i <= 3) { $param['series'][0]['data'][] = array( 'value' => $rows[$i]['s_hour'], 'name' => $rows[$i]['project_name'], ); } else { $other_val = $other_val + $rows[$i]['s_hour']; } } $param['series'][0]['data'][] = array( 'value' => $other_val, 'name' => 'Others', ); // 3. encapsulate in config attribute and json encode $config = ["config" => $param]; $j_param = json_encode($config); header("Content-Type: image/png"); // 4. post to chart renderer echo $this->post($this->url_renderer, $j_param); } function staff($sdate,$edate,$employee_id) { // 1. prepare the data using sql $sql = "SELECT COUNT(*) AS total, employee_name, SUM(unit_amount) as unit_amount,project_name FROM one_support.odoo_timesheet WHERE date_trx BETWEEN '{$sdate}' AND '{$edate}' AND employee_id = {$employee_id} GROUP BY project_name"; $qry_total_data = $this->db->query($sql, [$id]); $this->check_error($qry_total_data, "get xTotalAll mcu"); $rows = $qry_total_data->result_array(); if (count($rows) == 0) { $this->chart_error("No data found"); } // $rows = array( //fungsi mengatur pembagian label / text function wrapText($text, $maxLength) { return wordwrap($text, $maxLength, "\n", true); // Memecah teks menjadi beberapa baris dengan panjang maksimum dan menggunakan newline sebagai pemisah } // 2. generate parameter for the chart $color = ['#36A2EB', '#FF5733', '#FFC300', '#4BC0C0', '#9966FF']; // Mendapatkan nilai unik dari 'project_name' dan 'employee_name' serta mengatur ulang indeks array $uniqueProjects = array_values(array_unique(array_column($rows, 'project_name'))); $uniqueStaffs = array_values(array_unique(array_column($rows, 'employee_name'))); $param = array( 'title' => array( 'text' => 'Project By Staff', 'left' => 'center', // Menempatkan legend di tengah secara horizontal, 'top' => 'top', 'orient' => 'vertical' ), 'dataset' => array( 'source' => array( array('score', 'amount', 'product'), ) ), //menampilkan nama bagian tiap-tiap chart 'legend' => array( 'data' => $uniqueProjects, 'left' => 'center', 'bottom' => 'bottom', 'orient' => 'horizontal' ), 'grid' => array('containLabel' => true), 'yAxis' => array('type' => 'value'), 'xAxis' => array( 'type' => 'category', 'axisTick' => array('show' => false), 'data' => $uniqueStaffs, ), 'visualMap' => array( 'orient' => 'horizontal', 'show' => false, 'left' => 'center', 'min' => 0, 'max' => 100, 'dimension' => 0, 'inRange' => array( // 'color' => array('#0000FF', '#00eaf2', '#035bff') ) ), 'series' => array() ); // Memetakan warna tiap bar sesuai dengan kategori project_name $colorMapping = array(); foreach ($uniqueProjects as $index => $project_name) { $colorMapping[$project_name] = $color[$index % count($color)]; // Menggunakan modulus untuk memastikan palet warna diulang jika jumlah kategori lebih banyak daripada warna yang tersedia } foreach ($uniqueProjects as $project_name) { $data = array_fill(0, count($uniqueStaffs), null); // Inisialisasi data untuk setiap lokasi foreach ($rows as $row) { if ($row['project_name'] == $project_name) { // Menemukan indeks lokasi dalam $uniqueStaffs $employee_nameIndex = array_search($row['employee_name'], $uniqueStaffs); if ($employee_nameIndex !== false) { $data[$employee_nameIndex] = $row['unit_amount'] ?? 0; // Handling null values } } } $param['series'][] = array( 'name' => $project_name, 'type' => 'bar', 'barGap' => 0.5, 'label' => array( 'show' => true, 'position' => 'top', 'distance' => 25, 'fontSize' => 12, // Menyesuaikan ukuran font 'formatter' => '', // Menggunakan formatter untuk memisahkan baris 'rich' => array('name' => array()), ), 'itemStyle' => array( // Menentukan gaya item untuk bar, termasuk warnanya 'color' => $colorMapping[$project_name] ), 'data' => $data ); } // 3. encapsulate in config attribute and json encode $config = ["config" => $param]; $j_param = json_encode($config); // echo $j_param; header("Content-Type: image/png"); // 4. post to chart renderer echo $this->post($this->url_renderer, $j_param); } function check_error($qry, $stage) { if (!$qry) { $errMsg = $stage . "
" . $this->db->error()["messge"]; print_r($errMsg); $this->chart_error($errMsg); } } function chart_error($msg) { $param = array( 'title' => array( 'show' => true, 'textStyle' => array( 'color' => 'grey', 'fontSize' => 20 ), 'text' => $msg, 'left' => 'center', 'top' => 'center' ), 'xAxis' => array( 'show' => false ), 'yAxis' => array( 'show' => false ), 'series' => array() ); header("Content-Type: image/png"); $config = ["config" => $param]; $j_param = json_encode($config); echo $this->post($this->url_renderer, $j_param); exit; } function post($url, $data) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); curl_setopt($ch, CURLOPT_TIMEOUT, j120); curl_setopt($ch, CURLOPT_HTTPHEADER, [ "Content-Type: application/json", "Content-Length: " . strlen($data), ]); $result = curl_exec($ch); if (curl_errno($ch) > 0) { return [ "status" => "ERR", "message" => curl_error($ch), ]; } $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); if ($httpCode != 200) { return [ "status" => "ERR", "message" => "Http Response : $httpCode", ]; } return $result; } function getMaxValue($value) { $multiple = 150; return ceil($value / $multiple) * $multiple; } }