from typing import Any, Dict, List, Union, Protocol from dataclasses import dataclass from sqlalchemy.orm import Query from Services.PostgresDb.Models.response import PostgresResponse class DataValidator(Protocol): """Protocol for data validation methods.""" @staticmethod def validate_data(data: Any, cls_object: Any) -> None: """Validate data and raise HTTPExceptionApi if invalid.""" ... @dataclass class PaginationConfig: """ Configuration for pagination settings. Attributes: page: Current page number (default: 1) size: Items per page (default: 10) order_field: Field to order by (default: "id") order_type: Order direction (default: "asc") """ page: int = 1 size: int = 10 order_field: str = "id" order_type: str = "asc" class Pagination: """ Handles pagination logic for query results. Manages page size, current page, ordering, and calculates total pages and items based on the data source. Attributes: DEFAULT_SIZE: Default number of items per page (10) MIN_SIZE: Minimum allowed page size (10) MAX_SIZE: Maximum allowed page size (40) """ DEFAULT_SIZE = 10 MIN_SIZE = 10 MAX_SIZE = 40 def __init__(self): self.size: int = self.DEFAULT_SIZE self.page: int = 1 self.order_field: str = "id" self.order_type: str = "asc" self.page_count: int = 1 self.total_count: int = 0 self.total_pages: int = 1 def change(self, config: PaginationConfig) -> None: """Update pagination settings from config.""" self.size = ( config.size if self.MIN_SIZE <= config.size <= self.MAX_SIZE else self.DEFAULT_SIZE ) self.page = config.page self.order_field = config.order_field self.order_type = config.order_type self._update_page_counts() def feed(self, data: Union[List[Any], PostgresResponse, Query]) -> None: """Calculate pagination based on data source.""" self.total_count = ( len(data) if isinstance(data, list) else data.count if isinstance(data, PostgresResponse) else data.count() ) self._update_page_counts() def _update_page_counts(self) -> None: """Update page counts and validate current page.""" self.total_pages = max(1, (self.total_count + self.size - 1) // self.size) self.page = max(1, min(self.page, self.total_pages)) self.page_count = ( self.total_count % self.size if self.page == self.total_pages and self.total_count % self.size else self.size ) def as_dict(self) -> Dict[str, Any]: """Convert pagination state to dictionary format.""" return { "size": self.size, "page": self.page, "totalCount": self.total_count, "totalPages": self.total_pages, "pageCount": self.page_count, "orderField": self.order_field, "orderType": self.order_type, }