diff --git a/booth/migrations/0007_booth_gdg_id_booth_is_gdgbooth.py b/booth/migrations/0007_booth_gdg_id_booth_is_gdgbooth.py new file mode 100644 index 0000000..0167dcc --- /dev/null +++ b/booth/migrations/0007_booth_gdg_id_booth_is_gdgbooth.py @@ -0,0 +1,23 @@ +# Generated by Django 5.1.1 on 2025-05-22 18:42 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("booth", "0006_booth_manager_contact"), + ] + + operations = [ + migrations.AddField( + model_name="booth", + name="GDG_id", + field=models.IntegerField(null=True, verbose_name="GDG부스 id"), + ), + migrations.AddField( + model_name="booth", + name="is_GDGbooth", + field=models.BooleanField(default=False, verbose_name="GDG부스 여부"), + ), + ] diff --git a/booth/migrations/0008_alter_booth_gdg_id.py b/booth/migrations/0008_alter_booth_gdg_id.py new file mode 100644 index 0000000..71fdb9f --- /dev/null +++ b/booth/migrations/0008_alter_booth_gdg_id.py @@ -0,0 +1,18 @@ +# Generated by Django 5.1.1 on 2025-05-22 18:50 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("booth", "0007_booth_gdg_id_booth_is_gdgbooth"), + ] + + operations = [ + migrations.AlterField( + model_name="booth", + name="GDG_id", + field=models.IntegerField(blank=True, null=True, verbose_name="GDG부스 id"), + ), + ] diff --git a/booth/models.py b/booth/models.py index 6badd54..526946b 100644 --- a/booth/models.py +++ b/booth/models.py @@ -32,6 +32,8 @@ class Booth(models.Model): operating_status = models.CharField(max_length=100, choices=STATUS_CHOICES, verbose_name="부스 운영 상태") current_waiting_num = models.IntegerField(verbose_name="최신 대기 번호") is_restart = models.BooleanField(default=False, verbose_name="재시작 여부") + is_GDGbooth = models.BooleanField(default=False, verbose_name="GDG부스 여부") + GDG_id = models.IntegerField(null=True, blank=True, verbose_name="GDG부스 id") manager_contact = models.CharField(max_length=20, null=True, blank=True, verbose_name="관리자 연락처") def __str__(self): diff --git a/booth/serializers.py b/booth/serializers.py index a146a7c..70b50e7 100644 --- a/booth/serializers.py +++ b/booth/serializers.py @@ -40,7 +40,28 @@ def get_total_waiting_teams(self, obj): booth=obj, waiting_status__in=['waiting', 'entering'] ).count() - + +class GDGBoothListSerializer(serializers.ModelSerializer): + booth_thumbnail = serializers.SerializerMethodField() + + class Meta: + model = Booth + fields = ['booth_id', 'booth_name', 'booth_description', 'booth_location', 'booth_thumbnail', 'GDG_id'] + + def get_booth_thumbnail(self, obj): + # 상대 경로 + # booth_thumbnail = obj.BoothImages.first() + # if booth_thumbnail: + # return booth_thumbnail.image.url + # return '' + + # 절대 경로 + request = self.context.get('request') + booth_thumbnail = obj.booth_images.first() + if booth_thumbnail and request: + return request.build_absolute_uri(booth_thumbnail.booth_image.url) + return '' + class BoothWaitingListSerializer(serializers.ModelSerializer): waiting_id = serializers.SerializerMethodField() waiting_status = serializers.SerializerMethodField() # 현재 대기 상태 @@ -81,6 +102,13 @@ def get_total_waiting_teams(self, obj): waiting_status__in=['waiting', 'entering'] ).count() +class GDGBoothDetailSerializer(serializers.ModelSerializer): + booth_image_info = BoothImageSerializer(source='booth_images', many=True) + + class Meta: + model = Booth + fields = ['booth_id', 'booth_name', 'booth_description', 'booth_location', 'booth_notice', 'booth_start_time', 'booth_image_info', 'GDG_id'] + class BoothWaitingDetailSerializer(serializers.ModelSerializer): waiting_id = serializers.SerializerMethodField() waiting_status = serializers.SerializerMethodField() # 현재 대기 상태 diff --git a/booth/urls.py b/booth/urls.py index 5cbeadb..c2c3f33 100644 --- a/booth/urls.py +++ b/booth/urls.py @@ -1,7 +1,7 @@ from django.urls import path, include from rest_framework import routers -from .views import BoothViewSet, BoothWaitingStatusViewSet, BoothDataView +from .views import * app_name = 'booth' @@ -11,8 +11,12 @@ booth_waiting_router = routers.SimpleRouter(trailing_slash=False) booth_waiting_router.register(r'booths-waiting', BoothWaitingStatusViewSet, basename='booth-waiting') +GDGbooth_router = routers.SimpleRouter(trailing_slash=False) +GDGbooth_router.register(r'gdg-booths', GDGBoothViewSet, basename='booth') + urlpatterns = [ path('', include(booth_router.urls)), + path('', include(GDGbooth_router.urls)), path('', include(booth_waiting_router.urls)), path('upload-booth-data', BoothDataView.as_view(), name="upload_booth_data") ] diff --git a/booth/views.py b/booth/views.py index f8723da..36a2ebd 100644 --- a/booth/views.py +++ b/booth/views.py @@ -5,7 +5,7 @@ from django.db.models import Case, When, Value, IntegerField, Count, Q from rest_framework.filters import OrderingFilter from .models import Booth -from .serializers import BoothListSerializer, BoothDetailSerializer, BoothWaitingListSerializer, BoothWaitingDetailSerializer, BoothLocationSerializer +from .serializers import * from rest_framework import viewsets, mixins from utils.mixins import CustomResponseMixin from utils.responses import custom_response @@ -30,7 +30,7 @@ def get_serializer_class(self): def get_queryset(self): # '운영중 - 대기중지 - 운영전 - 운영종료' + 가나다 순서로 정렬 - queryset = Booth.objects.annotate( + queryset = Booth.objects.all().annotate( operating_status_order=Case( When(operating_status='operating', then=Value(1)), When(operating_status='paused', then=Value(2)), @@ -44,7 +44,7 @@ def get_queryset(self): # 부스 목록 조회 def list(self, request, *args, **kwargs): try: - queryset = self.get_queryset() + queryset = self.get_queryset().filter(is_GDGbooth=False) serializer = self.get_serializer(queryset, many=True) return custom_response( data=serializer.data, @@ -80,7 +80,7 @@ def get_booth_count(self, request): @action(detail=False, methods=['get'], url_path='location') def get_booth_location(self, request): try: - booths = Booth.objects.all() + booths = Booth.objects.filter(is_GDGbooth=False) serializer = BoothLocationSerializer(booths, many=True) return custom_response( serializer.data, @@ -99,12 +99,23 @@ def get_booth_location(self, request): def retrieve(self, request, *args, **kwargs): try: booth = self.get_object() - serializer = self.get_serializer(booth) - return custom_response( - data=serializer.data, - message="부스 상세 조회 성공", - code=status.HTTP_200_OK - ) + + if booth.is_GDGbooth == False: + serializer = self.get_serializer(booth) + return custom_response( + data=serializer.data, + message="부스 상세 조회 성공", + code=status.HTTP_200_OK + ) + + else: + return custom_response( + data={'detail': 'GDG부스 입니다.'}, + message='부스 상세 조회 실패', + code=status.HTTP_500_INTERNAL_SERVER_ERROR, + success=False + ) + except Exception as e: return custom_response( data={'detail': str(e)}, @@ -126,7 +137,7 @@ def get_serializer_class(self): def get_queryset(self): # '운영중 - 대기중지 - 운영전 - 운영종료' + 가나다 순서로 정렬 - queryset = Booth.objects.annotate( + queryset = Booth.objects.all().annotate( operating_status_order=Case( When(operating_status='operating', then=Value(1)), When(operating_status='paused', then=Value(2)), @@ -147,7 +158,7 @@ def list(self, request, *args, **kwargs): "data": None }, status=status.HTTP_401_UNAUTHORIZED) try: - queryset = self.get_queryset() + queryset = self.get_queryset().filter(is_GDGbooth=False) serializer = self.get_serializer(queryset, many=True) return custom_response( data=serializer.data, @@ -173,12 +184,23 @@ def retrieve(self, request, *args, **kwargs): }, status=status.HTTP_401_UNAUTHORIZED) try: booth = self.get_object() - serializer = self.get_serializer(booth) - return custom_response( - data=serializer.data, - message='부스 대기 상세 조회 성공', - code=status.HTTP_200_OK - ) + + if booth.is_GDGbooth == False: + serializer = self.get_serializer(booth) + return custom_response( + data=serializer.data, + message="부스 대기 상세 조회 성공", + code=status.HTTP_200_OK + ) + + else: + return custom_response( + data={'detail': 'GDG부스 입니다.'}, + message='부스 대기 상세 조회 실패', + code=status.HTTP_500_INTERNAL_SERVER_ERROR, + success=False + ) + except Exception as e: return custom_response( data={'detail': str(e)}, @@ -264,4 +286,67 @@ def post(self, request, *args, **kwargs): message="부스 데이터가 성공적으로 업로드되었습니다.", code=status.HTTP_200_OK, success=True - ) \ No newline at end of file + ) + +class GDGBoothViewSet(CustomResponseMixin, viewsets.GenericViewSet, mixins.RetrieveModelMixin, mixins.ListModelMixin): + """ + - GET /gdg-booths -> GDG부스 목록(가나다순) + - GET /gdg-booths/{pk} -> GDG부스 상세 + """ + + def get_serializer_class(self): + if self.action == 'list': + return GDGBoothListSerializer + return GDGBoothDetailSerializer + + def get_queryset(self): + queryset = Booth.objects.all() + return queryset.order_by('booth_name') + + # 부스 목록 조회 + def list(self, request, *args, **kwargs): + try: + queryset = self.get_queryset().filter(is_GDGbooth=True) + serializer = self.get_serializer(queryset, many=True) + return custom_response( + data=serializer.data, + message='GDG부스 목록 조회 성공', + code=status.HTTP_200_OK + ) + except Exception as e: + return custom_response( + data={'detail': str(e)}, + message='GDG부스 목록 조회 실패', + code=status.HTTP_500_INTERNAL_SERVER_ERROR, + success=False + ) + + #부스 상세 조회 + def retrieve(self, request, *args, **kwargs): + try: + booth = self.get_object() + serializer = self.get_serializer(booth) + + if booth.is_GDGbooth == True: + serializer = self.get_serializer(booth) + return custom_response( + data=serializer.data, + message="GDG부스 대기 상세 조회 성공", + code=status.HTTP_200_OK + ) + + else: + return custom_response( + data={'detail': 'GDG부스가 아닙니다.'}, + message='GDG부스 대기 상세 조회 실패', + code=status.HTTP_500_INTERNAL_SERVER_ERROR, + success=False + ) + + except Exception as e: + return custom_response( + data={'detail': str(e)}, + message='GDG부스 상세 조회 실패', + code=status.HTTP_500_INTERNAL_SERVER_ERROR, + success=False + ) \ No newline at end of file diff --git a/linenow/settings.py b/linenow/settings.py index 6954f78..f10b6bd 100644 --- a/linenow/settings.py +++ b/linenow/settings.py @@ -300,4 +300,3 @@ ] - diff --git a/waiting/views.py b/waiting/views.py index 9f8a6fb..6641dc7 100644 --- a/waiting/views.py +++ b/waiting/views.py @@ -285,9 +285,9 @@ def sms_sending(self, booth, status, waiting_id=None): if manager_contact != None: - message = f"[라인나우]\n지금 입장하실 차례입니다!\n{booth.booth_name} 부스로 이동해 주세요.\n\n입장 가능 시간은 10분이에요.\n제한 시간 10분 내 입장하지 않으면 전체 대기가 취소돼요.\n\n부스 입장을 원하지 않으신다면,\n반드시 서비스에 접속하여 입장을 취소해주세요.\nhttps://linewnow-test-service.netlify.app/\n\n부스 전화번호: {manager_contact}\n\n※ ‘입장 취소’ 진행 없이 입장하지 않으실 경우\n전체 부스의 대기가 자동 취소돼요.\n또한 노쇼 3회 누적 시, 금일 라인나우 이용이 제한되실 수 있어요." + message = f"[라인나우]\n지금 입장하실 차례입니다!\n{booth.booth_name} 부스로 이동해 주세요.\n\n입장 가능 시간은 10분이에요.\n제한 시간 10분 내 입장하지 않으면 전체 대기가 취소돼요.\n\n부스 입장을 원하지 않으신다면,\n반드시 서비스에 접속하여 입장을 취소해주세요.\nhttps://linenow.co.kr\n\n부스 전화번호: {manager_contact}\n\n※ ‘입장 취소’ 진행 없이 입장하지 않으실 경우\n전체 부스의 대기가 자동 취소돼요.\n또한 노쇼 3회 누적 시, 금일 라인나우 이용이 제한되실 수 있어요." else: - message = f"[라인나우]\n지금 입장하실 차례입니다!\n{booth.booth_name} 부스로 이동해 주세요.\n\n입장 가능 시간은 10분이에요.\n제한 시간 10분 내 입장하지 않으면 전체 대기가 취소돼요.\n\n부스 입장을 원하지 않으신다면,\n반드시 서비스에 접속하여 입장을 취소해주세요.\nhttps://linewnow-test-service.netlify.app/\n\n※ ‘입장 취소’ 진행 없이 입장하지 않으실 경우\n전체 부스의 대기가 자동 취소돼요.\n또한 노쇼 3회 누적 시, 금일 라인나우 이용이 제한되실 수 있어요." + message = f"[라인나우]\n지금 입장하실 차례입니다!\n{booth.booth_name} 부스로 이동해 주세요.\n\n입장 가능 시간은 10분이에요.\n제한 시간 10분 내 입장하지 않으면 전체 대기가 취소돼요.\n\n부스 입장을 원하지 않으신다면,\n반드시 서비스에 접속하여 입장을 취소해주세요.\nhttps://linenow.co.kr\n\n※ ‘입장 취소’ 진행 없이 입장하지 않으실 경우\n전체 부스의 대기가 자동 취소돼요.\n또한 노쇼 3회 누적 시, 금일 라인나우 이용이 제한되실 수 있어요." try: # 문자 발송 함수 호출 (sendsms 사용)