Skip to content

[FEATURE] 강사 대시보드 외주 조회 기능 구현#40

Merged
fervovita merged 20 commits into
devfrom
feat/#37-comission-dashboard
Jun 20, 2026
Merged

[FEATURE] 강사 대시보드 외주 조회 기능 구현#40
fervovita merged 20 commits into
devfrom
feat/#37-comission-dashboard

Conversation

@fervovita

@fervovita fervovita commented Jun 18, 2026

Copy link
Copy Markdown
Collaborator

🚀 Related issue

Closes #37

#️⃣ Summary

  • 강사 대시보드 API 구현

🔧 Changes

  • 시안 제출 현황 조회 GET /api/v1/instructors/commissions/draft-submissions
  • 매칭 중인 외주 조회 GET /api/v1/instructors/commissions/matchings
  • 수정 중인 외주 조회 GET/api/v1/instructors/commissions/revisions
  • revision_response에 강사가 수정 답변을 확인했는지 여부를 파악하기 위한 checked 필드 추가
  • commission/core의 controller/facade/service를 InstructorXXX로 변경

📸 Test Evidence

image image image

💬 Reviewer Notes

1. checked 필드

수정 중인 외주 조회의 응답에 hasUpadte가 있어서, 강사가 수정 답변을 확인했는지 여부를 트래킹하기 위해 revision_responsechecked 필드를 추가했습니다.
추후 강사가 수정 답변을 확인하는 API를 호출하면 이 필드를 true로 바꿔줘야 할 것 같습니다!

2. commission/dashboard 분리

대시보드 관련 로직을 commission/core에 위치시키게 되면, core -> application/revision 과 같이 역방향 의존성이 생기게 됩니다.
이를 피하기 위해 대시보드 관련 로직은 dashboard 패키지로 분리해 구현했습니다.

3. matched 계산

매칭 중인 외주의 matched는 지원자(디자이너)의 레벨 종류 수입니다.

CommissionApplicationRepository에서 COUNT(DISTINCT level)로 집계한 뒤, Commission.matchedCount(distinctLevelCount, applicantCount)에서 외주의 실제 모집 인원을 고려해 최종 값을 계산합니다.

PLAN: L1/L2/L3 -> matched

BASIC: 3 / 1 / 0 -> 2
MAX: 3 / 1 / 0 -> 4
MAX: 5 / 0 / 0 -> 3

위와 같이 레벨당 한자리씩 할당해놓고, 잉여 자리는 선착순으로 받도록 했습니다.

이 부분에 대해서는 테스트 코드에 작성해놨습니다.

저는 이렇게 이해했는데, 혹시나 다르게 이해하거나 이상한 부분이 있으면 편하게 말씀해주세요!!!

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 강사 대시보드 추가: 시안 제출 현황, 매칭 중인 외주, 수정 중인 외주를 한 곳에서 확인할 수 있습니다.
    • 외주별 상세 진행 상태 조회 기능 강화
  • 개선사항

    • 내부 서비스 구조 개선으로 더 안정적인 외주 관리 기능 제공

@fervovita fervovita self-assigned this Jun 18, 2026
@fervovita fervovita requested a review from Jong0128 as a code owner June 18, 2026 16:00
@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

CommissionServiceInstructorCommissionService로 전환하고, Commission.matchedCount 계산 메서드 및 RevisionResponse.checked 필드를 추가한다. DashboardCommissionRepository와 3종의 프로젝션 인터페이스를 신설하고, InstructorDashboardService 및 컨트롤러로 강사 대시보드 외주 조회 API 3개를 구현한다.

Changes

강사 대시보드 외주 조회 기능 구현

