Files
sam-kd/estimate/write_form.php

2426 lines
101 KiB
PHP
Raw Normal View History

<?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>