Skip to content

MOSU-140 refactor: Application JPA 의존성 Processor로 위임#141

Merged
wlgns12370 merged 5 commits intodevelopfrom
refactor/mosu-140
Jul 26, 2025
Merged

MOSU-140 refactor: Application JPA 의존성 Processor로 위임#141
wlgns12370 merged 5 commits intodevelopfrom
refactor/mosu-140

Conversation

@wlgns12370
Copy link
Contributor

@wlgns12370 wlgns12370 commented Jul 26, 2025

✨ 구현한 기능

  • Application JPA 의존성 Processor로 위임

📢 논의하고 싶은 내용

  • x

🎸 기타

  • x

Summary by CodeRabbit

  • New Features

    • Added a new processor to streamline and centralize the retrieval of user application data.
    • Introduced a static factory method to provide empty application response objects.
  • Bug Fixes

    • Application and exam queries now only consider records with completed payments, improving data accuracy.
  • Refactor

    • Simplified and modularized application service logic for easier maintenance.
    • Updated method and interface signatures to clarify input/output types.
    • Improved lunch validation logic for exams.
  • Chores

    • Removed unused or redundant code and internal stubs.
    • Enhanced security by restricting inquiry creation to authenticated users with the appropriate role.

@coderabbitai
Copy link

coderabbitai bot commented Jul 26, 2025

Walkthrough

This update introduces a new GetApplicationsStepProcessor to encapsulate the logic for retrieving user applications, refactors several processor classes to use a more flexible generic interface, and updates repository queries to filter by completed payment status. It also applies minor method renaming, removes unused code, and enforces authorization on inquiry creation.

Changes

Files/Paths Change Summary
.../application/ApplicationService.java Refactored to delegate application retrieval to GetApplicationsStepProcessor; removed direct repository dependencies.
.../application/processor/GetApplicationsStepProcessor.java New class implementing step processing for application retrieval, aggregating data from multiple repositories.
.../application/processor/RegisterApplicationStepProcessor.java Moved to .processor package; updated to use two generic parameters in interface implementation.
.../application/processor/SaveApplicationStepProcessor.java File deleted; previously contained a stub processor with no logic.
.../application/processor/SaveExamTicketStepProcessor.java Updated to use two generic parameters in interface implementation.
.../application/vaildator/ApplicationValidator.java Changed lunch filtering from negated method to direct method reference (hasNotLunch).
.../auth/processor/SignUpAccountStepProcessor.java
.../auth/processor/SignUpProfileStepProcessor.java
Both updated to use two generic parameters in interface implementation.
.../inquiry/InquiryAnswerService.java Removed fields and logic related to ProfileJpaRepository and NotifyEventPublisher.
.../domain/application/ApplicationJpaRepository.java Updated query in existsByUserIdAndExamIds to join payments and filter by payment status 'DONE'.
.../domain/exam/ExamJpaEntity.java Replaced providesLunch() with hasNotLunch() (inverted logic).
.../domain/examapplication/ExamApplicationJpaRepository.java Updated queries to include payment status 'DONE' filter and improved formatting.
.../global/processor/StepProcessor.java Changed interface to accept separate input/output generic types.
.../presentation/application/dto/ApplicationRequest.java Removed commented-out methods; no functional changes.
.../presentation/application/dto/ApplicationResponse.java Added static factory method empty().
.../presentation/inquiry/InquiryController.java Added @PreAuthorize annotation to restrict inquiry creation to authenticated users with 'USER' role.

Sequence Diagram(s)

sequenceDiagram
    participant Controller
    participant ApplicationService
    participant GetApplicationsStepProcessor
    participant ApplicationRepo
    participant ExamAppRepo
    participant ExamRepo
    participant SubjectRepo
    participant PaymentRepo

    Controller->>ApplicationService: getApplications(userId)
    ApplicationService->>GetApplicationsStepProcessor: process(userId)
    GetApplicationsStepProcessor->>ApplicationRepo: findAllByUserId(userId)
    GetApplicationsStepProcessor->>ExamAppRepo: findByApplicationIds(appIds)
    GetApplicationsStepProcessor->>ExamRepo: findByIds(examIds)
    GetApplicationsStepProcessor->>SubjectRepo: findByExamIds(examIds)
    GetApplicationsStepProcessor->>PaymentRepo: findByApplicationIds(appIds)
    GetApplicationsStepProcessor-->>ApplicationService: List<ApplicationResponse>
    ApplicationService-->>Controller: List<ApplicationResponse>
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~18 minutes

