From 3f0099b61ab9c4c4d7b3cce3a8f896157d3fd461 Mon Sep 17 00:00:00 2001 From: Seungkyu Kim <76573337+ed-kyu@users.noreply.github.com> Date: Fri, 22 Nov 2024 21:20:22 +0900 Subject: [PATCH] =?UTF-8?q?QR=20scan=20=EA=B4=80=EB=A0=A8=20api=20(#30)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: qr function init * feat: refactoring * feat: add qr scan schema, response class * chore: delete unused thing --- app/api/bingo/bingo_boards/routes.py | 11 ++++++++ app/api/bingo/bingo_boards/schema.py | 8 +++++- app/api/bingo/bingo_boards/services.py | 13 ++++++++-- app/models/bingo/bingo_boards.py | 35 +++++++++++++++++++++++++- app/models/bingo/schema.py | 11 +++++++- 5 files changed, 73 insertions(+), 5 deletions(-) diff --git a/app/api/bingo/bingo_boards/routes.py b/app/api/bingo/bingo_boards/routes.py index 6e4b129..4ed500c 100644 --- a/app/api/bingo/bingo_boards/routes.py +++ b/app/api/bingo/bingo_boards/routes.py @@ -6,6 +6,7 @@ UpdateBingoCountResponse, UserSelectedWordsResponse, UpdateBingoStatusResponse, + UpdateBingoStatusResponseByQRScan, GetUserBingoEventUser, ) from .services import ( @@ -16,6 +17,7 @@ GetUserSelectedWords, UpdateBingoStatusBySelectedUser, GetBingoEventUser, + UpdateBingoStatusByQRScan, ) @@ -77,3 +79,12 @@ async def get_bingo_event_users( bingo_boards: GetBingoEventUser = Depends(GetBingoEventUser), ): return await bingo_boards.execute(bingo_count) + + +@bingo_boards_router.patch("/update/{user_id}/{booth_id}", response_model=UpdateBingoStatusResponseByQRScan) +async def update_bingo_status_booth( + user_id: int = Path(..., title="요청 유저 ID", ge=0), + booth_id: int = Path(..., title="요청 부스 ID", ge=0), + bingo_boards: UpdateBingoStatusByQRScan = Depends(UpdateBingoStatusByQRScan), +): + return await bingo_boards.execute(user_id, booth_id) diff --git a/app/api/bingo/bingo_boards/schema.py b/app/api/bingo/bingo_boards/schema.py index 524e0a7..3db188c 100644 --- a/app/api/bingo/bingo_boards/schema.py +++ b/app/api/bingo/bingo_boards/schema.py @@ -61,12 +61,18 @@ class UpdateBingoCountResponse(BaseSchema): class UserSelectedWordsResponse(BaseSchema): selected_words: Optional[list[str]] = Field(title="선택한 단어들", default=None) + class UpdateBingoStatusResponse(BaseSchema): send_user_id: Optional[int] = Field(title="요청 유저 ID", default=None) receive_user_id: Optional[int] = Field(title="대상 유저 ID", default=None) updated_words: Optional[list[str]] = Field(title="업데이트된 단어들", default=None) bingo_count: Optional[int] = Field(title="업데이트된 빙고 갯수", default=None) + +class UpdateBingoStatusResponseByQRScan(UpdateBingoCountResponse): + booth_id: Optional[int] = Field(title="요청 부스 ID", default=None) + updated_words: Optional[list[str]] = Field(title="업데이트된 단어들", default=None) + + class GetUserBingoEventUser(BaseSchema): bingo_event_users: Optional[list[BingoEventUserInfo]] = Field(title="빙고 이벤트 당첨 유저 목록", default=None) - diff --git a/app/api/bingo/bingo_boards/services.py b/app/api/bingo/bingo_boards/services.py index ac5089e..c8171e7 100644 --- a/app/api/bingo/bingo_boards/services.py +++ b/app/api/bingo/bingo_boards/services.py @@ -1,6 +1,6 @@ from core.db import AsyncSessionDepends from models.bingo import BingoBoards -from api.bingo.bingo_boards.schema import BingoBoardResponse, UpdateBingoCountResponse, UserSelectedWordsResponse, UpdateBingoStatusResponse, GetUserBingoEventUser +from api.bingo.bingo_boards.schema import BingoBoardRequest, BingoBoardResponse, UpdateBingoCountResponse, UserSelectedWordsResponse, UpdateBingoStatusResponse, GetUserBingoEventUser, UpdateBingoStatusResponseByQRScan class BaseBingoBoard: @@ -11,6 +11,7 @@ def __init__(self, session: AsyncSessionDepends): class CreateBingoBoard(BaseBingoBoard): async def execute(self, user_id: int, board_data: dict) -> BingoBoards: try: + board_data = BingoBoardRequest.Config.json_schema_extra["example"]["board_data"] res = await BingoBoards.create(self.async_session, user_id, board_data) return BingoBoardResponse(**res.__dict__, ok=True, message="빙고판 생성에 성공하였습니다.") except ValueError as e: @@ -66,4 +67,12 @@ async def execute(self, bingo_count: int) -> list[str]: res = await BingoBoards.get_bingo_event_users(self.async_session, bingo_count) return GetUserBingoEventUser(bingo_event_users=res, ok=True, message="빙고 이벤트 당첨 유저 목록 생성에 성공하였습니다.") except ValueError as e: - return GetUserBingoEventUser(ok=False, message=str(e)) \ No newline at end of file + return GetUserBingoEventUser(ok=False, message=str(e)) + +class UpdateBingoStatusByQRScan(BaseBingoBoard): + async def execute(self, user_id: int, booth_id: int) -> BingoBoards: + try: + res = await BingoBoards.update_bingo_status_by_qr_scan(self.async_session, user_id, booth_id) + return UpdateBingoStatusResponseByQRScan(**res.__dict__, ok=True, message="빙고판 상태 업데이트에 성공하였습니다.") + except ValueError as e: + return UpdateBingoStatusResponseByQRScan(ok=False, message=str(e)) diff --git a/app/models/bingo/bingo_boards.py b/app/models/bingo/bingo_boards.py index 78f5573..c3e55db 100644 --- a/app/models/bingo/bingo_boards.py +++ b/app/models/bingo/bingo_boards.py @@ -1,6 +1,7 @@ from datetime import datetime from zoneinfo import ZoneInfo import asyncio +import random from sqlalchemy.orm import mapped_column from sqlalchemy import Integer, DateTime, JSON, select, desc @@ -8,7 +9,7 @@ from core.db import AsyncSession from models.base import Base -from models.bingo.schema import BingoInteractionSchema, BingoEventUserInfo +from models.bingo.schema import BingoInteractionSchema, BingoEventUserInfo, BingoQRScanSchema from models.user import BingoUser @@ -135,3 +136,35 @@ async def get_bingo_event_users(cls, session: AsyncSession, bingo_count: int) -> ] return bingo_event_users_info + + @classmethod + async def update_bingo_status_by_qr_scan(cls, session: AsyncSession, user_id: int, booth_id: int): + booth_exist = False + not_selected_ids = [] + # get board_data, check user_id is already have booth bingo + board = await cls.get_board_by_userid(session, user_id) + board_data = board.board_data + updated_booth_name = f'Booth {booth_id}' + for idx, bingo_dict in board_data.items(): + value, status = bingo_dict["value"], bingo_dict["status"] + if value == updated_booth_name: + booth_exist = True + break + if status == 0: + # get not selected list + not_selected_ids.append(idx) + + if not booth_exist: + # update random board data + booth_idx = random.choice(not_selected_ids) + board_data[booth_idx]["value"] = updated_booth_name + board_data[booth_idx]["status"] = 1 + await cls.update_board_by_userid(session, user_id, board_data) + + + return BingoQRScanSchema( + user_id=user_id, + booth_id=booth_id, + updated_words=[updated_booth_name], + bingo_count=board.bingo_count, + ) \ No newline at end of file diff --git a/app/models/bingo/schema.py b/app/models/bingo/schema.py index 2dd87bf..f2acfd1 100644 --- a/app/models/bingo/schema.py +++ b/app/models/bingo/schema.py @@ -19,13 +19,22 @@ class BingoBoardSchema(BaseModel): model_config = ConfigDict(from_attributes=True) + class BingoInteractionSchema(BaseModel): send_user_id: int receive_user_id: int updated_words: list[str] bingo_count: int + +class BingoQRScanSchema(BaseModel): + user_id: int + booth_id: int + updated_words: list[str] + bingo_count: int + + class BingoEventUserInfo(BaseModel): rank: int user_name: str - bingo_count: int \ No newline at end of file + bingo_count: int