feat: 자주 쓰는 내역(빠른등록) + 문자/푸시 텍스트 파싱 API

- quick_entry 테이블 + 도메인/매퍼/서비스/컨트롤러 (/account/quick-entries CRUD)
- /account/entries/parse: 문자·푸시 텍스트를 파서로 분석해 결과만 반환(저장X)
  → iPhone 등 알림 자동수집 불가 시 복사→붙여넣기 자동채움용

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
ByungCheol
2026-06-27 14:47:00 +09:00
co-authored by Claude Opus 4.8
parent 63b3ffea24
commit a1697a7a22
11 changed files with 327 additions and 0 deletions
@@ -0,0 +1,56 @@
package com.sb.web.account.service;
import com.sb.web.account.domain.QuickEntry;
import com.sb.web.account.dto.QuickEntryRequest;
import com.sb.web.account.dto.QuickEntryResponse;
import com.sb.web.account.mapper.QuickEntryMapper;
import com.sb.web.common.exception.ApiException;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* 자주 쓰는 내역(빠른 등록 템플릿) 서비스 — 사용자별.
*/
@Service
@RequiredArgsConstructor
public class QuickEntryService {
private final QuickEntryMapper mapper;
public List<QuickEntryResponse> list(Long memberId) {
return mapper.findByMember(memberId).stream().map(QuickEntryResponse::from).toList();
}
@Transactional
public QuickEntryResponse create(QuickEntryRequest req, Long memberId) {
Integer max = mapper.maxSortOrder(memberId);
QuickEntry e = QuickEntry.builder()
.memberId(memberId)
.label(blankToNull(req.getLabel()))
.type(req.getType())
.category("EXPENSE".equals(req.getType()) || "INCOME".equals(req.getType()) ? blankToNull(req.getCategory()) : null)
.amount(req.getAmount())
.memo(blankToNull(req.getMemo()))
.walletId(req.getWalletId())
.sortOrder(max == null ? 0 : max + 1)
.build();
mapper.insert(e);
return QuickEntryResponse.from(mapper.findByIdAndMember(e.getId(), memberId));
}
@Transactional
public void delete(Long id, Long memberId) {
if (mapper.findByIdAndMember(id, memberId) == null) {
throw new ApiException(HttpStatus.NOT_FOUND, "자주 쓰는 내역을 찾을 수 없습니다.");
}
mapper.delete(id, memberId);
}
private String blankToNull(String s) {
return (s == null || s.isBlank()) ? null : s.trim();
}
}