[api] 관리자 휴면/탈퇴/삭제 추가
This commit is contained in:
@@ -10,6 +10,8 @@
|
||||
- 단일 캠퍼스형은 생성 즉시 운영 가능하다.
|
||||
- 복합 캠퍼스형은 교사 생성 후 관리자 승인 절차를 거친 뒤 운영 가능하다.
|
||||
- 관리자(Back Office)도 캠퍼스를 직접 생성할 수 있다.
|
||||
- 관리자 생성 시 캠퍼스 마스터 역할의 교사는 회원 가입이 완료된 상태여야 하며, 필요하면 관리자 화면에서 회원 등록을 병행한다.
|
||||
- 관리자 생성 시 등록 정보는 캠퍼스 명칭, 직접 유입 개인화 도메인, 로고, 캠퍼스 사용 교재를 포함한다.
|
||||
|
||||
## 캠퍼스 유형
|
||||
- 단일 캠퍼스형: 1인 교사 공부방 또는 단일 학원형
|
||||
@@ -31,6 +33,9 @@
|
||||
- 동일 학생이어도 교재가 바뀌면 새 강좌 생성
|
||||
- 동일 교재여도 학생 구성이 바뀌면 새 강좌 생성
|
||||
- 강좌 복사 기능을 제공하며 수업 중 강좌도 복사 가능하다
|
||||
- 동일 캠퍼스 소속 교사는 본인이 개설한 강좌 외에 타 교사의 강좌도 검색·복사할 수 있다
|
||||
- 동일 강좌 ID 안에서는 교재 교체, 교재 추가, 전체 학생 변경이 불가하며, 교재 또는 학생 구성이 크게 바뀌면 신규 강좌 ID를 생성하는 흐름으로 본다
|
||||
- 개별 학생/수강생 상태 변경과 운영 중 학생 추가 초대는 가능하다
|
||||
- Live 상태 강좌 수는 제한될 수 있고 종료 강좌를 포함한 총 강좌 수는 무제한이다
|
||||
|
||||
## 강좌 생명주기
|
||||
@@ -45,6 +50,17 @@
|
||||
- 운영 중 학생 상태를 이용 중지 또는 수강 종료로 변경할 수 있다
|
||||
- 학생이 운영 중간에 가입하면 이전 과제/평가도 미수행 상태로 제시한다
|
||||
- 상태 변경 시 학생과 학부모에게 알림이 발송된다
|
||||
- 수업 코스는 교재 Unit 기반으로 정렬하고, 수업 자료, 온라인 콘텐츠, 과제, 평가를 선별 연동한다
|
||||
- 수업 일정과 과제/평가 출제 일정은 타임라인 기반으로 관리한다
|
||||
|
||||
## 캠퍼스/강좌 상태 관리
|
||||
- 온라인 캠퍼스, 가맹 캠퍼스, 클래스, 강좌, 회원의 캠퍼스 가입 상태는 별도 상태 체계로 관리한다
|
||||
- 온라인 캠퍼스에는 승인 대기, 운영 중, 운영 일시 정지, 운영 종료 상태가 있다
|
||||
- 클래스/가맹 캠퍼스에는 운영 중, 운영 일시 정지, 운영 종료 상태가 있다
|
||||
- 강좌에는 강의 준비 중, 강의 중, 강의 일시 정지, 강의 종료 상태가 있다
|
||||
- 교사 가입 상태에는 정상, 권한 일시 중지, 종료(탈퇴)가 있다
|
||||
- 학생/수강생의 강좌 가입 상태에는 수강 대기 중, 수강 중, 권한 일시 중지, 수강 종료, 종료(탈퇴)가 있다
|
||||
- 상위 조직이 일시 정지되면 하위 조직 상태에도 반영된다
|
||||
|
||||
## 교사 업무 흐름
|
||||
- 캠퍼스 생성 또는 초대 가입
|
||||
@@ -58,7 +74,9 @@
|
||||
|
||||
## 학생/수강생 학습 흐름
|
||||
- 초대 URL/초대 코드 기반 강좌 가입 또는 학생 회원 자기주도학습 시작
|
||||
- 예습 패키지 수행: 음원, 동영상, 단어 학습, 온라인 플래시 카드, 워드 리스트
|
||||
- 수업 참여
|
||||
- 온라인 학습 콘텐츠 수행
|
||||
- 과제 수행 및 제출
|
||||
- 평가 수행 및 제출
|
||||
- 복습 및 자기주도학습
|
||||
@@ -73,11 +91,22 @@
|
||||
|
||||
## SMS 정책
|
||||
- 캠퍼스 초대, 학습 알림, 보고서 발송 등에 SMS를 병행 사용할 수 있다
|
||||
- SMS 수량은 캠퍼스 마스터가 구매/충전하는 구조다
|
||||
- 발송 성공 시 수량이 차감된다
|
||||
- 백오피스에서 수량 충전 기능을 제공한다
|
||||
- 초대 시 이메일 발송은 필수, 휴대폰 SMS 발송은 선택으로 본다
|
||||
- SMS 발송은 개발 후 서비스 오픈 시 프로세스 Hidden 처리될 수 있다
|
||||
|
||||
## 초대 코드 정책
|
||||
- 초대 코드는 캠퍼스에 초대되는 회원의 가입 일치 여부를 판단하고, 캠퍼스별 교재 단위 이용자 수를 관리하는 수단이다
|
||||
- 교사용 초대 코드와 학생용 초대 코드는 생성·사용 로직을 이원화한다
|
||||
- 학생 초대 코드는 교재별 수량 관리 대상이며, 강좌에 학생을 초대할 때 잔여 수량 내에서 생성한다
|
||||
- 학생 초대 코드 상태는 미사용, 발송, 발송 실패, 재발송, 강좌 가입, 수업 시작으로 관리한다
|
||||
- 초대 코드 수량은 전체 수량, 대기 수량, 사용 수량, 잔여 수량으로 표현한다
|
||||
- 대기 수량은 발송/재발송 상태의 합계이고, 사용 수량은 강좌 가입/수업 시작 상태의 합계다
|
||||
- 학생이 초대 코드를 분실하면 교사가 동일 초대 코드를 재발송할 수 있어야 한다
|
||||
- 강좌 생성 후 학생별 초대 코드 목록은 Excel 목록형 또는 PDF 인쇄형으로 다운로드할 수 있다
|
||||
- 해외 임대 서비스에서는 유통업체 또는 관리자 화면을 통해 캠퍼스별·교재별 초대 코드 수량을 생성/증감 관리한다
|
||||
|
||||
## 개발 해석 포인트
|
||||
- 캠퍼스, 클래스, 강좌는 이름이 비슷하지만 역할이 다르므로 테이블/DTO/응답 모델을 명확히 분리해야 한다
|
||||
- 강좌는 실제 학습 데이터와 과제/평가의 기준 단위이므로, API 설계 시 강좌 식별자를 중심으로 묶는 것이 자연스럽다
|
||||
- 초대, 가입, 탈퇴, 종료, 상태 변경은 회원 상태와 강좌 소속 상태를 구분해 처리해야 한다
|
||||
- 초대 코드는 단순 인증 토큰이 아니라 교재별 이용 수량과 연결된 운영 데이터이므로 상태 이력과 수량 집계를 함께 고려해야 한다
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
# 정책서: 콘텐츠/LMS
|
||||
|
||||
## 콘텐츠 범주
|
||||
- 수업 자료: PPT, Lesson Plan, Syllabus, Scope & Sequence, Teacher Guide, Script, Worksheet, Word Test 등
|
||||
- 평가 자료: Test Sheet, 단원 평가, 중간/최종 평가, 평가 문항, 내신 수행평가 자료
|
||||
- 멀티미디어: MP3, MP4, 온라인 PPT, 온라인 클래스, 플래시 카드
|
||||
- 솔루션형 콘텐츠: 교사용 e-Book, 온라인 평가, 온라인 OMR 평가, Voca*List, 클래스 카드, 레벨 테스트
|
||||
- 교사 전용 자료: Lesson Plan, Syllabus, Scope & Sequence, 강의 계획서, Teacher Guide, 수업 PPT, 정답 및 해설, 워크시트
|
||||
- 교재 부가 자료: 본문 스크립트, 한글 해석/번역, 단어 리스트, 플래시 카드
|
||||
- 평가 자료: Word Test, Test Sheet, 단원 평가, 중간/최종 평가, 온라인 평가, 온라인 OMR 평가지
|
||||
- 멀티미디어: MP3, MP4
|
||||
- 온라인 학습 자료: 온라인 학습 콘텐츠, 온라인 플래시 카드, 온라인 클래스, 클래스 카드
|
||||
- 솔루션형 콘텐츠: 교사용 e-Book, 온라인 수업 PPT, 문항 출제 마법사, 레벨 테스트, 내신 수행 평가 자료실, Voca*List
|
||||
- 교사 보유 자료: PDF, MP3, MP4 업로드 자료
|
||||
|
||||
## 콘텐츠 생산과 활용
|
||||
@@ -12,17 +14,35 @@
|
||||
- 교사는 수업 뷰어에서 문서형 자료, URL, 온라인 콘텐츠, 과제, 평가를 통합적으로 사용한다
|
||||
- 학생은 온라인 학습 콘텐츠 뷰어와 과제/평가 뷰어에서 콘텐츠를 수행한다
|
||||
- 평가지는 별도 생성 솔루션(Test Generator)으로 출제, 편집, 출력한다
|
||||
- CMS는 교재 카테고리(SKILL), 시리즈, 교재, 목차(Unit), 문서 자료, 멀티미디어, 온라인 학습 DB, 평가 문항 DB, eBook, 온라인 OMR, 온라인 평가, 온라인 플래시 카드, 제휴 자료를 통합 관리한다
|
||||
- 콘텐츠는 원천 콘텐츠 생산, 2차 콘텐츠 저작, 사용자 활용 지원 서비스의 흐름으로 관리한다
|
||||
- A*List에서는 다운로드, 단독 웹 뷰어, 온라인 응시 기능을 중심으로 제공하고, A★캠퍼스에서는 수업 뷰어/과제 뷰어 연동, 강좌 단위 배포, LMS 저장을 중심으로 제공한다
|
||||
- 온라인 응시 기능은 A*List에서 교사 편의와 A★캠퍼스 체험을 위한 기능으로 제공될 수 있으며, 동일 URL로 복수 학생이 접속하되 DB 저장을 하지 않는 흐름이 있다
|
||||
- A★캠퍼스의 온라인 평가/온라인 OMR/레벨테스트는 강좌 또는 학생 단위로 배포·응시·채점·피드백·LMS 저장을 수행한다
|
||||
|
||||
## 콘텐츠 메타데이터
|
||||
- 콘텐츠는 교재, 시리즈, 레벨, 학년, 난이도, CEFR, Lexile, AR 등 학습 레벨 메타데이터를 가진다
|
||||
- 교재 레벨 메타는 백오피스/CMS에서 별도로 관리한다
|
||||
- 메타데이터는 검색, 교재 노출, 학습 추천, 보고서 분류에 영향을 줄 수 있다
|
||||
- 교재-콘텐츠 관리 위계는 교재 카테고리(SKILL), 시리즈, 레벨, 유닛(Unit), 레슨(Lesson), 콘텐츠 분류 카테고리, 콘텐츠로 구성한다
|
||||
- 부속 교재는 Workbook, Teacher's Book, 책 속의 책 등 물리적으로 분책된 교재를 관리하며, ISBN이 다른 경우 연관 교재 세트 개념으로 구성할 수 있다
|
||||
- 유닛에는 권장 수업 차시 수를 둘 수 있으며, 기본 커리큘럼과 수업 코스 설계에 활용한다
|
||||
- 개별 파일 기준 속성은 콘텐츠 타입, 파일 포맷, 교재 범위, 작성 언어, 제공 권한 범위를 포함한다
|
||||
- 문항/활동형 콘텐츠는 개별 활동 또는 개별 문항 단위로 SKILL, Sub SKILL, 난이도, 활동 유형, 문항 유형, 구조 메타를 적용한다
|
||||
|
||||
## 콘텐츠 접근 권한
|
||||
- 교사: 대부분의 수업 자료와 교사용 자료, 수업 뷰어 기능 접근 가능
|
||||
- 학생: 제한된 수업 자료와 멀티미디어, 온라인 학습 콘텐츠 접근 가능
|
||||
- 수강생: 강좌 기반 학습 활동 위주로 제한된 권한을 가진다
|
||||
- 학생용 I/F에서는 기본 권한 자료와 교사가 추가 허용한 자료를 함께 노출할 수 있다
|
||||
- 접근 권한 표기는 `●`, `▲`, `☆`, `X` 기준으로 해석한다
|
||||
- `●`: 해당 회원 유형이 기본 접근/사용 가능
|
||||
- `▲`: 수강생이 초대받은 강좌 교재 범위 안에서 접근/사용 가능
|
||||
- `☆`: 학생/수강생이 강좌 소속이고 교사가 수업 설계 중 허용 또는 전송한 경우 접근/사용 가능
|
||||
- `X`: 해당 인터페이스에서 직접 제공하지 않거나 구버전/별도 경로로 취급
|
||||
- 학생은 본문 스크립트, 한글 해석/번역, 단어 리스트, 멀티미디어, 온라인 학습 콘텐츠, 온라인 플래시 카드 등에 기본 접근할 수 있다
|
||||
- 수강생은 초대받은 강좌 교재 범위 안에서 본문 스크립트, 번역, 단어 리스트, 온라인 학습, 온라인 플래시 카드 등에 접근한다
|
||||
- 교사용 자료와 평가 자료 상당수는 교사가 공유하거나 강좌 과제/평가로 전송한 경우에만 학생/수강생에게 노출된다
|
||||
|
||||
## 주요 솔루션과 기능
|
||||
- 교수자용 수업 뷰어
|
||||
@@ -38,13 +58,29 @@
|
||||
- 문항 검색, 문항 수/유형 설정, 사용자 문항 추가, PDF 생성, 출력
|
||||
- 학습 분석 보고서
|
||||
- 레벨테스트, 교재별, Unit별 보고서 생성
|
||||
- 온라인 OMR 평가지
|
||||
- 문서 포맷 시험지를 OMR 타입 온라인 평가 콘텐츠로 2차 가공
|
||||
- 문항 타입, 정답, SKILL 메타를 입력하고 온라인 평가 뷰어로 응시
|
||||
- 온라인 수업 PPT
|
||||
- 수업 PPT를 HTML 포맷으로 변환하여 온라인 수업 PPT 뷰어와 통합 수업 뷰어에 연동
|
||||
- 교사용 eBook
|
||||
- PDF 기반 eBook 생성, 복수 책 구성, Audio/Video, 정답, 온라인 PPT, URL 연동
|
||||
- 레벨 테스트
|
||||
- 시험지 분류, 시험지 레벨, 문항 구성, 분석 가이드, 추천 교재, 시험 시간 설정, LMS 연동
|
||||
- 온라인 학습 콘텐츠
|
||||
- Unit 단위로 SKILL 영역을 구성하고, SKILL별 모듈을 선택·순서화한다
|
||||
- 모듈은 하나 이상의 Activity 또는 Test 문항으로 구성한다
|
||||
- 온라인 플래시 카드
|
||||
- 단어, 뜻, 예문, 음원, 이미지를 관리하고 수동/자동 단어 보기, 암기/미암기 관리, 내 단어장 등록을 제공한다
|
||||
|
||||
## 학습 관리 대상
|
||||
- 레벨테스트
|
||||
- 예습 패키지
|
||||
- 온라인 학습 콘텐츠
|
||||
- 온라인 평가
|
||||
- 온라인 과제
|
||||
- 클래스 과제
|
||||
- 셀프 스터디(더 공부하기)
|
||||
|
||||
## 학습 관리 영역
|
||||
- 정량 관리
|
||||
@@ -57,19 +93,42 @@
|
||||
- 학습 진도
|
||||
- 전체 성취도
|
||||
- SKILL별 성취도
|
||||
- Sub SKILL별 성취도
|
||||
- 단위 학습 성취도
|
||||
- 성취도 변화 추이
|
||||
- 산출물 관리
|
||||
- 오답 노트
|
||||
- 학습 산출물 데이터
|
||||
- 유사 문항 학습
|
||||
- 포트폴리오
|
||||
- 정성 관리
|
||||
- 교사 평가 텍스트
|
||||
- 평가 항목별 5점 척도 평가
|
||||
- SKILL별 정성 평가
|
||||
- 학습 태도 및 성장도 평가
|
||||
|
||||
## 학습 관리 데이터 구조
|
||||
- 정량적 학습 관리는 학습 뷰어와 LMS DB 데이터로 자동 축적한다
|
||||
- 정성적 학습 관리는 교사가 대시보드 통계나 과제 산출물을 보고 입력한 평가로 관리한다
|
||||
- 학습 수행 데이터는 단위 학습 일자, 시작 시간, 종료 시간, 수행 여부, 학습 항목, 학습 시간, 수행률, 빈도 등을 포함한다
|
||||
- 학습 성취 데이터는 문항 제출 답안, 정오 판정, 파일 산출물, 단위 성취도, SKILL별 성취도, 문항 유형별 성취도, 취약 SKILL 등을 포함한다
|
||||
- 학생 개인 기록 외에 강좌, 클래스, 캠퍼스 단위 평균과 순위 데이터를 생성할 수 있다
|
||||
- 레벨테스트 및 타 교재 학습 이력에 기반해 성취도 추이와 학습 포트폴리오를 구성한다
|
||||
- 학습 관리 구조는 교재, Unit, Lesson, 학습 모듈, Activity/Test 문항으로 이어진다
|
||||
- 단일형 콘텐츠는 온라인 평가/과제처럼 하나의 콘텐츠 수행으로 학습이 완료되는 단위다
|
||||
- 과정형 콘텐츠는 온라인 학습/온라인 클래스처럼 복수 모듈이 순차 학습 Flow를 이루는 콘텐츠다
|
||||
|
||||
## 시각화 및 보고
|
||||
- 대시보드 I/F와 학습 분석 보고서가 주요 표현 수단이다
|
||||
- 학생별/강좌별 현황, 성취도, 수행률, 레벨테스트 결과 시각화가 중요하다
|
||||
- 교사 화면에서는 강좌별 관리와 학생별 관리가 모두 필요하다
|
||||
- 레벨테스트 분석 보고서는 총점, SKILL/Sub SKILL별 성취율, 강점/취약 스킬, 추천 교재, 문항별 채점표를 포함한다
|
||||
- 단원/중간/기말 평가 보고서는 평가 성취도, 문항별 채점표, SKILL별 성취도, 학습 시간 그래프, 온라인 학습/과제 성취도 추이를 포함한다
|
||||
- 교재 학습 분석 보고서는 강의 종료 또는 교재 학습 완료 시 생성하며, 학습 수행 분석, 학습 성취도 분석, 교사 정성 평가를 포함한다
|
||||
|
||||
## 개발 해석 포인트
|
||||
- 콘텐츠 자체 메타데이터와 학습 수행 데이터는 분리 저장하는 편이 좋다
|
||||
- 학습 관리 영역은 단순 진도율이 아니라 성취도·산출물·포트폴리오까지 포함하므로 조회 API가 넓어질 가능성이 높다
|
||||
- 학생용 권한은 `회원 유형`, `강좌 소속 여부`, `교사 공유 여부`의 조합으로 판단해야 한다
|
||||
- 콘텐츠 접근 권한은 콘텐츠 타입별로 다르므로 공통 boolean 하나보다 콘텐츠-회원유형-강좌소속-공유여부 조합 정책으로 모델링하는 편이 안전하다
|
||||
- 학습 데이터는 개인, 강좌, 클래스, 캠퍼스 단위 집계가 필요하므로 원천 이벤트/결과 데이터와 집계 데이터를 분리하는 설계가 유리하다
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 정책서 요약 인덱스
|
||||
|
||||
원본 정책서: `D:/work/project/202601_alist/document/00_정책서/이퍼블릭_AList 교수학습지원 통합 플랫폼 구축_정책 설계_Ver 0.29.pdf`
|
||||
원본 정책서: `D:/work/project/202601_alist/document/00_정책서/이퍼블릭_AList 교수학습지원 통합 플랫폼 구축_정책 설계_Ver 0.32.pdf`
|
||||
|
||||
## 문서 구성
|
||||
- [서비스 개요](overview.md)
|
||||
@@ -12,7 +12,8 @@
|
||||
## 빠른 요약
|
||||
- 플랫폼은 메인 서비스, 캠퍼스 메인, 교사용 캠퍼스, 학생용 캠퍼스, 백오피스/CMS로 분리된다.
|
||||
- 핵심 도메인은 회원, 캠퍼스, 클래스, 강좌, 콘텐츠, 과제/평가, 학습 관리다.
|
||||
- 정책서상 주요 제약은 회원 유형별 권한 차등, 캠퍼스 소속 제한, 강좌-교재 1:1 관계, 캠퍼스 개인화 도메인, 레거시 병행 운영이다.
|
||||
- 정책서상 주요 제약은 회원 유형별 권한 차등, 캠퍼스 소속 제한, 강좌-교재 1:1 관계, 초대 코드 상태/수량 관리, 캠퍼스 개인화 도메인, 레거시 병행 운영이다.
|
||||
- `Ver 0.32`에서는 콘텐츠 생산/활용 구조, 콘텐츠 접근 권한, 학습 관리 데이터, 학습 분석 보고서, 인터페이스 메뉴 범위가 더 구체화되었다.
|
||||
- 실제 개발 판단에서는 이 문서 묶음을 기능 정의서보다 `도메인 정책서`로 취급하는 것이 적합하다.
|
||||
|
||||
## 개발 시 우선 참고 포인트
|
||||
|
||||
@@ -8,26 +8,35 @@
|
||||
- 캠퍼스 교사용(`class.a-campus.co.kr`)
|
||||
- 강좌/학생/학습/알림/수업준비/캠퍼스 관리 중심
|
||||
- 캠퍼스 학생용(`student.a-campus.co.kr`)
|
||||
- 오늘 학습, 셀프 스터디, 나의 학습, 알림방 중심
|
||||
- 나의 학습, 과제·평가, 자습하기, 복습하기, 학습 통계·리포트, 소통방 중심
|
||||
- 백오피스/CMS(`admin.alist.co.kr`)
|
||||
- 운영 관리, 교재/콘텐츠/CMS, 파트너, 홍보, 문의, 통계 관리
|
||||
|
||||
## 교사용 I/F 핵심 메뉴
|
||||
- 강좌 관리
|
||||
- 학생 관리
|
||||
- 학습 관리
|
||||
- 소통방
|
||||
- 수업 준비
|
||||
- 수업(강좌) 관리
|
||||
- 학생·학습 관리
|
||||
- 교재 수업 준비
|
||||
- 소통방: 알림장, 1:1 메시지
|
||||
- 마이페이지
|
||||
- 역할에 따라 가맹 캠퍼스 관리, 캠퍼스 관리, 공지 관리 등 추가 메뉴 노출
|
||||
- 캠퍼스 마스터 전용 메뉴와 가맹 캠퍼스장 전용 메뉴는 타 역할에서 Hidden 처리한다
|
||||
- 교사용 I/F는 강좌 생성, 강좌 복사, 학생 초대, 수업 요일 지정, 수업 하기, 과제 출제, 평가 출제, 레벨테스트 보내기 등을 CTA로 제공한다
|
||||
- 학생·학습 관리는 학습 기간, 누적/일자별 학습 시간, 예습 패키지 수행률, 온라인 학습 수행률/성취도, 과제/평가 수행률, 학습 분석 보고서 생성을 포함한다
|
||||
|
||||
## 학생용 I/F 핵심 메뉴
|
||||
- 오늘 학습
|
||||
- 셀프 스터디
|
||||
- 나의 학습
|
||||
- 과제·평가
|
||||
- 자습하기
|
||||
- 더 공부하기
|
||||
- 복습하기
|
||||
- 학습 통계·리포트
|
||||
- 알림방
|
||||
- 마이페이지
|
||||
- 학생만 `학습 교재 추가`, `교재 추가` 같은 자기주도학습 확장 기능 사용 가능
|
||||
- 수강생은 학생 정회원 전용 자기주도학습 메뉴가 Hidden 처리된다
|
||||
- 학생용 I/F는 오늘 학습, 수업 캘린더, 내 학습 시간 기록, 온라인 학습 결과, 공지·알림, 1:1 메시지를 Dashboard로 제공한다
|
||||
- 과제·평가 메뉴는 수업(강좌) 목록, 과제 목록, 평가 목록, 레벨테스트 목록과 과제/평가/레벨테스트 수행 CTA를 포함한다
|
||||
- 학습 통계·리포트는 교재별 학습 기간, 총 학습 시간, 일자별 학습 시간, 온라인 학습/과제/평가 점수, SKILL별 평균, 교사 정성 평가, 동일 교재 학습자 비교를 포함한다
|
||||
|
||||
## 백오피스/CMS 핵심 메뉴
|
||||
- 관리자/권한 관리
|
||||
@@ -39,6 +48,23 @@
|
||||
- 교재 관리, 캠퍼스 서비스 교재 관리
|
||||
- 콘텐츠 저작/관리, 온라인 콘텐츠 관리, 제휴사 콘텐츠 관리
|
||||
- 학습 관리, 통계 관리
|
||||
- 캠퍼스 초대 코드 관리와 교재별 초대 코드 수량 관리를 포함한다
|
||||
- 해외 임대 서비스 전용 메뉴는 국내 서비스에서 Hidden 처리될 수 있다
|
||||
|
||||
## 메인 서비스 메뉴 정책
|
||||
- 메인 서비스는 `교재/수업 자료`, `스마트 수업 지원`, `지원 센터`, `마이페이지`를 중심으로 구성한다
|
||||
- `교재/수업 자료`는 Coursebook, Phonics, Readers, Reading, Listening, Speaking, Writing, Grammar, Vocabulary, Adult, Oxford 등 SKILL/브랜드 기준 메뉴를 포함한다
|
||||
- `스마트 수업 지원`은 A★캠퍼스, Apps, A★List Player, Voca*List, 문항 출제 마법사, 온라인 클래스 등으로 구성한다
|
||||
- `지원 센터`는 세미나, Oxford 파트너 서비스, 교재 활용 동영상, 이벤트, 커뮤니티 게시판, FAQ, 공지사항, 1:1 문의 등을 포함한다
|
||||
- `마이페이지`는 나의 정보, 나의 교재/자료, 시험지 보관함, 나의 테스트 등을 포함한다
|
||||
- 시험지 보관함은 교사 회원에게만 제공한다
|
||||
- 2Depth 메뉴의 가감은 Back Office에서 운영 가능해야 한다
|
||||
|
||||
## 캠퍼스 메인 메뉴 정책
|
||||
- 캠퍼스 메인은 서비스 소개, 이용방법, 체험하기, 수업교재, 고객센터로 구성한다
|
||||
- 수업교재는 교재 소개와 제공 자료 목록을 보여주되 Viewing/Download는 제공하지 않고, 캠퍼스 마스터가 생성한 온라인 캠퍼스 교재로 등록할 수 있게 한다
|
||||
- 체험하기는 선생님 수업 뷰어, 과제 출제, 평가 출제, 학생 온라인 학습 체험을 제공한다
|
||||
- 서비스 문의하기는 비회원도 작성할 수 있으며, 비로그인 작성 시 임시 비밀번호, 이름, 이메일을 입력한다
|
||||
|
||||
## 도메인 정책
|
||||
- 메인 서비스와 캠퍼스 서비스 도메인을 분리한다
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
- 학생 가입: 서비스 직접 방문, 부모 동의 인증 포함 휴대폰 인증, 이메일 인증
|
||||
- 수강생 가입: 캠퍼스 초대 URL + 초대 코드 기반 가입, 학생용 I/F 접근 계정 생성
|
||||
- 관리자 계정: 개발 또는 마스터 관리자 등록 방식
|
||||
- 해외 임대 서비스는 휴대폰 인증 프로세스를 생략하고 이메일 인증을 필수 프로세스로 둘 수 있다
|
||||
|
||||
## 인터페이스 접근 권한
|
||||
- 관리자: 백오피스/CMS 접근, 메뉴별 권한 차등
|
||||
@@ -27,6 +28,14 @@
|
||||
- 수강생: 학생용 I/F 중심 접근, 메인 서비스 권한 없음 또는 제한
|
||||
- 학생/수강생은 같은 학생용 I/F를 사용하지만 권한 범위는 다르다
|
||||
|
||||
## 회원 유형별 서비스 활용
|
||||
- 교사: A*List 전체 자료 접근, 다운로드/Web Viewing, 교사용 eBook, 온라인 PPT, 문항 출제 마법사, 레벨테스트, 세미나 등 교사 지원 서비스 이용
|
||||
- 교사: A★캠퍼스에서 캠퍼스 생성 또는 초대 가입 후 캠퍼스 운영, 강좌 생성, 수업 코스 설계, 과제/평가 출제, 학생별 학습 관리 수행
|
||||
- 학생: A*List의 학생 접근 허용 자료 Viewing, 멀티미디어, 일부 온라인 콘텐츠 이용
|
||||
- 학생: `student.a-campus.co.kr/home`에서 교재 선택 기반 자기주도학습 가능
|
||||
- 학생: 강좌에 소속되면 예습 패키지, 온라인 학습, 과제/평가, 복습, 레벨테스트 응시 등 강좌 기반 학습 활동 가능
|
||||
- 수강생: 초대받은 강좌 기반 학습 활동만 이용 가능하며, 학생처럼 교재를 자유 선택하는 자기주도학습 권한은 제한된다
|
||||
|
||||
## 캠퍼스 소속 정책
|
||||
- 교사 회원은 온라인 캠퍼스 역할과 무관하게 Live 상태에서 단수의 캠퍼스에만 소속 가능
|
||||
- 수강생은 Live 상태에서 단수의 캠퍼스에만 소속 가능
|
||||
@@ -61,7 +70,10 @@
|
||||
## 회원 전환 및 ID 병합
|
||||
- 수강생은 모바일 본인 인증 또는 부모 인증 후 학생으로 전환 가능
|
||||
- 전환 시 클래스/강좌 정보와 학습 이력은 유지한다
|
||||
- 해외 임대 및 국내 제휴 등 분리 독립 시스템 이용자는 수강생에서 학생으로 전환할 수 없는 예외가 있을 수 있다
|
||||
- 학생/수강생은 ID 병합 기능 제공 대상이다
|
||||
- ID 병합 시 병합한 ID의 강좌 정보와 학습 이력을 승계하고, 병합 대상 ID의 상태값을 변경한다
|
||||
- ID 병합 대상 확인에는 비밀번호, 이름, 휴대폰 인증 또는 이메일 인증 정보가 사용된다
|
||||
- 교사는 ID 병합 대상이 아니다
|
||||
|
||||
## 레거시 회원 정책
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
- A★캠퍼스: 교사·학생이 실제 교수·학습 활동을 수행하는 온라인 캠퍼스
|
||||
- 백오피스/CMS: 플랫폼 운영, 콘텐츠 관리, 파트너/교재/회원/통계 관리
|
||||
- 해외 확장: 영어 홍보 사이트, 해외 임대(이식) 서비스, 제휴/유통업체 운영
|
||||
- 통합 솔루션: 교사용 통합 수업 뷰어, 학생용 통합 과제 뷰어, 온라인 학습 솔루션, 학습 분석 보고서 제공
|
||||
|
||||
## 주요 인터페이스
|
||||
- `www.alist.co.kr`: 메인 서비스
|
||||
@@ -22,8 +23,8 @@
|
||||
|
||||
## 역할별 큰 흐름
|
||||
- 교사: 회원 가입 후 캠퍼스 생성 또는 캠퍼스 초대 가입, 교재 선택, 수업 설계, 학생 초대, 과제/평가 관리, 학습 관리 수행
|
||||
- 학생: 본인 인증 기반 정회원으로 가입 가능, 자기주도학습과 캠퍼스 강좌 활동 수행
|
||||
- 수강생: 캠퍼스 초대 기반 준회원으로 가입하며 강좌 기반 학습 활동 위주로 이용
|
||||
- 학생: 본인 인증 기반 정회원으로 가입 가능, 일부 A*List 콘텐츠 이용, 자기주도학습과 캠퍼스 강좌 활동 수행
|
||||
- 수강생: 캠퍼스 초대 기반 준회원으로 가입하며 강좌 기반 학습 활동 위주로 이용하고, 교재 자유 선택은 제한된다
|
||||
- 관리자/유통업체: 캠퍼스 생성 승인, 교재/콘텐츠 관리, 파트너 및 운영 정책 관리
|
||||
|
||||
## 서비스 환경 정책
|
||||
@@ -36,3 +37,4 @@
|
||||
- 이 플랫폼은 단순 콘텐츠 사이트가 아니라 `회원 + 캠퍼스 + 강좌 + 학습 데이터`를 중심으로 동작하는 LMS 성격이 강하다.
|
||||
- 교사용과 학생용 인터페이스가 명확히 분리되어 있으므로 메뉴, 권한, 응답 데이터도 같은 기준으로 나눠 설계해야 한다.
|
||||
- 해외 임대/제휴 확장을 전제로 하므로 도메인, 캠퍼스 개인화, 메뉴 노출, 권한 모델에 고정값을 박아 넣지 않는 편이 안전하다.
|
||||
- A*List와 A★캠퍼스는 같은 콘텐츠를 공유하더라도 다운로드, 온라인 뷰어, 강좌 단위 배포, LMS 저장 여부가 다를 수 있으므로 I/F별 활용 정책을 분리해야 한다.
|
||||
|
||||
@@ -39,12 +39,15 @@ public class OpenApiConfig {
|
||||
@Bean
|
||||
public GroupedOpenApi frontApi() {
|
||||
return GroupedOpenApi.builder()
|
||||
.group("front")
|
||||
.group("100. front")
|
||||
.pathsToMatch("/**")
|
||||
.pathsToExclude(
|
||||
"/admin/**",
|
||||
"/error",
|
||||
"/actuator/**"
|
||||
"/admin/**"
|
||||
, "/cors/**"
|
||||
, "/files/**"
|
||||
, "/tusFiles/**"
|
||||
, "/error"
|
||||
, "/actuator/**"
|
||||
)
|
||||
.build();
|
||||
}
|
||||
@@ -52,8 +55,20 @@ public class OpenApiConfig {
|
||||
@Bean
|
||||
public GroupedOpenApi adminApi() {
|
||||
return GroupedOpenApi.builder()
|
||||
.group("admin")
|
||||
.group("500. admin")
|
||||
.pathsToMatch("/admin/**")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GroupedOpenApi commonApi() {
|
||||
return GroupedOpenApi.builder()
|
||||
.group("900. common")
|
||||
.pathsToMatch(
|
||||
"/cors/**"
|
||||
, "/files/**"
|
||||
, "/tusFiles/**"
|
||||
)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.alist.api.config.cache;
|
||||
|
||||
import com.alist.api.modules.auth.vo.CorsOriginVo;
|
||||
import com.alist.api.modules.auth.mapper.CorsMapper;
|
||||
import com.alist.api.modules.cors.vo.CorsOriginVo;
|
||||
import com.alist.api.modules.cors.mapper.CorsMapper;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@@ -28,7 +28,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
try {
|
||||
String requestUri = request.getRequestURI();
|
||||
boolean adminRequest = requestUri.startsWith("/admin/");
|
||||
boolean sharedRequest = requestUri.startsWith("/tusFiles/") || requestUri.startsWith("/files/");
|
||||
boolean sharedRequest = requestUri.startsWith("/tusFiles/") || requestUri.startsWith("/files/") || requestUri.startsWith("/cors/");
|
||||
String token = resolveToken(request, adminRequest, sharedRequest);
|
||||
|
||||
if (token != null && jwtTokenProvider.validateToken(token)) {
|
||||
|
||||
@@ -21,7 +21,7 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Tag(
|
||||
name = "50. Admin 로그인"
|
||||
name = "501. Admin 로그인"
|
||||
, description = "ADMIN 사이트 로그인입니다. 로그인시 토큰 발급이 함께됩니다."
|
||||
)
|
||||
@RestController
|
||||
|
||||
@@ -2,12 +2,9 @@ package com.alist.api.modules.admin.member;
|
||||
|
||||
import com.alist.api.common.response.ApiResponse;
|
||||
import com.alist.api.common.response.ApiResponseCode;
|
||||
import com.alist.api.modules.admin.member.form.AdminMemberSearchForm;
|
||||
import com.alist.api.modules.admin.member.form.AdminMemberUpdateForm;
|
||||
import com.alist.api.modules.admin.member.form.*;
|
||||
import com.alist.api.modules.admin.member.service.AdminMemberService;
|
||||
import com.alist.api.modules.admin.member.vo.AdminMemberDetailVo;
|
||||
import com.alist.api.modules.admin.member.vo.AdminMemberListVo;
|
||||
import com.alist.api.modules.admin.member.vo.AdminMemberUpdateVo;
|
||||
import com.alist.api.modules.admin.member.vo.*;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
@@ -15,7 +12,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@Tag(name = "51. 회원 관리", description = "관리자 회원 관리 API")
|
||||
@Tag(name = "502. 회원 관리", description = "관리자 회원 관리 API")
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/admin/member")
|
||||
@@ -76,4 +73,55 @@ public class AdminMemberController {
|
||||
|
||||
return ApiResponse.entity(result, ApiResponseCode.CODE_2005, "회원 수정");
|
||||
}
|
||||
|
||||
@Operation(
|
||||
summary = "회원 휴면 상태 변경",
|
||||
description = "관리자가 회원 PK 기준으로 휴면 상태를 변경합니다. Y: 휴면, N: 정상"
|
||||
)
|
||||
@PatchMapping("/dormant")
|
||||
public ResponseEntity<ApiResponse<AdminMemberDormantStatusVo>> updateAdminMemberDormantStatus(
|
||||
@Valid @RequestBody AdminMemberDormantStatusForm adminMemberDormantStatusForm
|
||||
) {
|
||||
AdminMemberDormantStatusVo result = adminMemberService.updateAdminMemberDormantStatus(adminMemberDormantStatusForm.toAdminMemberDormantStatusUpdateDto());
|
||||
|
||||
if (!result.isDormantStatusUpdated()) {
|
||||
return ApiResponse.entity(result, ApiResponseCode.CODE_2003);
|
||||
}
|
||||
|
||||
return ApiResponse.entity(result, ApiResponseCode.CODE_2005, "회원 휴면 상태 변경");
|
||||
}
|
||||
|
||||
@Operation(
|
||||
summary = "회원 탈퇴 상태 변경",
|
||||
description = "관리자가 회원 PK 기준으로 탈퇴 상태를 변경합니다. N: 정상, P: 탈퇴대기, Y: 탈퇴완료"
|
||||
)
|
||||
@PatchMapping("/withdraw")
|
||||
public ResponseEntity<ApiResponse<AdminMemberWithdrawStatusVo>> updateAdminMemberWithdrawStatus(
|
||||
@Valid @RequestBody AdminMemberWithdrawStatusForm adminMemberWithdrawStatusForm
|
||||
) {
|
||||
AdminMemberWithdrawStatusVo result = adminMemberService.updateAdminMemberWithdrawStatus(adminMemberWithdrawStatusForm.toAdminMemberWithdrawStatusUpdateDto());
|
||||
|
||||
if (!result.isWithdrawStatusUpdated()) {
|
||||
return ApiResponse.entity(result, ApiResponseCode.CODE_2003);
|
||||
}
|
||||
|
||||
return ApiResponse.entity(result, ApiResponseCode.CODE_2005, "회원 탈퇴 상태 변경");
|
||||
}
|
||||
|
||||
@Operation(
|
||||
summary = "회원 계정 삭제",
|
||||
description = "관리자가 회원 PK 기준으로 계정을 삭제 처리합니다. 실제 삭제가 아닌 del_yn 변경 방식입니다."
|
||||
)
|
||||
@PatchMapping("/delete")
|
||||
public ResponseEntity<ApiResponse<AdminMemberDeleteVo>> deleteAdminMember(
|
||||
@Valid @RequestBody AdminMemberDeleteForm adminMemberDeleteForm
|
||||
) {
|
||||
AdminMemberDeleteVo result = adminMemberService.deleteAdminMember(adminMemberDeleteForm.toAdminMemberDeleteDto());
|
||||
|
||||
if (!result.isMemberDeleted()) {
|
||||
return ApiResponse.entity(result, ApiResponseCode.CODE_2003);
|
||||
}
|
||||
|
||||
return ApiResponse.entity(result, ApiResponseCode.CODE_2005, "회원 계정 삭제");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.alist.api.modules.admin.member.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class AdminMemberDeleteDto {
|
||||
private Integer userIdx;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.alist.api.modules.admin.member.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class AdminMemberDormantStatusDto {
|
||||
private Integer userIdx;
|
||||
private String dormantYn;
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package com.alist.api.modules.admin.member.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class AdminMemberWithdrawStatusDto {
|
||||
private Integer userIdx;
|
||||
private String withdrawStatus;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.alist.api.modules.admin.member.form;
|
||||
|
||||
import com.alist.api.modules.admin.member.dto.AdminMemberDeleteDto;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Schema(description = "관리자 회원 계정 삭제 요청 폼")
|
||||
@Getter
|
||||
@Setter
|
||||
public class AdminMemberDeleteForm {
|
||||
@Schema(description = "회원 PK", example = "15", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "회원 PK는 필수입니다.")
|
||||
private Integer userIdx;
|
||||
|
||||
public AdminMemberDeleteDto toAdminMemberDeleteDto() {
|
||||
AdminMemberDeleteDto adminMemberDeleteDto = new AdminMemberDeleteDto();
|
||||
adminMemberDeleteDto.setUserIdx(userIdx);
|
||||
return adminMemberDeleteDto;
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package com.alist.api.modules.admin.member.form;
|
||||
|
||||
import com.alist.api.modules.admin.member.dto.AdminMemberDormantStatusDto;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Schema(description = "관리자 회원 휴면 상태 변경 요청 폼")
|
||||
@Getter
|
||||
@Setter
|
||||
public class AdminMemberDormantStatusForm {
|
||||
@Schema(description = "회원 PK", example = "15", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "회원 PK는 필수입니다.")
|
||||
private Integer userIdx;
|
||||
|
||||
@Schema(description = "휴면 여부. Y: 휴면, N: 정상", example = "Y", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "휴면 여부는 필수입니다.")
|
||||
@Pattern(regexp = "^[YN]$", message = "휴면 여부는 Y 또는 N만 가능합니다.")
|
||||
private String dormantYn;
|
||||
|
||||
public AdminMemberDormantStatusDto toAdminMemberDormantStatusUpdateDto() {
|
||||
AdminMemberDormantStatusDto adminMemberDormantStatusDto = new AdminMemberDormantStatusDto();
|
||||
adminMemberDormantStatusDto.setUserIdx(userIdx);
|
||||
adminMemberDormantStatusDto.setDormantYn(dormantYn);
|
||||
return adminMemberDormantStatusDto;
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package com.alist.api.modules.admin.member.form;
|
||||
|
||||
import com.alist.api.modules.admin.member.dto.AdminMemberWithdrawStatusDto;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Schema(description = "관리자 회원 탈퇴 상태 변경 요청 폼")
|
||||
@Getter
|
||||
@Setter
|
||||
public class AdminMemberWithdrawStatusForm {
|
||||
@Schema(description = "회원 PK", example = "15", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "회원 PK는 필수입니다.")
|
||||
private Integer userIdx;
|
||||
|
||||
@Schema(description = "탈퇴 상태. N: 정상, P: 탈퇴대기, Y: 탈퇴완료", example = "P", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "탈퇴 상태는 필수입니다.")
|
||||
@Pattern(regexp = "^[NPY]$", message = "탈퇴 상태는 N, P, Y만 가능합니다.")
|
||||
private String withdrawStatus;
|
||||
|
||||
public AdminMemberWithdrawStatusDto toAdminMemberWithdrawStatusUpdateDto() {
|
||||
AdminMemberWithdrawStatusDto adminMemberWithdrawStatusDto = new AdminMemberWithdrawStatusDto();
|
||||
adminMemberWithdrawStatusDto.setUserIdx(userIdx);
|
||||
adminMemberWithdrawStatusDto.setWithdrawStatus(withdrawStatus);
|
||||
return adminMemberWithdrawStatusDto;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.alist.api.modules.admin.member.mapper;
|
||||
|
||||
import com.alist.api.modules.admin.member.dto.AdminMemberSearchDto;
|
||||
import com.alist.api.modules.admin.member.dto.AdminMemberUpdateDto;
|
||||
import com.alist.api.modules.admin.member.dto.*;
|
||||
import com.alist.api.modules.admin.member.vo.AdminMemberDetailVo;
|
||||
import com.alist.api.modules.admin.member.vo.AdminMemberVo;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@@ -17,4 +16,10 @@ public interface AdminMemberMapper {
|
||||
AdminMemberDetailVo selectAdminMemberDetail(Integer userIdx);
|
||||
|
||||
int updateAdminMember(AdminMemberUpdateDto adminMemberUpdateDto);
|
||||
|
||||
int updateAdminMemberDormantStatus(AdminMemberDormantStatusDto adminMemberDormantStatusDto);
|
||||
|
||||
int updateAdminMemberWithdrawStatus(AdminMemberWithdrawStatusDto adminMemberWithdrawStatusDto);
|
||||
|
||||
int deleteAdminMember(AdminMemberDeleteDto adminMemberDeleteDto);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
package com.alist.api.modules.admin.member.service;
|
||||
|
||||
import com.alist.api.modules.admin.member.dto.AdminMemberSearchDto;
|
||||
import com.alist.api.modules.admin.member.dto.AdminMemberUpdateDto;
|
||||
import com.alist.api.modules.admin.member.dto.*;
|
||||
import com.alist.api.modules.admin.member.mapper.AdminMemberMapper;
|
||||
import com.alist.api.modules.admin.member.vo.AdminMemberDetailVo;
|
||||
import com.alist.api.modules.admin.member.vo.AdminMemberListVo;
|
||||
import com.alist.api.modules.admin.member.vo.AdminMemberUpdateVo;
|
||||
import com.alist.api.modules.admin.member.vo.AdminMemberVo;
|
||||
import com.alist.api.modules.admin.member.vo.*;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@@ -45,4 +41,31 @@ public class AdminMemberService {
|
||||
result.setMemberUpdated(updateCount > 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public AdminMemberDormantStatusVo updateAdminMemberDormantStatus(AdminMemberDormantStatusDto adminMemberDormantStatusDto) {
|
||||
int updateCount = adminMemberMapper.updateAdminMemberDormantStatus(adminMemberDormantStatusDto);
|
||||
|
||||
AdminMemberDormantStatusVo result = new AdminMemberDormantStatusVo();
|
||||
result.setDormantStatusUpdated(updateCount > 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public AdminMemberWithdrawStatusVo updateAdminMemberWithdrawStatus(AdminMemberWithdrawStatusDto adminMemberWithdrawStatusDto) {
|
||||
int updateCount = adminMemberMapper.updateAdminMemberWithdrawStatus(adminMemberWithdrawStatusDto);
|
||||
|
||||
AdminMemberWithdrawStatusVo result = new AdminMemberWithdrawStatusVo();
|
||||
result.setWithdrawStatusUpdated(updateCount > 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public AdminMemberDeleteVo deleteAdminMember(AdminMemberDeleteDto adminMemberDeleteDto) {
|
||||
int updateCount = adminMemberMapper.deleteAdminMember(adminMemberDeleteDto);
|
||||
|
||||
AdminMemberDeleteVo result = new AdminMemberDeleteVo();
|
||||
result.setMemberDeleted(updateCount > 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.alist.api.modules.admin.member.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Schema(description = "관리자 회원 계정 삭제 응답")
|
||||
@Getter
|
||||
@Setter
|
||||
public class AdminMemberDeleteVo {
|
||||
@Schema(description = "회원 계정 삭제 여부", example = "true")
|
||||
private boolean memberDeleted;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.alist.api.modules.admin.member.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Schema(description = "관리자 회원 휴면 상태 변경 응답")
|
||||
@Getter
|
||||
@Setter
|
||||
public class AdminMemberDormantStatusVo {
|
||||
@Schema(description = "휴면 상태 변경 여부", example = "true")
|
||||
private boolean dormantStatusUpdated;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.alist.api.modules.admin.member.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Schema(description = "관리자 회원 탈퇴 상태 변경 응답")
|
||||
@Getter
|
||||
@Setter
|
||||
public class AdminMemberWithdrawStatusVo {
|
||||
@Schema(description = "탈퇴 상태 변경 여부", example = "true")
|
||||
private boolean withdrawStatusUpdated;
|
||||
}
|
||||
@@ -15,7 +15,7 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@Tag(name = "51. ADMIN 사용자 관리", description = "ADMIN 사용자 회원가입 및 관리 API")
|
||||
@Tag(name = "503. ADMIN 사용자 관리", description = "ADMIN 사용자 회원가입 및 관리 API")
|
||||
@RestController
|
||||
@Slf4j
|
||||
@RequestMapping("/admin/user")
|
||||
|
||||
@@ -11,6 +11,7 @@ import com.alist.api.modules.auth.form.ApikeyLoginForm;
|
||||
import com.alist.api.modules.auth.form.TokenForm;
|
||||
import com.alist.api.modules.auth.service.SsoService;
|
||||
import com.alist.api.modules.auth.service.AuthService;
|
||||
import com.alist.api.modules.auth.vo.TokenVo;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
@@ -23,7 +24,7 @@ import org.springframework.web.bind.annotation.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Tag(name = "02. 엑세스 토큰 발급", description = "엑세스 토큰 발급")
|
||||
@Tag(name = "102. 엑세스 토큰 발급", description = "엑세스 토큰 발급")
|
||||
@RestController
|
||||
@RequestMapping("/auth")
|
||||
public class AuthController {
|
||||
@@ -62,11 +63,11 @@ public class AuthController {
|
||||
description = "엑세스 토큰이 발급됩니다. (테스트용 실사용X)"
|
||||
)
|
||||
@PostMapping("/token")
|
||||
public ResponseEntity<ApiResponse<TokenDto>> token(@Valid @RequestBody TokenForm tokenForm) {
|
||||
TokenDto tokenDto = new TokenDto();
|
||||
tokenDto.setAccessToken(jwtTokenProvider.createToken(tokenForm.toTokenDto().getId()));
|
||||
public ResponseEntity<ApiResponse<TokenVo>> token(@Valid @RequestBody TokenForm tokenForm) {
|
||||
TokenVo tokenVo = new TokenVo();
|
||||
tokenVo.setAccessToken(jwtTokenProvider.createToken(tokenForm.toTokenDto().getId()));
|
||||
|
||||
return ApiResponse.entity(tokenDto, ApiResponseCode.CODE_2001, "엑세스 토큰");
|
||||
return ApiResponse.entity(tokenVo, ApiResponseCode.CODE_2001, "엑세스 토큰");
|
||||
}
|
||||
|
||||
@Operation(
|
||||
|
||||
@@ -23,7 +23,7 @@ import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Tag(name = "01. SSO 인증", description = "공통 로그인, 인가 코드 발급, 코드 교환, 로그아웃 관련 API")
|
||||
@Tag(name = "101. SSO 인증", description = "공통 로그인, 인가 코드 발급, 코드 교환, 로그아웃 관련 API")
|
||||
@RestController
|
||||
@RequestMapping("/sso")
|
||||
public class SsoController {
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.alist.api.modules.auth.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Schema(description = "테스트용 토큰 발급 응답")
|
||||
@Getter
|
||||
@Setter
|
||||
public class TokenVo {
|
||||
@Schema(description = "아이디")
|
||||
private String id;
|
||||
@Schema(description = "엑세스 토큰")
|
||||
private String accessToken;
|
||||
@Schema(description = "리플레시 토큰")
|
||||
private String refreshToken;
|
||||
|
||||
@JsonIgnore
|
||||
@Schema(hidden = true)
|
||||
private int resultCode;
|
||||
}
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
package com.alist.api.modules.auth;
|
||||
package com.alist.api.modules.cors;
|
||||
|
||||
import com.alist.api.common.response.ApiResponse;
|
||||
import com.alist.api.common.response.ApiResponseCode;
|
||||
@@ -13,7 +13,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "97. CRS 갱신", description = "테스트 CORS 설정 관리 API")
|
||||
@Tag(name = "901. CRS 갱신", description = "테스트 CORS 설정 관리 API")
|
||||
@RestController
|
||||
@RequestMapping("/cors")
|
||||
@RequiredArgsConstructor
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
package com.alist.api.modules.auth.mapper;
|
||||
package com.alist.api.modules.cors.mapper;
|
||||
|
||||
import com.alist.api.modules.auth.vo.CorsOriginVo;
|
||||
import com.alist.api.modules.cors.vo.CorsOriginVo;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.alist.api.modules.auth.vo;
|
||||
package com.alist.api.modules.cors.vo;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
@@ -17,7 +17,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Tag(
|
||||
name = "98. 파일 업로드",
|
||||
name = "902. 파일 업로드",
|
||||
description = "DB 기록 없이 파일을 저장하고 uploadPath를 반환하는 단순 업로드 API입니다. SunEditor 이미지는 file-domain URL을 반환합니다."
|
||||
)
|
||||
@RestController
|
||||
|
||||
@@ -26,7 +26,7 @@ import java.nio.file.Path;
|
||||
|
||||
@Slf4j
|
||||
@Tag(
|
||||
name = "99. TUS 업로드"
|
||||
name = "903. TUS 업로드"
|
||||
, description = "TUS 기반 파일 업로드 초기화, 권한 검증, 상태 조회, 훅 처리, 취소 API"
|
||||
)
|
||||
@RestController
|
||||
|
||||
@@ -12,7 +12,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@Tag(name = "05. 사용자 관리", description = "사용자 회원가입 및 관리 API")
|
||||
@Tag(name = "103. 사용자 관리", description = "사용자 회원가입 및 관리 API")
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/user")
|
||||
@@ -126,10 +126,10 @@ public class UserController {
|
||||
description = "로그인한 사용자의 탈퇴 요청 또는 탈퇴 요청 철회를 처리합니다. P: 탈퇴대기, N: 탈퇴요청 철회"
|
||||
)
|
||||
@PatchMapping("/withdraw")
|
||||
public ResponseEntity<ApiResponse<UserWithdrawStatusUpdateVo>> updateWithdrawStatus(
|
||||
@Valid @RequestBody UserWithdrawStatusUpdateForm userWithdrawStatusUpdateForm
|
||||
public ResponseEntity<ApiResponse<UserWithdrawStatusVo>> updateWithdrawStatus(
|
||||
@Valid @RequestBody UserWithdrawStatusForm userWithdrawStatusForm
|
||||
) {
|
||||
UserWithdrawStatusUpdateVo result = userService.updateWithdrawStatus(userWithdrawStatusUpdateForm.toUserWithdrawStatusUpdateDto());
|
||||
UserWithdrawStatusVo result = userService.updateWithdrawStatus(userWithdrawStatusForm.toUserWithdrawStatusUpdateDto());
|
||||
|
||||
if (!result.isWithdrawStatusUpdated()) {
|
||||
if (result.getResultCode() == 4003 || result.getResultCode() == 4001) {
|
||||
@@ -141,4 +141,25 @@ public class UserController {
|
||||
|
||||
return ApiResponse.entity(result, ApiResponseCode.CODE_2005, "탈퇴 상태 변경");
|
||||
}
|
||||
|
||||
@Operation(
|
||||
summary = "사용자 휴면 상태 변경",
|
||||
description = "로그인한 사용자의 휴면 처리 또는 휴면 해지를 처리합니다. Y: 휴면 회원, N: 휴면 해지"
|
||||
)
|
||||
@PatchMapping("/dormant")
|
||||
public ResponseEntity<ApiResponse<UserDormantStatusVo>> updateDormantStatus(
|
||||
@Valid @RequestBody UserDormantStatusForm userDormantStatusForm
|
||||
) {
|
||||
UserDormantStatusVo result = userService.updateDormantStatus(userDormantStatusForm.toUserDormantStatusUpdateDto());
|
||||
|
||||
if (!result.isDormantStatusUpdated()) {
|
||||
if (result.getResultCode() == 4003 || result.getResultCode() == 4001) {
|
||||
return ApiResponse.entity(result, ApiResponseCode.CODE_4001);
|
||||
}
|
||||
|
||||
return ApiResponse.entity(result, ApiResponseCode.CODE_2003);
|
||||
}
|
||||
|
||||
return ApiResponse.entity(result, ApiResponseCode.CODE_2005, "휴면 상태 변경");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.alist.api.modules.user.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class UserDormantStatusDto {
|
||||
private Integer userTokenIdx;
|
||||
private String dormantYn;
|
||||
}
|
||||
+1
-1
@@ -5,7 +5,7 @@ import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class UserWithdrawStatusUpdateDto {
|
||||
public class UserWithdrawStatusDto {
|
||||
private Integer userTokenIdx;
|
||||
private String withdrawStatus;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.alist.api.modules.user.form;
|
||||
|
||||
import com.alist.api.modules.user.dto.UserDormantStatusDto;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Schema(description = "사용자 휴면 상태 변경 요청 폼")
|
||||
@Getter
|
||||
@Setter
|
||||
public class UserDormantStatusForm {
|
||||
@Schema(
|
||||
description = "휴면 여부. Y: 휴면 회원, N: 휴면 해지",
|
||||
example = "Y",
|
||||
requiredMode = Schema.RequiredMode.REQUIRED
|
||||
)
|
||||
@NotBlank(message = "휴면 여부는 필수입니다.")
|
||||
@Pattern(regexp = "^[YN]$", message = "휴면 여부는 Y 또는 N만 가능합니다.")
|
||||
private String dormantYn;
|
||||
|
||||
public UserDormantStatusDto toUserDormantStatusUpdateDto() {
|
||||
UserDormantStatusDto userDormantStatusDto = new UserDormantStatusDto();
|
||||
userDormantStatusDto.setDormantYn(dormantYn);
|
||||
return userDormantStatusDto;
|
||||
}
|
||||
}
|
||||
+6
-6
@@ -1,6 +1,6 @@
|
||||
package com.alist.api.modules.user.form;
|
||||
|
||||
import com.alist.api.modules.user.dto.UserWithdrawStatusUpdateDto;
|
||||
import com.alist.api.modules.user.dto.UserWithdrawStatusDto;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
@@ -10,7 +10,7 @@ import lombok.Setter;
|
||||
@Schema(description = "사용자 탈퇴 상태 변경 요청 폼")
|
||||
@Getter
|
||||
@Setter
|
||||
public class UserWithdrawStatusUpdateForm {
|
||||
public class UserWithdrawStatusForm {
|
||||
@Schema(
|
||||
description = "탈퇴 상태. P: 탈퇴대기, N: 탈퇴요청 철회",
|
||||
example = "P",
|
||||
@@ -20,9 +20,9 @@ public class UserWithdrawStatusUpdateForm {
|
||||
@Pattern(regexp = "^[PN]$", message = "탈퇴 상태는 P 또는 N만 가능합니다.")
|
||||
private String withdrawStatus;
|
||||
|
||||
public UserWithdrawStatusUpdateDto toUserWithdrawStatusUpdateDto() {
|
||||
UserWithdrawStatusUpdateDto userWithdrawStatusUpdateDto = new UserWithdrawStatusUpdateDto();
|
||||
userWithdrawStatusUpdateDto.setWithdrawStatus(withdrawStatus);
|
||||
return userWithdrawStatusUpdateDto;
|
||||
public UserWithdrawStatusDto toUserWithdrawStatusUpdateDto() {
|
||||
UserWithdrawStatusDto userWithdrawStatusDto = new UserWithdrawStatusDto();
|
||||
userWithdrawStatusDto.setWithdrawStatus(withdrawStatus);
|
||||
return userWithdrawStatusDto;
|
||||
}
|
||||
}
|
||||
@@ -18,5 +18,7 @@ public interface UserMapper {
|
||||
|
||||
int updateUserProfile(UserProfileUpdateDto userProfileUpdateDto);
|
||||
|
||||
int updateWithdrawStatus(UserWithdrawStatusUpdateDto userWithdrawStatusUpdateDto);
|
||||
int updateWithdrawStatus(UserWithdrawStatusDto userWithdrawStatusDto);
|
||||
|
||||
int updateDormantStatus(UserDormantStatusDto userDormantStatusDto);
|
||||
}
|
||||
|
||||
@@ -229,19 +229,19 @@ public class UserService {
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public UserWithdrawStatusUpdateVo updateWithdrawStatus(UserWithdrawStatusUpdateDto userWithdrawStatusUpdateDto) {
|
||||
UserWithdrawStatusUpdateVo result = new UserWithdrawStatusUpdateVo();
|
||||
public UserWithdrawStatusVo updateWithdrawStatus(UserWithdrawStatusDto userWithdrawStatusDto) {
|
||||
UserWithdrawStatusVo result = new UserWithdrawStatusVo();
|
||||
|
||||
Integer userTokenIdx = SecurityUtil.getLoginUserTokenIdx();
|
||||
userWithdrawStatusUpdateDto.setUserTokenIdx(userTokenIdx);
|
||||
userWithdrawStatusDto.setUserTokenIdx(userTokenIdx);
|
||||
|
||||
if (userTokenIdx == null || userWithdrawStatusUpdateDto.getWithdrawStatus() == null) {
|
||||
if (userTokenIdx == null || userWithdrawStatusDto.getWithdrawStatus() == null) {
|
||||
result.setWithdrawStatusUpdated(false);
|
||||
result.setResultCode(4003);
|
||||
return result;
|
||||
}
|
||||
|
||||
String withdrawStatus = userWithdrawStatusUpdateDto.getWithdrawStatus();
|
||||
String withdrawStatus = userWithdrawStatusDto.getWithdrawStatus();
|
||||
|
||||
if (!"P".equals(withdrawStatus) && !"N".equals(withdrawStatus)) {
|
||||
result.setWithdrawStatusUpdated(false);
|
||||
@@ -249,11 +249,40 @@ public class UserService {
|
||||
return result;
|
||||
}
|
||||
|
||||
int updateCount = userMapper.updateWithdrawStatus(userWithdrawStatusUpdateDto);
|
||||
int updateCount = userMapper.updateWithdrawStatus(userWithdrawStatusDto);
|
||||
|
||||
result.setWithdrawStatusUpdated(updateCount > 0);
|
||||
result.setResultCode(updateCount > 0 ? 2005 : 2003);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public UserDormantStatusVo updateDormantStatus(UserDormantStatusDto userDormantStatusDto) {
|
||||
UserDormantStatusVo result = new UserDormantStatusVo();
|
||||
|
||||
Integer userTokenIdx = SecurityUtil.getLoginUserTokenIdx();
|
||||
userDormantStatusDto.setUserTokenIdx(userTokenIdx);
|
||||
|
||||
if (userTokenIdx == null || userDormantStatusDto.getDormantYn() == null) {
|
||||
result.setDormantStatusUpdated(false);
|
||||
result.setResultCode(4003);
|
||||
return result;
|
||||
}
|
||||
|
||||
String dormantYn = userDormantStatusDto.getDormantYn();
|
||||
|
||||
if (!"Y".equals(dormantYn) && !"N".equals(dormantYn)) {
|
||||
result.setDormantStatusUpdated(false);
|
||||
result.setResultCode(4001);
|
||||
return result;
|
||||
}
|
||||
|
||||
int updateCount = userMapper.updateDormantStatus(userDormantStatusDto);
|
||||
|
||||
result.setDormantStatusUpdated(updateCount > 0);
|
||||
result.setResultCode(updateCount > 0 ? 2005 : 2003);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.alist.api.modules.user.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Schema(description = "사용자 휴면 상태 변경 응답")
|
||||
@Getter
|
||||
@Setter
|
||||
public class UserDormantStatusVo {
|
||||
@Schema(description = "휴면 상태 변경 여부", example = "true")
|
||||
private boolean dormantStatusUpdated;
|
||||
|
||||
@JsonIgnore
|
||||
@Schema(hidden = true)
|
||||
private Integer resultCode;
|
||||
}
|
||||
+1
-1
@@ -8,7 +8,7 @@ import lombok.Setter;
|
||||
@Schema(description = "사용자 탈퇴 상태 변경 응답")
|
||||
@Getter
|
||||
@Setter
|
||||
public class UserWithdrawStatusUpdateVo {
|
||||
public class UserWithdrawStatusVo {
|
||||
@Schema(description = "탈퇴 상태 변경 여부", example = "true")
|
||||
private boolean withdrawStatusUpdated;
|
||||
|
||||
@@ -69,4 +69,21 @@
|
||||
AND ATU.del_yn = 1
|
||||
</select>
|
||||
|
||||
<update id="updateDormantStatus">
|
||||
/*UserMapper.updateDormantStatus*/
|
||||
UPDATE ALISTLMS.test_user ATU
|
||||
INNER JOIN ALISTLMS.test_user_token ATUT ON ATUT.user_idx = ATU.user_idx
|
||||
SET ATU.dormant_yn = #{dormantYn}
|
||||
, ATU.dormant_at =
|
||||
CASE
|
||||
WHEN #{dormantYn} = 'Y' THEN now()
|
||||
WHEN #{dormantYn} = 'N' THEN NULL
|
||||
ELSE ATU.dormant_at
|
||||
END
|
||||
, ATU.update_at = now()
|
||||
WHERE ATUT.user_token_idx = #{userTokenIdx}
|
||||
AND ATU.del_yn = 1
|
||||
AND ATU.withdraw_status != 'Y'
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
|
||||
@@ -48,6 +48,44 @@
|
||||
AND ATU.del_yn = 1
|
||||
</update>
|
||||
|
||||
<update id="updateAdminMemberDormantStatus">
|
||||
/*AdminMemberMapper.updateAdminMemberDormantStatus*/
|
||||
UPDATE ALISTLMS.test_user
|
||||
SET dormant_yn = #{dormantYn}
|
||||
, dormant_at =
|
||||
CASE
|
||||
WHEN #{dormantYn} = 'Y' THEN now()
|
||||
WHEN #{dormantYn} = 'N' THEN NULL
|
||||
ELSE dormant_at
|
||||
END
|
||||
, update_at = now()
|
||||
WHERE user_idx = #{userIdx}
|
||||
AND del_yn = 1
|
||||
</update>
|
||||
|
||||
<update id="updateAdminMemberWithdrawStatus">
|
||||
/*AdminMemberMapper.updateAdminMemberWithdrawStatus*/
|
||||
UPDATE ALISTLMS.test_user
|
||||
SET withdraw_status = #{withdrawStatus}
|
||||
, withdraw_at =
|
||||
CASE
|
||||
WHEN #{withdrawStatus} IN ('P', 'Y') THEN now()
|
||||
WHEN #{withdrawStatus} = 'N' THEN NULL
|
||||
ELSE withdraw_at
|
||||
END
|
||||
, update_at = now()
|
||||
WHERE user_idx = #{userIdx}
|
||||
AND del_yn = 1
|
||||
</update>
|
||||
<update id="deleteAdminMember">
|
||||
/*AdminMemberMapper.deleteAdminMember*/
|
||||
UPDATE ALISTLMS.test_user
|
||||
SET del_yn = 0
|
||||
, update_at = now()
|
||||
WHERE user_idx = #{userIdx}
|
||||
AND del_yn = 1
|
||||
</update>
|
||||
|
||||
<select id="selectAdminMemberCount" resultType="int">
|
||||
/*AdminMemberMapper.selectAdminMemberCount*/
|
||||
SELECT COUNT(*)
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
|
||||
<mapper namespace="com.alist.api.modules.auth.mapper.CorsMapper">
|
||||
<select id="selectCorsAllowedList" resultType="com.alist.api.modules.auth.vo.CorsOriginVo">
|
||||
<mapper namespace="com.alist.api.modules.cors.mapper.CorsMapper">
|
||||
<select id="selectCorsAllowedList" resultType="com.alist.api.modules.cors.vo.CorsOriginVo">
|
||||
/* CorsMapper.selectCorsAllowedList */
|
||||
SELECT allowed_origin
|
||||
FROM ALISTLMS.test_cors_allowed_list
|
||||
Reference in New Issue
Block a user