from uuid import UUID from fastapi import APIRouter, Depends, File, Query, UploadFile from common.models.gmodel import UserInfo from router.v1.validator.dependencies import IsValidAccessToken, RemoveNoneResponse from services.item_service import ItemService from .protocol import ( Req_CreateItem, Req_UpdateItem, Res_DeleteItem, Res_ExcelUpload, Res_Item, Res_ItemList, Res_LowestPriceResult, Res_LowestPriceTrigger, ) # 라우터(컨트롤러). 인증(Depends(IsValidAccessToken))으로 UserInfo 를 받아 company_id 로 스코프. router = APIRouter(prefix="/v1/item", tags=["Item"], responses={404: {"description": "Not found"}}) @router.get(path="/list", response_model=Res_ItemList, summary="상품 목록") async def list_items( service: ItemService = Depends(), user_info: UserInfo = Depends(IsValidAccessToken), search: str | None = Query(None, description="상품명/상품코드 검색"), category: str | None = Query(None, description="카테고리 필터"), page: int = Query(1, ge=1), size: int = Query(20, ge=1, le=100), ): return RemoveNoneResponse(await service.list_items(user_info.company_id, search, category, page, size)) @router.post(path="/create", response_model=Res_Item, summary="상품 등록") async def create_item(req: Req_CreateItem, service: ItemService = Depends(), user_info: UserInfo = Depends(IsValidAccessToken)): return RemoveNoneResponse( await service.create_item(user_info.company_id, user_info.user_id, req.model_dump(exclude_unset=True)) ) @router.post(path="/upload-excel", response_model=Res_ExcelUpload, summary="엑셀 일괄 등록(스텁)") async def upload_items_excel( service: ItemService = Depends(), user_info: UserInfo = Depends(IsValidAccessToken), file: UploadFile = File(...), ): return RemoveNoneResponse( Res_ExcelUpload(received_filename=file.filename, status="not_implemented", message="엑셀 일괄 등록은 추후 구현") ) @router.get(path="/{item_id}", response_model=Res_Item, summary="상품 조회") async def get_item(item_id: UUID, service: ItemService = Depends(), user_info: UserInfo = Depends(IsValidAccessToken)): return RemoveNoneResponse(await service.get_item(user_info.company_id, str(item_id))) @router.patch(path="/update/{item_id}", response_model=Res_Item, summary="상품 수정") async def update_item( item_id: UUID, req: Req_UpdateItem, service: ItemService = Depends(), user_info: UserInfo = Depends(IsValidAccessToken) ): return RemoveNoneResponse(await service.update_item(user_info.company_id, str(item_id), req.model_dump(exclude_unset=True))) @router.delete(path="/delete/{item_id}", response_model=Res_DeleteItem, summary="상품 삭제") async def delete_item(item_id: UUID, service: ItemService = Depends(), user_info: UserInfo = Depends(IsValidAccessToken)): return RemoveNoneResponse(await service.delete_item(user_info.company_id, str(item_id))) @router.post(path="/{item_id}/lowest-price", response_model=Res_LowestPriceTrigger, summary="최저가 수집 요청(스텁)") async def trigger_lowest_price(item_id: UUID, service: ItemService = Depends(), user_info: UserInfo = Depends(IsValidAccessToken)): # 존재/소유 확인만 (없으면 result 에 ITEM_NOT_FOUND) got = await service.get_item(user_info.company_id, str(item_id)) if got.item is None: return RemoveNoneResponse(got) return RemoveNoneResponse(Res_LowestPriceTrigger(item_id=str(item_id), status="queued", message="최저가 수집 요청됨(스텁)")) @router.get(path="/{item_id}/lowest-price", response_model=Res_LowestPriceResult, summary="최저가 수집 결과(스텁)") async def get_lowest_price(item_id: UUID, service: ItemService = Depends(), user_info: UserInfo = Depends(IsValidAccessToken)): got = await service.get_item(user_info.company_id, str(item_id)) if got.item is None: return RemoveNoneResponse(got) return RemoveNoneResponse(Res_LowestPriceResult(item_id=str(item_id), results=[], message="최저가 수집 결과 없음(스텁)"))