Merge branch 'rework-dashboard' into 'master'
Rework dashboard See merge request fronk/thetool!880
This commit is contained in:
@@ -158,6 +158,26 @@ class DashboardNewController extends mfBaseController {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
$baufortschritt_140 = $countFunction([">status_code" => "139", "<status_code" => "899"]);
|
||||
$timeline_baufortschritt_140 = $this->getTimeline('weekly-leerrohr', $campaign_ids, $gemeinde_ids);
|
||||
|
||||
$ont_installiert_300 = $countFunction([">status_code" => "299", "<status_code" => "899"]);
|
||||
$timeline_ont_installiert_300 = $this->getTimeline('weekly-ont-installed', $campaign_ids, $gemeinde_ids);
|
||||
|
||||
$baufortschritt_140_base_value_before_history = $baufortschritt_140 - $timeline_baufortschritt_140[0][count($timeline_baufortschritt_140[0]) - 1]['value'];
|
||||
|
||||
foreach ($timeline_baufortschritt_140[0] as $key => $value) {
|
||||
$timeline_baufortschritt_140[0][$key]['value'] += $baufortschritt_140_base_value_before_history;
|
||||
}
|
||||
|
||||
$ont_installiert_300_base_value_before_history = $ont_installiert_300 - $timeline_ont_installiert_300[0][count($timeline_ont_installiert_300[0]) - 1]['value'];
|
||||
|
||||
foreach ($timeline_ont_installiert_300[0] as $key => $value) {
|
||||
$timeline_ont_installiert_300[0][$key]['value'] += $ont_installiert_300_base_value_before_history;
|
||||
}
|
||||
|
||||
|
||||
self::returnJson([
|
||||
'order_max_home_addrdb' => $order_max_homes,
|
||||
'order_actual_order' => $countFunction([]),
|
||||
@@ -167,21 +187,23 @@ class DashboardNewController extends mfBaseController {
|
||||
'order_mph' => $countFunction(["connection_type" => $mph_connection_types]),
|
||||
'order_mph_vorsorge' => $countFunction(["connection_type" => $mph_connection_types, "type" => "provision"]),
|
||||
'order_mph_vollanschluss' => $countFunction(["connection_type" => $mph_connection_types, "type" => "order"]),
|
||||
'baufortschritt_140' => $countFunction([">status_code" => "139", "<status_code" => "899"]),
|
||||
'baufortschritt_140' => $baufortschritt_140,
|
||||
'installationspaket_erhalten' => $countFunction(["connection_type" => $efh_connection_types], 145),
|
||||
'lehrrohr_im_haus' => $countFunction(["connection_type" => $efh_connection_types], 200),
|
||||
'inhouse_kabel_verlegt_efh' => $countFunction(["connection_type" => $efh_connection_types], 242),
|
||||
'inhouse_kabel_verlegt_mph' => $countFunction(["connection_type" => $mph_connection_types], 242),
|
||||
'installationsfortschritt_245' => $countFunction([">status_code" => "244", "<status_code" => "899"]),
|
||||
'ont_installiert_300' => $countFunction([">status_code" => "299", "<status_code" => "899"]),
|
||||
'ont_installiert_300' => $ont_installiert_300,
|
||||
'vollanschluss_dokumentiert_350' => $countFunction(["status_code" => ["350","500"], "type" => "order"]),
|
||||
'vorsorge_dokumentiert_351' => $countFunction(["status_code" => ["351","500"], "type" => "provision"]),
|
||||
'provider_bestellt_500' => $countFunction(["status_code" => "500"]),
|
||||
'timeline' => $this->getTimeline('weekly-orders', $campaign_ids, $gemeinde_ids)
|
||||
'timeline' => $this->getTimeline('weekly-orders', $campaign_ids, $gemeinde_ids),
|
||||
'timeline_leerrohr' => $timeline_baufortschritt_140,
|
||||
'timeline_ont_installed' => $timeline_ont_installiert_300
|
||||
]);
|
||||
}
|
||||
|
||||
private function getTimeline($type, $campaign_ids, $gemeinde_ids) {
|
||||
private function getTimeline($type, $campaign_ids, $gemeinde_ids) { //TODO: fix gemeinde
|
||||
$timeline = [];
|
||||
$baseParams = ["preordercampaign_id" => $campaign_ids];
|
||||
if (!empty($gemeinde_ids)) {
|
||||
@@ -196,6 +218,11 @@ class DashboardNewController extends mfBaseController {
|
||||
return $timeline;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// add Leerrohr to timeline
|
||||
// add ont installed to timeline
|
||||
|
||||
private function getTimelineData($type, $params) {
|
||||
$timeline = [];
|
||||
$start = strtotime('-1 year');
|
||||
@@ -203,18 +230,74 @@ class DashboardNewController extends mfBaseController {
|
||||
$interval = new DateInterval('P1W');
|
||||
$daterange = new DatePeriod(date_create(date('Y-m-d', $start)), $interval, date_create(date('Y-m-d', $end)));
|
||||
|
||||
foreach ($daterange as $date) {
|
||||
$date = $date->format('Y-m-d');
|
||||
$params['add-where'] = " AND tt_preorder.`create` >= UNIX_TIMESTAMP('" . $date . " 00:00:00') AND tt_preorder.`create` <= UNIX_TIMESTAMP('" . $date . " 23:59:59')";
|
||||
$timeline[] = [
|
||||
'date' => date(DATE_ATOM, strtotime($date)),
|
||||
'value' => PreorderModel::countActive($params)
|
||||
];
|
||||
// Generate a unique cache key based on the function parameters
|
||||
$cacheKey = md5($type . serialize($params));
|
||||
$cacheFile = TEMP_DIR . "/Dashboard/" . $cacheKey . ".json";
|
||||
|
||||
// Ensure the cache directory exists
|
||||
if (!is_dir(TEMP_DIR . "/Dashboard/")) {
|
||||
mkdir(TEMP_DIR . "/Dashboard/", 0755, true);
|
||||
}
|
||||
|
||||
return $timeline;
|
||||
// Load cached data if it exists
|
||||
if (file_exists($cacheFile)) {
|
||||
$cachedData = json_decode(file_get_contents($cacheFile), true);
|
||||
$lastCachedDate = end($cachedData)['date'];
|
||||
$lastCachedTimestamp = strtotime($lastCachedDate);
|
||||
|
||||
}
|
||||
// Only process the last 5 weeks
|
||||
$daterange = new DatePeriod(
|
||||
date_create(date('Y-m-d', max($lastCachedTimestamp, strtotime('-5 weeks')))),
|
||||
$interval,
|
||||
date_create(date('Y-m-d', $end))
|
||||
);
|
||||
|
||||
$timeline = $cachedData;
|
||||
}
|
||||
|
||||
foreach ($daterange as $date) {
|
||||
$date = $date->format('Y-m-d');
|
||||
$value = 0;
|
||||
|
||||
switch ($type) {
|
||||
case 'weekly-orders':
|
||||
$params['add-where'] = " AND tt_preorder.`create` <= UNIX_TIMESTAMP('" . $date . " 23:59:59')";
|
||||
$value = PreorderModel::countActive($params);
|
||||
break;
|
||||
case 'weekly-leerrohr':
|
||||
$params['add-where'] = " AND ph.`create` <= UNIX_TIMESTAMP('" . $date . " 23:59:59')";
|
||||
$value = PreorderModel::countHistoryStatus($params, 140);
|
||||
break;
|
||||
case 'weekly-ont-installed':
|
||||
$params['add-where'] = " AND ph.`create` <= UNIX_TIMESTAMP('" . $date . " 23:59:59')";
|
||||
$value = PreorderModel::countHistoryStatus($params, 300);
|
||||
break;
|
||||
}
|
||||
|
||||
$newData = [
|
||||
'date' => date(DATE_ATOM, strtotime($date)),
|
||||
'value' => $value
|
||||
];
|
||||
|
||||
// Update existing data or add new data
|
||||
$existingIndex = array_search($newData['date'], array_column($timeline, 'date'));
|
||||
if ($existingIndex !== false) {
|
||||
$timeline[$existingIndex] = $newData;
|
||||
} else {
|
||||
$timeline[] = $newData;
|
||||
}
|
||||
}
|
||||
|
||||
// Sort the timeline by date
|
||||
usort($timeline, function($a, $b) {
|
||||
return strtotime($a['date']) - strtotime($b['date']);
|
||||
});
|
||||
|
||||
// Cache the updated data
|
||||
file_put_contents($cacheFile, json_encode($timeline));
|
||||
|
||||
return $timeline;
|
||||
}
|
||||
|
||||
private function getTotalHomes(array $preordercampaign_id = [], array $gemeinde_id = []) {
|
||||
$baseSQL = "SELECT COUNT(adb_wohneinheit.id) as cnt FROM `" . ADDRESSDB_DBNAME . "`.Wohneinheit adb_wohneinheit
|
||||
|
||||
@@ -395,9 +395,10 @@ class PreorderModel {
|
||||
WHERE $where
|
||||
";
|
||||
|
||||
mfLoghandler::singleton()->debug($sql);
|
||||
|
||||
|
||||
$queryStart = microtime(true);
|
||||
$res = $db->query($sql);
|
||||
mfLoghandler::singleton()->debug("[Query took: ".(microtime(true) - $queryStart)." seconds] " . $sql);
|
||||
if($db->num_rows($res)) {
|
||||
$data = $db->fetch_object($res);
|
||||
return $data->cnt;
|
||||
@@ -860,9 +861,47 @@ class PreorderModel {
|
||||
INNER JOIN `".FRONKDB_DBNAME."`.PreorderStatusflag psf ON psfv.flag_id = psf.id
|
||||
WHERE $where AND psf.code = ".$statusFlag." AND psfv.value = 1";
|
||||
|
||||
mfLoghandler::singleton()->debug($sql);
|
||||
|
||||
$queryStart = microtime(true);
|
||||
$res = $db->query($sql);
|
||||
mfLoghandler::singleton()->debug("[Query took: ".(microtime(true) - $queryStart)." seconds] " . $sql);
|
||||
if ($db->num_rows($res)) {
|
||||
$data = $db->fetch_object($res);
|
||||
return $data->cnt;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static function countHistoryStatus($filter = [], $status_code = null) {
|
||||
if ($status_code === null) {
|
||||
die("Please select a status code");
|
||||
}
|
||||
|
||||
if(!is_array($filter)) return false;
|
||||
|
||||
if(!array_key_exists("deleted", $filter)) {
|
||||
$filter["deleted"] = null;
|
||||
}
|
||||
|
||||
if( !array_key_exists("<status_code", $filter) && !array_key_exists(">status_code", $filter) && !array_key_exists("status_code", $filter)
|
||||
&& !array_key_exists("<status_id", $filter) && !array_key_exists(">status_id", $filter) && !array_key_exists("status_id", $filter) ) {
|
||||
$filter["<status_code"] = 899;
|
||||
}
|
||||
|
||||
$db = FronkDB::singleton();
|
||||
|
||||
$where = self::getSqlFilter($filter);
|
||||
$sql = "SELECT COUNT(*) as cnt
|
||||
FROM `".FRONKDB_DBNAME."`.Preorder tt_preorder
|
||||
LEFT JOIN `".FRONKDB_DBNAME."`.Preorderstatus tt_preorderstatus ON tt_preorder.status_id = tt_preorderstatus.id
|
||||
LEFT JOIN `".ADDRESSDB_DBNAME."`.view_hausnummer as adb_hausnummer ON (tt_preorder.adb_hausnummer_id = adb_hausnummer.hausnummer_id)
|
||||
INNER JOIN `".FRONKDB_DBNAME."`.PreorderHistory ph ON tt_preorder.id = ph.preorder_id
|
||||
WHERE $where AND ph.`key` like 'status_id' AND tt_preorderstatus.code = ".$status_code;
|
||||
|
||||
$queryStart = microtime(true);
|
||||
$res = $db->query($sql);
|
||||
mfLoghandler::singleton()->debug("[Query took: ".(microtime(true) - $queryStart)." seconds] " . $sql);
|
||||
|
||||
if ($db->num_rows($res)) {
|
||||
$data = $db->fetch_object($res);
|
||||
return $data->cnt;
|
||||
|
||||
@@ -120,6 +120,8 @@ class PreorderHistoryModel {
|
||||
$preorder_id = $filter['preorder_id'];
|
||||
if (is_numeric($preorder_id)) {
|
||||
$where .= " AND PreorderHistory.preorder_id=$preorder_id";
|
||||
} else if (is_array($preorder_id)) {
|
||||
$where .= " AND PreorderHistory.preorder_id IN (" . implode(",", $preorder_id) . ")";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,6 +140,17 @@ class PreorderHistoryModel {
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists("new_value", $filter)) {
|
||||
$new_value = FronkDB::singleton()->escape($filter["new_value"]);
|
||||
if($new_value) {
|
||||
$where .= " AND `new_value` like '$new_value'";
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists("add-where", $filter)) {
|
||||
$where .= $filter['add-where'];
|
||||
}
|
||||
|
||||
return $where;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
#topnav {
|
||||
z-index: 99999;
|
||||
}
|
||||
|
||||
.dashboard-container {
|
||||
width: 100%;
|
||||
max-width: 600px;
|
||||
|
||||
@@ -80,7 +80,7 @@ Vue.component('tt-dashboard-display-card', {
|
||||
|
||||
Vue.component('tt-timeline-chart', {
|
||||
props: {
|
||||
chartData: {
|
||||
datasets: {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
@@ -88,14 +88,6 @@ Vue.component('tt-timeline-chart', {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
dataColor: {
|
||||
type: String,
|
||||
default: 'rgb(75, 192, 192)'
|
||||
},
|
||||
fillColor: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
showGrid: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
@@ -112,19 +104,24 @@ Vue.component('tt-timeline-chart', {
|
||||
},
|
||||
methods: {
|
||||
renderChart() {
|
||||
if (this.chart) {
|
||||
this.chart.destroy();
|
||||
}
|
||||
const ctx = this.$refs.chart.getContext('2d');
|
||||
this.chart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: this.chartData.map(item => item.date),
|
||||
datasets: [{
|
||||
label: 'Bestellungen',
|
||||
data: this.chartData.map(item => item.value),
|
||||
borderColor: this.dataColor,
|
||||
backgroundColor: this.fillColor ? this.dataColor : 'transparent',
|
||||
labels: this.datasets[0].data.map(item => item.date),
|
||||
datasets: this.datasets.map((dataset, index) => ({
|
||||
label: dataset.label,
|
||||
data: dataset.data.map(item => item.value),
|
||||
borderColor: dataset.color,
|
||||
backgroundColor: dataset.fill ? dataset.color : 'transparent',
|
||||
tension: 0.1,
|
||||
fill: this.fillColor
|
||||
}]
|
||||
fill: dataset.fill,
|
||||
yAxisID: dataset.yAxisID,
|
||||
order: dataset.order || index
|
||||
}))
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
@@ -148,11 +145,7 @@ Vue.component('tt-timeline-chart', {
|
||||
ticks: {
|
||||
callback: (value, index, values) => {
|
||||
const date = moment(value);
|
||||
if (this.label === 'KW') {
|
||||
return `KW ${date.isoWeek()}`;
|
||||
} else {
|
||||
return date.format('DD.MM');
|
||||
}
|
||||
return this.label === 'KW' ? `KW ${date.isoWeek()}` : date.format('DD.MM');
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -160,7 +153,7 @@ Vue.component('tt-timeline-chart', {
|
||||
beginAtZero: true,
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Anzahl der Bestellungen'
|
||||
text: 'Anzahl'
|
||||
},
|
||||
grid: {
|
||||
display: this.showGrid
|
||||
@@ -168,18 +161,12 @@ Vue.component('tt-timeline-chart', {
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
tooltip: {
|
||||
callbacks: {
|
||||
title: (context) => {
|
||||
const date = moment(context[0].label);
|
||||
if (this.label === 'KW') {
|
||||
return `KW ${date.isoWeek()}`;
|
||||
} else {
|
||||
return date.format('DD.MM');
|
||||
} }
|
||||
return this.label === 'KW' ? `KW ${date.isoWeek()}` : date.format('DD.MM.YYYY');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -188,11 +175,10 @@ Vue.component('tt-timeline-chart', {
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
chartData() {
|
||||
if (this.chart) {
|
||||
this.chart.data.labels = this.chartData.map(item => item.date);
|
||||
this.chart.data.datasets[0].data = this.chartData.map(item => item.value);
|
||||
this.chart.update();
|
||||
datasets: {
|
||||
deep: true,
|
||||
handler() {
|
||||
this.renderChart();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -332,12 +318,36 @@ Vue.component('dashboard-new', {
|
||||
<div class="dashboard-chart">
|
||||
<tt-timeline-chart
|
||||
v-if="dashboardData.timeline.length > 0"
|
||||
:chartData="dashboardData.timeline[0]"
|
||||
:datasets="[
|
||||
{
|
||||
label: 'Bestellungen',
|
||||
data: dashboardData.timeline[0],
|
||||
color: 'rgb(75, 192, 192)',
|
||||
fill: true,
|
||||
yAxisID: 'y',
|
||||
order: 3
|
||||
},
|
||||
{
|
||||
label: 'Leerrohr',
|
||||
data: dashboardData.timeline_leerrohr[0],
|
||||
color: 'rgb(255, 99, 132)',
|
||||
fill: false,
|
||||
yAxisID: 'y',
|
||||
order: 2
|
||||
},
|
||||
{
|
||||
label: 'ONT installiert',
|
||||
data: dashboardData.timeline_ont_installed[0],
|
||||
color: 'rgb(54, 162, 235)',
|
||||
fill: false,
|
||||
yAxisID: 'y',
|
||||
order: 1
|
||||
}
|
||||
]"
|
||||
label="KW"
|
||||
dataColor="rgb(75, 192, 192)"
|
||||
:fillColor="true"
|
||||
:showGrid="false"
|
||||
/>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</tt-card>
|
||||
|
||||
Reference in New Issue
Block a user