Skip to content

divisions

Cupcakes33 edited this page Jan 20, 2026 · 1 revision

API: 수련반 관리 (Divisions)

Domain: 수련부 및 수련반 관리
Base Path: /api/v1


엔드포인트 목록

수련부 (Sections)

메서드 경로 설명 권한
GET /sections 수련부 목록 조회 dojang.manageDivision
POST /sections 수련부 생성 dojang.manageDivision
PATCH /sections/:sectionId 수련부 수정 dojang.manageDivision
DELETE /sections/:sectionId 수련부 삭제 dojang.manageDivision
PATCH /sections/reorder 수련부 순서 변경 dojang.manageDivision

수련반 (Divisions)

메서드 경로 설명 권한
GET /divisions 수련반 목록 조회 dojang.manageDivision
GET /divisions/:divisionId 수련반 상세 조회 dojang.manageDivision
POST /divisions 수련반 생성 dojang.manageDivision
PATCH /divisions/:divisionId 수련반 수정 dojang.manageDivision
DELETE /divisions/:divisionId 수련반 삭제 dojang.manageDivision
PATCH /divisions/reorder 수련반 순서 변경 dojang.manageDivision

수련반 등록 (Enrollments)

메서드 경로 설명 권한
GET /enrollments 수련반 등록 원생 목록 조회 dojang.manageDivision
POST /enrollments 원생 등록 dojang.manageDivision
POST /enrollments/bulk 원생 일괄 등록 dojang.manageDivision
DELETE /enrollments/:studentId 원생 등록 해제 dojang.manageDivision

1. 수련부 목록 조회

Endpoint: GET /api/v1/sections

설명: 도장의 모든 수련부 목록을 조회합니다.

Request:

GET /api/v1/sections?dojangId=0J5FX8XNCSRPQ HTTP/1.1
Host: api.example.com
Authorization: Bearer {access_token}

Query Parameters:

파라미터 타입 필수 설명
dojangId string 도장 ID

Response (200 OK):

{
  "sections": [
    {
      "id": "0J5FX8XNCSRPQ",
      "name": "유소년부",
      "displayOrder": 1,
      "divisionCount": 3
    },
    {
      "id": "0J5FX8XNCSRPR",
      "name": "청소년부",
      "displayOrder": 2,
      "divisionCount": 2
    }
  ]
}

Response Fields:

필드 타입 설명
sections array 수련부 목록 (displayOrder 순)
sections[].id string 수련부 ID (13자리 TSID)
sections[].name string 수련부 이름
sections[].displayOrder integer 표시 순서
sections[].divisionCount integer 하위 수련반 수

2. 수련부 생성

Endpoint: POST /api/v1/sections

설명: 새로운 수련부를 생성합니다.

Request:

POST /api/v1/sections?dojangId=0J5FX8XNCSRPQ HTTP/1.1
Host: api.example.com
Authorization: Bearer {access_token}
Content-Type: application/json

{
  "name": "유소년부"
}

Query Parameters:

파라미터 타입 필수 설명
dojangId string 도장 ID

Request Body:

필드 타입 필수 설명
name string 수련부 이름 (1-50자)

Response (200 OK):

{
  "id": "0J5FX8XNCSRPQ",
  "name": "유소년부",
  "displayOrder": 1,
  "divisionCount": 0
}

Business Logic:

  1. JWT에서 tenant_id 추출 (dojangId와 동일 테넌트 검증)
  2. SECTION 레코드 생성
  3. displayOrder는 기존 최대값 + 1로 자동 설정
  4. 권한 검증: dojang.manageDivision

3. 수련부 수정

Endpoint: PATCH /api/v1/sections/:sectionId

설명: 수련부 정보를 수정합니다.

Request:

PATCH /api/v1/sections/0J5FX8XNCSRPQ?dojangId=0J5FX8XNCSRPT HTTP/1.1
Host: api.example.com
Authorization: Bearer {access_token}
Content-Type: application/json

{
  "name": "유소년부 (개편)"
}

Query Parameters:

파라미터 타입 필수 설명
dojangId string 도장 ID

Response (200 OK):

{
  "id": "0J5FX8XNCSRPQ",
  "name": "유소년부 (개편)",
  "displayOrder": 1,
  "divisionCount": 3
}

4. 수련부 삭제

Endpoint: DELETE /api/v1/sections/:sectionId

