- 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>
110 lines
4.2 KiB
Python
110 lines
4.2 KiB
Python
import uuid
|
|
|
|
from fastapi import Depends
|
|
|
|
from common.database.db_session_manager import DB_SESSION_MNG
|
|
from common.database.model.models import items
|
|
from common.enums import DBWRType, ErrorType
|
|
from common.logger import LOG
|
|
from crud.item_crud import IItemCRUD, ItemCRUD
|
|
from router.v1.item.protocol import ItemData, Res_DeleteItem, Res_Item, Res_ItemList
|
|
|
|
|
|
class ItemService:
|
|
"""상품 비즈니스 로직. company_id 로 소유권을 확인한다(멀티테넌트)."""
|
|
|
|
def __init__(self, item_crud: IItemCRUD = Depends(ItemCRUD)):
|
|
self.item_crud = item_crud
|
|
|
|
async def _fetch_owned(self, company_uuid: uuid.UUID, item_id: uuid.UUID):
|
|
"""item 조회 + 소유권 확인. (ErrorType, item|None) 반환."""
|
|
err_type, item = await DB_SESSION_MNG.execute_lambda(
|
|
items.DBType(),
|
|
DBWRType.DB_READ.value,
|
|
lambda s: self.item_crud.get_by_id(s, item_id),
|
|
)
|
|
if err_type != ErrorType.SUCCESS or item is None:
|
|
return ErrorType.ITEM_NOT_FOUND, None
|
|
if item.company_id != company_uuid:
|
|
return ErrorType.ITEM_NOT_FOUND, None
|
|
return ErrorType.SUCCESS, item
|
|
|
|
async def list_items(self, company_id: str, search, category, page: int, size: int) -> Res_ItemList:
|
|
res = Res_ItemList(page=page, size=size)
|
|
company_uuid = uuid.UUID(company_id)
|
|
skip = (page - 1) * size
|
|
|
|
err_type, rows, total = await DB_SESSION_MNG.execute_lambda(
|
|
items.DBType(),
|
|
DBWRType.DB_READ.value,
|
|
lambda s: self.item_crud.search(s, company_uuid, search, category, skip, size),
|
|
)
|
|
if err_type != ErrorType.SUCCESS:
|
|
res.result.SetResult(err_type)
|
|
return res
|
|
res.items = [ItemData.model_validate(r) for r in rows]
|
|
res.total = total
|
|
return res
|
|
|
|
async def get_item(self, company_id: str, item_id: str) -> Res_Item:
|
|
res = Res_Item()
|
|
err_type, item = await self._fetch_owned(uuid.UUID(company_id), uuid.UUID(item_id))
|
|
if err_type != ErrorType.SUCCESS:
|
|
res.result.SetResult(err_type)
|
|
return res
|
|
res.item = ItemData.model_validate(item)
|
|
return res
|
|
|
|
async def create_item(self, company_id: str, user_id: str, data: dict) -> Res_Item:
|
|
res = Res_Item()
|
|
item = items(**data, company_id=uuid.UUID(company_id), user_id=uuid.UUID(user_id))
|
|
err_type = await DB_SESSION_MNG.execute_lambda_run(
|
|
[items.DBType()],
|
|
[lambda s: self.item_crud.add_item(s, item)],
|
|
)
|
|
if err_type != ErrorType.SUCCESS:
|
|
res.result.SetResult(err_type)
|
|
return res
|
|
# 서버 기본값(created_at/updated_at)은 insert 후 Python 객체에 실리지 않으므로 재조회한다.
|
|
return await self.get_item(company_id, str(item.item_id))
|
|
|
|
async def update_item(self, company_id: str, item_id: str, data: dict) -> Res_Item:
|
|
res = Res_Item()
|
|
company_uuid = uuid.UUID(company_id)
|
|
item_uuid = uuid.UUID(item_id)
|
|
|
|
# 소유권 확인
|
|
err_type, _ = await self._fetch_owned(company_uuid, item_uuid)
|
|
if err_type != ErrorType.SUCCESS:
|
|
res.result.SetResult(err_type)
|
|
return res
|
|
|
|
err_type = await DB_SESSION_MNG.execute_lambda_run(
|
|
[items.DBType()],
|
|
[lambda s: self.item_crud.update_item(s, item_uuid, data)],
|
|
)
|
|
if err_type != ErrorType.SUCCESS:
|
|
res.result.SetResult(err_type)
|
|
return res
|
|
|
|
# 갱신 후 재조회
|
|
return await self.get_item(company_id, item_id)
|
|
|
|
async def delete_item(self, company_id: str, item_id: str) -> Res_DeleteItem:
|
|
res = Res_DeleteItem()
|
|
company_uuid = uuid.UUID(company_id)
|
|
item_uuid = uuid.UUID(item_id)
|
|
|
|
err_type, _ = await self._fetch_owned(company_uuid, item_uuid)
|
|
if err_type != ErrorType.SUCCESS:
|
|
res.result.SetResult(err_type)
|
|
return res
|
|
|
|
err_type = await DB_SESSION_MNG.execute_lambda_run(
|
|
[items.DBType()],
|
|
[lambda s: self.item_crud.soft_delete(s, item_uuid)],
|
|
)
|
|
if err_type != ErrorType.SUCCESS:
|
|
res.result.SetResult(err_type)
|
|
return res
|