- partner.supplier_items 매핑테이블 신설: supply_type(0없음/1유통/2제조/3총판), 부분 유니크 인덱스(soft-delete 인지). quotations.supplier_type와 의미단위 달라 컬럼명 supply_type. - 백엔드: supplier_item CRUD/service/router(/v1/supplier-item, by-supplier·by-item·create·bulk·update·delete). 소유권 company 스코프. ErrorType.SUPPLIER_ITEM_NOT_FOUND 추가. - DDL: 01-schema/04-alter(날짜접미 리네임) + dev DB 반영. - 프론트(feature): 협력사 엑셀 '취급상품' 컬럼(콤마 상품명→일괄매핑, 이름 미매칭 스킵+리포트, 유형 안받고 없음), 협력사 상세 취급상품 관리(추가/삭제/유형변경 즉시반영), 견적모달 협력사 리스트에 선택상품 공급유형 배지. - 재사용 서버검색 Combobox 신설 → 취급상품·견적상품·협력사초청·협상카드 픽리스트에 적용(size 100 캡 해소, 검색은 서버 ILIKE). 견적 선택상품 파생값은 useGetItem 단건조회로 안정화. - orval 재생성(supplier-item 클라이언트/모델). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
62 lines
3.0 KiB
Python
62 lines
3.0 KiB
Python
from uuid import UUID
|
|
|
|
from fastapi import APIRouter, Depends
|
|
|
|
from common.models.gmodel import Res_WebPacketProtocol, UserInfo
|
|
from router.v1.validator.dependencies import IsValidAccessToken, RemoveNoneResponse
|
|
from services.supplier_item_service import SupplierItemService
|
|
from .protocol import (
|
|
Req_BulkMapByNames,
|
|
Req_CreateSupplierItem,
|
|
Req_UpdateSupplyType,
|
|
Res_BulkMapByNames,
|
|
Res_ItemSupplyTypeList,
|
|
Res_SupplierItem,
|
|
Res_SupplierItemList,
|
|
)
|
|
|
|
# 협력사-상품 매핑 라우터. company_id 스코프는 상위 협력사/상품 소유권으로 확인.
|
|
router = APIRouter(prefix="/v1/supplier-item", tags=["SupplierItem"], responses={404: {"description": "Not found"}})
|
|
|
|
|
|
@router.get(path="/by-supplier/{supplier_id}", response_model=Res_SupplierItemList, summary="협력사 취급상품 목록")
|
|
async def list_supplier_items(
|
|
supplier_id: UUID, service: SupplierItemService = Depends(), user_info: UserInfo = Depends(IsValidAccessToken)
|
|
):
|
|
return RemoveNoneResponse(await service.list_by_supplier(user_info.company_id, str(supplier_id)))
|
|
|
|
|
|
@router.get(path="/by-item/{item_id}", response_model=Res_ItemSupplyTypeList, summary="상품 취급 협력사 공급유형 목록")
|
|
async def list_item_supply_types(
|
|
item_id: UUID, service: SupplierItemService = Depends(), user_info: UserInfo = Depends(IsValidAccessToken)
|
|
):
|
|
return RemoveNoneResponse(await service.list_by_item(user_info.company_id, str(item_id)))
|
|
|
|
|
|
@router.post(path="/create", response_model=Res_SupplierItem, summary="취급상품 매핑 추가")
|
|
async def create_supplier_item(
|
|
req: Req_CreateSupplierItem, service: SupplierItemService = Depends(), user_info: UserInfo = Depends(IsValidAccessToken)
|
|
):
|
|
return RemoveNoneResponse(await service.create(user_info.company_id, req))
|
|
|
|
|
|
@router.post(path="/by-supplier/{supplier_id}/bulk", response_model=Res_BulkMapByNames, summary="취급상품 이름 일괄 매핑(엑셀 업로드)")
|
|
async def bulk_map_supplier_items(
|
|
supplier_id: UUID, req: Req_BulkMapByNames, service: SupplierItemService = Depends(), user_info: UserInfo = Depends(IsValidAccessToken)
|
|
):
|
|
return RemoveNoneResponse(await service.bulk_map_by_names(user_info.company_id, str(supplier_id), req.names))
|
|
|
|
|
|
@router.patch(path="/update/{supplier_item_id}", response_model=Res_WebPacketProtocol, summary="취급상품 공급유형 수정")
|
|
async def update_supply_type(
|
|
supplier_item_id: UUID, req: Req_UpdateSupplyType, service: SupplierItemService = Depends(), user_info: UserInfo = Depends(IsValidAccessToken)
|
|
):
|
|
return RemoveNoneResponse(await service.update_type(user_info.company_id, str(supplier_item_id), req))
|
|
|
|
|
|
@router.delete(path="/delete/{supplier_item_id}", response_model=Res_WebPacketProtocol, summary="취급상품 매핑 삭제")
|
|
async def delete_supplier_item(
|
|
supplier_item_id: UUID, service: SupplierItemService = Depends(), user_info: UserInfo = Depends(IsValidAccessToken)
|
|
):
|
|
return RemoveNoneResponse(await service.delete(user_info.company_id, str(supplier_item_id)))
|