설명: 수련부를 삭제합니다 (하위 수련반이 있으면 삭제 불가).

Request:

DELETE /api/v1/sections/0J5FX8XNCSRPQ?dojangId=0J5FX8XNCSRPT HTTP/1.1
Host: api.example.com
Authorization: Bearer {access_token}

Query Parameters:

파라미터 타입 필수 설명
dojangId string 도장 ID

Response (204 No Content)

Business Logic:

  1. 하위 수련반(DIVISION) 존재 여부 확인
  2. 하위 수련반이 있으면 400 Bad Request 응답
  3. 없으면 SECTION 레코드 삭제 (소프트 삭제)

Error Response (400 Bad Request):

{
  "code": "HAS_CHILD_DIVISIONS",
  "message": "하위 수련반이 존재하여 삭제할 수 없습니다",
  "timestamp": "2026-01-08T12:00:00Z"
}

5. 수련부 순서 변경

Endpoint: PATCH /api/v1/sections/reorder

설명: 수련부들의 표시 순서를 변경합니다.

Request:

PATCH /api/v1/sections/reorder?dojangId=0J5FX8XNCSRPT HTTP/1.1
Host: api.example.com
Authorization: Bearer {access_token}
Content-Type: application/json

{
  "sectionIds": ["0J5FX8XNCSRPR", "0J5FX8XNCSRPQ", "0J5FX8XNCSRPS"]
}

Query Parameters:

파라미터 타입 필수 설명
dojangId string 도장 ID

Request Body:

필드 타입 필수 설명
sectionIds array 수련부 ID 목록 (순서대로 displayOrder 부여)

Response (204 No Content)

Business Logic:

  1. 배열 순서대로 displayOrder 1, 2, 3... 부여
  2. 해당 도장의 수련부만 변경 가능
  3. 존재하지 않는 ID가 포함되면 400 Bad Request

6. 수련반 목록 조회

Endpoint: GET /api/v1/divisions

설명: 특정 수련부의 수련반 목록을 조회합니다.

Request:

GET /api/v1/divisions?dojangId=0J5FX8XNCSRPT&sectionId=0J5FX8XNCSRPQ HTTP/1.1
Host: api.example.com
Authorization: Bearer {access_token}

Query Parameters:

파라미터 타입 필수 설명
dojangId string 도장 ID
sectionId string 수련부 ID

Response (200 OK):

{
  "divisions": [
    {
      "id": "0J5FX8XNCSRPV",
      "sectionId": "0J5FX8XNCSRPQ",
      "sectionName": "유소년부",
      "name": "유소년부 A반",
      "displayOrder": 1,
      "scheduleDays": ["MONDAY", "WEDNESDAY", "FRIDAY"],
      "startTime": "19:00",
      "endTime": "20:00",
      "studentCount": 15
    }
  ]
}

Response Fields:

필드 타입 설명
divisions array 수련반 목록 (displayOrder 순)
divisions[].id string 수련반 ID (13자리 TSID)
divisions[].sectionId string 소속 수련부 ID
divisions[].sectionName string 소속 수련부 이름
divisions[].name string 수련반 이름
divisions[].displayOrder integer 표시 순서
divisions[].scheduleDays array 수업 요일 배열
divisions[].startTime string 시작 시각 (HH:mm)
divisions[].endTime string 종료 시각 (HH:mm)
divisions[].studentCount integer 등록된 원생 수

7. 수련반 상세 조회

Endpoint: GET /api/v1/divisions/:divisionId

설명: 특정 수련반의 상세 정보를 조회합니다.

Request:

GET /api/v1/divisions/0J5FX8XNCSRPV?dojangId=0J5FX8XNCSRPT HTTP/1.1
Host: api.example.com
Authorization: Bearer {access_token}

Query Parameters:

파라미터 타입 필수 설명
dojangId string 도장 ID

Response (200 OK):

{
  "id": "0J5FX8XNCSRPV",
  "sectionId": "0J5FX8XNCSRPQ",
  "sectionName": "유소년부",
  "name": "유소년부 A반",
  "displayOrder": 1,
  "scheduleDays": ["MONDAY", "WEDNESDAY", "FRIDAY"],
  "startTime": "19:00",
  "endTime": "20:00",
  "studentCount": 15
}

Note: 등록된 원생 목록은 별도 API(GET /enrollments?divisionId=xxx)로 조회합니다.


8. 수련반 생성

