329 lines
14 KiB
PHP
329 lines
14 KiB
PHP
<?php
|
|
require_once __DIR__ . '/../app/lib/auth.php';
|
|
require_once __DIR__ . '/../app/lib/db.php';
|
|
require_once __DIR__ . '/../app/lib/helpers.php';
|
|
|
|
check_auth();
|
|
|
|
$pdo = db();
|
|
$uid = user_id();
|
|
$error = '';
|
|
|
|
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));
|
|
|
|
$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;
|
|
}
|
|
}
|
|
}
|
|
|
|
$stmt = $pdo->prepare("
|
|
INSERT INTO accounts
|
|
(
|
|
user_id,
|
|
account_type,
|
|
institution_name,
|
|
account_name,
|
|
opening_balance,
|
|
current_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
|
|
)
|
|
VALUES
|
|
(?, ?, ?, ?, ?, ?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
");
|
|
|
|
$stmt->execute([
|
|
$uid,
|
|
$accountType,
|
|
$institutionName,
|
|
$accountName,
|
|
$openingBalance,
|
|
$openingBalance,
|
|
$cardKind,
|
|
$billingDay,
|
|
$paymentDay,
|
|
$useCreditGracePeriod,
|
|
$statementStartMonthOffset,
|
|
$statementStartDay,
|
|
$statementEndMonthOffset,
|
|
$statementEndDay,
|
|
$billingCycleMemo
|
|
]);
|
|
|
|
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="accountCreateForm">
|
|
|
|
<div class="col-12 col-md-4">
|
|
<label class="form-label">유형</label>
|
|
<select name="account_type" id="account_type" class="form-select" required>
|
|
<option value="bank">은행계좌</option>
|
|
<option value="card">카드</option>
|
|
<option value="cash">현금</option>
|
|
<option value="other">기타</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="col-12 col-md-4">
|
|
<label class="form-label">기관명</label>
|
|
<input type="text" name="institution_name" class="form-control" placeholder="예: IBK, 우리, 농협" required>
|
|
</div>
|
|
|
|
<div class="col-12 col-md-4">
|
|
<label class="form-label">계좌명</label>
|
|
<input type="text" name="account_name" class="form-control" placeholder="예: IBK 신용카드 / IBK 체크카드" 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" value="0" inputmode="numeric" required>
|
|
</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">신용카드</option>
|
|
<option value="check">체크카드</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="col-12 col-md-3 credit-only">
|
|
<label class="form-label">납부일</label>
|
|
<input type="number" name="payment_day" class="form-control" min="1" max="31" 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" checked>
|
|
<label class="form-check-label">신용공여기간 계산 사용</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-12 credit-only">
|
|
<hr>
|
|
<div class="fw-bold mb-2">청구월 기준 사용기간</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">
|
|
<option value="-2">전전월</option>
|
|
<option value="-1" selected>전월</option>
|
|
<option value="0">당월</option>
|
|
<option value="1">익월</option>
|
|
</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" 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">
|
|
<option value="-2">전전월</option>
|
|
<option value="-1">전월</option>
|
|
<option value="0" selected>당월</option>
|
|
<option value="1">익월</option>
|
|
</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" placeholder="예: 10">
|
|
</div>
|
|
|
|
<div class="col-12 credit-only">
|
|
<label class="form-label">메모</label>
|
|
<input type="text" name="billing_cycle_memo" class="form-control" placeholder="예: 전월 11일 ~ 당월 10일 사용분">
|
|
</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 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 useGraceEl = document.getElementById('use_credit_grace_period');
|
|
|
|
const creditOnlyEls = document.querySelectorAll('.credit-only');
|
|
const creditPeriodOnlyEls = document.querySelectorAll('.credit-period-only');
|
|
const checkOnlyEls = document.querySelectorAll('.check-only');
|
|
|
|
const openingBalanceEl = document.getElementById('opening_balance');
|
|
|
|
function comma(v) {
|
|
v = String(v).replace(/,/g, '').replace(/[^\d.-]/g, '');
|
|
if (!v) return '';
|
|
return Number(v).toLocaleString('ko-KR');
|
|
}
|
|
|
|
function show(nodes, on) {
|
|
nodes.forEach(el => el.style.display = on ? '' : 'none');
|
|
}
|
|
|
|
function refresh() {
|
|
const isCard = accountTypeEl.value === 'card';
|
|
const isCredit = cardKindEl.value === 'credit';
|
|
const isCheck = cardKindEl.value === 'check';
|
|
const useGrace = useGraceEl.checked;
|
|
|
|
cardWrapEl.style.display = isCard ? '' : 'none';
|
|
|
|
show(creditOnlyEls, isCredit);
|
|
show(checkOnlyEls, isCheck);
|
|
show(creditPeriodOnlyEls, isCredit && useGrace);
|
|
}
|
|
|
|
openingBalanceEl.addEventListener('input', function () {
|
|
this.value = comma(this.value);
|
|
});
|
|
|
|
document.getElementById('accountCreateForm').addEventListener('submit', function () {
|
|
openingBalanceEl.value = openingBalanceEl.value.replace(/,/g, '');
|
|
});
|
|
|
|
accountTypeEl.addEventListener('change', refresh);
|
|
cardKindEl.addEventListener('change', refresh);
|
|
useGraceEl.addEventListener('change', refresh);
|
|
|
|
refresh();
|
|
})();
|
|
</script>
|
|
|
|
<?php require __DIR__ . '/../app/views/footer.php'; ?>
|