Files
chocoadmin/docs/business-rules.md
T

17 KiB

기존 관리자 비즈니스 규칙

작성일: 2026-06-09

1. 개요

이 문서는 기존 mouse-typing 관리자 기능을 조사해 신규 choco-admin에서 재현해야 할 비즈니스 규칙을 정리한 것이다.

조사 대상:

  • 기존 서비스: /Users/jisangs/work/jinaju/git/web/mouse-typing
  • 관리자 화면: src/web/admin/
  • 관리자 서버: src/web/server/admin/
  • 공통 로그 유틸: src/web/server/lib/maestro_log.php
  • 계정 표시/계산 유틸: src/web/js/lib/account_info.js, src/web/js/maestro_available_date.js

중요 결론:

  • 관리자 비밀번호는 MariaDB PASSWORD() 함수로 검증한다.
  • 연장 승인은 기존 만료일 기준 1년 연장하되, 만료된 계정은 오늘 기준 1년 연장한다.
  • 기존 연장 승인 서버는 날짜를 직접 계산하지 않고 화면에서 전달한 new_available_date를 저장한다.
  • 업그레이드 승인은 AccountType, ActivateStatus, AvailableActivateDateTime만 변경하고 PlayerCount는 변경하지 않는다.
  • 기존 관리자에는 연장 취소/업그레이드 거절 버튼이 없다. 승인 처리 중 같은 마에스트로의 다른 요청을 Status=2로 닫는 동작만 있다.
  • 기존 변경 처리에는 명시적 트랜잭션이 없다.

2. 기존 관리자 파일 맵

기존 화면 서버 파일 역할 신규 choco-admin 매핑
admin/login.html server/admin/login.php 관리자 로그인 /login, NextAuth Credentials Provider
admin/admin_all_list.html server/admin/maestro_all_list.php 전체 마에스트로 목록 조회 /maestros, GET /api/maestros
admin/admin_register_list.html server/admin/maestro_registered_list.php, server/admin/register_maestro.php 미승인 마에스트로 조회 및 등록 승인 MVP 외 또는 상세 보조 규칙
admin/admin_extension_list.html server/admin/maestro_extension_list.php, server/admin/extension_maestro.php 연장 요청 조회 및 승인 /extension-requests, PATCH /api/extension-requests/[id]
admin/admin_upgrade_list.html server/admin/maestro_upgrade_list.php, server/admin/upgrade_maestro.php 업그레이드 요청 조회 및 승인 /upgrade-requests, PATCH /api/upgrade-requests/[id]
admin/admin_expiration_list.html 없음 정적 골격만 존재, 실제 조회 로직 없음 MVP 제외
admin/admin_send_email.html server/mail/send_mail_test.php 테스트 메일 발송 화면 MVP 제외
admin/admin_header.html 없음 관리자 메뉴 링크 공통 사이드바/헤더

3. 상태값 코드표

maestro.AccountType

의미 정원 금액
1 20명 20 10,000
2 50명 50 20,000
3 100명 100 30,000
4 500명 500 40,000
5 1,000명 1,000 50,000
100 학생체험 - -
101 마에체험 - -

maestro.ActivateStatus

기존 표시 의미
0 미승인 / 입금대기 가입 후 관리자 승인 전
1 체험 체험 계정
2 활성화 유료 활성 계정
100 등록 취소 / 환불 등록 취소 또는 환불 상태

maestro_extension.Status

기존 표시 의미
1 요청 연장 요청
2 취소 닫힌 요청
3 업그레이드 적용 코드상 공통 표시 문구이나 실제 의미는 연장 적용

maestro_upgrade.Status

기존 표시 의미
1 요청 업그레이드 요청
2 취소 닫힌 요청
3 업그레이드 적용 업그레이드 적용

4. 로그인/관리자 인증 규칙

