- CardIssuerMatcher: 공백·접미사(카드/은행/페이/뱅크) 제거 + 별칭 통합(KB↔국민, 농협↔NH, 비씨↔BC, 씨티↔시티) · KB카드/국민카드/KB국민/국민 어떻게 등록해도 KB국민카드 알림에 자동 매칭 - AccountService.overlaps 가 CardIssuerMatcher 사용 - 단위테스트 4 추가 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -277,10 +277,9 @@ public class AccountService {
|
|||||||
return cards.size() == 1 ? cards.get(0).getId() : null;
|
return cards.size() == 1 ? cards.get(0).getId() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 양방향 부분일치 (KB국민 ↔ 국민 등) */
|
/** 표기 차이를 흡수한 카드사 매칭 (KB국민 ↔ 국민 ↔ 국민카드 ↔ KB카드 등) */
|
||||||
private boolean overlaps(String walletField, String issuer) {
|
private boolean overlaps(String walletField, String issuer) {
|
||||||
if (walletField == null || issuer == null) return false;
|
return CardIssuerMatcher.matches(walletField, issuer);
|
||||||
return walletField.contains(issuer) || issuer.contains(walletField);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ===================== 상환/납부 ===================== */
|
/* ===================== 상환/납부 ===================== */
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package com.sb.web.account.service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 카드사명 유연 매칭.
|
||||||
|
* 알림에서 감지한 카드사와 사용자가 등록한 카드의 「카드사/이름」을, 표기 차이
|
||||||
|
* (KB / 국민 / 국민카드 / KB카드, 농협 / NH, 비씨 / BC 등)에 관계없이 같은 카드사로 인식한다.
|
||||||
|
*/
|
||||||
|
public final class CardIssuerMatcher {
|
||||||
|
|
||||||
|
private CardIssuerMatcher() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 두 표기가 같은 카드사를 가리키면 true */
|
||||||
|
public static boolean matches(String walletField, String issuer) {
|
||||||
|
String a = canon(walletField);
|
||||||
|
String b = canon(issuer);
|
||||||
|
if (a.isEmpty() || b.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return a.equals(b) || a.contains(b) || b.contains(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 공백·접미사(카드/은행/페이/뱅크) 제거 + 동일 카드사 별칭 통합 후 소문자 키 */
|
||||||
|
static String canon(String s) {
|
||||||
|
if (s == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
String x = s.replaceAll("\\s+", "").toLowerCase()
|
||||||
|
.replace("카드", "").replace("은행", "").replace("페이", "").replace("뱅크", "");
|
||||||
|
if (x.contains("kb") || x.contains("국민")) {
|
||||||
|
return "국민";
|
||||||
|
}
|
||||||
|
if (x.contains("nh") || x.contains("농협")) {
|
||||||
|
return "농협";
|
||||||
|
}
|
||||||
|
if (x.equals("bc") || x.contains("비씨")) {
|
||||||
|
return "비씨";
|
||||||
|
}
|
||||||
|
if (x.contains("씨티") || x.contains("시티") || x.contains("citi")) {
|
||||||
|
return "씨티";
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package com.sb.web.account.service;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 카드사명 유연 매칭 단위테스트.
|
||||||
|
* 사용자가 카드를 어떻게 등록했든(KB카드/국민카드/KB국민/국민) 같은 카드사로 인식되어야 한다.
|
||||||
|
*/
|
||||||
|
class CardIssuerMatcherTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("KB국민카드: 다양한 표기 모두 매칭")
|
||||||
|
void kbVariants() {
|
||||||
|
// 알림에서 감지하는 카드사 = "KB국민"
|
||||||
|
assertThat(CardIssuerMatcher.matches("KB카드", "KB국민")).isTrue();
|
||||||
|
assertThat(CardIssuerMatcher.matches("국민카드", "KB국민")).isTrue();
|
||||||
|
assertThat(CardIssuerMatcher.matches("KB국민", "KB국민")).isTrue();
|
||||||
|
assertThat(CardIssuerMatcher.matches("국민", "KB국민")).isTrue();
|
||||||
|
assertThat(CardIssuerMatcher.matches("KB국민카드", "KB국민")).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("일반 카드사: 접미사 차이 흡수")
|
||||||
|
void commonIssuers() {
|
||||||
|
assertThat(CardIssuerMatcher.matches("삼성카드", "삼성")).isTrue();
|
||||||
|
assertThat(CardIssuerMatcher.matches("현대", "현대")).isTrue();
|
||||||
|
assertThat(CardIssuerMatcher.matches("신한카드", "신한")).isTrue();
|
||||||
|
assertThat(CardIssuerMatcher.matches("롯데 카드", "롯데")).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("별칭 통합: 농협/NH, 비씨/BC")
|
||||||
|
void aliases() {
|
||||||
|
assertThat(CardIssuerMatcher.matches("NH농협", "농협")).isTrue();
|
||||||
|
assertThat(CardIssuerMatcher.matches("농협카드", "NH")).isTrue();
|
||||||
|
assertThat(CardIssuerMatcher.matches("BC카드", "비씨")).isTrue();
|
||||||
|
assertThat(CardIssuerMatcher.matches("비씨", "BC")).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("다른 카드사/빈값은 매칭되지 않음")
|
||||||
|
void noMatch() {
|
||||||
|
assertThat(CardIssuerMatcher.matches("삼성카드", "현대")).isFalse();
|
||||||
|
assertThat(CardIssuerMatcher.matches("국민카드", "삼성")).isFalse();
|
||||||
|
assertThat(CardIssuerMatcher.matches("", "KB국민")).isFalse();
|
||||||
|
assertThat(CardIssuerMatcher.matches(null, "국민")).isFalse();
|
||||||
|
assertThat(CardIssuerMatcher.matches("삼성", null)).isFalse();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user