""" App Version Check API Views アプリバージョンチェック機能 """ from rest_framework import status from rest_framework.decorators import api_view, permission_classes from rest_framework.permissions import AllowAny from rest_framework.response import Response from django.utils.decorators import method_decorator from django.views.decorators.csrf import csrf_exempt from django.views import View from django.http import JsonResponse import json import logging from .models import AppVersion from .serializers import AppVersionCheckSerializer, AppVersionResponseSerializer logger = logging.getLogger(__name__) @api_view(['POST']) @permission_classes([AllowAny]) def app_version_check(request): """ アプリバージョンチェックAPI POST /api/app/version-check Request: { "current_version": "1.2.3", "platform": "android", "build_number": "123" } Response: { "latest_version": "1.3.0", "update_required": false, "update_available": true, "update_message": "新機能が追加されました。更新をお勧めします。", "download_url": "https://play.google.com/store/apps/details?id=com.example.app", "release_date": "2025-08-25T00:00:00Z" } """ try: # リクエストデータの検証 serializer = AppVersionCheckSerializer(data=request.data) if not serializer.is_valid(): return Response({ 'error': 'Invalid request data', 'details': serializer.errors }, status=status.HTTP_400_BAD_REQUEST) current_version = serializer.validated_data['current_version'] platform = serializer.validated_data['platform'] build_number = serializer.validated_data.get('build_number') # 最新バージョン情報を取得 latest_version_obj = AppVersion.get_latest_version(platform) if not latest_version_obj: return Response({ 'error': 'No version information available for this platform' }, status=status.HTTP_404_NOT_FOUND) # バージョン比較 comparison = AppVersion.compare_versions(current_version, latest_version_obj.version) # レスポンスデータ作成 response_data = { 'latest_version': latest_version_obj.version, 'update_required': False, 'update_available': False, 'update_message': latest_version_obj.update_message or 'アプリは最新版です', 'download_url': latest_version_obj.download_url or '', 'release_date': latest_version_obj.release_date } if comparison < 0: # current_version < latest_version response_data['update_available'] = True # 強制更新が必要かチェック if latest_version_obj.is_required: response_data['update_required'] = True response_data['update_message'] = ( latest_version_obj.update_message or 'このバージョンは古すぎるため、更新が必要です。' ) else: response_data['update_message'] = ( latest_version_obj.update_message or '新しいバージョンが利用可能です。更新をお勧めします。' ) # レスポンス検証 response_serializer = AppVersionResponseSerializer(data=response_data) if response_serializer.is_valid(): return Response(response_serializer.validated_data, status=status.HTTP_200_OK) else: logger.error(f"Response serialization error: {response_serializer.errors}") return Response({ 'error': 'Internal server error' }, status=status.HTTP_500_INTERNAL_SERVER_ERROR) except Exception as e: logger.error(f"App version check error: {e}") return Response({ 'error': 'Internal server error', 'message': str(e) }, status=status.HTTP_500_INTERNAL_SERVER_ERROR) @method_decorator(csrf_exempt, name='dispatch') class AppVersionManagementView(View): """アプリバージョン管理ビュー(管理者用)""" def get(self, request): """全バージョン情報取得""" try: platform = request.GET.get('platform') queryset = AppVersion.objects.all().order_by('-created_at') if platform: queryset = queryset.filter(platform=platform) versions = [] for version in queryset: versions.append({ 'id': version.id, 'version': version.version, 'platform': version.platform, 'build_number': version.build_number, 'is_latest': version.is_latest, 'is_required': version.is_required, 'update_message': version.update_message, 'download_url': version.download_url, 'release_date': version.release_date.isoformat(), 'created_at': version.created_at.isoformat() }) return JsonResponse({ 'versions': versions, 'total': len(versions) }) except Exception as e: logger.error(f"Version list error: {e}") return JsonResponse({ 'error': 'Failed to fetch versions' }, status=500) def post(self, request): """新バージョン登録""" try: data = json.loads(request.body) # 必須フィールドチェック required_fields = ['version', 'platform'] for field in required_fields: if field not in data: return JsonResponse({ 'error': f'Missing required field: {field}' }, status=400) # バージョンオブジェクト作成 version_obj = AppVersion( version=data['version'], platform=data['platform'], build_number=data.get('build_number'), is_latest=data.get('is_latest', False), is_required=data.get('is_required', False), update_message=data.get('update_message'), download_url=data.get('download_url') ) version_obj.save() return JsonResponse({ 'message': 'Version created successfully', 'id': version_obj.id, 'version': version_obj.version, 'platform': version_obj.platform }, status=201) except json.JSONDecodeError: return JsonResponse({ 'error': 'Invalid JSON data' }, status=400) except Exception as e: logger.error(f"Version creation error: {e}") return JsonResponse({ 'error': 'Failed to create version' }, status=500) def put(self, request): """バージョン情報更新""" try: data = json.loads(request.body) version_id = data.get('id') if not version_id: return JsonResponse({ 'error': 'Version ID is required' }, status=400) try: version_obj = AppVersion.objects.get(id=version_id) except AppVersion.DoesNotExist: return JsonResponse({ 'error': 'Version not found' }, status=404) # フィールド更新 updateable_fields = [ 'build_number', 'is_latest', 'is_required', 'update_message', 'download_url' ] for field in updateable_fields: if field in data: setattr(version_obj, field, data[field]) version_obj.save() return JsonResponse({ 'message': 'Version updated successfully', 'id': version_obj.id, 'version': version_obj.version }) except json.JSONDecodeError: return JsonResponse({ 'error': 'Invalid JSON data' }, status=400) except Exception as e: logger.error(f"Version update error: {e}") return JsonResponse({ 'error': 'Failed to update version' }, status=500)