기존 흐름:

  1. login.html에서 admin_name, passwordserver/admin/login.php로 POST한다.
  2. get_admin_id($adminName)에서 admin.Name = ? 조건으로 관리자 존재 여부를 먼저 확인한다.
  3. login($adminName, $password)에서 admin.Name = ? AND admin.Password = PASSWORD(?) 조건으로 검증한다.
  4. 응답 데이터로 adminID, accountType, activateStatus를 반환한다.

실패 조건:

조건 error_code message
Name에 해당하는 관리자 없음 not_registered_id 등록되지 않은 서비스 관리자 아이디입니다.
비밀번호 검증 결과 없음 no_data 또는 wrong_password 로그인하지 못했습니다. / 비밀번호가 틀렸습니다.
ActivateStatus === 0 not_activated 서비스 관리자 계정이 아직 활성화되지 않았습니다.

신규 구현 규칙:

  • 기존 계정 호환을 위해 최초 구현은 MariaDB PASSWORD() 함수를 이용해 검증한다.
  • NextAuth 세션에는 최소 adminID, accountType, activateStatus를 포함한다.
  • ActivateStatus = 0 관리자는 로그인시키지 않는다.
  • PASSWORD()는 보안상 낡은 방식이므로, 해시 업그레이드는 별도 마이그레이션 과제로 분리한다.

5. 마에스트로 목록 조회 규칙

전체 목록

기존 서버: server/admin/maestro_all_list.php

검색어가 없을 때:

  • 테이블: maestro
  • 컬럼: MaestroID, Name, AccountType, ActivateStatus, AvailableActivateDateTime, AcceptClausesDateTime, PlayerCount
  • 정렬: MaestroID DESC

검색어가 있을 때:

  • 조건: Name LIKE CONCAT('%', ?, '%')
  • 정렬: MaestroID DESC
  • 주의: 기존 검색 쿼리는 AvailableActivateDateTime을 조회하지 않는데 화면은 해당 값을 사용한다. 신규 구현에서는 전체/검색 결과 모두 동일 컬럼을 반환해야 한다.

기존 화면 표시:

  • 상태 텍스트는 accountStatus(accountType, activateStatus)로 계산한다.
  • AvailableActivateDateTime0으로 시작하면 빈 문자열로 표시한다.
  • 비활성화 버튼은 disabled 상태이며 동작하지 않는다.

신규 구현 규칙:

  • Name, Email, MaestroID 검색을 지원하되 기존 기본 정렬은 MaestroID DESC로 시작한다.
  • 전체/검색 결과의 반환 컬럼 차이를 만들지 않는다.

미승인 등록 목록

기존 서버: server/admin/maestro_registered_list.php

  • 테이블: maestro
  • 조건: ActivateStatus = 0
  • 검색 조건: Name LIKE CONCAT('%', ?, '%') AND ActivateStatus = 0
  • 컬럼: MaestroID, Name, AccountType, AcceptClausesDateTime
  • 정렬: MaestroID DESC

6. 등록/활성화 처리 규칙

기존 서버: server/admin/register_maestro.php

처리 순서:

  1. maestro.ActivateStatus = 1로 변경한다.
  2. maestro.AvailableActivateDateTime = '2022-07-31 23:59:59'로 변경한다.
  3. player에 테스트 플레이어 Name='마에스트로', EnterCode='', AccountType=1을 추가한다.
  4. 추가된 테스트 플레이어를 maestro.MaestroTestID에 저장한다.
  5. app.Status = 1인 앱을 모두 active_app에 추가한다.
  6. 샘플 학생 4명을 player.AccountType = 0으로 추가한다.
  7. player.AccountType = 0 학생 수를 세어 maestro.PlayerCount에 저장한다.
  8. 등록 완료 메일을 발송한다.
  9. maestro_logregister_maestro 로그를 기록한다.

주의:

  • 코드에는 DATE_ADD(NOW(), INTERVAL 1 YEAR)DATE_ADD(NOW(), INTERVAL 14 DAY)가 주석으로 남아 있지만 실제 실행 쿼리는 고정일 2022-07-31 23:59:59다.
  • 현재 MVP의 핵심 변경 기능은 연장/업그레이드이므로 등록 승인은 별도 범위로 둘 수 있다.

