Skip to content

Conversation

@chominju02
Copy link
Contributor

@chominju02 chominju02 commented Aug 2, 2025

✨ 구현한 기능

  • 각 exam당 신청 마감되었는지 체크하는 validator 구현
  • 에러 처리

📢 논의하고 싶은 내용

🎸 기타

Summary by CodeRabbit

  • New Features

    • Added validation to prevent applications to exams that have reached full capacity.
    • Introduced new error messages for closed applications and price loading failures.
  • Bug Fixes

    • Improved error handling when retrieving application price information.
  • Other Improvements

    • Enhanced validation and error codes for clearer feedback during the application process.
    • Updated refund processing criteria for more accurate status checks.

@chominju02 chominju02 self-assigned this Aug 2, 2025
@coderabbitai
Copy link

coderabbitai bot commented Aug 2, 2025

Walkthrough

The changes introduce an additional validation step to the application process, ensuring exams are not full before checking if their dates have passed. Supporting logic and error codes are added for this new validation, and exception handling is improved in discount calculations. Minor corrections and dependency updates are also included.

Changes

Cohort / File(s) Change Summary
Application Validation Logic
src/main/java/life/mosu/mosuserver/application/application/ApplicationService.java, src/main/java/life/mosu/mosuserver/application/application/vaildator/ApplicationValidator.java
Application validation now checks if exams are full before checking exam dates. Added examNotFull method, updated method naming, and corrected error code in lunch selection validation. Introduced dependency on quota cache.
Exam Application Service
src/main/java/life/mosu/mosuserver/application/examapplication/ExamApplicationService.java
Removed unused repository, changed lunchCount to primitive, added exception handling for discount calculation with new error code, and removed a logging statement.
Refund Query Logic
src/main/java/life/mosu/mosuserver/domain/refund/RefundJpaRepository.java
Modified refund query to filter by refund status instead of payment status, changing the criteria for returned records.
Error Codes
src/main/java/life/mosu/mosuserver/global/exception/ErrorCode.java
Added new error codes: PRICE_LOAD_FAILURE and APPLICATION_CLOSED for improved error reporting in application processing.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ApplicationService
    participant ApplicationValidator
    participant ExamQuotaCacheManager

    User->>ApplicationService: apply(examIds)
    ApplicationService->>ApplicationValidator: examNotFull(examIds)
    ApplicationValidator->>ExamQuotaCacheManager: getCurrentApplications(examIds)
    ApplicationValidator-->>ApplicationService: (throws if full)
    ApplicationService->>ApplicationValidator: examDateNotPassed(examIds)
    ApplicationValidator-->>ApplicationService: (throws if date passed)
    ApplicationService->>...: (proceed with further validations and processing)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~15 minutes

Possibly related PRs

Suggested reviewers

  • wlgns12370

Poem

In the warren where code is spun,
A check for full exams is now begun.
With new errors to catch and flows to mend,
The rabbits ensure no surprises at the end.
Hop, validate, and never stall—
Applications now fair for all! 🐇✨

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-179

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 @chominju02, 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 introduces a critical validation step to ensure that users cannot apply for exams once their capacity has been reached, enhancing the robustness of the application process. It also includes general improvements to error handling, minor code cleanups, and a correction to a refund query, contributing to overall system stability and maintainability.

Highlights

  • New Validation for Exam Capacity: I've implemented a new validator, examNotFull, within ApplicationValidator to prevent users from applying to exams that have already reached their maximum capacity. This check is now integrated into the application flow in ApplicationService.
  • Improved Error Handling: I've introduced two new error codes: APPLICATION_CLOSED for when an exam's application quota is met, and PRICE_LOAD_FAILURE for issues during price calculation. Error handling for retrieving discount amounts has also been enhanced in ExamApplicationService.
  • Code Refinements and Cleanup: I've made several minor improvements, including renaming ExamDateNotPassed to examDateNotPassed for consistent casing, updating an error code from EXAM_APPLICATION_NOT_FOUND to EXAM_NOT_FOUND, and removing an unused PaymentJpaRepository dependency.
  • Refund Query Correction: The refund query in RefundJpaRepository has been updated to correctly check r.refundStatus = 'DONE' instead of p.paymentStatus = 'CANCELLED_DONE', ensuring accurate refund status retrieval.
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 introduces a validator to check if an exam application is closed because it's full, using a cache for performance. It also includes some related refactoring and bug fixes. The overall implementation is good, and I have provided suggestions to improve error handling and code conciseness.

