Initial commit: AutonetSellCar platform with deployment system

- Frontend: Next.js 14 with TypeScript
- Backend: FastAPI with SQLAlchemy
- Agent: Carmodoo sync agent
- Deployment: Docker Compose based staging/production setup
- Scripts: Automated deployment with rollback support

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
AutonetSellCar Deploy
2025-12-30 13:24:39 +09:00
commit 1f0dcb1ddb
224 changed files with 55119 additions and 0 deletions

View File

@@ -0,0 +1,216 @@
"""
Performance Check Access Unit Tests
비즈니스 로직:
- 성능점검표는 항상 0.1 CC 결제 필요 (배너 차량 포함)
- 1 CC 차량 전체 구매 시 성능점검표 포함
- 관리자는 무조건 접근 가능
"""
import pytest
from unittest.mock import MagicMock, patch
from sqlalchemy.orm import Session
class TestPerformanceCheckAccess:
"""성능점검표 접근 권한 테스트"""
def test_admin_has_access(self):
"""관리자는 성능점검표에 무조건 접근 가능"""
# Given
user = MagicMock()
user.is_admin = True
user.id = 1
# When
has_access = self._check_access(user, car_id=1, has_perf_view=False, has_car_view=False)
# Then
assert has_access is True
def test_user_with_performance_check_purchase(self):
"""0.1 CC 결제한 사용자는 접근 가능"""
# Given
user = MagicMock()
user.is_admin = False
user.id = 1
# When
has_access = self._check_access(user, car_id=1, has_perf_view=True, has_car_view=False)
# Then
assert has_access is True
def test_user_with_full_car_view_purchase(self):
"""1 CC 결제한 사용자는 접근 가능 (성능점검표 포함)"""
# Given
user = MagicMock()
user.is_admin = False
user.id = 1
# When
has_access = self._check_access(user, car_id=1, has_perf_view=False, has_car_view=True)
# Then
assert has_access is True
def test_user_without_purchase(self):
"""결제하지 않은 사용자는 접근 불가"""
# Given
user = MagicMock()
user.is_admin = False
user.id = 1
# When
has_access = self._check_access(user, car_id=1, has_perf_view=False, has_car_view=False)
# Then
assert has_access is False
def test_anonymous_user(self):
"""비로그인 사용자는 접근 불가"""
# Given
user = None
# When
has_access = self._check_access(user, car_id=1, has_perf_view=False, has_car_view=False)
# Then
assert has_access is False
def test_banner_car_still_requires_payment(self):
"""배너 차량이어도 성능점검표는 결제 필요"""
# Given
user = MagicMock()
user.is_admin = False
user.id = 1
is_banner_car = True # 배너 차량
# When - 결제하지 않은 경우
has_access = self._check_access(
user, car_id=1,
has_perf_view=False,
has_car_view=False,
is_banner_car=is_banner_car
)
# Then - 배너 차량이어도 접근 불가
assert has_access is False
def test_banner_car_with_payment(self):
"""배너 차량 + 0.1 CC 결제 시 접근 가능"""
# Given
user = MagicMock()
user.is_admin = False
user.id = 1
is_banner_car = True
# When
has_access = self._check_access(
user, car_id=1,
has_perf_view=True,
has_car_view=False,
is_banner_car=is_banner_car
)
# Then
assert has_access is True
def _check_access(
self,
user,
car_id: int,
has_perf_view: bool,
has_car_view: bool,
is_banner_car: bool = False
) -> bool:
"""
성능점검표 접근 권한 확인 로직
Note: 이 로직은 backend/app/api/carmodoo.py의
get_car_performance_check 함수와 동일해야 함
"""
has_access = False
# 배너 차량 여부는 성능점검표 접근에 영향 없음
# (이미지와 연락처만 무료, 성능점검표는 유료)
if user:
if user.is_admin:
has_access = True
else:
# 0.1 CC 결제 또는 1 CC 결제
has_access = has_perf_view or has_car_view
return has_access
class TestPerformanceCheckPreview:
"""성능점검표 미리보기 테스트"""
def test_preview_available_without_payment(self):
"""결제 전에도 미리보기 정보 제공"""
# 미리보기에 포함되는 정보
preview_fields = ['check_number', 'check_date', 'mileage']
# 미리보기에 포함되지 않는 정보
full_access_fields = [
'is_flood_damaged',
'is_fire_damaged',
'device_status',
'body_parts',
'frame_parts',
'pdf_path'
]
# 미리보기 응답 구조 확인
preview_response = {
"car_id": 1,
"found": True,
"has_access": False,
"preview": {
"check_number": "A123456",
"check_date": "2024-01-01",
"mileage": 50000
},
"data": None # 결제 전에는 null
}
assert preview_response["has_access"] is False
assert preview_response["data"] is None
for field in preview_fields:
assert field in preview_response["preview"]
class TestBannerCarImageAccess:
"""배너 차량 이미지 접근 테스트 (참고용 - 성능점검표와 별개)"""
def test_banner_car_images_are_free(self):
"""배너 차량 이미지는 무료"""
is_banner_car = True
user = None # 비로그인
# 배너 차량 이미지 접근 가능 여부
can_view_images = is_banner_car # 배너면 무조건 가능
assert can_view_images is True
def test_banner_car_contact_is_free(self):
"""배너 차량 연락처는 무료"""
is_banner_car = True
user = None # 비로그인
# 배너 차량 연락처 접근 가능 여부
can_view_contact = is_banner_car # 배너면 무조건 가능
assert can_view_contact is True
def test_non_banner_car_images_require_payment(self):
"""비배너 차량 이미지는 유료"""
is_banner_car = False
has_paid = False
# 비배너 차량 이미지 접근
can_view_images = has_paid
assert can_view_images is False