Layer / File(s) Summary
CommissionService → InstructorCommissionService 전환
...core/service/InstructorCommissionService.java, ...core/facade/InstructorCommissionFacade.java, ...core/controller/InstructorCommissionController.java, ...draft/facade/DraftFacade.java, ...draft/service/DraftService.java
CommissionService 클래스명이 InstructorCommissionService로 변경되고, Facade·Controller·DraftFacade·DraftService의 주입 필드 타입과 메서드 호출 대상이 모두 InstructorCommissionService로 교체된다.
Commission.matchedCount 계산 로직 및 RevisionResponse.checked 필드
...core/entity/Commission.java, ...revision/entity/RevisionResponse.java, ...core/entity/CommissionTest.java
CommissiongetDesignerCount()matchedCount(distinctLevels, totalApplicants) 메서드가 추가되고, RevisionResponsechecked 불리언 컬럼(기본값 false)이 추가된다. CommissionTest에서 경계값 파라미터화 테스트로 matchedCount를 검증한다.
대시보드 프로젝션 인터페이스 및 DashboardCommissionRepository
...dashboard/repository/projection/DraftSubmissionView.java, ...MatchingView.java, ...RevisingView.java, ...dashboard/repository/DashboardCommissionRepository.java
DraftSubmissionView, MatchingView, RevisingView 프로젝션 인터페이스가 추가되고, DashboardCommissionRepository에 시안 제출 건수 카운팅·level distinct/total 집계·submitted/hasUpdated 불리언 산출 JPQL 쿼리 3개가 정의된다.
대시보드 응답 DTO 3종
...dashboard/dto/response/DraftSubmissionCommissionResponse.java, ...MatchingCommissionResponse.java, ...RevisingCommissionResponse.java
DraftSubmissionCommissionResponse, MatchingCommissionResponse, RevisingCommissionResponse 레코드 DTO와 각각의 중첩 레코드가 추가된다. 각 DTO의 of(...) 팩토리 메서드는 프로젝션 view 리스트를 CommissionItem 리스트로 스트림 변환한다.
InstructorDashboardService, 컨트롤러 및 테스트
...dashboard/service/InstructorDashboardService.java, ...dashboard/controller/InstructorDashboardController.java, ...InstructorDashboardServiceTest.java
InstructorDashboardServiceDashboardCommissionRepositoryfind*Views 메서드를 호출해 응답 DTO로 변환하며, InstructorDashboardController/api/v1/instructors/dashboards 하위에 3개 GET 엔드포인트를 노출한다. InstructorDashboardServiceTest에서 getMatchingCommissions의 계산 결과를 Mockito로 검증한다.

Sequence Diagram(s)

sequenceDiagram
  actor Instructor
  participant InstructorDashboardController
  participant InstructorDashboardService
  participant DashboardCommissionRepository
  participant Commission

  rect rgba(70, 130, 180, 0.5)
    Note over Instructor,Commission: 매칭 중인 외주 조회
    Instructor->>InstructorDashboardController: GET /api/v1/instructors/dashboards/matchings
    InstructorDashboardController->>InstructorDashboardService: getMatchingCommissions(instructorId)
    InstructorDashboardService->>DashboardCommissionRepository: findMatchingViews(instructorId, RECRUITING, PENDING)
    DashboardCommissionRepository-->>InstructorDashboardService: List~MatchingView~(commission, distinctLevelCount, totalCount)
    InstructorDashboardService->>Commission: matchedCount(distinctLevels, totalApplicants)
    Commission-->>InstructorDashboardService: matched int
    InstructorDashboardService-->>InstructorDashboardController: MatchingCommissionResponse
    InstructorDashboardController-->>Instructor: ApiResponse(MatchingCommissionResponse)
  end

  rect rgba(60, 179, 113, 0.5)
    Note over Instructor,Commission: 수정 중인 외주 조회
    Instructor->>InstructorDashboardController: GET /api/v1/instructors/dashboards/revisions
    InstructorDashboardController->>InstructorDashboardService: getRevisingCommissions(instructorId)
    InstructorDashboardService->>DashboardCommissionRepository: findRevisingViews(instructorId, EDITING)
    DashboardCommissionRepository-->>InstructorDashboardService: List~RevisingView~(commission, submitted, hasUpdated)
    InstructorDashboardService-->>InstructorDashboardController: RevisingCommissionResponse
    InstructorDashboardController-->>Instructor: ApiResponse(RevisingCommissionResponse)
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Ditda-Official/Ditda-Backend#34: CommissionFacade / CommissionController / CommissionService 도입 PR로, 이번 PR에서 동일한 클래스들을 InstructorCommission*으로 전환하는 직접적인 선행 작업이다.

Suggested reviewers

  • Jong0128
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 31.82% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Out of Scope Changes check ❓ Inconclusive 일부 변경사항이 명시된 이슈 범위를 벗어나 있습니다. InstructorCommissionService/Facade 리팩토링, Commission 헬퍼 메서드 추가, RevisionResponse.checked 필드 추가 등이 대시보드 기능과 직접적 관계가 명확하지 않습니다. 각 변경사항이 대시보드 기능 구현과 어떤 의존성을 가지는지 명시하거나, 별도 이슈로 분리하는 것을 권장합니다.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목은 강사 대시보드 외주 조회 기능 구현이라는 주요 변경사항을 명확하고 간결하게 요약하고 있습니다.
Linked Issues check ✅ Passed PR의 모든 코드 변경사항이 #37 이슈의 세 가지 목표를 충족합니다: 시안 제출 현황, 매칭 중인 외주, 수정 중인 외주 조회 기능이 각각 구현되었습니다.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/#37-comission-dashboard

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 8

