22from re import compile
33from typing import Any
44
5+ from core .const .scancode import SCANCODE_ERROR_GUIDE , SCANCODE_MESSAGES
56from core .const .tag import OpenAPITag
7+ from core .negotiation import IgnoreClientContentNegotiation
68from core .openapi .schemas import build_html_responses
9+ from core .templatetags .i18n_extras import is_english
710from drf_spectacular .openapi import OpenApiParameter , OpenApiTypes
811from drf_spectacular .utils import extend_schema
912from rest_framework import permissions , renderers , request , response , status , viewsets
1821
1922
2023class _ScanCodeError (Exception ):
21- def __init__ (self , msg : str , code : int ) -> None :
22- super ().__init__ (msg , code )
23- self .msg = msg
24+ def __init__ (self , key : str , code : int ) -> None :
25+ super ().__init__ (key , code )
26+ self .key = key
2427 self .code = code
2528
2629 def to_response (self ) -> response .Response :
30+ lang , sub_lang = ("en" , "ko" ) if is_english () else ("ko" , "en" )
2731 return response .Response (
28- data = {"error_msg" : self .msg },
32+ data = {
33+ "error_msg" : SCANCODE_MESSAGES [self .key ][lang ],
34+ "error_msg_sub" : SCANCODE_MESSAGES [self .key ][sub_lang ],
35+ "error_guide" : SCANCODE_ERROR_GUIDE [lang ],
36+ "error_guide_sub" : SCANCODE_ERROR_GUIDE [sub_lang ],
37+ },
2938 status = self .code ,
3039 template_name = "scancode_error.html" ,
3140 )
3241
3342
3443def _render_user (token : str ) -> response .Response :
3544 if not (user := UserExt .from_scancode_token (token )):
36- raise _ScanCodeError (msg = "인증 정보를 찾을 수 없습니다. " , code = status .HTTP_403_FORBIDDEN )
45+ raise _ScanCodeError (key = "user_not_found " , code = status .HTTP_403_FORBIDDEN )
3746 # 환불된 주문도 응답에 포함(현장 스태프의 이력 확인용). 단 모두 refunded 면 게이트.
3847 orders = list (Order .objects .filter_purchased_by (user ).filter_in_last_six_months ())
3948 if not any (o .current_status != PaymentHistoryStatus .refunded for o in orders ):
40- raise _ScanCodeError (
41- msg = "최근 6개월 이내에 결제된 유효한 주문이 없습니다 (환불 완료 또는 주문 없음)." ,
42- code = status .HTTP_403_FORBIDDEN ,
43- )
49+ raise _ScanCodeError (key = "user_no_valid_order" , code = status .HTTP_403_FORBIDDEN )
4450 return response .Response (
4551 data = {
4652 "user" : UserScanCodeSerializer (instance = user ).data ,
@@ -53,9 +59,9 @@ def _render_user(token: str) -> response.Response:
5359
5460def _render_order (token : str ) -> response .Response :
5561 if not (order := Order .from_scancode_token (token )):
56- raise _ScanCodeError (msg = "주문을 찾을 수 없습니다. " , code = status .HTTP_404_NOT_FOUND )
62+ raise _ScanCodeError (key = "order_not_found " , code = status .HTTP_404_NOT_FOUND )
5763 if order .current_status == PaymentHistoryStatus .refunded :
58- raise _ScanCodeError (msg = "전체 환불된 주문은 사용하실 수 없습니다. " , code = status .HTTP_404_NOT_FOUND )
64+ raise _ScanCodeError (key = "order_refunded " , code = status .HTTP_404_NOT_FOUND )
5965 return response .Response (
6066 data = {"order" : OrderScanCodeSerializer (instance = order ).data },
6167 status = status .HTTP_200_OK ,
@@ -65,7 +71,7 @@ def _render_order(token: str) -> response.Response:
6571
6672def _render_opr (token : str ) -> response .Response :
6773 if not (opr := OrderProductRelation .from_scancode_token (token )):
68- raise _ScanCodeError (msg = "티켓 정보를 찾을 수 없습니다. " , code = status .HTTP_403_FORBIDDEN )
74+ raise _ScanCodeError (key = "opr_not_found " , code = status .HTTP_403_FORBIDDEN )
6975 return response .Response (
7076 data = {"order_product" : OrderProductScanCodeSerializer (instance = opr ).data },
7177 status = status .HTTP_200_OK ,
@@ -87,6 +93,7 @@ class ScanCodeViewSet(viewsets.GenericViewSet):
8793 permission_classes = [permissions .AllowAny ]
8894 authentication_classes : list = []
8995 renderer_classes = [renderers .TemplateHTMLRenderer ]
96+ content_negotiation_class = IgnoreClientContentNegotiation # 스캐너 인앱 브라우저 Accept 로 406 이 나가지 않도록.
9097
9198 @extend_schema (
9299 summary = "QR 코드 페이지 (token 으로 dispatch)" ,
@@ -103,9 +110,9 @@ class ScanCodeViewSet(viewsets.GenericViewSet):
103110 def list (self , request : request .Request , * args : tuple [Any ], ** kwargs : dict [str , Any ]) -> response .Response :
104111 try :
105112 if not (token := request .query_params .get ("token" )):
106- raise _ScanCodeError (msg = "유효하지 않은 URL입니다. " , code = status .HTTP_404_NOT_FOUND )
113+ raise _ScanCodeError (key = "no_token " , code = status .HTTP_404_NOT_FOUND )
107114 if not (match := _SCANCODE_REGEX .match (token )):
108- raise _ScanCodeError (msg = "유효하지 않은 토큰입니다. " , code = status .HTTP_404_NOT_FOUND )
115+ raise _ScanCodeError (key = "invalid_token " , code = status .HTTP_404_NOT_FOUND )
109116 return _DISPATCH [match ["prefix" ]](token )
110117 except _ScanCodeError as e :
111118 return e .to_response ()
0 commit comments