Skip to content

Commit

Permalink
Feat #25 - 유치원 요약 정보 조회 API 구현 (#26)
Browse files Browse the repository at this point in the history
- 유치원 요약 정보 조회 기능 구현
- PetKindergardenSelector 클래스의 get_queryset_by_user 메서드 반환 타입 수정

Close #25
  • Loading branch information
DongwookKim0823 committed Jul 5, 2024
1 parent a9917a2 commit 9cfd65e
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 8 deletions.
41 changes: 41 additions & 0 deletions mung_manager/pet_kindergardens/apis/api_managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from mung_manager.pet_kindergardens.apis.apis import (
PetKindergardenListAPI,
PetKindergardenSelectionAPI,
PetKindergardenSummaryInfoAPI,
)
from mung_manager.schemas.errors.authentications import (
ErrorAuthenticationPasswordChangedSchema,
Expand Down Expand Up @@ -117,3 +118,43 @@ class PetKindergardenSelectionAPIManager(BaseAPIManager):
)
def post(self, request, *args, **kwargs):
return self.VIEWS_BY_METHOD["POST"]()(request, *args, **kwargs)


class PetKindergardenSummaryInfoAPIManager(BaseAPIManager):
VIEWS_BY_METHOD = {
"GET": PetKindergardenSummaryInfoAPI.as_view,
}

@extend_schema(
tags=["반려동물 유치원"],
summary="반려동물 유치원 요약 정보 조회",
description="""
Rogic
- 유저 토큰 클레임에 포함된 반려동물 유치원 아이디로 해당 반려동물 유치원의 요약 정보를 조회합니다.
""",
responses={
status.HTTP_200_OK: VIEWS_BY_METHOD["GET"]().cls.OutputSerializer,
status.HTTP_401_UNAUTHORIZED: OpenApiResponse(
response=OpenApiTypes.OBJECT,
examples=[
ErrorAuthenticationFailedSchema,
ErrorNotAuthenticatedSchema,
ErrorInvalidTokenSchema,
ErrorAuthorizationHeaderSchema,
ErrorAuthenticationPasswordChangedSchema,
ErrorAuthenticationUserDeletedSchema,
ErrorAuthenticationUserInactiveSchema,
ErrorAuthenticationUserNotFoundSchema,
ErrorTokenIdentificationSchema,
],
),
status.HTTP_403_FORBIDDEN: OpenApiResponse(
response=OpenApiTypes.OBJECT, examples=[ErrorPermissionDeniedSchema]
),
status.HTTP_500_INTERNAL_SERVER_ERROR: OpenApiResponse(
response=OpenApiTypes.OBJECT, examples=[ErrorUnknownServerSchema]
),
},
)
def get(self, request, *args, **kwargs):
return self.VIEWS_BY_METHOD["GET"]()(request, *args, **kwargs)
22 changes: 21 additions & 1 deletion mung_manager/pet_kindergardens/apis/apis.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from rest_framework.response import Response
from rest_framework.views import APIView

from mung_manager.apis.mixins import APIAuthMixin
from mung_manager.apis.mixins import APIAuthMixin, APIAuthWithPetKindergardenAccessMixin
from mung_manager.authentications.containers import AuthenticationContainer
from mung_manager.commons.base.serializers import BaseSerializer
from mung_manager.pet_kindergardens.containers import PetKindergardenContainer
Expand Down Expand Up @@ -56,3 +56,23 @@ def post(self, request: Request) -> Response:
}
).data
return Response(data=auth_data, status=status.HTTP_200_OK)


class PetKindergardenSummaryInfoAPI(APIAuthWithPetKindergardenAccessMixin, APIView):
class OutputSerializer(BaseSerializer):
id = serializers.IntegerField(label="유치원 아이디")
name = serializers.CharField(label="유치원 이름")
business_start_hour = serializers.TimeField(label="영업 시작 시간", format="%H:%M")
business_end_hour = serializers.TimeField(label="영업 종료 시간", format="%H:%M")

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._pet_kindergarden_selector = PetKindergardenContainer.pet_kindergarden_selector()

def get(self, request: Request) -> Response:
pet_kindergarden_id = request.pet_kindergarden_id
pet_kindergarden = self._pet_kindergarden_selector.get_by_pet_kindergarden_id_for_summary_info(
pet_kindergarden_id
).get()
pet_kindergardens_data = self.OutputSerializer(pet_kindergarden).data
return Response(data=pet_kindergardens_data, status=status.HTTP_200_OK)
6 changes: 6 additions & 0 deletions mung_manager/pet_kindergardens/apis/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from mung_manager.pet_kindergardens.apis.api_managers import (
PetkindergardenListAPIManager,
PetKindergardenSelectionAPIManager,
PetKindergardenSummaryInfoAPIManager,
)

