Skip to content

fix/student sync#166

Merged
play-ancora-gyungmin merged 4 commits intodevfrom
fix/student-sync
Mar 10, 2026
Merged

fix/student sync#166
play-ancora-gyungmin merged 4 commits intodevfrom
fix/student-sync

Conversation

@play-ancora-gyungmin
Copy link
Contributor

@play-ancora-gyungmin play-ancora-gyungmin commented Mar 10, 2026

🔗 관련 이슈

  • Closes #이슈번호

✨ 변경 사항

이번 PR에서 변경된 내용을 간단히 설명해주세요.

  • 강사 수업 개설 중 학생 등록시 앱 학생과 앱 학부모 유저를 연결하도록 수정
  • 기타 연결로직 보강

🧪 테스트 방법

리뷰어가 어떻게 테스트하면 되는지 적어주세요.

  • 로컬에서 페이지 접속
  • 주요 기능 동작 확인

📸 스크린샷 (선택)

UI 변경이 있다면 첨부해주세요.

✅ 체크리스트

  • CI 통과
  • lint / type-check 통과
  • 관련 이슈와 연결됨
  • 불필요한 코드 제거

Summary by CodeRabbit

Release Notes

  • New Features

    • Automatic linking of student and parent information during enrollment creation
    • Enhanced enrollment reuse with automatic connection of previously unlinked student and parent records
  • Tests

    • Added comprehensive test coverage for enrollment linking and matching scenarios
  • Chores

    • Updated configuration files

@coderabbitai
Copy link

coderabbitai bot commented Mar 10, 2026

📝 Walkthrough

Walkthrough

This change extends enrollment and lecture enrollment creation flows with automatic student and parent linking capabilities. When creating enrollments, the system now resolves missing student and parent-link IDs by querying repositories with phone, name, and parent phone criteria, either updating existing enrollments or creating new ones with these associations established.

Changes

Cohort / File(s) Summary
Configuration & Dependencies
.gitignore, src/config/container.config.ts
Added .omx ignore rule and injected studentRepo and parentChildLinkRepo into LecturesService constructor.
Repository Layer
src/repos/enrollments.repo.ts
Updated updateAppParentLinkIdByStudentPhone method signature to accept studentName and parentPhoneNumber parameters, expanding query filtering to match on all three criteria instead of phone alone.
Enrollment Service
src/services/enrollments.service.ts
Implements dual-path enrollment creation: attempts to locate and update existing enrollments with missing app-level links via new resolveStudentId and resolveParentLinkId helpers, or creates new enrollments if none exist.
Lectures Service
src/services/lectures.service.ts
Adds student and parent-link repository integration to LecturesService constructor and implements parallel resolution of student and parent IDs during enrollment processing for both existing and new enrollment paths.
Parent Service
src/services/parents.service.ts
Added parent profile retrieval during child registration with error handling; now passes parent name and phone number when updating enrollment parent links.
Service Tests
src/services/enrollments.service.test.ts, src/services/lectures.service.test.ts
Added 155 and 134 lines of unit tests respectively, covering automatic app-level linking, existing enrollment reuse scenarios, and new repository/fixture mocks.
Parent Service Tests
src/services/parents.service.test.ts
Updated test mocks to resolve parent data and assertions to verify propagation of child name and parent phone to repository update calls.

Sequence Diagrams

sequenceDiagram
    participant Client
    participant EnrollmentService
    participant EnrollmentRepo
    participant StudentRepo
    participant ParentChildLinkRepo
    
    Client->>EnrollmentService: createEnrollment(request)
    
    activate EnrollmentService
    EnrollmentService->>EnrollmentRepo: findManyByInstructorAndPhones
    activate EnrollmentRepo
    EnrollmentRepo-->>EnrollmentService: existingEnrollment?
    deactivate EnrollmentRepo
    
    alt Existing Enrollment Found
        EnrollmentService->>StudentRepo: findByPhoneNameParentPhone (if appStudentId null)
        activate StudentRepo
        StudentRepo-->>EnrollmentService: student
        deactivate StudentRepo
        
        EnrollmentService->>ParentChildLinkRepo: findByPhoneNameParentPhone (if appParentLinkId null)
        activate ParentChildLinkRepo
        ParentChildLinkRepo-->>EnrollmentService: parentLink
        deactivate ParentChildLinkRepo
        
        EnrollmentService->>EnrollmentRepo: updateEnrollment with appStudentId/appParentLinkId
        activate EnrollmentRepo
        EnrollmentRepo-->>EnrollmentService: updated
        deactivate EnrollmentRepo
    else No Existing Enrollment
        par StudentId Resolution
            EnrollmentService->>StudentRepo: findByPhoneNameParentPhone
            activate StudentRepo
            StudentRepo-->>EnrollmentService: student
            deactivate StudentRepo
        and ParentLinkId Resolution
            EnrollmentService->>ParentChildLinkRepo: findByPhoneNameParentPhone
            activate ParentChildLinkRepo
            ParentChildLinkRepo-->>EnrollmentService: parentLink
            deactivate ParentChildLinkRepo
        end
        
        EnrollmentService->>EnrollmentRepo: createEnrollment with resolved IDs
        activate EnrollmentRepo
        EnrollmentRepo-->>EnrollmentService: newEnrollment
        deactivate EnrollmentRepo
    end
    
    EnrollmentService-->>Client: enrollment
    deactivate EnrollmentService
