Repository navigation
Closed
Labels
Description
어떤 기능인가요?
추가하려는 기능에 대해 간결하게 설명해주세요
운영진 콘솔에서 사물함 신청 현황을 보고, 잘못된 신청을 취소하고, 학생에게 사물함을 직접 배정하는 관리자 API를 추가한다. #146(상태 일괄 변경)에 이어지는 사물함 관리자 API의 네 번째 작업이다.
GET /v1/admin/lockers/applications— 회차 기준 신청 현황, 이름·학번 키워드 검색, 페이징DELETE /v1/admin/lockers/applications/{lockerApplicationId}— 신청 취소POST /v1/admin/lockers/applications— 수동 배정
지금은 누가 어느 칸을 썼는지 볼 방법도, 잘못 들어간 신청을 되돌릴 방법도 DB 직접 수정뿐이다.
핵심 제약은 locker_applications에 취소를 표현할 방법이 없다는 것이다. 지금 구조에서 취소는 곧 행 삭제라 이력이 남지 않고, 유니크 2개(회차+회원, 회차+사물함)가 취소된 신청까지 붙잡아 같은 학생·같은 칸에 다시 배정할 수 없다.
📝 작업 상세 내용
- V26 마이그레이션 —
locker_applications에is_canceled추가, 유니크 2개를 generated column 기반으로 교체해 취소된 신청이 재배정을 막지 않게 한다 -
LockerApplication에canceled와cancel()추가 — 이미 취소된 신청은 다시 취소할 수 없다 - 신청 현황 목록 조회 — 운영 회차 기준, 이름·학번 키워드 검색, 페이징.
MemberService.searchIdsByKeyword재사용 - 신청 취소 — 행은 남기고
is_canceled만 바꾼다. 사용 기간이 끝난 회차는 거부 - 수동 배정 —
memberId를 받고, 그 회차에 선택 가능한 칸인지 확인한다. 회원·사물함 중복은 유니크가 막는다 - 학생 조회에서 취소 건 제외 —
getApplicationsByMemberId에 필터 한 줄. 학생에게는 "미신청"으로 보인다 - 알림 —
LOCKER_ASSIGNED_BY_ADMIN·LOCKER_ASSIGNMENT_CANCELED신설(아웃박스) -
AdminLockerService에 세 동작 추가, 목록 조회와 납부자 확인은api:admin-api의 UseCase로 조합 -
LockerErrorCode보강,@ApiErrorCode로 문서화
📁 참고 자료 (선택)
- API 명세: 관리자 페이지(노션)
- 관리자 화면 구현: https://github.com/kmu-yed/stream-admin
- 선행: 사물함 운영 회차 관리자 API 추가 #119(운영 회차) → 사물함 신청 시 모집 기간 검증 추가 #128(신청 기간 검증) → 사물함 구역 목록·상세 관리자 API 추가 #132(구역 조회) → 사물함 상태 일괄 변경 관리자 API 추가 #146(상태 일괄 변경)
- 키워드 검색·페이징 선례:
AdminFeeSearchUseCase,AdminFeeController.searchFeeStatuses - 납부자 확인 선례:
RentalApplyUseCase의PayerService.validatePayer - 유니크 + generated column 선례: V1(
student_id), V16(phone_number), V20(period_year+semester) - 취소 알림 선례:
EventApplicationCanceled - V26으로 잡는다. main이 V19까지이고 사물함 스택(사물함 운영 회차 관리자 API 추가 #119~사물함 상태 일괄 변경 관리자 API 추가 #146)이 V20·V21, #139가 V22, #166이 V23~V25를 쓴다. 머지 순서가 바뀌면 다시 맞춘다
정한 것
- 취소해도 행은 남긴다. 운영진이 왜 비었는지 알아야 하고, 나중에 신청 이력을 볼 수도 있다. 대신 유니크 2개를
IF(is_canceled = 0, col, NULL) VIRTUAL형태로 바꿔 취소된 신청이 재배정을 막지 않게 한다 - 학생에게는 "미신청"으로 보인다. 명세의 배정 상태 뱃지가 미신청·배정완료·기간종료 셋뿐이라 취소 뱃지가 없다. 취소 건을 학생 응답에서 빼면 미신청으로 보이고, 기간이 남아 있으면 다시 신청할 수 있다. 표시용
LockerApplicationStatus와 [Feat/#72] 내 배정 사물함 조회 API 추가 #73(내 배정 사물함 조회)을 건드리지 않는다 - 컬럼은
status가 아니라is_canceled다. 승인 절차가 없어 신청이 곧 배정이라 값이 둘뿐이고, 저장소의 소프트 삭제 패턴과 모양이 같다. "기간종료"는 저장하지 않고 회차로 계산한다 - 수동 배정은
memberId를 받는다. 화면이 "학생회비 납부자 목록에서 이름 또는 학번으로 검색해 선택"하는 구조라, 검색은 #166이 만드는 납부자 목록 조회를 쓰고 배정 요청은 식별자만 받는다. 납부자인지는PayerService.validatePayer로 확인하며, 교차 도메인이라api:admin-api의 UseCase에서 조합한다 —core:domain:event는 회비를 모른다 - 수동 배정은 신청 기간 제약을 받지 않는다. 학생이 신청을 놓쳤거나 고장 난 칸을 옮겨줄 때 쓰는 기능이라 신청 기간이 끝난 뒤가 오히려 주 사용 시점이다. 사용 기간이 끝난 회차만 막는다
- 취소·수동 배정 모두 학생에게 알림을 보낸다. 본인이 하지 않은 변경이고, 화면이 조용히 바뀌므로 알림이 유일한 전달 수단이다. 기존
LOCKER_ASSIGNED("사물함을 신청했어요")는 학생이 직접 신청한 경우로 남긴다 - 운영진 전용 동작은
AdminLockerService에 둔다. #119에서 분리해둔 그대로다 - 응답에 학년은 넣지 않는다
이 이슈에서 다루지 않는 것
- 구역 배치(layout)·사진 교체 — 별도 이슈
- 학생이 직접 신청을 취소하는 기능 — 학생 앱은 신청만 한다
- 사물함 등록·삭제, 구역 등록·수정
Activity
Merge pull request #177 from billilge/feat/#149-admin-locker-applicat…