urlpatterns = [
Expand All @@ -16,4 +17,9 @@
PetKindergardenSelectionAPIManager.as_view(),
name="pet-kindergarden-selection",
),
path(
"/summary",
PetKindergardenSummaryInfoAPIManager.as_view(),
name="pet-kindergarden-summary-info",
),
]
19 changes: 15 additions & 4 deletions mung_manager/pet_kindergardens/selectors/abstracts.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
from abc import ABC, abstractmethod
from typing import Any

from django.db.models.query import QuerySet
from django.db.models import QuerySet
from django_stubs_ext import ValuesQuerySet, WithAnnotations

from mung_manager.errors.exceptions import NotImplementedException
from mung_manager.pet_kindergardens.models import PetKindergarden
from mung_manager.pet_kindergardens.selectors.pet_kindergardens import (
info_for_full_address,
)
from mung_manager.pet_kindergardens.types import info_for_summary


class AbstractPetKindergardenSelector(ABC):

@abstractmethod
def get_queryset_by_user(
self,
user,
) -> QuerySet[Any]:
self, user
) -> QuerySet[WithAnnotations[PetKindergarden, info_for_full_address], dict[str, Any]]:
raise NotImplementedException()

@abstractmethod
def get_by_pet_kindergarden_id_for_summary_info(
self, pet_kindergarden_id: int
) -> ValuesQuerySet[PetKindergarden, info_for_summary]:
raise NotImplementedException()
29 changes: 26 additions & 3 deletions mung_manager/pet_kindergardens/selectors/pet_kindergardens.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,53 @@

from django.db.models import F, QuerySet, Value
from django.db.models.functions import Concat
from django_stubs_ext import WithAnnotations
from django_stubs_ext.aliases import ValuesQuerySet

from mung_manager.pet_kindergardens.models import PetKindergarden
from mung_manager.pet_kindergardens.selectors.abstracts import (
AbstractPetKindergardenSelector,
)
from mung_manager.pet_kindergardens.types import info_for_full_address, info_for_summary


class PetKindergardenSelector(AbstractPetKindergardenSelector):
"""
이 클래스는 반려동물 유치원을 DB에서 PULL하는 비즈니스 로직을 담당합니다.
"""

def get_queryset_by_user(self, user) -> QuerySet[Any]:
"""이 함수는 사용자 정보로, 해당 사용자가 속한 유치원 목록을 조회합니다.
def get_queryset_by_user(
self, user
) -> QuerySet[WithAnnotations[PetKindergarden, info_for_full_address], dict[str, Any]]:
"""
이 함수는 사용자 정보로, 해당 사용자가 속한 유치원 목록을 조회합니다.
Args:
user: User: 유저 객체
Returns:
QuerySet[Any]: 존재하지 않으면 빈 쿼리셋을 반환
QuerySet[WithAnnotations[PetKindergarden, info_for_full_address], dict[str, Any]]: 정의된 응답 스키마
"""

return (
PetKindergarden.objects.filter(customers__user=user)
.annotate(full_address=Concat(F("road_address"), Value(" "), F("detail_address")))
.values("id", "name", "full_address", "profile_thumbnail_url")
)

def get_by_pet_kindergarden_id_for_summary_info(
self, pet_kindergarden_id: int
) -> ValuesQuerySet[PetKindergarden, info_for_summary]:
"""
이 함수는 반려동물 유치원 아이디로 해당 반려동물 유치원의 요약 정보를 조회합니다.
Args:
pet_kindergarden_id (int): 반려동물 유치원 아이디
Returns:
ValuesQuerySet[PetKindergarden, info_for_summary]: 정의된 응답 스키마
"""

return PetKindergarden.objects.filter(id=pet_kindergarden_id).values(
"id", "name", "business_start_hour", "business_end_hour"
)
7 changes: 7 additions & 0 deletions mung_manager/pet_kindergardens/types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from datetime import time
from typing import TypedDict

info_for_full_address = TypedDict("info_for_full_address", {"full_address": str})
info_for_summary = TypedDict(
"info_for_summary", {"id": int, "name": str, "business_start_hour": time, "business_end_hour": time}
)

0 comments on commit 9cfd65e

Please sign in to comment.