Files
sb-backend/src/main/resources/db/account.sql
T
ByungCheol 63b3ffea24
CI / build (push) Failing after 13m58s
feat: 기본(디폴트) 분류 — 관리자 설정 + 사용자 불러오기
- default_category 테이블(전체 공용) + 도메인/매퍼/서비스
- 관리자 API /api/admin/default-categories (CRUD·reorder, ADMIN 보호)
- 사용자 /account/categories/import: 기존 내역 기반 → 기본분류 복사로 변경
  (대/소분류 계층 유지, 같은 이름은 건너뜀; CategoryMapper.findByMemberTypeName 추가)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 23:03:38 +09:00

198 lines
12 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- ============================================================
-- 가계부 스키마 (MariaDB) — account_entry
-- 본인(member)이 등록한 내역만 조회 가능 (소유자 격리)
-- 실행: 애플리케이션 기동 시 연결된 DB(sbdb)에 자동 생성 (IF NOT EXISTS)
-- ============================================================
-- 계좌/카드/대출 (사용자별) — BANK(은행) / CARD(카드) / LOAN(대출)
-- 잔액 부호: 자산(+) / 부채(카드·대출, ). opening_balance 는 기준일의 부호있는 시작 잔액.
CREATE TABLE IF NOT EXISTS wallet (
id BIGINT NOT NULL AUTO_INCREMENT,
member_id BIGINT NOT NULL COMMENT '소유자 member.id',
type VARCHAR(10) NOT NULL COMMENT 'BANK / CARD / LOAN / INVEST',
name VARCHAR(50) NOT NULL COMMENT '별칭',
issuer VARCHAR(50) NULL COMMENT '은행명/카드사/대출기관/증권사',
account_number VARCHAR(255) NULL COMMENT '계좌번호(BANK) — AES-GCM 암호화 저장',
card_type VARCHAR(10) NULL COMMENT 'CREDIT / CHECK (CARD)',
opening_balance BIGINT NOT NULL DEFAULT 0 COMMENT '초기 잔액(부호있음: 자산+, 부채-)',
opening_date DATE NULL COMMENT '초기잔액 기준일',
current_value BIGINT NULL COMMENT '현재 평가금액(INVEST, 수동 갱신)',
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY idx_wallet_member (member_id, type)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- 기존 wallet 컬럼 추가 (멱등)
ALTER TABLE wallet ADD COLUMN IF NOT EXISTS opening_balance BIGINT NOT NULL DEFAULT 0;
ALTER TABLE wallet ADD COLUMN IF NOT EXISTS opening_date DATE NULL;
ALTER TABLE wallet ADD COLUMN IF NOT EXISTS current_value BIGINT NULL;
ALTER TABLE wallet ADD COLUMN IF NOT EXISTS sort_order INT NOT NULL DEFAULT 0;
-- 계좌번호 암호화 저장(AES-GCM)으로 평문보다 길어 VARCHAR(255) 필요 — 운영 적용 완료(CREATE TABLE 정의에 반영).
-- 매 기동 MODIFY 는 라이브 테이블 락 위험이 있어 제거. 기존 환경 확장이 필요하면 1회 수동 적용:
-- ALTER TABLE wallet MODIFY account_number VARCHAR(255) NULL;
CREATE TABLE IF NOT EXISTS account_entry (
id BIGINT NOT NULL AUTO_INCREMENT,
member_id BIGINT NOT NULL COMMENT '소유자 member.id',
entry_date DATE NOT NULL COMMENT '거래일',
type VARCHAR(10) NOT NULL COMMENT 'INCOME / EXPENSE / TRANSFER',
category VARCHAR(50) NULL COMMENT '분류(식비, 급여 등)',
amount BIGINT NOT NULL COMMENT '금액(원, 양수)',
memo VARCHAR(255) NULL,
wallet_id BIGINT NULL COMMENT '발생/출금 계좌(wallet.id)',
to_wallet_id BIGINT NULL COMMENT '이체 입금 계좌(TRANSFER)',
installment_months INT NULL COMMENT '카드 할부 개월수(2~24, 일시불은 NULL)',
pending TINYINT(1) NOT NULL DEFAULT 0 COMMENT '확인 필요(미확정) 여부',
notif_key VARCHAR(160) NULL COMMENT '알림 자동인식 중복방지 키',
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY idx_account_member_date (member_id, entry_date)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- 기존 account_entry 컬럼 추가 (멱등)
ALTER TABLE account_entry ADD COLUMN IF NOT EXISTS wallet_id BIGINT NULL;
ALTER TABLE account_entry ADD COLUMN IF NOT EXISTS to_wallet_id BIGINT NULL;
ALTER TABLE account_entry ADD COLUMN IF NOT EXISTS installment_months INT NULL;
-- 카드 결제 알림 자동인식: 미확인(확인 필요) 플래그 + 중복방지 키
ALTER TABLE account_entry ADD COLUMN IF NOT EXISTS pending TINYINT(1) NOT NULL DEFAULT 0 COMMENT '확인 필요(미확정) 여부';
ALTER TABLE account_entry ADD COLUMN IF NOT EXISTS notif_key VARCHAR(160) NULL COMMENT '알림 자동인식 중복방지 키';
ALTER TABLE account_entry ADD INDEX IF NOT EXISTS idx_entry_notif (member_id, notif_key);
-- 가계부 태그 (사용자별 관리 — 게시판 태그와 분리)
CREATE TABLE IF NOT EXISTS account_tag (
id BIGINT NOT NULL AUTO_INCREMENT,
member_id BIGINT NOT NULL COMMENT '소유자 member.id',
name VARCHAR(50) NOT NULL,
sort_order INT NOT NULL DEFAULT 0 COMMENT '표시 순서',
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY uk_account_tag_member_name (member_id, name),
KEY idx_account_tag_member (member_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
ALTER TABLE account_tag ADD COLUMN IF NOT EXISTS sort_order INT NOT NULL DEFAULT 0;
-- 정기/반복 거래 규칙 (사용자별)
CREATE TABLE IF NOT EXISTS recurring (
id BIGINT NOT NULL AUTO_INCREMENT,
member_id BIGINT NOT NULL COMMENT '소유자 member.id',
title VARCHAR(100) NOT NULL COMMENT '이름(월세, 급여 등)',
type VARCHAR(10) NOT NULL COMMENT 'INCOME/EXPENSE/TRANSFER',
amount BIGINT NOT NULL,
category VARCHAR(50) NULL,
memo VARCHAR(255) NULL,
wallet_id BIGINT NULL COMMENT '발생/출금 계좌',
to_wallet_id BIGINT NULL COMMENT '이체 입금 계좌',
frequency VARCHAR(10) NOT NULL COMMENT 'DAILY/WEEKLY/MONTHLY/YEARLY',
day_of_month INT NULL COMMENT 'MONTHLY/YEARLY (1~31)',
day_of_week INT NULL COMMENT 'WEEKLY (1=월~7=일)',
month_of_year INT NULL COMMENT 'YEARLY (1~12)',
start_date DATE NOT NULL,
end_date DATE NULL,
last_run_date DATE NULL COMMENT '마지막 생성된 거래일',
active TINYINT(1) NOT NULL DEFAULT 1,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY idx_recurring_member (member_id, active)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- 분류(카테고리) — 사용자별, 수입/지출 타입
CREATE TABLE IF NOT EXISTS account_category (
id BIGINT NOT NULL AUTO_INCREMENT,
member_id BIGINT NOT NULL COMMENT '소유자 member.id',
type VARCHAR(10) NOT NULL COMMENT 'INCOME / EXPENSE',
name VARCHAR(50) NOT NULL,
parent_id BIGINT NULL COMMENT '대분류 id(account_category.id). NULL=대분류, 값=소분류',
sort_order INT NOT NULL DEFAULT 0,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY uk_category_member_type_name (member_id, type, name)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- 대/소분류 계층 추가(기존 DB 마이그레이션) — 소분류 이름은 그대로, parent_id 만 부여
ALTER TABLE account_category ADD COLUMN IF NOT EXISTS parent_id BIGINT NULL COMMENT '대분류 id. NULL=대분류, 값=소분류';
-- 기본(디폴트) 분류 — 전체 사용자 공용 템플릿(관리자 관리). 사용자가 '기본 분류 불러오기'로 자기 분류에 복사.
CREATE TABLE IF NOT EXISTS default_category (
id BIGINT NOT NULL AUTO_INCREMENT,
type VARCHAR(10) NOT NULL COMMENT 'INCOME / EXPENSE',
name VARCHAR(50) NOT NULL,
parent_id BIGINT NULL COMMENT '대분류 id(default_category.id). NULL=대분류, 값=소분류',
sort_order INT NOT NULL DEFAULT 0,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY uk_default_category_type_name (type, name)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- 예산 (사용자별, 카테고리별)
-- fixed=1(고정): base_unit/base_amount 로 일수기준 환산 / fixed=0(비고정): daily/weekly/monthly/yearly 직접
CREATE TABLE IF NOT EXISTS budget (
id BIGINT NOT NULL AUTO_INCREMENT,
member_id BIGINT NOT NULL COMMENT '소유자 member.id',
category VARCHAR(50) NOT NULL COMMENT '지출 분류',
fixed TINYINT(1) NOT NULL DEFAULT 0,
base_unit VARCHAR(10) NULL COMMENT 'DAY/WEEK/MONTH (고정)',
base_amount BIGINT NULL COMMENT '고정 기준 금액',
daily BIGINT NULL,
weekly BIGINT NULL,
monthly BIGINT NULL,
yearly BIGINT NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY uk_budget_member_category (member_id, category)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- 가계부 항목 - 태그 (다대다, tag_id 는 account_tag.id 참조)
CREATE TABLE IF NOT EXISTS account_entry_tag (
entry_id BIGINT NOT NULL,
tag_id BIGINT NOT NULL,
PRIMARY KEY (entry_id, tag_id),
KEY idx_aet_tag (tag_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- 사용자별 월 예상 수입 (월별 저장)
CREATE TABLE IF NOT EXISTS budget_income (
member_id BIGINT NOT NULL COMMENT '소유자 member.id',
`year` INT NOT NULL,
`month` INT NOT NULL,
expected_income BIGINT NULL COMMENT '월 예상 수입',
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (member_id, `year`, `month`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- 투자 보유 종목 (INVEST 지갑별 · 사용자별)
CREATE TABLE IF NOT EXISTS invest_holding (
id BIGINT NOT NULL AUTO_INCREMENT,
member_id BIGINT NOT NULL COMMENT '소유자 member.id',
wallet_id BIGINT NOT NULL COMMENT '투자(INVEST) 지갑 wallet.id',
name VARCHAR(100) NOT NULL COMMENT '종목명',
ticker VARCHAR(20) NULL COMMENT '종목코드(선택)',
current_price BIGINT NULL COMMENT '현재가(원, 수동 갱신)',
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY idx_holding_member_wallet (member_id, wallet_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- 투자 매매 이력 (종목별 매수/매도)
CREATE TABLE IF NOT EXISTS invest_trade (
id BIGINT NOT NULL AUTO_INCREMENT,
member_id BIGINT NOT NULL COMMENT '소유자 member.id',
holding_id BIGINT NOT NULL COMMENT 'invest_holding.id',
trade_type VARCHAR(10) NOT NULL COMMENT 'BUY / SELL',
trade_date DATE NOT NULL,
quantity DECIMAL(18,6) NOT NULL COMMENT '수량(주, 소수점 매매 지원)',
price BIGINT NOT NULL COMMENT '단가(원)',
fee BIGINT NOT NULL DEFAULT 0 COMMENT '수수료/세금(원)',
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY idx_trade_member_holding (member_id, holding_id),
KEY idx_trade_date (holding_id, trade_date, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- 소수점 매매(예: 해외주식 소수점 매수) 지원: 기존 BIGINT → DECIMAL
ALTER TABLE invest_trade MODIFY COLUMN quantity DECIMAL(18,6) NOT NULL COMMENT '수량(주, 소수점 매매 지원)';