Skip to content

✨ OMF-235 폼 변환 자동화 작업#115

Merged
wonjuneee merged 13 commits intodevelopfrom
feat/OMF-235
Mar 5, 2026
Merged

✨ OMF-235 폼 변환 자동화 작업#115
wonjuneee merged 13 commits intodevelopfrom
feat/OMF-235

Conversation

@wonjuneee
Copy link
Collaborator

@wonjuneee wonjuneee commented Mar 1, 2026

✨ Related Issue


📌 Task Details

  • 폼변환 요청이 성공적으로 등록 시, 이벤트 발행을 통해 변환 자동화 로직이 동작하도록 구현
  • AWS 람다를 통해 구글폼 변환 요청 자동화 로직 실행하도록 구현
  • 폼변환 요청에 대한 응답을 디스코드 웹훅과 연동

💬 Review Requirements (Optional)

Summary by CodeRabbit

릴리즈 노트

새로운 기능

  • Google 폼을 설문지로 변환하는 기능 추가
  • 폼 변환 결과를 실시간으로 추적 및 상세 보고
  • 변환 성공/실패 시 자동 알림 기능 추가
  • 지원하지 않는 질문 유형에 대한 상세 안내 제공

@wonjuneee wonjuneee requested a review from KJaeKwan March 1, 2026 04:22
@wonjuneee wonjuneee self-assigned this Mar 1, 2026
@wonjuneee wonjuneee added the 🌟feature 새로운 기능 label Mar 1, 2026
@coderabbitai
Copy link

coderabbitai bot commented Mar 1, 2026

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 1cb3a80a-1ef6-4d34-96bc-e9bd5c3b9bc3

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Note

.coderabbit.yml has unrecognized properties

CodeRabbit is using all valid settings from your configuration. Unrecognized properties (listed below) have been ignored and may indicate typos or deprecated fields that can be removed.

⚠️ Parsing warnings (1)
Validation error: Unrecognized key(s) in object: 'tools'
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • 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
📝 Walkthrough

Walkthrough

이 PR은 Google 폼을 설문으로 변환하는 기능을 도입합니다. 새로운 에러 코드, 데이터 모델, 이벤트 기반 변환 서비스, 그리고 Discord 알림 통합을 포함하여 전체 변환 워크플로우를 구현합니다.

Changes

Cohort / File(s) Summary
에러 코드 및 도메인 모델
src/main/java/OneQ/OnSurvey/domain/survey/SurveyErrorCode.java, src/main/java/OneQ/OnSurvey/domain/survey/model/formRequest/FormConversionPayload.java, src/main/java/OneQ/OnSurvey/domain/survey/model/formRequest/FormConversionResponse.java
새로운 FORM_CONVERSION_FAILED 에러 코드 추가 및 폼 변환 요청/응답을 위한 중첩된 레코드 구조(FormConversionPayload, FormConversionResponse와 그 하위 레코드들)를 정의합니다.
이벤트 기반 아키텍처
src/main/java/OneQ/OnSurvey/domain/survey/model/formRequest/event/FormRequestConversionEvent.java, src/main/java/OneQ/OnSurvey/domain/survey/service/formRequest/FormCommandService.java
FormRequest 저장 후 ApplicationEventPublisher를 통해 FormRequestConversionEvent를 발행하는 이벤트 기반 흐름을 구현합니다.
폼 변환 오케스트레이션
src/main/java/OneQ/OnSurvey/domain/survey/service/formRequest/FormRequestLambda.java
외부 Lambda 서비스와 통신하여 Google 폼을 설문으로 변환하는 복잡한 로직을 포함합니다. 설문 생성, 섹션/문제/선택지 처리, 유형 매핑, 트랜잭션 관리 및 상세한 로깅을 수행합니다.
트랜잭션 관리
src/main/java/OneQ/OnSurvey/global/infra/transaction/TransactionHandler.java
새로운 트랜잭션 경계(PROPAGATION_REQUIRES_NEW)에서 작업을 실행하는 유틸리티 컴포넌트를 제공합니다.
알림 인프라 확장
src/main/java/OneQ/OnSurvey/global/infra/discord/DiscordAlarmService.java, src/main/java/OneQ/OnSurvey/global/infra/discord/DiscordAlarmAsyncFacade.java, src/main/java/OneQ/OnSurvey/global/infra/discord/notifier/AlertNotifier.java, src/main/java/OneQ/OnSurvey/global/infra/discord/notifier/DiscordAlertNotifier.java, src/main/java/OneQ/OnSurvey/global/infra/discord/notifier/NoOpAlertNotifier.java
설문 변환 알림을 위한 비동기 메서드(sendSurveyConversionAsync)를 추가하고, Discord 알림 서비스에서 성공/실패 메시지를 구성하여 전송합니다.
알림 데이터 모델
src/main/java/OneQ/OnSurvey/global/infra/discord/notifier/dto/SurveyConversionAlert.java
변환 결과(성공/실패)를 모델링하는 SurveyConversionAlert 레코드 및 하위 레코드들(SurveyDetails, UnsupportedQuestion)과 팩토리 메서드를 정의합니다.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant FormCommandService
    participant EventPublisher
    participant FormRequestLambda
    participant ExternalLambda
    participant SurveyCommand
    participant QuestionCommand
    participant MemberFinder
    participant AlertNotifier

    Client->>FormCommandService: FormRequest 저장
    FormCommandService->>FormCommandService: FormRequest 영속화
    FormCommandService->>EventPublisher: FormRequestConversionEvent 발행
    EventPublisher->>FormRequestLambda: convertGoogleFormIntoSurvey() 호출
    FormRequestLambda->>ExternalLambda: FormConversionPayload 전송
    ExternalLambda-->>FormRequestLambda: FormConversionResponse 반환
    FormRequestLambda->>MemberFinder: 요청자 이메일로 회원 조회
    loop 각 변환 결과 처리
        FormRequestLambda->>SurveyCommand: 설문 생성 (upsertSurvey)
        SurveyCommand-->>FormRequestLambda: surveyId 반환
        FormRequestLambda->>QuestionCommand: 섹션 생성 (upsertSections)
        FormRequestLambda->>QuestionCommand: 문제 생성 (upsertInfoList)
        FormRequestLambda->>QuestionCommand: 선택지 생성 (upsertChoiceOptionList)
    end
    FormRequestLambda->>AlertNotifier: SurveyConversionAlert 전송
    AlertNotifier-->>Client: 변환 결과 알림 (비동기)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목은 'OMF-235 폼 변환 자동화 작업'으로 변경 사항의 핵심을 명확하게 요약하고 있습니다.