Loading
sequenceDiagram
    participant Client
    participant LecturesService
    participant StudentRepo
    participant ParentChildLinkRepo
    participant EnrollmentRepo
    
    Client->>LecturesService: createLectureEnrollments(request)
    
    activate LecturesService
    
    alt Existing Enrollment with Missing Links
        LecturesService->>StudentRepo: findByPhoneNameParentPhone (if appStudentId null)
        activate StudentRepo
        StudentRepo-->>LecturesService: student
        deactivate StudentRepo
        
        LecturesService->>ParentChildLinkRepo: findByPhoneNameParentPhone (if appParentLinkId null)
        activate ParentChildLinkRepo
        ParentChildLinkRepo-->>LecturesService: parentLink
        deactivate ParentChildLinkRepo
        
        LecturesService->>EnrollmentRepo: updateEnrollment
        activate EnrollmentRepo
        EnrollmentRepo-->>LecturesService: updated
        deactivate EnrollmentRepo
    else New Enrollment
        par Parallel Resolution
            LecturesService->>StudentRepo: findByPhoneNameParentPhone
            activate StudentRepo
            StudentRepo-->>LecturesService: student
            deactivate StudentRepo
        and
            LecturesService->>ParentChildLinkRepo: findByPhoneNameParentPhone
            activate ParentChildLinkRepo
            ParentChildLinkRepo-->>LecturesService: parentLink
            deactivate ParentChildLinkRepo
        end
        
        LecturesService->>EnrollmentRepo: createEnrollment with resolved IDs
        activate EnrollmentRepo
        EnrollmentRepo-->>LecturesService: newEnrollment
        deactivate EnrollmentRepo
    end
    
    LecturesService-->>Client: lectureEnrollment
    deactivate LecturesService
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Poem

🐰 A rabbit hops through enrollments with glee,
Linking students and parents automatically!
No more missing connections in sight,
Dual paths resolve everything just right,
Hoppy updating, fresh creation—
The enrollment linking sensation! 🎓✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'fix/student sync' is vague and generic, using non-descriptive terms that don't convey meaningful information about the specific changes, which involve student linking logic, enrollment updates, and repository integration. Revise the title to be more descriptive and specific, such as 'Link app students and parents during enrollment creation' or 'Sync student and parent links in lecture enrollment flow'.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/student-sync

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


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

🧹 Nitpick comments (2)
src/services/parents.service.test.ts (1)

65-149: Add a failure test for missing parent in registerChild.

Line [78] and Line [127] cover success lookup, but the new NotFound branch is not locked by tests. Add one case where mockParentRepo.findById returns null and assert NotFoundException.