Comment on lines +174 to +178
try {
return calculator.getAppliedDiscountAmount(totalAmount);
} catch (Exception ex) {
throw new CustomRuntimeException(ErrorCode.PRICE_LOAD_FAILURE);
}

Choose a reason for hiding this comment

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

high

Catching a generic Exception is too broad and can mask unexpected runtime exceptions. It's better to catch the specific exception(s) you expect, such as IllegalArgumentException which is thrown by FixedQuantityDiscountCalculator. This makes error handling more robust and predictable.

        } catch (IllegalArgumentException ex) {

JOIN ExamJpaEntity e ON ea.examId = e.id
WHERE r.examApplicationId = :examApplicationId
AND p.paymentStatus = 'CANCELLED_DONE'
AND r.refundStatus = 'DONE'

Choose a reason for hiding this comment

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

high

The query condition p.paymentStatus = 'CANCELLED_DONE' seems to be replaced with r.refundStatus = 'DONE'. Ensure that this change accurately reflects the intended logic for filtering refunds. It's crucial that the correct status is used to identify refunds for the given exam application.

Comment on lines +86 to +95
.anyMatch(examId -> {
Optional<Long> currentApplications = examQuotaCacheManager.getCurrentApplications(
examId);
Optional<Long> maxCapacity = examQuotaCacheManager.getMaxCapacity(examId);

if (currentApplications.isPresent() && maxCapacity.isPresent()) {
return currentApplications.get() >= maxCapacity.get();
}
return false;
});

Choose a reason for hiding this comment

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

medium

The lambda expression within anyMatch can be simplified to be more concise and idiomatic by using Optional.flatMap and Optional.map. This avoids explicit isPresent() and .get() calls, which improves readability.

        boolean isFull = examIds.stream()
                .anyMatch(examId -> examQuotaCacheManager.getMaxCapacity(examId)
                        .flatMap(maxCapacity -> examQuotaCacheManager.getCurrentApplications(examId)
                                .map(currentApplications -> currentApplications >= maxCapacity))
                        .orElse(false));

Set<Subject> subjects = request.getSubjects();

validator.ExamDateNotPassed(examIds);
validator.examNotFull(examIds);

Choose a reason for hiding this comment

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

medium

It's good to see the addition of validator.examNotFull(examIds) to prevent applications for full exams. This enhances the application process by preventing users from applying to exams that have reached their capacity.

}

public void ExamDateNotPassed(List<Long> examIds) {
public void examDateNotPassed(List<Long> examIds) {

Choose a reason for hiding this comment

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

medium

Renaming ExamDateNotPassed to examDateNotPassed improves code readability by adhering to Java naming conventions for methods (camelCase).

List<ExamApplicationJpaEntity> examApplicationEntities = examApplicationJpaRepository.findByApplicationId(
applicationId);
Integer lunchCount = (int) examApplicationEntities.stream()
int lunchCount = (int) examApplicationEntities.stream()

Choose a reason for hiding this comment

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

medium

Changing the type of lunchCount from Integer to int is a good practice as it avoids potential NullPointerException and is more memory-efficient for primitive types.

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: 1

🧹 Nitpick comments (1)
src/main/java/life/mosu/mosuserver/global/exception/ErrorCode.java (1)

155-156: Remove unnecessary empty lines.

Extra empty lines at the end of the file should be removed for consistency.

-    LUA_SCRIPT_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "LUA 스크립트 실행 중 오류가 발생했습니다.");
-
-
+    LUA_SCRIPT_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "LUA 스크립트 실행 중 오류가 발생했습니다.");
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between c280b8d and 9fe89cf.