Description check ✅ Passed PR 설명은 템플릿의 모든 필수 섹션(Related Issue, Task Details)을 포함하고 있으며, 작업 항목들이 체계적으로 기술되어 있습니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/OMF-235

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

Comment @coderabbitai help to get the list of available commands and usage tips.

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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@src/main/java/OneQ/OnSurvey/domain/survey/service/formRequest/FormRequestLambda.java`:
- Around line 116-123: The catch block in FormRequestLambda currently only logs
the exception and exits, so failures aren't added to alert.details; update the
exception handler inside the try/catch surrounding survey creation (the
catch(Exception e) block) to also add a failure detail to alert.details(), e.g.
call
alert.details().add(SurveyConversionAlert.SurveyDetails.failure(event.requestId()
or result.url() as appropriate, e.getMessage())) so the alert contains the
creation failure (include requestId and the exception message) and keep the
existing log call; ensure you reference the existing alert variable and use
SurveyConversionAlert.SurveyDetails.failure(...) consistent with the
success/failure usage elsewhere.
- Around line 220-230: The loop currently pairs savedInfoList and
questionUpsertInfoList by index which can mis-map options because savedInfoList
is sorted by Question.getOrder; instead, build a Map keyed by questionId from
the original questionUpsertInfoList and look up the matching originalInfo for
each savedInfo (use savedInfo.getQuestionId()) before constructing
OptionUpsertDto items — mirror the approach used in
SurveyFormFacade.buildOptionUpsertDtosFromSavedQuestions and update the code
around savedInfoList/questionUpsertInfoList usage (and the call site
upsertQuestionList/QuestionUpsertDto handling) so options are matched by
questionId rather than list index.
- Around line 60-67: The Lambda POST call in FormRequestLambda using
webClient.post().uri(lambdaUrl).bodyValue(payload).retrieve().bodyToMono(FormConversionResponse.class).block()
lacks error handling so HTTP 4xx/5xx responses throw WebClientResponseException
and skip the response == null branch (preventing
alertNotifier.sendSurveyConversionAsync from running); update this call to
handle non-2xx status with .onStatus(...) to map errors to a meaningful
FormConversionResponse or a handled exception and add .onErrorResume(...) to
catch WebClientResponseException/timeout errors and return a fallback
FormConversionResponse (or trigger alertNotifier.sendSurveyConversionAsync in
the resume path), and ensure the request uses an appropriate per-request timeout
(override the global WebClientConfig 2000ms timeout for the lambda call) so the
Lambda call has sufficient time.

In `@src/main/java/OneQ/OnSurvey/domain/survey/SurveyErrorCode.java`:
- Around line 32-33: The enum SurveyErrorCode has inconsistent error-code
naming: change the FORM_CONVERSION_FAILED enum entry in SurveyErrorCode so its
code string follows the existing pattern (use "FORM_REQUEST_400" instead of
"FORM_REQUEST_001") to match other entries like FORM_REQUEST_NOT_FOUND and HTTP
400 semantics; update only the first argument of the FORM_CONVERSION_FAILED
entry to "FORM_REQUEST_400" and keep the message and HttpStatus.BAD_REQUEST
unchanged.

In `@src/main/java/OneQ/OnSurvey/global/infra/discord/DiscordAlarmService.java`:
- Line 140: Fix the typo in the string literal used when building the alarm
message in DiscordAlarmService: replace "tittle" with "title" in the string
passed to StringBuilder (the line that calls .append("\u3000 tittle:
").append(safe(d.title())).append('\n')), so the message reads "title" while
keeping the surrounding formatting and safe(d.title()) call unchanged.
- Line 158: The error line in DiscordAlarmService (the append chain that builds
"* error: " using safe(alert.error())) is missing the opening backtick; change
the string assembly so the error text is wrapped in backticks (matching the
other alert formatting), e.g. prepend a backtick before safe(alert.error()) and
keep the closing backtick and newline; locate the append call in
DiscordAlarmService where safe(alert.error()) is used and update that append
sequence to include the opening backtick so formatting is consistent with other
alarm methods.

In
`@src/main/java/OneQ/OnSurvey/global/infra/discord/notifier/NoOpAlertNotifier.java`:
- Around line 12-17: NoOpAlertNotifier is annotated for the local profile but
still invokes the external DiscordAlarmAsyncFacade (the private final field
discord) in its methods (lines ~31-34), so remove the direct calls to discord
and replace them with a true no-op behavior (e.g., log locally or return a
completed future) inside NoOpAlertNotifier's alert methods; locate Anywhere the
class references discord (calls to discord.send/notify/execute) and replace
those invocations with non-networking stubs so local runs never transmit to the
production Discord channel.

ℹ️ Review info

Configuration used: Path: .coderabbit.yml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c2591bd and 9dd3a9d.

📒 Files selected for processing (13)
  • src/main/java/OneQ/OnSurvey/domain/survey/SurveyErrorCode.java
  • src/main/java/OneQ/OnSurvey/domain/survey/model/formRequest/FormConversionPayload.java
  • src/main/java/OneQ/OnSurvey/domain/survey/model/formRequest/FormConversionResponse.java
  • src/main/java/OneQ/OnSurvey/domain/survey/model/formRequest/event/FormRequestConversionEvent.java
  • src/main/java/OneQ/OnSurvey/domain/survey/service/formRequest/FormCommandService.java
  • src/main/java/OneQ/OnSurvey/domain/survey/service/formRequest/FormRequestLambda.java
  • src/main/java/OneQ/OnSurvey/global/infra/discord/DiscordAlarmAsyncFacade.java
  • src/main/java/OneQ/OnSurvey/global/infra/discord/DiscordAlarmService.java
  • src/main/java/OneQ/OnSurvey/global/infra/discord/notifier/AlertNotifier.java
  • src/main/java/OneQ/OnSurvey/global/infra/discord/notifier/DiscordAlertNotifier.java
  • src/main/java/OneQ/OnSurvey/global/infra/discord/notifier/NoOpAlertNotifier.java
  • src/main/java/OneQ/OnSurvey/global/infra/discord/notifier/dto/SurveyConversionAlert.java
  • src/main/java/OneQ/OnSurvey/global/infra/transaction/TransactionHandler.java

Copy link
Collaborator

@KJaeKwan KJaeKwan left a comment

Choose a reason for hiding this comment

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

확인했습니다~

@wonjuneee wonjuneee force-pushed the feat/OMF-235 branch 2 times, most recently from da71993 to 6e37565 Compare March 4, 2026 05:20
# Conflicts:
#	src/main/java/OneQ/OnSurvey/domain/question/entity/ChoiceOption.java
#	src/main/java/OneQ/OnSurvey/domain/question/entity/Question.java
#	src/main/java/OneQ/OnSurvey/domain/question/entity/question/Choice.java
#	src/main/java/OneQ/OnSurvey/domain/question/entity/question/DateAnswer.java
#	src/main/java/OneQ/OnSurvey/domain/question/entity/question/LongAnswer.java
#	src/main/java/OneQ/OnSurvey/domain/question/entity/question/NPS.java
#	src/main/java/OneQ/OnSurvey/domain/question/entity/question/NumberAnswer.java
#	src/main/java/OneQ/OnSurvey/domain/question/entity/question/Rating.java
#	src/main/java/OneQ/OnSurvey/domain/question/entity/question/ShortAnswer.java
#	src/main/java/OneQ/OnSurvey/domain/question/model/dto/type/ChoiceDto.java
#	src/main/java/OneQ/OnSurvey/domain/question/model/dto/type/DateDto.java
#	src/main/java/OneQ/OnSurvey/domain/question/model/dto/type/DefaultQuestionDto.java
#	src/main/java/OneQ/OnSurvey/domain/question/model/dto/type/RatingDto.java
#	src/main/java/OneQ/OnSurvey/domain/question/service/QuestionCommandService.java
@wonjuneee wonjuneee merged commit d6e13d2 into develop Mar 5, 2026
5 checks passed
wonjuneee added a commit that referenced this pull request Mar 5, 2026
This reverts commit d6e13d2, reversing
changes made to 4c2c611.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🌟feature 새로운 기능

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants