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