-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RAC-462 feat : wish 분리 및 신청서 API #327
Changes from all commits
05f7dd7
506d69a
a489203
15397fa
c1d5347
2e67fa6
e4a30a7
a9b3c9d
c74cd93
1601ef8
0625164
211ea10
463676f
62557b4
3f6b1fa
687d9a9
46a863f
a125cba
7ca9c5e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,8 +3,6 @@ | |
import com.postgraduate.admin.domain.repository.AdminUserRepository; | ||
import com.postgraduate.domain.member.user.domain.entity.User; | ||
import com.postgraduate.domain.member.user.exception.UserNotFoundException; | ||
import com.postgraduate.domain.member.user.domain.entity.Wish; | ||
import com.postgraduate.domain.member.user.exception.WishNotFoundException; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Service; | ||
|
||
|
@@ -15,14 +13,12 @@ | |
public class AdminUserService { | ||
private final AdminUserRepository adminUserRepository; | ||
|
||
public List<Wish> allJunior() { | ||
public List<User> allJunior() { | ||
return adminUserRepository.findAllJunior(); | ||
} | ||
|
||
public void updateWishDone(Long wishId) { | ||
User user = adminUserRepository.findUserByWishId(wishId) | ||
.orElseThrow(WishNotFoundException::new); | ||
user.updateWishDone(); | ||
//todo : wish삭제에 따른 수정 필요 | ||
} | ||
Comment on lines
20
to
22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Codebase verification Implement updateWishDone method properly - it's actively being used The method is actively called from
Example implementation: public void updateWishDone(Long wishId) {
throw new UnsupportedOperationException("This operation needs to be implemented - wish deletion functionality pending");
} 🔗 Analysis chainRemove or properly implement the updateWishDone method The current implementation with just a TODO comment is problematic:
Either:
- public void updateWishDone(Long wishId) {
- //todo : wish삭제에 따른 수정 필요
- }
public void updateWishDone(Long wishId) {
- //todo : wish삭제에 따른 수정 필요
+ throw new UnsupportedOperationException("This operation is no longer supported due to wish functionality separation");
} Let's verify if this method is still being called anywhere: 🏁 Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Search for any remaining calls to updateWishDone
rg -l "updateWishDone" --type java
Length of output: 187 Script: #!/bin/bash
# Let's check how updateWishDone is being used in AdminUserUseCase.java
rg "updateWishDone" src/main/java/com/postgraduate/admin/application/usecase/AdminUserUseCase.java -A 3 -B 3
Length of output: 277 |
||
|
||
public User userByUserId(Long userId) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -61,18 +61,18 @@ public void launchSalaryJob() throws JobInstanceAlreadyCompleteException, JobExe | |
.addLocalDateTime("date", LocalDateTime.now()) | ||
.toJobParameters(); | ||
jobLauncher.run(salaryJob, jobParameters); | ||
checkSalaryJobSuccess(jobParameters); | ||
checkSalaryJobSuccess(); | ||
} | ||
|
||
public void launchSalaryJobWithAdmin() throws JobInstanceAlreadyCompleteException, JobExecutionAlreadyRunningException, JobParametersInvalidException, JobRestartException { | ||
JobParameters jobParameters = new JobParametersBuilder() | ||
.addLocalDateTime("date", LocalDateTime.now()) | ||
.toJobParameters(); | ||
jobLauncher.run(salaryJobWithAdmin, jobParameters); | ||
checkSalaryJobSuccess(jobParameters); | ||
checkSalaryJobSuccess(); | ||
} | ||
|
||
private void checkSalaryJobSuccess(JobParameters jobParameters) throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException, JobParametersInvalidException { | ||
private void checkSalaryJobSuccess() throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException, JobParametersInvalidException { | ||
int retries = 0; | ||
boolean success = false; | ||
int seniorSize = seniorGetService.allSeniorId() | ||
|
@@ -90,6 +90,9 @@ private void checkSalaryJobSuccess(JobParameters jobParameters) throws JobExecut | |
Thread.currentThread().interrupt(); //스레드 상태 복원 | ||
log.error("Thread Interrupt 발생"); | ||
} | ||
JobParameters jobParameters = new JobParametersBuilder() | ||
.addLocalDateTime("date", LocalDateTime.now()) | ||
.toJobParameters(); | ||
jobLauncher.run(salaryJobWithAdmin, jobParameters); | ||
Comment on lines
+93
to
96
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Improve error handling and job tracking The creation of new JobParameters on each retry makes it difficult to correlate related job executions. Additionally, the job execution exceptions are not properly handled. - JobParameters jobParameters = new JobParametersBuilder()
- .addLocalDateTime("date", LocalDateTime.now())
- .toJobParameters();
- jobLauncher.run(salaryJobWithAdmin, jobParameters);
+ JobParameters jobParameters = new JobParametersBuilder()
+ .addLocalDateTime("date", LocalDateTime.now())
+ .addString("retryAttempt", String.valueOf(retries))
+ .addString("originalJobId", originalJobId) // Add correlation ID
+ .toJobParameters();
+ try {
+ jobLauncher.run(salaryJobWithAdmin, jobParameters);
+ } catch (JobExecutionException e) {
+ log.error("Failed to execute salary job on retry {}: {}", retries, e.getMessage());
+ throw e;
+ }
|
||
retries++; | ||
} | ||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -2,13 +2,11 @@ | |||||||||||||||||||
|
||||||||||||||||||||
import com.postgraduate.domain.member.user.application.dto.res.UserInfoResponse; | ||||||||||||||||||||
import com.postgraduate.domain.member.user.application.dto.res.UserMyPageResponse; | ||||||||||||||||||||
import com.postgraduate.domain.member.user.domain.entity.MemberRole; | ||||||||||||||||||||
import com.postgraduate.domain.member.user.domain.entity.constant.Role; | ||||||||||||||||||||
import com.postgraduate.domain.member.user.domain.entity.constant.Status; | ||||||||||||||||||||
import com.postgraduate.domain.member.user.domain.entity.Wish; | ||||||||||||||||||||
import com.postgraduate.global.auth.login.application.dto.req.SeniorSignUpRequest; | ||||||||||||||||||||
import com.postgraduate.global.auth.login.application.dto.req.SignUpRequest; | ||||||||||||||||||||
import com.postgraduate.domain.member.user.domain.entity.User; | ||||||||||||||||||||
import com.postgraduate.global.auth.login.application.dto.req.UserChangeRequest; | ||||||||||||||||||||
|
||||||||||||||||||||
public class UserMapper { | ||||||||||||||||||||
|
||||||||||||||||||||
|
@@ -48,29 +46,13 @@ public static User mapToUser(SeniorSignUpRequest request, String profile) { | |||||||||||||||||||
.phoneNumber(request.phoneNumber()) | ||||||||||||||||||||
.marketingReceive(request.marketingReceive()) | ||||||||||||||||||||
.profile(profile) | ||||||||||||||||||||
.role(Role.SENIOR) | ||||||||||||||||||||
.build(); | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
public static Wish mapToWish(User user, SignUpRequest request) { | ||||||||||||||||||||
Status matchingStatus = request.matchingReceive() ? Status.WAITING : Status.REJECTED; | ||||||||||||||||||||
return Wish.builder() | ||||||||||||||||||||
public static MemberRole mapToRole(Role role, User user) { | ||||||||||||||||||||
return MemberRole.builder() | ||||||||||||||||||||
.role(role) | ||||||||||||||||||||
Comment on lines
+52
to
+54
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add null checks for To prevent potential Apply this diff to add null checks: public static MemberRole mapToRole(Role role, User user) {
+ if (role == null || user == null) {
+ throw new IllegalArgumentException("Role and User must not be null");
+ }
return MemberRole.builder()
.role(role)
.user(user)
.build();
} 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||
.user(user) | ||||||||||||||||||||
.major(request.major()) | ||||||||||||||||||||
.field(request.field()) | ||||||||||||||||||||
.matchingReceive(request.matchingReceive()) | ||||||||||||||||||||
.status(matchingStatus) | ||||||||||||||||||||
.build(); | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
public static Wish mapToWish(User user, UserChangeRequest request) { | ||||||||||||||||||||
Status matchingStatus = request.matchingReceive() ? Status.WAITING : Status.REJECTED; | ||||||||||||||||||||
return Wish.builder() | ||||||||||||||||||||
.user(user) | ||||||||||||||||||||
.major(request.major()) | ||||||||||||||||||||
.field(request.field()) | ||||||||||||||||||||
.matchingReceive(request.matchingReceive()) | ||||||||||||||||||||
.status(matchingStatus) | ||||||||||||||||||||
.build(); | ||||||||||||||||||||
} | ||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,27 @@ | ||||||||||||||||
package com.postgraduate.domain.member.user.domain.entity; | ||||||||||||||||
|
||||||||||||||||
import com.postgraduate.domain.member.user.domain.entity.constant.Role; | ||||||||||||||||
import jakarta.persistence.*; | ||||||||||||||||
import lombok.AllArgsConstructor; | ||||||||||||||||
import lombok.Builder; | ||||||||||||||||
import lombok.Getter; | ||||||||||||||||
import lombok.NoArgsConstructor; | ||||||||||||||||
|
||||||||||||||||
@Entity | ||||||||||||||||
@Builder | ||||||||||||||||
@AllArgsConstructor | ||||||||||||||||
@NoArgsConstructor | ||||||||||||||||
@Getter | ||||||||||||||||
public class MemberRole { | ||||||||||||||||
@Id | ||||||||||||||||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||||||||||||||||
private Long roleId; | ||||||||||||||||
|
||||||||||||||||
@Enumerated(EnumType.STRING) | ||||||||||||||||
@Column(nullable = false) | ||||||||||||||||
private Role role; | ||||||||||||||||
Comment on lines
+20
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add validation to ensure role is never null While the column is marked as non-nullable in the database, the entity should validate this at the application level. Consider adding Bean Validation annotations. @Enumerated(EnumType.STRING)
@Column(nullable = false)
+@NotNull(message = "Role cannot be null")
private Role role; 📝 Committable suggestion
Suggested change
|
||||||||||||||||
|
||||||||||||||||
@ManyToOne(fetch = FetchType.LAZY) | ||||||||||||||||
@JoinColumn(name = "user_id") | ||||||||||||||||
private User user; | ||||||||||||||||
Comment on lines
+24
to
+26
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Codebase verification Add index and foreign key constraint to improve query performance The suggestion to add an index and explicit foreign key constraint is valid as:
Regarding the transactional context concern:
Recommended changes:
🔗 Analysis chainConsider adding an index on the user_id foreign key The many-to-one relationship would benefit from an index on the foreign key column for better query performance, especially when querying roles by user. @ManyToOne(fetch = FetchType.LAZY)
-@JoinColumn(name = "user_id")
+@JoinColumn(name = "user_id", foreignKey = @ForeignKey(name = "fk_member_role_user"))
+@Index(name = "idx_member_role_user_id")
private User user; Also, be cautious with lazy loading. Ensure that the user field is always accessed within a transactional context to prevent LazyInitializationException. 🏁 Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Check if @Transactional is properly used in services accessing MemberRole
ast-grep --pattern 'class $_ {
$$$
@Transactional
$$$
public $_ $_($$$) {
$$$
memberRole.getUser()
$$$
}
$$$
}'
Length of output: 137 Script: #!/bin/bash
# Let's first check for any references to MemberRole.getUser()
rg "memberRole.*getUser" -A 3
# Check for service classes that use MemberRole
rg "class.*Service.*\{" -A 5 | rg -B 5 "MemberRole"
# Check if there's any @Index annotation already on MemberRole
rg "@Index" src/main/java/com/postgraduate/domain/member/user/domain/entity/MemberRole.java
# Check for existing foreign key constraints in MemberRole
rg "@ForeignKey|@JoinColumn" src/main/java/com/postgraduate/domain/member/user/domain/entity/MemberRole.java
Length of output: 2361 Script: #!/bin/bash
# Let's check for @Transactional annotations in services that use MemberRole
rg "@Transactional" src/main/java/com/postgraduate/domain/member/user/domain/service/UserDeleteService.java
rg "@Transactional" src/main/java/com/postgraduate/domain/member/user/domain/service/UserUpdateService.java
rg "@Transactional" src/main/java/com/postgraduate/domain/member/user/domain/service/UserSaveService.java
# Check if there are any existing indexes in the entity
rg "Table|Index" src/main/java/com/postgraduate/domain/member/user/domain/entity/MemberRole.java
# Let's see the full MemberRole entity class to understand its structure
cat src/main/java/com/postgraduate/domain/member/user/domain/entity/MemberRole.java
Length of output: 1146 |
||||||||||||||||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -11,6 +11,7 @@ | |||||||||||||||
import org.hibernate.annotations.*; | ||||||||||||||||
|
||||||||||||||||
import java.time.LocalDateTime; | ||||||||||||||||
import java.util.ArrayList; | ||||||||||||||||
import java.util.List; | ||||||||||||||||
|
||||||||||||||||
import static java.time.LocalDate.now; | ||||||||||||||||
|
@@ -46,10 +47,9 @@ public class User { | |||||||||||||||
@Column(nullable = false) | ||||||||||||||||
private int point; | ||||||||||||||||
|
||||||||||||||||
@Enumerated(EnumType.STRING) | ||||||||||||||||
@Column(nullable = false) | ||||||||||||||||
@OneToMany(mappedBy = "user", fetch = FetchType.EAGER) | ||||||||||||||||
@Builder.Default | ||||||||||||||||
private Role role = Role.USER; | ||||||||||||||||
private List<MemberRole> roles = new ArrayList<>(); | ||||||||||||||||
Comment on lines
+50
to
+52
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider using Currently, the Apply this diff to change the fetch type: - @OneToMany(mappedBy = "user", fetch = FetchType.EAGER)
+ @OneToMany(mappedBy = "user", fetch = FetchType.LAZY) 📝 Committable suggestion
Suggested change
|
||||||||||||||||
|
||||||||||||||||
@Column(nullable = false) | ||||||||||||||||
private Boolean marketingReceive; | ||||||||||||||||
|
@@ -69,23 +69,29 @@ public class User { | |||||||||||||||
@Builder.Default | ||||||||||||||||
private boolean isDelete = false; | ||||||||||||||||
|
||||||||||||||||
@OneToOne(mappedBy = "user") | ||||||||||||||||
private Wish wish; | ||||||||||||||||
|
||||||||||||||||
public void addWish(Wish wish) { | ||||||||||||||||
this.wish = wish; | ||||||||||||||||
public boolean isJunior() { | ||||||||||||||||
return roles.stream() | ||||||||||||||||
.map(MemberRole::getRole) | ||||||||||||||||
.toList() | ||||||||||||||||
.contains(Role.USER); | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
public void updateWishDone() { | ||||||||||||||||
this.wish.updateDone(); | ||||||||||||||||
public boolean isSenior() { | ||||||||||||||||
return roles.stream() | ||||||||||||||||
.map(MemberRole::getRole) | ||||||||||||||||
.toList() | ||||||||||||||||
.contains(Role.SENIOR); | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
public boolean isJunior() { | ||||||||||||||||
return this.wish != null; | ||||||||||||||||
public boolean isAdmin() { | ||||||||||||||||
return roles.stream() | ||||||||||||||||
.map(MemberRole::getRole) | ||||||||||||||||
.toList() | ||||||||||||||||
.contains(Role.ADMIN); | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
public void updateRole(Role role) { | ||||||||||||||||
this.role = role; | ||||||||||||||||
public void updateRole(MemberRole memberRole) { | ||||||||||||||||
roles.add(memberRole); | ||||||||||||||||
Comment on lines
+93
to
+94
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ensure idempotent role updates in Adding roles without checking for existing entries might introduce duplicates, especially if Apply this diff: public void updateRole(MemberRole memberRole) {
- roles.add(memberRole);
+ if (!roles.contains(memberRole)) {
+ roles.add(memberRole);
+ }
} Note: If you've converted 📝 Committable suggestion
Suggested change
|
||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
public void updateInfo(String profile, String nickName, String phoneNumber) { | ||||||||||||||||
|
@@ -143,8 +149,4 @@ public boolean isHardDelete() { | |||||||||||||||
) | ||||||||||||||||
); | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
public boolean isSenior() { | ||||||||||||||||
return this.role.equals(Role.SENIOR); | ||||||||||||||||
} | ||||||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codebase verification
Critical: Null return in wishInfo() causes runtime risk in active endpoint
The method is actively used in the
/user/matching/{userId}
endpoint where its result is directly added to the model. Returning null will cause issues when the template tries to access wishInfo attributes.AdminWithThymeLeafController.userMatching()
adds the null response to model without null checkingImmediate action required to prevent runtime errors. Either:
🔗 Analysis chain
Critical: Replace null return with proper error handling.
Returning null with a TODO comment is problematic as it can lead to NullPointerException in consuming code. Consider these alternatives:
Here's a suggested improvement:
Let's check if this method is still being used:
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
Length of output: 195
Script:
Length of output: 536