Endpoint: POST /api/v1/divisions

설명: 새로운 수련반을 생성합니다.

Request:

POST /api/v1/divisions?dojangId=0J5FX8XNCSRPT HTTP/1.1
Host: api.example.com
Authorization: Bearer {access_token}
Content-Type: application/json

{
  "sectionId": "0J5FX8XNCSRPQ",
  "name": "유소년부 A반",
  "scheduleDays": ["MONDAY", "WEDNESDAY", "FRIDAY"],
  "startTime": "19:00",
  "endTime": "20:00"
}

Query Parameters:

파라미터 타입 필수 설명
dojangId string 도장 ID

Request Body:

필드 타입 필수 설명
sectionId string 수련부 ID
name string 수련반 이름 (1-50자)
scheduleDays array 요일 배열 (MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY)
startTime string 시작 시각 (HH:mm 형식)
endTime string 종료 시각 (HH:mm 형식)

Response (200 OK):

{
  "id": "0J5FX8XNCSRPV",
  "sectionId": "0J5FX8XNCSRPQ",
  "sectionName": "유소년부",
  "name": "유소년부 A반",
  "displayOrder": 1,
  "scheduleDays": ["MONDAY", "WEDNESDAY", "FRIDAY"],
  "startTime": "19:00",
  "endTime": "20:00",
  "studentCount": 0
}

Business Logic:

  1. JWT에서 tenant_id 추출 (SECTION과 동일 테넌트 검증)
  2. DIVISION 레코드 생성
  3. scheduleDays는 Set로 저장
  4. displayOrder는 해당 수련부 내 최대값 + 1로 자동 설정
  5. 권한 검증: dojang.manageDivision

9. 수련반 수정

Endpoint: PATCH /api/v1/divisions/:divisionId

설명: 수련반 정보를 수정합니다.

Request:

PATCH /api/v1/divisions/0J5FX8XNCSRPV?dojangId=0J5FX8XNCSRPT HTTP/1.1
Host: api.example.com
Authorization: Bearer {access_token}
Content-Type: application/json

{
  "name": "유소년부 A반 (수정)",
  "scheduleDays": ["MONDAY", "TUESDAY", "WEDNESDAY", "FRIDAY"],
  "startTime": "18:30",
  "endTime": "19:30"
}

Query Parameters:

파라미터 타입 필수 설명
dojangId string 도장 ID

Response (200 OK):

{
  "id": "0J5FX8XNCSRPV",
  "sectionId": "0J5FX8XNCSRPQ",
  "sectionName": "유소년부",
  "name": "유소년부 A반 (수정)",
  "displayOrder": 1,
  "scheduleDays": ["MONDAY", "TUESDAY", "WEDNESDAY", "FRIDAY"],
  "startTime": "18:30",
  "endTime": "19:30",
  "studentCount": 15
}

10. 수련반 삭제

Endpoint: DELETE /api/v1/divisions/:divisionId

설명: 수련반을 삭제합니다 (등록된 원생이 있으면 삭제 불가).

Request:

DELETE /api/v1/divisions/0J5FX8XNCSRPV?dojangId=0J5FX8XNCSRPT HTTP/1.1
Host: api.example.com
Authorization: Bearer {access_token}

Query Parameters:

파라미터 타입 필수 설명
dojangId string 도장 ID

Response (204 No Content)

Business Logic:

  1. 등록된 원생(ENROLLMENT) 존재 여부 확인
  2. 등록된 원생이 있으면 400 Bad Request 응답
  3. 없으면 DIVISION 레코드 삭제 (소프트 삭제)

Error Response (400 Bad Request):

{
  "code": "HAS_ENROLLED_STUDENTS",
  "message": "등록된 원생이 존재하여 삭제할 수 없습니다",
  "timestamp": "2026-01-08T12:00:00Z"
}

11. 수련반 순서 변경

Endpoint: PATCH /api/v1/divisions/reorder

설명: 특정 수련부 내 수련반들의 표시 순서를 변경합니다.

Request:

PATCH /api/v1/divisions/reorder?dojangId=0J5FX8XNCSRPT HTTP/1.1
Host: api.example.com
Authorization: Bearer {access_token}
Content-Type: application/json

{
  "sectionId": "0J5FX8XNCSRPQ",
  "divisionIds": ["0J5FX8XNCSRPW", "0J5FX8XNCSRPV", "0J5FX8XNCSRPX"]
}

