Вы сказали:
Подробно с пояснениями
1 добавить первую загрузку страницы через post загрузка данных для chartGroups
2 добавить фильтр startDate и endDate и byaccount_set по нажатию Применить отправить post запрос и обновить chartGroups
<?php
/***********************************************************
* CONFIG
**********************************************************/
//$SQLite3 = new SQLite3('database.sqlite'); // <--- путь к твоей базе
/***********************************************************
* INPUT FILTERS
**********************************************************/
$start = $_GET['startDate'] ?? '';//date('Y-m-01');
$end = $_GET['endDate'] ?? '';//date('Y-m-d');
$user = $_GET['byaccount_set'] ?? '';
$valid = '/^\d{4}-\d{2}-\d{2}$/';
if (!preg_match($valid, $start)) $start = '';//date('Y-m-01');
if (!preg_match($valid, $end)) $end = '';//date('Y-m-d');
$userCond = $SetDateManual = "";
if ($user !== "") {
// поле deal_stage.users_order_ids хранит массив, например ["34","40"]
$userCond = " AND deal_stage.users_order_ids LIKE '%\"$user\"%' ";
}
if($start != '' && $end != ''){
// Создаем объекты DateTime для обеих дат
$date1 = new DateTime($start);
$date2 = new DateTime($end);
// Вычисляем разницу между датами с помощью метода diff()
$interval = $date1->diff($date2);
// Получаем количество дней из свойства 'days' объекта DateInterval
$days = $interval->days;
//echo "Количество дней между датами: " . $days;
$daysSet = $days;
$SetDateManual = " date(deal_stage.deal_create) BETWEEN :start AND :end ";
}else{
$daysSet = 484;
$SetDateManual = " deal_stage.deal_create >= date('now', '-$daysSet days') ";//strftime('%Y', deal_stage.deal_create) = :yr
}
$year = date('Y');
/***********************************************************
* MAIN QUERY
**********************************************************/
$sql = "
SELECT *,
deal_stage.id AS ds_id,
deal_stage.status_deal AS ds_status,
deal_stage.deal_create AS ds_date,
deal_stage.order_id AS order_id,
orders.kp_num_out AS kp_num_out,
orders.sum_order AS sum_order,
orders.payment_step AS payment_step
FROM deal_stage
LEFT JOIN orders ON orders.id = deal_stage.order_id
WHERE $SetDateManual -- date(deal_stage.deal_create) BETWEEN :start AND :end
$userCond
ORDER BY deal_stage.deal_create DESC
";
$stmt = $SQLite3->prepare($sql);
if($start != '' && $end != ''){
$stmt->bindValue(':start', $start, SQLITE3_TEXT);
$stmt->bindValue(':end', $end, SQLITE3_TEXT);
}
$res = $stmt->execute();
/***********************************************************
* GROUPING
**********************************************************/
$data = [
'dealKP' => ['rows'=>[], 'sum_bill'=>0, 'sum_order'=>0],
'group1' => ['rows'=>[], 'sum_bill'=>0, 'sum_order'=>0],
'group2' => ['rows'=>[], 'sum_bill'=>0, 'sum_order'=>0],
'group3' => ['rows'=>[], 'sum_bill'=>0, 'sum_order'=>0],
];
$id_orderArray = [];
while ($r = $res->fetchArray(SQLITE3_ASSOC)) {
//$kp = is_numeric($r['kp_num_out']) ? (int)$r['kp_num_out'] : 0;
$so = is_numeric($r['sum_order']) ? (int)$r['sum_order'] : 0;
$ba = is_numeric($r['bill_amount']) ? (int)$r['bill_amount'] : 0;
//сейчас КП отправленно
if($r['ds_status'] == 3 && empty($r['deal_finish']) && empty($id_orderArray[$r['order_id']][0])){
$id_orderArray[$r['id']][]=$r['order_id'];//???
$id_orderArray[$r['id']][]=3;//???
$data['dealKP']['rows'][] = $r;
//$data['dealKP']['sum_kp'] += $kp;
$data['dealKP']['sum_bill'] += $ba;
$data['dealKP']['sum_order'] += $so;
}
// КП отправлено по дате isset($r['deal_finish'])
if($r['ds_status'] == 3 && isset($r['deal_finish']) && empty($id_orderArray[$r['order_id']][0])){
}
if ($r['ds_status'] == 150 && ($r['payment_step'] == 1 || $r['payment_step'] == 7) && empty($id_orderArray[$r['order_id']][0])) {//&& empty($id_orderKP[$r['order_id']])
$id_orderArray[$r['id']][]=$r['order_id'];//???
$id_orderArray[$r['id']][]=150;//???
$data['group1']['rows'][] = $r;
//$data['group1']['sum_kp'] += $kp;
$data['group1']['sum_bill'] += $ba;
$data['group1']['sum_order'] += $so;
} elseif ($r['ds_status'] == 100 && $r['payment_step'] != 1 && empty($id_orderArray[$r['order_id']][0])) {//&& empty($id_orderKP[$r['order_id']])
$id_orderArray[$r['id']][]=$r['order_id'];//???
$id_orderArray[$r['id']][]=100;//???
$data['group2']['rows'][] = $r;
//$data['group2']['sum_kp'] += $kp;
$data['group2']['sum_bill'] += $ba;
$data['group2']['sum_order'] += $so;
} elseif ($r['ds_status'] < 99 && empty($id_orderArray[$r['order_id']][0])) {
$data['group3']['rows'][] = $r;
//$data['group3']['sum_kp'] += $kp;
$data['group3']['sum_bill'] += $ba;
$data['group3']['sum_order'] += $so;
}
}
// echo '<pre>',print_r($GLOBALS,1);
// exit;
/***********************************************************
* EXTRA QUERIES
**********************************************************/
// === Кварталы ===
//$year = date('Y');
$sqlQ = "
SELECT
strftime('%m', deal_create) AS m,
SUM(CASE WHEN orders.bill_amount GLOB '[0-9]*' THEN orders.bill_amount ELSE 0 END) AS sum_kp,
SUM(orders.sum_order) AS sum_order
FROM deal_stage
LEFT JOIN orders ON orders.id = deal_stage.order_id
WHERE strftime('%Y', deal_stage.deal_create) = :yr
GROUP BY m
";
$stmtQ = $SQLite3->prepare($sqlQ);
$stmtQ->bindValue(':yr', $year, SQLITE3_TEXT);
$resQ = $stmtQ->execute();
$quarters = ['Q1'=>0,'Q2'=>0,'Q3'=>0,'Q4'=>0];
while ($q = $resQ->fetchArray(SQLITE3_ASSOC)) {
$m = (int)$q['m'];
if ($m >= 1 && $m <= 3) $quarters['Q1'] += $q['sum_order'];
if ($m >= 4 && $m <= 6) $quarters['Q2'] += $q['sum_order'];
if ($m >= 7 && $m <= 9) $quarters['Q3'] += $q['sum_order'];
if ($m >= 10 && $m <= 12) $quarters['Q4'] += $q['sum_order'];
}
// === Понедельник–пятница текущей недели ===
$monday = date('Y-m-d', strtotime('monday this week'));
$friday = date('Y-m-d', strtotime('friday this week'));
$sqlW = "
SELECT
SUM(CASE WHEN status_deal = 150 THEN 1 ELSE 0 END) AS s150,
SUM(CASE WHEN status_deal = 100 THEN 1 ELSE 0 END) AS s100
FROM orders
WHERE date(deal_update) BETWEEN :m AND :f
";
$stmtW = $SQLite3->prepare($sqlW);
$stmtW->bindValue(':m', $monday, SQLITE3_TEXT);
$stmtW->bindValue(':f', $friday, SQLITE3_TEXT);
$weekStats = $stmtW->execute()->fetchArray(SQLITE3_ASSOC);
// === Статус 3 ===
$sqlS3 = "
SELECT
SUM(CASE WHEN orders.bill_amount GLOB '[0-9]*' THEN orders.bill_amount ELSE 0 END) AS sum_kp,
SUM(orders.sum_order) AS sum_order,
COUNT(*) AS cnt
FROM deal_stage
LEFT JOIN orders ON orders.id = deal_stage.order_id
WHERE deal_stage.status_deal = 3
AND date(deal_stage.deal_create) BETWEEN :start AND :end
";
$stmt3 = $SQLite3->prepare($sqlS3);
$stmt3->bindValue(':start', $start, SQLITE3_TEXT);
$stmt3->bindValue(':end', $end, SQLITE3_TEXT);
$stats3 = $stmt3->execute()->fetchArray(SQLITE3_ASSOC);
function NumToPrice($num){
$amountFloat = $num / 100; // 123.45
return number_format($amountFloat, 2, '.', ' '); // "123.45"
}
?>
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Отчёт по заявкам</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.jsdelivr.net@^2.2.0/dist/chartjs-plugin-datalabels.min.js"></script>
</head>
<body class="bg-light">
<div class="container mt-4">
<div class="card shadow-sm mb-4">
<div class="card-header bg-white">
<h5>Фильтр</h5>
</div>
<div class="card-body">
<form class="row g-3">
<div class="col-md-3">
<label class="form-label">Дата от:</label>
<input type="date" name="startDate" class="form-control" value="<?= $start ?>">
</div>
<div class="col-md-3">
<label class="form-label">Дата до:</label>
<input type="date" name="endDate" class="form-control" value="<?= $end ?>">
</div>
<div class="col-md-3">
<label class="form-label">Сотрудник:</label>
<select name="byaccount_set" class="form-select">
<option value="">Все</option>
<option value="34" <?= $user=="34"?"selected":"" ?>>ID 34</option>
<option value="35" <?= $user=="35"?"selected":"" ?>>ID 35</option>
<option value="40" <?= $user=="40"?"selected":"" ?>>ID 40</option>
<option value="38" <?= $user=="38"?"selected":"" ?>>ID 38</option>
</select>
</div>
<div class="col-md-3 d-flex align-items-end">
<button class="btn btn-primary w-100">Применить</button>
</div>
</form>
</div>
</div>
<!-- === MAIN DATA === -->
<div class="card shadow-sm mb-4">
<div class="card-header bg-white"><h5>Результаты</h5></div>
<div class="card-body">
<h6>КП отправлено</h6>
<p>Кол-во: <?= count($data['dealKP']['rows']) ?> |
Сумма счета: <b><?= NumToPrice($data['dealKP']['sum_bill']) ?></b> |
Сумма заказа: <b><?= NumToPrice($data['dealKP']['sum_order']) ?></b></p>
<hr>
<h6>Приобретено</h6>
<p>Кол-во: <?= count($data['group1']['rows']) ?> |
Сумма счета: <b><?= NumToPrice($data['group1']['sum_bill']) ?></b> |
Сумма заказа: <b><?= NumToPrice($data['group1']['sum_order']) ?></b></p>
<hr>
<h6>Не приобретено</h6>
<p>Кол-во: <?= count($data['group2']['rows']) ?> |
Сумма счета: <b><?= NumToPrice($data['group2']['sum_bill']) ?></b> |
Сумма заказа: <b><?= NumToPrice($data['group2']['sum_order']) ?></b></p>
<hr>
<h6>В работе</h6>
<p>Кол-во: <?= count($data['group3']['rows']) ?> |
Сумма счета: <b><?= NumToPrice($data['group3']['sum_bill']) ?></b> |
Сумма заказа: <b><?= NumToPrice($data['group3']['sum_order']) ?></b></p>
</div>
</div>
<!-- === CHARTS === -->
<div class="card shadow-sm mb-4">
<div class="card-header bg-white"><h5>Диаграмма групп</h5></div>
<div class="card-body">
<canvas id="chartGroups"></canvas>
</div>
</div>
<div class="card shadow-sm mb-4">
<div class="card-header bg-white"><h5>Кварталы</h5></div>
<div class="card-body">
<canvas id="chartQuarters"></canvas>
</div>
</div>
<div class="card shadow-sm mb-4">
<div class="card-header bg-white"><h5>Статус за неделю</h5></div>
<div class="card-body">
<canvas id="chartWeek"></canvas>
</div>
</div>
</div>
<script>
/******** PIE — groups ********/
//new Chart(document.getElementById("chartGroups"), {
const chartGroups = document.getElementById("chartGroups");
const chartGP = new Chart(chartGroups, {
type: "pie",
data: {
labels: ["КП отправлено", "Приобретено", "Не приобретено", "В работе"],
datasets: [{
data: [
<?= count($data['dealKP']['rows']) ?>,
<?= count($data['group1']['rows']) ?>,
<?= count($data['group2']['rows']) ?>,
<?= count($data['group3']['rows']) ?>
],
sumBill: [
'<?= NumToPrice($data['dealKP']['sum_bill']) ?>',
"<?= NumToPrice($data['group1']['sum_bill']) ?>",
"<?= NumToPrice($data['group2']['sum_bill']) ?>",
"<?= NumToPrice($data['group3']['sum_bill']) ?>"
],
sumOrder: [
'<?= NumToPrice($data['dealKP']['sum_order']) ?>',
"<?= NumToPrice($data['group1']['sum_order']) ?>",
"<?= NumToPrice($data['group2']['sum_order']) ?>",
"<?= NumToPrice($data['group3']['sum_order']) ?>"
],
backgroundColor: ['#6de3c7',"#ffa500","#ff0000","#79c4f7"]
}]
},
options: {
plugins: {
tooltip: {
mode: 'index',
intersect: false,
callbacks: {
label: function(context) {
const total = context.dataset.data.reduce((a, b) => a + b, 0);
const value = context.raw;
const percent = ((value / total) * 100).toFixed(1);
let sum_bill = context.dataset.sumBill[context.dataIndex];
let sum_order = context.dataset.sumOrder[context.dataIndex];
//return
${context.label}: ${value} (${percent}%) ;
return ${value} (${percent}%) / Счет: ${sum_bill} ₽ | Сумма: ${sum_order} ₽
}
}
}
},
responsive: true,
maintainAspectRatio: false
}
});
/******** BAR — quarters ********/
new Chart(document.getElementById("chartQuarters"), {
type: "bar",
data: {
labels: ["Q1","Q2","Q3","Q4"],
datasets: [{
label: "Сумма заказов",
data: [
<?= $quarters['Q1'] ?>,
<?= $quarters['Q2'] ?>,
<?= $quarters['Q3'] ?>,
<?= $quarters['Q4'] ?>
],
backgroundColor: "#007bff"
}]
}
});
/******** BAR — week stats ********/
new Chart(document.getElementById("chartWeek"), {
type: "bar",
data: {
labels: ["Статус 150", "Статус 100"],
datasets: [{
label: "Количество",
data: [
<?= $weekStats['s150'] ?>,
<?= $weekStats['s100'] ?>
],
backgroundColor: ["#28a745","#ffc107"]
}]
}
});
</script>
</body>
</html>