o2o-negosium-original/negodata/backend/router/v1/card/card.py
Mina Choi 6fa024137f [feat] negodata: 견적·카드 검색/필터 서버사이드 전환 + 견적 상세 Sheet 리팩터
- 백엔드: quotation 목록 search 파라미터(name/number ILIKE) 추가; card 목록 is_wildcard 탭 필터 + total_nego/total_wild 탭 카운트 추가; status/type 코드 int 비교 보정
- 프론트: cards/quotation 검색·상태·유형 필터·페이지네이션을 useServerList 기반 서버사이드로 전환; 엔터 즉시검색 + 디바운스 500ms·최소 2글자; 죽은 client 필터 훅(useCardFilters/useQuotationFilters) 제거
- generated 파라미터/응답 타입 손보강(listCardsParams.is_wildcard, listQuotationsParams.search, resCardList.total_nego/total_wild) — orval 재생성 시 동일
- 견적 상세 Drawer→Sheet 분리, useOverlayParams→useOverlayRouter, CreateQuotationWizard→QuotationCreateModal

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 17:03:53 +09:00

52 lines
2.3 KiB
Python

from uuid import UUID
from fastapi import APIRouter, Depends, Query
from common.models.gmodel import PageParams, UserInfo
from router.v1.validator.dependencies import IsValidAccessToken, RemoveNoneResponse
from services.card_service import CardService
from .protocol import (
Req_CreateCard,
Req_UpdateCard,
Res_Card,
Res_CardList,
Res_DeleteCard,
)
router = APIRouter(prefix="/v1/card", tags=["Card"], responses={404: {"description": "Not found"}})
@router.get(path="/list", response_model=Res_CardList, summary="협상카드 목록")
async def list_cards(
service: CardService = Depends(),
user_info: UserInfo = Depends(IsValidAccessToken),
search: str | None = Query(None, description="카드명/카드번호/스크립트 검색"),
is_wildcard: bool | None = Query(None, description="탭 필터: 미지정=전체 / false=협상카드 / true=와일드카드"),
pg: PageParams = Depends(),
):
return RemoveNoneResponse(await service.list_cards(user_info.user_id, search, is_wildcard, pg))
@router.post(path="/create", response_model=Res_Card, summary="협상카드 등록")
async def create_card(req: Req_CreateCard, service: CardService = Depends(), user_info: UserInfo = Depends(IsValidAccessToken)):
return RemoveNoneResponse(
await service.create_card(user_info.user_id, req.model_dump(exclude_unset=True))
)
@router.get(path="/{card_id}", response_model=Res_Card, summary="협상카드 조회")
async def get_card(card_id: UUID, service: CardService = Depends(), user_info: UserInfo = Depends(IsValidAccessToken)):
return RemoveNoneResponse(await service.get_card(user_info.user_id, str(card_id)))
@router.patch(path="/update/{card_id}", response_model=Res_Card, summary="협상카드 수정")
async def update_card(
card_id: UUID, req: Req_UpdateCard, service: CardService = Depends(), user_info: UserInfo = Depends(IsValidAccessToken)
):
return RemoveNoneResponse(await service.update_card(user_info.user_id, str(card_id), req.model_dump(exclude_unset=True)))
@router.delete(path="/delete/{card_id}", response_model=Res_DeleteCard, summary="협상카드 삭제")
async def delete_card(card_id: UUID, service: CardService = Depends(), user_info: UserInfo = Depends(IsValidAccessToken)):
return RemoveNoneResponse(await service.delete_card(user_info.user_id, str(card_id)))