Files
sam-kd/estimate/write_form.php
hskwon aca1767eb9 초기 커밋: 5130 레거시 시스템
- URL 하드코딩 → .env APP_URL 기반 동적 URL로 변경
- DB 연결 하드코딩 → .env 기반으로 변경
- MySQL strict mode DATE 오류 수정
2025-12-10 20:14:31 +09:00

2426 lines
101 KiB
PHP
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
// 2025/05/23 데이터 복사시 견적번호 마지막의 뒤 -00형태 제거하기
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';
$mode = isset($_REQUEST['mode']) ? $_REQUEST['mode'] : '';
$num = isset($_REQUEST["num"]) ? $_REQUEST["num"] : "";
$tablename = isset($_REQUEST["tablename"]) ? $_REQUEST["tablename"] : "";
$header = isset($_REQUEST["header"]) ? $_REQUEST["header"] : ""; // 수주창에서 호출하는 경우 사용
$itemoption = isset($_REQUEST["itemoption"]) ? $_REQUEST["itemoption"] : ""; // option = screen , slat 선택 전달 (수주내역에서 호출)
$tempKey = isset($_REQUEST["tempKey"]) ? $_REQUEST["tempKey"] : "";
$estimateSurang = $_REQUEST['estimateSurang'] ?? '';
$EstimateFirstSum = $_REQUEST['EstimateFirstSum'] ?? '';
$EstimateUpdatetSum = $_REQUEST['EstimateUpdatetSum'] ?? '';
$EstimateDiffer = $_REQUEST['EstimateDiffer'] ?? '';
$estimateTotal = $_REQUEST['estimateTotal'] ?? '';
$makeWidth = $_REQUEST['makeWidth'] ?? '';
$makeHeight = $_REQUEST['makeHeight'] ?? '';
$maguriWing = $_REQUEST['maguriWing'] ?? '';
$inspectionFee = $_REQUEST['inspectionFee'] ?? '';
// print '$makeWidth ' . $makeWidth . '<br>';
// print '$makeHeight ' . $makeHeight . '<br>';
// print '$maguriWing ' . $maguriWing . '<br>';
// print '$inspectionFee ' . $inspectionFee . '<br>';
if($header == 'header')
{
$title_message = "견적서에서 발주 산출";
}
else
{
if($mode === 'copy')
$title_message = "(데이터복사) 견적 산출";
else
$title_message = "견적 산출" ;
}
if($itemoption == 'screen')
{
$title_message = "스크린 발주서 수정";
$tablename = 'output';
$major_category = '스크린';
}
else if($itemoption == 'slat')
{
$title_message = "철재스라트 발주서 수정";
$tablename = 'output';
$major_category = '철재';
}
$authorities = ["개발자","전진","노완호","이세희","함신옥","손금주","이은진","이경호"];
// print $position;
?>
<title> <?=$title_message?> </title>
<style>
textarea {
overflow: hidden;
resize: none; /* 사용자 크기 조절을 방지 */
}
/* 기본 스타일 설정 */
input[type="checkbox"],
input[type="radio"] {
transform: scale(1.3); /* 크기 확대 */
margin: 3px; /* 여백 추가 */
}
/* "readonly" 상태일 때 스타일 설정 */
.readonly-checkbox,
.readonly-radio {
pointer-events: none; /* 사용자 상호작용 비활성화 */
opacity: 1; /* 불투명도 설정 */
color: red;
}
/* 레이블 텍스트 크게 설정 */
label {
font-size: 1.2em; /* 글꼴 크기 확대 */
display: inline-block;
margin: 3px 0;
}
.w-40{
width: 40%!important;
}
.w-50{
width: 50%!important;
}
.w-60{
width: 60%!important;
}
.w-85{
width: 85%!important;
}
.viewNoBtn {
cursor : pointer;
}
/* CSS: 수동편집된 요소의 배경색 */
.manually-edited {
background-color: #f8d7da !important;
}
</style>
</head>
<?
include $_SERVER['DOCUMENT_ROOT'] . '/mymodal.php';
// 첨부 이미지에 대한 부분
require_once($_SERVER['DOCUMENT_ROOT'] . "/lib/mydb.php");
$pdo = db_connect();
$today = date("Y-m-d"); // 현재일자 변수지정
if(!empty($itemoption) && $itemoption == 'screen')
{
$today = date("Y-m-d"); // 현재일자 변수지정
$num = $_GET['num'] ?? '';
$tempKey = $_GET['tempKey'] ?? '';
if ($tempKey) {
$jsonFilePath = $_SERVER['DOCUMENT_ROOT'] . '/output/json/' . $tempKey . '.json';
// JSON 파일이 존재하면 읽어옴
if (file_exists($jsonFilePath)) {
$jsonData = file_get_contents($jsonFilePath);
$estimateList = json_decode($jsonData, true);
$estimateList_auto = json_decode($jsonData, true); // auto는 기존자료 복사
} else {
echo "JSON 파일을 찾을 수 없습니다.";
exit;
}
} else {
echo "유효하지 않은 접근입니다.";
exit;
}
if (empty($makeWidth) || !is_numeric($makeWidth)) $makeWidth = '160';
if (empty($makeHeight) || !is_numeric($makeHeight)) $makeHeight = '350';
if (empty($maguriWing) || !is_numeric($maguriWing)) $maguriWing = '50';
// echo '<pre>';
// print_r($estimateList);
// echo '</pre>';
}
else if(!empty($itemoption) && $itemoption == 'slat')
{
$today = date("Y-m-d"); // 현재일자 변수지정
$num = $_GET['num'] ?? '';
$tempKey = $_GET['tempKey'] ?? '';
if ($tempKey) {
$jsonFilePath = $_SERVER['DOCUMENT_ROOT'] . '/output/json/' . $tempKey . '.json';
// JSON 파일이 존재하면 읽어옴
if (file_exists($jsonFilePath)) {
$jsonData = file_get_contents($jsonFilePath);
$estimateSlatList = json_decode($jsonData, true);
$estimateSlatList_auto = json_decode($jsonData, true); // auto는 기존자료 복사
} else {
echo "JSON 파일을 찾을 수 없습니다.";
exit;
}
} else {
echo "유효하지 않은 접근입니다.";
exit;
}
if (empty($makeWidth) || !is_numeric($makeWidth)) $makeWidth = '110';
if (empty($makeHeight) || !is_numeric($makeHeight)) $makeHeight = '350';
if (empty($maguriWing) || !is_numeric($maguriWing)) $maguriWing = '50';
// echo '<pre>';
// print_r($estimateSlatList);
// echo '</pre>';
}
else
{
// 수주리스트에서 호출이 아닌 경우 이것 실행
if ($mode=="modify" || !empty($num) )
{
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 정보를 불러온다.
if($count<1){
print "검색결과가 없습니다.<br>";
}else{
include '_row.php';
if($indate!="0000-00-00") $indate = date("Y-m-d", strtotime( $indate) );
else $indate="";
if($outdate!="0000-00-00") $outdate = date("Y-m-d", strtotime( $outdate) );
else $outdate="";
}
}catch (PDOException $Exception) {
print "오류: ".$Exception->getMessage();
}
}
else if ($mode!="modify" && $mode!="view"){ // 수정모드가 아닐때 신규 자료일때는 변수 초기화 한다.
include '_request.php';
$indate=date("Y-m-d");
$orderman=$_SESSION["name"];
$outworkplace=null;
$comment=null;
$secondord = '';
$secondordman = '';
$secondordmantel = '';
$inspectionFeeFormatted = '50,000'; // 검사비 설정
}
else if ($mode == "copy" || $mode == 'split') {
try {
$sql = "select * from " . $DB . ".{$tablename} where num = ? ";
$stmh = $pdo->prepare($sql);
$stmh->bindValue(1, $num, PDO::PARAM_STR);
$stmh->execute();
$count = $stmh->rowCount();
if($count<1){
print "검색결과가 없습니다.<br>";
} else {
$row = $stmh->fetch(PDO::FETCH_ASSOC);
}
include '_row.php';
} catch (PDOException $Exception) {
print "오류: ".$Exception->getMessage();
}
// 자료번호 초기화
$num = 0;
$indate=date("Y-m-d");
$orderman=$_SESSION["name"];
}
}
if ($mode == "copy") {
// 견적번호의 마지막 -00 제거하기
$pjnum = substr($pjnum, 0, -3);
}
if(!empty($itemoption) && ($itemoption == 'slat' || $itemoption == 'screen' ) )
{
// 전달받은 체크박스상태 값으로 수정함.
$steel = $_REQUEST['steelChecked'] == 'checked' ? '1' : '0';
$motor = $_REQUEST['motorChecked'] == 'checked' ? '1' : '0';
$warranty = $_REQUEST['warrantyChecked'] == 'checked' ? '인정' : '';
$slatcheck = $_REQUEST['slatChecked'] == 'checked' ? '1' : '0';
$partscheck = $_REQUEST['partsChecked'] == 'checked' ? '1' : '0';
// echo $itemoption . '<br>' ;
// echo $steel;
// echo $motor;
// echo $warranty;
// echo $slatcheck;
// echo $partscheck;
}
// echo '<pre>';
// print_r($row);
// echo '</pre>';
// echo '모델명 : ' . $model_name;
// 검사비가 0일때 신규일때는 만들어주고 수정일때는 무시함
if (!empty($inspectionFee)) {
$inspectionFee = (int)str_replace(',', '', $inspectionFee);
}
// 검사비 출력용으로 포맷 적용
$inspectionFeeFormatted = number_format($inspectionFee);
?>
<form id="board_form" name="board_form" method="post" enctype="multipart/form-data" >
<input type="hidden" id="mode" name="mode" value="<?= isset($mode) ? $mode : '' ?>">
<input type="hidden" id="num" name="num" value="<?= isset($num) ? $num : '' ?>">
<input type="hidden" id="level" name="level" value="<?= isset($level) ? $level : '' ?>">
<input type="hidden" id="user_name" name="user_name" value="<?= isset($user_name) ? $user_name : '' ?>">
<input type="hidden" id="update_log" name="update_log" value="<?= isset($update_log) ? $update_log : null ?>">
<input type="hidden" id="tablename" name="tablename" value="<?= isset($tablename) ? $tablename : '' ?>">
<input type="hidden" id="header" name="header" value="<?= isset($header) ? $header : '' ?>">
<input type="hidden" id="is_deleted" name="is_deleted" value="<?= isset($is_deleted) ? $is_deleted : null ?>">
<input type="hidden" id="position" name="position" value="<?= isset($position) ? $position : null ?>">
<input type="hidden" id="secondordnum" name="secondordnum" value="<?= isset($secondordnum) ? $secondordnum : null ?>">
<input type="hidden" id="major_category" name="major_category" value="<?= isset($major_category) ? $major_category : null ?>">
<input type="hidden" id="estimateList" name="estimateList">
<input type="hidden" id="estimateSlatList" name="estimateSlatList">
<input type="hidden" id="estimateList_auto" name="estimateList_auto">
<input type="hidden" id="estimateSlatList_auto" name="estimateSlatList_auto">
<div class="container">
<div class="row justify-content-center align-items-center ">
<div class="card align-middle " style="width: 55rem;">
<div class="card-body text-center">
<div class="row d-flex justify-content-center align-items-center mb-3" >
<div class="col-sm-1" >
<div class="d-flex p-1 mb-1 justify-content-start align-items-center ">
<?=$mode?>
</div>
</div>
<div class="col-sm-9" >
<div class="d-flex p-1 mb-1 justify-content-center align-items-center ">
<h4> <?=$title_message?> </h4> &nbsp; &nbsp; &nbsp; &nbsp;
<?php if($mode =='view') { ?>
<button type="button" class="btn btn-dark btn-sm mx-1" onclick='location.reload();' > <i class="bi bi-arrow-clockwise"></i> </button>
<button type="button" class="btn btn-dark btn-sm mx-1" onclick="location.href='write_form.php?mode=modify&num=<?=$num?>&tablename=<?=$tablename?>';" > <i class="bi bi-pencil-square"></i> 수정 </button>
<button id="copyBtn" class="btn btn-primary btn-sm mx-1" type="button"><i class="bi bi-copy"></i> 복사</button>
<button id="deleteBtn" class="btn btn-danger btn-sm mx-1" type="button"><i class="bi bi-trash2"></i> 삭제</button>
<?php } ?>
<?php if($mode!=='view') { ?>
<?php if(!empty($itemoption)) : ?>
<button id="adaptParentBtn" class="btn btn-dark btn-sm me-1 " type="button"> <i class="bi bi-hdd-fill"></i> 발주서에 적용하기 </button>
<?php else : ?>
<button id="saveBtn" class="btn btn-dark btn-sm mx-1 " type="button"> <i class="bi bi-hdd-fill"></i> 저장 </button>
<?php endif; ?>
<? } ?>
<button type="button" class="btn btn-outline-dark btn-sm mx-2" id="showlogBtn"> H
</div>
</div>
<div class="col-sm-2" >
<button type="button" class="btn btn-outline-dark btn-sm " onclick="self.close();" > <i class="bi bi-box-arrow-left"></i> 창닫기 </button> &nbsp;
</div>
</div>
</div>
</div>
</div>
</div>
<div class="container-fluid" >
<div class="row" >
<div class="col-lg-12 col-sm-12">
<div class="d-flex justify-content-center align-items-center">
<div class="card">
<div class="card-body text-center">
<div class="d-flex justify-content-center align-items-center" >
<table class="table table-bordered"
<?php if (!empty($itemoption)) echo 'style="display:none;"'; ?>>
<tbody
<?php if (!empty($itemoption)) echo 'style="display:none;"'; ?> >
<tr>
<td class="text-end" style="width:100px;"> 제품 대분류 </td>
<td style="width:220px;">
<span class="text-center text-danger mx-2">
<?php
$checkstep_options = ["스크린", "철재"];
$major_category_array = explode(", ", $major_category);
// 값이 비어있을 경우 '스크린'을 기본으로 선택
if (empty($major_category)) {
$major_category_array = ["스크린"];
}
foreach ($checkstep_options as $option) {
$checked = in_array($option, $major_category_array) ? 'checked' : '';
echo '<span class="fw-bold text-primary ms-2">' . $option . '</span> &nbsp;
<input type="radio" name="radio_item" value="' . $option . '" ' . $checked . '> ';
}
?>
</span>
</td>
<td class="text-end" style="width:60px;"> 모델명 </td>
<td>
<!-- 제품모델(KSS01 등) 선택 -->
<?php
$modelsList = [];
// $modelsList가 전역에서 아직 설정되지 않았거나, 배열이 아니거나 비어있으면 JSON 파일에서 로드합니다.
if (!isset($modelsList) || !is_array($modelsList) || empty($modelsList)) {
$jsonFile = $_SERVER['DOCUMENT_ROOT'].'/models/models.json';
if(file_exists($jsonFile)) {
$jsonContent = file_get_contents($jsonFile);
$modelsList = json_decode($jsonContent, true);
if(!is_array($modelsList)) {
$modelsList = [];
}
}
}
// (1) $model_name 공백 제거
$model_name = isset($model_name) ? trim($model_name) : '';
// 모델 리스트 로드 로직은 그대로…
echo '<select
id="model_name"
name="model_name"
class="form-select mx-1 d-block w-auto viewmode viewNoBtn"
style="font-size:0.8rem; height:32px;"
data-readonly="true"
>';
echo '<option value="">(모델 선택)</option>';
foreach ($modelsList as $model) {
// (2) 값 준비
$optValue = trim($model['model_name']);
$pairValue = trim($model['pair']);
$value = htmlspecialchars($optValue, ENT_QUOTES, 'UTF-8');
$pair = htmlspecialchars($pairValue, ENT_QUOTES, 'UTF-8');
// (3) selected 결정
$selected = ($model_name === $optValue) ? ' selected' : '';
echo "<option value=\"{$value}\" data-pair=\"{$pair}\"{$selected}>{$value}</option>";
}
echo '</select>';
?>
</td>
<td class="text-end" style="width:50px;"> 접수 </td>
<td style="width:100px;">
<input type="date" id="indate" name="indate" class="form-control" value="<?=$indate?>" >
</td>
<td class="text-end" style="width:80px;"> 견적번호 </td>
<td style="width:180px;">
<input type="text" id="pjnum" name="pjnum" class="form-control" value="<?=$pjnum?>" >
</td>
<td class="text-end" style="width:80px;">발주처</td>
<td style="width:300px;">
<div class="d-flex align-items-center justify-content-center">
<input type="text" id="secondord" name="secondord" value="<?=$secondord?>" class="form-control text-start" autocomplete="off" onkeydown="if(event.keyCode == 13) { phonebookBtn('secondord'); }"> &nbsp;
<button type="button" class="btn btn-dark-outline btn-sm restrictbtn" onclick="phonebookBtn('secondord');"> <i class="bi bi-gear"></i> </button>
</div>
</td>
<td class="text-end" style="width:60px;"> 담당자</td>
<td style="width:130px;">
<input type="text" id="secondordman" name="secondordman" class="form-control text-start" autocomplete="off" value="<?=$secondordman?>" onkeydown="if(event.keyCode == 13) { phonebookBtn('secondordman'); }">
</td>
<td class="text-end" style="width:90px;"> 연락처 <i class="bi bi-telephone-forward-fill"></i></td>
<td style="width:130px;">
<div class="d-flex align-items-center justify-content-center">
<input type="text" id="secondordmantel" name="secondordmantel" value="<?=$secondordmantel?>" autocomplete="off" class="form-control text-start" onkeydown="if(event.keyCode == 13) { phonebookBtn('secondordmantel'); }">
</div>
</td>
<td class="text-center" style="width:100px;"> (경동)작성자 </td>
<td style="width:100px;">
<input type="text" id="orderman" name="orderman" value="<?=$orderman?>" class="form-control" placeholder="주일/경동 직원" >
</td>
</tr>
</tbody>
</table>
</div>
<div class="row">
<div class="col-sm-8">
<div class="d-flex justify-content-center align-items-center"
<?php if(!empty($itemoption)) echo 'style="display:none;"'; ?> >
<table class="table table-bordered">
<tbody>
<tr>
<td colspan="4" class="text-start" >
<?php
$steelChecked = ($steel == "1") ? 'checked' : '' ; // 절곡체크가 steel 임.
$motorChecked = ($motor == "1") ? 'checked' : ''; // 모터가 들어가는지 체크
$warrantyChecked = ($warranty == "인정") ? 'checked' : ''; // 인정제품인지 체크
$slatChecked = ($slatcheck == "1") ? 'checked' : ''; // 주자재(스크린,철재) 체크
$partsChecked = ($partscheck == "1") ? 'checked' : ''; // 부자재 체크
?>
<div class="d-flex align-items-center justify-content-center">
<h6>
<label for="warranty">
<input type="checkbox" id="warranty" data-readonly="true" name="warranty" value="인정" <?= $warrantyChecked ?> onchange="toggleOtherCheckboxes(this)">
<span class="badge bg-primary-subtle border border-primary-subtle text-primary-emphasis rounded-pill me-1"> 인정 </span>
</label>
<label for="slatcheck">
<input type="checkbox" id="slatcheck" data-readonly="true" name="slatcheck" value="1" <?= $slatChecked ?>>
<span class="badge bg-info-subtle border border-info-subtle text-info-emphasis rounded-pill me-1"> 주자재(스크린,철재) </span>
</label>
<label for="motor">
<input type="checkbox" id="motor" data-readonly="true" name="motor" value="1" <?= $motorChecked ?>>
<span class="badge bg-success-subtle border border-success-subtle text-success-emphasis rounded-pill me-1"> 모터 </span>
</label>
<label for="steel">
<input type="checkbox" data-readonly="true" id="steel" name="steel" value="1" <?= $steelChecked ?>>
<span class="badge bg-secondary-subtle border border-secondary-subtle text-secondary-emphasis rounded-pill me-1"> 절곡 </span>
</label>
<label for="partscheck">
<input type="checkbox" id="partscheck" data-readonly="true" name="partscheck" value="1" <?= $partsChecked ?>>
<span class="badge bg-danger-subtle border border-danger-subtle text-danger-emphasis rounded-pill me-1"> 부자재 </span>
</label>
<button type="button" id="applyToAllRowsBtn" class="btn btn-warning btn-sm ms-3" title="체크박스 설정을 모든 행에 적용">
<i class="bi bi-arrow-down-circle"></i> 체크 해제된 모든행의 값 제거하기
</button>
</h6>
</div>
<script>
function toggleOtherCheckboxes(warrantyCheckbox) {
// 나머지 4개 체크박스 ID들
const otherCheckboxes = ['slatcheck', 'motor', 'steel', 'partscheck'];
// 인정 체크박스가 체크되었는지 확인
const isChecked = warrantyCheckbox.checked;
// 나머지 체크박스들을 모두 동일한 상태로 설정
otherCheckboxes.forEach(function(checkboxId) {
const checkbox = document.getElementById(checkboxId);
if (checkbox) {
checkbox.checked = isChecked;
}
});
}
// 모든 행에 체크박스 설정 적용하는 함수
function applyCheckboxSettingsToAllRows() {
console.log('🔍 [DEBUG] applyCheckboxSettingsToAllRows 함수 시작');
// 중복 실행 방지를 위한 플래그
if (window.isApplyingCheckboxSettings) {
console.log('⚠️ [DEBUG] 이미 실행 중입니다. 중복 실행 방지');
return;
}
window.isApplyingCheckboxSettings = true;
try {
// 체크박스 상태 확인
const warrantyChecked = document.getElementById('warranty').checked;
const slatcheckChecked = document.getElementById('slatcheck').checked;
const motorChecked = document.getElementById('motor').checked;
const steelChecked = document.getElementById('steel').checked;
const partscheckChecked = document.getElementById('partscheck').checked;
console.log('📋 [DEBUG] 체크박스 상태:', {
warranty: warrantyChecked,
slatcheck: slatcheckChecked,
motor: motorChecked,
steel: steelChecked,
partscheck: partscheckChecked
});
// 현재 선택된 제품 타입 확인
const selectedType = $('input[name="radio_item"]:checked').val();
console.log('🎯 [DEBUG] 선택된 제품 타입:', selectedType);
let targetTable = '';
let uncheckedClasses = {};
if (selectedType === '스크린') {
targetTable = '#estimateTable';
console.log('📺 [DEBUG] 스크린 테이블 선택됨:', targetTable);
// 스크린 테이블용 클래스 매핑 name
uncheckedClasses = {
'slatcheck': ['col10_SW', 'col11_SH'], // 주자재 - 제품명, 종류, 가이드레일, 마감유형
'motor': ['col18_brand','col18', 'col18_wireless', 'col19', 'col20', 'col21', 'col22','col15','col16','col17'], // 연동제어기 매립, 노출, 뒷박스, 모터 - 브랜드, 전원, 유/무선, 용량
'steel': [ 'col6','col7', 'col36_custom','col36_frontbottom','col36_railwidth','col36_boxdirection','col23', 'col24', 'col25', 'col26', 'col27', 'col28', 'col29', 'col30', 'col31', 'col32', 'col33', 'col34', 'col35', 'col36', 'col37', 'col38', 'col39', 'col40', 'col41', 'col42', 'col43', 'col44', 'col45', 'col46', 'col47', 'col48', 'col49', 'col50', 'col51', 'col52', 'col53', 'col54', 'col55', 'col56', 'col57'], // 절곡 - 모든 절곡 관련 컬럼
'partscheck': ['col59_inch','col59_length','col59','col60','col61','col62', 'col63', 'col64', 'col65', 'col66', 'col67', 'col68', 'col69', 'col70', 'col71', 'col72', 'col73', 'col74', 'col75'] // 부자재 - 부자재 관련 컬럼
};
} else if (selectedType === '철재') {
targetTable = '#estimateSlatTable';
console.log('🔧 [DEBUG] 철재 테이블 선택됨:', targetTable);
// 철재 테이블용 클래스 매핑 name
// 마지막에 조인트바 col76 강제로 체크사항에 넣음
uncheckedClasses = {
'slatcheck': ['col10_SW', 'col11_SH', 'col76'], // 주자재 - 제품명, 종류, 가이드레일, 마감유형
'motor': ['col19_brand','col19', 'col19_wireless', 'col20', 'col21', 'col22', 'col23', 'col16','col17','col18', 'col76'], // 연동제어기 매립, 노출, 뒷박스, 모터 - 브랜드, 전원, 유/무선, 용량
'steel': ['col37', 'col37_custom','col37_frontbottom', 'col37_railwidth', 'col37_boxdirection', 'col25', 'col26', 'col27', 'col28', 'col29', 'col30', 'col31', 'col32', 'col33', 'col34', 'col35', 'col36', 'col37', 'col39', 'col40', 'col41', 'col42', 'col43', 'col44', 'col45', 'col46_wing', 'col47', 'col48', 'col50', 'col51', 'col52', 'col53', 'col54', 'col55', 'col56', 'col57', 'col58' ], // 절곡 - 모든 절곡 관련 컬럼
'partscheck': ['col61','col62', 'col63', 'col64', 'col65', 'col66', 'col67', 'col68', 'col69', 'col70', 'col71', 'col74', 'col75', 'col77'] // 부자재 - 부자재 관련 컬럼 조인트바는 주자재로 인식
};
} else {
console.error('❌ [DEBUG] 제품 타입이 선택되지 않음');
alert('제품 타입을 선택해주세요.');
return;
}
// 테이블 존재 여부 확인
const tableExists = $(targetTable).length > 0;
console.log('📊 [DEBUG] 테이블 존재 여부:', tableExists, '테이블:', targetTable);
if (!tableExists) {
console.error('❌ [DEBUG] 테이블을 찾을 수 없음:', targetTable);
alert('테이블을 찾을 수 없습니다: ' + targetTable);
return;
}
// 테이블 내 행 수 확인
const rowCount = $(targetTable + ' tbody tr').length;
console.log('📈 [DEBUG] 테이블 행 수:', rowCount);
// 처리된 요소들을 추적하기 위한 Set
const processedElements = new Set();
let totalProcessedElements = 0;
// 체크되지 않은 항목들의 값을 빈 값으로 설정
Object.keys(uncheckedClasses).forEach(function(checkboxName) {
const checkbox = document.getElementById(checkboxName);
console.log('🔍 [DEBUG] 체크박스 확인:', checkboxName, '존재:', !!checkbox, '체크됨:', checkbox ? checkbox.checked : 'N/A');
if (checkbox && !checkbox.checked) {
const classesToClear = uncheckedClasses[checkboxName];
console.log('🧹 [DEBUG] 클리어할 클래스들:', checkboxName, classesToClear);
classesToClear.forEach(function(className) {
const elements = $(targetTable + ' tbody tr').find('input[name*="' + className + '"], select[name*="' + className + '"]');
console.log('🔍 [DEBUG] 클래스', className, '에 해당하는 요소 수:', elements.length);
$(targetTable + ' tbody tr').each(function(rowIndex) {
const row = $(this);
const rowElements = row.find('input[name*="' + className + '"], select[name*="' + className + '"]');
rowElements.each(function(elementIndex) {
const element = $(this)[0];
// 이미 처리된 요소는 건너뛰기
if (processedElements.has(element)) {
console.log('⏭️ [DEBUG] 이미 처리된 요소 건너뛰기:', className, '행:', rowIndex, '요소:', elementIndex);
return;
}
processedElements.add(element);
totalProcessedElements++;
const oldValue = $(this).val();
let newValue = '';
if ($(this).is('select')) {
$(this).val('').trigger('change');
newValue = '';
console.log('🔄 [DEBUG] SELECT 요소 값 변경:', className, '행:', rowIndex, '요소:', elementIndex, '이전값:', oldValue, '새값:', newValue);
} else {
// col10_SW, col11_SH인 경우 'x' 입력, 그 외는 빈 값
if (className === 'col10_SW' || className === 'col11_SH' ) {
$(this).val('x');
newValue = 'x';
} else if (className === 'col76') {
$(this).val('');
newValue = '';
// 조인트바 강제생성함
Slat_updateCo76(row) ;
} else {
$(this).val('');
newValue = '';
}
console.log('🔄 [DEBUG] INPUT 요소 값 변경:', className, '행:', rowIndex, '요소:', elementIndex, '이전값:', oldValue, '새값:', newValue);
}
});
});
});
} else {
console.log('✅ [DEBUG] 체크박스가 체크되어 있거나 존재하지 않음:', checkboxName);
}
});
console.log('📊 [DEBUG] 총 처리된 요소 수:', totalProcessedElements);
// 성공 메시지 표시
Toastify({
text: "체크박스 설정이 모든 행에 적용되었습니다. (처리된 요소: " + totalProcessedElements + "개)",
duration: 3000,
close: true,
gravity: "top",
position: "center",
style: {
background: "linear-gradient(to right, #00b09b, #96c93d)"
},
}).showToast();
// 계산 업데이트 (한 번만 실행)
if (typeof calculateAmounts === 'function') {
console.log('🧮 [DEBUG] calculateAmounts 함수 호출');
calculateAmounts();
} else {
console.warn('⚠️ [DEBUG] calculateAmounts 함수를 찾을 수 없음');
}
} catch (error) {
console.error('❌ [DEBUG] 오류 발생:', error);
alert('오류가 발생했습니다: ' + error.message);
} finally {
// 플래그 해제
window.isApplyingCheckboxSettings = false;
console.log('🏁 [DEBUG] applyCheckboxSettingsToAllRows 함수 종료');
}
}
</script>
</td>
</tr>
<tr <?php if(!empty($itemoption)) echo 'style="display:none;"'; ?> >
<td class="text-end" style="width:90px;"> 현 장 명 </td>
<td style="width:400px;">
<input type="text" id="outworkplace" name="outworkplace" value="<?=$outworkplace?>" class="form-control searchplace text-start me-1" >
</td>
<td class="text-end" style="width:60px;" > 비고 </td>
<td >
<div class="d-flex p-1 mb-1 justify-content-start align-items-center ">
<textarea id="comment" name="comment" class="form-control text-dark" style="height: 55px;" placeholder="기타 사항 기록" ><?=$comment?></textarea>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="col-sm-4">
<div class="d-flex mb-1 justify-content-center align-items-center ">
<div class="d-flex align-items-center justify-content-end mt-0">
<table class="table table-bordered mt-0 text-end w-auto">
<thead >
<tr>
<th colspan="5" class="text-end">공급가액 기준, VAT별도</th>
</tr>
<tr class="table-secondary">
<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>
<tr>
<td>
<input type="text" id="estimateSurang" name="estimateSurang" class="form-control text-center" readonly >
</td>
<td>
<input type="text" id="EstimateFirstSum" name="EstimateFirstSum" class="form-control text-end text-primary" readonly
value="<?= isset($EstimateFirstSum) && !empty($EstimateFirstSum) && is_numeric($EstimateFirstSum) ? number_format((float)$EstimateFirstSum) : '' ?>">
</td>
<td>
<input type="text" id="EstimateUpdatetSum" name="EstimateUpdatetSum" class="form-control text-end text-primary" readonly
value="<?= isset($EstimateUpdatetSum) && !empty($EstimateUpdatetSum) && is_numeric($EstimateUpdatetSum) ? number_format((float)$EstimateUpdatetSum) : '' ?>">
</td>
<td>
<input type="text" id="EstimateDiffer" name="EstimateDiffer" class="form-control text-end text-danger" readonly
value="<?= isset($EstimateDiffer) && !empty($EstimateDiffer) && is_numeric($EstimateDiffer) ? number_format((float)$EstimateDiffer) : '' ?>">
</td>
<td>
<input type="text" id="estimateTotal" name="estimateTotal" class="form-control text-end" readonly
value="<?= isset($estimateTotal) && $estimateTotal != 0 ? number_format($estimateTotal) : $estimateTotal ?>">
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<div class="d-flex justify-content-center align-items-center">
<span class="text-dark fs-6 me-4"> 공통 제작치수 적용 </span>
<span class="text-primary fs-6 mx-1"> 가로(폭) </span>
<input type="text" id="makeWidth" name="makeWidth" value="<?php echo htmlspecialchars($makeWidth); ?>" class="form-control text-primary fs-6 w60px me-2">
<span class="text-danger fs-6 mx-1"> 세로(높이) </span>
<input type="text" id="makeHeight" name="makeHeight" value="<?php echo htmlspecialchars($makeHeight); ?>" class="form-control text-danger fs-6 w60px">
<span class="text-success fs-6 ms-4 me-1"> 마구리 날개치수 </span>
<input type="text" id="maguriWing" name="maguriWing" value="<?php echo htmlspecialchars($maguriWing); ?>" class="form-control text-success fs-6 w60px">
<span class="text-dark fs-6 ms-4 me-1"> 검사비 설정 </span>
<input type="text"
id="inspectionFee"
name="inspectionFee"
value="<?php echo htmlspecialchars($inspectionFeeFormatted); ?>"
class="form-control text-dark text-end fs-6 w80px col-input"
onclick="this.select();"
oninput="NumberWithComma(this);">
<span class="text-secondary fs-6 ms-5 me-1"> ※ 값을 설정하고 행을 추가해 주세요. 이 값이 반영됩니다. </span>
</div>
</div>
</div>
</div>
<div id="ScreenSection" >
<div class="row">
<div class="col-sm-4">
<div class="d-flex justify-content-end mt-2">
<button type='button' id='view_screenguidebookBtn' class='btn btn-primary btn-sm ms-2 me-3 mt-1'> <i class='bi bi-chevron-down'></i> </button>
</div>
</div>
<div class="col-sm-8">
<div id="view_screenguidebook">
<div class="d-flex justify-content-start mt-2">
<table class="table table-bordered w-85">
<thead class="table-secondary">
<tr>
<th>상품명</th>
<th>제품명</th>
<th>제품명 설명</th>
<th>비고</th>
</tr>
</thead>
<tbody>
<tr>
<td class="text-start">국민방화 스크린 셔터</td>
<td class="text-start">KSS01</td>
<td class="text-start">K(경동:국민방화 브랜드명) S(실리카코팅직물 스크린) S(SUS마감)</td>
<td class="text-start"></td>
</tr>
<tr>
<td class="text-start">국민방화 스크린 셔터</td>
<td class="text-start">KSS02</td>
<td class="text-start">K(경동:국민방화 브랜드명) S(실리카코팅직물 스크린) S(SUS마감)</td>
<td class="text-start"></td>
</tr>
<tr>
<td class="text-start">국민방화 스크린 셔터</td>
<td class="text-start">KSE01</td>
<td class="text-start">K(경동:국민방화 브랜드명) S(실리카코팅직물 스크린) E(EGI마감)</td>
<td class="text-start"></td>
</tr>
<tr>
<td class="text-start">국민방화 스크린 플러스 셔터</td>
<td class="text-start">KWE01</td>
<td class="text-start">K(경동:국민방화 브랜드명) W(와이어글라스코팅직물 스크린) E(EGI마감)</td>
<td class="text-start">SUS 마감일 경우 --- 기존 EGI 마감재에 SUS 마감재로 덧방 추가</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<?php include $_SERVER['DOCUMENT_ROOT'] . '/estimate/common/common_screen.php'; // 견적서에서 screen 화면 테이블 공통부분
// 스크린셔터
generateTableSection('estimate', '스크린셔터', $badgeClass = 'bg-primary', $user_id, '견적서', $mode);
?>
</div> <!-- end of ScreenSection -->
<div id="SlatSection">
<div class="row">
<div class="col-sm-4">
<div class="d-flex justify-content-end mt-2">
<button type='button' id='view_slatguidebookBtn' class='btn btn-success btn-sm ms-2 me-3 mt-1'> <i class='bi bi-chevron-down'></i> </button>
</div>
</div>
<div class="col-sm-8">
<div id="view_slatguidebook">
<div class="d-flex justify-content-start mt-2">
<table class="table table-bordered ">
<thead class="table-success">
<tr>
<th>상품명</th>
<th>제품명</th>
<th>제품명 설명</th>
<th>비고</th>
</tr>
</thead>
<tbody>
<tr>
<td class="text-start">국민방화 스틸 셔터</td>
<td class="text-start">KD-SL60</td>
<td class="text-start">KD(경동:국민방화 브랜드명) SL(철재 : SLAT) 60(비차열 60분)</td>
<td class="text-start">해당 성적서는 사용 안하고 있음 - KTE01 및 KQTS01로 대체 사용중</td>
</tr>
<tr>
<td class="text-start">국민방화 스틸 셔터</td>
<td class="text-start">KTE01</td>
<td class="text-start">K(경동:국민방화 브랜드명) T(철재 : Steel) E(EGI마감)</td>
<td class="text-start"></td>
</tr>
<tr>
<td class="text-start">국민방화 투시형 스틸 셔터</td>
<td class="text-start">KQTS01</td>
<td class="text-start">K(경동:국민방화 브랜드명) Q(투시형 : Quartz) T(철재 : Steel) S(SUS마감)</td>
<td class="text-start">투시창 생략하여 제작 설치 가능</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<?php include $_SERVER['DOCUMENT_ROOT'] . '/estimate/common/common_slat.php'; // 견적서에서 slat 화면 테이블 공통부분
generateTableSection_slat('estimateSlat', '철재(스라트)', $badgeClass = 'bg-success', $user_id, '견적서', $mode);
?>
</div>
</div> <!-- end of SlatSection -->
</div>
</div>
</form>
<script>
const authorities = <?php echo json_encode($authorities, JSON_UNESCAPED_UNICODE); ?>;
// console.log(authorities); // 배열 출력
function inputNumbers(input) {
input.value = input.value.replace(/[^0-9.]/g, '');
}
function isZeroOrEmpty(value) {
return value === '0' || value === '';
}
function captureReturnKey(e) {
if(e.keyCode==13 && e.srcElement.type != 'textarea')
return false;
}
$(document).ready(function() {
$(document).on('click', '.fetch_receiverBtn', function() {
callreceiver();
});
$('#receiver').on('keypress', function(event) {
if (event.keyCode === 13) { // 엔터키의 코드는 13입니다.
callreceiver();
}
});
});
</script>
<script>
// 페이지 로딩
$(document).ready(function(){
var loader = document.getElementById('loadingOverlay');
if(loader)
loader.style.display = 'none';
});
</script>
<script>
var mode = $("#mode").val();
var ajaxRequest_write = null;
</script>
<script>
var dataTable; // DataTables 인스턴스 전역 변수
var outputpageNumber; // 현재 페이지 번호 저장을 위한 전역 변수
var ajaxRequest_write = null;
$(document).ready(function() {
// DataTables 초기 설정
dataTable = $('#myTable').DataTable({
"paging": true,
"ordering": true,
"searching": true,
"pageLength": 500,
"lengthMenu": [200, 500, 1000],
"language": {
"lengthMenu": "Show _MENU_ entries",
"search": "Live Search:"
},
"order": [[0, 'asc']]
});
// 페이지 번호 복원 (초기 로드 시)
var savedPageNumber = getCookie('estimatepageNumber');
if (savedPageNumber) {
dataTable.page(parseInt(savedPageNumber) - 1).draw(false);
}
// 페이지 변경 이벤트 리스너
dataTable.on('page.dt', function() {
var estimatepageNumber = dataTable.page.info().page + 1;
setCookie('estimatepageNumber', estimatepageNumber, 10); // 쿠키에 페이지 번호 저장
});
// 페이지 길이 셀렉트 박스 변경 이벤트 처리
$('#myTable_length select').on('change', function() {
var selectedValue = $(this).val();
dataTable.page.len(selectedValue).draw(); // 페이지 길이 변경 (DataTable 파괴 및 재초기화 없이)
// 변경 후 현재 페이지 번호 복원
savedPageNumber = getCookie('estimatepageNumber');
if (savedPageNumber) {
dataTable.page(parseInt(savedPageNumber) - 1).draw(false);
}
});
});
function restorePageNumber() {
var savedPageNumber = getCookie('estimatepageNumber');
// if (savedPageNumber) {
// dataTable.page(parseInt(savedPageNumber) - 1).draw('page');
// }
location.reload(true);
}
$(document).ready(function(){
$("#copyBtn").click(function(){
location.href = 'write_form.php?mode=copy&num=' + $("#num").val() + "&tablename=" + $("#tablename").val() ;
}); // end of function
$("#viewscreenBtn").click(function(){
var url = '/make/write_form_new.php?mode=view&num=' + $("#num").val() + "&tablename=" + $("#tablename").val() ;
customPopup(url, '스크린 작업지시서', 1850, 900);
}); // end of function
$("#viewslatBtn").click(function(){
var url = '/egimake/write_form_new.php?mode=view&num=' + $("#num").val() + "&tablename=" + $("#tablename").val() ;
customPopup(url, '철재(스라트) 작업지시서', 1850, 900);
}); // end of function
// 삭제버튼
$("#deleteBtn").click( function() {
var update_log = $("#update_log").val();
var user_name = $("#user_name").val();
var level = $("#level").val();
if (!update_log.includes(user_name) && level !== '1')
{
Swal.fire({
title: '삭제불가',
text: "작성자와 관리자만 삭제가능합니다.",
icon: 'error',
confirmButtonText: '확인'
});
} else {
Swal.fire({
title: '자료 삭제',
text: "삭제는 신중! 정말 삭제하시겠습니까?",
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: '삭제',
cancelButtonText: '취소'
}).then((result) => {
if (result.isConfirmed) {
$("#mode").val('delete'); // `mode` 값을 설정
var form = $('#board_form')[0];
var formData = new FormData(form); // `formData`를 여기에서 정의합니다.
// `formData`에 필요한 추가 데이터를 수동으로 설정
formData.set('mode', $("#mode").val());
formData.set('num', $("#num").val());
// console.log('mode', $("#mode").val());
// console.log('num', $("#num").val());
if ( (typeof ajaxRequest_write !== 'undefined' && ajaxRequest_write) || ajaxRequest_write!==null ) {
ajaxRequest_write.abort();
}
ajaxRequest_write = $.ajax({
enctype: 'multipart/form-data', // file을 서버에 전송하려면 이렇게 해야 함 주의
processData: false,
contentType: false,
cache: false,
timeout: 1000000,
url: "insert.php",
type: "post",
data: formData,
dataType: "json",
success : function( data ){
// console.log(data);
Toastify({
text: "파일 삭제완료 ",
duration: 2000,
close:true,
gravity:"top",
position: "center",
style: {
background: "linear-gradient(to right, #00b09b, #96c93d)"
},
}).showToast();
setTimeout(function(){
if (window.opener && !window.opener.closed) {
// 부모 창에 restorePageNumber 함수가 있는지 확인
if (typeof window.opener.restorePageNumber === 'function') {
window.opener.restorePageNumber(); // 함수가 있으면 실행
}
// window.opener.location.reload(); // 부모 창 새로고침
window.close();
}
}, 2000);
},
error : function( jqxhr , status , error ){
console.log( jqxhr , status , error );
}
});
}
});
}
});
// 화면이 시작된 후
hideOverlay();
});
function inputNumberFormat(input) {
input.value = input.value.replace(/\D/g, '').replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
function saveData() {
const myform = document.getElementById('board_form');
let allValid = true;
if (!allValid) return;
var num = $("#num").val();
showMsgModal(2); // 파일저장중
// 복사일때는 insert로 처리함
if($("#mode").val() !=='copy')
{
if (Number(num) < 1) {
$("#mode").val('insert');
} else {
$("#mode").val('modify');
}
}
else
{
$("#mode").val('insert');
}
// **계산이 끝난 뒤 이 내부 콜백이 실행됩니다**
calculateAmounts(function() {
// ① 계산 결과를 스냅샷에 저장
collectAndSave();
// 선택된 라디오 버튼 값을 수집
var selectedRadio = $("input[name='radio_item']:checked").val();
$("#major_category").val(selectedRadio);
var form = $('#board_form')[0];
var datasource = new FormData(form);
if (ajaxRequest_write !== null) {
ajaxRequest_write.abort();
}
ajaxRequest_write = $.ajax({
enctype: 'multipart/form-data',
processData: false,
contentType: false,
cache: false,
timeout: 600000,
url: "insert.php",
type: "post",
data: datasource,
dataType: "json",
success: function(data) {
console.log(data);
setTimeout(function() {
if (window.opener && !window.opener.closed) {
if (typeof window.opener.restorePageNumber === 'function') {
window.opener.restorePageNumber(); // 함수가 있으면 실행
}
}
setTimeout(function() {
hideMsgModal();
if (data && data.num)
// 저장된 데이터 번호를 사용하여 새로운 페이지로 이동
window.location.href = 'write_form.php?mode=view&tablename=' + $('#tablename').val() + '&num=' + data.num;
}, 1000);
}, 1500);
hideOverlay();
hideMsgModal();
},
error: function(jqxhr, status, error) {
console.log(jqxhr, status, error);
hideMsgModal();
}
});
});
}
// 저장 버튼 클릭 핸들러 등에서 실행
function collectAndSave() {
const actualList = []; // 사용자가 수정한 최종값
const autoList = []; // 자동산출 스냅샷
$('#estimateTable tbody tr').each(function() {
const rowActual = {};
const rowAuto = {};
$(this).find('input, select').each(function() {
const name = $(this).attr('name').replace('[]', '');
const curVal = $(this).val() || '';
const autoVal = $(this).attr('data-auto') || '';
rowActual[name] = curVal;
rowAuto[name] = autoVal;
});
actualList.push(rowActual);
autoList.push(rowAuto);
});
// 첫 번째 테이블 값 저장
$('#estimateList').val( JSON.stringify(actualList) );
$('#estimateList_auto').val( JSON.stringify(autoList) );
// 두 번째(슬랫) 테이블도 동일하게
const actualListSlat = [];
const autoListSlat = [];
$('#estimateSlatTable tbody tr').each(function() {
const rowActual = {};
const rowAuto = {};
$(this).find('input, select').each(function() {
const name = $(this).attr('name').replace('[]', '');
const curVal = $(this).val() || '';
const autoVal = $(this).attr('data-auto') || '';
rowActual[name] = curVal;
rowAuto[name] = autoVal;
});
actualListSlat.push(rowActual);
autoListSlat.push(rowAuto);
});
$('#estimateSlatList').val(JSON.stringify(actualListSlat) );
$('#estimateSlatList_auto').val(JSON.stringify(autoListSlat) );
}
function deleteData() {
var level = '<?php echo isset($level) ? $level : ''; ?>';
if (!first_writer.includes(first_writer) && level !== '1') {
Swal.fire({
title: '삭제불가',
text: "작성자와 관리자만 삭제가능합니다.",
icon: 'error',
confirmButtonText: '확인'
});
} else {
Swal.fire({
title: '자료 삭제',
text: "삭제는 신중! 정말 삭제하시겠습니까?",
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: '삭제',
cancelButtonText: '취소'
}).then((result) => {
if (result.isConfirmed) {
$("#mode").val('delete');
var form = $('#board_form')[0];
var formData = new FormData(form);
formData.set('mode', $("#mode").val());
formData.set('num', $("#num").val());
if (ajaxRequest_write !== null) {
ajaxRequest_write.abort();
}
ajaxRequest_write = $.ajax({
enctype: 'multipart/form-data',
processData: false,
contentType: false,
cache: false,
timeout: 1000000,
url: "insert_estimate.php",
type: "post",
data: formData,
dataType: "json",
success: function(data) {
Toastify({
text: "파일 삭제완료 ",
duration: 2000,
close: true,
gravity: "top",
position: "center",
style: {
background: "linear-gradient(to right, #00b09b, #96c93d)"
},
}).showToast();
setTimeout(function() {
if (window.opener && !window.opener.closed) {
if (typeof window.opener.restorePageNumber === 'function') {
window.opener.restorePageNumber();
}
window.opener.location.reload();
window.close();
}
}, 1000);
},
error: function(jqxhr, status, error) {
console.log(jqxhr, status, error);
}
});
}
});
}
}
$(document).ready(function() {
// Log 파일보기
$("#showlogBtn").click( function() {
var num = '<?php echo $num; ?>'
// table 이름을 넣어야 함
var workitem = $("#tablename").val();
// 버튼 비활성화
var btn = $(this);
popupCenter("../Showlog.php?num=" + num + "&workitem=" + workitem , '로그기록', 500, 500);
btn.prop('disabled', false);
});
// 모든행에 적용하기 버튼 클릭 이벤트
$("#applyToAllRowsBtn").click(function() {
// 중복 클릭 방지
if (window.isApplyingCheckboxSettings) {
return;
}
// 확인 다이얼로그 표시
Swal.fire({
title: '설정 적용 확인',
text: '체크박스 설정을 모든 행에 적용하시겠습니까?',
icon: 'question',
showCancelButton: true,
confirmButtonText: '적용',
cancelButtonText: '취소'
}).then((result) => {
if (result.isConfirmed) {
applyCheckboxSettingsToAllRows();
}
});
});
});
function phonebookBtn(searchfield)
{
var search = $("#" + searchfield).val();
href = '../phonebook/list.php?search=' + search ;
popupCenter(href, '전화번호 검색', 1600, 800);
}
</script>
<script>
var ajaxRequest = null;
var ajaxRequest_write = null;
var hallDoorOptions = [] ;
var carDoorOptions = [];
var carWallOptions = [];
var etcOptions = [];
$(document).ready(function() {
initializePage();
bindEventHandlers();
$("#saveBtn").click(function() {
saveData();
});
// 발주서에 적용하기 버튼 클릭 이벤트 처리
$("#adaptParentBtn").click(function() {
// 팝업 창에서 데이터 저장 및 부모 창에 전달
const myform = document.getElementById('board_form');
let allValid = true;
// 유효성 검사 실패 시 리턴
if (!allValid) return;
var num = $("#num").val();
$("#overlay").show();
$("button").prop("disabled", true);
// 현재 창의 값을 부모창으로 전달
if (window.opener && !window.opener.closed) {
const currentMakeWidth = $("#makeWidth").val();
const currentMakeHeight = $("#makeHeight").val();
const currentMaguriWing = $("#maguriWing").val();
const currentInspectionFee = $("#inspectionFee").val();
// 부모창에 해당 필드가 있는 경우에만 값 설정
if (window.opener.$("#makeWidth").length) {
window.opener.$("#makeWidth").val(String(currentMakeWidth || ''));
}
if (window.opener.$("#makeHeight").length) {
window.opener.$("#makeHeight").val(String(currentMakeHeight || ''));
}
if (window.opener.$("#maguriWing").length) {
window.opener.$("#maguriWing").val(String(currentMaguriWing || ''));
}
if (window.opener.$("#inspectionFee").length) {
window.opener.$("#inspectionFee").val(String(currentInspectionFee || ''));
}
}
Toastify({
text: "발주서에 적용중...",
duration: 2000,
close: true,
gravity: "top",
position: "center",
style: {
background: "linear-gradient(to right, #00b09b, #96c93d)"
},
}).showToast();
let formData = [];
let jsonString = '';
if($("#major_category").val() == '스크린')
{
// estimateTable의 데이터를 JSON으로 직렬화
$('#estimateTable tbody tr').each(function() {
let rowData = {};
$(this).find('input, select').each(function() {
let name = $(this).attr('name').replace('[]', '');
let value = $(this).val();
rowData[name] = value;
});
formData.push(rowData);
});
jsonString = JSON.stringify(formData);
$('#estimateList').val(jsonString);
}
else if($("#major_category").val() == '철재')
{
// estimateTable의 데이터를 JSON으로 직렬화
$('#estimateSlatTable tbody tr').each(function() {
let rowData = {};
$(this).find('input, select').each(function() {
let name = $(this).attr('name').replace('[]', '');
let value = $(this).val();
rowData[name] = value;
});
formData.push(rowData);
});
jsonString = JSON.stringify(formData);
$('#estimateSlatList').val(jsonString);
}
// 부모 창에 데이터를 전달
if (window.opener && !window.opener.closed) {
// 부모 창의 숨겨진 필드 estimateList에 데이터 저장
if($("#major_category").val() == '스크린')
{
window.opener.document.getElementById('estimateList').value = jsonString;
}
else if($("#major_category").val() == '철재')
{
window.opener.document.getElementById('estimateSlatList').value = jsonString;
}
const parsedData = JSON.parse(jsonString); // 파싱된 배열 전달
// 복사할 필드 ID 목록
const fields = [
'estimateSurang',
'EstimateFirstSum',
'EstimateUpdatetSum',
'EstimateDiffer',
'estimateTotal',
'makeWidth',
'makeHeight',
'maguriWing',
'inspectionFee'
];
// 하나라도 오류가 나오면 전체 전달이 안된다.
$.each(fields, function(_, id) {
// 팝업창 내 값 읽기
const val = $('#' + id).val() || '';
// 부모창 요소 찾기
const $parentInput = $(window.opener.document).find('#' + id);
if ($parentInput.length) {
// 존재하면 값 대입
$parentInput.val(val);
console.log(`[DEBUG] 부모창에 '${id}' 입력란이 있습니다. 값="${val}" 로 설정됨.`);
} else {
// 없으면 경고
console.warn(`[DEBUG] 부모창에 '${id}' 입력란을 찾을 수 없습니다!`);
}
});
// 체크박스에 대한 처리 부모창에 checkbox 그대로 체크해주기
const checkFields = [
'steel', // 체크5개 요소 전달
'motor',
'warranty',
'slatcheck',
'partscheck'
];
$.each(checkFields, function(_, id) {
const isChecked = $('#' + id).prop('checked');
const $parentInput = $(window.opener.document).find('#' + id);
if ($parentInput.length) {
$parentInput.prop('checked', isChecked);
}
});
if($("#major_category").val() == '스크린')
{
// Check if screenTable has existing rows
if(window.opener.document.getElementById('screenTable').getElementsByTagName('tr').length > 0) {
Swal.fire({
title: '스크린 발주서 기존데이터에 덮어쓰시겠습니까?',
icon: 'question',
showCancelButton: true,
confirmButtonText: '네',
cancelButtonText: '아니오'
}).then((result) => {
if (result.isConfirmed) {
window.opener.renderEstimateData({ estimateList: parsedData }, "reload");
// 일정 시간 후 창을 닫음
setTimeout(function() {
window.close();
}, 1000);
} else {
window.opener.renderEstimateData({ estimateList: parsedData }, null);
// 일정 시간 후 창을 닫음
setTimeout(function() {
window.close();
}, 1000);
}
});
} else {
window.opener.renderEstimateData({ estimateList: parsedData }, "reload");
// 일정 시간 후 창을 닫음
setTimeout(function() {
window.close();
}, 1000);
}
}
else if($("#major_category").val() == '철재')
{
// Check if slatTable has existing rows
if(window.opener.document.getElementById('slatTable').getElementsByTagName('tr').length > 0) {
Swal.fire({
title: '철재 슬랫 발주서 기존데이터에 덮어쓰시겠습니까?',
icon: 'question',
showCancelButton: true,
confirmButtonText: '네',
cancelButtonText: '아니오'
}).then((result) => {
if (result.isConfirmed) {
window.opener.renderEstimateData_slat({ estimateSlatList: parsedData }, "reload");
// 일정 시간 후 창을 닫음
setTimeout(function() {
window.close();
}, 1000);
} else {
window.opener.renderEstimateData_slat({ estimateSlatList: parsedData }, null);
// 일정 시간 후 창을 닫음
setTimeout(function() {
window.close();
}, 1000);
}
});
} else {
window.opener.renderEstimateData_slat({ estimateSlatList: parsedData }, "reload");
// 일정 시간 후 창을 닫음
setTimeout(function() {
window.close();
}, 1000);
}
}
} else {
alert('부모창을 찾을 수 없습니다.');
return;
// 일정 시간 후 창을 닫음
setTimeout(function() {
window.close();
}, 1000);
}
});
$("#viewEstimateUnit").click(function() {
// var url = '/output/estimateUnit.php';
var url = '/estimate/list_unit.php?header=no';
customPopup(url, '견적 단가 관리', 1850, 900);
});
$("#viewEstimate").click(function() {
var num = $("#num").val();
var url = '/estimate/EsDetail_screen.php?option=option&num=' + num;
customPopup(url, '견적서', 1200, 900);
});
$("#viewEstimateDetail").click(function() {
var num = $("#num").val();
var url = '/estimate/EsDetail_screen.php?num=' + num;
customPopup(url, '견적 산출내역서', 1200, 900);
});
$("#viewEstimateSlatUnit").click(function() {
// var url = '/output/estimateUnit.php';
var url = '/estimate/list_unit.php?header=no';
customPopup(url, '견적 단가 관리', 1850, 900);
});
$("#viewEstimateSlat").click(function() {
var num = $("#num").val();
// option이 있으면 산출내역 없음
var url = '/estimate/EsDetail_slat.php?option=option&num=' + num;
customPopup(url, '견적서', 1200, 900);
});
$("#viewEstimateSlatDetail").click(function() {
var num = $("#num").val();
var url = '/estimate/EsDetail_slat.php?num=' + num;
customPopup(url, '견적산출', 1200, 900);
});
$(".deleteBtn").click(function() {
deleteData();
});
});
// 초기 페이지 설정
function initializePage() {
var loader = document.getElementById('loadingOverlay');
if (loader) loader.style.display = 'none';
// 쿠키 기반 초기 뷰 상태
initializeView('estimate_screenDiv', 'showEsimateScreenView', "block");
initializeView('estimate_slatDiv', 'showEsimateslatView', "block");
// 실제값과 자동산출값 둘 다 PHP에서 JSON으로 가져오기
var estimate = <?php echo json_encode($estimateList ?? []); ?>;
var estimateAuto = <?php echo json_encode($estimateList_auto ?? []); ?>;
var estimateSlat = <?php echo json_encode($estimateSlatList ?? []); ?>;
var estimateSlatAuto = <?php echo json_encode($estimateSlatList_auto?? []); ?>;
// 데이터 유무에 따라 div 토글
if (estimate.length > 0) $("#estimate_screenDiv").show();
if (estimateSlat.length > 0) $("#estimate_slatDiv").show();
// 테이블 로드 (actual, auto 둘 다 넘김)
loadTableData('#estimateTable', estimate, estimateAuto,
'estimate');
loadTableData('#estimateSlatTable', estimateSlat, estimateSlatAuto,
'estimateSlat');
}
// loadTableData 함수 시그니처 변경
function loadTableData(tableId, dataList, autoList, typebutton) {
var tableBody = $(tableId).find('tbody');
var theadId = (tableId === '#estimateTable')
? '#thead_estimate'
: '#thead_estimateSlat';
// JSON 파싱 안전 처리
if (typeof dataList === 'string') {
try { dataList = JSON.parse(dataList); }
catch (e) { console.error(e); dataList = []; }
}
if (typeof autoList === 'string') {
try { autoList = JSON.parse(autoList); }
catch (e) { console.error(e); autoList = []; }
}
$(theadId).show();
if (!Array.isArray(dataList)) dataList = [];
if (!Array.isArray(autoList)) autoList = [];
if (dataList.length === 0) {
$(tableId === '#estimateTable'
? "#estimate_screenDiv"
: "#estimate_slatDiv"
).hide();
return;
}
// 실제값과 자동값을 인덱스로 매칭해서 addRow 호출
dataList.forEach(function(item, idx) {
var autoItem = autoList[idx] || {};
if (tableId === '#estimateTable') {
addRow(tableBody, item, typebutton, null, autoItem);
} else {
addRow_slat(tableBody, item, typebutton, null, autoItem);
}
});
$(tableId === '#estimateTable'
? "#estimate_screenDiv"
: "#estimate_slatDiv"
).show();
}
// 공통 함수: 페이지 로드 시 쿠키를 기반으로 각 요소의 표시 상태 설정
function initializeView(viewId, cookieName, status) {
var view = getCookie(cookieName);
var listContainer = $("#" + viewId);
if (view === "show") {
listContainer.css("display", status);
} else {
listContainer.css("display", status); // 항상열리게 하려면 여기서 조정한다.
// listContainer.css("display", "none");
}
}
// 이벤트 핸들러 바인딩
function bindEventHandlers() {
if (mode == 'view') {
disableView();
}
$(document).on('click', '.remove-row', function() {
if (mode !== 'view') {
var currentRow = $(this).closest('tr');
var tableBody = currentRow.closest('tbody');
// 현재 행 제거
currentRow.remove();
// 남아있는 행들의 col1 값을 다시 정렬
tableBody.children('tr').each(function(index) {
$(this).find('input[name="col1[]"]').val(index + 1);
});
alertToast('행 삭제');
Screen_updateTotals();
}
});
$(document).on('click', '.close-modal', function() {
$(this).closest('.modal').modal('hide');
});
// add-row는 두개로 나눠야 한다. 함수호출이 다르니... remove-row, copy-row는 한개로 가능하다.
$(document).on('click', '.add-row', function () {
if (mode !== 'view') {
// console.log('add-row 호출됨');
$("#estimate_screenDiv").show();
var tableId = $(this).data('table');
var tableBody = $('#' + tableId).find('tbody');
var currentRow = $(this).closest('tr');
addRow(tableBody, {}, tableId, currentRow); // ← 현재 행 다음에 삽입
alertToast('행 추가');
Screen_updateTotals();
}
});
$(document).on('click', '.add-row-slat', function () {
if (mode !== 'view') {
// console.log('add-row-slat 호출됨');
$("#estimate_slatDiv").show();
var tableId = $(this).data('table');
var tableBody = $('#' + tableId).find('tbody');
var currentRow = $(this).closest('tr');
addRow_slat(tableBody, {}, tableId, currentRow); // ← 현재 행 다음에 삽입
alertToast('행 추가');
Screen_updateTotals();
}
});
// 행 복사
$(document).on('click', '.copy-row', function() {
if (mode !== 'view') {
var currentRow = $(this).closest('tr');
var tableBody = currentRow.closest('tbody');
var clonedRow = currentRow.clone(true); // true로 이벤트와 데이터를 복사
// 전체 행 수를 기준으로 새로운 col1 값 설정
var newCol1Value = tableBody.children('tr').length + 1;
clonedRow.find('input, select').each(function(index) {
var currentInput = currentRow.find('input, select').eq(index);
// col1 값이 있는 필드인 경우, 새로 계산된 값 설정
if ($(this).attr('name') === 'col1[]') {
$(this).val(newCol1Value);
} else {
// 나머지 필드는 그대로 복사
$(this).val(currentInput.val());
}
});
// 현재 행 바로 아래에 추가
currentRow.after(clonedRow);
alertToast('행 복사');
updateSerialNumbers(tableBody);
Screen_updateTotals();
Slat_updateTotals();
}
});
// 철재 처리부분
$(document).on('click', '.remove-row', function() {
if (mode !== 'view') {
$(this).closest('tr').remove();
alertToast('행삭제');
Slat_updateTotals();
}
});
}
function alertToast(message) {
// 기본 배경 색상 (초록)
let backgroundColor = "linear-gradient(to right, #00b09b, #96c93d)";
// 조건에 따라 색상 변경
if (message.includes("추가")) {
backgroundColor = "linear-gradient(to right, #2196F3, #21CBF3)"; // 파란 계열
} else if (message.includes("삭제")) {
backgroundColor = "linear-gradient(to right, #f44336, #e57373)"; // 빨간 계열
} else if (message.includes("복사")) {
backgroundColor = "linear-gradient(to right, #4CAF50, #81C784)"; // 녹색 계열
}
Toastify({
text: message,
duration: 2000,
close: true,
gravity: "top",
position: "center",
style: {
background: backgroundColor
},
}).showToast();
}
function showModal(options, modalId, modalBodyId, input) {
targetInput = input;
$(modalBodyId).empty();
options.forEach(function(item) {
$(modalBodyId).append('<tr><td class="text-center">' + item + '</td></tr>');
});
$(modalId).modal('show');
}
function inputNumberFormat(input) {
// 콤마 제거 후 숫자만 남기기
let value = input.value.replace(/[^\d]/g, '');
// 3자리마다 콤마 추가
if (value) {
value = parseInt(value).toLocaleString();
}
input.value = value;
}
function NumberWithComma(input) {
// 콤마 제거 후 숫자만 남기기
let value = input.value.replace(/[^\d]/g, '');
// 3자리마다 콤마 추가
if (value) {
value = parseInt(value).toLocaleString();
}
input.value = value;
}
function disableView() {
// 수동 편집된 요소는 제외하고 나머지를 readonly 처리
$('input, textarea, select')
.not('.manually-edited')
.prop('readonly', true);
// 히든 필드와 수동 편집된 히든 필드는 건드리지 않기
$('input[type=hidden]')
.not('.manually-edited')
.prop('readonly', false);
// select와 버튼들 disabled 설정
$('select, .restrictbtn, .sub_add, .add').prop('disabled', true);
// 파일 input은 readonly 해제
$('input[type=file]').prop('readonly', false);
// 버튼들 disabled 설정
$('.viewNoBtn').prop('disabled', true);
$('.specialbtnClear').prop('disabled', true);
// 버튼 비활성화 (수동 편집 여부와 상관 없이)
$('button.add-row, button.remove-row, button.copy-row')
.prop('disabled', true);
// 모든행에 적용하기 버튼 비활성화
$('#applyToAllRowsBtn').prop('disabled', true);
// checkbox/radio 통합 처리 - disabled 대신 클릭 이벤트 차단
$('input[type="checkbox"], input[type="radio"]')
.each(function() {
if (!$(this).hasClass('manually-edited')) {
// disabled 속성 제거하고 스타일만 적용
$(this).removeProp('disabled')
.addClass('readonly-checkbox readonly-radio');
// 클릭 이벤트 차단
$(this).on('click', function(event) {
event.preventDefault();
return false;
});
}
});
// 파일 입력 비활성화
$('input[type=file]')
.not('.manually-edited')
.prop('disabled', true);
$('.fetch_receiverBtn, .viewmode')
.not('.manually-edited')
.prop('disabled', true);
// 레이블 텍스트 크게 설정
$('label').css('font-size', '1.2em');
// select 속성 readonly 효과 내기
$('select[data-readonly="true"]').on('mousedown', function(event) {
event.preventDefault();
});
// select[data-readonly] 에 마우스 다운 차단 (수동 편집된 건 제외)
document.querySelectorAll('select[data-readonly="true"]').forEach(function(select) {
if (!select.classList.contains('manually-edited')) {
select.addEventListener('mousedown', function(event) {
event.preventDefault();
});
}
});
console.log('disableView 함수 호출');
}
function captureReturnKey(e) {
if (e.keyCode == 13 && e.srcElement.type != 'textarea') {
return false;
}
}
function recaptureReturnKey(e) {
if (e.keyCode == 13 && e.srcElement.type != 'textarea') {
return false;
}
}
function closePopup() {
if (popupWindow && !popupWindow.closed) {
popupWindow.close();
isWindowOpen = false;
}
}
function showWarningModal() {
Swal.fire({
title: '등록 오류 알림',
text: '필수입력 요소를 확인바랍니다.',
icon: 'warning',
}).then(result => {
if (result.isConfirmed) {
return;
}
});
}
function showlotError() {
Swal.fire({
title: '등록 오류 알림',
text: '입력 항목들을 점검해주세요.',
icon: 'warning',
}).then(result => {
if (result.isConfirmed) {
return;
}
});
}
function inputNumber(input) {
// 현재 커서 위치를 저장
const cursorPosition = input.selectionStart;
// 입력값에서 숫자만 남기고 제거
const value = input.value.replace(/,/g, '');
// 천 단위 콤마 추가
const formattedValue = Number(value).toLocaleString();
// 포맷팅된 값으로 설정
input.value = formattedValue;
// 포맷팅 후에도 원래 커서 위치 유지
input.setSelectionRange(cursorPosition, cursorPosition);
}
</script>
<?php include $_SERVER['DOCUMENT_ROOT'] . '/estimate/common/common_addrowJS.php'; // 견적서에서 screen or slat JS코드 공통 ?>
<!-- mode == 'view' "view" 조회 화면일때 사용금지 시키는 구문 -->
<script>
$(document).ready(function() {
var mode = '<?php echo $mode; ?>' ;
if (mode === 'view') {
disableView();
}
//발주서에 적용하기
$('#adaptBtn').on('click', function() {
let formData = [];
$('#estimateTable tbody tr').each(function() {
let rowData = {};
$(this).find('input, select').each(function() {
let name = $(this).attr('name').replace('[]', '');
let value = $(this).val();
rowData[name] = value;
});
formData.push(rowData);
});
let jsonString = JSON.stringify(formData);
// 폼 생성 및 전송
let form = $('<form></form>').attr({
method: 'POST',
action: '/output/write_form.php' // 데이터를 전송할 URL
});
// 폼에 데이터를 숨겨진 필드로 추가
$('<input>').attr({
type: 'hidden',
name: 'estimateData',
value: jsonString
}).appendTo(form);
// 폼 전송
form.appendTo('body').submit();
});
});
$(document).ready(function() {
// 뷰 ID와 쿠키 이름 매핑 (output-list 제거)
var views = [
{ id: "estimate_screenDiv", cookie: "showEsimateScreenView", button: "#estimateScreen_view" , status : "block" },
{ id: "view_screenguidebook", cookie: "showEsimateScreenDetailView", button: "#view_screenguidebookBtn" , status : "none" },
{ id: "estimate_slatDiv", cookie: "showEsimateslatView", button: "#estimateslat_view", status : "block" },
{ id: "view_slatguidebook", cookie: "showEsimateslatDetailView", button: "#view_slatguidebookBtn", status : "none" }
];
// 각 뷰 버튼에 클릭 이벤트 할당 및 페이지 로드 시 초기화
views.forEach(function(view) {
// 버튼 클릭 시 View 토글
$(view.button).on("click", function() {
toggleView(view.id, view.cookie);
});
// 페이지 로드 시 View 초기화
initializeView(view.id, view.cookie, view.status); // 추가 초기상태도 전달한다.
});
});
// 공통 함수: View 토글 및 쿠키 설정
function toggleView(viewId, cookieName) {
var view = getCookie(cookieName);
var listContainer = $("#" + viewId);
if (view === "show") {
listContainer.css("display", "none");
setCookie(cookieName, "hide", 10);
} else {
listContainer.css("display", "block");
setCookie(cookieName, "show", 10);
}
}
$(document).ready(function() {
let previousOption = $('input[name="radio_item"]:checked').val(); // 이전 선택 상태 저장
// 선택된 라디오 버튼에 따라 섹션 표시 및 데이터 초기화
function toggleSections() {
const selectedOption = $('input[name="radio_item"]:checked').val();
const outworkplace = $('#outworkplace').val();
const num = $('#num').val(); // 신규인 경우는 스크린 행추가
// 섹션 토글
$("#ScreenSection").toggle(selectedOption === "스크린");
$("#SlatSection").toggle(selectedOption === "철재");
if (selectedOption === '스크린') {
// 철재견적서 tbody 비우기
$('#estimateSlatTable tbody').empty();
setTimeout(function () {
const tableId = 'estimateTable';
const tableBody = $('#' + tableId).find('tbody');
if (tableBody.find('tr').length === 0) { // 행이 없을 때만 추가
addRow(tableBody, {}, tableId, null);
alertToast('스크린 행 자동 추가');
Screen_updateTotals();
}
}, 800);
} else if (selectedOption === '철재') {
// 스크린견적서 tbody 비우기
$('#estimateTable tbody').empty();
setTimeout(function () {
const tableId = 'estimateSlatTable';
const tableBody = $('#' + tableId).find('tbody');
// console.log('tableBody.find length : ' + tableBody.find('tr').length);
if (tableBody.find('tr').length === 0) { // 행이 없을 때만 추가
addRow_slat(tableBody, {}, tableId, null);
alertToast('철재 행 자동 추가');
Screen_updateTotals();
}
}, 800);
}
}
// 페이지 로드 시 초기 상태 설정
toggleSections();
// 라디오 버튼 클릭 시 토글 기능 추가
$('input[name="radio_item"]').on('change', function() {
const selectedOption = $(this).val(); // 현재 선택된 옵션
if (selectedOption !== previousOption) {
swal.fire({
title: '변환 확인',
text: '스크린/철재 변환은 기존 자료가 초기화 됩니다. 진행하시겠습니까?',
icon: 'warning',
showCancelButton: true,
confirmButtonText: '네',
cancelButtonText: '아니오'
}).then((result) => {
if (result.isConfirmed) {
// 사용자가 '네'를 선택한 경우
previousOption = selectedOption; // 이전 상태 업데이트
toggleSections();
if(selectedOption === '철재')
{
$('#makeWidth').val('110');
$('#makeHeight').val('350');
}
else
{
$('#makeWidth').val('160');
$('#makeHeight').val('350');
}
} else {
// 사용자가 '아니오'를 선택한 경우
$('input[name="radio_item"][value="' + previousOption + '"]').prop('checked', true);
}
});
}
});
});
</script>
<script>
// simple debounce helper
function debounce(fn, delay) {
let timer = null;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), delay);
};
}
// 콜백(done)을 인자로 받도록 수정
function calculateAmounts(done) {
// 중복 실행 방지를 위한 플래그
if (window.isCalculatingAmounts) {
// 이미 계산 중이면 콜백만 실행하고 리턴
if (typeof done === 'function') {
// 현재 진행 중인 계산이 완료될 때까지 대기
const checkInterval = setInterval(() => {
if (!window.isCalculatingAmounts) {
clearInterval(checkInterval);
done();
}
}, 500);
}
return;
}
window.isCalculatingAmounts = true;
try {
const selectedType = $('input[name="radio_item"]:checked').val();
if (!selectedType) {
// console.log('타입이 선택되지 않았습니다.');
return;
}
let estimateList = [];
let estimateSlatList = [];
// estimateList 수집 (스크린용)
$('#estimateTable tbody tr').each(function() {
let rowData = {};
$(this).find('input, select').each(function() {
const name = $(this).attr('name')?.replace('[]', '') || '';
const value = $(this).val() || '';
rowData[name] = value;
});
estimateList.push(rowData);
});
// estimateSlatList 수집 (철재 슬랫용)
$('#estimateSlatTable tbody tr').each(function() {
let rowData = {};
$(this).find('input, select').each(function() {
const name = $(this).attr('name')?.replace('[]', '') || '';
const value = $(this).val() || '';
rowData[name] = value;
});
estimateSlatList.push(rowData);
});
// FormData 준비
const formData = new FormData();
formData.append('type', selectedType);
const num = $('#num').val();
const inspectionFee = $('#inspectionFee').val().replace(/,/g, ''); // 콤마 제거
if (num) formData.append('num', num);
if (estimateList.length) {
try {
const jsonStr = JSON.stringify(estimateList);
// console.log('estimateList JSON:', jsonStr); // 디버깅용
formData.append('estimateList', jsonStr);
} catch (e) {
console.error('estimateList JSON 변환 실패:', e);
return;
}
}
if (estimateSlatList.length) {
try {
const jsonStr = JSON.stringify(estimateSlatList);
// console.log('estimateSlatList JSON:', jsonStr); // 디버깅용
formData.append('estimateSlatList', jsonStr);
} catch (e) {
console.error('estimateSlatList JSON 변환 실패:', e);
return;
}
}
if (inspectionFee) formData.append('inspectionFee', inspectionFee);
// checkbox 5개 상태 추가
const steel = $('#steel').prop('checked') ? '1' : '0';
const motor = $('#motor').prop('checked') ? '1' : '0';
const warranty = $('#warranty').prop('checked') ? '인정' : '';
const slatcheck = $('#slatcheck').prop('checked') ? '1' : '0';
const partscheck = $('#partscheck').prop('checked') ? '1' : '0';
formData.append('steel', steel);
formData.append('motor', motor);
formData.append('warranty', warranty);
formData.append('slatcheck', slatcheck);
formData.append('partscheck', partscheck);
// 중복 호출 방지
if (ajaxRequest !== null ) ajaxRequest.abort();
ajaxRequest = $.ajax({
url: '/estimate/get_estimate_amount.php',
type: 'POST',
data: formData,
processData: false,
contentType: false,
dataType: 'json', // 'text'에서 'json'으로 변경
success: function(resp) {
// console.log('resp: ' + resp);
if (!resp.success) {
console.error('계산 오류:', resp.error);
return;
}
// Check if resp.data exists and has the expected structure
if (!resp.data || !resp.data.details) {
console.error('Invalid response structure:', resp);
return;
}
const { details, itemDetails, surangSum } = resp.data;
console.log('details : ' + details);
itemDetails.forEach((item, index) => {
console.log(`Item ${index + 1}:`, item);
});
// 각 행별 합계 뿌리기
let calculatedTotal = 0;
if (Array.isArray(details)) {
details.forEach((sum, idx) => {
calculatedTotal += Math.round(sum);
// const subtotalCell = $(`.subtotal-cell[data-serial="${idx}"]`);
// if (subtotalCell.length) {
// // 항목별 금액 정보 표시
// const itemDetail = itemDetails[idx] || {};
// const detailText = Object.entries(itemDetail)
// .map(([key, value]) => `${key}: ${value.toLocaleString()}원`)
// .join(', ');
// subtotalCell.text(sum.toLocaleString() + '원');
// // 툴팁으로 항목별 금액 표시
// subtotalCell.attr('title', detailText);
// }
});
}
// const total_amount = Math.round(initialTotal);
// const vat = Math.round(total_amount * 0.1);
// const total = total_amount + vat;
$('#estimateTotal').val(calculatedTotal.toLocaleString()); // 자동계산금액
$('#estimateSurang').val(surangSum.toLocaleString());
// 비교용 로그 출력
// console.log('estimateSurang :', details.length.toLocaleString());
// console.log('🔍 행별 합계 누적(calculatedTotal):', calculatedTotal.toLocaleString());
// console.log('📦 전체 계산된 합(total_amount):', total_amount.toLocaleString());
// console.log('📋 항목별 금액:', itemDetails);
// const difference = Math.abs(calculatedTotal - total_amount);
// if (difference <= 10) {
// console.log('%c✅ 행별 합과 전체 합이 10원 이내로 일치합니다.', 'color: green; font-weight: bold;');
// } else {
// console.warn('%c⚠ 행별 합과 전체 합이 10원 이상 차이가 납니다.', 'color: red; font-weight: bold;');
// }
ajaxRequest = null;
// **계산이 완전히 끝난 뒤** 콜백 실행**
if (typeof done === 'function') done();
},
error: function(xhr, status, err) {
console.error('AJAX 오류:', status, err);
console.error('응답:', xhr.responseText);
ajaxRequest = null;
if (typeof done === 'function') done();
}
});
} finally {
// 플래그 해제 (AJAX 완료 후)
setTimeout(() => {
window.isCalculatingAmounts = false;
}, 100);
}
}
var debouncedCalc = debounce(calculateAmounts, 500);
$(function() {
if (!$('input[name="radio_item"]:checked').length) {
$('input[name="radio_item"][value="스크린"]').prop('checked', true);
}
// 라디오 버튼 클릭 시 토글 기능 추가
$('input[name="radio_item"]').on('change', function() {
debouncedCalc();
});
// 이벤트 바인딩 시 중복 방지
$('input, select').off('input change.calc').on('input change.calc', debouncedCalc);
$('.add-row').off('click.calc').on('click.calc', debouncedCalc);
$('.remove-row').off('click.calc').on('click.calc', debouncedCalc);
$('.copy-row').off('click.calc').on('click.calc', debouncedCalc);
// 초기 실행 (한 번만)
if (!window.initialCalcDone) {
debouncedCalc();
window.initialCalcDone = true;
}
});
// 비고란의 textarea 크기 조절
$(document).ready(function() {
const $textarea = $('#comment');
// textarea 요소가 없으면 함수 종료
if (!$textarea.length) return;
// textarea 높이를 조절하는 함수
function adjustHeight($el) {
$el.css('height', 'auto'); // 먼저 높이를 초기화
$el.css('height', $el[0].scrollHeight + 'px'); // 내용에 맞춰 높이 재설정
}
// 입력 이벤트 발생 시 높이 조절
$textarea.on('input', function() {
adjustHeight($(this));
});
// 페이지 로드시, 이미 입력된 내용이 있다면 높이 조절
adjustHeight($textarea);
});
// 견적번호 생성
$(document).ready(function () {
if (!$('#pjnum').val()) {
$.ajax({
url: '/estimate/get_initial_pjnum.php',
type: 'GET',
success: function (data) {
if (data) $('#pjnum').val(data);
}
});
}
});
</script>
</body>
</html>