- URL 하드코딩 → .env APP_URL 기반 동적 URL로 변경 - DB 연결 하드코딩 → .env 기반으로 변경 - MySQL strict mode DATE 오류 수정
471 lines
17 KiB
PHP
471 lines
17 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;
|
|
}
|
|
$title_message = '연차 관리자모드';
|
|
$tablename = 'almember';
|
|
|
|
include $_SERVER['DOCUMENT_ROOT'] . '/load_header.php';
|
|
?>
|
|
|
|
<title><?= $title_message ?></title>
|
|
|
|
<body>
|
|
<?php if($mycompany ==='경동')
|
|
require_once($_SERVER['DOCUMENT_ROOT'] . '/myheader.php');
|
|
else
|
|
require_once($_SERVER['DOCUMENT_ROOT'] . '/myheader1.php');
|
|
?>
|
|
</head>
|
|
|
|
<?php
|
|
require_once($_SERVER['DOCUMENT_ROOT'] . "/common.php");
|
|
|
|
// 테스트 예제
|
|
// $fiscalYearEnd = "2024-12-31"; // 현재 기준 회계년도말
|
|
// 현재 연도를 가져온 후, 이전 연도의 마지막 날을 생성
|
|
// $fiscalYearEnd = (date('Y') - 1) . "-12-31";
|
|
|
|
// // 입사일 배열
|
|
// $hireDates = [
|
|
// "2024-12-2", "2024-12-5", "2024-11-21", "2024-6-17", "2022-6-8",
|
|
// "2022-10-11", "2022-10-17", "2020-3-6", "2020-8-1", "2021-1-7",
|
|
// "2021-1-25", "2021-3-22", "2021-6-24", "2021-9-13", "2021-10-1",
|
|
// "2020-5-1", "2019-4-1", "2019-12-9", "2023-3-6", "2017-11-1",
|
|
// "2023-4-3", "2016-11-14", "2015-7-14", "2024-4-9", "2023-7-3",
|
|
// "2023-7-24", "2023-8-1", "2023-8-1", "2024-3-4", "2023-9-1",
|
|
// "2024-2-5"
|
|
// ];
|
|
|
|
// foreach ($hireDates as $hireDate) {
|
|
// $result = calculateAnnualLeave($hireDate, $fiscalYearEnd);
|
|
// echo "입사일: $hireDate, 근속연수: {$result['G']}, 최초1,2년미만 가산: {$result['H']}, 년도별 연차일수: {$result['I']}, 총발생일수: {$result['J']}<br>";
|
|
// }
|
|
|
|
require_once($_SERVER['DOCUMENT_ROOT'] . "/lib/mydb.php");
|
|
$pdo = db_connect();
|
|
|
|
// 검색 조건 변수 추가
|
|
$mode = isset($_REQUEST["mode"]) ? $_REQUEST["mode"] : "";
|
|
$search = isset($_REQUEST["search"]) ? $_REQUEST["search"] : "";
|
|
$corpSearch = isset($_REQUEST["corpSearch"]) ? $_REQUEST["corpSearch"] : $mycompany ;
|
|
$partSearch = isset($_REQUEST["partSearch"]) ? $_REQUEST["partSearch"] : "";
|
|
|
|
|
|
$year = isset($_REQUEST["year"]) ? $_REQUEST["year"] : date("Y");
|
|
$showRetired = isset($_POST['showRetired']) ? $_POST['showRetired'] : 0;
|
|
|
|
// JSON 파일에서 소속 및 부서 데이터 로드
|
|
$corpFile = $_SERVER['DOCUMENT_ROOT'] . '/member/corp.json';
|
|
$corpData = file_exists($corpFile) ? json_decode(file_get_contents($corpFile), true) : [];
|
|
if (!is_array($corpData)) $corpData = [];
|
|
|
|
$partFile = $_SERVER['DOCUMENT_ROOT'] . '/member/part.json';
|
|
$partData = file_exists($partFile) ? json_decode(file_get_contents($partFile), true) : [];
|
|
if (!is_array($partData)) $partData = [];
|
|
|
|
// 기본 SQL 조건
|
|
$conditions = ["referencedate = :year", "is_deleted IS NULL"];
|
|
$bindParams = [':year' => $year];
|
|
|
|
if (!$showRetired) {
|
|
$conditions[] = "(comment IS NULL OR comment = '')";
|
|
} else {
|
|
$conditions[] = "comment = '퇴사'";
|
|
}
|
|
|
|
// 검색 조건 추가
|
|
if ($mode == "search") {
|
|
if (!empty($search)) {
|
|
$columns = [];
|
|
$stmt = $pdo->query("SHOW COLUMNS FROM " . $DB . "." . $tablename);
|
|
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
|
$columns[] = $row['Field'];
|
|
}
|
|
$searchConditions = [];
|
|
foreach ($columns as $index => $col) {
|
|
$paramName = ":search{$index}";
|
|
$searchConditions[] = "$col LIKE $paramName";
|
|
$bindParams[$paramName] = "%$search%";
|
|
}
|
|
$conditions[] = "(" . implode(" OR ", $searchConditions) . ")";
|
|
}
|
|
if (!empty($corpSearch)) {
|
|
$conditions[] = "company LIKE :corpSearch";
|
|
$bindParams[":corpSearch"] = "%$corpSearch%";
|
|
}
|
|
if (!empty($partSearch)) {
|
|
$conditions[] = "part LIKE :partSearch";
|
|
$bindParams[":partSearch"] = "%$partSearch%";
|
|
}
|
|
}
|
|
|
|
// almember의 기본정보 배열을 불러옴 (예, $basic_name_arr, $basic_part_arr 등)
|
|
require_once($_SERVER['DOCUMENT_ROOT'] . "/almember/load_DB.php");
|
|
|
|
// echo '<pre>';
|
|
// print_r($previous_year_usage_arr);
|
|
// echo '</pre>';
|
|
|
|
$sql = "SELECT * FROM {$DB}.almember WHERE " . implode(" AND ", $conditions) . " ORDER BY referencedate DESC, dateofentry ASC, num DESC";
|
|
$stmh = $pdo->prepare($sql);
|
|
$stmh->execute($bindParams);
|
|
$total_row = $stmh->rowCount();
|
|
|
|
// print $admin;
|
|
|
|
?>
|
|
|
|
|
|
<form name="board_form" id="board_form" method="post" action="admin.php?mode=search">
|
|
<input type="hidden" id="ALadmin" name="ALadmin" value="<?=$ALadmin?>">
|
|
<div class="container">
|
|
<div class="card mt-2 mb-4">
|
|
<div class="card-body">
|
|
<div class="d-flex mt-3 mb-3 justify-content-center align-items-center">
|
|
<span class="text-dark fs-5" > <?=$title_message?> </span>
|
|
<button type="button" class="btn btn-dark btn-sm mx-2" onclick='location.reload()'> <i class="bi bi-arrow-clockwise"></i> </button>
|
|
<button type="button" id="backBtn" class="btn btn-outline-primary btn-sm mx-2" > <ion-icon name="caret-back-circle-outline"></ion-icon> 이전화면 </button>
|
|
</div>
|
|
<div class="d-flex mt-3 mb-3 justify-content-center align-items-center">
|
|
<span class="text-secondary fs-6" > 주일/경동 연차는 (회계년도말) 기준으로 산정한다. </span>
|
|
</div>
|
|
<div class="d-flex mt-3 justify-content-center align-items-center">
|
|
<i class="bi bi-caret-right"></i> <?= $total_row ?>개
|
|
<!-- 퇴사자 체크박스 -->
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="showRetired" name="showRetired" value=1 onchange="filterRetired()" <?php echo isset($_POST['showRetired']) && $_POST['showRetired'] == 1 ? 'checked' : ''; ?>>
|
|
<label class="form-check-label mx-2" for="showRetired">퇴사자 보기</label>
|
|
</div>
|
|
|
|
<span class="mx-1"> 선택년도</span>
|
|
<select name="year" id="year" class="form-select w80px mx-1" style="font-size: 0.8rem; height: 32px;">
|
|
<?php
|
|
$current_year = date("Y"); // 현재 년도를 얻습니다.
|
|
$year_arr = array(); // 빈 배열을 생성합니다.
|
|
|
|
for ($i = 0; $i < 3; $i++) {
|
|
$year_arr[] = $current_year - $i;
|
|
}
|
|
for($i=0;$i<count($year_arr);$i++) {
|
|
if($year==$year_arr[$i])
|
|
print "<option selected value='" . $year_arr[$i] . "'> " . $year_arr[$i] . "</option>";
|
|
else
|
|
print "<option value='" . $year_arr[$i] . "'> " . $year_arr[$i] . "</option>";
|
|
}
|
|
?>
|
|
</select>
|
|
|
|
<!-- 소속 검색 select 추가 -->
|
|
<div class="inputWrap30 mx-1">
|
|
<select name="corpSearch" id="corpSearch" class="form-select w-auto mx-1" style="font-size: 0.8rem; height: 32px;">
|
|
<option value=""><?= "(소속)" ?></option>
|
|
<?php foreach($corpData as $corp): ?>
|
|
<option value="<?= htmlspecialchars($corp, ENT_QUOTES, 'UTF-8') ?>" <?= ($corpSearch === $corp) ? 'selected' : '' ?>>
|
|
<?= htmlspecialchars($corp, ENT_QUOTES, 'UTF-8') ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
<!-- 부서 검색 select 추가 -->
|
|
<div class="inputWrap30 mx-1">
|
|
<select name="partSearch" id="partSearch" class="form-select w-auto mx-1" style="font-size: 0.8rem; height: 32px;">
|
|
<option value=""><?= "(부서)" ?></option>
|
|
<!-- 옵션은 JS에서 동적으로 채워짐 -->
|
|
</select>
|
|
</div>
|
|
|
|
<input type="text" name="search" id="search" class="form-control mx-1" style="width:150px; height: 32px;" value="<?=$search?>" onkeydown="JavaScript:SearchEnter();" placeholder="검색어" autocomplete="off" >
|
|
|
|
<button type="button" id="searchBtn" class="btn btn-dark btn-sm mx-1" > <i class="bi bi-search"></i> 검색 </button>
|
|
<?php if (intval($ALadmin) == 1 ) { ?>
|
|
<button type="button" class="btn btn-dark btn-sm mx-1" onclick="popupCenter('write_form.php', '신규', 600, 400);return false;" > <i class="bi bi-pencil"></i> 신규 </button>
|
|
<button type="button" class="btn btn-dark btn-sm mx-1" id="csvDownload" > <i class="bi bi-floppy-fill"></i> CSV </button>
|
|
<button type="button" id="massBtn" class="btn btn-sm btn-primary mx-1"> <i class="bi bi-cloud-arrow-up"></i> 대량등록</button>
|
|
<?php } ?>
|
|
|
|
</div>
|
|
<div class="row d-flex mt-3 mb-1 justify-content-center align-items-center">
|
|
<table class="table table-hover" id="myTable">
|
|
<thead class="table-primary">
|
|
<tr>
|
|
<th class="text-center">번호</th>
|
|
<th class="text-center">구분</th>
|
|
<th class="text-center">성명</th>
|
|
<th class="text-center">회사</th>
|
|
<th class="text-center">파트</th>
|
|
<th class="text-center">입사일</th>
|
|
<th class="text-center">해당연도</th>
|
|
<th class="text-center">근속년</th>
|
|
<th class="text-center">1~2년미만 가산</th>
|
|
<th class="text-center">근속년수별</th>
|
|
<th class="text-center">발생일합</th>
|
|
<th class="text-center">전년도 선사용</th>
|
|
<th class="text-center">사용일 합계</th>
|
|
<th class="text-center">잔여일</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php
|
|
$start_num = $total_row;
|
|
while ($row = $stmh->fetch(PDO::FETCH_ASSOC)) {
|
|
include "_row.php";
|
|
|
|
// 년도를 추출하여 -1을 적용
|
|
// 문자열 연결 연산자 `.` 추가
|
|
$fiscalYearEnd = ($referencedate - 1) . "-12-31";
|
|
// echo '참고년도 : ' . $referencedate ;
|
|
// echo '전년도 : ' . $fiscalYearEnd ;
|
|
$result = calculateAnnualLeave($dateofentry, $fiscalYearEnd);
|
|
$continueYear = $result['G'];
|
|
$initial_less_than_one_year = $result['H'];
|
|
$service_based = $result['I'];
|
|
$availableday = $result['J'];
|
|
|
|
$totalusedday = 0;
|
|
$totalremainday = isset($availableday) ? $availableday : 0;
|
|
|
|
if (isset($totalname_arr) && is_array($totalname_arr) && count($totalname_arr) > 0) {
|
|
for ($i = 0; $i < count($totalname_arr); $i++) {
|
|
if (trim($name) == trim($totalname_arr[$i]) && $referencedate == $totalusedYear_arr[$i]) {
|
|
$totalusedday = $totalused_arr[$i];
|
|
$previous_year_usage = $previous_year_usage_arr[$i];
|
|
$totalremainday = $availableday - $totalusedday - $previous_year_usage;
|
|
}
|
|
}
|
|
}
|
|
|
|
?>
|
|
<tr onclick="redirectToView('<?= $row['num'] ?>', '<?= $tablename ?>')">
|
|
<td class="text-center"><?=$start_num?> </td>
|
|
<td class="text-center"><?=$comment?> </td>
|
|
<td class="text-center"><?=$name?> </td>
|
|
<td class="text-center"><?=$company?> </td>
|
|
<td class="text-center"><?=$part?> </td>
|
|
<td class="text-center"><?=$dateofentry?> </td>
|
|
<td class="text-center"><?=$referencedate?> </td>
|
|
<td class="text-center"><?= $continueYear ? $continueYear : '' ?> </td>
|
|
<td class="text-center text-dark"><?= $initial_less_than_one_year ? $initial_less_than_one_year : '' ?> </td>
|
|
<td class="text-center text-secondary"><b><?= $service_based ? $service_based : '' ?></b> </td>
|
|
<td class="text-center text-primary"><b><?= $availableday ? $availableday : '' ?></b> </td>
|
|
<td class="text-center "> <?= $previous_year_usage ? '<h6> <span class="badge bg-primary"> ' . $previous_year_usage . ' </span> </h6> ' : '' ?> </td>
|
|
<td class="text-center text-success"><b><?= $totalusedday ? $totalusedday : '' ?></b> </td>
|
|
<td class="text-center <?= ($totalremainday < 0) ? 'text-danger' : 'text-dark' ?>">
|
|
<b><?= $totalremainday ?: '' ?></b>
|
|
</td>
|
|
</tr>
|
|
<?php
|
|
$start_num--;
|
|
}
|
|
?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
<br>
|
|
<br>
|
|
<div class="container">
|
|
<? include '../footer.php'; ?>
|
|
</div>
|
|
|
|
<!-- 페이지로딩 -->
|
|
<script>
|
|
$(document).ready(function(){
|
|
var loader = document.getElementById('loadingOverlay');
|
|
loader.style.display = 'none';
|
|
});
|
|
</script>
|
|
|
|
<script>
|
|
var dataTable; // DataTables 인스턴스 전역 변수
|
|
var aladminpageNumber; // 현재 페이지 번호 저장을 위한 전역 변수
|
|
|
|
$(document).ready(function() {
|
|
// DataTables 초기 설정
|
|
dataTable = $('#myTable').DataTable({
|
|
"paging": true,
|
|
"ordering": true,
|
|
"searching": false,
|
|
"pageLength": 50,
|
|
"lengthMenu": [25, 50, 100, 200, 500, 1000],
|
|
"language": {
|
|
"lengthMenu": "Show _MENU_ entries",
|
|
"search": "Live Search:"
|
|
},
|
|
"order": [[0, 'desc']]
|
|
});
|
|
|
|
// 페이지 번호 복원 (초기 로드 시)
|
|
var savedPageNumber = getCookie('aladminpageNumber');
|
|
if (savedPageNumber) {
|
|
dataTable.page(parseInt(savedPageNumber) - 1).draw(false);
|
|
}
|
|
|
|
// 페이지 변경 이벤트 리스너
|
|
dataTable.on('page.dt', function() {
|
|
var aladminpageNumber = dataTable.page.info().page + 1;
|
|
setCookie('aladminpageNumber', aladminpageNumber, 10); // 쿠키에 페이지 번호 저장
|
|
});
|
|
|
|
// 페이지 길이 셀렉트 박스 변경 이벤트 처리
|
|
$('#myTable_length select').on('change', function() {
|
|
var selectedValue = $(this).val();
|
|
dataTable.page.len(selectedValue).draw(); // 페이지 길이 변경 (DataTable 파괴 및 재초기화 없이)
|
|
|
|
// 변경 후 현재 페이지 번호 복원
|
|
savedPageNumber = getCookie('aladminpageNumber');
|
|
if (savedPageNumber) {
|
|
dataTable.page(parseInt(savedPageNumber) - 1).draw(false);
|
|
}
|
|
});
|
|
});
|
|
|
|
function restorePageNumber() {
|
|
var savedPageNumber = getCookie('aladminpageNumber');
|
|
if (savedPageNumber) {
|
|
dataTable.page(parseInt(savedPageNumber) - 1).draw('page');
|
|
}
|
|
}
|
|
|
|
function SearchEnter(){
|
|
if(event.keyCode == 13){
|
|
document.getElementById('board_form').submit();
|
|
}
|
|
}
|
|
|
|
$(document).ready(function(){
|
|
$('select[name="year"]').change(function(){
|
|
var val = $('input[name="year"]:checked').val();
|
|
document.getElementById('board_form').submit();
|
|
});
|
|
|
|
$("#closeModalBtn").click(function(){
|
|
$('#myModal').modal('hide');
|
|
});
|
|
|
|
$("#searchBtn").click(function(){
|
|
document.getElementById('board_form').submit();
|
|
});
|
|
|
|
$("#backBtn").click(function(){
|
|
location.href='/annualleave/index.php';
|
|
});
|
|
|
|
$("#massBtn").click(function(){
|
|
popupCenter('write_form_init.php', '연초 대량등록', 420, 800);
|
|
});
|
|
});
|
|
|
|
function redirectToView(num, tablename) {
|
|
var ALadmin = document.getElementById("ALadmin").value; // hidden input의 값 가져오기
|
|
|
|
if (ALadmin != "1") {
|
|
Swal.fire({
|
|
title: '접근 제한',
|
|
text: '관리자만 수정이 가능합니다.',
|
|
icon: 'warning',
|
|
confirmButtonText: '확인'
|
|
});
|
|
return; // 함수 실행 중지
|
|
}
|
|
|
|
var url = "write_form.php?mode=modify&num=" + num + "&tablename=" + tablename;
|
|
customPopup(url, '연차 수정', 600, 400);
|
|
}
|
|
|
|
|
|
document.getElementById("csvDownload").addEventListener("click", function() {
|
|
const table = document.getElementById("myTable");
|
|
const theadRow = table.querySelector("thead tr");
|
|
const rows = table.querySelectorAll("tbody tr");
|
|
|
|
const csvRows = [];
|
|
|
|
// Include the header row
|
|
const headerData = [];
|
|
theadRow.querySelectorAll("th").forEach(function(cell) {
|
|
headerData.push(cell.textContent);
|
|
});
|
|
csvRows.push(headerData.join(","));
|
|
|
|
// Include the data rows
|
|
rows.forEach(function(row) {
|
|
const rowData = [];
|
|
row.querySelectorAll("td").forEach(function(cell) {
|
|
rowData.push(cell.textContent);
|
|
});
|
|
csvRows.push(rowData.join(","));
|
|
});
|
|
|
|
const csvContent = csvRows.join("\n");
|
|
// 한글깨짐문제 '\ufeff' + data 이것 참조
|
|
const blob = new Blob(['\ufeff' + csvContent], { type: "text/csv;charset=utf-8;" });
|
|
const link = document.createElement("a");
|
|
link.href = URL.createObjectURL(blob);
|
|
link.setAttribute("download", "직원연차.csv");
|
|
document.body.appendChild(link);
|
|
link.click();
|
|
});
|
|
|
|
function filterRetired() {
|
|
// 퇴사자 체크박스 상태 확인
|
|
// const showRetired = document.getElementById('showRetired').checked;
|
|
document.getElementById('board_form').submit();
|
|
|
|
}
|
|
|
|
$(document).ready(function(){
|
|
var title = '<?=$title_message;?>';
|
|
saveMenuLog(title);
|
|
});
|
|
|
|
</script>
|
|
|
|
<script>
|
|
$(document).ready(function(){
|
|
// PHP의 부서 JSON 데이터를 JS 변수로 저장 (각 항목은 ['corp'=> ..., 'part'=> ...] 형식)
|
|
var partData = <?= json_encode($partData) ?>;
|
|
|
|
// PHP에서 전달된 부서 검색 값 (기존에 선택된 값)
|
|
var initialPart = "<?= htmlspecialchars($partSearch, ENT_QUOTES, 'UTF-8') ?>";
|
|
|
|
// 부서 select 업데이트 함수
|
|
function updatePartSelect(selectedCorp) {
|
|
var $partSelect = $('#partSearch');
|
|
$partSelect.empty();
|
|
$partSelect.append('<option value=""><?= "(부서)" ?></option>');
|
|
// 선택된 소속과 일치하는 부서 옵션만 추가
|
|
$.each(partData, function(index, dept) {
|
|
if(dept.corp === selectedCorp) {
|
|
$partSelect.append('<option value="'+ dept.part +'">'+ dept.part +'</option>');
|
|
}
|
|
});
|
|
// 만약 초기 부서값이 있다면 선택
|
|
if(initialPart !== "") {
|
|
$partSelect.val(initialPart);
|
|
}
|
|
}
|
|
|
|
// 페이지 로드 시, 이미 소속이 선택되어 있다면 부서 옵션 업데이트
|
|
var initialCorp = $('#corpSearch').val();
|
|
updatePartSelect(initialCorp);
|
|
|
|
// 소속 select 변경 시 부서 select 업데이트
|
|
$('#corpSearch').on('change', function(){
|
|
var selectedCorp = $(this).val();
|
|
updatePartSelect(selectedCorp);
|
|
});
|
|
});
|
|
</script>
|
|
|
|
|
|
</body>
|
|
</html>
|