Files
sam-kd/account/list.php

2340 lines
90 KiB
PHP
Raw Permalink Normal View History

<?php
require_once $_SERVER['DOCUMENT_ROOT'] . '/load_GoogleDrive.php'; // 세션 등 여러가지 포함됨 파일 포함
if (!isset($_SESSION["level"]) || $_SESSION["level"] > 5) {
sleep(1);
header("Location:" . $WebSite . "login/login_form.php");
exit;
}
// 에러 표시 설정
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
// **대량 등록용 임시 key 발급**
$bulkTimeKey = bin2hex(random_bytes(16));
include $_SERVER['DOCUMENT_ROOT'] . '/load_header.php';
$title_message = '금전 출납부';
$tablename = 'account';
require_once $_SERVER['DOCUMENT_ROOT'] . '/load_GoogleDriveSecond.php'; // attached, image에 대한 정보 불러오기
?>
<link href="css/style.css" rel="stylesheet">
<title> <?=$title_message?> </title>
<style>
/* 테이블에 테두리 추가 */
#myTable, #myTable th, #myTable td {
border: 1px solid black;
border-collapse: collapse;
}
/* 테이블 셀 패딩 조정 */
#myTable th, #myTable td {
padding: 8px;
text-align: center;
}
/* 전체 모달 폰트 기본값 12px 유지 */
#bulkEntryModal * {
font-size: 12px;
box-sizing: border-box;
}
/* 모달 배경 오버레이 */
#bulkEntryModal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.6);
z-index: 1050;
}
/* 모달 내용 영역 (가운데 정렬) */
#bulkEntryModal > div {
background: white;
width: 1920px;
height: 950px;
margin: 40px auto;
padding: 20px;
border-radius: 8px;
position: relative;
display: flex;
flex-direction: column;
}
/* 버튼 스타일 */
#bulkEntryModal .btn {
padding: 2px 8px;
font-size: 12px;
cursor: pointer;
}
/* 테이블 관련 */
#bulkEntryModal table {
width: 100%;
border-collapse: collapse;
}
#bulkEntryModal table th,
#bulkEntryModal table td {
padding: 4px;
vertical-align: middle;
font-size: 12px;
border: 1px solid #dee2e6;
}
#bulkEntryModal table thead {
background-color: #f8f9fa;
}
/* 모달 바디 스크롤 설정 */
#bulkEntryModal .custom-modal-body {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
margin: 10px 0;
}
/* 테이블 헤더 고정 */
#bulkEntryModal .table-responsive {
position: relative;
}
#bulkEntryModal table thead {
position: sticky;
top: 0;
z-index: 10;
background-color: #f8f9fa;
}
/* 모달 열릴 때 바디 스크롤 방지 */
body.modal-open {
overflow: hidden;
}
</style>
</head>
<body>
<!-- 로딩 오버레이 -->
<div id="loadingOverlay" style="
display: none;
position: fixed;
top: 0; left: 0;
width: 100%; height: 100%;
background: rgba(0,0,0,0.6);
z-index: 2000;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 1.5em;
display: none;
">
<div>
<i class="bi bi-arrow-clockwise rotate" style="font-size:2em; animation: spin 1s linear infinite;"></i>
<div>잠시만 기다려주세요…</div>
</div>
</div>
<style>
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
</style>
<?php
// 세무사아이디면 다른 메뉴 연결
if($_SESSION["userid"] == '0266771300') {
include $_SERVER['DOCUMENT_ROOT'] . '/myheader_accountant.php';
}
else {
include $_SERVER['DOCUMENT_ROOT'] . '/myheader.php';
}
$search = isset($_REQUEST['search']) ? $_REQUEST['search'] : '';
$fromdate = isset($_REQUEST['fromdate']) ? $_REQUEST['fromdate'] : '';
$todate = isset($_REQUEST['todate']) ? $_REQUEST['todate'] : '';
$mode = isset($_REQUEST['mode']) ? $_REQUEST['mode'] : '';
// 현재 날짜
$currentDate = date("Y-m-d");
// fromdate 또는 todate가 빈 문자열이거나 null인 경우
if ($fromdate === "" || $fromdate === null || $todate === "" || $todate === null) {
// 현재 월의 1일을 fromdate로 설정
// $fromdate = date("Y-m-01");
// 전달(이전 달)의 1일을 fromdate로 설정
$fromdate = date("Y-m-01", strtotime("-1 month"));
$todate = $currentDate;
$Transtodate = $todate;
} else {
$Transtodate = $todate;
}
function checkNull($strtmp) {
return $strtmp !== null && trim($strtmp) !== '';
}
require_once($_SERVER['DOCUMENT_ROOT'] . "/lib/mydb.php");
$pdo = db_connect();
$inoutsep_select = isset($_REQUEST['inoutsep_select']) ? $_REQUEST['inoutsep_select'] : '';
$content_select = isset($_REQUEST['content_select']) ? $_REQUEST['content_select'] : '';
$order = " ORDER BY registDate ASC, num ASC ";
$sql_conditions = [];
$sql_params = [];
if (checkNull($search)) {
$sql_conditions[] = "searchtag LIKE :search";
$sql_params[':search'] = "%$search%";
}
$sql_conditions[] = "registDate BETWEEN :fromdate AND :todate";
$sql_params[':fromdate'] = $fromdate;
$sql_params[':todate'] = $todate;
$sql_conditions[] = "is_deleted = 0";
if (checkNull($inoutsep_select)) {
$sql_conditions[] = "inoutsep = :inoutsep";
$sql_params[':inoutsep'] = $inoutsep_select;
}
if (checkNull($content_select)) {
$sql_conditions[] = "content = :content";
$sql_params[':content'] = $content_select;
}
$sql = "SELECT * FROM " . $tablename . " WHERE " . implode(' AND ', $sql_conditions) . $order;
try {
$stmh = $pdo->prepare($sql);
foreach ($sql_params as $param => $value) {
$stmh->bindValue($param, $value);
}
$stmh->execute();
$total_row = $stmh->rowCount();
// 수입, 지출을 기반으로 초기 잔액 계산
$initialBalanceSql = "SELECT
SUM(CASE WHEN inoutsep = '수입' THEN REPLACE(amount, ',', '') ELSE 0 END) +
SUM(CASE WHEN inoutsep = '최초전월이월' THEN REPLACE(amount, ',', '') ELSE 0 END) -
SUM(CASE WHEN inoutsep = '지출' THEN REPLACE(amount, ',', '') ELSE 0 END) AS balance
FROM $tablename
WHERE is_deleted = '0' AND registDate < :fromdate
AND (dueDate = '0000-00-00' OR dueDate IS NULL OR dueDate = '')";
$initialBalanceStmh = $pdo->prepare($initialBalanceSql);
$initialBalanceStmh->bindParam(':fromdate', $fromdate);
$initialBalanceStmh->execute();
$initialBalance = $initialBalanceStmh->fetch(PDO::FETCH_ASSOC)['balance'];
$totalIncomeSql = "SELECT SUM(REPLACE(amount, ',', '')) AS totalIncome
FROM $tablename
WHERE is_deleted = '0' AND (inoutsep = '수입' OR inoutsep = '최초전월이월')
AND registDate BETWEEN :fromdate AND :todate
AND (dueDate = '0000-00-00' OR dueDate IS NULL OR dueDate = '')";
$totalIncomeStmh = $pdo->prepare($totalIncomeSql);
$totalIncomeStmh->bindParam(':fromdate', $fromdate);
$totalIncomeStmh->bindParam(':todate', $todate);
$totalIncomeStmh->execute();
$totalIncome = $totalIncomeStmh->fetch(PDO::FETCH_ASSOC)['totalIncome'];
$totalExpenseSql = "SELECT SUM(REPLACE(amount, ',', '')) AS totalExpense
FROM $tablename
WHERE is_deleted = '0' AND inoutsep = '지출'
AND registDate BETWEEN :fromdate AND :todate
AND (dueDate = '0000-00-00' OR dueDate IS NULL OR dueDate = '')";
$totalExpenseStmh = $pdo->prepare($totalExpenseSql);
$totalExpenseStmh->bindParam(':fromdate', $fromdate);
$totalExpenseStmh->bindParam(':todate', $todate);
$totalExpenseStmh->execute();
$totalExpense = $totalExpenseStmh->fetch(PDO::FETCH_ASSOC)['totalExpense'];
$finalBalance = $initialBalance + $totalIncome - $totalExpense;
// Bankbook options
$bankbookOptions = [];
$jsonFile = $_SERVER['DOCUMENT_ROOT'] . "/account/accoutlist.json";
$accounts = [];
$selectedAccount = null;
$accountBalances = [];
if (file_exists($jsonFile)) {
$jsonContent = file_get_contents($jsonFile);
$accounts = json_decode($jsonContent, true);
if (is_array($accounts) && !empty($accounts)) {
// 선택된 계좌 또는 기본 계좌(첫 번째) 설정
$selectedAccountIndex = isset($_REQUEST['selected_account']) ? intval($_REQUEST['selected_account']) : 0;
$selectedAccount = $accounts[$selectedAccountIndex] ?? $accounts[0];
// 각 계좌별 잔액 계산
foreach ($accounts as $index => $account) {
$accountDisplay = $account['company'] . ' ' . $account['number'];
if (!empty($account['memo'])) {
$accountDisplay .= ' (' . $account['memo'] . ')';
}
// 해당 계좌의 잔액 계산
$accountBalanceSql = "SELECT
SUM(CASE WHEN inoutsep = '수입' AND bankbook = ? THEN REPLACE(amount, ',', '') ELSE 0 END) +
SUM(CASE WHEN inoutsep = '최초전월이월' AND bankbook = ? THEN REPLACE(amount, ',', '') ELSE 0 END) -
SUM(CASE WHEN inoutsep = '지출' AND bankbook = ? THEN REPLACE(amount, ',', '') ELSE 0 END) AS balance
FROM $tablename
WHERE is_deleted = '0'
AND (dueDate = '0000-00-00' OR dueDate IS NULL OR dueDate = '')";
$accountBalanceStmh = $pdo->prepare($accountBalanceSql);
$accountBalanceStmh->bindValue(1, $accountDisplay, PDO::PARAM_STR);
$accountBalanceStmh->bindValue(2, $accountDisplay, PDO::PARAM_STR);
$accountBalanceStmh->bindValue(3, $accountDisplay, PDO::PARAM_STR);
$accountBalanceStmh->execute();
$accountBalances[$index] = $accountBalanceStmh->fetch(PDO::FETCH_ASSOC)['balance'] ?? 0;
}
}
}
// 각 계좌별 요약 정보를 담을 배열 초기화
$accountSummaries = [];
if (is_array($accounts)) {
foreach ($accounts as $index => $account) {
$accountDisplay = $account['company'] . ' ' . $account['number'];
if (!empty($account['memo'])) {
$accountDisplay .= ' (' . $account['memo'] . ')';
}
// 1. 계좌별 기초 잔액 (기간 이전)
$initialSql = "SELECT
(SUM(CASE WHEN inoutsep = '수입' OR inoutsep = '최초전월이월' THEN REPLACE(amount, ',', '') ELSE 0 END) -
SUM(CASE WHEN inoutsep = '지출' THEN REPLACE(amount, ',', '') ELSE 0 END)) AS balance
FROM $tablename
WHERE is_deleted = '0' AND registDate < :fromdate AND bankbook = :bankbook
AND (dueDate = '0000-00-00' OR dueDate IS NULL OR dueDate = '')";
$initialStmh = $pdo->prepare($initialSql);
$initialStmh->bindParam(':fromdate', $fromdate);
$initialStmh->bindParam(':bankbook', $accountDisplay);
$initialStmh->execute();
$initialBalanceAccount = $initialStmh->fetch(PDO::FETCH_ASSOC)['balance'] ?? 0;
// 2. 기간 내 수입
$incomeSql = "SELECT SUM(REPLACE(amount, ',', '')) AS totalIncome
FROM $tablename
WHERE is_deleted = '0' AND (inoutsep = '수입' OR inoutsep = '최초전월이월')
AND registDate BETWEEN :fromdate AND :todate AND bankbook = :bankbook
AND (dueDate = '0000-00-00' OR dueDate IS NULL OR dueDate = '')";
$incomeStmh = $pdo->prepare($incomeSql);
$incomeStmh->bindParam(':fromdate', $fromdate);
$incomeStmh->bindParam(':todate', $todate);
$incomeStmh->bindParam(':bankbook', $accountDisplay);
$incomeStmh->execute();
$totalIncomeAccount = $incomeStmh->fetch(PDO::FETCH_ASSOC)['totalIncome'] ?? 0;
// 3. 기간 내 지출
$expenseSql = "SELECT SUM(REPLACE(amount, ',', '')) AS totalExpense
FROM $tablename
WHERE is_deleted = '0' AND inoutsep = '지출'
AND registDate BETWEEN :fromdate AND :todate AND bankbook = :bankbook
AND (dueDate = '0000-00-00' OR dueDate IS NULL OR dueDate = '')";
$expenseStmh = $pdo->prepare($expenseSql);
$expenseStmh->bindParam(':fromdate', $fromdate);
$expenseStmh->bindParam(':todate', $todate);
$expenseStmh->bindParam(':bankbook', $accountDisplay);
$expenseStmh->execute();
$totalExpenseAccount = $expenseStmh->fetch(PDO::FETCH_ASSOC)['totalExpense'] ?? 0;
// 4. 최종 잔액
$finalBalanceAccount = $initialBalanceAccount + $totalIncomeAccount - $totalExpenseAccount;
// 계산된 정보를 배열에 저장
$accountSummaries[$index] = [
'name' => $accountDisplay,
'income' => $totalIncomeAccount,
'expense' => $totalExpenseAccount,
'balance' => $finalBalanceAccount
];
}
}
// 각 계좌별 최종 잔액 정보를 담을 배열 초기화
$accountFinalBalances = [];
if (is_array($accounts)) {
foreach ($accounts as $index => $account) {
$accountDisplay = $account['company'] . ' ' . $account['number'];
if (!empty($account['memo'])) {
$accountDisplay .= ' (' . $account['memo'] . ')';
}
// 계좌별 전체 기간의 최종 잔액 계산
$balanceSql = "SELECT
(SUM(CASE WHEN inoutsep = '수입' OR inoutsep = '최초전월이월' THEN REPLACE(amount, ',', '') ELSE 0 END) -
SUM(CASE WHEN inoutsep = '지출' THEN REPLACE(amount, ',', '') ELSE 0 END)) AS balance
FROM $tablename
WHERE is_deleted = '0' AND bankbook = :bankbook
AND (dueDate = '0000-00-00' OR dueDate IS NULL OR dueDate = '')";
$balanceStmh = $pdo->prepare($balanceSql);
$balanceStmh->bindParam(':bankbook', $accountDisplay);
$balanceStmh->execute();
$balanceResult = $balanceStmh->fetch(PDO::FETCH_ASSOC);
// 계산된 정보를 배열에 저장
$accountFinalBalances[$index] = [
'name' => $accountDisplay,
'balance' => $balanceResult['balance'] ?? 0
];
}
}
// print $sql;
?>
<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="tablename" name="tablename" value="<?= isset($tablename) ? $tablename : '' ?>">
<input type="hidden" id="savetitle" name="savetitle" value="<?=isset($savetitle) ? $savetitle : '' ?>" >
<input type="hidden" id="pInput" name="pInput" value="<?=isset($pInput) ? $pInput : '' ?>" >
<div id="bulkEntryModal" style="display:none; position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.6); z-index:1050;">
<div style="background:white; width:1880px; height:950px; margin:40px auto; padding:20px; border-radius:8px; position:relative;">
<div class="d-flex justify-content-between bg-dark text-white" >
<h3 class="p-2">금전출납부 대량 등록</h3>
<button type="button" id="closeAccountModal" style="background:none; border:none; color:white; font-size:24px;">&times;</button>
</div>
<div class="custom-modal-body">
<div class="table-responsive">
<table class="table table-bordered" id="bulkEntryTable">
<thead>
<tr>
<th style="width:6%;">+/-/Copy</th>
<th style="width:6%;">등록일자</th>
<th style="width:7%;">구분</th>
<th style="width:15%;">계좌</th>
<th style="width:8%;">항목</th>
<th style="width:8%;">세부항목</th>
<th style="width:5%;">거래처 <i class="bi bi-search"></i></th>
<th style="width:5%;">거래처코드</th>
<th style="width:6%;">만기일자</th>
<th style="width:6%;">배서일자</th>
<th style="width:14%;">상세내용</th>
<th style="width:6%;">금액</th>
<th style="width:8%;">이미지첨부</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
<div class="d-flex justify-content-end">
<button type="button" id="saveBulkBtn" class="btn btn-dark btn-sm me-2">
<i class="bi bi-floppy-fill"></i> 전체 저장
</button>
<button type="button" class="btn btn-dark btn-sm me-2" id="closeAccountModal2">
&times; 닫기
</button>
</div>
</div>
</div>
</div>
<!-- 전자어음 검색 모달 -->
<div class="modal fade" id="electronicBillModal" tabindex="-1" aria-labelledby="electronicBillModalLabel" aria-hidden="true" style="z-index:1060;">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="electronicBillModalLabel">전자어음 검색</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="table-responsive">
<table class="table table-hover">
<thead class="table-secondary">
<tr>
<th>번호</th>
<th>등록일자</th>
<th>항목</th>
<th>세부항목</th>
<th>상세내용</th>
<th>금액</th>
<th>만기일자</th>
<th>선택</th>
</tr>
</thead>
<tbody id="electronicBillTableBody">
<!-- 전자어음 데이터가 여기에 동적으로 추가됩니다 -->
</tbody>
</table>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">닫기</button>
</div>
</div>
</div>
</div>
<div class="container-fluid">
<!-- Modal -->
<div id="myModal" class="modal">
<div class="modal-content" style="width:1000px;">
<div class="modal-header">
<span class="modal-title"> <?=$title_message?> </span>
<span class="close">&times;</span>
</div>
<div class="modal-body">
<div class="custom-card"></div>
</div>
</div>
</div>
</div>
<div class="container-fluid">
<div class="card justify-content-center text-center mt-5">
<div class="card-header">
<span class="text-center fs-5"> <?=$title_message?>
<button type="button" class="btn btn-dark btn-sm me-1" onclick='location.reload()'>
<i class="bi bi-arrow-clockwise" ></i> </button>
</span>
</div>
<div class="card-body">
<div class="d-flex justify-content-center align-items-center mt-2">
<span>
<?= $total_row ?> &nbsp;
</span>
<!-- 기간부터 검색까지 연결 묶음 start -->
<span id="showdate" class="btn btn-dark btn-sm">기간</span> &nbsp;
<div id="showframe" class="card" style="width:500px;">
<div class="card-header" style="padding:2px;">
<div class="d-flex justify-content-center align-items-center">
기간 설정
</div>
</div>
<div class="card-body">
<div class="d-flex justify-content-center align-items-center">
<button type="button" class="btn btn-outline-success btn-sm me-1 change_dateRange" onclick='alldatesearch()'>전체</button>
<button type="button" class="btn btn-outline-primary btn-sm me-1 change_dateRange" onclick='pre_year()'>전년도</button>
<button type="button" class="btn btn-dark btn-sm me-1 change_dateRange" onclick='pre_month()'>전월</button>
<button type="button" class="btn btn-dark btn-sm me-1 change_dateRange" onclick='dayBeforeYesterday()'>전전일</button>
<button type="button" class="btn btn-dark btn-sm me-1 change_dateRange" onclick='yesterday()'>전일</button>
<button type="button" class="btn btn-outline-danger btn-sm me-1 change_dateRange" onclick='this_today()'>오늘</button>
<button type="button" class="btn btn-dark btn-sm me-1 change_dateRange" onclick='this_month()'>당월</button>
<button type="button" class="btn btn-dark btn-sm me-1 change_dateRange" onclick='this_year()'>당해년도</button>
</div>
</div>
</div>
<input type="date" id="fromdate" name="fromdate" class="form-control" style="width:110px;" value="<?=$fromdate?>"> &nbsp; ~ &nbsp;
<input type="date" id="todate" name="todate" class="form-control me-1" style="width:110px;" value="<?=$todate?>"> &nbsp;
<!-- 번째 select : 수입/지출 구분 -->
<select id="inoutsep_select" name="inoutsep_select" class="form-select form-select-sm mx-1 d-block w-auto mx-1" >
<option value="">구분</option>
<option value="수입" <?= $inoutsep_select === '수입' ? 'selected' : '' ?>>수입</option>
<option value="지출" <?= $inoutsep_select === '지출' ? 'selected' : '' ?>>지출</option>
<option value="최초전월이월" <?= $inoutsep_select === '최초전월이월' ? 'selected' : '' ?>>최초전월이월</option>
</select>
<!-- 번째 select : 항목 선택 -->
<select id="content_select" name="content_select" class="form-select form-select-sm mx-1 d-block w-auto mx-1" >
<option value="">전체항목</option>
<?php
include 'fetch_options.php';
$options = array_merge(array_keys($incomeOptions), array_keys($expenseOptions));
foreach ($options as $option) {
$selected = ($content_select === $option) ? 'selected' : '';
echo "<option value=\"$option\" $selected>$option</option>";
}
?>
</select>
<div class="inputWrap30">
<input type="text" id="search" class="form-control" style="width:150px;" name="search" value="<?=$search?>" onKeyPress="if (event.keyCode==13){ enter(); }">
<button class="btnClear"></button>
</div>
&nbsp;&nbsp;
<button class="btn btn-outline-dark btn-sm" type="button" id="searchBtn"> <i class="bi bi-search"></i> </button> &nbsp;&nbsp;&nbsp;&nbsp;
<button type="button" class="btn btn-secondary btn-sm ms-2 me-2" onclick="settings();" data-bs-toggle="tooltip" data-bs-placement="bottom" title="계정 관리(추가/수정/삭제)" > <i class="bi bi-gear-fill"></i> </button>
<button id="newBtn" type="button" class="btn btn-dark btn-sm me-2"> <i class="bi bi-pencil-square"></i> 신규 </button>
<button id="bulkNewBtn" type="button" class="btn btn-info btn-sm me-2"> <i class="bi bi-plus-square"></i> 대량등록 </button>
<button type="button" class="btn btn-dark btn-sm me-2" onclick="generateExcel();" > <i class="bi bi-file-earmark-spreadsheet"></i> 엑셀다운로드 </button>
<button type="button" class="btn btn-primary btn-sm me-2" onclick="detail();" > <i class="bi bi-ticket-detailed"></i> 상세내역 </button>
</div>
</div>
<div class="d-flex flex-wrap justify-content-start align-items-center mt-2 p-2 border rounded" style="gap: 10px;">
<strong class="me-2">계좌 잔액:</strong>
<?php foreach ($accountFinalBalances as $summary): ?>
<?php if ($summary['balance'] > 0): ?>
<?php
// USD가 포함된 경우 금액 앞에 $ 추가
$isUSD = stripos($summary['name'], 'USD') !== false;
$formattedBalance = $isUSD ? '$' . number_format($summary['balance']) : number_format($summary['balance']);
?>
<div class="border rounded p-1" style="font-size: 0.8em;">
<span class="text-secondary"><?= htmlspecialchars($summary['name']) ?>:</span>
<span class="fw-bold ms-1"><?= $formattedBalance ?></span>
</div>
<?php endif; ?>
<?php endforeach; ?>
</div>
<div class="table-responsive">
<table class="table table-hover" id="myTable">
<thead class="table-secondary">
<tr>
<th class="text-center" style="width:40px;">번호</th>
<th class="text-center" style="width:70px;">등록일자</th>
<th class="text-center" style="width:50px;">구분</th>
<th class="text-center" style="width:80px;">항목</th>
<th class="text-center" style="width:80px;">세부항목</th>
<th class="text-center" style="width:250px;">상세내용</th>
<th class="text-center" style="width:90px;">수입</th>
<th class="text-center" style="width:90px;">지출</th>
<th class="text-center" style="width:90px;">잔액</th>
<th class="text-center" style="width:230px;">계좌</th>
<th class="text-center" style="width:70px;">만기일자</th>
<th class="text-center" style="width:70px;">배서일자</th>
<th class="text-center" style="width:60px;"> 첨부서류</th>
</tr>
<tr style="background-color: #808080!important;">
<th class="text-end" colspan="6"> 합계 &nbsp; </th>
<th class="text-end" id="totalIncomeAmount"></th>
<th class="text-end" id="totalExpenseAmount"></th>
<th class="text-end" id="totalBalanceAmount"></th>
<th class="text-end" colspan="4"></th>
</tr>
</thead>
<?php
// 1. 계좌별 기초 잔액을 계산하여 배열로 관리 (기간 시작일 이전)
$runningBalances = [];
if (is_array($accounts)) {
foreach ($accounts as $account) {
$accountDisplay = $account['company'] . ' ' . $account['number'];
if (!empty($account['memo'])) {
$accountDisplay .= ' (' . $account['memo'] . ')';
}
$initialBalanceSql = "SELECT
(SUM(CASE WHEN inoutsep = '수입' OR inoutsep = '최초전월이월' THEN REPLACE(amount, ',', '') ELSE 0 END) -
SUM(CASE WHEN inoutsep = '지출' THEN REPLACE(amount, ',', '') ELSE 0 END)) AS balance
FROM $tablename
WHERE is_deleted = '0' AND registDate < :fromdate AND bankbook = :bankbook
AND (dueDate = '0000-00-00' OR dueDate IS NULL OR dueDate = '')";
$initialBalanceStmh = $pdo->prepare($initialBalanceSql);
$initialBalanceStmh->bindParam(':fromdate', $fromdate);
$initialBalanceStmh->bindParam(':bankbook', $accountDisplay);
$initialBalanceStmh->execute();
$result = $initialBalanceStmh->fetch(PDO::FETCH_ASSOC);
$runningBalances[$accountDisplay] = $result['balance'] ?? 0;
}
}
$start_num = $total_row;
$counter = 1;
// 2. 루프를 돌며 각 거래에 대한 계좌별 잔액을 계산하고 출력
// 이 while 루프는 페이지 상단에서 시작된 try 블록 안에서 실행됩니다.
while($row = $stmh->fetch(PDO::FETCH_ASSOC)) {
include '_row.php'; // $num, $registDate, $bankbook 등의 변수 할당
$amount = floatval(str_replace(',', '', $row['amount']));
// json에 없는 계좌의 거래가 있을 경우를 대비해 초기화
if (!isset($runningBalances[$bankbook])) {
$runningBalances[$bankbook] = 0;
}
// 해당 계좌의 잔액을 업데이트 (어음이 아닌 경우만)
if ($dueDate === '0000-00-00' || !$dueDate || $dueDate === '' || $bankbook === '전자어음') {
if ($row['inoutsep'] === '수입' || $row['inoutsep'] === '최초전월이월') {
$runningBalances[$bankbook] += $amount;
} else { // 지출
$runningBalances[$bankbook] -= $amount;
}
}
?>
<tr>
<td class="text-center" onclick="loadForm('update', '<?=$num?>');"><?= $counter ?></td>
<td class="text-center" onclick="loadForm('update', '<?=$num?>');"><?= $registDate ?></td>
<td class="text-center <?= ($inoutsep === '수입' || $inoutsep === '최초전월이월') ? 'text-primary' : 'text-danger' ?>" onclick="loadForm('update', '<?=$num?>');"><?= $inoutsep ?></td>
<td class="text-center fw-bold <?= ($inoutsep === '수입' || $inoutsep === '최초전월이월') ? 'text-primary' : 'text-danger' ?>" onclick="loadForm('update', '<?=$num?>');"> <?= $content ?> </td>
<td class="text-center fw-bold <?= ($inoutsep === '수입' || $inoutsep === '최초전월이월') ? 'text-primary' : 'text-danger' ?>" onclick="loadForm('update', '<?=$num?>');"> <?= $contentSub ?> </td>
<td class="text-start <?= ($inoutsep === '수입' || $inoutsep === '최초전월이월') ? 'text-primary' : 'text-danger' ?>" onclick="loadForm('update', '<?=$num?>');"><?= $content_detail ?></td>
<?php if ($inoutsep === '수입' || $inoutsep === '최초전월이월') : ?>
<td class="text-end fw-bold text-primary" onclick="loadForm('update', '<?=$num?>');">
<?= is_numeric($amount) ? number_format($amount) : htmlspecialchars($amount) ?>
</td>
<td class="text-end"></td>
<?php else : ?>
<td class="text-end"></td>
<td class="text-end fw-bold text-danger" onclick="loadForm('update', '<?=$num?>');">
<?= is_numeric($amount) ? number_format($amount) : htmlspecialchars($amount) ?>
</td>
<?php endif; ?>
<td class="text-end fw-bold" onclick="loadForm('update', '<?=$num?>');"><?= number_format($runningBalances[$bankbook]) ?></td>
<td class="text-start" onclick="loadForm('update', '<?=$num?>');"><?= $bankbook ?></td>
<td class="text-start" onclick="loadForm('update', '<?=$num?>');">
<?= ($dueDate === '0000-00-00' || !$dueDate) ? '' : '(어음)'. $dueDate ?>
</td>
<td class="text-start" onclick="loadForm('update', '<?=$num?>');">
<?= ($bankbook === '전자어음' && $endorsementDate && $endorsementDate !== '0000-00-00') ? $endorsementDate : '' ?>
</td>
<td class="text-center">
<?php
// picuploads 테이블에서 이미지 검색
$imageSql = "SELECT picname FROM {$DB}.picuploads WHERE tablename = 'account' AND parentnum = :num AND item = 'image' ";
$imageStmh = $pdo->prepare($imageSql);
$imageStmh->bindParam(':num', $num);
$imageStmh->execute();
$images = $imageStmh->fetchAll(PDO::FETCH_COLUMN); // 모든 결과를 배열로 가져옴
if (!empty($images)) {
foreach ($images as $fileId) {
if ($fileId) {
$imageId = 'account_image_' . $num . '_' . array_search($fileId, $images); // 고유 ID 생성
$link = "https://drive.google.com/file/d/{$fileId}/view?usp=drivesdk";
?>
<i class="bi bi-check2-square text-success" style="cursor: pointer;"
onclick="openTmpImagePopup('<?= $link ?>', '<?= $imageId ?>');"></i>
<?php
}
}
} else {
echo ' ';
}
?>
</td>
</tr>
<?php
$start_num--;
$counter++;
} // while 루프의 닫는 괄호
// ▼▼▼ 페이지 상단의 try 구문을 닫는 필수 catch 구문 ▼▼▼
} catch (PDOException $Exception) {
print "오류: ".$Exception->getMessage();
}
?>
</table>
</div>
</div>
</div>
</div>
</form>
<!-- 이미지 로딩 모달 -->
<div class="modal fade" id="loadingImageModal" tabindex="-1" aria-labelledby="loadingImageModalLabel" aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false">
<div class="modal-dialog modal-dialog-centered modal-sm">
<div class="modal-content">
<div class="modal-body text-center">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Loading...</span>
</div>
<p class="mt-2 mb-0">이미지를 불러오는 ...</p>
</div>
</div>
</div>
</div>
<script>
// 페이지 로딩
$(document).ready(function(){
var loader = document.getElementById('loadingOverlay');
if (loader) {
loader.style.display = 'none';
}
$("#loadingOverlay").hide();
});
function numberWithCommas(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
$(document).ready(function() {
const initialBalance = <?= json_encode($initialBalance) ?>;
const finalBalance = <?= json_encode($finalBalance) ?>;
dataTable = $('#myTable').DataTable({
"paging": true,
"ordering": true,
"searching": true,
"pageLength": 1000,
"lengthMenu": [1000],
"language": {
"lengthMenu": "Show _MENU_ entries",
"search": "Live Search:"
},
"order": [[0, 'desc']],
"dom": 't<"bottom"ip>',
"columnDefs": [
{
"orderable": true, // 정렬 활성화
"targets": [0, 1, 2, 3, 4, 5, 6, 7, 8] // 정렬 가능하도록 설정할 열 인덱스
},
{
"orderable": false, // 정렬 비활성화
"targets": [9, 10, 11, 12] // 나머지 열 (계좌, 만기일자, 배서일자) 비활성화
}
],
"footerCallback": function (row, data, start, end, display) {
var api = this.api();
var intVal = function (i) {
return typeof i === 'string' ?
i.replace(/[\$,]/g, '')*1 :
typeof i === 'number' ?
i : 0;
};
// Calculate the totals for Income, Expense, and Balance
// 컬럼숫자 입력
var totalIncomeAmount = api.column(6, { page: 'current' }).data().reduce(function (a, b) { return intVal(a) + intVal(b); }, 0);
var totalExpenseAmount = api.column(7, { page: 'current' }).data().reduce(function (a, b) { return intVal(a) + intVal(b); }, 0);
// Update the header with the calculated totals
$('#totalIncomeAmount').html(numberWithCommas(totalIncomeAmount));
$('#totalExpenseAmount').html(numberWithCommas(totalExpenseAmount));
$('#totalBalanceAmount').html(numberWithCommas(finalBalance));
}
});
});
</script>
<script>
let isSaving = false;
var ajaxRequest = null;
var ajaxRequest_SubOption = null;
// PHP 변수를 JS 에 전달
const bulkTimeKey = "<?= $bulkTimeKey ?>";
document.addEventListener('DOMContentLoaded', function() {
$("#newBtn").on("click", function() {
loadForm('insert');
});
$("#searchBtn").on("click", function() {
$("#board_form").submit();
});
// 복사 버튼 클릭 이벤트
$(document).on("click", "#copyBtn", function() {
document.querySelector(".modal-body .custom-card").innerHTML = '';
$("#myModal").hide();
var num = $("#num").val();
loadForm('copy', num);
});
// 전자어음 선택 버튼 클릭 이벤트
$(document).on("click", "#selectElectronicBillBtn", function() {
// 거래처가 먼저 선택되어 있는지 확인
const secondordnum = document.getElementById('secondordnum').value;
if (!secondordnum || secondordnum.trim() === '') {
alert('전자어음을 선택하기 전에 먼저 거래처를 검색하여 선택해주세요.');
return;
}
loadElectronicBills();
});
});
// 모달창에 내용을 넣는 구조임 모달을 부르고 내용을 동적으로 넣는다.
function loadForm(mode, num = null) {
// 로딩 오버레이 보여주기
$("#loadingOverlay").show();
if (num == null || mode == 'copy') {
$("#mode").val('insert');
} else {
$("#mode").val('update');
$("#num").val(num);
}
if (ajaxRequest !== null) {
ajaxRequest.abort();
}
ajaxRequest = $.ajax({
type: "POST",
url: "fetch_modal.php",
data: { mode: mode, num: num },
dataType: "html",
success: function(response) {
document.querySelector(".modal-body .custom-card").innerHTML = response;
$("#myModal").show();
// PHP 데이터를 JSON으로 인코딩
const incomeOptions = <?php echo json_encode($incomeOptions, JSON_UNESCAPED_UNICODE); ?>;
const expenseOptions = <?php echo json_encode($expenseOptions, JSON_UNESCAPED_UNICODE); ?>;
console.log('Income Options:', incomeOptions);
console.log('Expense Options:', expenseOptions);
function updateDescription() {
const contentSelect = document.getElementById('content');
const descriptionDiv = document.getElementById('content_description');
const selectedValue = contentSelect.value;
// 수입인지 지출인지에 따라 설명 변경
const descriptions = document.querySelector('input[name="inoutsep"]:checked').value === '수입' ? incomeOptions : expenseOptions;
descriptionDiv.innerText = descriptions[selectedValue] || '';
// '거래처 수금' 또는 계좌가 '전자어음'일 때 검색 버튼 추가
const bankbookSelect = document.getElementById('bankbook');
const isElectronicBill = bankbookSelect && bankbookSelect.value === '전자어음';
if (selectedValue === '거래처 수금' || isElectronicBill) {
// contentSub를 '외상매출금'으로 설정 (거래처 수금일 때만)
if (selectedValue === '거래처 수금') {
const contentSubSelect = document.getElementById('contentSub');
if (contentSubSelect) {
contentSubSelect.innerHTML = '<option value="외상매출금">외상매출금</option>';
contentSubSelect.value = '외상매출금';
}
}
// 검색 버튼이 이미 있는지 확인
let searchBtn = document.getElementById('phonebookSearchBtn');
if (!searchBtn) {
searchBtn = document.createElement('button');
searchBtn.id = 'phonebookSearchBtn';
searchBtn.type = 'button';
searchBtn.className = 'btn btn-primary btn-sm ms-2 w120px';
searchBtn.innerHTML = '거래처 <i class="bi bi-search"></i> ';
descriptionDiv.parentNode.insertBefore(searchBtn, descriptionDiv.nextSibling);
// 검색 버튼 클릭 이벤트
searchBtn.addEventListener('click', function() {
phonebookBtn('');
});
}
} else {
// '거래처 수금'이 아닌 경우 검색 버튼 제거
const searchBtn = document.getElementById('phonebookSearchBtn');
if (searchBtn) {
searchBtn.remove();
}
}
}
function updateContentOptions() {
console.log('updateContentOptions');
const contentSelect = document.getElementById('content');
if (contentSelect) {
contentSelect.innerHTML = '';
const selectedType = document.querySelector('input[name="inoutsep"]:checked').value;
let options;
if (selectedType === '최초전월이월') {
options = {'최초전월이월': '최초전월이월'};
} else {
options = selectedType === '수입' ? incomeOptions : expenseOptions;
}
for (const [value, text] of Object.entries(options)) {
const option = document.createElement('option');
option.value = value;
option.text = value;
contentSelect.appendChild(option);
}
// 수입 선택 시 자동으로 '거래처 수금' 선택
if (selectedType === '수입') {
contentSelect.value = '거래처 수금';
}
updateDescription();
}
}
function phonebookBtn(search)
{
returnID = '수금등록';
href = '/phonebook/list.php?search=' + search + '&returnID=' + returnID;
popupCenter(href, '전화번호 검색', 1800, 800);
}
$(document).on("click", "#closeBtn", function() {
$("#myModal").hide();
});
// loadForm() 성공 콜백 안에서
// 1) 기존에 붙어 있던 saveBtn 클릭 핸들러 제거
$(document).off("click", "#saveBtn");
// 2) 새로 핸들러 바인딩
$(document).on("click", "#saveBtn", function() {
// if (isSaving) return;
// isSaving = true;
// AJAX 요청을 보냄
if (ajaxRequest !== null) {
ajaxRequest.abort();
}
ajaxRequest = $.ajax({
url: "/account/insert.php",
type: "post",
data: {
mode: $("#mode").val(),
num: $("#num").val(),
update_log: $("#update_log").val(),
registDate: $("#registDate").val(),
inoutsep: $("input[name='inoutsep']:checked").val(),
content: $("#content").val(),
amount: $("#amount").val(),
dueDate: $("#dueDate").val(),
first_writer: $("#first_writer").val(),
content_detail: $("#content_detail").val(),
contentSub: $("#contentSub").val(),
bankbook: $("#bankbook").val(),
secondordnum: $("#secondordnum").val(),
endorsementDate: $("#endorsementDate").val(),
parentEBNum: $("#parentEBNum").val()
},
dataType: "json",
success: function(response) {
Toastify({
text: "저장 완료",
duration: 3000,
close: true,
gravity: "top",
position: "center",
backgroundColor: "#4fbe87",
}).showToast();
setTimeout(function() {
$("#myModal").hide();
location.reload();
}, 1500); // 1.5초 후 실행
},
error: function(jqxhr, status, error) {
console.log("AJAX Error: ", status, error);
// isSaving = false;
}
});
});
$(document).on("click", "#deleteBtn", function() {
var level = '<?= $_SESSION["level"] ?>';
if (level !== '1') {
Swal.fire({
title: '삭제불가',
text: "관리자만 삭제 가능합니다.",
icon: 'error',
confirmButtonText: '확인'
});
return;
}
Swal.fire({
title: '자료 삭제',
text: "삭제는 신중! 정말 삭제하시겠습니까?",
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: '삭제',
cancelButtonText: '취소'
}).then((result) => {
if (result.isConfirmed) {
$("#mode").val('delete');
var formData = $("#board_form").serialize();
$.ajax({
url: "/account/insert.php",
type: "post",
data: formData,
success: function(response) {
Toastify({
text: "파일 삭제완료",
duration: 2000,
close: true,
gravity: "top",
position: "center",
backgroundColor: "#4fbe87",
}).showToast();
$("#myModal").hide();
location.reload();
},
error: function(jqxhr, status, error) {
console.log(jqxhr, status, error);
}
});
}
});
});
$(".close").on("click", function() {
$("#myModal").hide();
});
// 항목 선택 변경 시 설명 업데이트
$(document).on("change", "#content", updateDescription);
$(document).on("change", "input[name='inoutsep']", updateContentOptions);
// 계좌 선택 변경 시 배서일자 필드 표시/숨김 처리
$(document).on("change", "#bankbook", function() {
const endorsementDateContainer = document.getElementById('endorsementDateContainer');
const selectElectronicBillBtn = document.getElementById('selectElectronicBillBtn');
if (endorsementDateContainer) {
endorsementDateContainer.style.display = this.value === '전자어음' ? 'inline-block' : 'none';
}
if (selectElectronicBillBtn) {
selectElectronicBillBtn.style.display = this.value === '전자어음' ? 'inline-block' : 'none';
}
// 계좌가 바뀌면 거래처 검색 버튼 표시/숨김도 갱신
if (typeof updateDescription === 'function') updateDescription();
// 전자어음 선택 시 그리기 버튼 표시
const drawBtn = document.getElementById('drawBtn');
if (drawBtn) {
if (this.value === '전자어음') {
drawBtn.style.display = 'inline-block';
} else {
drawBtn.style.display = 'none';
// 그리기 모드가 활성화되어 있다면 비활성화
if (document.body.classList.contains('drawing-mode')) {
toggleDrawingMode();
}
}
}
});
// 전자어음 선택 버튼 클릭 이벤트
$(document).on("click", "#selectElectronicBillBtn", function() {
loadElectronicBills();
});
// 기존 이미지 불러오기 (Google Drive에서 가져오기)
function displayImageLoad() {
$('#displayImage').show();
var data = <?php echo json_encode($saveimagename_arr); ?>;
$("#displayImage").html('');
if (Array.isArray(data) && data.length > 0) {
data.forEach(function (fileData, i) {
const realName = fileData.realname || '다운로드 파일';
const thumbnail = fileData.thumbnail || '/assets/default-thumbnail.png';
const link = fileData.link || '#';
const fileId = fileData.fileId || null;
const rotation = fileData.rotation || 0;
const mode = '<?php echo $mode; ?>';
if (!fileId) {
console.error("fileId가 누락되었습니다. index: " + i, fileData);
return;
}
// 구글 드라이브 이미지 팝업 링크 생성
let deleteButton = '';
if (mode !== 'view') {
deleteButton = `<button type="button" class="btn btn-danger btn-sm mx-3" id="delImage${i}" onclick="delImageFn('${i}', '${fileId}')">
<i class="bi bi-trash"></i>
</button>`;
}
$("#displayImage").append(
"<div class='row mb-3'>" +
"<div class='col d-flex align-items-center justify-content-center'>" +
"<div class='position-relative'>" +
"<a href='#' onclick=\"openTmpImagePopup('" + link + "', 'image" + i + "'); return false;\">" +
"<img id='image" + i + "' src='" + thumbnail + "' style='width:100px; height:auto; transform: rotate(" + rotation + "deg);'>" +
"</a>" +
(mode !== 'view' ?
"<div class='position-absolute top-0 end-0 mt-1 me-1'>" +
"<button type='button' class='btn btn-primary btn-sm rotate-btn' onclick=\"rotateImage('" + fileId + "', 'image" + i + "')\">" +
"<i class='bi bi-arrow-clockwise'></i>" +
"</button>" +
"</div>" : "") +
"</div>" +
deleteButton +
"</div>" +
"</div>"
);
});
} else {
$("#displayImage").append(
"<div class='text-center text-muted'>No files</div>"
);
}
}
displayImageLoad(); // 기존이미지 업로드 보이기
// 모달 로드 완료 후 초기 상태 설정
if (typeof updateDescription === 'function') {
updateDescription();
}
},
error: function(jqxhr, status, error) {
console.log("AJAX error in loadForm:", status, error);
},
complete: function() {
// 성공이든 실패든 로딩 오버레이 숨기기
$("#loadingOverlay").hide();
}
});
}
function updateSubOptions() {
const contentSelect = document.getElementById('content');
const contentSubSelect = document.getElementById('contentSub');
const selectedValue = contentSelect.value;
const inoutsepValue = document.querySelector('input[name="inoutsep"]:checked')?.value || '지출';
if (ajaxRequest !== null) {
ajaxRequest.abort();
}
// AJAX 요청으로 세부항목 가져오기
ajaxRequest = $.ajax({
url: 'fetch_modal.php',
type: 'POST',
data: {
action: 'getSubOptions',
selectedKey: selectedValue,
inoutsep: inoutsepValue // 수입/지출 구분 추가
},
dataType: 'json',
success: function(response) {
// 기존 옵션 초기화
contentSubSelect.innerHTML = '';
if (response.subOptions && response.subOptions.length > 0) {
// 새로운 옵션 추가
response.subOptions.forEach(item => {
for (const key in item) {
const option = document.createElement('option');
option.value = key;
option.text = key;
contentSubSelect.appendChild(option);
}
});
} else {
// 세부항목이 없는 경우 기본값 처리
const option = document.createElement('option');
option.value = '';
option.text = '세부항목 없음';
contentSubSelect.appendChild(option);
}
},
error: function(jqxhr, status, error) {
console.log("AJAX Error:", status, error);
}
});
}
// content 선택 변경 이벤트
$(document).on('change', '#content', updateSubOptions);
</script>
<script>
function generateExcel() {
var table = document.getElementById('myTable');
var rows = table.getElementsByTagName('tr');
var data = [];
// 각 행을 반복하여 데이터 수집
for (var i = 1; i < rows.length; i++) { // 헤더 행을 건너뜀
var cells = rows[i].getElementsByTagName('td');
var rowData = {};
rowData['number'] = cells[0]?.innerText || '';
rowData['registDate'] = cells[1]?.innerText || '';
rowData['content'] = cells[2]?.innerText || '';
rowData['contentSub'] = cells[3]?.innerText || '';
rowData['contentDetail'] = cells[4]?.innerText || '';
rowData['income'] = cells[5]?.innerText || '';
rowData['expense'] = cells[6]?.innerText || '';
rowData['balance'] = cells[7]?.innerText || '';
rowData['dueDate'] = cells[8]?.innerText || '';
data.push(rowData);
}
// saveExcel.php에 데이터 전송
var xhr = new XMLHttpRequest();
xhr.open("POST", "saveExcel.php", true);
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
try {
var response = JSON.parse(xhr.responseText);
if (response.success) {
console.log('Excel file generated successfully.');
// 다운로드 스크립트로 리디렉션
window.location.href = 'saveExcel.php?download=' + encodeURIComponent(response.filename);
} else {
console.log('Failed to generate Excel file: ' + response.message);
}
} catch (e) {
console.log('Error parsing response: ' + e.message + '\nResponse text: ' + xhr.responseText);
}
} else {
console.log('Failed to generate Excel file: Server returned status ' + xhr.status);
}
}
};
xhr.send(JSON.stringify(data));
}
function settings() {
// 계정설정
const url = `settings.php`;
customPopup(url, '계정 관리', 600, 850);
}
function detail() {
// detail.php로 이동할 URL 생성
const url = `detail.php`;
// customPopup을 사용하여 detail.php를 팝업으로 열기
customPopup(url, '상세 내역', 800, 900);
}
function openPopup(url, title, width, height) {
// 화면 중앙에 팝업을 띄우도록 좌표 계산
const left = (window.screen.width / 2) - (width / 2);
const top = (window.screen.height / 2) - (height / 2);
// 팝업 창 생성
const popupWindow = window.open(
url,
title,
`width=${width},height=${height},top=${top},left=${left},scrollbars=yes,resizable=yes`
);
// 오버레이 생성
const overlay = document.createElement('div');
overlay.id = 'overlay';
overlay.style.position = 'fixed';
overlay.style.top = 0;
overlay.style.left = 0;
overlay.style.width = '100%';
overlay.style.height = '100%';
overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.5)'; // 반투명 검은색
overlay.style.zIndex = 10000; // 최상위 레이어
overlay.style.cursor = 'not-allowed'; // 사용자가 클릭하지 못하도록 마우스 커서를 변경
document.body.appendChild(overlay);
// 팝업이 닫히면 오버레이 제거
const interval = setInterval(() => {
if (popupWindow.closed) {
clearInterval(interval);
document.body.removeChild(overlay);
}
}, 500);
// 팝업 창에 포커스 이동
if (window.focus) {
popupWindow.focus();
}
}
function enter() {
$("#board_form").submit();
}
</script>
<!-- 부트스트랩 툴팁 -->
<script>
document.addEventListener('DOMContentLoaded', function () {
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
return new bootstrap.Tooltip(tooltipTriggerEl);
});
// $("#order_form_write").modal("show");
});
</script>
<script>
// PHP 데이터를 JavaScript 변수로 변환
const incomeOptions = <?php echo json_encode($incomeOptions, JSON_UNESCAPED_UNICODE); ?>;
const expenseOptions = <?php echo json_encode($expenseOptions, JSON_UNESCAPED_UNICODE); ?>;
// 수입/지출 선택에 따른 계정과목 업데이트
document.getElementById('inoutsep_select').addEventListener('change', function() {
const contentSelect = document.getElementById('content_select');
const selectedType = this.value;
// 기존 옵션 제거 (전체항목 제외)
while (contentSelect.options.length > 1) {
contentSelect.remove(1);
}
// 선택된 타입에 따라 옵션 추가
const options = selectedType === '수입' ? incomeOptions : expenseOptions;
// 옵션 추가
Object.keys(options).forEach(key => {
const option = document.createElement('option');
option.value = key;
option.textContent = key;
contentSelect.appendChild(option);
});
// 전체항목으로 초기화
contentSelect.value = '';
});
$(document).ready(function(){
// 방문기록 남김
var title = '<?php echo $title_message; ?>';
saveMenuLog(title);
});
// account/list.php 파일의 기존 <script> 태그 안에 추가
// --- 대량등록 관련 스크립트 시작 ---
$(document).ready(function() {
// 배경 스크롤 방지 함수
function disableBodyScroll() {
$('body').css('overflow', 'hidden');
}
// 배경 스크롤 복원 함수
function enableBodyScroll() {
$('body').css('overflow', 'auto');
}
// '대량등록' 버튼 클릭 시 모달 열기
$("#bulkNewBtn").on("click", function() {
// 테이블 내용 초기화
$("#bulkEntryTable tbody").empty();
// 첫 행 추가
addRow_BulkEntry();
// 배경 스크롤 방지
disableBodyScroll();
// 모달 표시
$("#bulkEntryModal").show();
});
// 모달 닫기 버튼
$("#bulkEntryModal .close").on("click", function() {
$("#bulkEntryModal").hide();
// 배경 스크롤 복원
enableBodyScroll();
});
// 행 추가 버튼 (+)
$(document).on('click', '#bulkEntryTable .add-row', function() {
addRow_BulkEntry();
});
// 행 삭제 버튼 (-)
$(document).on('click', '#bulkEntryTable .remove-row', function() {
if ($("#bulkEntryTable tbody tr").length > 1) { // 최소 1개의 행은 유지
$(this).closest('tr').remove();
}
});
// '전체 저장' 버튼 클릭 이벤트
$("#saveBulkBtn").on("click", function() {
saveBulkData();
});
// '구분' 변경 시 '항목' 드롭다운 업데이트
$(document).on('change', '.bulk-inoutsep', function() {
updateBulkContentOptions($(this));
});
// '항목' 변경 시 '세부항목' 드롭다운 업데이트
$(document).on('change', '.bulk-content', function() {
updateBulkSubOptions($(this));
});
// '계좌' 변경 시 배서일자 필드 표시/숨김
$(document).on('change', '.bulk-bankbook', function() {
const $row = $(this).closest('tr');
const $endorsementDateField = $row.find('.bulk-endorsementDate');
const $selectElectronicBillBtn = $row.find('.bulk-select-electronic-bill-btn');
if (this.value === '전자어음') {
$endorsementDateField.show();
$selectElectronicBillBtn.show();
// 전자어음 선택 시 오늘날짜로 설정
// 지출이 선택된 경우에만 오늘 날짜로 설정
if (!$endorsementDateField.val() && $row.find('.bulk-inoutsep').val() === '지출') {
$endorsementDateField.val(new Date().toISOString().slice(0, 10));
}
} else {
$endorsementDateField.hide();
$selectElectronicBillBtn.hide();
}
});
// 대량등록에서 전자어음 선택 버튼 클릭 이벤트
$(document).on('click', '.bulk-select-electronic-bill-btn', function() {
const $row = $(this).closest('tr');
const secondordnum = $row.find('.bulk-secondordnum').val();
// 거래처가 먼저 선택되어 있는지 확인
if (!secondordnum || secondordnum.trim() === '') {
alert('전자어음을 선택하기 전에 먼저 거래처를 검색하여 선택해주세요.');
return;
}
loadElectronicBillsForBulk($row);
});
// 대량등록 모달 바깥 영역 클릭 시 닫기
$("#bulkEntryModal").on('click', function(e) {
if (e.target === this) {
$("#bulkEntryModal").hide();
// 배경 스크롤 복원
enableBodyScroll();
}
});
});
/**
* 대량등록 테이블에 새로운 행을 추가하는 함수
*/
function addRow_BulkEntry() {
// 현재 행의 등록일자 가져오기
const currentRow = $(event.target).closest('tr');
const currentDate = currentRow ? currentRow.find('.bulk-registDate').val() : new Date().toISOString().slice(0, 10);
const bankbookOptions = `<?php
$optionsHtml = "";
$jsonFile = $_SERVER['DOCUMENT_ROOT'] . "/account/accoutlist.json";
if (file_exists($jsonFile)) {
$accounts = json_decode(file_get_contents($jsonFile), true);
if (is_array($accounts)) {
foreach ($accounts as $account) {
$displayText = htmlspecialchars($account['company'] . ' ' . $account['number'] . (!empty($account['memo']) ? ' (' . $account['memo'] . ')' : ''), ENT_QUOTES);
$optionsHtml .= "<option value='" . $displayText . "'>" . $displayText . "</option>";
}
}
}
echo $optionsHtml;
?><option value="전자어음">전자어음</option>`;
const newRow = `
<tr>
<td class="text-center">
<button type="button" class="btn btn-sm btn-outline-primary add-row" style="padding: 2px 5px;">+</button>
<button type="button" class="btn btn-sm btn-outline-danger remove-row" style="padding: 2px 6px;">-</button>
<button type="button" class="btn btn-sm btn-outline-secondary copy-row" style="padding: 2px 6px;">
<i class="bi bi-files"></i>
</button>
</td>
<td><input type="date" class="form-control form-control-sm bulk-registDate noborder-input" value="${currentDate}"></td>
<td>
<select class="form-select form-select-sm bulk-inoutsep">
<option value="지출" selected>지출</option>
<option value="수입">수입</option>
<option value="최초전월이월">최초전월이월</option>
</select>
</td>
<td><select class="form-select form-select-sm bulk-bankbook">${bankbookOptions}</select></td>
<td><select class="form-select form-select-sm bulk-content"></select></td>
<td><select class="form-select form-select-sm bulk-contentSub"></select></td>
<td>
<button type="button" class="btn btn-sm btn-outline-primary bulk-search-company">
<i class="bi bi-search"></i>
</button>
</td>
<td><input type="text" class="form-control form-control-sm bulk-secondordnum noborder-input" autocomplete="off"></td>
<td><input type="date" class="form-control form-control-sm bulk-dueDate noborder-input"></td>
<td>
<input type="date" class="form-control form-control-sm bulk-endorsementDate noborder-input" value="" style="display: none;">
<button type="button" class="btn btn-outline-primary btn-sm bulk-select-electronic-bill-btn" style="display: none;">
<i class="bi bi-search"></i>
</button>
</td>
<td><input type="text" class="form-control form-control-sm bulk-content_detail noborder-input text-start" autocomplete="off"></td>
<td><input type="text" class="form-control form-control-sm bulk-amount text-end noborder-input" onkeyup="inputNumberFormat(this)" autocomplete="off"></td>
<td>
<input type="file"
class="form-control form-control-sm bulk-image-input"
multiple
accept="image/*">
</td>
</tr>
`;
if (currentRow && currentRow.length) {
// 현재 행이 있는 경우 해당 행 다음에 추가
currentRow.after(newRow);
currentRow.next().find('.bulk-inoutsep').trigger('change');
} else {
// 현재 행이 없는 경우(첫 행 추가) 테이블에 추가
$('#bulkEntryTable tbody').append(newRow);
$('#bulkEntryTable tbody tr:last .bulk-inoutsep').trigger('change');
}
}
/**
* '구분' (수입/지출/최초전월이월) 선택에 따라 '항목' 드롭다운 메뉴를 업데이트하는 함수
*/
function updateBulkContentOptions($selectElement) {
const selectedType = $selectElement.val();
const contentSelect = $selectElement.closest('tr').find('.bulk-content');
let options;
contentSelect.empty();
if(selectedType == '최초전월이월') {
contentSelect.append(`<option value="최초전월이월">최초전월이월</option>`);
options = incomeOptions;
} else {
options = (selectedType === '수입') ? incomeOptions : expenseOptions;
}
// 나머지 옵션들 추가
for (const key in options) {
if (key !== '전월이월') { // 전월이월은 이미 추가했으므로 건너뜀
contentSelect.append(`<option value="${key}">${key}</option>`);
}
}
contentSelect.trigger('change'); // 항목이 변경되었으므로 세부항목도 업데이트
}
/**
* '항목' 선택에 따라 '세부항목' 드롭다운 메뉴를 업데이트하는 함수
*/
function updateBulkSubOptions($selectElement) {
const selectedKey = $selectElement.val();
const inoutsepValue = $selectElement.closest('tr').find('.bulk-inoutsep').val() || '지출';
console.log('updateBulkSubOptions 함수 호출 후 selectedKey : ', selectedKey, ', inoutsep:', inoutsepValue);
const contentSubSelect = $selectElement.closest('tr').find('.bulk-contentSub');
$.ajax({
url: 'fetch_modal.php',
type: 'POST',
data: {
action: 'getSubOptions',
selectedKey: selectedKey,
inoutsep: inoutsepValue // 수입/지출 구분 추가
},
dataType: 'json',
success: function(response) {
contentSubSelect.empty();
console.log(response);
if (response.subOptions && response.subOptions.length > 0) {
response.subOptions.forEach(item => {
for (const key in item) {
contentSubSelect.append(`<option value="${key}">${key}</option>`);
}
});
} else {
contentSubSelect.append(`<option value="">없음</option>`);
}
},
error: function() {
contentSubSelect.empty().append('<option value="">없음</option>');
}
});
}
/**
* 대량 등록 모달의 모든 데이터를 서버로 전송하여 저장하는 함수
*/
function saveBulkData() {
// 1) 행 데이터 수집 (entries 배열)
let entries = [];
$("#bulkEntryTable tbody tr").each(function() {
const $r = $(this);
const amt = $r.find(".bulk-amount").val().replace(/,/g,'');
const registDate = $r.find(".bulk-registDate").val();
if (!amt || !registDate || registDate === '0000-00-00') {
Swal.fire({
title: '등록일과 금액은 필수입니다.',
icon: 'warning',
confirmButtonText: '확인'
});
return;
}
if (!amt) return; // 금액 없으면 건너뜀
entries.push({
registDate: $r.find(".bulk-registDate").val(),
inoutsep: $r.find(".bulk-inoutsep").val(),
bankbook: $r.find(".bulk-bankbook").val(),
content: $r.find(".bulk-content").val() || '',
contentSub: $r.find(".bulk-contentSub").val() || '',
content_detail: $r.find(".bulk-content_detail").val() || '',
amount: amt,
secondordnum:$r.find(".bulk-secondordnum").val()|| '',
dueDate: $r.find(".bulk-dueDate").val() || '',
endorsementDate: $r.find(".bulk-endorsementDate").val() || '',
// **여기에 timekey 추가**
timekey: bulkTimeKey
});
});
if (entries.length === 0) {
return Swal.fire('입력 없음','저장할 데이터가 없습니다.','info');
}
// 2) 서버에 bulk insert
$.ajax({
url: "/account/insert_bulk.php",
method: "POST",
data: { entries: JSON.stringify(entries) },
dataType: "json"
}).done(function(resp) {
if (resp.status !== 'success') {
return Swal.fire('저장 실패', resp.message || 'Bulk insert 오류','error');
}
// resp.nums 는 [num1, num2, …] 형태로, entries 순서와 같은 인덱스 매칭
const nums = resp.nums;
let uploads = []; // Promise 배열
nums.forEach((num, idx) => {
const input = $("#bulkEntryTable tbody tr").eq(idx).find(".bulk-image-input")[0];
if (input && input.files.length > 0) {
// FormData 로 이미지만 전송
const fd = new FormData();
fd.append("tablename", "account");
fd.append("item", "image");
fd.append("upfilename","bulkImage");
fd.append("folderPath","경동기업/uploads");
fd.append("DBtable", "picuploads");
// **여기도 timekey 사용**
fd.append("timekey", bulkTimeKey);
fd.append("num", num); // 실제 num 업뎃 후에도 num 포함해 두면 안전합니다
Array.from(input.files).forEach(file => {
fd.append("bulkImage[]", file);
});
uploads.push(
$.ajax({
url: "/filedrive/fileprocess.php",
method: "POST",
data: fd,
processData: false,
contentType: false
})
);
}
});
// 3) 모든 이미지 업로드가 끝나면 리로드
Promise.all(uploads)
.then(() => {
Toastify({
text: `${entries.length}건 저장 완료`,
duration: 2000,
close: true,
gravity: "top", position: "center",
backgroundColor: "#4fbe87"
}).showToast();
})
.catch(err => {
console.error("이미지 업로드 중 오류:", err);
Toastify({
text: "일부 이미지 업로드에 실패했습니다.",
duration: 3000,
close: true,
gravity: "top", position: "center",
backgroundColor: "#f44336"
}).showToast();
})
.finally(() => {
setTimeout(()=> {
$("#bulkEntryModal").hide();
// 배경 스크롤 복원
enableBodyScroll();
location.reload();
}, 1500);
});
}).fail((jq,status,err) => {
Swal.fire('서버 오류','대량 저장 중 오류가 발생했습니다.','error');
console.error(status, err);
});
}
// --- 대량등록 관련 스크립트 끝 ---
$(function() {
var $modal = $('#bulkEntryModal');
var $openBtn = $('#openAccountModal');
var $closeBtns = $('#closeAccountModal, #closeAccountModal2');
var $dateInput = $('#accountDate');
var $accountCompany = $('#accountCompany');
var $secondord = $('#secondord');
var $saveBtn = $('#saveAccountBtn');
var $body = $('body');
// 모달 열기
$openBtn.on('click', function() {
$modal.show();
// 날짜 초기화
if (!$dateInput.val()) {
var today = new Date();
var yyyy = today.getFullYear();
var mm = String(today.getMonth() + 1).padStart(2, '0');
var dd = String(today.getDate()).padStart(2, '0');
$dateInput.val(yyyy + '-' + mm + '-' + dd);
}
// 거래처 초기화
if ($secondord.val()) {
$accountCompany.val($secondord.val());
}
$body.addClass('modal-open'); // 스크롤 방지
});
// 모달 닫기 (× 버튼들)
$closeBtns.on('click', function() {
$modal.hide();
$body.removeClass('modal-open');
});
// 저장 버튼 클릭
$saveBtn.on('click', function() {
saveData_account(); // 사용자가 정의한 함수 호출
$modal.hide();
$body.removeClass('modal-open');
});
// 바깥 영역 클릭 시 닫기
$modal.on('click', function(e) {
if (e.target === this) {
$modal.hide();
$body.removeClass('modal-open');
}
});
});
</script>
<script>
// 거래처 검색 버튼 클릭 이벤트
$(document).on('click', '.bulk-search-company', function() {
const $row = $(this).closest('tr');
const $secondordnum = $row.find('.bulk-secondordnum');
const $contentDetail = $row.find('.bulk-content_detail');
returnID = '수금등록';
href = '/phonebook/list.php?search=&returnID=' + returnID;
popupCenter(href, '전화번호 검색', 1800, 800);
});
// 거래처 선택 시 처리
function setCompanyInfo(companyCode, companyName) {
const $activeRow = $('#bulkEntryTable tbody tr:last');
$activeRow.find('.bulk-secondordnum').val(companyCode);
$activeRow.find('.bulk-content_detail').val(companyName);
}
// 팝업 중앙 정렬 함수
function popupCenter(url, title, w, h) {
var left = (screen.width/2)-(w/2);
var top = (screen.height/2)-(h/2);
return window.open(url, title, 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=yes, copyhistory=no, width='+w+', height='+h+', top='+top+', left='+left);
}
// 행 복사 이벤트
$(document).on('click', '.copy-row', function() {
const $currentRow = $(this).closest('tr');
const $newRow = $currentRow.clone();
// 현재 행의 값들 저장
const currentInoutsep = $currentRow.find('.bulk-inoutsep').val();
const currentBankbook = $currentRow.find('.bulk-bankbook').val();
const currentContent = $currentRow.find('.bulk-content').val();
const currentContentSub = $currentRow.find('.bulk-contentSub').val();
const currentSecondordnum = $currentRow.find('.bulk-secondordnum').val();
const currentContentDetail = $currentRow.find('.bulk-content_detail').val();
const currentAmount = $currentRow.find('.bulk-amount').val();
const currentDueDate = $currentRow.find('.bulk-dueDate').val();
const currentEndorsementDate = $currentRow.find('.bulk-endorsementDate').val();
const currentRegistDate = $currentRow.find('.bulk-registDate').val();
// 현재 행 바로 아래에 삽입
$currentRow.after($newRow);
// 모든 값들을 새 행에 설정
$newRow.find('.bulk-registDate').val(currentRegistDate);
$newRow.find('.bulk-inoutsep').val(currentInoutsep);
$newRow.find('.bulk-bankbook').val(currentBankbook);
$newRow.find('.bulk-secondordnum').val(currentSecondordnum);
$newRow.find('.bulk-content_detail').val(currentContentDetail);
$newRow.find('.bulk-amount').val(currentAmount);
$newRow.find('.bulk-dueDate').val(currentDueDate);
$newRow.find('.bulk-endorsementDate').val(currentEndorsementDate);
// 구분 변경 이벤트 트리거
$newRow.find('.bulk-inoutsep').trigger('change');
// 항목과 세부항목 설정을 위한 지연 처리
setTimeout(function() {
$newRow.find('.bulk-content').val(currentContent);
$newRow.find('.bulk-content').trigger('change');
// 세부항목 설정을 위한 추가 지연
setTimeout(function() {
$newRow.find('.bulk-contentSub').val(currentContentSub);
}, 100);
}, 100);
// 토스트 메시지 표시
Toastify({
text: "행이 복사되었습니다",
duration: 2000,
close: true,
gravity: "top",
position: "center",
backgroundColor: "#4fbe87",
}).showToast();
});
// 항목 선택 변경 이벤트 핸들러 수정
$(document).on('change', '.bulk-content', function() {
const $row = $(this).closest('tr');
const selectedKey = $(this).val();
const inoutsepValue = $row.find('.bulk-inoutsep').val() || '지출';
const $contentSubSelect = $row.find('.bulk-contentSub');
// 현재 선택된 세부항목 값 저장
const currentSubValue = $contentSubSelect.val();
$.ajax({
url: 'fetch_modal.php',
type: 'POST',
data: {
action: 'getSubOptions',
selectedKey: selectedKey,
inoutsep: inoutsepValue // 수입/지출 구분 추가
},
dataType: 'json',
success: function(response) {
$contentSubSelect.empty();
if (response.subOptions && response.subOptions.length > 0) {
response.subOptions.forEach(item => {
for (const key in item) {
const option = document.createElement('option');
option.value = key;
option.text = key;
$contentSubSelect.append(option);
}
});
// 이전에 선택된 값이 있으면 다시 선택
if (currentSubValue) {
$contentSubSelect.val(currentSubValue);
}
} else {
$contentSubSelect.append(`<option value="">없음</option>`);
}
},
error: function() {
$contentSubSelect.empty().append('<option value="">없음</option>');
}
});
});
function getGoogleDriveFileId(link) {
// 구글드라이브 파일ID 추출
var match = link.match(/\/d\/([a-zA-Z0-9_-]+)/);
return match ? match[1] : '';
}
// --- 여기부터 수정 및 추가된 함수 ---
// 로딩 모달을 보여주는 함수 (새로 추가)
function showImageLoadingModal() {
$('#loadingImageModal').modal('show');
}
// 로딩 모달을 숨기는 함수 (새로 추가)
function hideImageLoadingModal() {
$('#loadingImageModal').modal('hide');
}
// 이미지 팝업을 여는 함수 (보완됨)
function openTmpImagePopup(link, imageId) {
showImageLoadingModal(); // 이미지 클릭 즉시 로딩 모달 표시
console.log('link : ', link);
console.log('imageId : ', imageId);
var fileId = getGoogleDriveFileId(link);
if (!fileId) {
alert('구글드라이브 파일ID 추출 실패');
hideImageLoadingModal(); // 오류 발생 시 모달 숨김
return;
}
const imgElement = document.getElementById(imageId);
let currentRotation = 0;
if (imgElement) {
const transformStyle = imgElement.style.transform;
currentRotation = transformStyle
? parseInt(transformStyle.replace('rotate(', '').replace('deg)', '')) || 0
: 0;
} else {
console.warn('이미지 요소가 존재하지 않습니다:', imageId);
}
$.post('/filedrive/download_and_rotate.php', { fileId: fileId, rotation: currentRotation }, function(res) {
if (res.success) {
// 팝업 창 열기. 팝업 창이 로딩 모달을 닫는 역할을 함.
var popupWindow = popupCenter(
'/filedrive/view_tmpimg.php?img=' + encodeURIComponent(res.imgUrl) + '&rotation=' + res.rotation,
'imagePopup', 800, 600
);
if (!popupWindow) {
alert('팝업 창을 여는 데 실패했습니다. 브라우저의 팝업 차단 설정을 확인해주세요.');
hideImageLoadingModal();
}
} else {
alert(res.msg || '이미지 처리 실패');
hideImageLoadingModal();
}
}, 'json').fail(function() {
alert('서버와 통신 중 오류가 발생했습니다.');
hideImageLoadingModal();
});
}
// 전자어음 데이터 로드 함수
function loadElectronicBills() {
$.ajax({
url: 'get_electronic_bills.php',
type: 'GET',
dataType: 'json',
success: function(response) {
if (response.success) {
displayElectronicBills(response.data);
$('#electronicBillModal').modal('show');
} else {
alert('전자어음 데이터를 불러오는데 실패했습니다.');
}
},
error: function() {
alert('서버와 통신 중 오류가 발생했습니다.');
}
});
}
// 전자어음 목록 표시 함수
function displayElectronicBills(data) {
const tbody = $('#electronicBillTableBody');
tbody.empty();
if (data.length === 0) {
tbody.append('<tr><td colspan="8" class="text-center">배서일자가 없는 전자어음이 없습니다.</td></tr>');
return;
}
data.forEach(function(item) {
const row = `
<tr>
<td>${item.num}</td>
<td>${item.registDate}</td>
<td>${item.content || ''}</td>
<td>${item.contentSub || ''}</td>
<td>${item.content_detail || ''}</td>
<td class="text-end">${numberWithCommas(item.amount)}</td>
<td>${item.dueDate || ''}</td>
<td>
<button type="button" class="btn btn-primary btn-sm" onclick="selectElectronicBill('${item.num}', '${item.content}', '${item.contentSub}', '${item.content_detail}', '${item.amount}', '${item.dueDate}')">
선택
</button>
</td>
</tr>
`;
tbody.append(row);
});
}
// 전자어음 선택 함수
function selectElectronicBill(num, content, contentSub, contentDetail, amount, dueDate) {
// 모달 닫기
$('#electronicBillModal').modal('hide');
// 구분이 '지출'인 경우 항목을 '외상매출채권(전자어음)'으로 설정
const inoutsep = document.getElementById('inoutsep') ? document.getElementById('inoutsep').value : '';
if (inoutsep === '지출') {
$('#content').val('외상매출채권(전자어음)');
$('#contentSub').val('없음');
} else {
$('#content').val(content);
$('#contentSub').val(contentSub);
}
$('#content_detail').val(contentDetail);
$('#amount').val(numberWithCommas(amount));
$('#dueDate').val(dueDate);
$('#parentEBNum').val(num);
// 항목 변경 이벤트 트리거
$('#content').trigger('change');
// 토스트 메시지 표시
Toastify({
text: "전자어음 데이터가 적용되었습니다",
duration: 2000,
close: true,
gravity: "top",
position: "center",
backgroundColor: "#4fbe87",
}).showToast();
}
// 대량등록용 전자어음 데이터 로드 함수
function loadElectronicBillsForBulk($row) {
$.ajax({
url: 'get_electronic_bills.php',
type: 'GET',
dataType: 'json',
success: function(response) {
if (response.success) {
displayElectronicBillsForBulk(response.data, $row);
$('#electronicBillModal').modal('show');
} else {
alert('전자어음 데이터를 불러오는데 실패했습니다.');
}
},
error: function() {
alert('서버와 통신 중 오류가 발생했습니다.');
}
});
}
// 대량등록용 전자어음 목록 표시 함수
function displayElectronicBillsForBulk(data, $row) {
const tbody = $('#electronicBillTableBody');
tbody.empty();
if (data.length === 0) {
tbody.append('<tr><td colspan="8" class="text-center">배서일자가 없는 전자어음이 없습니다.</td></tr>');
return;
}
data.forEach(function(item) {
const rowIndex = $row.index();
const row = `
<tr>
<td>${item.num}</td>
<td>${item.registDate}</td>
<td>${item.content || ''}</td>
<td>${item.contentSub || ''}</td>
<td>${item.content_detail || ''}</td>
<td class="text-end">${numberWithCommas(item.amount)}</td>
<td>${item.dueDate || ''}</td>
<td>
<button type="button" class="btn btn-primary btn-sm" onclick="selectElectronicBillForBulk('${item.num}', '${item.content || ''}', '${item.contentSub || ''}', '${item.content_detail || ''}', '${item.amount}', '${item.dueDate || ''}', ${rowIndex})">
선택
</button>
</td>
</tr>
`;
tbody.append(row);
});
}
// 대량등록용 전자어음 선택 함수
function selectElectronicBillForBulk(num, content, contentSub, contentDetail, amount, dueDate, rowIndex) {
// 모달 닫기
$('#electronicBillModal').modal('hide');
// 해당 행의 필드에 데이터 적용
const $row = $('#bulkEntryTable tbody tr').eq(rowIndex);
// 구분이 '지출'인 경우 항목을 '외상매출채권(전자어음)'으로 설정
const inoutsep = $row.find('.bulk-inoutsep').val();
if (inoutsep === '지출') {
$row.find('.bulk-content').val('외상매출채권(전자어음)');
$row.find('.bulk-contentSub').val('없음');
} else {
$row.find('.bulk-content').val(content);
$row.find('.bulk-contentSub').val(contentSub);
}
$row.find('.bulk-content_detail').val(contentDetail);
$row.find('.bulk-amount').val(numberWithCommas(amount));
$row.find('.bulk-dueDate').val(dueDate);
// 항목 변경 이벤트 트리거
$row.find('.bulk-content').trigger('change');
// 토스트 메시지 표시
Toastify({
text: "전자어음 데이터가 적용되었습니다",
duration: 2000,
close: true,
gravity: "top",
position: "center",
backgroundColor: "#4fbe87",
}).showToast();
}
// 전자어음 목록 불러오기
// 그리기 모드 토글 함수
function toggleDrawingMode() {
const body = document.body;
const isDrawingMode = body.classList.contains('drawing-mode');
if (isDrawingMode) {
// 그리기 모드 비활성화
body.classList.remove('drawing-mode');
// 그리기 관련 컨트롤들 숨기기
const drawingControls = document.querySelectorAll('.drawing-controls .btn, .drawing-controls select, .drawing-controls input[type="color"], .drawing-controls input[type="range"], .drawing-controls span');
drawingControls.forEach(control => {
if (control.id !== 'drawBtn') {
control.style.display = 'none';
}
});
// 캔버스 제거
const canvas = document.querySelector('.drawing-canvas');
if (canvas) {
canvas.remove();
}
} else {
// 그리기 모드 활성화
body.classList.add('drawing-mode');
// 그리기 관련 컨트롤들 표시
const drawingControls = document.querySelectorAll('.drawing-controls .btn, .drawing-controls select, .drawing-controls input[type="color"], .drawing-controls input[type="range"], .drawing-controls span');
drawingControls.forEach(control => {
if (control.id !== 'drawBtn') {
control.style.display = 'inline-block';
}
});
// 캔버스 생성
createDrawingCanvas();
}
}
// 그리기 캔버스 생성 함수
function createDrawingCanvas() {
const previewContainer = document.getElementById('previewContainer');
if (!previewContainer) return;
// 기존 캔버스 제거
const existingCanvas = document.querySelector('.drawing-canvas');
if (existingCanvas) {
existingCanvas.remove();
}
// 새 캔버스 생성
const canvas = document.createElement('canvas');
canvas.className = 'drawing-canvas';
canvas.width = previewContainer.offsetWidth;
canvas.height = previewContainer.offsetHeight;
previewContainer.appendChild(canvas);
// 그리기 기능 초기화
initDrawingCanvas(canvas);
}
// 그리기 기능 초기화
function initDrawingCanvas(canvas) {
const ctx = canvas.getContext('2d');
let isDrawing = false;
let lastX = 0;
let lastY = 0;
// 마우스 이벤트 리스너
canvas.addEventListener('mousedown', startDrawing);
canvas.addEventListener('mousemove', draw);
canvas.addEventListener('mouseup', stopDrawing);
canvas.addEventListener('mouseout', stopDrawing);
function startDrawing(e) {
isDrawing = true;
[lastX, lastY] = [e.offsetX, e.offsetY];
}
function draw(e) {
if (!isDrawing) return;
ctx.beginPath();
ctx.moveTo(lastX, lastY);
ctx.lineTo(e.offsetX, e.offsetY);
ctx.strokeStyle = document.getElementById('drawColor').value;
ctx.lineWidth = document.getElementById('eraserSize').value;
ctx.lineCap = 'round';
ctx.stroke();
[lastX, lastY] = [e.offsetX, e.offsetY];
}
function stopDrawing() {
isDrawing = false;
}
}
// 그리기 버튼 클릭 이벤트
$(document).on("click", "#drawBtn", function() {
toggleDrawingMode();
});
// 지우개 크기 조절
$(document).on("input", "#eraserSize", function() {
document.getElementById('eraserSizeLabel').textContent = this.value + 'px';
});
// 그리기 초기화 버튼
$(document).on("click", "#clearDrawingBtn", function() {
const canvas = document.querySelector('.drawing-canvas');
if (canvas) {
const ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
});
// 그리기 저장 버튼
$(document).on("click", "#saveDrawingBtn", function() {
const canvas = document.querySelector('.drawing-canvas');
if (canvas) {
const dataURL = canvas.toDataURL('image/png');
// 여기에 저장 로직 추가
console.log('그리기 저장:', dataURL);
}
});
</script>
</body>
</html>