📒 Files selected for processing (5)
  • src/main/java/life/mosu/mosuserver/application/application/ApplicationService.java (1 hunks)
  • src/main/java/life/mosu/mosuserver/application/application/vaildator/ApplicationValidator.java (5 hunks)
  • src/main/java/life/mosu/mosuserver/application/examapplication/ExamApplicationService.java (2 hunks)
  • src/main/java/life/mosu/mosuserver/domain/refund/RefundJpaRepository.java (1 hunks)
  • src/main/java/life/mosu/mosuserver/global/exception/ErrorCode.java (2 hunks)
🔇 Additional comments (9)
src/main/java/life/mosu/mosuserver/global/exception/ErrorCode.java (1)

68-68: LGTM!

The APPLICATION_CLOSED error code with HTTP 400 status is semantically correct for representing application deadline closure validation.

src/main/java/life/mosu/mosuserver/domain/refund/RefundJpaRepository.java (1)

29-29: LGTM! Improved query accuracy.

Filtering by refundStatus = 'DONE' instead of paymentStatus = 'CANCELLED_DONE' is more semantically correct for a refund query. This change ensures the method returns refunds based on their actual status rather than the related payment status.

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

44-45: LGTM! Well-structured validation sequence.

The separation of capacity and date validation is logical and aligns with the PR objective. Checking if exams are full before validating dates provides better user experience by prioritizing capacity constraints.

src/main/java/life/mosu/mosuserver/application/examapplication/ExamApplicationService.java (2)

123-123: LGTM! Minor optimization.

Using primitive int instead of Integer for lunchCount is a good optimization since the value cannot be null in this context.


174-179: LGTM! Improved error handling.

The try-catch block properly handles exceptions during discount calculation and provides consistent error reporting using the new PRICE_LOAD_FAILURE error code.

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

9-9: LGTM! Proper dependency injection.

Adding ExamQuotaCacheManager dependency to support the new capacity validation feature is well-structured.

Also applies to: 25-25


36-36: LGTM! Corrected error code.

Using EXAM_NOT_FOUND instead of EXAM_APPLICATION_NOT_FOUND is more semantically accurate for this validation context.


74-74: LGTM! Improved naming convention.

Renaming from ExamDateNotPassed to examDateNotPassed follows proper Java naming conventions.


84-100: LGTM! Well-implemented capacity validation.

The examNotFull method properly implements the core feature of checking exam capacity. The logic correctly compares current applications against maximum capacity and handles cache misses gracefully by defaulting to "not full" (safe failure mode).

The implementation handles edge cases well:

  • Proper use of Optional to handle cache misses
  • Safe default behavior when cache data is unavailable
  • Clear logic flow with appropriate error code usage

APPLICATION_SCHOOL_DUPLICATED(HttpStatus.BAD_REQUEST, "동일 일자의 같은 학교를 신청할 수 없습니다."),
EXAM_DUPLICATED(HttpStatus.BAD_REQUEST, "동일한 시험을 신청할 수 없습니다."),
WRONG_APPLICATION_ID_TYPE(HttpStatus.BAD_REQUEST, "신청 ID 타입이 올바르지 않습니다."),
PRICE_LOAD_FAILURE(HttpStatus.CONFLICT, "신청 가격 정보를 가져오는데 실패했습니다."),
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Reconsider HTTP status code for PRICE_LOAD_FAILURE.

Using HTTP 409 (Conflict) for price loading failure seems semantically incorrect. Consider using HTTP 500 (Internal Server Error) or HTTP 503 (Service Unavailable) instead, as this represents a system/service failure rather than a resource conflict.

-    PRICE_LOAD_FAILURE(HttpStatus.CONFLICT, "신청 가격 정보를 가져오는데 실패했습니다."),
+    PRICE_LOAD_FAILURE(HttpStatus.INTERNAL_SERVER_ERROR, "신청 가격 정보를 가져오는데 실패했습니다."),
🤖 Prompt for AI Agents
In src/main/java/life/mosu/mosuserver/global/exception/ErrorCode.java at line
67, the HTTP status code for PRICE_LOAD_FAILURE is currently set to 409
(Conflict), which is not appropriate for a system failure. Change the status
code to 500 (Internal Server Error) or 503 (Service Unavailable) to better
represent a service or system failure when price loading fails.

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.

2 participants