7. 연장 신청 조회/승인 규칙

요청 생성

기존 서버: server/maestro/request_extension_maestro.php

  • maestro_extensionAccountType, RequestedDateTime = NOW(), Status = 1, MaestroID를 INSERT한다.
  • 같은 마에스트로의 기존 요청 중복 여부는 검사하지 않는다.
  • INSERT 후 MaestroID 기준 전체 연장 요청 수가 1개 이상인지 단순 확인한다.
  • 입금 안내 메일을 발송한다.

관리자 목록 조회

기존 서버: server/admin/maestro_extension_list.php

검색어가 없을 때:

  • 테이블: maestro_extension E, maestro M
  • 조건: E.Status < 2 AND E.MaestroID = M.MaestroID
  • 컬럼: E.MaestroExtensionID, E.MaestroID, M.Name, E.AccountType, E.RequestedDateTime, M.AvailableActivateDateTime, E.Status
  • 정렬: E.MaestroExtensionID DESC

검색어가 있을 때:

  • 조건: M.Name LIKE CONCAT('%', ?, '%') AND E.MaestroID = M.MaestroID
  • 주의: 검색 쿼리에는 E.Status < 2 조건이 없다. 신규 구현에서는 기본 정책에 맞게 상태 필터를 명시적으로 제공해야 한다.

관리자 승인

기존 화면: admin/admin_extension_list.html

  • availableActivateDateTime의 날짜 부분을 기준으로 새 만료일을 계산한다.
  • 계산 유틸: src/web/js/maestro_available_date.js
  • 현재 만료일이 지났으면 오늘 기준 1년 후 날짜를 사용한다.
  • 현재 만료일이 지나지 않았으면 기존 만료일 기준 1년 후 날짜를 사용한다.
  • 서버에는 new_available_date 문자열을 POST한다.

기존 서버: server/admin/extension_maestro.php

처리 순서:

  1. maestro.ActivateStatus = 2, maestro.AvailableActivateDateTime = DATE_FORMAT(?, '%Y-%m-%d')로 변경한다.
  2. 같은 MaestroIDmaestro_extension.Status = 1 요청을 모두 Status = 2로 변경한다.
  3. 선택한 MaestroExtensionID 요청을 Status = 3으로 변경한다.
  4. 연장 완료 메일을 발송한다.
  5. maestro_logextension_maestro 로그를 기록한다.

로그:

  • Type: extension_maestro
  • Remark: {maestro_name}({registered_account_type})

신규 구현 규칙:

  • 날짜 계산은 클라이언트가 아니라 서버에서 수행한다.
  • 기존 규칙과 동일하게 만료 전이면 기존 만료일 기준 +1년, 만료 후면 현재일 기준 +1년으로 계산한다.
  • AvailableActivateDateTime 저장 시 기존 서버는 날짜만 저장하므로 시간은 DB 기본 파싱 결과를 고려해야 한다. 신규 구현에서는 일관성을 위해 YYYY-MM-DD 00:00:00 또는 기존 호환 형식을 명시한다.
  • 승인 전 선택한 요청이 Status = 1인지 확인한다.
  • 트랜잭션 안에서 maestro, maestro_extension, maestro_log를 함께 처리한다.
  • 같은 마에스트로의 다른 Status = 1 요청을 Status = 2로 닫은 뒤 선택 요청을 Status = 3으로 적용하는 기존 동작을 재현한다.

8. 업그레이드 신청 조회/승인 규칙

요청 생성

