- URL 하드코딩 → .env APP_URL 기반 동적 URL로 변경 - DB 연결 하드코딩 → .env 기반으로 변경 - MySQL strict mode DATE 오류 수정
456 lines
14 KiB
PHP
456 lines
14 KiB
PHP
<?php
|
|
require_once($_SERVER['DOCUMENT_ROOT'] . "/session.php");
|
|
|
|
$title_message = '연차 신청';
|
|
|
|
include $_SERVER['DOCUMENT_ROOT'] . '/load_header.php';
|
|
|
|
$tablename = "eworks";
|
|
|
|
isset($_REQUEST["num"]) ? $num=$_REQUEST["num"] : $num='';
|
|
require_once($_SERVER['DOCUMENT_ROOT'] . "/lib/mydb.php");
|
|
$pdo = db_connect();
|
|
|
|
try{
|
|
$sql = "select * from " . $DB . "." . $tablename . " where num = ? ";
|
|
$stmh = $pdo->prepare($sql);
|
|
$stmh->bindValue(1,$num,PDO::PARAM_STR);
|
|
$stmh->execute();
|
|
$count = $stmh->rowCount();
|
|
$row = $stmh->fetch(PDO::FETCH_ASSOC); // $row 배열로 DB 정보를 불러온다.
|
|
|
|
include 'rowDBask.php';
|
|
|
|
}catch (PDOException $Exception) {
|
|
print "오류: ".$Exception->getMessage();
|
|
}
|
|
// end of if
|
|
|
|
// 배열로 기본정보 불러옴
|
|
include "load_DB.php";
|
|
|
|
// holiday 테이블에서 휴일 목록 불러오기
|
|
$holidayDates = [];
|
|
try {
|
|
$holidaySql = "SELECT startdate, enddate FROM " . $DB . ".holiday WHERE is_deleted IS NULL";
|
|
$holidayStmt = $pdo->query($holidaySql);
|
|
$holidayRows = $holidayStmt->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
foreach ($holidayRows as $holidayRow) {
|
|
$startdate = $holidayRow['startdate'];
|
|
$enddate = $holidayRow['enddate'];
|
|
|
|
// enddate가 '0000-00-00'이거나 비어있으면 startdate만 휴일
|
|
if (empty($enddate) || $enddate === '0000-00-00' || $enddate === null) {
|
|
$holidayDates[] = $startdate;
|
|
} else {
|
|
// 기간 내의 모든 날짜를 배열에 추가
|
|
$start = new DateTime($startdate);
|
|
$end = new DateTime($enddate);
|
|
$end->modify('+1 day'); // 종료일 포함
|
|
|
|
$period = new DatePeriod($start, new DateInterval('P1D'), $end);
|
|
foreach ($period as $date) {
|
|
$holidayDates[] = $date->format('Y-m-d');
|
|
}
|
|
}
|
|
}
|
|
} catch (PDOException $e) {
|
|
// 오류 발생 시 빈 배열 유지
|
|
error_log("Holiday 데이터 로드 오류: " . $e->getMessage());
|
|
}
|
|
|
|
// print $totalremainday;
|
|
|
|
// 잔여일수 개인별 산출 루틴
|
|
try{
|
|
// 연차 잔여일수 산출
|
|
$totalusedday = 0;
|
|
$totalremainday = 0;
|
|
for($i=0;$i<count($totalname_arr);$i++)
|
|
if($author== $totalname_arr[$i])
|
|
{
|
|
$availableday = $availableday_arr[$i];
|
|
}
|
|
|
|
// 연차 사용일수 계산
|
|
for($i=0;$i<count($totalname_arr);$i++)
|
|
if($author== $totalname_arr[$i])
|
|
{
|
|
$totalusedday = $totalused_arr[$i];
|
|
$totalremainday = $availableday - $totalusedday;
|
|
|
|
}
|
|
|
|
} catch (PDOException $Exception) {
|
|
print "오류: ".$Exception->getMessage();
|
|
}
|
|
|
|
?>
|
|
|
|
<body>
|
|
|
|
<!-- Modal -->
|
|
<div class="modal fade" id="myModal" role="dialog">
|
|
<div class="modal-dialog modal-lg modal-center" >
|
|
|
|
<!-- Modal content-->
|
|
<div class="modal-content modal-lg">
|
|
<div class="modal-header">
|
|
<h4 class="modal-title">알림</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div id=alertmsg class="fs-1 mb-5 justify-content-center" >
|
|
결재가 완료되었습니다. <br>
|
|
<br>
|
|
수고하셨습니다.
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" id="closeModalBtn" class="btn btn-default" data-dismiss="modal">닫기</button>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<div class="container h-60">
|
|
<div class="row d-flex justify-content-center align-items-center h-50">
|
|
<div class="col-12 text-center">
|
|
<div class="card align-middle" style="width:24rem; border-radius:20px;">
|
|
<div class="card" style="padding:10px;margin:10px;">
|
|
<h3 class="card-title text-center" style="color:#113366;"> (연차) 승인</h3>
|
|
</div>
|
|
<div class="card-body text-center">
|
|
<form id="board_form" class="form-signin" method="post" >
|
|
<input type="hidden" id="mode" name="mode">
|
|
<input type="hidden" id="num" name="num" value="<?=$num?>" >
|
|
<input type="hidden" id="registdate" name="registdate" value="<?=$today?>" >
|
|
<input type="hidden" id="al_part" name="al_part" value="<?=$al_part?>" >
|
|
<input type="hidden" id="author_id" name="author_id" value="<?=$author_id?>" >
|
|
<input type="hidden" id="admin_name" name="admin_name" value="<?=$admin_name?>" >
|
|
|
|
<span class="form-control">
|
|
성 명 <input type="text" id="author" name="author" size=8 class="text-center" readonly value="<?=$author?>" >
|
|
</span>
|
|
<span class="form-control">
|
|
선택
|
|
<?php
|
|
// 연차종류 4종류로 만듬
|
|
$item_arr = array('연차','오전반차','오전반반차','오후반차','오후반반차');
|
|
for($i=0;$i<count($item_arr);$i++) {
|
|
if($al_item==$item_arr[$i])
|
|
print "<input type='radio' name='al_item' checked='checked' value='" . $item_arr[$i] . "'> " . $item_arr[$i] . "   ";
|
|
else
|
|
print "<input type='radio' name='al_item' value='" . $item_arr[$i] . "'> " . $item_arr[$i] . "   ";
|
|
}
|
|
?>
|
|
|
|
</span>
|
|
<span class="form-control">
|
|
신청시작일 <input type="date" id="al_askdatefrom" name="al_askdatefrom" readonly required autofocus value="<?=$al_askdatefrom?>" >
|
|
</span>
|
|
<span class="form-control">
|
|
신청종료일
|
|
<input type="date" id="askdateto" name="askdateto" readonly required value="<?=$al_askdateto?>" >
|
|
</span>
|
|
<span class="form-control">
|
|
<span style="color:blue">신청 기간 산출</span>
|
|
<input type="text" id="al_usedday" size=2 name="al_usedday" readonly class="text-center" value="<?=$al_usedday?>" >
|
|
</span>
|
|
<span class="form-control">
|
|
<span style="color:red">연차 잔여일수</span>
|
|
<input type="text" id="totalremainday" name="totalremainday" size=2 class="text-center" readonly value="<?=$totalremainday?>" >
|
|
</span>
|
|
<br>
|
|
<h6 class="form-signin-heading">신청 사유</h6>
|
|
<select name="al_content" id="al_content" readonly class="form-control text-center" >
|
|
<?php
|
|
$content_arr= array();
|
|
array_push($content_arr,"개인사정","휴가","여행", "병원진료등", "모두 함께 쉬는 연차휴가", "기타");
|
|
for($i=0;$i<count($content_arr);$i++) {
|
|
if($al_content==$content_arr[$i])
|
|
print "<option selected readonly value='" . $content_arr[$i] . "'> " . $content_arr[$i] . "</option>";
|
|
else
|
|
print "<option readonly value='" . $content_arr[$i] . "'> " . $content_arr[$i] . "</option>";
|
|
}
|
|
?>
|
|
</select>
|
|
<?php
|
|
switch($status) {
|
|
case 'send':
|
|
$statusstr = '결재요청';
|
|
break;
|
|
case 'ing':
|
|
$statusstr = '결재중';
|
|
break;
|
|
case 'end':
|
|
$statusstr = '결재완료';
|
|
break;
|
|
default:
|
|
$statusstr = '';
|
|
break;
|
|
}
|
|
?>
|
|
<h6 class="form-signin-heading">결재 상태</h6>
|
|
<input type="hidden" id="status" name="status" value="<?=$status?>" >
|
|
<input type="text" id="statusstr" name="statusstr" class="form-control text-center" readonly value="<?=$statusstr?>" >
|
|
<br>
|
|
<button id="saveBtn" class="btn btn-lg btn-secondary btn-block" type="button">
|
|
<? if((int)$num>0) print '승인'; else print '결재요청(등록)'; ?></button>
|
|
<? if((int)$num>0) { ?>
|
|
<button id="delBtn" class="btn btn-lg btn-danger btn-block" type="button">삭제</button>
|
|
<? } ?>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<script>
|
|
|
|
$(document).ready(function(){
|
|
// 파트 가져옴 (제조파트, 지원파트)
|
|
var al_part = '<?php echo $al_part; ?>';
|
|
|
|
// 신청일 변경시 종료일도 변경함
|
|
$("#al_askdatefrom").change(function(){
|
|
var radioVal = $('input[name="al_item"]:checked').val();
|
|
console.log(radioVal);
|
|
$('#al_askdateto').val($("#al_askdatefrom").val());
|
|
|
|
const result = getDateDiff($("#al_askdatefrom").val(), $("#al_askdateto").val());
|
|
|
|
switch(radioVal)
|
|
{
|
|
case '연차' :
|
|
$('#al_usedday').val(result);
|
|
break;
|
|
case '오전반차' :
|
|
case '오후반차' :
|
|
$('#al_usedday').val(result/2);
|
|
break;
|
|
case '오전반반차' :
|
|
case '오후반반차' :
|
|
$('#al_usedday').val(result/4);
|
|
break;
|
|
}
|
|
});
|
|
|
|
$('input[name="al_item"]').change(function(){
|
|
var radioVal = $('input[name="al_item"]:checked').val();
|
|
console.log(radioVal);
|
|
|
|
// $('#al_askdateto').val($("#al_askdatefrom").val());
|
|
|
|
const result = getDateDiff($("#al_askdatefrom").val(), $("#al_askdateto").val());
|
|
|
|
switch(radioVal)
|
|
{
|
|
case '연차' :
|
|
$('#al_usedday').val(result);
|
|
break;
|
|
case '오전반차' :
|
|
case '오후반차' :
|
|
$('#al_usedday').val(result/2);
|
|
break;
|
|
case '오전반반차' :
|
|
case '오후반반차' :
|
|
$('#al_usedday').val(result/4);
|
|
break;
|
|
}
|
|
});
|
|
|
|
// 종료일을 변경해도 자동계산해 주기
|
|
$("#al_askdateto").change(function(){
|
|
var radioVal = $('input[name="al_item"]:checked').val();
|
|
console.log(radioVal);
|
|
// $('#al_askdateto').val($("#al_askdatefrom").val());
|
|
|
|
const result = getDateDiff($("#al_askdatefrom").val(), $("#al_askdateto").val());
|
|
|
|
switch(radioVal)
|
|
{
|
|
case '연차' :
|
|
$('#al_usedday').val(result);
|
|
break;
|
|
case '오전반차' :
|
|
case '오후반차' :
|
|
$('#al_usedday').val(result/2);
|
|
break;
|
|
}
|
|
});
|
|
|
|
$("#closeBtn").click(function(){ // 저장하고 창닫기
|
|
|
|
});
|
|
|
|
$("#copyBtn").click(function(){ // 데이터복사버튼
|
|
|
|
var num = $("#num").val();
|
|
location.href='copy_data.php?num=' + num;
|
|
});
|
|
|
|
$("#saveBtn").click(function(){ // DATA 저장버튼 누름
|
|
var num = $("#num").val();
|
|
var status = $("#status").val();
|
|
$("#mode").val('modify');
|
|
var admin_name = $("#admin_name").val();
|
|
|
|
var resultOK = 0;
|
|
|
|
console.log(status);
|
|
console.log(admin_name);
|
|
|
|
if((admin_name == '소현철' || admin_name =='김보곤') && status =='ing') {
|
|
$("#status").val('end');
|
|
resultOK = 1;
|
|
} // end of if
|
|
|
|
// 지원파트 1차 결재
|
|
if((admin_name=='최장중' || admin_name=='김보곤') && status=='send' && al_part=='지원파트') {
|
|
$("#status").val('ing');
|
|
resultOK = 1;
|
|
} // end of if
|
|
// 제조파트 1차 결재
|
|
if((admin_name=='이경묵' || admin_name=='김보곤') && status=='send' && al_part=='제조파트') {
|
|
$("#status").val('ing');
|
|
resultOK = 1;
|
|
} // end of if
|
|
|
|
console.log('변경후 status ' + status);
|
|
if(resultOK == 1) { // 결과가 성공하면
|
|
$.ajax({
|
|
url: "insert_ask.php",
|
|
type: "post",
|
|
data: $("#board_form").serialize(),
|
|
dataType:"json",
|
|
success : function( data ){
|
|
console.log( data);
|
|
$('#myModal').modal('show');
|
|
//1초 지연후 실행
|
|
setTimeout(function() {
|
|
opener.location.reload();
|
|
window.close();
|
|
}, 2000);
|
|
},
|
|
error : function( jqxhr , status , error ){
|
|
console.log( jqxhr , status , error );
|
|
}
|
|
});
|
|
}
|
|
else // 오류가 있으면 오류창 띄움
|
|
{
|
|
tmp='결재권자가 틀립니다. 확인바랍니다.';
|
|
$('#alertmsg').html(tmp);
|
|
$('#myModal').modal('show');
|
|
//1초 지연후 실행
|
|
setTimeout(function() {
|
|
opener.location.reload();
|
|
window.close();
|
|
}, 2000);
|
|
}
|
|
|
|
|
|
});
|
|
|
|
$("#delBtn").click(function(){ // del
|
|
var num = $("#num").val();
|
|
var status = $("#status").val();
|
|
|
|
// 결재요청이 아닌경우 수정안됨
|
|
if(confirm("데이터 삭제.\n\n정말 지우시겠습니까?")) {
|
|
$("#mode").val('delete');
|
|
$.ajax({
|
|
url: "insert_ask.php",
|
|
type: "post",
|
|
data: $("#board_form").serialize(),
|
|
dataType:"json",
|
|
success : function( data ){
|
|
console.log( data);
|
|
opener.location.reload();
|
|
window.close();
|
|
},
|
|
error : function( jqxhr , status , error ){
|
|
console.log( jqxhr , status , error );
|
|
}
|
|
});
|
|
} // end of if
|
|
|
|
});
|
|
|
|
|
|
}); // end of ready document
|
|
|
|
// PHP에서 전달된 휴일 목록을 JavaScript 변수로 변환
|
|
var holidayDates = <?= json_encode($holidayDates, JSON_UNESCAPED_UNICODE) ?>;
|
|
// 휴일 날짜를 Set으로 변환하여 빠른 검색 가능하도록 함
|
|
var holidaySet = new Set(holidayDates);
|
|
|
|
// 날짜를 YYYY-MM-DD 형식으로 변환하는 함수
|
|
function formatDate(date) {
|
|
const year = date.getFullYear();
|
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
const day = String(date.getDate()).padStart(2, '0');
|
|
return year + '-' + month + '-' + day;
|
|
}
|
|
|
|
// 두날짜 사이 일자 구하기 (주말과 휴일 제외)
|
|
const getDateDiff = (d1, d2) => {
|
|
if (!d1 || !d2) return 0;
|
|
|
|
const date1 = new Date(d1);
|
|
const date2 = new Date(d2);
|
|
|
|
// 날짜 유효성 검사
|
|
if (isNaN(date1.getTime()) || isNaN(date2.getTime())) {
|
|
console.warn('getDateDiff: 유효하지 않은 날짜', d1, d2);
|
|
return 0;
|
|
}
|
|
|
|
// holidaySet이 없으면 빈 Set 사용 (방어 코드)
|
|
const holidays = (typeof holidaySet !== 'undefined' && holidaySet instanceof Set)
|
|
? holidaySet
|
|
: (typeof window.holidaySet !== 'undefined' && window.holidaySet instanceof Set)
|
|
? window.holidaySet
|
|
: new Set();
|
|
|
|
let count = 0;
|
|
const oneDay = 24 * 60 * 60 * 1000; // 하루의 밀리세컨드 수
|
|
|
|
// 시작일과 종료일을 포함하여 계산하기 위해 date1의 복사본 생성
|
|
let startDate = new Date(date1);
|
|
let endDate = new Date(date2);
|
|
|
|
// 시작일이 종료일보다 큰 경우 교환
|
|
if (startDate > endDate) {
|
|
const temp = startDate;
|
|
startDate = endDate;
|
|
endDate = temp;
|
|
}
|
|
|
|
// 시작일부터 종료일까지 반복 (포함)
|
|
const currentDate = new Date(startDate);
|
|
while (currentDate <= endDate) {
|
|
const dayOfWeek = currentDate.getDay(); // 요일 (0:일, 1:월, ..., 6:토)
|
|
const dateString = formatDate(currentDate); // YYYY-MM-DD 형식으로 변환
|
|
|
|
// 주말이 아니고 휴일도 아닌 경우에만 count 증가
|
|
if (dayOfWeek !== 0 && dayOfWeek !== 6 && !holidays.has(dateString)) {
|
|
count++;
|
|
}
|
|
|
|
currentDate.setTime(currentDate.getTime() + oneDay); // 다음 날짜로 이동
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
</script>
|
|
</body>
|
|
</html>
|
|
|