Files
wehub-resource-sync 41b710f9c7
CI / Frontend checks (push) Failing after 0s
CI / Backend tests (push) Failing after 1s
I18n Documentation Sync / sync-docs (push) Failing after 0s
chore: import upstream snapshot with attribution
2026-07-13 12:28:40 +08:00

86 lines
2.9 KiB
Python

"""
基础服务类
提供通用的业务逻辑操作
"""
from typing import Generic, TypeVar, Type, Optional, List, Dict, Any
from sqlalchemy.orm import Session
from sqlalchemy import and_, or_
from ..repositories.base import BaseRepository, ModelType as RepoModelType
from ..schemas.base import BaseSchema, PaginationParams, PaginationResponse
CreateSchemaType = TypeVar("CreateSchemaType")
UpdateSchemaType = TypeVar("UpdateSchemaType")
ResponseSchemaType = TypeVar("ResponseSchemaType")
class BaseService(Generic[RepoModelType, CreateSchemaType, UpdateSchemaType, ResponseSchemaType]):
"""Base service class with common CRUD operations."""
def __init__(self, repository: BaseRepository[RepoModelType]):
self.repository = repository
def get(self, id: str) -> Optional[RepoModelType]:
"""Get a single record by ID."""
return self.repository.get_by_id(id)
def get_multi(
self,
skip: int = 0,
limit: int = 100,
filters: Optional[Dict[str, Any]] = None
) -> List[RepoModelType]:
"""Get multiple records with optional filtering."""
if filters:
return self.repository.find_by(**filters)
return self.repository.get_all(skip=skip, limit=limit)
def create(self, **kwargs) -> RepoModelType:
"""Create a new record."""
return self.repository.create(**kwargs)
def update(self, id: str, **kwargs) -> Optional[RepoModelType]:
"""Update an existing record."""
return self.repository.update(id, **kwargs)
def delete(self, id: str) -> bool:
"""Delete a record by ID."""
return self.repository.delete(id)
def count(self, filters: Optional[Dict[str, Any]] = None) -> int:
"""Count records with optional filtering."""
if filters:
return len(self.repository.find_by(**filters))
return self.repository.count()
def exists(self, id: str) -> bool:
"""Check if a record exists by ID."""
return self.repository.exists(id)
def get_paginated(
self,
pagination: PaginationParams,
filters: Optional[Dict[str, Any]] = None
) -> tuple[List[RepoModelType], PaginationResponse]:
"""Get paginated results."""
skip = (pagination.page - 1) * pagination.size
limit = pagination.size
items = self.get_multi(skip=skip, limit=limit, filters=filters)
total = self.count(filters)
pages = (total + pagination.size - 1) // pagination.size
has_next = pagination.page < pages
has_prev = pagination.page > 1
pagination_response = PaginationResponse(
page=pagination.page,
size=pagination.size,
total=total,
pages=pages,
has_next=has_next,
has_prev=has_prev
)
return items, pagination_response