feat: 기본 분류 초기 시드 — default_category 비어있으면 기본 세트 생성
- 기동 시 1회(ApplicationRunner), 데이터 없을 때만 생성(운영 데이터 미간섭) - 지출 10대분류(+소분류)·수입 3대분류(+소분류) 기본 템플릿 - 관리자가 이후 수정/정렬/삭제 가능 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,75 @@
|
|||||||
|
package com.sb.web.account.service;
|
||||||
|
|
||||||
|
import com.sb.web.account.domain.DefaultCategory;
|
||||||
|
import com.sb.web.account.mapper.DefaultCategoryMapper;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.boot.ApplicationArguments;
|
||||||
|
import org.springframework.boot.ApplicationRunner;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 기본(디폴트) 분류 초기 시드. default_category 가 비어 있을 때만 한 번 생성한다.
|
||||||
|
* (관리자가 이후 자유롭게 수정/삭제 가능 — 비어 있을 때만 채우므로 운영 데이터를 덮어쓰지 않음)
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class DefaultCategorySeeder implements ApplicationRunner {
|
||||||
|
|
||||||
|
private final DefaultCategoryMapper mapper;
|
||||||
|
|
||||||
|
// 대분류 → 소분류 목록 (입력 순서 유지)
|
||||||
|
private static final Map<String, List<String>> EXPENSE = new LinkedHashMap<>();
|
||||||
|
private static final Map<String, List<String>> INCOME = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
EXPENSE.put("식비", List.of("외식", "식료품", "카페/간식", "배달"));
|
||||||
|
EXPENSE.put("교통", List.of("대중교통", "택시", "주유", "주차/통행료"));
|
||||||
|
EXPENSE.put("주거/통신", List.of("월세/관리비", "공과금", "통신비", "인터넷"));
|
||||||
|
EXPENSE.put("생활", List.of("생필품", "의류/미용", "가구/가전"));
|
||||||
|
EXPENSE.put("건강/의료", List.of("병원", "약국", "운동"));
|
||||||
|
EXPENSE.put("문화/여가", List.of("영화/공연", "여행", "취미", "구독서비스"));
|
||||||
|
EXPENSE.put("교육", List.of("학원", "도서", "강의"));
|
||||||
|
EXPENSE.put("경조사", List.of("축의금", "부의금", "선물"));
|
||||||
|
EXPENSE.put("금융", List.of("보험", "대출이자", "수수료"));
|
||||||
|
EXPENSE.put("기타", List.of());
|
||||||
|
|
||||||
|
INCOME.put("급여", List.of("월급", "상여금"));
|
||||||
|
INCOME.put("부수입", List.of("용돈", "이자/배당", "환급"));
|
||||||
|
INCOME.put("기타수입", List.of("중고판매", "기타"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public void run(ApplicationArguments args) {
|
||||||
|
if (!mapper.findAll().isEmpty()) {
|
||||||
|
return; // 이미 데이터가 있으면 시드하지 않음
|
||||||
|
}
|
||||||
|
int n = seed("EXPENSE", EXPENSE) + seed("INCOME", INCOME);
|
||||||
|
log.info("[default-category] 기본 분류 시드 생성: {}건", n);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int seed(String type, Map<String, List<String>> tree) {
|
||||||
|
int count = 0;
|
||||||
|
int majorOrder = 0;
|
||||||
|
for (Map.Entry<String, List<String>> e : tree.entrySet()) {
|
||||||
|
DefaultCategory major = DefaultCategory.builder()
|
||||||
|
.type(type).name(e.getKey()).parentId(null).sortOrder(majorOrder++).build();
|
||||||
|
mapper.insert(major); // 생성키(id) 채워짐
|
||||||
|
count++;
|
||||||
|
int subOrder = 0;
|
||||||
|
for (String child : e.getValue()) {
|
||||||
|
mapper.insert(DefaultCategory.builder()
|
||||||
|
.type(type).name(child).parentId(major.getId()).sortOrder(subOrder++).build());
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user