Files
financial/app/lib/transaction_form_service.php
T
2026-06-07 00:33:58 +09:00

325 lines
9.5 KiB
PHP

<?php
require_once __DIR__ . '/db.php';
require_once __DIR__ . '/helpers.php';
/*
테이블 필요
CREATE TABLE IF NOT EXISTS user_transaction_defaults (
user_id BIGINT UNSIGNED NOT NULL PRIMARY KEY,
default_account_id BIGINT UNSIGNED DEFAULT NULL,
default_card_account_id BIGINT UNSIGNED DEFAULT NULL,
default_income_category_id BIGINT UNSIGNED DEFAULT NULL,
default_expense_category_id BIGINT UNSIGNED DEFAULT NULL,
default_transfer_category_id BIGINT UNSIGNED DEFAULT NULL,
default_card_payment_category_id BIGINT UNSIGNED DEFAULT NULL,
keep_last_values TINYINT(1) NOT NULL DEFAULT 1,
continue_after_save TINYINT(1) NOT NULL DEFAULT 1,
quick_amounts VARCHAR(255) DEFAULT NULL,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP
);
*/
function get_transaction_form_defaults(int $userId): array
{
$pdo = db();
$stmt = $pdo->prepare("
SELECT *
FROM user_transaction_defaults
WHERE user_id = ?
LIMIT 1
");
$stmt->execute([$userId]);
$row = $stmt->fetch();
if (!$row) {
return get_transaction_form_default_seed();
}
$row['keep_last_values'] = (int)$row['keep_last_values'];
$row['continue_after_save'] = (int)$row['continue_after_save'];
$row['quick_amounts'] = parse_quick_amounts($row['quick_amounts'] ?? '');
return array_merge(get_transaction_form_default_seed(), $row);
}
function get_transaction_form_default_seed(): array
{
return [
'default_account_id' => null,
'default_card_account_id' => null,
'default_income_category_id' => null,
'default_expense_category_id' => null,
'default_transfer_category_id' => null,
'default_card_payment_category_id' => null,
'keep_last_values' => 1,
'continue_after_save' => 1,
'quick_amounts' => [10000, 30000, 50000, 100000],
];
}
function save_transaction_form_defaults(int $userId, array $data): void
{
$pdo = db();
$quickAmounts = normalize_quick_amounts(
$data['quick_amounts'] ?? []
);
$stmt = $pdo->prepare("
INSERT INTO user_transaction_defaults
(
user_id,
default_account_id,
default_card_account_id,
default_income_category_id,
default_expense_category_id,
default_transfer_category_id,
default_card_payment_category_id,
keep_last_values,
continue_after_save,
quick_amounts
)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
default_account_id = VALUES(default_account_id),
default_card_account_id = VALUES(default_card_account_id),
default_income_category_id = VALUES(default_income_category_id),
default_expense_category_id = VALUES(default_expense_category_id),
default_transfer_category_id = VALUES(default_transfer_category_id),
default_card_payment_category_id = VALUES(default_card_payment_category_id),
keep_last_values = VALUES(keep_last_values),
continue_after_save = VALUES(continue_after_save),
quick_amounts = VALUES(quick_amounts)
");
$stmt->execute([
$userId,
nullable_id($data['default_account_id'] ?? null),
nullable_id($data['default_card_account_id'] ?? null),
nullable_id($data['default_income_category_id'] ?? null),
nullable_id($data['default_expense_category_id'] ?? null),
nullable_id($data['default_transfer_category_id'] ?? null),
nullable_id($data['default_card_payment_category_id'] ?? null),
!empty($data['keep_last_values']) ? 1 : 0,
!empty($data['continue_after_save']) ? 1 : 0,
implode(',', $quickAmounts),
]);
}
function nullable_id($value): ?int
{
$v = (int)$value;
return $v > 0 ? $v : null;
}
function parse_quick_amounts(string $csv): array
{
if (trim($csv) === '') {
return [10000, 30000, 50000, 100000];
}
$items = explode(',', $csv);
$result = [];
foreach ($items as $item) {
$v = (int)trim($item);
if ($v > 0) {
$result[] = $v;
}
}
if (!$result) {
return [10000, 30000, 50000, 100000];
}
return array_values(array_unique($result));
}
function normalize_quick_amounts(array $items): array
{
$result = [];
foreach ($items as $item) {
$v = (int)$item;
if ($v > 0) {
$result[] = $v;
}
}
if (!$result) {
$result = [10000, 30000, 50000, 100000];
}
$result = array_values(array_unique($result));
sort($result);
return $result;
}
/**
* 거래 등록 화면 초기값
*/
function build_transaction_form_state(
int $userId,
array $defaults,
?array $lastState = null
): array {
$state = [
'transaction_date' => current_date_ymd(),
'transaction_type' => 'expense',
'account_id' => $defaults['default_account_id'] ?: 0,
'related_account_id' => 0,
'category_id' => $defaults['default_expense_category_id'] ?: 0,
'amount' => '',
'merchant_name' => '',
'description' => '',
'is_installment' => 0,
'installment_months' => '',
'installment_interest_rate' => '',
'continue_after_save' => $defaults['continue_after_save'],
'keep_last_values' => $defaults['keep_last_values'],
'save_as_defaults' => 0,
];
if (!empty($defaults['keep_last_values']) && is_array($lastState)) {
$state = array_merge($state, $lastState);
$state['transaction_date'] = current_date_ymd();
$state['amount'] = '';
}
return $state;
}
/**
* 유형 변경 시 기본 카테고리 자동 선택
*/
function apply_default_category_by_type(array &$state, array $defaults): void
{
$type = $state['transaction_type'] ?? 'expense';
if ($type === 'income') {
$state['category_id'] = $defaults['default_income_category_id'] ?: 0;
return;
}
if ($type === 'expense') {
$state['category_id'] = $defaults['default_expense_category_id'] ?: 0;
return;
}
if ($type === 'transfer') {
$state['category_id'] = $defaults['default_transfer_category_id'] ?: 0;
return;
}
if ($type === 'card_payment') {
$state['category_id'] = $defaults['default_card_payment_category_id'] ?: 0;
return;
}
}
/**
* 카드 지출이면 카드 기본계좌 우선 적용
*/
function apply_default_card_account(array &$state, array $defaults): void
{
if (($state['transaction_type'] ?? '') !== 'expense') {
return;
}
if (!empty($defaults['default_card_account_id'])) {
$state['account_id'] = (int)$defaults['default_card_account_id'];
}
}
/**
* 저장 후 마지막 상태 저장
*/
function remember_transaction_form_state(array $state): void
{
$_SESSION['tx_create_last_form'] = [
'transaction_type' => $state['transaction_type'],
'account_id' => $state['account_id'],
'related_account_id' => $state['related_account_id'],
'category_id' => $state['category_id'],
'merchant_name' => $state['merchant_name'],
'description' => '',
'is_installment' => $state['is_installment'],
'installment_months' => $state['installment_months'],
'installment_interest_rate' => $state['installment_interest_rate'],
'continue_after_save' => $state['continue_after_save'],
'keep_last_values' => $state['keep_last_values'],
'transaction_date' => current_date_ymd(),
'amount' => '',
];
}
function get_remembered_transaction_form_state(): ?array
{
return $_SESSION['tx_create_last_form'] ?? null;
}
function clear_remembered_transaction_form_state(): void
{
unset($_SESSION['tx_create_last_form']);
}
/**
* 기본값 자동 저장용 데이터 만들기
*/
function make_default_payload_from_form(array $state): array
{
$payload = [
'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' => $state['keep_last_values'] ?? 1,
'continue_after_save' => $state['continue_after_save'] ?? 1,
];
$type = $state['transaction_type'] ?? 'expense';
if ($type === 'income') {
$payload['default_account_id'] = $state['account_id'];
$payload['default_income_category_id'] = $state['category_id'];
} elseif ($type === 'expense') {
$payload['default_account_id'] = $state['account_id'];
$payload['default_expense_category_id'] = $state['category_id'];
$payload['default_card_account_id'] = $state['account_id'];
} elseif ($type === 'transfer') {
$payload['default_account_id'] = $state['account_id'];
$payload['default_transfer_category_id'] = $state['category_id'];
} elseif ($type === 'card_payment') {
$payload['default_account_id'] = $state['account_id'];
$payload['default_card_payment_category_id'] = $state['category_id'];
}
return $payload;
}