기존 서버: server/maestro/request_upgrade_maestro.php

  • maestro_upgradeRegisteredActivateStatus, RegisteredAccountType, RequestedAccountType, RequestedDateTime = NOW(), Status = 1, MaestroID를 INSERT한다.
  • 같은 마에스트로의 기존 요청 중복 여부는 검사하지 않는다.
  • INSERT 후 MaestroID 기준 전체 업그레이드 요청 수가 1개 이상인지 단순 확인한다.
  • 체험 계정이면 체험 업그레이드 입금 안내 메일, 그 외에는 일반 업그레이드 입금 안내 메일을 발송한다.

관리자 목록 조회

기존 서버: server/admin/maestro_upgrade_list.php

검색어가 없을 때:

  • 테이블: maestro_upgrade U, maestro M
  • 조건: U.Status < 2 AND U.MaestroID = M.MaestroID
  • 컬럼: U.MaestroUpgradeID, U.MaestroID, M.Name, U.RegisteredActivateStatus, U.RegisteredAccountType, U.RequestedAccountType, U.RequestedDateTime, M.AvailableActivateDateTime, U.Status
  • 정렬: U.MaestroUpgradeID DESC

검색어가 있을 때:

  • 조건: M.Name LIKE CONCAT('%', ?, '%') AND U.MaestroID = M.MaestroID
  • 주의: 검색 쿼리에는 U.Status < 2 조건이 없다. 신규 구현에서는 상태 필터를 명시적으로 제공해야 한다.

관리자 승인

기존 화면: admin/admin_upgrade_list.html

  • Status = 1인 요청만 승인 버튼을 표시한다.
  • 체험 계정(RegisteredActivateStatus = 1)은 기존 요금제를 trialAccountType으로 표시하고 추가 금액은 요청 요금제 전체 금액으로 계산한다.
  • 그 외 계정은 추가 금액을 RequestedAccountType 금액 - RegisteredAccountType 금액으로 계산한다.

기존 서버: server/admin/upgrade_maestro.php

처리 순서:

  1. maestro.AccountType = upgrade_account_type으로 변경한다.
  2. maestro.ActivateStatus = 2로 변경한다.
  3. maestro.AvailableActivateDateTime = DATE_ADD(NOW(), INTERVAL 1 YEAR)로 변경한다.
  4. 같은 MaestroIDmaestro_upgrade.Status = 1 요청을 모두 Status = 2로 변경한다.
  5. 선택한 MaestroUpgradeID 요청을 Status = 3으로 변경한다.
  6. 체험 계정이면 체험 업그레이드 완료 메일, 그 외에는 일반 업그레이드 완료 메일을 발송한다.
  7. maestro_logupgrade_maestro 로그를 기록한다.

로그:

  • Type: upgrade_maestro
  • Remark: {registered_account_type} -> {upgrade_account_type}

확정 사항:

  • PlayerCount는 변경하지 않는다.
  • AvailableActivateDateTime은 기존 만료일 기준이 아니라 승인 시점 NOW() 기준 1년 후로 설정한다.

신규 구현 규칙:

  • 승인 전 선택한 요청이 Status = 1인지 확인한다.
  • 트랜잭션 안에서 maestro, maestro_upgrade, maestro_log를 함께 처리한다.
  • 같은 마에스트로의 다른 Status = 1 요청을 Status = 2로 닫은 뒤 선택 요청을 Status = 3으로 적용하는 기존 동작을 재현한다.
  • PlayerCount는 업그레이드 승인에서 변경하지 않는다.

9. 취소/거절 규칙

기존 관리자 UI/서버에서 확인된 사실:

  • 연장 신청에 대한 별도 취소 버튼이나 취소 API는 없다.
  • 업그레이드 신청에 대한 별도 거절 버튼이나 거절 API는 없다.
  • Status = 2는 승인 처리 중 같은 마에스트로의 다른 미처리 요청을 닫기 위해 사용된다.
  • 화면 유틸 status()Status = 2를 "취소"로 표시하지만, 관리자가 명시적으로 취소/거절하는 흐름은 구현되어 있지 않다.

