prepare(" SELECT * FROM accounts WHERE user_id = ? AND is_active = 1 ORDER BY FIELD(account_type, 'bank', 'card', 'cash', 'other'), id ASC "); $stmt->execute([$uid]); $accounts = $stmt->fetchAll(); $stmt = $pdo->prepare(" SELECT * FROM categories WHERE user_id = ? AND is_active = 1 ORDER BY category_type, sort_order, id "); $stmt->execute([$uid]); $categories = $stmt->fetchAll(); $defaults = get_transaction_form_defaults($uid); $lastForm = $_SESSION['tx_create_last_form'] ?? []; $form = [ 'transaction_type' => 'expense', 'account_id' => (int)($defaults['default_account_id'] ?? 0), 'related_account_id' => 0, 'category_id' => (int)($defaults['default_expense_category_id'] ?? 0), 'amount' => '', 'transaction_date' => date('Y-m-d'), 'merchant_name' => '', 'description' => '', 'is_installment' => 0, 'installment_months' => '', 'installment_interest_rate' => '0', 'installment_interest_total' => '', 'installment_total_billed' => '', 'continue_after_save' => !empty($defaults['continue_after_save']) ? 1 : 0, 'keep_last_values' => !empty($defaults['keep_last_values']) ? 1 : 0, 'save_as_defaults' => 0, ]; if (!empty($defaults['keep_last_values']) && !empty($lastForm)) { $form = array_merge($form, $lastForm); } $copyId = (int)($_GET['copy_id'] ?? 0); if ($copyId > 0 && $_SERVER['REQUEST_METHOD'] !== 'POST') { $stmt = $pdo->prepare(" SELECT * FROM transactions WHERE id = ? AND user_id = ? LIMIT 1 "); $stmt->execute([$copyId, $uid]); $copy = $stmt->fetch(); if ($copy) { $form = array_merge($form, [ 'transaction_type' => $copy['transaction_type'], 'account_id' => (int)$copy['account_id'], 'related_account_id' => (int)($copy['related_account_id'] ?? 0), 'category_id' => (int)$copy['category_id'], 'amount' => number_format((float)$copy['amount'], 0), 'transaction_date' => date('Y-m-d'), 'merchant_name' => (string)($copy['merchant_name'] ?? ''), 'description' => (string)($copy['description'] ?? ''), 'is_installment' => (int)($copy['is_installment'] ?? 0), 'installment_months' => $copy['installment_months'] ?? '', 'installment_interest_rate' => (string)($copy['installment_interest_rate'] ?? '0'), 'installment_interest_total' => !empty($copy['installment_interest_total']) ? number_format((float)$copy['installment_interest_total'], 0) : '', 'installment_total_billed' => !empty($copy['installment_total_billed']) ? number_format((float)$copy['installment_total_billed'], 0) : '', 'continue_after_save' => 0, 'keep_last_values' => 0, 'save_as_defaults' => 0, ]); $success = '기존 거래를 복사했습니다. 날짜/메모 수정 후 저장하세요.'; } } if ($_SERVER['REQUEST_METHOD'] === 'POST') { try { $form = [ 'transaction_type' => $_POST['transaction_type'] ?? 'expense', 'account_id' => (int)($_POST['account_id'] ?? 0), 'related_account_id' => !empty($_POST['related_account_id']) ? (int)$_POST['related_account_id'] : 0, 'category_id' => (int)($_POST['category_id'] ?? 0), 'amount' => trim((string)($_POST['amount'] ?? '')), 'transaction_date' => $_POST['transaction_date'] ?? date('Y-m-d'), 'merchant_name' => trim((string)($_POST['merchant_name'] ?? '')), 'description' => trim((string)($_POST['description'] ?? '')), 'is_installment' => (int)($_POST['is_installment'] ?? 0), 'installment_months' => trim((string)($_POST['installment_months'] ?? '')), 'installment_interest_rate' => trim((string)($_POST['installment_interest_rate'] ?? '0')), 'installment_interest_total' => trim((string)($_POST['installment_interest_total'] ?? '')), 'installment_total_billed' => trim((string)($_POST['installment_total_billed'] ?? '')), 'continue_after_save' => !empty($_POST['continue_after_save']) ? 1 : 0, 'keep_last_values' => !empty($_POST['keep_last_values']) ? 1 : 0, 'save_as_defaults' => !empty($_POST['save_as_defaults']) ? 1 : 0, ]; $transactionType = $form['transaction_type']; $accountId = (int)$form['account_id']; $categoryId = (int)$form['category_id']; $amount = (float)str_replace(',', '', $form['amount']); $transactionDate = $form['transaction_date']; $merchantName = $form['merchant_name']; $description = $form['description']; $relatedAccountId = $form['related_account_id'] > 0 ? (int)$form['related_account_id'] : null; $isInstallment = (int)$form['is_installment']; $installmentMonths = $form['installment_months'] !== '' ? (int)$form['installment_months'] : null; $installmentInterestRate = $form['installment_interest_rate'] !== '' ? (float)$form['installment_interest_rate'] : 0.0; $installmentInterestTotal = $form['installment_interest_total'] !== '' ? (float)str_replace(',', '', $form['installment_interest_total']) : null; $installmentTotalBilled = $form['installment_total_billed'] !== '' ? (float)str_replace(',', '', $form['installment_total_billed']) : null; if ($amount <= 0) { throw new RuntimeException('금액은 0보다 커야 합니다.'); } if (!in_array($transactionType, ['income', 'expense', 'transfer', 'card_payment'], true)) { throw new RuntimeException('거래 유형이 올바르지 않습니다.'); } if ($accountId <= 0) { throw new RuntimeException('주 계좌/카드를 선택하세요.'); } if ($categoryId <= 0) { throw new RuntimeException('카테고리를 선택하세요.'); } if (in_array($transactionType, ['transfer', 'card_payment'], true) && !$relatedAccountId) { throw new RuntimeException('관련 계좌를 선택해야 합니다.'); } if ($relatedAccountId && $relatedAccountId === $accountId) { throw new RuntimeException('주 계좌와 관련 계좌는 같을 수 없습니다.'); } if ($transactionType !== 'expense') { $isInstallment = 0; $installmentMonths = null; $installmentInterestRate = 0.0; $installmentInterestTotal = null; $installmentTotalBilled = null; } create_transaction([ 'user_id' => $uid, 'account_id' => $accountId, 'category_id' => $categoryId, 'transaction_type' => $transactionType, 'amount' => $amount, 'transaction_date' => $transactionDate, 'merchant_name' => $merchantName !== '' ? $merchantName : null, 'description' => $description !== '' ? $description : null, 'related_account_id' => $relatedAccountId, 'is_installment' => $isInstallment, 'installment_months' => $installmentMonths, 'installment_interest_rate' => $installmentInterestRate, 'installment_interest_total' => $installmentInterestTotal, 'installment_total_billed' => $installmentTotalBilled, ]); if ($form['save_as_defaults']) { $save = [ 'default_account_id' => 0, 'default_card_account_id' => 0, 'default_income_category_id' => 0, 'default_expense_category_id' => 0, 'default_transfer_category_id' => 0, 'default_card_payment_category_id' => 0, 'keep_last_values' => $form['keep_last_values'], 'continue_after_save' => $form['continue_after_save'], ]; if ($transactionType === 'income') { $save['default_account_id'] = $accountId; $save['default_income_category_id'] = $categoryId; } elseif ($transactionType === 'expense') { $save['default_account_id'] = $accountId; $save['default_expense_category_id'] = $categoryId; } elseif ($transactionType === 'transfer') { $save['default_account_id'] = $accountId; $save['default_transfer_category_id'] = $categoryId; } elseif ($transactionType === 'card_payment') { $save['default_account_id'] = $accountId; $save['default_card_payment_category_id'] = $categoryId; } foreach ($accounts as $acc) { if ((int)$acc['id'] === $accountId && $acc['account_type'] === 'card') { $save['default_card_account_id'] = $accountId; break; } } save_transaction_form_defaults($uid, array_merge($defaults, $save)); } if ($form['keep_last_values']) { $_SESSION['tx_create_last_form'] = [ 'transaction_type' => $transactionType, 'account_id' => $accountId, 'related_account_id' => $relatedAccountId ?: 0, 'category_id' => $categoryId, 'amount' => '', 'transaction_date' => date('Y-m-d'), 'merchant_name' => $merchantName, 'description' => '', 'is_installment' => $isInstallment, 'installment_months' => $installmentMonths ?? '', 'installment_interest_rate' => (string)$installmentInterestRate, 'installment_interest_total' => '', 'installment_total_billed' => '', 'continue_after_save' => $form['continue_after_save'], 'keep_last_values' => $form['keep_last_values'], 'save_as_defaults' => 0, ]; } else { unset($_SESSION['tx_create_last_form']); } if ($form['continue_after_save']) { $success = '저장되었습니다. 계속 등록할 수 있습니다.'; $form['amount'] = ''; $form['description'] = ''; $form['transaction_date'] = date('Y-m-d'); $form['installment_interest_total'] = ''; $form['installment_total_billed'] = ''; } else { redirect('/transactions.php'); } } catch (Throwable $e) { $error = $e->getMessage(); } } $accountsJson = []; foreach ($accounts as $acc) { $accountsJson[] = [ 'id' => (int)$acc['id'], 'name' => $acc['account_name'], 'type' => $acc['account_type'], 'card_kind' => $acc['card_kind'] ?? null, 'billing_day' => $acc['billing_day'] ?? null, 'payment_day' => $acc['payment_day'] ?? null, 'use_credit_grace_period' => !empty($acc['use_credit_grace_period']) ? 1 : 0, ]; } $categoriesJson = []; foreach ($categories as $cat) { $categoriesJson[] = [ 'id' => (int)$cat['id'], 'type' => $cat['category_type'], 'name' => $cat['name'], ]; } require __DIR__ . '/../app/views/header.php'; ?>