Possibly related PRs

Suggested labels

우선순위 중

Suggested reviewers

  • jbh010204
  • chominju02

Poem

In the fields of code where logic hops,
A rabbit refactors, never stops.
Processors now with types anew,
Queries filter payments through.
Lunch is checked, responses neat,
Secure inquiries can't be beat!
🐇✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/mosu-140

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@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.

Summary of Changes

Hello @wlgns12370, 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!

This pull request focuses on a significant refactoring of the application's core service layer, specifically within the application and exam management domains. The main objective is to reduce the ApplicationService's direct dependencies on JPA repositories by delegating data access and complex business logic to dedicated 'Processor' components. This change aims to improve modularity, maintainability, and testability of the codebase. Additionally, it includes important functional updates to ensure data consistency related to payment statuses and minor code quality improvements.

Highlights

  • Core Refactoring: JPA Dependency Delegation: The primary goal of this PR is to refactor ApplicationService by delegating its direct JPA repository dependencies and associated business logic to new or existing StepProcessor classes. This promotes a cleaner architecture with improved separation of concerns.
  • New Processor for Application Retrieval: Introduced a new GetApplicationsStepProcessor to encapsulate the logic for retrieving user applications, which was previously handled directly within ApplicationService.
  • Enhanced StepProcessor Interface: The generic StepProcessor interface has been updated from StepProcessor<T> to StepProcessor<REQ, RES>, allowing for distinct request and response types, which improves type safety and flexibility for various processing steps.
  • Functional Enhancement: Payment Status Filtering: Modified several JPA queries across ApplicationJpaRepository and ExamApplicationJpaRepository to explicitly filter results based on paymentStatus = 'DONE'. This ensures that only successfully paid applications and exam entries are considered in relevant operations, preventing issues with incomplete transactions.
  • Code Cleanup and Minor Refactorings: Performed general code cleanup, including the removal of commented-out code in ApplicationRequest.java, renaming of providesLunch() to hasNotLunch() in ExamJpaEntity.java for better semantic clarity, and the removal of SaveApplicationStepProcessor.java.
  • Security Enhancement: Added @PreAuthorize annotation to the create method in InquiryController.java to enforce user authentication and role-based access control (hasRole('USER')).
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 in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

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 issue 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 or fill out our survey to provide feedback.

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

@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

This pull request refactors the ApplicationService by delegating JPA dependencies to processors, improving the service layer. It also generalizes the StepProcessor interface. Key changes include updated JPQL queries to check for DONE payment status and a new authorization rule in InquiryController. The review comments suggest improvements for method naming, SQL keyword capitalization, handling of empty lists, query readability, and adding explanatory comments for security annotations.

Comment on lines 20 to 22
public static ApplicationResponse empty() {
return new ApplicationResponse(null, null);
}

Choose a reason for hiding this comment

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

high

The empty() factory method returns null for the exams list. This is generally considered an anti-pattern as it can lead to NullPointerException in client code that attempts to iterate over the list. It is safer to always return an empty collection instead of null.

Suggested change
public static ApplicationResponse empty() {
return new ApplicationResponse(null, null);
}
public static ApplicationResponse empty() {
return new ApplicationResponse(null, List.of());
}

Comment on lines +75 to 77
public boolean hasNotLunch() {
return lunchName == null;
}

Choose a reason for hiding this comment

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

medium

The method name hasNotLunch is a bit unconventional as it's phrased in the negative, which can sometimes be less clear to read than a positive statement. While it works with the method reference, a more idiomatic name would improve long-term maintainability. Consider renaming it to something like doesNotProvideLunch.

Suggested change
public boolean hasNotLunch() {
return lunchName == null;
}
public boolean doesNotProvideLunch() {
return lunchName == null;
}

Comment on lines +72 to +73
JOIN ExamJpaEntity e on ea.examId = e.id
JOIN PaymentJpaEntity p on p.examApplicationId = ea.id

Choose a reason for hiding this comment

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

medium

For consistency with other SQL keywords in this query (which are in uppercase), it's good practice to also capitalize the on keyword.