🧹 Nitpick comments (1)
src/main/java/ditda/backend/domain/commission/dashboard/dto/response/RevisingCommissionResponse.java (1)

16-22: 💤 Low value

Map 조회 결과에 대한 방어적 처리를 고려해보세요.

18번 라인에서 statuses.get(c.getId())null을 반환할 경우 CommissionItem.from에서 NPE가 발생할 수 있습니다.

현재 RevisionService.getRevisionStatuses가 누락된 ID를 new RevisionStatus(false, false)로 채워주지만(Context snippet 참조), DTO 레이어에서도 방어적 처리를 추가하면 향후 상위 계약 변경 시에도 안전합니다.

♻️ 방어적 코드 제안
 	public static RevisingCommissionResponse of(List<Commission> commissions, Map<Long, RevisionStatus> statuses) {
 		List<CommissionItem> items = commissions.stream()
-			.map(c -> CommissionItem.from(c, statuses.get(c.getId())))
+			.map(c -> CommissionItem.from(c, 
+				statuses.getOrDefault(c.getId(), new RevisionStatus(false, false))))
 			.toList();

 		return new RevisingCommissionResponse(items);
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/java/ditda/backend/domain/commission/dashboard/dto/response/RevisingCommissionResponse.java`
around lines 16 - 22, In the of method of RevisingCommissionResponse class, the
call to statuses.get(c.getId()) can return null, which would then be passed to
CommissionItem.from() and cause a NullPointerException. Replace the direct
statuses.get(c.getId()) call with a null-safe approach such as
statuses.getOrDefault(c.getId(), new RevisionStatus(false, false)) to provide a
default RevisionStatus when the ID is not found in the map, ensuring the DTO
layer has defensive handling regardless of upstream changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@src/main/java/ditda/backend/domain/commission/application/service/CommissionApplicationService.java`:
- Around line 54-56: The Collectors.toMap method used in the return statement of
the stream operation does not specify a merge function to handle duplicate keys,
which causes an IllegalStateException when commissionIds contains duplicates.
Modify the Collectors.toMap call to include a third parameter that provides a
merge function to handle key collisions, such as keeping the existing value or
applying a merge strategy that makes sense for the countByCommissionId data.

In
`@src/main/java/ditda/backend/domain/commission/dashboard/controller/InstructorDashboardController.java`:
- Around line 17-53: The InstructorDashboardController endpoints
(getDraftSubmissions, getMatchingCommissions, and getRevisingCommissions)
currently lack explicit role-based access control annotations. Add
`@PreAuthorize`("hasRole('INSTRUCTOR')") annotation either at the class level
above the InstructorDashboardController declaration to secure all endpoints at
once, or add the annotation individually to each endpoint method. This ensures
that only users with the ROLE_INSTRUCTOR role can access these dashboard API
endpoints, making the authorization requirement explicit and enforced at the
method level.

In
`@src/main/java/ditda/backend/domain/commission/dashboard/dto/response/DraftSubmissionCommissionResponse.java`:
- Around line 20-25: The Map#get calls for draftSubmissionCount.get(c.getId())
and viewable.get(c.getId()) in the CommissionItem.from() method invocation can
return null values, and these nulls are being unboxed into primitive types which
causes a NullPointerException. Replace the direct Map#get calls with either
Map#getOrDefault providing appropriate default values (such as 0 for long and
false for boolean), or wrap the get results with null-checking logic to ensure
primitive type safety when assembling the response.

In
`@src/main/java/ditda/backend/domain/commission/dashboard/service/InstructorDashboardService.java`:
- Around line 89-95: The stream operation collecting commissions into the
matchedCount map is vulnerable to NullPointerException because the get() calls
on distinctLevelCount and applicantCount maps can return null before calling
intValue(). Add null checks or use getOrDefault() with appropriate default
values when retrieving from these maps in the Commission::matchedCount method
call. Alternatively, verify that the aggregation methods used to populate
distinctLevelCount and applicantCount (likely from CommissionApplicationService)
guarantee entries exist for all commission IDs in the commissions list, and if
not, filter the commissions stream to only include IDs that exist in both maps.

