[일괄다운로드 PR1] BulkReportDownload 모델 + 마이그레이션
ID: 2d6027ef-f080-454c-b637-0d8fb0e249c3
## 설명
일괄 리포트 다운로드 비동기 처리를 위한 DB 레이어.
### 모델: BulkReportDownload
- `workspace_id` (references, not null, index)
- `user_id` (references, not null) — 요청한 관리자
- `status` (string, default: "pending") — pending/processing/completed/failed
- `member_count` (integer) — 선택된 멤버 수
- `processed_count` (integer, default: 0) — 진행 상황
- `error_message` (text, nullable)
- `member_ids` (text[]) — 선택된 workspace_member IDs
- `has_one_attached :file` (ZIP)
### TDD
1. validation: workspace, user 필수
2. status enum: pending → processing → completed/failed
3. scope: expired (created_at < 7.days.ago)
4. association: belongs_to workspace/user, has_one_attached file
### 참고 패턴
- Active Storage: `Coaching::Recording`, `Study::Assignment` 등 4개 모델에서 사용 중
## 완료 기준
- [ ] 마이그레이션 정상 실행
- [ ] 모델 validation, scope, enum 테스트 통과
- [ ] fixture 생성
첨부 이미지
이미지 추가 (Ctrl+V로 붙여넣기 또는 클릭)
JPEG, PNG, GIF, WebP / 최대 10MB
활동 로그
-
팀팀리드 일괄다운로드 비동기 처리 전체 구현 완료
2026년 03월 30일 01:43:37
상세 보기
## 구현 완료된 PR (5개)
### PR1: BulkReportDownload 모델 + 마이그레이션
- `db/migrate/20260330012810_create_bulk_report_downloads.rb`
- `app/models/bulk_report_download.rb` (enum status, scope expired/active, has_one_attached :file)
- `test/models/bulk_report_download_test.rb` (17 tests)
- `test/fixtures/bulk_report_downloads.yml` (5 fixtures)### PR2: BulkReportGenerateJob + CleanupJob
- `app/jobs/bulk_report_generate_job.rb` (PDF→ZIP→Active Storage, 순차 처리, GC 관리)
- `app/jobs/bulk_report_cleanup_job.rb` (7일 만료 삭제)
- `config/recurring.yml` 에 매일 2am cleanup 등록
- 테스트 9 runs### PR3: BulkReportMailer
- `app/mailers/bulk_report_mailer.rb` (completed/failed)
- `app/views/bulk_report_mailer/completed.html.erb`, `failed.html.erb`
- i18n 4개 언어 (ko, en, zh, vi)
- 테스트 6 runs### PR4: Controller + Routes 비동기 전환
- `handle_bulk_download` 동기→비동기 전환 (Job enqueue)
- `bulk_download_status` (JSON 폴링), `bulk_download_file` (파일 다운로드)
- 중복 요청 방지
- 테스트 10 runs### PR5: View + Stimulus 폴링 배너
- `bulk_download_status_controller.js` (3초 폴링, 상태별 UI)
- `_bulk_download_banner.html.erb` (progress bar, download button)
- i18n 4개 언어## 전체 테스트
- **42 runs, 90 assertions, 0 failures, 0 errors** -
팀팀리드 상태 변경: 진행 중 → 리뷰
2026년 03월 30일 01:30:05
-
팀팀리드 작업 시작 - 일괄다운로드 PR1 (모델 + 마이그레이션)
2026년 03월 30일 01:26:11
상세 보기
## 작업 계획
- 목표: BulkReportDownload 모델 + 마이그레이션 + 테스트 + fixture
- 접근 방식: TDD (테스트 먼저 → 구현)## 전체 일괄다운로드 진행 순서
1. **PR1 (현재)**: 모델 + 마이그레이션
2. PR2 + PR3 (PR1 완료 후 병렬): Job + Mailer
3. PR4 (PR2 완료 후): Controller + Routes
4. PR5 (PR4 완료 후): View + Stimulus -
팀팀리드 티켓 클레임 완료
2026년 03월 30일 01:26:07
-
팀팀리드 기능 계획 수립 - 워크스페이스 리포트 일괄 다운로드 비동기 ��리
2026년 03월 30일 00:48:17
상세 보기
## 기능 개요
- 일괄 리포트 ��운로드 시 동기 PDF 생성으로 인한 HTTP 타임아웃 해결
- 백그라운드 Job으로 전환 + 폴링 방식 상태 표시 + 이메일 알림## 분석 결과
- 영향 범위: members_controller, PdfGenerator, routes, members views, i18n
- 기존 패턴: AiInsightGenerateJob(폴링), GiftMailer(���메일), Active Storage(4개 모델)
- Turbo Stream broadcast 미사용 → 폴링 방식 채택## 생성된 티켓 (5개)
- [PR1] BulkReportDownload 모델 + 마이그레이��� (high)
- [PR2] BulkReportGenerateJob + CleanupJob (high)
- [PR3] BulkReportMailer (medium)
- [PR4] Controller + Routes 비동기 전환 (high)
- [PR5] View + Stimulus 폴링 배너 UI (high)## 리스크
- Grover 메모리 → 순차 처리 + 주기적 GC
- 디스크 누적 → 7일 만료 CleanupJob (매일 2am)
- 중복 요청 → pending/processing 존재 시 거부## 기술적 결정
- ActionCable 인프라 없음 → Turbo Stream broadcast 대신 Stimulus 폴링 (3초)
- Active Storage local disk 사용 (프로덕션 전환 시 S3 검토) -
팀팀리드 상태 변경: 할 일 → 백로그
2026년 03월 30일 00:48:04