신규 구현 판단:

  • docs/plan/project-plan.md의 취소/거절 기능은 기존 관리자 재현이 아니라 신규 보완 기능이다.
  • 취소/거절 API를 만들 경우 Status = 1인 단일 요청만 Status = 2로 변경하고 maestro_log에 별도 로그를 남기는 방식으로 정의해야 한다.
  • 기존 maestro_log.Type에는 취소/거절 전용 타입이 없으므로 신규 타입을 도입할지 기존 타입에 Remark로 표현할지 결정이 필요하다.

권장 신규 로그 타입:

  • cancel_extension_maestro
  • reject_upgrade_maestro

10. maestro_log 기록 규칙

공통 함수: src/web/server/lib/maestro_log.php

INSERT INTO maestro_log (Type, MaestroID, LogDateTime, Remark)
VALUES (?, ?, NOW(), ?)

확인된 로그 타입:

Type 발생 위치 Remark 형식
add_maestro server/maestro/add_maestro.php {maestro_name} / {email} / {account_type}
register_maestro server/admin/register_maestro.php {name} / {email}
extension_maestro server/admin/extension_maestro.php {maestro_name}({registered_account_type})
upgrade_maestro server/admin/upgrade_maestro.php {registered_account_type} -> {upgrade_account_type}
update_maestro_name server/maestro/update_maestro_info.php {previous_name} -> {new_name}
update_maestro_email server/maestro/update_maestro_info.php {previous_email} -> {new_email}

확인 결과:

  • update_maestro 타입은 코드 검색에서 확인되지 않았다.
  • 로그에는 관리자 ID나 관리자 이름이 포함되지 않는다.
  • 로그 시간은 DB 서버의 NOW()를 사용한다.
  • Remark 컬럼은 char(100)이므로 신규 구현에서도 길이 초과에 주의한다.

11. 신규 choco-admin 구현 시 반드시 지켜야 할 규칙

  • 운영 DB 스키마는 변경하지 않는다.
  • 관리자 로그인은 기존 admin.Nameadmin.Password = PASSWORD(?) 호환 검증을 지원한다.
  • 모든 변경 API는 서버에서 현재 상태를 다시 조회하고 Status = 1인지 확인한다.
  • 승인/취소/거절 같은 변경 작업은 트랜잭션으로 묶는다.
  • 연장 승인은 서버에서 새 만료일을 계산한다.
  • 업그레이드 승인은 PlayerCount를 변경하지 않는다.
  • 연장/업그레이드 승인 시 같은 마에스트로의 다른 요청을 Status = 2로 닫고 선택 요청을 Status = 3으로 적용한다.
  • 기존 목록 검색 쿼리의 상태 필터 누락은 그대로 복제하지 말고 명시적 필터로 보완한다.
  • 메일 발송은 트랜잭션 커밋 이후 수행하는 것이 안전하다. 기존 코드는 DB 변경 후 메일을 발송한다.

12. 기존 코드에는 없지만 신규 구현에서 보완할 사항

  • 명시적 트랜잭션: 기존 관리자 변경 로직에는 BEGIN, COMMIT, ROLLBACK이 없다.
  • 중복 처리 방지: 기존 승인 서버는 요청의 현재 Status를 먼저 검증하지 않는다.
  • 서버 사이드 날짜 계산: 기존 연장 승인은 클라이언트 계산값을 신뢰한다.
  • 검색 필터 일관성: 연장/업그레이드 검색 쿼리에 Status < 2 조건이 빠져 있다.
  • 목록 컬럼 일관성: 전체 마에스트로 검색 쿼리에 AvailableActivateDateTime이 빠져 있다.
  • 취소/거절 정의: 기존에는 별도 액션이 없으므로 신규 기능으로 명세화해야 한다.
  • 감사성 강화: 기존 maestro_log에는 관리자 식별자가 없으므로 세션 기반 감사 로그가 필요하면 별도 설계가 필요하다. 단, DB 스키마 변경 없이 구현하려면 Remark에 관리자 정보를 포함하는 방식만 가능하다.