Query Parameters:

파라미터 타입 필수 설명
dojangId string 도장 ID

Request Body:

필드 타입 필수 설명
sectionId string 수련부 ID
divisionIds array 수련반 ID 목록 (순서대로 displayOrder 부여)

Response (204 No Content)

Business Logic:

  1. 배열 순서대로 displayOrder 1, 2, 3... 부여
  2. 해당 수련부의 수련반만 변경 가능
  3. 다른 수련부의 수련반 ID가 포함되면 400 Bad Request

12. 수련반 등록 원생 목록 조회

Endpoint: GET /api/v1/enrollments

설명: 특정 수련반에 등록된 원생 목록을 조회합니다.

Request:

GET /api/v1/enrollments?dojangId=0J5FX8XNCSRPT&divisionId=0J5FX8XNCSRPV HTTP/1.1
Host: api.example.com
Authorization: Bearer {access_token}

Query Parameters:

파라미터 타입 필수 설명
dojangId string 도장 ID
divisionId string 수련반 ID

Response (200 OK):

{
  "students": [
    {
      "studentId": "0J5FX8XNCSRPY",
      "studentName": "홍길동",
      "enrolledAt": "2025-01-20T10:00:00"
    },
    {
      "studentId": "0J5FX8XNCSRPZ",
      "studentName": "김철수",
      "enrolledAt": "2025-01-22T14:30:00"
    }
  ]
}

Response Fields:

필드 타입 설명
students array 등록된 원생 목록
students[].studentId string 원생 ID
students[].studentName string 원생 이름
students[].enrolledAt datetime 등록 일시

13. 원생 등록

Endpoint: POST /api/v1/enrollments

설명: 수련반에 원생을 등록합니다.

Request:

POST /api/v1/enrollments?dojangId=0J5FX8XNCSRPT&divisionId=0J5FX8XNCSRPV HTTP/1.1
Host: api.example.com
Authorization: Bearer {access_token}
Content-Type: application/json

{
  "studentId": "0J5FX8XNCSRPY"
}

Query Parameters:

파라미터 타입 필수 설명
dojangId string 도장 ID
divisionId string 수련반 ID

Request Body:

필드 타입 필수 설명
studentId string 등록할 원생 ID

Response (201 Created) - 응답 본문 없음

Business Logic:

  1. ENROLLMENT 레코드 생성
  2. 중복 등록 방지: (division_id, student_id) UNIQUE 제약
  3. 한 원생이 여러 수련반에 등록 가능

14. 원생 일괄 등록

Endpoint: POST /api/v1/enrollments/bulk

설명: 수련반에 여러 원생을 일괄 등록합니다.

Request:

POST /api/v1/enrollments/bulk?dojangId=0J5FX8XNCSRPT&divisionId=0J5FX8XNCSRPV HTTP/1.1
Host: api.example.com
Authorization: Bearer {access_token}
Content-Type: application/json

{
  "studentIds": ["0J5FX8XNCSRPY", "0J5FX8XNCSRPZ", "0J5FX8XNCSRP0"]
}

Query Parameters:

파라미터 타입 필수 설명
dojangId string 도장 ID
divisionId string 수련반 ID

Request Body:

필드 타입 필수 설명
studentIds array 등록할 원생 ID 목록

Response (200 OK):

{
  "successCount": 2,
  "failedCount": 1,
  "failedStudentIds": ["0J5FX8XNCSRP0"]
}

Response Fields:

필드 타입 설명
successCount integer 등록 성공 수
failedCount integer 등록 실패 수
failedStudentIds array 실패한 원생 ID 목록 (이미 등록된 경우 등)

15. 원생 등록 해제

Endpoint: DELETE /api/v1/enrollments/:studentId

설명: 수련반에서 원생 등록을 해제합니다.

Request:

DELETE /api/v1/enrollments/0J5FX8XNCSRPY?dojangId=0J5FX8XNCSRPT&divisionId=0J5FX8XNCSRPV HTTP/1.1
Host: api.example.com
Authorization: Bearer {access_token}

Query Parameters:

파라미터 타입 필수 설명
dojangId string 도장 ID
divisionId string 수련반 ID

Response (204 No Content)

Business Logic:

  1. ENROLLMENT 레코드 삭제 (소프트 삭제)
  2. 과거 출석 이력은 유지됨

Last Updated: 2026-01-08

Clone this wiki locally