feat(B01,B03): 프로젝트 생성 전 임시 보관함 (temp upload)
라이다 원본은 업로드에 오래 걸려 프로젝트 정보 확정 전에 미리 올릴 수 있어야 한다.
계정에 묶인 임시 보관함을 만들고, 나중에 만든 프로젝트로 자료를 옮겨 쓴다.
저장·DB
- storage/tmp/{user_id}/{batch_id}/ 아래에 프로젝트 저장소와 동일한 구조를 써서
청크 저장·병합 엔진(resolve_upload_destination/merge_upload_chunks)을 그대로 재사용
- 010_temp_upload.sql: temp_upload_batches / temp_upload_files 신설,
upload_sessions.project_id NULL 허용 + temp_batch_id 추가(FK명 조회 후 재생성)
- config: TEMP_UPLOAD_DIR_NAME / TEMP_UPLOAD_RETENTION_DAYS(30) /
TEMP_UPLOAD_CLEANUP_INTERVAL_HOURS(6)
백엔드
- B03_FileInput_Router_Temp.py: 묶음 생성·목록·삭제, 일반/청크 업로드, finalize,
이어올리기 상태 조회, 프로젝트 연결(attach)
- attach: 파일 이동 후 input_files 등록, stage 0 완료, WF1·자동 설계 체인 트리거
- common_util_temp_cleanup.py: 완료 시각 기준 만료분 주기 삭제(서버 시작 시 1회 포함)
프론트엔드
- B01 대시보드 임시 보관함 섹션: 프로젝트 등록과 같은 폼 + 보관 목록.
진행률은 모달이 아니라 리스트 행에 표시, 새로고침 후 이어올리기 지원
- B03 업로드 컨테이너 내부 불러오기 버튼과 선택 모달.
완료된 묶음만 노출하고, 선택 후 업로드를 누르면 이동과 분석으로 이어짐
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
"""임시 보관함(프로젝트 생성 전 업로드) 요청·응답 모델."""
|
||||
|
||||
from typing import Any
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
|
||||
|
||||
class TempBatchCreateRequest(BaseModel):
|
||||
"""보관함 묶음 생성 요청 — 프로젝트 등록 폼과 비슷하게 이름만 받는다."""
|
||||
|
||||
model_config = ConfigDict(extra="forbid", str_strip_whitespace=True)
|
||||
|
||||
name: str = Field(min_length=1, max_length=200)
|
||||
memo: str | None = Field(default=None, max_length=500)
|
||||
|
||||
|
||||
class TempBatchFile(BaseModel):
|
||||
"""묶음 안의 저장 완료 파일 한 건."""
|
||||
|
||||
file_type: str
|
||||
original_filename: str
|
||||
file_size_bytes: int
|
||||
crs_epsg: int | None = None
|
||||
|
||||
|
||||
class TempBatchPendingSession(BaseModel):
|
||||
"""중단된 청크 세션 — 보관함 리스트 행에 진행률로 보여 준다."""
|
||||
|
||||
upload_session_id: str
|
||||
original_filename: str
|
||||
file_size_bytes: int
|
||||
total_chunks: int
|
||||
completed_chunks: int
|
||||
progress_percent: float
|
||||
|
||||
|
||||
class TempBatchItem(BaseModel):
|
||||
"""보관함 목록의 묶음 한 건."""
|
||||
|
||||
batch_id: str
|
||||
name: str
|
||||
memo: str | None = None
|
||||
status: str
|
||||
files: list[TempBatchFile]
|
||||
pending_sessions: list[TempBatchPendingSession]
|
||||
total_size_bytes: int
|
||||
required_complete: bool
|
||||
completed_at: str | None = None
|
||||
expires_at: str | None = None
|
||||
linked_project_id: str | None = None
|
||||
created_at: str | None = None
|
||||
|
||||
|
||||
class TempBatchListResponse(BaseModel):
|
||||
"""내 보관함 전체 목록."""
|
||||
|
||||
status: str = "success"
|
||||
batches: list[TempBatchItem]
|
||||
retention_days: int
|
||||
|
||||
|
||||
class TempBatchCreateResponse(BaseModel):
|
||||
"""묶음 생성 응답."""
|
||||
|
||||
status: str = "success"
|
||||
batch_id: str
|
||||
name: str
|
||||
|
||||
|
||||
class TempFileUploadResult(BaseModel):
|
||||
"""보관함에 저장된 파일 한 건."""
|
||||
|
||||
batch_id: str
|
||||
file_type: str
|
||||
original_filename: str
|
||||
relative_path: str
|
||||
size_bytes: int
|
||||
metadata: dict[str, Any]
|
||||
|
||||
|
||||
class TempFileUploadResponse(BaseModel):
|
||||
"""보관함 업로드(일반·청크 공통) 응답."""
|
||||
|
||||
status: str = "success"
|
||||
batch_id: str
|
||||
files: list[TempFileUploadResult]
|
||||
required_complete: bool
|
||||
|
||||
|
||||
class TempBatchAttachResponse(BaseModel):
|
||||
"""보관함 묶음을 프로젝트로 옮긴 결과."""
|
||||
|
||||
status: str = "success"
|
||||
project_id: str
|
||||
batch_id: str
|
||||
moved_files: int
|
||||
analysis_started: bool
|
||||
Reference in New Issue
Block a user