65 Commits

Author SHA1 Message Date
ByungCheol 947c7a1f68 feat(account): 대출 계좌 loan_amount/loan_rate/loan_method/loan_months/loan_start 필드 추가
CI / build (push) Failing after 15m38s
- wallet 테이블: loan_amount(실행금액), loan_rate(연이자율%), loan_method(상환방식),
  loan_months(기간), loan_start(시작일) ALTER TABLE 추가
- Wallet 도메인/DTO/Mapper/Service 동기화
- WalletResponse.from()에 대출 필드 반영

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02 00:45:42 +09:00
ByungCheol 24e235404b feat: 월별 예산 + 전월/다음달 복사
CI / build (push) Failing after 15m52s
- budget 테이블에 year/month 추가, (member,category)→(member,category,year,month) 유니크 교체
  기존 상시 예산은 현재 월로 1회 이관
- 예산 조회/생성/현황/기간차트를 월별로(findByMember에 year/month)
- copyMonth: 다른 월 예산을 대상 월로 복사(같은 분류 덮어씀) + POST /budgets/copy
- 백업 복구 시 예산은 현재 월로 등록

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 22:35:32 +09:00
ByungCheol 10f51976d9 feat: 외화 결제 입력 — 통화+환율→원화 환산, 원본 보존 + 환율 API
CI / build (push) Failing after 14m19s
- account_entry에 currency/original_amount/exchange_rate 컬럼 추가(멱등 ALTER)
  amount는 환산 원화(표준값) 유지 → 통계·예산 무변경
- AccountEntry/Request/Response·매퍼·서비스에 외화 필드 전달
- FxService(open.er-api.com 무료·무인증, 통화별 일자 캐시) + FxController
  GET /api/fx/rate?from=USD&to=KRW → { from, to, rate }
