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

682 lines
24 KiB
PHP

<!-- 페이지 로딩 -->
<script>
var ajaxRequest_write = null;
$(document).ready(function() {
$('#loadingOverlay').hide(); // 로딩 오버레이 숨기기
var dataList = <?php echo json_encode($detailJson ?? []); ?>;
// JSON 데이터를 처리하기 전에 유효성 검사
if (dataList && typeof dataList === 'string') {
try {
dataList = JSON.parse(dataList); // JSON 문자열을 객체로 변환
} catch (e) {
console.error('JSON parsing error: ', e);
dataList = []; // 오류 발생 시 빈 배열로 초기화
}
}
// 배열인지 확인
// console.log('dataList after JSON.parse check: ', dataList);
if (!Array.isArray(dataList)) {
dataList = [];
}
else
{
$("#updateText").text('견적수정됨');
}
// 테이블에 데이터 로드
loadTableData('#detailTable', dataList);
// 셔터박스 오류메시지 화면에 표시
var shutterboxMsg = <?= json_encode($shutterboxMsg) ?>;
// JavaScript로 처리
if (shutterboxMsg) {
var shutterboxDiv = document.getElementById("shutterboxMsg");
shutterboxDiv.style.display = "block"; // 보이게 설정
shutterboxDiv.innerHTML = shutterboxMsg; // 내용 설정
}
});
function loadTableData(tableBodySelector, dataList) {
// console.log('loadTableData data: ', dataList); // 여기서 데이터 확인
var tableBody = $(tableBodySelector); // 테이블 본문 선택
// 데이터를 반복하면서 테이블에 행을 업데이트
var count = 1;
dataList.forEach(function(rowData, index) {
var row = tableBody.find('tr').eq(index + count); // index에 맞는 tr을 가져옴
if (row.length) {
updateRowData(row, rowData, index);
}
// console.log('index data: ', index); // 여기서 데이터 확인
// console.log('rowData data: ', rowData); // 여기서 데이터 확인
// count++;
});
}
// 기존 행을 수정하는 함수
function updateRowData(row, rowData, rowIndex) {
// 수정해야 할 td 요소들을 선택하여 해당 값을 업데이트
row.find('.su-input').val(rowData[0]); // 수량
row.find('.area-length-input').val(rowData[2]); // 길이
row.find('.area-price-input').val(rowData[3]); // 면적단가
row.find('.unit-price-input').val(rowData[4]); // 단가
// 수정된 행에 동적 계산 함수 호출
calculateRowTotal(row); // 필요 시 계산 함수 호출
}
function inputNumber(input) {
const value = input.value.replace(/,/g, ''); // 콤마 제거
input.value = parseInt(value, 10).toLocaleString(); // 다시 콤마 추가
calculateRowTotal($(input).closest('tr')); // 행의 합계 다시 계산
}
function generatePDF() {
var title_message = '<?php echo $title_message; ?>';
var workplace = '<?php echo $outworkplace; ?>';
var deadline = '<?php echo $indate; ?>';
var deadlineDate = new Date(deadline);
var formattedDate = "(" + String(deadlineDate.getFullYear()).slice(-2) + "." + ("0" + (deadlineDate.getMonth() + 1)).slice(-2) + "." + ("0" + deadlineDate.getDate()).slice(-2) + ")";
var result = 'KD' + title_message + '(' + workplace +')' + formattedDate + '.pdf';
var element = document.getElementById('content-to-print');
// 강제로 input 요소의 폰트 크기 변경
var inputs = element.querySelectorAll('input');
inputs.forEach(function(input) {
input.style.fontSize = '6px'; // 모든 input 요소에 10px 폰트 크기 적용
});
var opt = {
margin: [15, 8, 17, 8], // Top, right, bottom, left margins
filename: result,
image: { type: 'jpeg', quality: 0.70 },
html2canvas: { scale: 4 },
jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' },
pagebreak: { mode: [''] }
};
html2pdf().from(element).set(opt).save();
}
// 이벤트 리스너 설정 및 계산 함수 호출
function setupEventListeners() {
document.querySelectorAll('input').forEach(input => {
input.addEventListener('input', function () {
const row = input.closest('tr');
calculateRowTotal(row);
calculateAllSubtotals();
calculateGrandTotal();
calculateRowTotalFirstTable();
});
});
}
// 페이지 로드 시 초기 계산 및 이벤트 리스너 설정
window.onload = function () {
calculateAllSubtotals();
calculateGrandTotal();
setupEventListeners();
calculateRowTotalFirstTable();
};
$(document).ready(function() {
// 초기 상태에 따라 Estimateview와 listview를 보여주기/숨기기 설정
if ($('#showEstimateCheckbox').is(':checked')) {
$('.Estimateview').show();
} else {
$('.Estimateview').hide();
}
if ($('#showlistCheckbox').is(':checked')) {
$('.listview').show();
} else {
$('.listview').hide();
}
// showEstimateCheckbox 체크박스 변경 시 Estimateview 보여주기/숨기기 설정
$('#showEstimateCheckbox').on('change', function() {
if ($(this).is(':checked')) {
$('.Estimateview').show();
} else {
$('.Estimateview').hide();
}
});
// showlistCheckbox 체크박스 변경 시 listview 보여주기/숨기기 설정
$('#showlistCheckbox').on('change', function() {
if ($(this).is(':checked')) {
$('.listview').show();
} else {
$('.listview').hide();
}
});
});
$(document).ready(function () {
var rowArray = <?= isset($row_array_json) ? $row_array_json : '[]' ?>;
if (Array.isArray(rowArray) && rowArray.length > 0) {
rowArray.forEach(function (rowspanValue, index) {
var cell = document.getElementById('dynamicRowspan-' + index);
var cellCompare = document.getElementById('dynamicRowspanCompare-' + index);
// console.log('index', index);
if (cell && rowspanValue > 0) {
cell.setAttribute('rowspan', rowspanValue);
}
if (cellCompare && rowspanValue > 0) {
cellCompare.setAttribute('rowspan', rowspanValue);
}
});
}
});
// 숫자 포맷팅 함수 (콤마 추가 및 소수점 둘째자리에서 반올림)
function formatNumber(value) {
// 소수점 둘째 자리에서 반올림
const roundedValue = Math.round(value);
// 콤마 추가 포맷팅
return new Intl.NumberFormat().format(roundedValue);
}
// 숫자에서 콤마를 제거하는 함수
function cleanNumber(value) {
// value가 null 또는 undefined인 경우 0을 반환하도록 처리
if (!value) return 0;
return parseFloat(value.replace(/,/g, '')) || 0;
}
// 입력 필드에서 숫자를 포맷팅하는 함수
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); // 커서 위치 유지
}
// 행별 합계 계산
function calculateRowTotal(row) {
// row를 jQuery 객체로 변환
row = $(row);
// jQuery 객체에서 값을 가져옴
const suInput = row.find('.su-input');
const areaLengthInput = row.find('.area-length-input');
const areaPriceInput = row.find('.area-price-input');
const unitPriceInput = row.find('.unit-price-input');
const su = suInput.length ? cleanNumber(suInput.val()) : 1;
const areaLength = areaLengthInput.length ? cleanNumber(areaLengthInput.val()) : 1;
const areaPrice = areaPriceInput.length ? cleanNumber(areaPriceInput.val()) : 1;
let unitPrice = unitPriceInput.length ? cleanNumber(unitPriceInput.val()) : 1;
const roundedAreaPrice = parseFloat(areaPrice.toFixed(2));
if (roundedAreaPrice > 0) {
unitPrice = Math.ceil(areaLength * roundedAreaPrice); // 기본 수량 * 단가
unitPriceInput.val(formatNumber(unitPrice)); // 단가 업데이트
}
let totalPrice;
if (!areaLength && !areaPrice) {
totalPrice = su * unitPrice;
} else if (areaLength && !areaPrice) {
totalPrice = areaLength * unitPrice;
} else {
totalPrice = su * unitPrice;
}
const totalCell = row.find('.total-price');
if (totalCell.length) {
totalCell.text(formatNumber(totalPrice));
}
return totalPrice;
}
// 일련번호별 소계 계산 (jQuery 방식)
function calculateSubtotalBySerial(serialNumber) {
let subtotal = 0;
const rows = $(`.calculation-row[data-serial="${serialNumber}"]`);
rows.each(function() {
subtotal += calculateRowTotal($(this));
});
const subtotalCells = $(`.subtotal-cell[data-serial="${serialNumber}"]`);
if (subtotalCells.length > 0) {
subtotalCells.each(function() {
$(this).text(formatNumber(subtotal));
});
} else {
console.error(`소계 셀을 찾을 수 없습니다. 일련번호: ${serialNumber}`);
}
return subtotal;
}
// 모든 일련번호별 소계 및 총합계 계산 (jQuery 방식)
function calculateAllSubtotals() {
let grandTotal = 0;
const uniqueSerials = new Set();
$('.calculation-row').each(function() {
uniqueSerials.add($(this).data('serial'));
});
uniqueSerials.forEach(function(serialNumber) {
grandTotal += calculateSubtotalBySerial(serialNumber);
});
return grandTotal;
}
// 총합계 계산 (jQuery 방식)
function calculateGrandTotal() {
const grandTotal = calculateAllSubtotals();
const grandTotalCells = $('.grand-total');
if (grandTotalCells.length > 0) {
grandTotalCells.each(function() {
$(this).text(formatNumber(grandTotal));
});
$('#totalsum').text(formatNumber(grandTotal));
var EstimateFirstSum = $("#EstimateFirstSum").val();
var EstimateUpdatetSum = $("#EstimateUpdatetSum").val();
$('#koreantotalsum').text(KoreanNumber(Math.ceil(grandTotal)));
// 총금액에서 최초금액 추출하기
if(grandTotal > 0 && EstimateFirstSum < 1)
$("#EstimateFirstSum").val(formatNumber(grandTotal));
else
$("#EstimateUpdatetSum").val(formatNumber(grandTotal));
// 차액계산
if(cleanNumber($("#EstimateUpdatetSum").val())> 0)
$("#EstimateDiffer").val(formatNumber(cleanNumber($("#EstimateUpdatetSum").val()) - cleanNumber($("#EstimateFirstSum").val())));
else
$("#EstimateDiffer").val(0);
// console.log('grand total : ', grandTotal);
} else {
console.error("전체 합계 셀을 찾을 수 없습니다. '.grand-total'이라는 클래스가 올바르게 설정되었는지 확인해주세요.");
}
}
// 첫 번째 테이블: 행별 합계 계산 (jQuery 방식)
function calculateRowTotalFirstTable() {
const rows = $('.calculation-firstrow');
rows.each(function() {
const suInput = $(this).find('.total-su-input'); // 수량 입력 필드
const subtotalCell = $(this).find('.subtotal-cell'); // 소계 셀
const unitPriceCell = $(this).find('.total-unit-price'); // 단가 셀
const su = suInput ? cleanNumber(suInput.text()) : 1;
const subtotal = subtotalCell ? cleanNumber(subtotalCell.text()) : 0;
let unitPrice = 0;
if (su > 0) {
unitPrice = subtotal / su; // 소계를 수량으로 나눠서 단가 계산
}
if (unitPriceCell.length) {
unitPriceCell.text(formatNumber(unitPrice)); // 단가 셀에 표시
}
});
}
function KoreanNumber(number) {
const koreanNumbers = ['', '일', '이', '삼', '사', '오', '육', '칠', '팔', '구'];
const koreanUnits = ['', '십', '백', '천'];
const bigUnits = ['', '만', '억', '조'];
let result = '';
let unitIndex = 0;
let numberStr = String(number);
// 숫자가 0인 경우 '영원'을 반환
if (number == 0) return '영원';
// 뒤에서부터 4자리씩 끊어서 처리
while (numberStr.length > 0) {
let chunk = numberStr.slice(-4); // 마지막 4자리
numberStr = numberStr.slice(0, -4); // 나머지 숫자
let chunkResult = '';
for (let i = 0; i < chunk.length; i++) {
const digit = parseInt(chunk[i]);
if (digit > 0) {
chunkResult += koreanNumbers[digit] + koreanUnits[chunk.length - i - 1];
}
}
if (chunkResult) {
result = chunkResult + bigUnits[unitIndex] + result;
}
unitIndex++;
}
// 불필요한 '일십', '일백', '일천' 등의 단위를 제거하고 '원'을 붙여 반환
result = result.replace(/일(?=십|백|천)/g, '').trim();
return result + '';
}
function removeAllButLastOccurrence(string, target) {
// 마지막 '만'의 위치를 찾습니다
const lastPos = string.lastIndexOf(target);
// 마지막 '만'이 없으면 원래 문자열을 반환합니다
if (lastPos === -1) {
return string;
}
// 마지막 '만'을 제외한 모든 '만'을 제거합니다
const beforeLastPos = string.slice(0, lastPos);
const afterLastPos = string.slice(lastPos);
// '만'을 빈 문자열로 대체합니다
const result = beforeLastPos.replace(new RegExp(target, 'g'), '') + afterLastPos;
return result;
}
$(document).ready(function() {
// 저장 버튼 클릭 시 saveData 함수 호출
$(".saveBtn").click(function() {
saveData();
});
});
function saveData() {
const myform = document.getElementById('board_form');
let allValid = true;
if (!allValid) return;
var num = $("#num").val();
$("#overlay").show();
$("button").prop("disabled", true);
// 모드 설정 (insert 또는 modify)
if ($("#mode").val() !== 'copy') {
if (Number(num) < 1) {
$("#mode").val('insert');
} else {
$("#mode").val('modify');
}
} else {
$("#mode").val('insert');
}
// 데이터 수집 (input 요소만 저장)
let formData = [];
$('#detailTable tbody tr').each(function() {
let rowData = [];
// 각 tr의 input 요소 순서대로 처리
$(this).find('input, select').each(function() {
let value = $(this).val();
rowData.push(value); // input 값을 배열에 순서대로 추가
});
formData.push(rowData); // 각 행의 input 데이터를 배열에 추가
});
// formData는 이제 각 행의 input 값들만 포함하는 배열입니다.
console.log('formData:', formData);
// JSON 문자열로 변환하여 form input에 설정
let jsonString = JSON.stringify(formData);
$('#detailJson').val(jsonString);
// console.log('detailJson', jsonString);
$("#estimateSurang").val('<?= $estimateSurang ?>'); // 견적수량 저장
$("#estimateTotal").val($("#subtotal").text()); // 견적총액 저장
console.log('$("#estimateSurang").val($("#subtotal").text())' , $("#estimateSurang").val());
console.log('$("#estimateTotal").val($("#subtotal").text())' , $("#estimateTotal").val());
var form = $('#board_form')[0];
var datasource = new FormData(form);
if (ajaxRequest_write !== null) {
ajaxRequest_write.abort();
}
showMsgModal(2); // 파일저장중
// Ajax 요청으로 서버에 데이터 전송
ajaxRequest_write = $.ajax({
enctype: 'multipart/form-data',
processData: false,
contentType: false,
cache: false,
timeout: 600000,
url: "/estimate/insert_detail.php", // 산출내역 저장
type: "post",
data: datasource,
dataType: "json",
success: function(data) {
// console.log(data);
setTimeout(function() {
$(opener.location).attr("href", "javascript:restorePageNumber();");
setTimeout(function() {
hideMsgModal();
hideOverlay();
}, 1500);
}, 1000);
},
error: function(jqxhr, status, error) {
console.log(jqxhr, status, error);
}
});
}
function generatePDF_server(callback) {
var workplace = '<?php echo $title_message; ?>';
var item = '<?php echo $emailTitle; ?>';
var today = new Date();
var formattedDate = "(" + String(today.getFullYear()).slice(-2) + "." + ("0" + (today.getMonth() + 1)).slice(-2) + "." + ("0" + today.getDate()).slice(-2) + ")";
var result = 'KD' + item +'(' + workplace + ')' + formattedDate + '.pdf';
var element = document.getElementById('content-to-print');
var opt = {
margin: [10, 3, 12, 3], // Top, right, bottom, left margins
filename: result,
image: { type: 'jpeg', quality: 0.70 },
html2canvas: { scale: 4 },
jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' },
pagebreak: { mode: [''] }
};
html2pdf().from(element).set(opt).output('datauristring').then(function (pdfDataUri) {
var pdfBase64 = pdfDataUri.split(',')[1]; // Base64 인코딩된 PDF 데이터 추출
var formData = new FormData();
formData.append('pdf', pdfBase64);
formData.append('filename', result);
$.ajax({
type: 'POST',
url: '/email/save_pdf.php', // PDF 파일을 저장하는 PHP 파일
data: formData,
processData: false,
contentType: false,
success: function (response) {
var res = JSON.parse(response);
if (callback) {
callback(res.filename); // 서버에 저장된 파일 경로를 콜백으로 전달
}
},
error: function (xhr, status, error) {
Swal.fire('Error', 'PDF 저장에 실패했습니다.', 'error');
}
});
});
}
var ajaxRequest = null;
function sendmail() {
var secondordnum = '<?php echo $secondordnum; ?>'; // 서버에서 가져온 값
var item = '<?php echo $emailTitle; ?>';
if (!secondordnum) {
Swal.fire({
icon: 'warning',
title: '오류 알림',
text: '발주처 코드가 없습니다.'
});
return; // 함수 종료
}
if (typeof ajaxRequest !== 'undefined' && ajaxRequest !== null) {
ajaxRequest.abort();
}
ajaxRequest = $.ajax({
type: 'POST',
url: '/email/get_companyCode.php',
data: { secondordnum: secondordnum },
dataType: 'json',
success: function(response) {
console.log('response : ', response);
if (response.error) {
Swal.fire('Error', response.error, 'error');
} else {
var email = response.email;
var vendorName = response.vendor_name;
Swal.fire({
title: 'E메일 보내기',
text: vendorName + ' Email 주소확인',
icon: 'warning',
input: 'text', // input 창을 텍스트 필드로 설정
inputLabel: 'Email 주소 수정 가능',
inputValue: email, // 기존 이메일 주소를 기본값으로 설정
showCancelButton: true,
confirmButtonText: '보내기',
cancelButtonText: '취소',
reverseButtons: true,
inputValidator: (value) => {
if (!value) {
return '이메일 주소를 입력해주세요!';
}
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailPattern.test(value)) {
return '올바른 이메일 형식을 입력해주세요!';
}
}
}).then((result) => {
if (result.isConfirmed) {
const updatedEmail = result.value; // 입력된 이메일 주소 가져오기
generatePDF_server(function(filename) {
sendEmail(updatedEmail, vendorName, item, filename);
});
}
});
}
},
error: function(xhr, status, error) {
Swal.fire('Error', '전송중 오류가 발생했습니다.', 'error');
}
});
}
function sendEmail(recipientEmail, vendorName, item, filename) {
if (typeof ajaxRequest !== 'undefined' && ajaxRequest !== null) {
ajaxRequest.abort();
}
var today = new Date();
var formattedDate = "(" + String(today.getFullYear()).slice(-2) + "." + ("0" + (today.getMonth() + 1)).slice(-2) + "." + ("0" + today.getDate()).slice(-2) + ")";
ajaxRequest = $.ajax({
type: 'POST',
url: '/email/send_email.php', // 이메일 전송을 처리하는 PHP 파일
data: { email: recipientEmail, vendorName: vendorName, filename: filename, item: item, formattedDate: formattedDate },
success: function(response) {
console.log(response);
Swal.fire('Success', '정상적으로 전송되었습니다.', 'success');
},
error: function(xhr, status, error) {
Swal.fire('Error', '전송에 실패했습니다. 확인바랍니다.', 'error');
}
});
}
$(document).ready(function() {
// 재계산 버튼 클릭 이벤트
$('.initialBtn').on('click', function() {
// 재계산 확인 알림
Swal.fire({
title: '견적데이터 재계산',
text: "견적 데이터를 재계산 하시겠습니까?",
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: '예, 재계산합니다',
cancelButtonText: '취소'
}).then((result) => {
if (result.isConfirmed) {
$("#estimateTotal").val(0); // 견적총액 저장
$("#EstimateFirstSum").val(0); // 견적초기금액
$("#EstimateUpdatetSum").val(0); // 수정금액
$("#EstimateDiffer").val(0); // 차액금액
var form = $('#board_form')[0];
var datasource = new FormData(form);
const initialData = JSON.stringify([]); // 빈 배열로 재계산
$('#detailJson').val(initialData);
// 재계산된 데이터 저장 요청
$.ajax({
enctype: 'multipart/form-data',
processData: false,
contentType: false,
cache: false,
timeout: 600000,
url: "/estimate/insert_detail.php",
type: "post",
data: datasource,
dataType: "json",
success: function(response) {
Swal.fire({
title: '재계산 완료',
text: "모든 데이터가 재계산되었습니다.",
icon: 'success',
confirmButtonText: '확인'
}).then(() => {
hideMsgModal();
// 페이지 새로고침
location.reload();
});
},
error: function(jqxhr, status, error) {
Swal.fire({
title: '오류',
text: "재계산 중 오류가 발생했습니다.",
icon: 'error',
confirmButtonText: '확인'
});
console.log("AJAX Error: ", status, error);
}
});
}
});
});
});
</script>