362 lines
17 KiB
PHP
362 lines
17 KiB
PHP
<?php
|
|
require_once __DIR__ . '/../app/lib/auth.php';
|
|
require_once __DIR__ . '/../app/lib/db.php';
|
|
require_once __DIR__ . '/../app/lib/helpers.php';
|
|
require_once __DIR__ . '/../app/lib/account_service.php';
|
|
|
|
check_auth();
|
|
|
|
$pdo = db();
|
|
$uid = user_id();
|
|
$id = (int)($_GET['id'] ?? 0);
|
|
$error = '';
|
|
|
|
$stmt = $pdo->prepare("SELECT * FROM accounts WHERE id = ? AND user_id = ?");
|
|
$stmt->execute([$id, $uid]);
|
|
$account = $stmt->fetch();
|
|
|
|
if (!$account) {
|
|
exit('계좌를 찾을 수 없습니다.');
|
|
}
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
try {
|
|
$accountType = $_POST['account_type'] ?? '';
|
|
$institutionName = trim($_POST['institution_name'] ?? '');
|
|
$accountName = trim($_POST['account_name'] ?? '');
|
|
$openingBalance = (float)str_replace(',', '', (string)($_POST['opening_balance'] ?? 0));
|
|
$isActive = isset($_POST['is_active']) ? 1 : 0;
|
|
|
|
$cardKind = $_POST['card_kind'] ?? null;
|
|
$billingDay = !empty($_POST['billing_day']) ? (int)$_POST['billing_day'] : null;
|
|
$paymentDay = !empty($_POST['payment_day']) ? (int)$_POST['payment_day'] : null;
|
|
$useCreditGracePeriod = !empty($_POST['use_credit_grace_period']) ? 1 : 0;
|
|
$billingCycleMemo = trim($_POST['billing_cycle_memo'] ?? '');
|
|
|
|
$statementStartMonthOffset = isset($_POST['statement_start_month_offset']) && $_POST['statement_start_month_offset'] !== ''
|
|
? (int)$_POST['statement_start_month_offset']
|
|
: null;
|
|
$statementStartDay = !empty($_POST['statement_start_day']) ? (int)$_POST['statement_start_day'] : null;
|
|
$statementEndMonthOffset = isset($_POST['statement_end_month_offset']) && $_POST['statement_end_month_offset'] !== ''
|
|
? (int)$_POST['statement_end_month_offset']
|
|
: null;
|
|
$statementEndDay = !empty($_POST['statement_end_day']) ? (int)$_POST['statement_end_day'] : null;
|
|
|
|
if (!in_array($accountType, ['bank', 'card', 'cash', 'other'], true)) {
|
|
throw new RuntimeException('계정 유형이 올바르지 않습니다.');
|
|
}
|
|
|
|
if ($institutionName === '' || $accountName === '') {
|
|
throw new RuntimeException('기관명과 계좌명을 입력하세요.');
|
|
}
|
|
|
|
if ($accountType !== 'card') {
|
|
$cardKind = null;
|
|
$billingDay = null;
|
|
$paymentDay = null;
|
|
$useCreditGracePeriod = 0;
|
|
$billingCycleMemo = null;
|
|
$statementStartMonthOffset = null;
|
|
$statementStartDay = null;
|
|
$statementEndMonthOffset = null;
|
|
$statementEndDay = null;
|
|
} else {
|
|
if (!in_array($cardKind, ['credit', 'check'], true)) {
|
|
throw new RuntimeException('카드 종류를 선택하세요.');
|
|
}
|
|
|
|
if ($cardKind === 'check') {
|
|
$billingDay = null;
|
|
$paymentDay = null;
|
|
$useCreditGracePeriod = 0;
|
|
$billingCycleMemo = '즉시출금';
|
|
$statementStartMonthOffset = null;
|
|
$statementStartDay = null;
|
|
$statementEndMonthOffset = null;
|
|
$statementEndDay = null;
|
|
}
|
|
|
|
if ($cardKind === 'credit') {
|
|
if ($paymentDay === null || $paymentDay < 1 || $paymentDay > 31) {
|
|
throw new RuntimeException('납부일은 1~31 사이여야 합니다.');
|
|
}
|
|
|
|
if ($useCreditGracePeriod) {
|
|
if ($statementStartMonthOffset === null || $statementEndMonthOffset === null) {
|
|
throw new RuntimeException('사용기간의 시작/종료 월 기준을 선택하세요.');
|
|
}
|
|
|
|
if ($statementStartDay === null || $statementStartDay < 1 || $statementStartDay > 31) {
|
|
throw new RuntimeException('사용기간 시작일은 1~31 사이여야 합니다.');
|
|
}
|
|
|
|
if ($statementEndDay === null || $statementEndDay < 1 || $statementEndDay > 31) {
|
|
throw new RuntimeException('사용기간 종료일은 1~31 사이여야 합니다.');
|
|
}
|
|
} else {
|
|
$statementStartMonthOffset = null;
|
|
$statementStartDay = null;
|
|
$statementEndMonthOffset = null;
|
|
$statementEndDay = null;
|
|
}
|
|
|
|
if ($billingCycleMemo === '') {
|
|
$billingCycleMemo = null;
|
|
}
|
|
|
|
if ($billingDay !== null && ($billingDay < 1 || $billingDay > 31)) {
|
|
throw new RuntimeException('구형 결제기준일은 1~31 사이여야 합니다.');
|
|
}
|
|
}
|
|
}
|
|
|
|
$stmt = $pdo->prepare("
|
|
UPDATE accounts
|
|
SET
|
|
account_type = ?,
|
|
institution_name = ?,
|
|
account_name = ?,
|
|
opening_balance = ?,
|
|
is_active = ?,
|
|
card_kind = ?,
|
|
billing_day = ?,
|
|
payment_day = ?,
|
|
use_credit_grace_period = ?,
|
|
statement_start_month_offset = ?,
|
|
statement_start_day = ?,
|
|
statement_end_month_offset = ?,
|
|
statement_end_day = ?,
|
|
billing_cycle_memo = ?
|
|
WHERE id = ?
|
|
AND user_id = ?
|
|
");
|
|
$stmt->execute([
|
|
$accountType,
|
|
$institutionName,
|
|
$accountName,
|
|
$openingBalance,
|
|
$isActive,
|
|
$cardKind,
|
|
$billingDay,
|
|
$paymentDay,
|
|
$useCreditGracePeriod,
|
|
$statementStartMonthOffset,
|
|
$statementStartDay,
|
|
$statementEndMonthOffset,
|
|
$statementEndDay,
|
|
$billingCycleMemo,
|
|
$id,
|
|
$uid
|
|
]);
|
|
|
|
recalculate_account_balance($id);
|
|
|
|
redirect('/accounts.php');
|
|
} catch (Throwable $e) {
|
|
$error = $e->getMessage();
|
|
}
|
|
}
|
|
|
|
require __DIR__ . '/../app/views/header.php';
|
|
?>
|
|
|
|
<div class="page-head">
|
|
<h2>계좌 / 카드 수정</h2>
|
|
<a href="/accounts.php" class="btn btn-outline-secondary">목록</a>
|
|
</div>
|
|
|
|
<?php if ($error): ?>
|
|
<div class="alert alert-danger"><?= h($error) ?></div>
|
|
<?php endif; ?>
|
|
|
|
<div class="card finance-card">
|
|
<div class="card-body">
|
|
<form method="post" class="row g-3" id="accountEditForm">
|
|
<div class="col-12 col-md-4">
|
|
<label class="form-label">유형</label>
|
|
<select name="account_type" id="account_type" class="form-select" required>
|
|
<?php foreach (['bank'=>'은행계좌','card'=>'카드','cash'=>'현금','other'=>'기타'] as $k => $v): ?>
|
|
<option value="<?= $k ?>" <?= $account['account_type'] === $k ? 'selected' : '' ?>><?= $v ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="col-12 col-md-4">
|
|
<label class="form-label">기관명</label>
|
|
<input type="text" name="institution_name" class="form-control" value="<?= h($account['institution_name']) ?>" required>
|
|
</div>
|
|
|
|
<div class="col-12 col-md-4">
|
|
<label class="form-label">계좌명</label>
|
|
<input type="text" name="account_name" class="form-control" value="<?= h($account['account_name']) ?>" required>
|
|
</div>
|
|
|
|
<div class="col-12 col-md-4">
|
|
<label class="form-label">시작 잔액</label>
|
|
<input type="text" name="opening_balance" id="opening_balance" class="form-control" inputmode="numeric" value="<?= h(money_plain($account['opening_balance'])) ?>" required>
|
|
</div>
|
|
|
|
<div class="col-12 col-md-4 d-flex align-items-end">
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" name="is_active" id="is_active" <?= $account['is_active'] ? 'checked' : '' ?>>
|
|
<label class="form-check-label" for="is_active">활성</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-12" id="card_setting_wrap" style="display:none;">
|
|
<div class="loan-create-highlight">
|
|
<div class="title">카드 설정</div>
|
|
<div class="desc">
|
|
카드사/결제일마다 신용공여기간이 다르므로 사용기간을 직접 설정합니다.
|
|
</div>
|
|
|
|
<div class="row g-3 mt-1">
|
|
<div class="col-12 col-md-3">
|
|
<label class="form-label">카드 종류</label>
|
|
<select name="card_kind" id="card_kind" class="form-select">
|
|
<option value="">선택하세요</option>
|
|
<option value="credit" <?= ($account['card_kind'] ?? '') === 'credit' ? 'selected' : '' ?>>신용카드</option>
|
|
<option value="check" <?= ($account['card_kind'] ?? '') === 'check' ? 'selected' : '' ?>>체크카드</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="col-12 col-md-3 credit-only">
|
|
<label class="form-label">납부일</label>
|
|
<input type="number" name="payment_day" id="payment_day" class="form-control" min="1" max="31" value="<?= h((string)($account['payment_day'] ?? '')) ?>" placeholder="예: 25">
|
|
</div>
|
|
|
|
<div class="col-12 col-md-3 credit-only d-flex align-items-end">
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" name="use_credit_grace_period" id="use_credit_grace_period" value="1" <?= !empty($account['use_credit_grace_period']) ? 'checked' : '' ?>>
|
|
<label class="form-check-label" for="use_credit_grace_period">신용공여기간 계산 사용</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-12 credit-only">
|
|
<hr>
|
|
<div class="fw-bold mb-2">청구월 기준 사용기간</div>
|
|
<div class="form-text mb-3">
|
|
예: 결제일 25일 기준 IBK는 “전월 11일 ~ 당월 10일 사용분” → 시작 월 기준 전월 / 시작일 11 / 종료 월 기준 당월 / 종료일 10
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-12 col-md-3 credit-period-only">
|
|
<label class="form-label">시작 월 기준</label>
|
|
<select name="statement_start_month_offset" class="form-select">
|
|
<?php foreach ([-2=>'전전월', -1=>'전월', 0=>'당월', 1=>'익월'] as $k => $v): ?>
|
|
<option value="<?= $k ?>" <?= (string)($account['statement_start_month_offset'] ?? '') === (string)$k ? 'selected' : '' ?>><?= $v ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="col-12 col-md-3 credit-period-only">
|
|
<label class="form-label">시작일</label>
|
|
<input type="number" name="statement_start_day" class="form-control" min="1" max="31" value="<?= h((string)($account['statement_start_day'] ?? '')) ?>" placeholder="예: 11">
|
|
</div>
|
|
|
|
<div class="col-12 col-md-3 credit-period-only">
|
|
<label class="form-label">종료 월 기준</label>
|
|
<select name="statement_end_month_offset" class="form-select">
|
|
<?php foreach ([-2=>'전전월', -1=>'전월', 0=>'당월', 1=>'익월'] as $k => $v): ?>
|
|
<option value="<?= $k ?>" <?= (string)($account['statement_end_month_offset'] ?? '') === (string)$k ? 'selected' : '' ?>><?= $v ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="col-12 col-md-3 credit-period-only">
|
|
<label class="form-label">종료일</label>
|
|
<input type="number" name="statement_end_day" class="form-control" min="1" max="31" value="<?= h((string)($account['statement_end_day'] ?? '')) ?>" placeholder="예: 10">
|
|
</div>
|
|
|
|
<div class="col-12 credit-only">
|
|
<label class="form-label">신용공여기간 메모</label>
|
|
<input type="text" name="billing_cycle_memo" class="form-control" value="<?= h($account['billing_cycle_memo'] ?? '') ?>" placeholder="예: 전월 11일 ~ 당월 10일 사용분">
|
|
</div>
|
|
|
|
<div class="col-12 credit-only">
|
|
<div class="alert alert-info mb-0">
|
|
결제일 25일 기준 예시:
|
|
IBK 신용카드 = 전월 11일 ~ 당월 10일,
|
|
우리카드 = 전월 12일 ~ 당월 11일.
|
|
신규 카드사는 카드사 안내표를 보고 직접 입력하면 됩니다.
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-12 check-only" style="display:none;">
|
|
<div class="alert alert-secondary mb-0">
|
|
체크카드는 신용공여기간 없이 거래월 기준으로 반영됩니다.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-12 d-flex flex-wrap gap-2">
|
|
<button class="btn btn-primary">저장</button>
|
|
<a href="/accounts.php" class="btn btn-outline-secondary">목록</a>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
(function () {
|
|
const accountTypeEl = document.getElementById('account_type');
|
|
const cardWrapEl = document.getElementById('card_setting_wrap');
|
|
const cardKindEl = document.getElementById('card_kind');
|
|
const creditOnlyEls = document.querySelectorAll('.credit-only');
|
|
const creditPeriodOnlyEls = document.querySelectorAll('.credit-period-only');
|
|
const checkOnlyEls = document.querySelectorAll('.check-only');
|
|
const useGraceEl = document.getElementById('use_credit_grace_period');
|
|
const openingBalanceEl = document.getElementById('opening_balance');
|
|
|
|
function formatWithComma(value) {
|
|
const normalized = String(value || '').replace(/,/g, '').replace(/[^\d.-]/g, '');
|
|
if (normalized === '' || normalized === '-') return normalized;
|
|
const negative = normalized.startsWith('-');
|
|
const raw = negative ? normalized.slice(1) : normalized;
|
|
const parts = raw.split('.');
|
|
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
|
return (negative ? '-' : '') + parts.join('.');
|
|
}
|
|
|
|
function setDisplay(nodes, visible) {
|
|
nodes.forEach(el => el.style.display = visible ? '' : 'none');
|
|
}
|
|
|
|
function toggleCardSettings() {
|
|
const isCard = accountTypeEl.value === 'card';
|
|
const isCredit = cardKindEl.value === 'credit';
|
|
const isCheck = cardKindEl.value === 'check';
|
|
const useGrace = useGraceEl && useGraceEl.checked;
|
|
|
|
cardWrapEl.style.display = isCard ? '' : 'none';
|
|
|
|
if (!isCard) {
|
|
return;
|
|
}
|
|
|
|
setDisplay(creditOnlyEls, isCredit);
|
|
setDisplay(checkOnlyEls, isCheck);
|
|
setDisplay(creditPeriodOnlyEls, isCredit && useGrace);
|
|
}
|
|
|
|
openingBalanceEl.addEventListener('input', function () {
|
|
this.value = formatWithComma(this.value);
|
|
});
|
|
|
|
document.getElementById('accountEditForm').addEventListener('submit', function () {
|
|
openingBalanceEl.value = openingBalanceEl.value.replace(/,/g, '');
|
|
});
|
|
|
|
accountTypeEl.addEventListener('change', toggleCardSettings);
|
|
cardKindEl.addEventListener('change', toggleCardSettings);
|
|
if (useGraceEl) {
|
|
useGraceEl.addEventListener('change', toggleCardSettings);
|
|
}
|
|
|
|
toggleCardSettings();
|
|
})();
|
|
</script>
|
|
|
|
<?php require __DIR__ . '/../app/views/footer.php'; ?>
|