🧪 Suggested test case
+    it('학부모 프로필이 없으면 NotFoundException을 던진다', async () => {
+      mockParentChildLinkRepo.findByParentIdAndPhoneNumber.mockResolvedValue(null);
+      mockParentRepo.findById.mockResolvedValue(null);
+      (mockPrisma.$transaction as jest.Mock).mockImplementation(async (fn) =>
+        fn(mockPrisma),
+      );
+
+      await expect(
+        parentsService.registerChild(UserType.PARENT, parentId, childData),
+      ).rejects.toThrow(NotFoundException);
+    });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/services/parents.service.test.ts` around lines 65 - 149, The tests lack a
negative case for parentsService.registerChild when the parent record is
missing; add a new unit test that mocks mockParentRepo.findById to resolve to
null, then call parentsService.registerChild(UserType.PARENT, parentId,
childData) and assert it throws a NotFoundException (or the service's specific
error type). Ensure other dependencies
(mockParentChildLinkRepo.findByParentIdAndPhoneNumber) are set to avoid
short-circuiting, and verify the exception is thrown rather than any successful
create or transaction; reference parentsService.registerChild,
mockParentRepo.findById, mockParentChildLinkRepo.findByParentIdAndPhoneNumber,
and NotFoundException in the test.
src/services/lectures.service.test.ts (1)

231-292: Consider a regression test for duplicate phone with different profile fields.

This block covers missing-link backfill well. Add one case with same studentPhone but different studentName/parentPhone to ensure reuse logic does not target the wrong enrollment.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/services/lectures.service.test.ts` around lines 231 - 292, Add a
regression test that ensures reuse logic ignores enrollments that match only on
studentPhone but have different studentName or parentPhone: create an
existingEnrollment returned by mockEnrollmentsRepo.findManyByInstructorAndPhones
with the same studentPhone but different studentName and/or parentPhone and null
app links, call lecturesService.createLecture with an enrollmentRequest that has
the same phone but different profile fields, then assert
mockEnrollmentsRepo.update is NOT called for that existingEnrollment and
mockEnrollmentsRepo.createMany is called to create a new enrollment; reference
lecturesService.createLecture,
mockEnrollmentsRepo.findManyByInstructorAndPhones, mockEnrollmentsRepo.update
and mockEnrollmentsRepo.createMany when adding the new test.
🤖 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/services/enrollments.service.ts`:
- Around line 140-150: The code currently takes the first match from
enrollmentsRepository.findManyByInstructorAndPhones and reuses it
(existingEnrollments[0]), which can pick the wrong record for shared phones;
instead, in the block that sets enrollmentId/existingEnrollment, perform a
profile-aware selection: search existingEnrollments for an exact match on a
unique student identifier from the incoming data (e.g., data.studentId) or, if
unavailable, match on additional profile fields (email, fullName) before reusing
an enrollment; only set enrollmentId to an existing record if one matches those
profile fields—otherwise create a new enrollment (or return a conflict) to avoid
updating the wrong record. Ensure changes are applied where
enrollmentsRepository.findManyByInstructorAndPhones is consumed and where
enrollmentId/existingEnrollment are assigned.

In `@src/services/lectures.service.ts`:
- Around line 175-199: The code currently uses phone-only lookup when deciding
connections (see connectionData, resolveStudentId, resolveParentLinkId,
existing, enrollmentReq, enrollmentsRepository.update), which can attach the
wrong profile if studentPhone is duplicated; change the resolver calls to use a
composite key (studentPhone + studentName + parentPhone) — either extend
resolveStudentId/resolveParentLinkId to accept and match that composite tuple or
add new helper functions (e.g., resolveStudentIdByCompositeKey /
resolveParentLinkIdByCompositeKey) that perform lookups using all three fields
from enrollmentReq before setting connectionData, and then proceed to call
enrollmentsRepository.update only when the composite match is found.

---

Nitpick comments:
In `@src/services/lectures.service.test.ts`:
- Around line 231-292: Add a regression test that ensures reuse logic ignores
enrollments that match only on studentPhone but have different studentName or
parentPhone: create an existingEnrollment returned by
mockEnrollmentsRepo.findManyByInstructorAndPhones with the same studentPhone but
different studentName and/or parentPhone and null app links, call
lecturesService.createLecture with an enrollmentRequest that has the same phone
but different profile fields, then assert mockEnrollmentsRepo.update is NOT
called for that existingEnrollment and mockEnrollmentsRepo.createMany is called
to create a new enrollment; reference lecturesService.createLecture,
mockEnrollmentsRepo.findManyByInstructorAndPhones, mockEnrollmentsRepo.update
and mockEnrollmentsRepo.createMany when adding the new test.

In `@src/services/parents.service.test.ts`:
- Around line 65-149: The tests lack a negative case for
parentsService.registerChild when the parent record is missing; add a new unit
test that mocks mockParentRepo.findById to resolve to null, then call
parentsService.registerChild(UserType.PARENT, parentId, childData) and assert it
throws a NotFoundException (or the service's specific error type). Ensure other
dependencies (mockParentChildLinkRepo.findByParentIdAndPhoneNumber) are set to
avoid short-circuiting, and verify the exception is thrown rather than any
successful create or transaction; reference parentsService.registerChild,
mockParentRepo.findById, mockParentChildLinkRepo.findByParentIdAndPhoneNumber,
and NotFoundException in the test.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 92629bfb-b7bc-413a-a560-dbad9a4db391

📥 Commits

Reviewing files that changed from the base of the PR and between 6f8810e and 5bbf9da.

📒 Files selected for processing (9)
  • .gitignore
  • src/config/container.config.ts
  • src/repos/enrollments.repo.ts
  • src/services/enrollments.service.test.ts
  • src/services/enrollments.service.ts
  • src/services/lectures.service.test.ts
  • src/services/lectures.service.ts
  • src/services/parents.service.test.ts
  • src/services/parents.service.ts

@play-ancora-gyungmin play-ancora-gyungmin merged commit cad260e into dev Mar 10, 2026
2 checks passed
@play-ancora-gyungmin play-ancora-gyungmin deleted the fix/student-sync branch March 10, 2026 16:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

BE 백엔드라벨 Feature

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants