- item/supplier/quotation/quotation_setting CRUD·service·router 추가 - item protocol delivery_type str→int (ERD/스키마 SMALLINT 일치) - DeliveryType enum + 한글 라벨, 공용 GET /v1/enums (도메인 코드 메타데이터) - CompanyBrief → CompanyData 로 *Data 네이밍 통일 - CORS: WebServerConfig.client_url(단일) 도입 (config_models/router) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
85 lines
4.0 KiB
Python
85 lines
4.0 KiB
Python
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="최저가 수집 결과 없음(스텁)"))
|