- WebConfig: /api/fx/** 인증 보호
- (.gitignore: 로컬 시드 스크립트 제외 규칙)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 21:37:04 +09:00
ByungCheol b969ba6104 feat: 내 글/댓글 모아보기 API
CI / build (push) Successful in 59s
- GET /board/my/posts, /board/my/comments (페이징)
- PostSummary 에 category 추가, MyCommentResponse(글 제목·카테고리 포함)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 18:25:48 +09:00
ByungCheol ddcd6f4335 feat: 신고 블라인드 관리자 해제 + 해제 시 신고기록 초기화
CI / build (push) Failing after 14m33s
- POST /board/comments/{id}/unblock (관리자) — 댓글 블라인드 해제
- 글/댓글 블라인드 해제 시 신고 기록 삭제(재블라인드 방지)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 18:16:56 +09:00
ByungCheol ba75613e1c feat: 게시판 신고 — 누적 5건 시 블라인드(관리자만 열람)
CI / build (push) Failing after 11m17s
- report 테이블(회원당 대상별 1회), comment.blocked 컬럼
- POST /board/posts|comments/{id}/report, 본인 글/댓글 신고 불가
- 글: 5건이면 blocked(기존 열람제한 재사용) / 댓글: blocked → 비관리자 본문 숨김
- 삭제·탈퇴 시 신고 정리

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 18:05:10 +09:00
ByungCheol a47b8405f4 feat(billing): 구매 복원 + RTDN 수신 스캐폴드 + 만료 강등 정합성
CI / build (push) Failing after 12m15s
- 만료 강등 스케줄러: 해지(자동갱신 off) 건만 강등(자동갱신은 마켓/RTDN 관리)
- POST /api/billing/restore: 최근 결제 기준 멤버십 복원(기기변경·재설치)
- POST /api/billing/google/rtdn: Google Play 실시간 알림 수신 스캐폴드(비인증, 로깅)
- 실연동 지점(영수증 검증·RTDN 처리)은 TODO 로 표시

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 17:29:15 +09:00
ByungCheol 8142b8b518 feat: 회원 탈퇴(자기 계정 삭제) — Play 정책 대응
CI / build (push) Failing after 15m7s
- DELETE /api/auth/me: 본인 계정과 모든 데이터 영구 삭제
- 게시판(글/댓글/추천/이미지)·가계부 전체·포인트·결제기록·세션 → 회원 순 삭제
- WithdrawMapper(게시판/포인트/결제/세션) + BackupMapper(가계부) 재사용
- AuthServiceTest 생성자 보강

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 16:56:23 +09:00
ByungCheol be15f5b85d feat: 정기결제 관리 — 구독 현황/해지/재개/플랜변경 백엔드
CI / build (push) Failing after 12m10s
- member.plan_product, plan_auto_renew 컬럼(구독 상품·자동갱신)
- GET /api/billing/subscription: 플랜·만료일·다음결제일·자동갱신
- POST /api/billing/cancel: 자동갱신 중단(만료일까지 이용), /resume: 재개
- verify 시 상품·자동갱신 기록, 만료 강등·관리자 변경 시 구독정보 정리

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 16:04:20 +09:00
ByungCheol a4b6c3fd2d fix: 목록 태그 필터도 게시판별로 — /board/tags?category 로 매핑된 그룹 태그만
CI / build (push) Failing after 12m6s
- 게시판 목록 화면의 태그 필터가 전체 태그를 보여주던 문제(매핑 무시) 수정
- 글쓰기와 동일한 listWritableGroups 기준으로 일관 적용

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 15:44:24 +09:00
ByungCheol d5366e8e72 feat: 태그 그룹 게시판 매핑 엄격 모드 — 미체크 그룹은 어디에도 미노출
CI / build (push) Failing after 12m19s
- listWritableGroups: 명시적으로 매핑된 게시판에만 노출(boards.contains)
- 게시판 미지정 그룹은 글쓰기에서 숨김 (수정 화면은 기존 글 태그 유실 방지로 전체 표시 유지)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 15:24:12 +09:00
ByungCheol 1e93280140 feat: 인앱 결제(Google Play) 스캐폴드 + 멤버십 만료 처리
CI / build (push) Failing after 13m46s
- member.plan_expires_at + iap_purchase 테이블(중복 결제 방지)
- POST /api/billing/google/verify: 구매 검증 후 PREMIUM 부여/갱신(만료 연장), 세션 plan 즉시 동기화
- GET /api/billing/products: 구독 상품(월간/연간)
- 테스트 모드(billing.test-mode=true): test- 토큰 검증 없이 승인 → 전 과정 테스트 가능
- GooglePlayVerifier 인터페이스 + 스텁(실연동 지점), 실연동 시 구현체 교체
- 관리자 수동 plan 변경은 만료일 없이(영구), 결제는 만료일 부여
- 만료 자동 강등 스케줄러(매시), MemberResponse.planExpiresAt 노출

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 15:12:45 +09:00
ByungCheol d1c13e7cc1 feat: 포인트 적립내역 조회 — GET /auth/point-history
CI / build (push) Failing after 12m7s
- point_history 최신순 조회(최대 100건), PointHistoryResponse
- PointService.getHistory, 인터셉터 경로 등록

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 14:44:24 +09:00
ByungCheol 629ab1f811 feat: 기본 분류 초기 시드 — default_category 비어있으면 기본 세트 생성
- 기동 시 1회(ApplicationRunner), 데이터 없을 때만 생성(운영 데이터 미간섭)
- 지출 10대분류(+소분류)·수입 3대분류(+소분류) 기본 템플릿
- 관리자가 이후 수정/정렬/삭제 가능

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 14:44:23 +09:00
ByungCheol b94f162f7e refactor: 게시판별 태그 매핑 도입으로 불필요해진 board_setting 제거
CI / build (push) Failing after 11m32s
- BoardSettingMapper(+XML)/BoardSettingRequest/Response 삭제
- TagService board_setting 의존 제거, /admin/board-setting 엔드포인트 제거
- board_setting 테이블 DDL 제거
- 글 수정 시 전체 그룹 조회(기존 글 태그 유실 방지): listWritableGroups(blank)=전체

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 14:04:59 +09:00
ByungCheol caaad65ca2 feat: 태그 그룹을 게시판별로 매핑 — 게시판 성격에 맞는 태그만 노출
CI / build (push) Failing after 12m11s
- tag_category_board 매핑 테이블 추가(그룹 ↔ community/saving/tips)
- TagCategory 응답에 boards 추가, 생성/수정 시 매핑 저장(유효 게시판만)
- listWritableGroups(category): 해당 게시판에 매핑된 그룹만(매핑 없으면 전체=하위호환)
- GET /board/tag-groups?category=... 로 게시판별 필터

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 13:34:19 +09:00
ByungCheol b4344f5270 feat: 게시판 인기글/블라인드/자기글 추천차단 + 프로필 전역 동기화
CI / build (push) Failing after 15m11s
- GET /api/auth/profile: 아바타·포인트 포함 전체 프로필(재로그인 없이 최신화)
- 자기 글/댓글 추천·비추천 차단(400)
- 인기 글: 등록 1일 이내 + 추천 50건 이상이면 목록 상단 최대 3건 노출(hot)
- 인기 댓글: 동일 조건으로 댓글 목록 상단 정렬(hot)
- PostSummary 에 downCount 추가(비추천 20+ 블라인드 판정용)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 13:21:19 +09:00
ByungCheol ef9dace1df feat: 게시판 추천/비추천 + 작성자 아바타 + 추천자 + 활동 포인트
CI / build (push) Failing after 12m4s
- 작성자 아바타: post/comment 조회 시 member JOIN(google_picture/profile_image),
  목록·상세·댓글 응답에 노출
- 추천/비추천: post_vote/comment_vote 테이블 + 토글 API
  (POST /board/posts|comments/{id}/vote), 게시글/댓글 응답에 up/down/myVote
- 추천자 목록: GET /board/posts/{id}/recommenders + PostDetail.recommenders
- 포인트: member.points + point_history. 글/댓글 작성 시 10P, 하루 3회 한도(합산).
  PointService, GET /auth/points, MemberResponse.points 노출
- @MapperScan 에 point.mapper 추가, AuthController WebMvc 테스트 MockBean 보강

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 12:27:35 +09:00
ByungCheol 98f5f51112 feat: 프로필 사진 — 구글 아바타 동기화 + 사용자 지정 이미지
- member.google_picture(구글 아바타 URL), profile_image(사용자 지정 data URL) 컬럼 추가(멱등)
- 구글 로그인 시 picture 클레임 추출 → 신규 저장, 기존은 변경 시 동기화
- PUT /api/auth/profile-image: 사용자 지정 사진 설정/해제(빈값=해제→구글 폴백), data URL·용량 검증
- MemberResponse 에 googlePicture/profileImage 노출(표시 우선순위 프론트 처리)
- 관리자 목록(findAll)은 무거운 profile_image 제외해 가볍게 조회

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 11:39:35 +09:00
ByungCheol 6256d3e63d feat: 멤버십(무료/유료) 게이팅 — 백엔드
CI / build (push) Failing after 13m40s
- member.plan(FREE/PREMIUM) 컬럼 추가 + SessionUser/MemberResponse 노출
- auth_session 백업에 plan 저장(세션 복원 시 유료 상태 유지)
- 관리자 회원 plan 변경 API (PUT /api/admin/members/{id}/plan)
- PremiumInterceptor 로 유료 전용 경로 차단(통계/예산/고정지출/태그/OCR/투자/카드알림/백업)
  · 관리자는 플랜과 무관하게 허용, 무료 회원은 403 PREMIUM_REQUIRED
- WebConfigTest: 유료 경로 등록 회귀 가드 추가

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 11:02:19 +09:00
ByungCheol 93e06c9475 ci: main 푸시 시 CI 중복 실행 제거(Deploy만) — 배포 시간 단축
CI / build (push) Failing after 13m44s
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 09:22:44 +09:00
ByungCheol f130d53f62 fix: 복구 - 계좌를 이름 대신 원본 ID 기준 매핑 + 잘못된 이체 스킵
CI / build (push) Failing after 12m9s
- 같은 이름 계좌가 있어도 정확히 매핑(이름 충돌로 '출금=입금' 오류 해결)
- 이체인데 계좌 없거나 같으면 해당 항목만 건너뜀(전체 롤백 방지)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 09:03:11 +09:00
ByungCheol 3b46d2ba09 feat: 데이터 가져오기(복구) — 엑셀 백업으로 전체 교체 (트랜잭션)
CI / build (push) Failing after 12m39s
- POST /api/account/restore: 기존 데이터 전부 삭제 후 이름 기준 재생성
  (계좌→태그→분류(대/소)→내역→고정→예산→자주내역), 한 트랜잭션(실패 시 롤백)
- 빈 데이터 안전장치, 투자 종목/매매는 복구 대상 외(삭제됨)
- BackupMapper(deleteByMember), RestoreRequest DTO, BackupService/Controller

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 08:38:21 +09:00
ByungCheol bf6fb97ed8 feat: 게시글 수정 시에도 공지 체크박스 반영 (관리자)
CI / build (push) Failing after 11m18s
- BoardService.update: 관리자면 req.notice 로 공지 갱신
  (작성/수정 체크박스로 공지 on/off, 상세 토글 버튼 제거 대응)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 22:59:04 +09:00
ByungCheol 8d8d26ec3a feat: 게시판 공지 기능 (관리자) — 목록 최상단 고정
CI / build (push) Failing after 14m19s
- post.notice 컬럼 추가(멱등 ALTER)
- 목록 정렬 ORDER BY notice DESC, id DESC (공지 최상단)
- 작성 시 공지 설정(관리자만 반영) + /posts/{id}/notice·unnotice 토글
- Post/PostSummary/PostDetail/PostRequest 에 notice 반영

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 22:06:48 +09:00
ByungCheol b48d8c667c feat: 구글 로그인 — 같은 이메일이면 기존 계정에 자동 연결
CI / build (push) Failing after 14m59s
- member.google_id 컬럼 추가(멱등 ALTER) + 기존 GOOGLE 계정 sub 백필
- googleLogin: google_id 조회 → 없으면 검증된 동일 이메일 계정(LOCAL 우선)에
  연결 → 그래도 없으면 신규 생성. provider 는 유지(아이디 로그인/프로필 편집 보존)
- MemberMapper: findByGoogleId/findByEmailForLink/linkGoogle 추가, google_id 매핑

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 19:01:57 +09:00
ByungCheol 09efd65fa9 feat: 구글 로그인/가입 — ID 토큰 검증 후 세션 발급
CI / build (push) Failing after 14m2s
- AuthService.googleLogin: 구글 tokeninfo 로 ID 토큰 검증(aud==클라이언트 ID)
  후 provider=GOOGLE 회원 조회/자동가입 → 세션 발급(login 과 동일 경로)
- GoogleLoginRequest DTO, /api/auth/google·/google-client-id 엔드포인트
- application.yml: app.google-client-id=${GOOGLE_CLIENT_ID:}

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 18:02:19 +09:00
ByungCheol a1697a7a22 feat: 자주 쓰는 내역(빠른등록) + 문자/푸시 텍스트 파싱 API
CI / build (push) Failing after 15m21s
- quick_entry 테이블 + 도메인/매퍼/서비스/컨트롤러 (/account/quick-entries CRUD)
- /account/entries/parse: 문자·푸시 텍스트를 파서로 분석해 결과만 반환(저장X)
  → iPhone 등 알림 자동수집 불가 시 복사→붙여넣기 자동채움용

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 14:47:00 +09:00
ByungCheol 63b3ffea24 feat: 기본(디폴트) 분류 — 관리자 설정 + 사용자 불러오기
CI / build (push) Failing after 13m58s
- 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
ByungCheol 5f21cc4474 feat: 분류 대/소분류(2단계) — account_category.parent_id
CI / build (push) Failing after 11m45s
- parent_id 추가(CREATE + ALTER IF NOT EXISTS 멱등 마이그레이션)
- 도메인/DTO/매퍼에 parentId 노출, 2단계 검증(대분류 아래만 소분류)
- 자식 있는 대분류는 소분류화·삭제 차단(countChildren)
- 통계/예산/내역은 소분류 이름 기준 그대로(무변경)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 23:16:03 +09:00
ByungCheol 3fc233d697 feat: 순자산 추이 주간 집계 추가 (/networth/trend?unit=WEEK)
CI / build (push) Failing after 14m43s
- weeklyWalletFlow(월요일 기준 주별 순현금흐름) + netWorthTrendWeekly(기본 13주)
- 컨트롤러에 unit=WEEK&weeks=N 지원(기존 월별은 그대로)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 22:38:06 +09:00
ByungCheol 7de643022b feat: 고정지출 생성분을 '확인 필요(pending)'로 — 실제 처리 여부 확인
CI / build (push) Failing after 15m1s
- RecurringService.buildEntry: pending=true로 생성 → 가계부 '확인 필요' 목록에 노출,
  사용자가 실제 결제·이체 확인 후 확정(빈 body confirm은 분류/계좌 유지)
- 메모 없으면 제목으로 채워 확인 목록에서 식별 쉽게

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 17:13:14 +09:00
ByungCheol 6eef6cbd29 feat: 계좌 관리에 현금(CASH) 유형 추가
CI / build (push) Failing after 14m23s
- WalletRequest 유형 검증에 CASH 허용
- netWorth: CASH를 자산으로 합산(기존 else 분기에서 부채로 잡히던 것 방지)
- 추이(trend)는 부호있는 openingBalance+흐름이라 CASH 자동 반영(변경 불필요)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 15:43:29 +09:00
ByungCheol 553855b31c feat: 상환/납부에 연회비(카드) 추가 — 지출(분류 연회비)로 분리 저장
CI / build (push) Failing after 15m13s
- RepaymentRequest.annualFee 추가, repay()에서 연회비>0이면 EXPENSE(분류=연회비) 생성
- 연회비는 카드 대상에만 허용(대출 입력 시 400)
- 원금/이자/연회비 중 하나는 필수로 완화

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 22:52:23 +09:00
ByungCheol a0fc546ad8 feat: 자동인식 분류 학습 — 같은 메모 키워드는 과거 분류로 자동 채움
CI / build (push) Failing after 14m39s
- 알림 자동등록 시 memo(가맹점) 키워드로 과거에 '확정'한 내역의 분류를
  찾아(가장 많이 쓴 분류) pending 내역에 미리 채운다.
- 메모 포함관계 매칭('스타벅스' ↔ '스타벅스 강남점'), 같은 type(수입/지출)만.
- 안전상 '확인 필요' 상태는 유지(분류만 선반영) — 무검토 오확정 방지.
- AccountEntryMapper.findLearnedCategory 추가.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 22:22:54 +09:00
ByungCheol 120e042971 fix: 광고 푸시·문자 오등록 차단 강화 (죽은 코드 수정)
CI / build (push) Successful in 56s
- 기존 광고 차단(if !strong && AD_HINT)은 강신호가 보장된 지점이라
  항상 false → 한 번도 실행되지 않는 죽은 코드였음. 광고어가 섞여도
  승인/입금 등 신호가 있으면 그대로 등록되던 원인.
- 광고어를 2단계로 분리:
  - AD_BLOCK(이벤트·쿠폰·혜택·당첨 등): 거래신호가 있어도 무조건 제외
  - AD_WEAK(적립·포인트·할인 등): '결제'만 있고 명확한 거래신호가 없을 때 제외
    (실거래 영수증의 '포인트 적립'은 보존)
- '결제'는 광고 문구에도 흔해 약신호(weakApproval)로 강등
- 파서 단위테스트 +4 (광고+강신호 차단, 실거래 포인트 보존, 결제단독 광고/정상)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 22:15:54 +09:00
ByungCheol 31590343cf feat: 알림 분류 — 카드 승인/취소 + 은행 입금/출금·이체 구분
CI / build (push) Failing after 15m11s
- 파서: 입금→수입, 출금/이체→지출, 카드 승인→지출, 카드 취소/환불→수입(환불)
  은행 거래는 은행(BANK) 지갑에, 카드는 카드(CARD) 지갑에 매칭(matchWalletId 일반화)
- createFromNotification: 파싱된 수입/지출 타입·지갑종류로 생성
- 파서 테스트 갱신(은행 입금/출금 케이스 포함)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 22:47:32 +09:00
ByungCheol 55c47a43e6 fix: 업로드 이미지 URL 을 절대경로로 반환 — 앱(Capacitor)에서 이미지 표시
CI / build (push) Failing after 15m22s
- 앱은 출처가 localhost 라 /api/images/{id} 상대경로가 백엔드로 안 감 → 안 보임
- app.public-url(기본 https://app.sblog.kr) 기준 절대 URL 반환 → 웹/PC/APK 모두 로드

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 20:32:37 +09:00
ByungCheol f9abd0c989 feat: 게시글 인라인 이미지 서버 업로드(DB 저장) — base64 대체
CI / build (push) Failing after 15m30s
- board_image 테이블 + BoardImageController/Service/Mapper
  · POST /api/board/images(로그인) → {url:/api/images/{id}}
  · GET  /api/images/{id}(공개, img src 로 로드) — 1년 캐시
- 본문엔 짧은 URL 만 들어가 글이 비대해지지 않음

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 19:17:25 +09:00
ByungCheol 2da43b2f77 feat: 카드 알림 계좌 자동선택 - 카드사 표기 차이 유연 매칭
CI / build (push) Failing after 14m23s
- CardIssuerMatcher: 공백·접미사(카드/은행/페이/뱅크) 제거 + 별칭 통합(KB↔국민, 농협↔NH, 비씨↔BC, 씨티↔시티)
  · KB카드/국민카드/KB국민/국민 어떻게 등록해도 KB국민카드 알림에 자동 매칭
- AccountService.overlaps 가 CardIssuerMatcher 사용
- 단위테스트 4 추가

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 17:33:33 +09:00
ByungCheol eded44a476 feat: 투자 매매내역 수정 API (PUT /trades/{id})
CI / build (push) Failing after 15m14s
- InvestController/Service/Mapper: updateTrade 추가
- 수정 결과를 시점별로 시뮬레이션해 보유수량이 음수가 되면 거부(매도 과다 방지)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 16:42:33 +09:00
ByungCheol a9ff2387c8 feat: 무차별 대입 방지(로그인·비밀번호 게이트) + 미처리 예외 추적 강화
CI / build (push) Failing after 14m0s
- 로그인/비밀번호 재인증에 실패 기반 레이트리밋(Redis 슬라이딩 윈도우)
  · 로그인 IP당 10회/10분, 비밀번호 게이트 회원당 5회/10분, 초과 시 429
  · 성공 시 실패 카운터 초기화, Redis 장애 시 통과(가용성 우선)
  · 회원가입 레이트리밋도 공통 enforceRateLimit 으로 일원화
- GlobalExceptionHandler: 미처리 500 로그에 메서드+경로 기록(추적성), 잘못된 JSON은 400
- 테스트: 레이트리밋 429 케이스 2개 추가 (백엔드 총 34)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 15:03:53 +09:00
ByungCheol 4a85902183 test: 인증 컨트롤러 웹 계층 통합테스트 + 배포 게이트 DB 서비스
CI / build (push) Failing after 13m2s
- AuthControllerWebMvcTest(@WebMvcTest): 실제 인터셉터·경로매핑 로드해 검증
  · 보호 경로(verify-password/profile/me) 토큰 없으면 401(500 아님)
  · 유효 토큰이면 컨트롤러 도달(CURRENT_MEMBER 주입), 공개 경로(signup-enabled) 200
  · 단위테스트가 못 잡은 인터셉터 와이어링 누락(이번 500 버그)을 잡는 계층
  · @MapperScan 매퍼는 DB 없는 경량 SqlSessionFactory로 빈 생성만 통과
- deploy.yaml: clean build 가 @SpringBootTest(SbBtApplicationTests) 포함 →
  CI와 동일한 MariaDB/Redis 서비스+env 추가
  (없으면 배포 게이트가 DB 못 붙어 실패 → 직전 게이트 변경이 배포를 깨뜨렸던 문제 수정)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 14:49:48 +09:00
ByungCheol b748f7d48d ci: 배포 워크플로에 테스트 게이트 추가 — 실패 시 배포 중단
CI / build (push) Failing after 15m25s
- deploy.yaml 은 CI와 별개로 push:[main]에 트리거되며 테스트를 건너뛰고 있었음
  (백엔드 bootJar -x test, 프론트 테스트 스텝 없음) → 게이트 무력
- 배포 잡 안에서 테스트를 먼저 실행하도록 변경(Gitea는 워크플로 간 needs 불안정)
  · 백엔드: clean bootJar -x test → clean build (test 포함)
  · 프론트: Install → Test(npm test) → Build 순으로 분리

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 14:27:33 +09:00
ByungCheol e9a3fc82e5 fix: verify-password·profile 인터셉터 보호 경로 누락 수정
CI / build (push) Failing after 15m51s
- WebConfig authInterceptor 경로에 /api/auth/verify-password, /api/auth/profile 추가
  (누락 시 CURRENT_MEMBER 미설정 → 로그인 사용자도 NPE 500)
- WebConfigTest: 인증 필수 auth 엔드포인트 보호 경로 등록 회귀 가드

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 14:14:15 +09:00
ByungCheol e592c174bf feat: 가입정보 변경·비밀번호 재인증 API + 백엔드 단위테스트·CI 게이트
CI / build (push) Failing after 14m50s
- POST /auth/verify-password, PUT /auth/profile(세션 표시 이름 동기화)
- MemberMapper.updateProfile, AuthSessionMapper.updateName
- 단위테스트(24): CardNotificationParser(8), AuthService(16, Mockito)
- CI(.gitea): 테스트 리포트 아티팩트 업로드(clean build가 곧 테스트 게이트)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 14:08:01 +09:00
ByungCheol 5e2bdae37d feat: 세션 DB 이중 저장 — Redis 유실/재시작에도 로그인 유지
- auth_session 테이블에 세션 영속 백업(login 시 Redis+DB 동시 저장)
- getSession: Redis 미스/장애 시 DB에서 복원 후 Redis 재수화(슬라이딩)
- logout: Redis+DB 동시 삭제, 만료분 일별 정리(@Scheduled)
- Redis 재시작으로 세션 전멸하던 주기적 로그아웃 해결

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 08:12:57 +09:00
ByungCheol c05be0880c feat: 회원가입 제한·봇차단(허니팟/레이트리밋)·카드 자동인식 보정
- 관리자 회원가입 허용 토글(app_setting), 공개 GET /auth/signup-enabled
- 회원가입 봇차단: 허니팟(website) + IP 레이트리밋(Redis, 1h 5회)
- 카드 알림: 현금 오선택 보정(카드 양방향 매칭+단일카드 자동), 광고 푸시 차단(승인신호 없는 광고성 표현 무시)
- @MapperScan 에 admin.mapper 추가
- account.sql: 매 기동 wallet MODIFY 제거(라이브 락 위험) — CREATE 정의에 255 반영됨

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 00:15:57 +09:00
ByungCheol fb94df8112 feat: 시세 자동조회·퇴직연금 평가액·게시판 카테고리·태그 정렬·계좌번호 암호화
- 투자: 종목코드로 현재가 시세 자동조회(StockQuoteService, 투자탭/포트폴리오 진입 시 갱신)
- 투자: 퇴직연금 등 평가액 직접입력형 계좌(currentValue 활성화, manualValuation)
- 게시판: community/saving/tips 카테고리 분리(post.category + 목록 필터)
- 태그: 순서 변경(account_tag.sort_order, /tags/reorder)
- 보안: 계좌번호 AES-256-GCM 암호화 저장/복호화(EncryptedStringTypeHandler, account_number VARCHAR(255))
  키는 서버 .env ACCOUNT_CRYPTO_KEY 로 주입(미설정 시 평문 통과)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 05:00:18 +09:00
ByungCheol 8fec057752 feat: 카드 결제 알림 자동인식(미확인 내역) 백엔드
CI / build (push) Failing after 14m48s
- account_entry pending/notif_key 컬럼 추가(멱등 마이그레이션)
- CardNotificationParser: 카드사·금액·가맹점·승인/취소 파싱
- POST /entries/notification(미확인 지출 생성, 중복방지, 카드 자동매칭)
- POST /entries/{id}/confirm(확정), GET /entries/pending/count

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 18:51:30 +09:00