- URL 하드코딩 → .env APP_URL 기반 동적 URL로 변경 - DB 연결 하드코딩 → .env 기반으로 변경 - MySQL strict mode DATE 오류 수정
560 lines
19 KiB
PHP
560 lines
19 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 = '절곡작업일지 관리';
|
||
?>
|
||
|
||
<link href="css/style.css" rel="stylesheet">
|
||
<title> <?=$title_message?> </title>
|
||
<style>
|
||
.work-log-table th, .work-log-table td {
|
||
padding: 8px!important;
|
||
vertical-align: middle;
|
||
}
|
||
.work-log-form {
|
||
background-color: #f8f9fa;
|
||
border-radius: 8px;
|
||
padding: 20px;
|
||
margin-bottom: 20px;
|
||
}
|
||
.form-group {
|
||
margin-bottom: 15px;
|
||
}
|
||
</style>
|
||
|
||
</head>
|
||
|
||
<body>
|
||
<?php
|
||
require_once($_SERVER['DOCUMENT_ROOT'] . '/myheader.php');
|
||
|
||
function checkNull($strtmp) {
|
||
return ($strtmp !== null && trim($strtmp) !== '');
|
||
}
|
||
|
||
// 필터링 값 가져오기
|
||
$search = isset($_REQUEST['search']) ? $_REQUEST['search'] : '';
|
||
$workDateFrom = isset($_REQUEST['workDateFrom']) ? $_REQUEST['workDateFrom'] : '';
|
||
$workDateTo = isset($_REQUEST['workDateTo']) ? $_REQUEST['workDateTo'] : '';
|
||
$prodCodeFilter = isset($_REQUEST['prodCodeFilter']) ? $_REQUEST['prodCodeFilter'] : '';
|
||
$mode = isset($_REQUEST["mode"]) ? $_REQUEST["mode"] : '';
|
||
|
||
require_once($_SERVER['DOCUMENT_ROOT'] . "/lib/mydb.php");
|
||
$pdo = db_connect();
|
||
|
||
// 품목명을 매핑하는 배열
|
||
$prodNames = [
|
||
'R' => '가이드레일(벽면형)',
|
||
'S' => '가이드레일(측면형)',
|
||
'G' => '연기차단재',
|
||
'B' => '하단마감재(스크린)',
|
||
'T' => '하단마감재(철재)',
|
||
'L' => 'L - Bar',
|
||
'C' => '케이스'
|
||
];
|
||
|
||
// 종류명을 매핑하는 배열
|
||
$specNames = [
|
||
'I' => '화이바원단',
|
||
'S' => 'SUS(마감)',
|
||
'U' => 'SUS(마감)2',
|
||
'E' => 'EGI(마감)',
|
||
'A' => '스크린용',
|
||
'D' => 'D형',
|
||
'C' => 'C형',
|
||
'M' => '본체',
|
||
'T' => '본체(철재)',
|
||
'B' => '후면코너부',
|
||
'L' => '린텔부',
|
||
'P' => '점검구',
|
||
'F' => '전면부'
|
||
];
|
||
|
||
// 모양&길이를 매핑하는 배열
|
||
$slengthNames = [
|
||
'53' => 'W50 × 3000',
|
||
'54' => 'W50 × 4000',
|
||
'83' => 'W80 × 3000',
|
||
'84' => 'W80 × 4000',
|
||
'12' => '1219',
|
||
'24' => '2438',
|
||
'30' => '3000',
|
||
'35' => '3500',
|
||
'40' => '4000',
|
||
'41' => '4150',
|
||
'42' => '4200',
|
||
'43' => '4300'
|
||
];
|
||
|
||
// 작업일지 데이터 조회
|
||
try {
|
||
$whereClause = [];
|
||
$params = [];
|
||
|
||
if (checkNull($search)) {
|
||
$whereClause[] = "(work_order_no LIKE ? OR work_type LIKE ? OR worker LIKE ? OR remark LIKE ?)";
|
||
$searchParam = "%$search%";
|
||
$params = array_merge($params, [$searchParam, $searchParam, $searchParam, $searchParam]);
|
||
}
|
||
|
||
if (checkNull($workDateFrom)) {
|
||
$whereClause[] = "work_date >= ?";
|
||
$params[] = $workDateFrom;
|
||
}
|
||
|
||
if (checkNull($workDateTo)) {
|
||
$whereClause[] = "work_date <= ?";
|
||
$params[] = $workDateTo;
|
||
}
|
||
|
||
if (checkNull($prodCodeFilter)) {
|
||
$whereClause[] = "prod_code = ?";
|
||
$params[] = $prodCodeFilter;
|
||
}
|
||
|
||
$sql = "SELECT * FROM bending_work_log WHERE is_deleted IS NULL";
|
||
if (!empty($whereClause)) {
|
||
$sql .= " AND " . implode(' AND ', $whereClause);
|
||
}
|
||
$sql .= " ORDER BY work_date DESC, id DESC";
|
||
|
||
$stmt = $pdo->prepare($sql);
|
||
$stmt->execute($params);
|
||
$workLogs = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||
|
||
} catch (PDOException $Exception) {
|
||
print "오류: ".$Exception->getMessage();
|
||
}
|
||
?>
|
||
|
||
<form id="board_form" name="board_form" method="post" enctype="multipart/form-data">
|
||
<input type="hidden" id="mode" name="mode" value="<?=$mode?>">
|
||
<input type="hidden" id="num" name="num">
|
||
<input type="hidden" id="header" name="header" value="<?=$header?>">
|
||
<input type="hidden" id="work_log_id" name="work_log_id" value="">
|
||
|
||
<div class="container-fluid">
|
||
<div class="card justify-content-center text-center mt-1 mb-5">
|
||
<div class="card-header">
|
||
<div class="d-flex justify-content-center align-items-center">
|
||
<span class="text-center 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>
|
||
</div>
|
||
</div>
|
||
<div class="card-body">
|
||
|
||
<div class="container mt-2 mb-4">
|
||
<div class="d-flex mb-2 justify-content-center align-items-center">
|
||
▷ 작업일지 관리
|
||
|
||
<!-- 작업일자 범위 -->
|
||
<div class="inputWrap30">
|
||
<input type="date" id="workDateFrom" name="workDateFrom" class="form-control" style="width:150px;" value="<?= $workDateFrom ?>">
|
||
</div>
|
||
~
|
||
<div class="inputWrap30">
|
||
<input type="date" id="workDateTo" name="workDateTo" class="form-control" style="width:150px;" value="<?= $workDateTo ?>">
|
||
</div>
|
||
|
||
|
||
<!-- 품목명 select box -->
|
||
<div class="inputWrap30">
|
||
<select id="prodCodeFilter" name="prodCodeFilter" class="form-select w-auto mx-1" style="font-size:0.7rem; height:32px;" >
|
||
<option value="">품목명 선택</option>
|
||
<?php foreach($prodNames as $key => $value) { ?>
|
||
<option value="<?= $key ?>" <?= ($prodCodeFilter == $key) ? 'selected' : '' ?>><?= $value ?></option>
|
||
<?php } ?>
|
||
</select>
|
||
</div>
|
||
|
||
|
||
<!-- 검색 input -->
|
||
<div class="inputWrap30">
|
||
<input type="text" id="search" class="form-control text-start" style="width:150px;" name="search" value="<?= $search ?>" autocomplete="off" placeholder="작업지시번호, 작업유형, 작업자 검색">
|
||
<button class="btnClear"></button>
|
||
</div>
|
||
|
||
<button class="btn btn-outline-dark btn-sm" type="button" id="searchBtn"> <i class="bi bi-search"></i> </button>
|
||
|
||
<button id="newBtn" type="button" class="btn btn-dark btn-sm me-2"> <i class="bi bi-pencil-square"></i> 신규입력 </button>
|
||
<button id="stockBtn" type="button" class="btn btn-success btn-sm me-2"> <i class="bi bi-boxes"></i> 재고현황 </button>
|
||
</div>
|
||
|
||
<!-- 작업일지 입력 폼 -->
|
||
<div class="work-log-form" id="workLogForm" style="display: none;">
|
||
<h5 class="mb-3">작업일지 입력</h5>
|
||
<div class="row">
|
||
<div class="col-md-3">
|
||
<div class="form-group">
|
||
<label for="work_date">작업일자</label>
|
||
<input type="date" id="work_date" name="work_date" class="form-control" required>
|
||
</div>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<div class="form-group">
|
||
<label for="work_order_no">작업지시번호</label>
|
||
<input type="text" id="work_order_no" name="work_order_no" class="form-control" placeholder="WO-2024-001">
|
||
</div>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<div class="form-group">
|
||
<label for="work_type">작업유형</label>
|
||
<input type="text" id="work_type" name="work_type" class="form-control" placeholder="가이드레일 제작">
|
||
</div>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<div class="form-group">
|
||
<label for="worker">작업자</label>
|
||
<input type="text" id="worker" name="worker" class="form-control" placeholder="작업자명">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="row">
|
||
<div class="col-md-3">
|
||
<div class="form-group">
|
||
<label for="prod_code">품목</label>
|
||
<select id="prod_code" name="prod_code" class="form-select" required>
|
||
<option value="">품목 선택</option>
|
||
<?php foreach($prodNames as $key => $value) { ?>
|
||
<option value="<?= $key ?>"><?= $value ?></option>
|
||
<?php } ?>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<div class="form-group">
|
||
<label for="spec_code">종류</label>
|
||
<select id="spec_code" name="spec_code" class="form-select" required>
|
||
<option value="">종류 선택</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<div class="form-group">
|
||
<label for="slength_code">모양&길이</label>
|
||
<select id="slength_code" name="slength_code" class="form-select" required>
|
||
<option value="">모양&길이 선택</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<div class="form-group">
|
||
<label for="quantity">사용수량</label>
|
||
<input type="number" id="quantity" name="quantity" class="form-control" min="0" required>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="row">
|
||
<div class="col-md-12">
|
||
<div class="form-group">
|
||
<label for="remark">비고</label>
|
||
<textarea id="remark" name="remark" class="form-control" rows="2" placeholder="추가 설명"></textarea>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="row">
|
||
<div class="col-md-12 text-end">
|
||
<button type="button" id="saveWorkLogBtn" class="btn btn-primary">저장</button>
|
||
<button type="button" id="cancelWorkLogBtn" class="btn btn-secondary">취소</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 작업일지 목록 -->
|
||
<div class="table-responsive">
|
||
<table class="table table-hover work-log-table">
|
||
<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">작업자</th>
|
||
<th class="text-center">비고</th>
|
||
<th class="text-center">관리</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php foreach ($workLogs as $log): ?>
|
||
<tr>
|
||
<td class="text-center"><?= $log['id'] ?></td>
|
||
<td class="text-center"><?= $log['work_date'] ?></td>
|
||
<td class="text-center"><?= $log['work_order_no'] ?></td>
|
||
<td class="text-center"><?= $log['work_type'] ?></td>
|
||
<td class="text-center"><?= $prodNames[$log['prod_code']] ?? $log['prod_code'] ?></td>
|
||
<td class="text-center"><?= $specNames[$log['spec_code']] ?? $log['spec_code'] ?></td>
|
||
<td class="text-center"><?= $slengthNames[$log['slength_code']] ?? $log['slength_code'] ?></td>
|
||
<td class="text-center"><?= number_format($log['quantity']) ?></td>
|
||
<td class="text-center"><?= $log['worker'] ?></td>
|
||
<td class="text-start"><?= $log['remark'] ?></td>
|
||
<td class="text-center">
|
||
<button type="button" class="btn btn-sm btn-outline-primary" onclick="editWorkLog(<?= $log['id'] ?>)">수정</button>
|
||
<button type="button" class="btn btn-sm btn-outline-danger" onclick="deleteWorkLog(<?= $log['id'] ?>)">삭제</button>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
|
||
<script>
|
||
|
||
var loader = document.getElementById('loadingOverlay');
|
||
if(loader)
|
||
loader.style.display = 'none';
|
||
|
||
$(document).ready(function() {
|
||
|
||
$("#newBtn").on("click", function() {
|
||
$("#workLogForm").show();
|
||
clearWorkLogForm();
|
||
});
|
||
|
||
$("#searchBtn").on("click", function() {
|
||
$("#board_form").submit();
|
||
});
|
||
|
||
$("#stockBtn").on("click", function() {
|
||
window.open('list_stock.php', '_blank');
|
||
});
|
||
|
||
$("#cancelWorkLogBtn").on("click", function() {
|
||
$("#workLogForm").hide();
|
||
clearWorkLogForm();
|
||
});
|
||
|
||
$("#saveWorkLogBtn").on("click", function() {
|
||
saveWorkLog();
|
||
});
|
||
|
||
// 품목별 선택 가능한 종류 목록 설정
|
||
const specOptions = {
|
||
'G': ['I'], // 연기차단재 - 화이바원단
|
||
'B': ['S', 'E'], // 하단마감재(스크린) - SUS, EGI
|
||
'T': ['S', 'E'], // 하단마감재(철재) - SUS, EGI
|
||
'L': ['A'], // L - Bar - 스크린용
|
||
'R': ['S', 'D', 'C', 'M', 'E'], // 가이드레일 - SUS, D형, C형, 본체, EGI
|
||
'S': ['S', 'D', 'C', 'M', 'E', 'U'], // 가이드레일 - SUS, D형, C형, 본체
|
||
'C': ['B', 'L', 'P', 'F'] // 케이스 - 후면코너부, 린텔부, 점검구, 전면부
|
||
};
|
||
|
||
// 모양&길이 옵션
|
||
const slengthOptions = {
|
||
'G': ['53', '54', '83', '84'], // 연기차단재
|
||
'default': ['12', '24', '30', '35', '40', '42', '43'] // 기타
|
||
};
|
||
|
||
// 품목 변경 시 종류 옵션 업데이트
|
||
$("#prod_code").on("change", function() {
|
||
const selectedProd = $(this).val();
|
||
const specSelect = $("#spec_code");
|
||
const slengthSelect = $("#slength_code");
|
||
|
||
// 종류 옵션 초기화
|
||
specSelect.html('<option value="">종류 선택</option>');
|
||
slengthSelect.html('<option value="">모양&길이 선택</option>');
|
||
|
||
if (selectedProd && specOptions[selectedProd]) {
|
||
specOptions[selectedProd].forEach(function(spec) {
|
||
const specName = getSpecName(spec);
|
||
specSelect.append(`<option value="${spec}">${specName}</option>`);
|
||
});
|
||
}
|
||
|
||
// 모양&길이 옵션 설정
|
||
const slengthCodes = slengthOptions[selectedProd] || slengthOptions['default'];
|
||
slengthCodes.forEach(function(slength) {
|
||
const slengthName = getSlengthName(slength);
|
||
slengthSelect.append(`<option value="${slength}">${slengthName}</option>`);
|
||
});
|
||
});
|
||
});
|
||
|
||
function getSpecName(specCode) {
|
||
const specNames = {
|
||
'I': '화이바원단',
|
||
'S': 'SUS(마감)',
|
||
'U': 'SUS(마감)2',
|
||
'E': 'EGI(마감)',
|
||
'A': '스크린용',
|
||
'D': 'D형',
|
||
'C': 'C형',
|
||
'M': '본체',
|
||
'B': '후면코너부',
|
||
'L': '린텔부',
|
||
'P': '점검구',
|
||
'F': '전면부'
|
||
};
|
||
return specNames[specCode] || specCode;
|
||
}
|
||
|
||
function getSlengthName(slengthCode) {
|
||
const slengthNames = {
|
||
'53': 'W50 × 3000',
|
||
'54': 'W50 × 4000',
|
||
'83': 'W80 × 3000',
|
||
'84': 'W80 × 4000',
|
||
'12': '1219',
|
||
'24': '2438',
|
||
'30': '3000',
|
||
'35': '3500',
|
||
'40': '4000',
|
||
'42': '4200',
|
||
'43': '4300'
|
||
};
|
||
return slengthNames[slengthCode] || slengthCode;
|
||
}
|
||
|
||
function clearWorkLogForm() {
|
||
$("#work_log_id").val('');
|
||
$("#work_date").val('');
|
||
$("#work_order_no").val('');
|
||
$("#work_type").val('');
|
||
$("#worker").val('');
|
||
$("#prod_code").val('');
|
||
$("#spec_code").html('<option value="">종류 선택</option>');
|
||
$("#slength_code").html('<option value="">모양&길이 선택</option>');
|
||
$("#quantity").val('');
|
||
$("#remark").val('');
|
||
}
|
||
|
||
function saveWorkLog() {
|
||
const formData = {
|
||
id: $("#work_log_id").val(),
|
||
work_date: $("#work_date").val(),
|
||
work_order_no: $("#work_order_no").val(),
|
||
work_type: $("#work_type").val(),
|
||
worker: $("#worker").val(),
|
||
prod_code: $("#prod_code").val(),
|
||
spec_code: $("#spec_code").val(),
|
||
slength_code: $("#slength_code").val(),
|
||
quantity: $("#quantity").val(),
|
||
remark: $("#remark").val()
|
||
};
|
||
|
||
// 필수 필드 검증
|
||
if (!formData.work_date || !formData.prod_code || !formData.spec_code || !formData.slength_code || !formData.quantity) {
|
||
alert('필수 항목을 모두 입력해주세요.');
|
||
return;
|
||
}
|
||
|
||
$.ajax({
|
||
url: "save_work_log.php",
|
||
type: "POST",
|
||
data: formData,
|
||
dataType: "json",
|
||
success: function(response) {
|
||
if (response.success) {
|
||
Toastify({
|
||
text: "저장완료",
|
||
duration: 3000,
|
||
close: true,
|
||
gravity: "top",
|
||
position: "center",
|
||
backgroundColor: "#4fbe87",
|
||
}).showToast();
|
||
|
||
setTimeout(function() {
|
||
location.reload();
|
||
}, 1000);
|
||
} else {
|
||
alert('저장 중 오류가 발생했습니다: ' + response.message);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
console.error('AJAX Error:', status, error);
|
||
alert('저장 중 오류가 발생했습니다.');
|
||
}
|
||
});
|
||
}
|
||
|
||
function editWorkLog(id) {
|
||
// 수정 기능: 해당 id의 데이터를 찾아 폼에 채우고, 폼을 보여줌
|
||
var log = null;
|
||
<?php // PHP에서 JS로 workLogs 배열을 전달 ?>
|
||
var workLogs = <?php echo json_encode($workLogs); ?>;
|
||
for (var i = 0; i < workLogs.length; i++) {
|
||
if (workLogs[i].id == id) {
|
||
log = workLogs[i];
|
||
break;
|
||
}
|
||
}
|
||
if (log) {
|
||
$("#work_log_id").val(log.id);
|
||
$("#work_date").val(log.work_date);
|
||
$("#work_order_no").val(log.work_order_no);
|
||
$("#work_type").val(log.work_type);
|
||
$("#worker").val(log.worker);
|
||
$("#prod_code").val(log.prod_code).trigger('change');
|
||
setTimeout(function() {
|
||
$("#spec_code").val(log.spec_code);
|
||
$("#slength_code").val(log.slength_code);
|
||
}, 100); // 옵션 렌더링 후 값 세팅
|
||
$("#quantity").val(log.quantity);
|
||
$("#remark").val(log.remark);
|
||
$("#workLogForm").show();
|
||
}
|
||
}
|
||
|
||
function deleteWorkLog(id) {
|
||
if (confirm('정말 삭제하시겠습니까?')) {
|
||
$.ajax({
|
||
url: "delete_work_log.php",
|
||
type: "POST",
|
||
data: { id: id },
|
||
dataType: "json",
|
||
success: function(response) {
|
||
if (response.success) {
|
||
Toastify({
|
||
text: "삭제완료",
|
||
duration: 2000,
|
||
close: true,
|
||
gravity: "top",
|
||
position: "center",
|
||
backgroundColor: "#dc3545",
|
||
}).showToast();
|
||
|
||
setTimeout(function() {
|
||
location.reload();
|
||
}, 1000);
|
||
} else {
|
||
alert('삭제 중 오류가 발생했습니다: ' + response.message);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
console.error('AJAX Error:', status, error);
|
||
alert('삭제 중 오류가 발생했습니다.');
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
function enter() {
|
||
$("#board_form").submit();
|
||
}
|
||
|
||
$(document).ready(function(){
|
||
// 방문기록 남김
|
||
var title_message = '<?php echo $title_message ; ?>';
|
||
saveMenuLog(title_message);
|
||
});
|
||
|
||
</script>
|
||
|
||
</body>
|
||
</html>
|