o2o-negosium-original/negodata/backend/services/supplier_service.py
Mina Choi 1f778ab975 [feat] negodata/backend: 상품·협력사·견적 도메인 CRUD + delivery_type 코드화 + 공용 /v1/enums
- 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>
2026-06-17 15:58:38 +09:00

110 lines
4.5 KiB
Python

import uuid
from fastapi import Depends
from common.database.db_session_manager import DB_SESSION_MNG
from common.database.model.models import suppliers
from common.enums import DBWRType, ErrorType
from common.logger import LOG
from crud.supplier_crud import ISupplierCRUD, SupplierCRUD
from router.v1.supplier.protocol import Res_DeleteSupplier, Res_Supplier, Res_SupplierList, SupplierData
class SupplierService:
"""협력사 비즈니스 로직. company_id 로 소유권을 확인한다(멀티테넌트)."""
def __init__(self, supplier_crud: ISupplierCRUD = Depends(SupplierCRUD)):
self.supplier_crud = supplier_crud
async def _fetch_owned(self, company_uuid: uuid.UUID, supplier_id: uuid.UUID):
"""supplier 조회 + 소유권 확인. (ErrorType, supplier|None) 반환."""
err_type, supplier = await DB_SESSION_MNG.execute_lambda(
suppliers.DBType(),
DBWRType.DB_READ.value,
lambda s: self.supplier_crud.get_by_id(s, supplier_id),
)
if err_type != ErrorType.SUCCESS or supplier is None:
return ErrorType.SUPPLIER_NOT_FOUND, None
if supplier.company_id != company_uuid:
return ErrorType.SUPPLIER_NOT_FOUND, None
return ErrorType.SUCCESS, supplier
async def list_suppliers(self, company_id: str, search, page: int, size: int) -> Res_SupplierList:
res = Res_SupplierList(page=page, size=size)
company_uuid = uuid.UUID(company_id)
skip = (page - 1) * size
err_type, rows, total = await DB_SESSION_MNG.execute_lambda(
suppliers.DBType(),
DBWRType.DB_READ.value,
lambda s: self.supplier_crud.search(s, company_uuid, search, skip, size),
)
if err_type != ErrorType.SUCCESS:
res.result.SetResult(err_type)
return res
res.suppliers = [SupplierData.model_validate(r) for r in rows]
res.total = total
return res
async def get_supplier(self, company_id: str, supplier_id: str) -> Res_Supplier:
res = Res_Supplier()
err_type, supplier = await self._fetch_owned(uuid.UUID(company_id), uuid.UUID(supplier_id))
if err_type != ErrorType.SUCCESS:
res.result.SetResult(err_type)
return res
res.supplier = SupplierData.model_validate(supplier)
return res
async def create_supplier(self, company_id: str, user_id: str, data: dict) -> Res_Supplier:
res = Res_Supplier()
supplier = suppliers(**data, company_id=uuid.UUID(company_id), user_id=uuid.UUID(user_id))
err_type = await DB_SESSION_MNG.execute_lambda_run(
[suppliers.DBType()],
[lambda s: self.supplier_crud.add_supplier(s, supplier)],
)
if err_type != ErrorType.SUCCESS:
res.result.SetResult(err_type)
return res
# 서버 기본값(created_at/updated_at)은 insert 후 객체에 실리지 않으므로 재조회한다.
return await self.get_supplier(company_id, str(supplier.supplier_id))
async def update_supplier(self, company_id: str, supplier_id: str, data: dict) -> Res_Supplier:
res = Res_Supplier()
company_uuid = uuid.UUID(company_id)
supplier_uuid = uuid.UUID(supplier_id)
# 소유권 확인
err_type, _ = await self._fetch_owned(company_uuid, supplier_uuid)
if err_type != ErrorType.SUCCESS:
res.result.SetResult(err_type)
return res
err_type = await DB_SESSION_MNG.execute_lambda_run(
[suppliers.DBType()],
[lambda s: self.supplier_crud.update_supplier(s, supplier_uuid, data)],
)
if err_type != ErrorType.SUCCESS:
res.result.SetResult(err_type)
return res
# 갱신 후 재조회
return await self.get_supplier(company_id, supplier_id)
async def delete_supplier(self, company_id: str, supplier_id: str) -> Res_DeleteSupplier:
res = Res_DeleteSupplier()
company_uuid = uuid.UUID(company_id)
supplier_uuid = uuid.UUID(supplier_id)
err_type, _ = await self._fetch_owned(company_uuid, supplier_uuid)
if err_type != ErrorType.SUCCESS:
res.result.SetResult(err_type)
return res
err_type = await DB_SESSION_MNG.execute_lambda_run(
[suppliers.DBType()],
[lambda s: self.supplier_crud.soft_delete(s, supplier_uuid)],
)
if err_type != ErrorType.SUCCESS:
res.result.SetResult(err_type)
return res