Suggested change
JOIN ExamJpaEntity e on ea.examId = e.id
JOIN PaymentJpaEntity p on p.examApplicationId = ea.id
JOIN ExamJpaEntity e ON ea.examId = e.id
JOIN PaymentJpaEntity p ON p.examApplicationId = ea.id


@PostMapping

@PreAuthorize("isAuthenticated() and hasRole('USER')")

Choose a reason for hiding this comment

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

medium

Adding @PreAuthorize is a good security measure. Consider adding a comment explaining why this annotation is necessary and what security concern it addresses. This helps future developers understand the purpose of the annotation and avoid accidentally removing it.

Suggested change
@PreAuthorize("isAuthenticated() and hasRole('USER')")
@PreAuthorize("isAuthenticated() and hasRole('USER')") // Ensures only authenticated users with the 'USER' role can create inquiries

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/main/java/life/mosu/mosuserver/presentation/application/dto/ApplicationResponse.java (1)

20-22: Consider using empty collections instead of null values.

The empty() factory method follows good patterns, but returning null values in DTOs can cause issues for API consumers. Consider using an empty list for exams and potentially Optional<Long> for applicationId or a sentinel value like 0L.

 public static ApplicationResponse empty() {
-    return new ApplicationResponse(null, null);
+    return new ApplicationResponse(null, List.of());
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a18c5aa and e6e79b8.

📒 Files selected for processing (16)
  • src/main/java/life/mosu/mosuserver/application/application/ApplicationService.java (3 hunks)
  • src/main/java/life/mosu/mosuserver/application/application/processor/GetApplicationsStepProcessor.java (1 hunks)
  • src/main/java/life/mosu/mosuserver/application/application/processor/RegisterApplicationStepProcessor.java (2 hunks)
  • src/main/java/life/mosu/mosuserver/application/application/processor/SaveApplicationStepProcessor.java (0 hunks)
  • src/main/java/life/mosu/mosuserver/application/application/processor/SaveExamTicketStepProcessor.java (1 hunks)
  • src/main/java/life/mosu/mosuserver/application/application/vaildator/ApplicationValidator.java (1 hunks)
  • src/main/java/life/mosu/mosuserver/application/auth/processor/SignUpAccountStepProcessor.java (1 hunks)
  • src/main/java/life/mosu/mosuserver/application/auth/processor/SignUpProfileStepProcessor.java (1 hunks)
  • src/main/java/life/mosu/mosuserver/application/inquiry/InquiryAnswerService.java (0 hunks)
  • src/main/java/life/mosu/mosuserver/domain/application/ApplicationJpaRepository.java (1 hunks)
  • src/main/java/life/mosu/mosuserver/domain/exam/ExamJpaEntity.java (1 hunks)
  • src/main/java/life/mosu/mosuserver/domain/examapplication/ExamApplicationJpaRepository.java (5 hunks)
  • src/main/java/life/mosu/mosuserver/global/processor/StepProcessor.java (1 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/application/dto/ApplicationRequest.java (0 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/application/dto/ApplicationResponse.java (1 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/inquiry/InquiryController.java (1 hunks)
💤 Files with no reviewable changes (3)
  • src/main/java/life/mosu/mosuserver/presentation/application/dto/ApplicationRequest.java
  • src/main/java/life/mosu/mosuserver/application/application/processor/SaveApplicationStepProcessor.java
  • src/main/java/life/mosu/mosuserver/application/inquiry/InquiryAnswerService.java
🔇 Additional comments (28)
src/main/java/life/mosu/mosuserver/presentation/inquiry/InquiryController.java (2)

39-39: Good security enhancement!

Adding authorization to the inquiry creation endpoint is a solid improvement that ensures only authenticated users with the USER role can create inquiries. This change maintains consistency with other user-level operations in the controller.


60-67: Verify missing authorization on getInquiryDetail

The getInquiryDetail endpoint (GET /inquiry/{postId}) has no @PreAuthorize and, given our SecurityConfig’s .anyRequest().permitAll(), is effectively open to anonymous users. All other inquiry endpoints enforce role checks via method-level @PreAuthorize.
Please confirm whether returning inquiry details publicly is intentional or if this method should be secured (e.g., only authenticated users or specific roles).

src/main/java/life/mosu/mosuserver/global/processor/StepProcessor.java (1)

3-5: Excellent architectural improvement with dual generic types.

The refactoring from StepProcessor<T> to StepProcessor<REQ, RES> provides better type safety and flexibility, allowing processors to have distinct input and output types rather than being constrained to the same type.

src/main/java/life/mosu/mosuserver/domain/exam/ExamJpaEntity.java (1)

75-77: Good method renaming for clarity.

The rename from providesLunch() to hasNotLunch() improves code readability by eliminating double negation in calling code and making the boolean condition more explicit.

src/main/java/life/mosu/mosuserver/application/application/vaildator/ApplicationValidator.java (1)

51-51: Consistent update with domain entity changes.

The change from lambda expression with negation to method reference ExamJpaEntity::hasNotLunch improves readability and maintains consistency with the domain entity method renaming.

src/main/java/life/mosu/mosuserver/application/auth/processor/SignUpAccountStepProcessor.java (1)

14-14: Proper implementation of updated StepProcessor interface.

The class correctly implements the new dual-generic StepProcessor<UserJpaEntity, UserJpaEntity> interface while maintaining the same input/output type, which is appropriate for this account creation processor.

src/main/java/life/mosu/mosuserver/application/auth/processor/SignUpProfileStepProcessor.java (2)

14-15: LGTM: Interface signature updated correctly.

The change from StepProcessor<ProfileJpaEntity> to StepProcessor<ProfileJpaEntity, ProfileJpaEntity> aligns with the refactored interface that now explicitly specifies both input and output types. Since this processor handles the same type for both input and output, the implementation is consistent.


14-15: LGTM: Interface signature updated correctly.

The update to implement StepProcessor<ProfileJpaEntity, ProfileJpaEntity> correctly aligns with the refactored interface design while maintaining the same input/output types and preserving existing functionality.

src/main/java/life/mosu/mosuserver/application/application/processor/SaveExamTicketStepProcessor.java (2)

13-14: LGTM: Interface signature updated correctly.

The change to StepProcessor<ApplicationProcessingContext, ApplicationProcessingContext> is consistent with the interface refactoring and correctly specifies both input and output types as the same.


13-14: LGTM: Consistent interface signature update.

The change to StepProcessor<ApplicationProcessingContext, ApplicationProcessingContext> maintains consistency with the refactored interface design while preserving the existing processing logic.

src/main/java/life/mosu/mosuserver/domain/examapplication/ExamApplicationJpaRepository.java (7)

35-35: Good: Payment status filtering added for data consistency.

Adding the AND p.paymentStatus = 'DONE' condition ensures only exam applications with completed payments are returned, which improves data consistency.


64-76: LGTM: Query formatting improved.

The JPQL query formatting has been improved for better readability while maintaining the same logic.


75-75: Payment status filtering verified

All usages of the updated repository methods have been reviewed and handle “only DONE” applications as expected:

  • ExamApplicationService uses findExamApplicationInfoById(...) and reacts with an EXAM_APPLICATION_NOT_FOUND exception when no result is returned.
  • NotifyVariableFactory invokes findExamInfo(...) and findExamInfoWithExamNumber(...) (and throws EXAM_APPLICATION_NOT_FOUND) only for customers who have completed payment.
  • findExamAndPaymentByExamApplicationId(...) is currently unused (its previous caller is commented out).

No callers expect non-DONE payment statuses, so the added AND p.paymentStatus = 'DONE' filter will not break existing functionality.


35-35: Payment status filtering correctly implemented.

The addition of AND p.paymentStatus = 'DONE' ensures only completed payments are returned, which improves data consistency.


75-75: Consistent payment status filtering applied.

The same payment completion filter is correctly applied to maintain consistency across query methods.


90-90: Payment filtering maintained in ExamInfo query.

Consistent application of the payment status filter ensures only completed transactions are included.


106-106: Verify Payment Status Filter Across Queries

The addition of AND p.paymentStatus = 'DONE' changes the behavior of several repository methods and their callers:

  • ExamApplicationService.java

    • Method: findExamApplicationInfoById(examApplicationId)
    • Impact: Unpaid or pending applications will now result in Optional.empty() → throws EXAM_APPLICATION_NOT_FOUND.
  • NotifyVariableFactory.java

    • Methods:
      • findExamInfo(targetId)
      • findExamInfoWithExamNumber(targetId)
    • Impact: Pre-exam notification flows (1 week, 3 days, 1 day before) will skip any applications whose payment isn’t DONE.
  • ApplicationJpaRepository.java

    • Method: existsByUserIdAndExamIds(userId, examIds)
    • Impact: Existence checks now only count paid exam applications.

Please confirm that:

  1. Excluding non-paid applications in all of these scenarios aligns with the intended business rules.
  2. Exception handling and error messages distinguish between “not found” vs. “payment incomplete.”
  3. Relevant tests and documentation have been updated to cover the new filter behavior.
src/main/java/life/mosu/mosuserver/application/application/processor/RegisterApplicationStepProcessor.java (4)

1-1: Good: Package structure improved.

Moving the processor to the dedicated processor package improves code organization and separation of concerns.


18-19: LGTM: Interface signature updated correctly.

The change to StepProcessor<RegisterApplicationCommand, RegisterApplicationCommand> is consistent with the interface refactoring and correctly specifies both input and output types.


1-1: Good refactoring: Package organization improved.

Moving the processor to the dedicated processor package improves code organization and follows the established pattern for processor classes.


18-19: Interface signature updated consistently.

The update to StepProcessor<RegisterApplicationCommand, RegisterApplicationCommand> maintains consistency with the refactored interface design across all processor classes.

src/main/java/life/mosu/mosuserver/application/application/processor/GetApplicationsStepProcessor.java (3)

17-26: LGTM: Clean dependency injection setup

The processor is properly configured as a Spring component with constructor injection for all required repositories. The separation of concerns is well-maintained by encapsulating JPA operations within this dedicated processor.


29-34: LGTM: Proper handling of empty results

The early return pattern for empty applications is efficient and prevents unnecessary processing. The empty list return is appropriate for the use case.


36-44: ApplicationContext chaining is safe as implemented

We’ve confirmed that fetchExams, fetchSubjects, and fetchPayments all invoke Spring Data JPA findBy…In methods, which by contract return non-null lists (empty when there’s no match). The collectors:

  • .toMap(...) in fetchExams and fetchPayments are fed distinct keys (no duplicates).
  • Collectors.groupingBy(...) in fetchSubjects handles zero or many entries cleanly.
  • In assemble(), missing subjects default to List.of(), and missing payments simply pass null into the DTO (which should be handled at the presentation layer).

Any exceptions from the repository (e.g. connectivity issues) will propagate as DataAccessException, which you can catch or translate at a higher layer if desired. No additional null-checks or try/catch blocks are required within ApplicationContext itself.

src/main/java/life/mosu/mosuserver/application/application/ApplicationService.java (3)

6-7: LGTM: Clean import organization

The imports have been properly updated to reflect the new processor dependency and the relocated RegisterApplicationStepProcessor.


31-31: LGTM: Proper dependency injection

The GetApplicationsStepProcessor is correctly injected as a final field, maintaining consistency with other processor dependencies.


64-66: Excellent refactoring: Simplified service method

The getApplications method is now much cleaner and follows the single responsibility principle. The complex JPA operations and data assembly logic has been properly delegated to the dedicated processor, making the service more focused on orchestration rather than implementation details.

src/main/java/life/mosu/mosuserver/domain/application/ApplicationJpaRepository.java (1)

12-25: Verify duplicate application handling after payment filter

The updated existsByUserIdAndExamIds now only detects applications with a 'DONE' payment status. We found a single caller in the validator:

  • File: src/main/java/life/mosu/mosuserver/application/application/vaildator/ApplicationValidator.java
    Method: NoDuplicateApplication(Long userId, List<Long> examIds)
    Logic:
    boolean alreadyApplied = applicationJpaRepository.existsByUserIdAndExamIds(userId, examIds);
    if (alreadyApplied) {
        throw new CustomRuntimeException(ErrorCode.APPLICATION_SCHOOL_DUPLICATED);
    }
    Incomplete or pending payments will now return false, allowing users to reapply before payment completion.

Please verify that this new behavior aligns with your business requirements—i.e., should pending‐payment applications be excluded from duplicate checks, or do you need to adjust the query or validation logic?

@wlgns12370 wlgns12370 merged commit 294ee0c into develop Jul 26, 2025
2 checks passed
@wlgns12370 wlgns12370 deleted the refactor/mosu-140 branch August 7, 2025 01:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant