Phase 11. 이메일 발송 환경 및 자동 발송
This commit is contained in:
+60
-75
@@ -432,86 +432,71 @@ chocoadmin/
|
||||
|
||||
> `/maestros/[maestroId]` 상세 화면에서 관리자 계정 정보 수정과 학생 목록 조회를 완성한다.
|
||||
|
||||
- [ ] 기존 `mouse-typing` 마에스트로 정보 수정 로직 조사
|
||||
- [ ] 이름 변경 시 중복 검사 기준 확인 (`maestro.Name`, 자기 자신 제외)
|
||||
- [ ] 이메일 변경 처리와 로그 형식 확인
|
||||
- [ ] 입장코드 수정 대상 컬럼과 기존 값 생성/검증 규칙 확인
|
||||
- [ ] `maestro_log.Type` / `Remark` 형식을 기존 서비스와 맞춤
|
||||
- [ ] 마에스트로 정보 수정 API 구현 (`PATCH /api/maestros/[id]`)
|
||||
- [ ] Zod 요청 스키마 정의: 이름, 이메일, 상태, 계정유형, 사용 가능일, 입장코드
|
||||
- [ ] 관리자 인증 및 권한 검증
|
||||
- [ ] 이름 중복 검사: 다른 계정이 사용 중이면 저장 실패 응답
|
||||
- [ ] 트랜잭션으로 `maestro` 정보 수정
|
||||
- [ ] 변경 전/후 값을 포함해 `maestro_log` 기록
|
||||
- [ ] 변경 없음, 유효하지 않은 상태값, 존재하지 않는 마에스트로에 대한 응답 정책 정리
|
||||
- [ ] 마에스트로 상세 화면 수정 폼 구현
|
||||
- [ ] 이름/이메일 입력
|
||||
- [ ] 상태 콤보박스
|
||||
- [ ] 계정유형 콤보박스
|
||||
- [ ] 사용 가능일 입력
|
||||
- [ ] 입장코드 수정 콤보박스
|
||||
- [ ] 저장 전 확인, 저장 중 비활성화, 성공/실패 토스트
|
||||
- [ ] 학생 목록 API 구현 (`GET /api/maestros/[id]/students`)
|
||||
- [ ] 전체 학생 목록 조회
|
||||
- [ ] 서버 사이드 페이지네이션
|
||||
- [ ] 이름 검색
|
||||
- [ ] 정렬 기준과 기본 page size 정의
|
||||
- [ ] 학생 목록 UI 구현
|
||||
- [ ] 이름 검색 입력
|
||||
- [ ] 페이지네이션 컨트롤
|
||||
- [ ] 빈 목록/검색 결과 없음 상태
|
||||
- [ ] 검증
|
||||
- [ ] 이름 중복 저장 실패 확인
|
||||
- [ ] 정보 수정 성공 시 DB 반영과 `maestro_log` 기록 확인
|
||||
- [ ] 학생 목록 페이지네이션/검색 동작 확인
|
||||
- [ ] 비인증 접근 차단 확인
|
||||
- [x] 기존 `mouse-typing` 마에스트로 정보 수정 로직 조사
|
||||
- [x] 이름 변경 시 중복 검사 기준 확인 (`maestro.Name`, 자기 자신 제외)
|
||||
- [x] 이메일 변경 처리와 로그 형식 확인
|
||||
- [x] 입장코드 수정 대상 컬럼과 기존 값 생성/검증 규칙 확인
|
||||
- [x] `maestro_log.Type` / `Remark` 형식을 기존 서비스와 맞춤
|
||||
- [x] 마에스트로 정보 수정 API 구현 (`PATCH /api/maestros/[id]`)
|
||||
- [x] Zod 요청 스키마 정의: 이름, 이메일, 상태, 계정유형, 사용 가능일, 입장코드
|
||||
- [x] 관리자 인증 및 권한 검증
|
||||
- [x] 이름 중복 검사: 다른 계정이 사용 중이면 저장 실패 응답
|
||||
- [x] 트랜잭션으로 `maestro` 정보 수정
|
||||
- [x] 변경 전/후 값을 포함해 `maestro_log` 기록
|
||||
- [x] 변경 없음, 유효하지 않은 상태값, 존재하지 않는 마에스트로에 대한 응답 정책 정리
|
||||
- [x] 마에스트로 상세 화면 수정 폼 구현
|
||||
- [x] 이름/이메일 입력
|
||||
- [x] 상태 콤보박스
|
||||
- [x] 계정유형 콤보박스
|
||||
- [x] 사용 가능일 입력
|
||||
- [x] 입장코드 수정 콤보박스
|
||||
- [x] 저장 전 확인, 저장 중 비활성화, 성공/실패 토스트
|
||||
- [x] 학생 목록 API 구현 (`GET /api/maestros/[id]/students`)
|
||||
- [x] 전체 학생 목록 조회
|
||||
- [x] 서버 사이드 페이지네이션
|
||||
- [x] 이름 검색
|
||||
- [x] 정렬 기준과 기본 page size 정의
|
||||
- [x] 학생 목록 UI 구현
|
||||
- [x] 이름 검색 입력
|
||||
- [x] 페이지네이션 컨트롤
|
||||
- [x] 빈 목록/검색 결과 없음 상태
|
||||
- [x] 검증
|
||||
- [x] 이름 중복 저장 실패 확인
|
||||
- [x] 정보 수정 성공 시 DB 반영과 `maestro_log` 기록 확인
|
||||
- [x] 학생 목록 페이지네이션/검색 동작 확인
|
||||
- [x] 비인증 접근 차단 확인
|
||||
|
||||
### Phase 11. 이메일 발송 환경 및 자동 발송
|
||||
|
||||
> 기존 `chocomae` 서비스의 관리자 승인 완료 메일을 `chocoadmin`에서도 동일하게 발송한다.
|
||||
> 상세 계획: `docs/phase/phase11.md`
|
||||
|
||||
- [ ] 기존 이메일 발송 설정 이관 준비
|
||||
- [ ] 기존 서비스 파일 확인: `/Users/jisangs/work/jinaju/git/web/mouse-typing/src/web/server/mail/send_jinaju_mail.php`
|
||||
- [ ] 기존 서비스 파일 확인: `/Users/jisangs/work/jinaju/git/web/mouse-typing/src/web/server/mail/mail_contents.php`
|
||||
- [ ] 기존 서비스 파일 확인: `/Users/jisangs/work/jinaju/git/web/mouse-typing/src/web/server/mail/mail_setting.php`
|
||||
- [ ] 발송자 이름/주소, BCC, SMTP host/port/security/auth 설정을 환경변수로 정리
|
||||
- [ ] 기존 코드의 하드코딩된 SMTP/API 키를 신규 서비스 코드에 복사하지 않고 `.env` / 배포 시크릿으로 분리
|
||||
- [ ] 메일 발송 모듈 구현 (`lib/mail.ts`)
|
||||
- [ ] 공통 메일 클라이언트 생성
|
||||
- [ ] 발송자, 수신자, BCC, 제목, HTML/텍스트 본문 구성
|
||||
- [ ] 메일 발송 성공/실패 로그 기록
|
||||
- [ ] 운영에서 민감정보가 로그에 남지 않도록 마스킹
|
||||
- [ ] 연장 완료 이메일 템플릿 구현
|
||||
- [ ] 호출 기준: `/Users/jisangs/work/jinaju/git/web/mouse-typing/src/web/server/admin/extension_maestro.php:29`
|
||||
- [ ] 제목: `[초코마에] {마에스트로명} - 마에스트로 계정 유효기간 연장 완료`
|
||||
- [ ] 내용: 유효기간 +1년 연장 완료, 새 유효기간 안내
|
||||
- [ ] 관리자가 연장 승인하고 DB 커밋이 정상 완료된 후 자동 발송
|
||||
- [ ] 업그레이드 완료 이메일 템플릿 구현
|
||||
- [ ] 호출 기준: `/Users/jisangs/work/jinaju/git/web/mouse-typing/src/web/server/admin/upgrade_maestro.php:30`
|
||||
- [ ] 제목: `[초코마에] {마에스트로명} - 마에스트로 계정의 요금제 업그레이드 완료 알림`
|
||||
- [ ] 내용: 기존 요금제에서 상위 요금제로 변경 완료, 유효기간 오늘부터 1년
|
||||
- [ ] 관리자가 업그레이드 승인하고 DB 커밋이 정상 완료된 후 자동 발송
|
||||
- [ ] 승인 API에 이메일 자동 발송 연결
|
||||
- [ ] `PATCH /api/extension-requests/[id]` 승인 완료 후 연장 완료 메일 발송
|
||||
- [ ] `PATCH /api/upgrade-requests/[id]` 승인 완료 후 업그레이드 완료 메일 발송
|
||||
- [ ] 메일 발송 실패 시 승인 결과 롤백 여부를 정책으로 확정하고 구현
|
||||
- [ ] 동일 승인 건 재호출 시 이메일 중복 발송 방지 정책 정리
|
||||
- [ ] 환경변수 추가
|
||||
- [ ] `MAIL_FROM_NAME`
|
||||
- [ ] `MAIL_FROM_ADDRESS`
|
||||
- [ ] `MAIL_BCC_ADDRESS`
|
||||
- [ ] `MAIL_SMTP_HOST`
|
||||
- [ ] `MAIL_SMTP_PORT`
|
||||
- [ ] `MAIL_SMTP_SECURE`
|
||||
- [ ] `MAIL_SMTP_USER`
|
||||
- [ ] `MAIL_SMTP_PASSWORD`
|
||||
- [ ] `MAIL_SEND_ENABLED`
|
||||
- [ ] 문서화 및 검증
|
||||
- [ ] `.env.example` 또는 배포 문서에 메일 환경변수 설명 추가
|
||||
- [ ] local/stage에서 테스트 수신자 또는 sandbox 설정으로 발송 테스트
|
||||
- [ ] 연장 승인 완료 후 이메일 제목/본문/수신자/BCC 확인
|
||||
- [ ] 업그레이드 승인 완료 후 이메일 제목/본문/수신자/BCC 확인
|
||||
- [ ] 메일 발송 실패 로그와 관리자 화면 응답 확인
|
||||
- [x] 기존 이메일 발송 설정 이관 준비
|
||||
- [x] 기존 서비스 파일 확인: `send_jinaju_mail.php` — SMTP gmail:465, SMTPS, 발송자/BCC 주소 확인
|
||||
- [x] 기존 서비스 파일 확인: `mail_contents.php` — 연장/업그레이드 완료 이메일 제목·본문 확인
|
||||
- [x] 기존 서비스 파일 확인: `mail_setting.php` — From, BCC, sender_name 확인
|
||||
- [x] `.env.local`에 메일 환경변수 추가 (SMTP 비밀번호는 배포 시크릿으로 분리)
|
||||
- [x] `nodemailer` 패키지 설치 (`pnpm add nodemailer && pnpm add -D @types/nodemailer`)
|
||||
- [x] 메일 발송 모듈 구현 (`lib/mail.ts`)
|
||||
- [x] `createTransporter()` — 환경변수 기반 SMTP transport
|
||||
- [x] `sendMail()` — 공통 발송 함수 (`MAIL_SEND_ENABLED` 체크, From/BCC/ReplyTo 구성, 성공·실패 로그)
|
||||
- [x] `sendExtensionDoneEmail()` — 연장 완료 이메일 템플릿
|
||||
- [x] `sendUpgradeDoneEmail()` — 업그레이드 완료 이메일 템플릿 (체험→유료 / 유료→유료 내부 분기)
|
||||
- [x] `lib/extension-requests.ts` 수정
|
||||
- [x] `approveExtensionRequest` 반환값에 `maestroName`, `maestroEmail` 추가 (이미 `include: { maestro: true }` 있음 — 추가 쿼리 불필요)
|
||||
- [x] `lib/upgrade-requests.ts` 수정
|
||||
- [x] `getActionTarget`에 `include: { maestro: { select: { Name, Email } } }` 추가
|
||||
- [x] `approveUpgradeRequest` 반환값에 `maestroName`, `maestroEmail`, `registeredActivateStatus`, `registeredAccountType`, `requestedAccountType` 추가
|
||||
- [x] 승인 API에 이메일 자동 발송 연결
|
||||
- [x] `app/api/extension-requests/[id]/route.ts` — 승인 후 `void sendExtensionDoneEmail(...)` 호출
|
||||
- [x] `app/api/upgrade-requests/[id]/route.ts` — 승인 후 `void sendUpgradeDoneEmail(...)` 호출
|
||||
- [x] 메일 발송 실패 정책 적용: 실패 시 `logger.error`만 기록, 승인 결과(200)는 그대로 반환 (롤백 없음)
|
||||
- [x] 검증
|
||||
- [x] `MAIL_SEND_ENABLED=false`에서 승인 시 `send skipped` 로그 확인, 승인 결과 200 정상
|
||||
- [x] `MAIL_SEND_ENABLED=true`에서 연장 승인 후 이메일 제목/본문/수신자/BCC 확인
|
||||
- [ ] 업그레이드 승인 후 체험→유료 케이스: `0원 : 무료 체험 기간` 본문 확인
|
||||
- [ ] 업그레이드 승인 후 유료→유료 케이스: `{prev_price}원` 본문 확인
|
||||
- [x] SMTP 오류 시 승인 API 200 응답 + `error: send failed` 로그 확인
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user