In
`@src/main/java/ditda/backend/domain/commission/revision/entity/RevisionResponse.java`:
- Around line 43-45: The `checked` field in the RevisionResponse entity is being
added as a NOT NULL column, but the `@Builder.Default` annotation only provides a
default at the Java level and will not apply to existing database rows, causing
schema migration to fail if the table already contains data. To fix this, add a
columnDefinition parameter to the `@Column` annotation on the `checked` field that
explicitly defines the database-level default value (e.g., "BOOLEAN NOT NULL
DEFAULT FALSE"), or alternatively verify and document that the
revision_responses table will be empty at deployment time to ensure the NOT NULL
constraint can be safely applied.

In
`@src/main/java/ditda/backend/domain/commission/revision/repository/RevisionRequestRepository.java`:
- Around line 14-23: The submitted flag calculation in the findRevisionStatuses
method has inverted logic that contradicts both the comment and the API
specification. The current CASE expression for submitted returns true when
responses are absent (resp.id IS NULL), but according to the comment and
downstream API contract, it should return false when there are no responses.
Invert the CASE condition for the submitted calculation: change it to return
false when COUNT of null response IDs is greater than 0, and true otherwise, so
that submitted=false indicates no responses have been made.

In
`@src/test/java/ditda/backend/domain/commission/dashboard/service/InstructorDashboardServiceTest.java`:
- Around line 91-92: The mock setup for
commissionService.getCommissionByInstructorAndStatus at line 91-92 is using null
for the third parameter, but the actual service call in the code being tested
uses Sort.by("applicationDeadline").ascending(). Update the given() statement to
pass Sort.by("applicationDeadline").ascending() as the third argument instead of
null to match the actual invocation made by the service under test.
- Around line 60-61: The test mock setup for
commissionService.getCommissionByInstructorAndStatus is passing null as the
third parameter, but the actual InstructorDashboardService implementation passes
Sort.by("applicationDeadline").ascending() as the third parameter, causing a
Mockito PotentialStubbingProblem. Update the given() stub configuration to use
Sort.by("applicationDeadline").ascending() instead of null as the third argument
to commissionService.getCommissionByInstructorAndStatus so the mock matches the
actual service behavior.

---

Nitpick comments:
In
`@src/main/java/ditda/backend/domain/commission/dashboard/dto/response/RevisingCommissionResponse.java`:
- Around line 16-22: In the of method of RevisingCommissionResponse class, the
call to statuses.get(c.getId()) can return null, which would then be passed to
CommissionItem.from() and cause a NullPointerException. Replace the direct
statuses.get(c.getId()) call with a null-safe approach such as
statuses.getOrDefault(c.getId(), new RevisionStatus(false, false)) to provide a
default RevisionStatus when the ID is not found in the map, ensuring the DTO
layer has defensive handling regardless of upstream changes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro Plus

Run ID: 08b2a9ab-51c6-4d6f-a4c1-26d5b854fe20

📥 Commits

Reviewing files that changed from the base of the PR and between 382f6d0 and 80cd326.

📒 Files selected for processing (22)
  • src/main/java/ditda/backend/domain/commission/application/repository/CommissionApplicationRepository.java
  • src/main/java/ditda/backend/domain/commission/application/repository/projection/ApplicationSubmissionCount.java
  • src/main/java/ditda/backend/domain/commission/application/service/CommissionApplicationService.java
  • src/main/java/ditda/backend/domain/commission/core/controller/InstructorCommissionController.java
  • src/main/java/ditda/backend/domain/commission/core/entity/Commission.java
  • src/main/java/ditda/backend/domain/commission/core/facade/InstructorCommissionFacade.java
  • src/main/java/ditda/backend/domain/commission/core/repository/CommissionRepository.java
  • src/main/java/ditda/backend/domain/commission/core/service/InstructorCommissionService.java
  • src/main/java/ditda/backend/domain/commission/dashboard/controller/InstructorDashboardController.java
  • src/main/java/ditda/backend/domain/commission/dashboard/dto/response/DraftSubmissionCommissionResponse.java
  • src/main/java/ditda/backend/domain/commission/dashboard/dto/response/MatchingCommissionResponse.java
  • src/main/java/ditda/backend/domain/commission/dashboard/dto/response/RevisingCommissionResponse.java
  • src/main/java/ditda/backend/domain/commission/dashboard/service/InstructorDashboardService.java
  • src/main/java/ditda/backend/domain/commission/draft/facade/DraftFacade.java
  • src/main/java/ditda/backend/domain/commission/draft/service/DraftService.java
  • src/main/java/ditda/backend/domain/commission/revision/dto/RevisionStatus.java
  • src/main/java/ditda/backend/domain/commission/revision/entity/RevisionResponse.java
  • src/main/java/ditda/backend/domain/commission/revision/repository/RevisionRequestRepository.java
  • src/main/java/ditda/backend/domain/commission/revision/repository/projection/RevisionStatusView.java
  • src/main/java/ditda/backend/domain/commission/revision/service/RevisionService.java
  • src/test/java/ditda/backend/domain/commission/core/entity/CommissionTest.java
  • src/test/java/ditda/backend/domain/commission/dashboard/service/InstructorDashboardServiceTest.java

@Ditda-Official Ditda-Official deleted a comment from coderabbitai Bot Jun 18, 2026

@Jong0128 Jong0128 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

수고많으셨습니다!! 👍
아래 커멘트 확인 부탁드립니다 😄

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/main/java/ditda/backend/domain/commission/dashboard/dto/response/MatchingCommissionResponse.java (1)

40-43: ⚡ Quick win

카운트 다운캐스팅은 안전 변환으로 바꾸는 것을 권장합니다.

Line 40-43의 intValue()는 overflow 시 값이 조용히 깨질 수 있습니다. Math.toIntExact(...)로 fail-fast 처리하는 편이 안전합니다.

변경 예시
-			int matched = commission.matchedCount(
-				view.getDistinctLevelCount().intValue(),
-				view.getTotalCount().intValue()
-			);
+			int matched = commission.matchedCount(
+				Math.toIntExact(view.getDistinctLevelCount()),
+				Math.toIntExact(view.getTotalCount())
+			);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/java/ditda/backend/domain/commission/dashboard/dto/response/MatchingCommissionResponse.java`
around lines 40 - 43, The code in the matchedCount() method call uses intValue()
to convert values to int, which can silently overflow and corrupt data. Replace
both intValue() calls with Math.toIntExact() instead - specifically on
view.getDistinctLevelCount().intValue() and view.getTotalCount().intValue()
arguments passed to commission.matchedCount(). This ensures overflow conditions
throw an exception immediately rather than silently wrapping the values.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@src/main/java/ditda/backend/domain/commission/dashboard/dto/response/MatchingCommissionResponse.java`:
- Around line 40-43: The code in the matchedCount() method call uses intValue()
to convert values to int, which can silently overflow and corrupt data. Replace
both intValue() calls with Math.toIntExact() instead - specifically on
view.getDistinctLevelCount().intValue() and view.getTotalCount().intValue()
arguments passed to commission.matchedCount(). This ensures overflow conditions
throw an exception immediately rather than silently wrapping the values.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro Plus

Run ID: 9c2e5777-5912-487b-ba49-088a8b356d3c

📥 Commits

Reviewing files that changed from the base of the PR and between 80cd326 and d362da8.

📒 Files selected for processing (11)
  • src/main/java/ditda/backend/domain/commission/core/service/InstructorCommissionService.java
  • src/main/java/ditda/backend/domain/commission/dashboard/controller/InstructorDashboardController.java
  • src/main/java/ditda/backend/domain/commission/dashboard/dto/response/DraftSubmissionCommissionResponse.java
  • src/main/java/ditda/backend/domain/commission/dashboard/dto/response/MatchingCommissionResponse.java
  • src/main/java/ditda/backend/domain/commission/dashboard/dto/response/RevisingCommissionResponse.java
  • src/main/java/ditda/backend/domain/commission/dashboard/repository/DashboardCommissionRepository.java
  • src/main/java/ditda/backend/domain/commission/dashboard/repository/projection/DraftSubmissionView.java
  • src/main/java/ditda/backend/domain/commission/dashboard/repository/projection/MatchingView.java
  • src/main/java/ditda/backend/domain/commission/dashboard/repository/projection/RevisingView.java
  • src/main/java/ditda/backend/domain/commission/dashboard/service/InstructorDashboardService.java
  • src/test/java/ditda/backend/domain/commission/dashboard/service/InstructorDashboardServiceTest.java
💤 Files with no reviewable changes (1)
  • src/main/java/ditda/backend/domain/commission/core/service/InstructorCommissionService.java
✅ Files skipped from review due to trivial changes (1)
  • src/main/java/ditda/backend/domain/commission/dashboard/repository/projection/MatchingView.java

@Jong0128

Copy link
Copy Markdown
Collaborator

까먹고 approve를 안했네요 ^^;;
merge 해도 좋을꺼같습니다!!

@fervovita fervovita merged commit 49c9b52 into dev Jun 20, 2026
2 checks passed
@fervovita fervovita deleted the feat/#37-comission-dashboard branch June 20, 2026 07:50
@fervovita fervovita mentioned this pull request Jun 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] 강사 대시보드 외주 조회 기능 구현

2 participants