Skip to content

[UPLUS-150] 청구서 데이터 예약 알림 메시지 형식 수정#15

Merged
starboxxxx merged 1 commit into
developfrom
fix/UPLUS-150
Jan 26, 2026
Merged

[UPLUS-150] 청구서 데이터 예약 알림 메시지 형식 수정#15
starboxxxx merged 1 commit into
developfrom
fix/UPLUS-150

Conversation

@starboxxxx
Copy link
Copy Markdown
Contributor

🎫 지라 티켓

UPLUS-150


✅ 작업 사항

청구서 데이터 예약 알림 메시지 형식 수정


📋 체크리스트

  • 코드가 정상적으로 빌드됩니다.
  • 관련 테스트 코드를 작성했습니다.
  • 기존 테스트가 모두 통과합니다.
  • 코드 스타일(Spotless, Checkstyle)을 준수합니다.

⌨ 기타

@starboxxxx starboxxxx requested a review from swthewhite January 26, 2026 08:23
@starboxxxx starboxxxx self-assigned this Jan 26, 2026
@starboxxxx starboxxxx added the fix 버그 수정 label Jan 26, 2026
@github-actions github-actions Bot requested a review from k0081915 January 26, 2026 08:23
@github-actions github-actions Bot added the size/M PR size: M label Jan 26, 2026
@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello @starboxxxx, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

이 Pull Request는 청구서 알림 데이터 구조와 처리 로직을 리팩토링합니다. InvoiceAggregateRecord는 알림 목적을 위해 청구서 세부 정보를 보다 세분화되고 구조화된 형태로 제공하는 새로운 InvoiceNotificationEvent 모델로 대체되었습니다. 변경 사항에는 이 새로운 데이터 모델을 수용하고 개정된 형식으로 청구서 알림이 생성 및 전송되도록 배치 처리 구성 요소(프로세서 및 라이터)를 업데이트하는 것이 포함됩니다.

Highlights

  • 모델 재구성: 기존 InvoiceAggregateRecord가 제거되고 InvoiceNotificationEvent라는 새로운 데이터 모델로 대체되었습니다. 이 새로운 모델은 SubscriptionInfoVariables와 같은 중첩 레코드를 포함하여 알림 데이터에 대한 더 구조화된 형식을 제공합니다.
  • 프로세서 로직 업데이트: InvoiceSendProcessor는 이제 InvoiceSendRecordInvoiceNotificationEvent로 처리합니다. 기존의 집계 로직(buildAggregate)은 buildEvent로 대체되었으며, 이는 새로운 InvoiceNotificationEvent를 상세한 인보이스 정보와 아이템 매핑을 포함하여 구성합니다.
  • 라이터 적응: InvoiceSendWriterInvoiceAggregateRecord 대신 InvoiceNotificationEvent를 처리하도록 업데이트되었습니다. 이제 Kafka 메시지 전송 시 키로 invId 대신 eventId (UUID)를 사용합니다.
  • 알림 전송 프로세서 업데이트: NotificationSendProcessor에서 templateGroupId101L에서 2L로 변경되었습니다. 이는 알림 템플릿과 관련된 사소한 구성 변경으로 보입니다.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

이번 PR은 청구서 데이터 기반의 알림 메시지 형식을 기존 InvoiceAggregateRecord에서 새로운 InvoiceNotificationEvent로 리팩토링하는 작업을 포함하고 있습니다. 전반적으로 메시지 구조가 더 명확해지고 Kafka 이벤트로 사용하기에 적합해진 점이 좋습니다.
다만, 코드 내에 하드코딩된 값(매직 넘버, 매직 스트링)들이 여러 곳에서 발견되었습니다. 이들을 상수나 enum으로 추출하여 코드의 가독성과 유지보수성을 높이는 방향으로 개선하는 것을 제안합니다. 또한, 일부 Java 네이밍 컨벤션에 맞지 않는 부분에 대한 개선 의견도 포함했습니다. 자세한 내용은 각 파일의 리뷰 코멘트를 참고해 주세요.

