- URL 하드코딩 → .env APP_URL 기반 동적 URL로 변경 - DB 연결 하드코딩 → .env 기반으로 변경 - MySQL strict mode DATE 오류 수정
339 lines
13 KiB
PHP
339 lines
13 KiB
PHP
<?php
|
|
require_once($_SERVER['DOCUMENT_ROOT'] . "/session.php");
|
|
|
|
if (!isset($_SESSION["level"]) || $_SESSION["level"] > 5) {
|
|
sleep(1);
|
|
header("Location:" . $WebSite . "login/login_form.php");
|
|
exit;
|
|
}
|
|
|
|
include $_SERVER['DOCUMENT_ROOT'] . '/load_header.php';
|
|
$title_message = '현설(탈락,유찰,낙찰) 통계';
|
|
$title_prefix = '현설(탈락,유찰,낙찰) 통계자료';
|
|
?>
|
|
|
|
<title><?= $title_prefix ?> <?= $title_message ?></title>
|
|
</head>
|
|
<body>
|
|
<?php require_once($_SERVER['DOCUMENT_ROOT'] . '/myheader1.php'); // 주일메뉴 ?>
|
|
<?php require_once($_SERVER['DOCUMENT_ROOT'] . '/mymodal.php'); ?>
|
|
|
|
<?php
|
|
require_once($_SERVER['DOCUMENT_ROOT'] . "/lib/mydb.php");
|
|
$pdo = db_connect();
|
|
|
|
// $monthAgo = date("Y-m-d", strtotime("-1 month"));
|
|
$today = date("Y-m-d");
|
|
$todate = date("Y-m-d");
|
|
$monthAgo = date("Y-01-01"); // 현재 년도의 1월 1일
|
|
|
|
$tablename = 'bid';
|
|
$fromdate = isset($_REQUEST['fromdate']) && $_REQUEST['fromdate'] ? $_REQUEST['fromdate'] : $monthAgo;
|
|
$transtodate = date("Y-m-d", strtotime($todate . '+1 day'));
|
|
$todate = isset($_REQUEST['todate']) ? $_REQUEST['todate'] : date("Y-m-t");
|
|
|
|
try {
|
|
// SQL: secondordnum을 그룹화하고 siteresult별 개수 집계
|
|
$sql = "SELECT secondordnum, secondord, siteresult, COUNT(*) as count
|
|
FROM {$DB}.{$tablename}
|
|
WHERE siteDate BETWEEN :fromdate AND :todate AND is_deleted IS NULL
|
|
GROUP BY secondordnum, siteresult
|
|
ORDER BY secondordnum";
|
|
|
|
$stmh = $pdo->prepare($sql);
|
|
$stmh->bindValue(':fromdate', $fromdate);
|
|
$stmh->bindValue(':todate', $todate);
|
|
$stmh->execute();
|
|
$rows = $stmh->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
// 시공사별 데이터 가공
|
|
$data = [];
|
|
foreach ($rows as $row) {
|
|
$company = $row['secondord'] . '(' . $row['secondordnum'] . ')'; // 시공사 코드
|
|
$result = $row['siteresult']; // 낙찰/유찰/탈락
|
|
$count = $row['count'];
|
|
|
|
if (!isset($data[$company])) {
|
|
$data[$company] = ["탈락" => 0, "유찰" => 0, "낙찰" => 0];
|
|
}
|
|
$data[$company][$result] = (int) $count;
|
|
}
|
|
|
|
// JSON 변환
|
|
$chartData = [];
|
|
foreach ($data as $company => $values) {
|
|
$chartData[] = [
|
|
"name" => $company,
|
|
"data" => [$values["탈락"], $values["유찰"], $values["낙찰"]]
|
|
];
|
|
}
|
|
|
|
$jsonChartData = json_encode($chartData, JSON_UNESCAPED_UNICODE);
|
|
|
|
} catch (PDOException $Exception) {
|
|
die("오류: " . $Exception->getMessage());
|
|
}
|
|
|
|
// echo '<pre>';
|
|
// print_r($data);
|
|
// echo '</pre>';
|
|
|
|
// 기존 집계 결과($data)를 이용해 각 시공사의 비율 데이터 계산
|
|
$rateChartData = [];
|
|
foreach ($data as $company => $values) {
|
|
$total = array_sum($values);
|
|
if ($total > 0) {
|
|
$failure_rate = round($values["탈락"] / $total * 100, 2);
|
|
$bidding_fail_rate = round($values["유찰"] / $total * 100, 2);
|
|
$win_rate = round($values["낙찰"] / $total * 100, 2);
|
|
} else {
|
|
$failure_rate = $bidding_fail_rate = $win_rate = 0;
|
|
}
|
|
$rateChartData[] = [
|
|
"name" => $company,
|
|
"data" => [$failure_rate, $bidding_fail_rate, $win_rate]
|
|
];
|
|
}
|
|
|
|
$jsonRateChartData = json_encode($rateChartData, JSON_UNESCAPED_UNICODE);
|
|
|
|
// 기존 집계 결과($data)를 이용해 각 시공사의 비율 데이터 계산 (개별 차트용)
|
|
$companyCharts = [];
|
|
foreach ($data as $company => $values) {
|
|
$total = array_sum($values);
|
|
if ($total > 0) {
|
|
$failure_rate = round($values["탈락"] / $total * 100, 2);
|
|
$bidding_fail_rate = round($values["유찰"] / $total * 100, 2);
|
|
$win_rate = round($values["낙찰"] / $total * 100, 2);
|
|
} else {
|
|
$failure_rate = $bidding_fail_rate = $win_rate = 0;
|
|
}
|
|
$companyCharts[$company] = [
|
|
"name" => $company, // 시공사 코드 또는 시공사명을 저장 (원하는 값으로 수정 가능)
|
|
"data" => [$failure_rate, $bidding_fail_rate, $win_rate]
|
|
];
|
|
}
|
|
|
|
$jsonCompanyCharts = json_encode($companyCharts, JSON_UNESCAPED_UNICODE);
|
|
|
|
?>
|
|
<form id="board_form" name="board_form" method="post" action="statistics.php?mode=search">
|
|
<input type="hidden" id="active_tab" name="active_tab" value="<?= $active_tab ?>">
|
|
<div class="container mt-3 mb-5">
|
|
<div class="card mb-2 mt-2">
|
|
<div class="card-body">
|
|
<div class="d-flex p-1 m-1 mt-1 mb-3 justify-content-center align-items-center">
|
|
<h5><?= $title_message ?></h5>
|
|
<button type="button" class="btn btn-dark btn-sm mx-3" onclick='location.reload();' title="새로고침"> <i class="bi bi-arrow-clockwise"></i> </button>
|
|
</div>
|
|
|
|
<div class="d-flex p-1 m-1 mt-1 mb-1 justify-content-center align-items-center">
|
|
<span id="showdate" class="btn btn-dark btn-sm"> 기간 </span>
|
|
<div id="showframe" class="card" style="width:500px;">
|
|
<div class="card-header " style="padding:2px;">
|
|
<div class="d-flex justify-content-center align-items-center">
|
|
기간 설정
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="d-flex justify-content-center align-items-center">
|
|
<button type="button" class="btn btn-outline-success btn-sm me-1 change_dateRange" onclick='alldatesearch()' > 전체 </button>
|
|
<button type="button" id="preyear" class="btn btn-outline-primary btn-sm me-1 change_dateRange" onclick='pre_year()' > 전년도 </button>
|
|
<button type="button" id="three_month" class="btn btn-dark btn-sm me-1 change_dateRange" onclick='three_month_ago()' > M-3월 </button>
|
|
<button type="button" id="prepremonth" class="btn btn-dark btn-sm me-1 change_dateRange" onclick='prepre_month()' > 전전월 </button>
|
|
<button type="button" id="premonth" class="btn btn-dark btn-sm me-1 change_dateRange" onclick='pre_month()' > 전월 </button>
|
|
<button type="button" class="btn btn-outline-danger btn-sm me-1 change_dateRange" onclick='this_today()' > 오늘 </button>
|
|
<button type="button" id="thismonth" class="btn btn-dark btn-sm me-1 change_dateRange" onclick='this_month()' > 당월 </button>
|
|
<button type="button" id="thisyear" class="btn btn-dark btn-sm me-1 change_dateRange" onclick='this_year()' > 당해년도 </button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<input type="date" id="fromdate" name="fromdate" class="form-control" style="width:100px;" value="<?= $fromdate ?>"> ~
|
|
<input type="date" id="todate" name="todate" class="form-control me-1" style="width:100px;" value="<?= $todate ?>">
|
|
<input type="hidden" id="search" name="search" value="<?= $search ?>" onkeydown="JavaScript:SearchEnter();" autocomplete="off" class="form-control" style="width:200px;">
|
|
<button id="searchBtn" type="button" class="btn btn-dark btn-sm"><i class="bi bi-search"></i> 검색 </button>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
|
|
<!-- 부트스트랩 테이블 영역 -->
|
|
<div class="container mt-4">
|
|
<div class="card">
|
|
<div class="card-header text-center">
|
|
<h5>시공사별 입찰 결과 건수 및 비율</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<table class="table table-bordered table-striped">
|
|
<thead>
|
|
<tr>
|
|
<th>시공사</th>
|
|
<th>탈락 건수</th>
|
|
<th>탈락 비율 (%)</th>
|
|
<th>유찰 건수</th>
|
|
<th>유찰 비율 (%)</th>
|
|
<th>낙찰 건수</th>
|
|
<th>낙찰 비율 (%)</th>
|
|
<th>총 건수</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($data as $company => $values): ?>
|
|
<?php $total = array_sum($values); ?>
|
|
<tr>
|
|
<td><?= htmlspecialchars($company) ?></td>
|
|
<td><?= $values["탈락"] ?></td>
|
|
<td><?= $total > 0 ? round($values["탈락"] / $total * 100, 2) : 0 ?>%</td>
|
|
<td><?= $values["유찰"] ?></td>
|
|
<td><?= $total > 0 ? round($values["유찰"] / $total * 100, 2) : 0 ?>%</td>
|
|
<td><?= $values["낙찰"] ?></td>
|
|
<td><?= $total > 0 ? round($values["낙찰"] / $total * 100, 2) : 0 ?>%</td>
|
|
<td><?= $total ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<!-- 그래프 출력 -->
|
|
<div class="container mt-4">
|
|
<div class="card">
|
|
<div class="card-header text-center">
|
|
<h5>시공사별 입찰 결과 통계</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div id="bidChart" style="height: 500px;"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 시공사별 입찰 결과 비율 차트 출력 -->
|
|
<div class="container mt-4">
|
|
<div class="card">
|
|
<div class="card-header text-center">
|
|
<h5>시공사별 입찰 결과 비율 (%)</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div id="rateChart" style="height: 500px;"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 시공사별 입찰 결과 비율 (개별 차트) -->
|
|
<div class="container mt-4">
|
|
<div class="card">
|
|
<div class="card-header text-center">
|
|
<h5>시공사별 입찰 결과 비율 (개별 차트)</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<?php foreach($companyCharts as $company => $chartData): ?>
|
|
<div id="chart_<?= htmlspecialchars($company) ?>" style="height: 300px; margin-bottom: 30px;"></div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<script>
|
|
$(document).ready(function(){
|
|
var loader = document.getElementById('loadingOverlay');
|
|
if(loader)
|
|
loader.style.display = 'none';
|
|
});
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// 전체 건수 차트 (기존)
|
|
const chartData = <?= $jsonChartData ?>;
|
|
Highcharts.chart('bidChart', {
|
|
chart: { type: 'bar' },
|
|
title: { text: '' },
|
|
xAxis: {
|
|
categories: ['탈락', '유찰', '낙찰'],
|
|
title: { text: '입찰 결과 유형' }
|
|
},
|
|
yAxis: {
|
|
min: 0,
|
|
title: { text: '건수' }
|
|
},
|
|
tooltip: {
|
|
shared: true,
|
|
pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b> 건<br/>',
|
|
useHTML: true
|
|
},
|
|
series: chartData
|
|
});
|
|
|
|
// 시공사별 비율 차트
|
|
const rateChartData = <?= $jsonRateChartData ?>;
|
|
Highcharts.chart('rateChart', {
|
|
chart: { type: 'bar' },
|
|
title: { text: '' },
|
|
xAxis: {
|
|
categories: ['탈락율', '유찰율', '낙찰율'],
|
|
title: { text: '입찰 결과 비율 (%)' }
|
|
},
|
|
yAxis: {
|
|
min: 0,
|
|
max: 100,
|
|
title: { text: '비율 (%)' }
|
|
},
|
|
tooltip: {
|
|
shared: true,
|
|
pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}%</b><br/>',
|
|
useHTML: true
|
|
},
|
|
series: rateChartData
|
|
});
|
|
});
|
|
</script>
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const companyCharts = <?= $jsonCompanyCharts ?>;
|
|
|
|
// 각 회사별 차트를 순회하며 생성
|
|
for (let company in companyCharts) {
|
|
let chartData = companyCharts[company];
|
|
Highcharts.chart('chart_' + company, {
|
|
chart: { type: 'bar' },
|
|
title: { text: chartData.name + ' 입찰 결과 비율 (%)' },
|
|
xAxis: {
|
|
categories: ['탈락율', '유찰율', '낙찰율'],
|
|
title: { text: '입찰 결과 유형 (%)' }
|
|
},
|
|
yAxis: {
|
|
min: 0,
|
|
max: 100,
|
|
title: { text: '비율 (%)' }
|
|
},
|
|
tooltip: {
|
|
shared: true,
|
|
pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}%</b><br/>',
|
|
useHTML: true
|
|
},
|
|
series: [{
|
|
name: chartData.name,
|
|
data: chartData.data
|
|
}]
|
|
});
|
|
}
|
|
});
|
|
</script>
|
|
|
|
|
|
<script>
|
|
$(document).ready(function(){
|
|
// 방문기록 남김
|
|
var title_message = '<?php echo $title_message ; ?>';
|
|
saveMenuLog(title_message);
|
|
});
|
|
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|