부모 티켓
1개 티켓

백로그

0
티켓 없음

할 일

1
높음 614a8fe8
서브 티켓 [조직문화 PR2] 서비스: 설문 생성/응답 제출/결과 집계

EngagementSurveys 서비스 3개 TDD 구현

## 작업 내용: 3개 서비스 객체 구현 ### 참조 스킬 - `.claude/skills/service-objects/SKILL.md` — Result 패턴, 네이밍 컨벤션 - `.claude/skills/rails-testing/SKILL.md` — Minitest 테스트 패턴 ### 기존 코드 참조 (반드시 읽기) - `app/services/diagnosis/scoring/engagement_calculator.rb` — 기존 채점 로직 (FACTOR_DIMENSION_MAP 등) - `app/services/diagnosis/engagement_result_formatter.rb` — 결과 포맷 - `app/services/diagnosis/score_calculator_factory.rb` — 팩토리 - `app/models/workspace_engagement_survey.rb` — PR1에서 생성한 모델 - `app/models/diagnosis_session.rb` — DiagnosisSession 구조 - `db/seeds/engagement/engagement_questions_b2b.csv` — B2B 10문항 구조 ### 1. EngagementSurveys::CreateService 파일: `app/services/engagement_surveys/create_service.rb` ```ruby # 호출: EngagementSurveys::CreateService.call(workspace:, user:, year:, quarter:) # 반환: Result (success/failure) ``` - workspace + year + quarter로 WorkspaceEngagementSurvey 생성 - access_token은 모델에서 자동 생성 - 동일 workspace+year+quarter 중복 시 실패 반환 - title은 자동 생성: "#{year} Q#{quarter}" ### 2. EngagementSurveys::SubmitResponseService 파일: `app/services/engagement_surveys/submit_response_service.rb` ```ruby # 호출: EngagementSurveys::SubmitResponseService.call( # survey:, workspace_group:, responses:, user: nil # ) # responses: [{ question_no: 1, dimension: "belonging", factor: "psychological_safety", value: 5 }, ...] # 반환: Result (success/failure) ``` - DiagnosisSession을 생성하여 응답 저장 - context_type: "b2b" - workspace_engagement_survey_id: survey.id - workspace_group_id: workspace_group.id - user_id: user&.id (로그인 시 참고용, nil 허용) - scoring_framework: "engagement_3factor" - 설문이 active 상태가 아니면 실패 반환 - responses를 DiagnosisSession의 response_data(또는 적절한 필드)에 저장 - 기존 EngagementCalculator로 채점하여 결과 저장 - 주의: 기존 DiagnosisSession이 어떤 필드에 응답/결과를 저장하는지 확인 후 동일 패턴 사용 ### 3. EngagementSurveys::ResultAggregator 파일: `app/services/engagement_surveys/result_aggregator.rb` ```ruby # 호출: EngagementSurveys::ResultAggregator.call(survey:, group: nil) # group이 nil이면 전체 집계, 있으면 해당 그룹만 # 반환: Result with data: # { # total_responses: Integer, # overall_score: Float, # 10번 문항(overall) 전체 평균 # engagement_types: { # 10번 문항 기준 비율 # active: Float, # 6,7점 비율 (%) # passive: Float, # 4,5점 비율 (%) # disengaged: Float # 1,2,3점 비율 (%) # }, # factor_scores: { # 3요인 평균 # psychological_safety: Float, # self_efficacy: Float, # flow_experience: Float # }, # dimension_scores: { # 9요인 평균 # belonging: Float, autonomy: Float, meaning: Float, # recognition: Float, achievement: Float, growth: Float, # vitality: Float, strength_use: Float, positive_affect: Float # }, # group_results: [ # 그룹별 결과 (group이 nil일 때) # { group: WorkspaceGroup, ...위와 동일 구조... } # 3명 이하는 nil # ] # } ``` - 해당 survey의 모든 DiagnosisSession을 조회 - 3명 이하 그룹은 결과를 nil로 반환 (insufficient_responses: true 표시) - overall_score: 각 세션의 overall(10번 문항) 점수 평균 - engagement_types: overall 문항 기준 6,7점=active / 4,5점=passive / 1,2,3점=disengaged 비율 - factor_scores: 3요인별 평균 (EngagementCalculator의 FACTOR_DIMENSION_MAP 참조) - dimension_scores: 9개 dimension별 평균 - 강약점: 가장 높은/낮은 factor, dimension 표시 ### 테스트 - `test/services/engagement_surveys/create_service_test.rb` - 정상 생성, 중복 방지, 필수 필드 누락 - `test/services/engagement_surveys/submit_response_service_test.rb` - 정상 응답 저장, 비활성 설문 거부, user_id 기록, 채점 결과 확인 - `test/services/engagement_surveys/result_aggregator_test.rb` - 전체 집계, 그룹별 집계, 3명 이하 필터링, 몰입 유형 비율, 3요인/9요인 분석 ## 중요 사항 - 모든 rails 명령은 `docker compose exec web` 으로 실행 - TDD: 테스트 먼저 작성 → 구현 - 기존 EngagementCalculator 로직을 최대한 재사용 - Result 패턴 사용 (service-objects 스킬 참조)

D
developer-1
4 months

진행 중

0
티켓 없음

리뷰

0
티켓 없음

완료 (전체)

0
티켓 없음