Comment on lines +106 to 114
private String mapItemName(String type) {
return switch (type) {
case "PLAN" -> "기본 요금";
case "VAS" -> "부가서비스";
case "DISCOUNT" -> "할인";
case "MICRO" -> "소액 결제";
default -> "기타";
};
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

mapItemName 메소드와 buildEvent 메소드 내에서 "PLAN", "VAS" 등 invoiceType을 나타내는 문자열이 하드코딩되어 사용되고 있습니다. (e.g., L72, L108-L111)

이러한 방식은 오타에 취약하며, 새로운 타입이 추가될 때 여러 곳을 수정해야 하는 불편함이 있습니다.

InvoiceItemType과 같은 enum을 정의하여 타입 안정성을 높이고 유지보수성을 개선하는 것을 강력히 권장합니다. enum을 사용하면 관련 로직을 한 곳에서 관리할 수 있습니다.

개선 예시:

public enum InvoiceItemType {
    PLAN("기본 요금"),
    VAS("부가서비스"),
    DISCOUNT("할인"),
    MICRO("소액 결제"),
    ETC("기타");

    private final String koreanName;

    InvoiceItemType(String koreanName) {
        this.koreanName = koreanName;
    }

    public String getKoreanName() {
        return koreanName;
    }

    public static InvoiceItemType fromString(String text) {
        if (text != null) {
            for (InvoiceItemType b : InvoiceItemType.values()) {
                if (text.equalsIgnoreCase(b.name())) {
                    return b;
                }
            }
        }
        return ETC;
    }
}

// InvoiceSendProcessor.java

private InvoiceNotificationEvent buildEvent() {
    String planName = currentItems.stream()
            .filter(i -> InvoiceItemType.PLAN.name().equals(i.invoiceType())) // enum 사용
            .map(InvoiceItemRecord::invoiceName)
            .findFirst()
            .orElse(null);
    // ...
}

private String mapItemName(String type) {
    return InvoiceItemType.fromString(type).getKoreanName();
}

UUID.randomUUID(),
item.id(),
101L,
2L,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

templateGroupId로 사용되는 2L은 의미를 알기 어려운 매직 넘버입니다. 코드의 가독성과 유지보수성을 높이기 위해, 이 값의 의미를 명확히 나타내는 상수로 정의하는 것을 고려해 보세요. 예를 들어, NotificationTemplateConstants와 같은 별도의 상수 관리 클래스에 USAGE_NOTIFICATION_TEMPLATE_GROUP_ID와 같이 정의하여 사용할 수 있습니다.


return new InvoiceNotificationEvent(
UUID.randomUUID(),
1L, // templateGroupId 고정
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

templateGroupId로 사용되는 1L은 매직 넘버입니다. 이 값의 의미를 명확히 나타내는 상수로 정의하여 가독성과 유지보수성을 향상시키는 것이 좋습니다. 예를 들어, INVOICE_NOTIFICATION_TEMPLATE_GROUP_ID와 같은 이름의 상수를 사용할 수 있습니다. NotificationSendProcessor에서 발견된 매직 넘버와 함께 NotificationTemplateConstants와 같은 클래스에서 상수를 중앙 관리하면 더욱 체계적인 코드가 될 것입니다.

1L, // templateGroupId 고정
new InvoiceNotificationEvent.SubscriptionInfo(
currentInvoice.subId(),
currentInvoice.phone_enc(),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

사용하시는 currentInvoice 객체의 phone_enc()email_enc() 메소드 호출은 InvoiceSendRecord의 필드명이 Java 네이밍 컨벤션(camelCase)을 따르지 않고 있음을 보여줍니다. 코드의 일관성과 가독성을 위해 InvoiceSendRecordphone_enc, email_enc 필드를 phoneEnc, emailEnc와 같이 camelCase로 리팩토링하는 것을 고려해 보세요. 이 변경은 InvoiceSendRecord를 생성하는 부분(예: DB 쿼리)에도 영향을 줄 수 있으므로 관련 코드도 함께 수정해야 합니다.

currentInvoice.createdAt().format(DATE_FORMAT),
currentInvoice.dueDate().format(DATE_FORMAT),
currentInvoice.totalPrice(),
"PAID",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

paymentStatus에 하드코딩된 문자열 "PAID"가 사용되었습니다. 이러한 값은 오타에 취약하고, 나중에 상태가 추가/변경될 때 관리가 어렵습니다. PaymentStatus와 같은 enum을 정의하거나, 최소한 상수로 분리하여 관리하는 것을 권장합니다.

개선 예시:

public enum PaymentStatus {
    PAID, UNPAID, FAILED;
}

// ...
new InvoiceNotificationEvent.Variables(
    // ...
    PaymentStatus.PAID.name(),
    items
);

@github-actions
Copy link
Copy Markdown

SonarQube Quality Summary (Community)

Quality Gate FAILED

Branch: fix/UPLUS-150
Compared to: default branch

Issues

  • 🐞 Bugs: 0
  • 🔐 Vulnerabilities: 2
  • 📎 Code Smells: 50

Measures

  • Coverage: 0%
  • Duplication: 0%

🔗 Dashboard: https://sonarqube.swthewhite.store/dashboard?id=batch-core&branch=fix/UPLUS-150

Generated automatically by GitHub Actions.

@github-actions
Copy link
Copy Markdown

👋 PR 리마인드 알림입니다

이 PR이 몇 시간 동안 업데이트되지 않았어요.

  • 🙋 PR 작성자: 추가 작업 중이거나 설명이 필요하면 코멘트 남겨주세요
  • 👀 리뷰어 / 팀원: 이미 봤다면 LGTM 한 줄도 좋아요!

바쁘실 수 있다는 점 이해합니다 🙏
다만 작은 한 줄이 PR 흐름을 살려줘요 🙂

@starboxxxx starboxxxx merged commit d9d2cad into develop Jan 26, 2026
8 of 10 checks passed
@starboxxxx starboxxxx deleted the fix/UPLUS-150 branch January 26, 2026 14:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix 버그 수정 remind-needed size/M PR size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant