-
Notifications
You must be signed in to change notification settings - Fork 4
refactor: 우산 대여 코드 이벤트 분리 #502
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
base: dev
Are you sure you want to change the base?
Changes from all commits
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 |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| package upbrella.be.config.event | ||
|
|
||
| import org.springframework.beans.factory.InitializingBean | ||
| import org.springframework.context.ApplicationContext | ||
| import org.springframework.context.annotation.Bean | ||
| import org.springframework.context.annotation.Configuration | ||
| import upbrella.be.util.event.Events | ||
|
|
||
| @Configuration | ||
| class EventsConfiguration( | ||
| private val applicationContext: ApplicationContext | ||
| ) { | ||
|
|
||
| @Bean | ||
| fun eventsInitializer(): InitializingBean { | ||
| return InitializingBean { Events.setPublisher(applicationContext) } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,21 +1,8 @@ | ||
| package upbrella.be.rent.dto.response | ||
|
|
||
| import upbrella.be.rent.entity.ConditionReport | ||
|
|
||
| data class ConditionReportResponse( | ||
| val id: Long, | ||
| val umbrellaUuid: Long, | ||
| val content: String?, | ||
| val etc: String? | ||
| ) { | ||
| companion object { | ||
| fun fromConditionReport(conditionReport: ConditionReport): ConditionReportResponse { | ||
| return ConditionReportResponse( | ||
| id = conditionReport.history.id!!, | ||
| umbrellaUuid = conditionReport.history.umbrella.uuid, | ||
| content = conditionReport.content, | ||
| etc = conditionReport.etc | ||
| ) | ||
| } | ||
| } | ||
| } | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,21 +1,8 @@ | ||
| package upbrella.be.rent.dto.response | ||
|
|
||
| import upbrella.be.rent.entity.ImprovementReport | ||
|
|
||
| data class ImprovementReportResponse( | ||
| val id: Long = 0, | ||
| val umbrellaUuid: Long = 0, | ||
| val content: String? = "", | ||
| val etc: String? = "" | ||
| ) { | ||
| companion object { | ||
| fun fromImprovementReport(improvementReport: ImprovementReport): ImprovementReportResponse { | ||
| return ImprovementReportResponse( | ||
| id = improvementReport.history.id ?: 0, | ||
| umbrellaUuid = improvementReport.history.umbrella.uuid, | ||
| content = improvementReport.content, | ||
| etc = improvementReport.etc | ||
| ) | ||
| } | ||
| } | ||
| } | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| package upbrella.be.rent.event | ||
|
|
||
| import org.springframework.context.event.EventListener | ||
| import org.springframework.stereotype.Service | ||
| import upbrella.be.rent.entity.ConditionReport | ||
| import upbrella.be.rent.entity.ImprovementReport | ||
| import upbrella.be.rent.service.ConditionReportService | ||
| import upbrella.be.rent.service.ImprovementReportService | ||
| import upbrella.be.rent.service.RentService | ||
| import upbrella.be.slack.SlackAlarmService | ||
| import upbrella.be.slack.dto.service.input.NotifyConditionReportInput | ||
| import upbrella.be.slack.dto.service.input.NotifyImprovementReportInput | ||
| import upbrella.be.slack.dto.service.input.NotifyRentInput | ||
| import upbrella.be.slack.dto.service.input.NotifyReturnInput | ||
|
|
||
| @Service | ||
| class RentEventHandler( | ||
| private val slackAlarmService: SlackAlarmService, | ||
| private val conditionReportService: ConditionReportService, | ||
| private val rentService: RentService, | ||
| private val improvementReportService: ImprovementReportService, | ||
| ) { | ||
|
|
||
| @EventListener(UmbrellaRentedEvent::class) | ||
| fun handleUmbrellaRentedEvent(event: UmbrellaRentedEvent) { | ||
| slackAlarmService.notifyRent( | ||
| NotifyRentInput( | ||
| userId = event.userId, | ||
| userName = event.userName, | ||
| rentStoreName = event.rentStoreName | ||
| ) | ||
| ) | ||
|
|
||
| event.conditionReportContent | ||
| ?.takeIf { it.isNotBlank() } | ||
| ?.let { content -> | ||
| ConditionReport( | ||
| historyId = event.historyId, | ||
| content = content | ||
| ).also { conditionReport -> | ||
| conditionReportService.saveConditionReport(conditionReport) | ||
| slackAlarmService.notifyConditionReport( | ||
| NotifyConditionReportInput( | ||
| umbrellaId = event.umbrellaId, | ||
| rentStoreName = event.rentStoreName, | ||
| content = content | ||
| ) | ||
| ) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| @EventListener(UmbrellaReturnedEvent::class) | ||
| fun handleUmbrellaReturnedEvent(event: UmbrellaReturnedEvent) { | ||
|
|
||
| val unrefundedRentCount = rentService.countUnrefundedRent() | ||
| slackAlarmService.notifyReturn( | ||
| NotifyReturnInput( | ||
| userId = event.rentUserId, | ||
| rentStoreName = event.rentStoreName, | ||
| rentedAt = event.rentedAt.toString(), | ||
| returnStoreName = event.returnStoreName, | ||
| returnedAt = event.returnedAt.toString(), | ||
| unrefundedCount = unrefundedRentCount | ||
| ) | ||
| ) | ||
|
|
||
| event.improvementReportContent?.takeIf { it.isNotBlank() } | ||
| ?.let { content -> | ||
| ImprovementReport( | ||
| historyId = event.historyId, | ||
| content = content | ||
| ).also { improvementReport -> | ||
| improvementReportService.save(improvementReport) | ||
| slackAlarmService.notifyImprovementReport( | ||
| NotifyImprovementReportInput( | ||
| umbrellaId = event.returnedUmbrellaId, | ||
| rentStoreName = event.rentStoreName, | ||
| rentedAt = event.rentedAt.toString(), | ||
| returnStoreName = event.returnStoreName, | ||
| returnedAt = event.returnedAt.toString(), | ||
| content = content | ||
| ) | ||
| ) | ||
| } | ||
| } | ||
| } | ||
|
Comment on lines
+53
to
+87
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. Apply the same transaction phase separation for return events. Similar to the rental event handler, separate persistence from notifications to ensure Slack failures don't impact the return transaction. - @EventListener(UmbrellaReturnedEvent::class)
- fun handleUmbrellaReturnedEvent(event: UmbrellaReturnedEvent) {
+ // Persist improvement reports within the transaction
+ @TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT)
+ fun persistImprovementReport(event: UmbrellaReturnedEvent) {
+ event.improvementReportContent?.takeIf { it.isNotBlank() }
+ ?.let { content ->
+ val improvementReport = ImprovementReport(
+ historyId = event.historyId,
+ content = content
+ )
+ improvementReportService.save(improvementReport)
+ }
+ }
+
+ // Send notifications after successful commit
+ @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
+ fun notifyReturnAfterCommit(event: UmbrellaReturnedEvent) {
val unrefundedRentCount = rentService.countUnrefundedRent()
slackAlarmService.notifyReturn(
NotifyReturnInput(
userId = event.rentUserId,
rentStoreName = event.rentStoreName,
rentedAt = event.rentedAt.toString(),
returnStoreName = event.returnStoreName,
returnedAt = event.returnedAt.toString(),
unrefundedCount = unrefundedRentCount
)
)
event.improvementReportContent?.takeIf { it.isNotBlank() }
?.let { content ->
- ImprovementReport(
- historyId = event.historyId,
- content = content
- ).also { improvementReport ->
- improvementReportService.save(improvementReport)
- slackAlarmService.notifyImprovementReport(
- NotifyImprovementReportInput(
- umbrellaId = event.returnedUmbrellaId,
- rentStoreName = event.rentStoreName,
- rentedAt = event.rentedAt.toString(),
- returnStoreName = event.returnStoreName,
- returnedAt = event.returnedAt.toString(),
- content = content
- )
+ slackAlarmService.notifyImprovementReport(
+ NotifyImprovementReportInput(
+ umbrellaId = event.returnedUmbrellaId,
+ rentStoreName = event.rentStoreName,
+ rentedAt = event.rentedAt.toString(),
+ returnStoreName = event.returnStoreName,
+ returnedAt = event.returnedAt.toString(),
+ content = content
)
- }
+ )
}
}🤖 Prompt for AI Agents |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| package upbrella.be.rent.event | ||
|
|
||
| import upbrella.be.util.event.Event | ||
|
|
||
| class UmbrellaRentedEvent( | ||
| val userId: Long, | ||
| val userName: String, | ||
| val rentStoreName: String, | ||
| val conditionReportContent: String? = null, | ||
| val umbrellaId: Long, | ||
| val historyId: Long, | ||
| ) : Event() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| package upbrella.be.rent.event | ||
|
|
||
| import upbrella.be.util.event.Event | ||
| import java.time.LocalDateTime | ||
|
|
||
| class UmbrellaReturnedEvent( | ||
| val rentUserId: Long, | ||
| val rentStoreName: String, | ||
| val rentedAt: LocalDateTime, | ||
| val returnStoreName: String, | ||
| val returnedAt: LocalDateTime, | ||
| val historyId: Long, | ||
| val improvementReportContent: String? = null, | ||
| val returnedUmbrellaId: Long, | ||
| ) : Event() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| package upbrella.be.rent.repository | ||
|
|
||
| import com.querydsl.core.types.Projections | ||
| import com.querydsl.jpa.impl.JPAQueryFactory | ||
| import org.springframework.stereotype.Repository | ||
| import upbrella.be.rent.dto.response.ConditionReportResponse | ||
| import upbrella.be.rent.entity.QConditionReport.conditionReport | ||
| import upbrella.be.rent.entity.QHistory.history | ||
|
|
||
| @Repository | ||
| class CustomConditionReportRepository( | ||
| private val queryFactory: JPAQueryFactory | ||
| ) { | ||
| fun findAllConditionReport(): List<ConditionReportResponse> { | ||
| return queryFactory | ||
| .select( | ||
| Projections.constructor( | ||
| ConditionReportResponse::class.java, | ||
| conditionReport.id, | ||
| history.umbrella.uuid, | ||
| conditionReport.content, | ||
| conditionReport.etc | ||
| ) | ||
| ) | ||
| .from(conditionReport) | ||
| .join(history) | ||
| .fetch() | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,30 @@ | ||||||||||||||||||||
| package upbrella.be.rent.repository | ||||||||||||||||||||
|
|
||||||||||||||||||||
| import com.querydsl.core.types.Projections | ||||||||||||||||||||
| import com.querydsl.jpa.impl.JPAQueryFactory | ||||||||||||||||||||
| import org.springframework.stereotype.Repository | ||||||||||||||||||||
| import upbrella.be.rent.dto.response.ImprovementReportResponse | ||||||||||||||||||||
| import upbrella.be.rent.entity.QHistory.history | ||||||||||||||||||||
| import upbrella.be.rent.entity.QImprovementReport.improvementReport | ||||||||||||||||||||
|
|
||||||||||||||||||||
| @Repository | ||||||||||||||||||||
| class CustomImprovementReportRepository( | ||||||||||||||||||||
| private val queryFactory: JPAQueryFactory, | ||||||||||||||||||||
| ) { | ||||||||||||||||||||
| fun findAllImprovementReport(): List<ImprovementReportResponse> { | ||||||||||||||||||||
| return queryFactory | ||||||||||||||||||||
| .select( | ||||||||||||||||||||
| Projections.constructor( | ||||||||||||||||||||
| ImprovementReportResponse::class.java, | ||||||||||||||||||||
| improvementReport.id, | ||||||||||||||||||||
| history.umbrella.uuid, | ||||||||||||||||||||
| improvementReport.content, | ||||||||||||||||||||
| improvementReport.etc | ||||||||||||||||||||
| ) | ||||||||||||||||||||
| ) | ||||||||||||||||||||
| .from(improvementReport) | ||||||||||||||||||||
| .join(history) | ||||||||||||||||||||
| .fetchJoin() | ||||||||||||||||||||
| .fetch() | ||||||||||||||||||||
|
Comment on lines
+25
to
+28
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. Bug: Cartesian join and invalid fetchJoin due to missing association
Fix the join by joining on the FK and remove fetchJoin: .from(improvementReport)
- .join(history)
- .fetchJoin()
+ .join(history)
+ .on(history.id.eq(improvementReport.historyId))
.fetch()If some ImprovementReports could reference missing History rows (ideally they should not), use 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||
| } | ||||||||||||||||||||
| } | ||||||||||||||||||||
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.
Explicitly map historyId to the DB column to avoid naming strategy surprises
Previously the FK column was
history_idvia@JoinColumn. Now that it's a scalar, relying on implicit naming may break if the physical naming strategy changes. Map it explicitly.Apply this diff:
📝 Committable suggestion
🤖 Prompt for AI Agents