First implementation API for PIP (Proyecto: Pharmacy Integration Platform)
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
from .entities import (
|
||||
APIClientEntity,
|
||||
APIKeyEntity,
|
||||
AuditLogEntity,
|
||||
ConnectorConfigEntity,
|
||||
ConnectorEntity,
|
||||
ConnectorStatus,
|
||||
ConnectorVersionEntity,
|
||||
ERPType,
|
||||
ERPSystemEntity,
|
||||
InventoryHistoryEntity,
|
||||
InventoryRecordEntity,
|
||||
MedicationCatalogEntryEntity,
|
||||
MedicationEntity,
|
||||
PharmacyEntity,
|
||||
PharmacyStatus,
|
||||
ReservationEntity,
|
||||
ReservationStatus,
|
||||
SyncJobEntity,
|
||||
SyncJobStatus,
|
||||
SyncLogEntity,
|
||||
SyncStrategy,
|
||||
TechnicalUserEntity,
|
||||
UserRole,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"APIClientEntity",
|
||||
"APIKeyEntity",
|
||||
"AuditLogEntity",
|
||||
"ConnectorConfigEntity",
|
||||
"ConnectorEntity",
|
||||
"ConnectorStatus",
|
||||
"ConnectorVersionEntity",
|
||||
"ERPType",
|
||||
"ERPSystemEntity",
|
||||
"InventoryHistoryEntity",
|
||||
"InventoryRecordEntity",
|
||||
"MedicationCatalogEntryEntity",
|
||||
"MedicationEntity",
|
||||
"PharmacyEntity",
|
||||
"PharmacyStatus",
|
||||
"ReservationEntity",
|
||||
"ReservationStatus",
|
||||
"SyncJobEntity",
|
||||
"SyncJobStatus",
|
||||
"SyncLogEntity",
|
||||
"SyncStrategy",
|
||||
"TechnicalUserEntity",
|
||||
"UserRole",
|
||||
]
|
||||
@@ -0,0 +1,317 @@
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class PharmacyStatus(str, Enum):
|
||||
ACTIVE = "active"
|
||||
INACTIVE = "inactive"
|
||||
SUSPENDED = "suspended"
|
||||
PENDING = "pending"
|
||||
|
||||
|
||||
class ERPType(str, Enum):
|
||||
FARMATIC = "farmatic"
|
||||
NIXFARMA = "nixfarma"
|
||||
UNYCOP = "unycop"
|
||||
CUSTOM_REST = "custom_rest"
|
||||
CUSTOM_SOAP = "custom_soap"
|
||||
CSV = "csv"
|
||||
FTP = "ftp"
|
||||
SQL = "sql"
|
||||
MOCK = "mock"
|
||||
|
||||
|
||||
class ConnectorStatus(str, Enum):
|
||||
ACTIVE = "active"
|
||||
INACTIVE = "inactive"
|
||||
ERROR = "error"
|
||||
PENDING = "pending"
|
||||
UPDATING = "updating"
|
||||
|
||||
|
||||
class SyncStrategy(str, Enum):
|
||||
FULL = "full"
|
||||
INCREMENTAL = "incremental"
|
||||
EVENT_DRIVEN = "event_driven"
|
||||
SCHEDULED = "scheduled"
|
||||
HYBRID = "hybrid"
|
||||
|
||||
|
||||
class SyncJobStatus(str, Enum):
|
||||
PENDING = "pending"
|
||||
RUNNING = "running"
|
||||
COMPLETED = "completed"
|
||||
FAILED = "failed"
|
||||
CANCELLED = "cancelled"
|
||||
|
||||
|
||||
class ReservationStatus(str, Enum):
|
||||
PENDING = "pending"
|
||||
CONFIRMED = "confirmed"
|
||||
CANCELLED = "cancelled"
|
||||
EXPIRED = "expired"
|
||||
|
||||
|
||||
class UserRole(str, Enum):
|
||||
SUPERADMIN = "superadmin"
|
||||
ADMIN = "admin"
|
||||
OPERATOR = "operator"
|
||||
VIEWER = "viewer"
|
||||
API_CLIENT = "api_client"
|
||||
|
||||
|
||||
class PharmacyEntity(BaseModel):
|
||||
id: uuid.UUID | None = None
|
||||
code: str
|
||||
name: str
|
||||
address: str | None = None
|
||||
city: str | None = None
|
||||
province: str | None = None
|
||||
postal_code: str | None = None
|
||||
country: str = "ES"
|
||||
latitude: float | None = None
|
||||
longitude: float | None = None
|
||||
phone: str | None = None
|
||||
email: str | None = None
|
||||
opening_hours: dict | None = None
|
||||
status: PharmacyStatus = PharmacyStatus.PENDING
|
||||
erp_type: ERPType | None = None
|
||||
erp_version: str | None = None
|
||||
connector_id: uuid.UUID | None = None
|
||||
sync_strategy: SyncStrategy = SyncStrategy.INCREMENTAL
|
||||
sync_interval_minutes: int = 30
|
||||
last_sync_at: datetime | None = None
|
||||
last_sync_status: SyncJobStatus | None = None
|
||||
metadata_: dict | None = Field(default=None, alias="metadata")
|
||||
created_at: datetime | None = None
|
||||
updated_at: datetime | None = None
|
||||
|
||||
model_config = {"populate_by_name": True}
|
||||
|
||||
|
||||
class ERPSystemEntity(BaseModel):
|
||||
id: uuid.UUID | None = None
|
||||
name: str
|
||||
erp_type: ERPType
|
||||
version: str | None = None
|
||||
base_url: str | None = None
|
||||
auth_config: dict | None = None
|
||||
status: ConnectorStatus = ConnectorStatus.PENDING
|
||||
metadata_: dict | None = Field(default=None, alias="metadata")
|
||||
created_at: datetime | None = None
|
||||
updated_at: datetime | None = None
|
||||
|
||||
model_config = {"populate_by_name": True}
|
||||
|
||||
|
||||
class ConnectorEntity(BaseModel):
|
||||
id: uuid.UUID | None = None
|
||||
erp_system_id: uuid.UUID
|
||||
pharmacy_id: uuid.UUID
|
||||
name: str
|
||||
connector_type: ERPType
|
||||
version: str = "1.0.0"
|
||||
config: dict | None = None
|
||||
status: ConnectorStatus = ConnectorStatus.PENDING
|
||||
last_heartbeat_at: datetime | None = None
|
||||
last_error: str | None = None
|
||||
metadata_: dict | None = Field(default=None, alias="metadata")
|
||||
created_at: datetime | None = None
|
||||
updated_at: datetime | None = None
|
||||
|
||||
model_config = {"populate_by_name": True}
|
||||
|
||||
|
||||
class ConnectorVersionEntity(BaseModel):
|
||||
id: uuid.UUID | None = None
|
||||
connector_id: uuid.UUID | None = None
|
||||
connector_type: ERPType
|
||||
version: str
|
||||
changelog: str | None = None
|
||||
download_url: str | None = None
|
||||
checksum: str | None = None
|
||||
is_latest: bool = False
|
||||
is_required: bool = False
|
||||
released_at: datetime | None = None
|
||||
created_at: datetime | None = None
|
||||
|
||||
|
||||
class ConnectorConfigEntity(BaseModel):
|
||||
id: uuid.UUID | None = None
|
||||
connector_id: uuid.UUID
|
||||
key: str
|
||||
value: str
|
||||
encrypted: bool = False
|
||||
description: str | None = None
|
||||
created_at: datetime | None = None
|
||||
updated_at: datetime | None = None
|
||||
|
||||
|
||||
class MedicationEntity(BaseModel):
|
||||
id: uuid.UUID | None = None
|
||||
nregistro: str
|
||||
name: str
|
||||
active_ingredient: str | None = None
|
||||
dosage: str | None = None
|
||||
form: str | None = None
|
||||
atc_code: str | None = None
|
||||
prescription_required: bool = False
|
||||
manufacturer: str | None = None
|
||||
metadata_: dict | None = Field(default=None, alias="metadata")
|
||||
created_at: datetime | None = None
|
||||
updated_at: datetime | None = None
|
||||
|
||||
model_config = {"populate_by_name": True}
|
||||
|
||||
|
||||
class MedicationCatalogEntryEntity(BaseModel):
|
||||
id: uuid.UUID | None = None
|
||||
pharmacy_id: uuid.UUID
|
||||
medication_id: uuid.UUID
|
||||
price: float | None = None
|
||||
stock: int = 0
|
||||
is_available: bool = False
|
||||
last_verified_at: datetime | None = None
|
||||
metadata_: dict | None = Field(default=None, alias="metadata")
|
||||
created_at: datetime | None = None
|
||||
updated_at: datetime | None = None
|
||||
|
||||
model_config = {"populate_by_name": True}
|
||||
|
||||
|
||||
class InventoryRecordEntity(BaseModel):
|
||||
id: uuid.UUID | None = None
|
||||
pharmacy_id: uuid.UUID
|
||||
medication_id: uuid.UUID
|
||||
stock: int = 0
|
||||
reserved_stock: int = 0
|
||||
available_stock: int = 0
|
||||
min_stock: int | None = None
|
||||
max_stock: int | None = None
|
||||
last_updated_at: datetime | None = None
|
||||
source: str | None = None
|
||||
batch_id: str | None = None
|
||||
metadata_: dict | None = Field(default=None, alias="metadata")
|
||||
created_at: datetime | None = None
|
||||
updated_at: datetime | None = None
|
||||
|
||||
model_config = {"populate_by_name": True}
|
||||
|
||||
|
||||
class InventoryHistoryEntity(BaseModel):
|
||||
id: uuid.UUID | None = None
|
||||
inventory_record_id: uuid.UUID | None = None
|
||||
pharmacy_id: uuid.UUID
|
||||
medication_id: uuid.UUID
|
||||
previous_stock: int
|
||||
new_stock: int
|
||||
delta: int
|
||||
reason: str | None = None
|
||||
source: str | None = None
|
||||
created_at: datetime | None = None
|
||||
|
||||
|
||||
class ReservationEntity(BaseModel):
|
||||
id: uuid.UUID | None = None
|
||||
pharmacy_id: uuid.UUID
|
||||
medication_id: uuid.UUID
|
||||
user_id: uuid.UUID | None = None
|
||||
external_reference: str | None = None
|
||||
quantity: int
|
||||
status: ReservationStatus = ReservationStatus.PENDING
|
||||
expires_at: datetime | None = None
|
||||
confirmed_at: datetime | None = None
|
||||
cancelled_at: datetime | None = None
|
||||
idempotency_key: str | None = None
|
||||
metadata_: dict | None = Field(default=None, alias="metadata")
|
||||
created_at: datetime | None = None
|
||||
updated_at: datetime | None = None
|
||||
|
||||
model_config = {"populate_by_name": True}
|
||||
|
||||
|
||||
class SyncJobEntity(BaseModel):
|
||||
id: uuid.UUID | None = None
|
||||
pharmacy_id: uuid.UUID
|
||||
connector_id: uuid.UUID
|
||||
strategy: SyncStrategy
|
||||
status: SyncJobStatus = SyncJobStatus.PENDING
|
||||
started_at: datetime | None = None
|
||||
completed_at: datetime | None = None
|
||||
items_total: int | None = None
|
||||
items_processed: int | None = None
|
||||
items_failed: int | None = None
|
||||
error_message: str | None = None
|
||||
metadata_: dict | None = Field(default=None, alias="metadata")
|
||||
created_at: datetime | None = None
|
||||
updated_at: datetime | None = None
|
||||
|
||||
model_config = {"populate_by_name": True}
|
||||
|
||||
|
||||
class SyncLogEntity(BaseModel):
|
||||
id: uuid.UUID | None = None
|
||||
sync_job_id: uuid.UUID
|
||||
level: str = "INFO"
|
||||
message: str
|
||||
details: dict | None = None
|
||||
created_at: datetime | None = None
|
||||
|
||||
|
||||
class AuditLogEntity(BaseModel):
|
||||
id: uuid.UUID | None = None
|
||||
actor_id: uuid.UUID | None = None
|
||||
actor_type: str | None = None
|
||||
action: str
|
||||
resource_type: str
|
||||
resource_id: str | None = None
|
||||
old_value: dict | None = None
|
||||
new_value: dict | None = None
|
||||
ip_address: str | None = None
|
||||
user_agent: str | None = None
|
||||
request_id: str | None = None
|
||||
created_at: datetime | None = None
|
||||
|
||||
|
||||
class TechnicalUserEntity(BaseModel):
|
||||
id: uuid.UUID | None = None
|
||||
username: str
|
||||
email: str | None = None
|
||||
full_name: str | None = None
|
||||
role: UserRole = UserRole.VIEWER
|
||||
is_active: bool = True
|
||||
scopes: list[str] = Field(default_factory=list)
|
||||
last_login_at: datetime | None = None
|
||||
created_at: datetime | None = None
|
||||
updated_at: datetime | None = None
|
||||
|
||||
|
||||
class APIClientEntity(BaseModel):
|
||||
id: uuid.UUID | None = None
|
||||
name: str
|
||||
description: str | None = None
|
||||
owner_id: uuid.UUID | None = None
|
||||
is_active: bool = True
|
||||
scopes: list[str] = Field(default_factory=list)
|
||||
rate_limit: int | None = None
|
||||
allowed_ips: list[str] = Field(default_factory=list)
|
||||
metadata_: dict | None = Field(default=None, alias="metadata")
|
||||
created_at: datetime | None = None
|
||||
updated_at: datetime | None = None
|
||||
|
||||
model_config = {"populate_by_name": True}
|
||||
|
||||
|
||||
class APIKeyEntity(BaseModel):
|
||||
id: uuid.UUID | None = None
|
||||
api_client_id: uuid.UUID
|
||||
key_prefix: str
|
||||
key_hash: bytes
|
||||
name: str
|
||||
is_active: bool = True
|
||||
expires_at: datetime | None = None
|
||||
last_used_at: datetime | None = None
|
||||
created_at: datetime | None = None
|
||||
@@ -0,0 +1,35 @@
|
||||
from .repositories import (
|
||||
IAPIClientRepository,
|
||||
IAPIKeyRepository,
|
||||
IAuditLogRepository,
|
||||
IConnectorConfigRepository,
|
||||
IConnectorRepository,
|
||||
IConnectorVersionRepository,
|
||||
IERPSystemRepository,
|
||||
IInventoryRepository,
|
||||
IMedicationCatalogRepository,
|
||||
IMedicationRepository,
|
||||
IPharmacyRepository,
|
||||
IReservationRepository,
|
||||
ISyncJobRepository,
|
||||
ISyncLogRepository,
|
||||
ITechnicalUserRepository,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"IAPIClientRepository",
|
||||
"IAPIKeyRepository",
|
||||
"IAuditLogRepository",
|
||||
"IConnectorConfigRepository",
|
||||
"IConnectorRepository",
|
||||
"IConnectorVersionRepository",
|
||||
"IERPSystemRepository",
|
||||
"IInventoryRepository",
|
||||
"IMedicationCatalogRepository",
|
||||
"IMedicationRepository",
|
||||
"IPharmacyRepository",
|
||||
"IReservationRepository",
|
||||
"ISyncJobRepository",
|
||||
"ISyncLogRepository",
|
||||
"ITechnicalUserRepository",
|
||||
]
|
||||
@@ -0,0 +1,249 @@
|
||||
import uuid
|
||||
from abc import ABC, abstractmethod
|
||||
from collections.abc import Sequence
|
||||
from typing import Any
|
||||
|
||||
from src.domain.entities import (
|
||||
APIClientEntity,
|
||||
APIKeyEntity,
|
||||
AuditLogEntity,
|
||||
ConnectorConfigEntity,
|
||||
ConnectorEntity,
|
||||
ConnectorVersionEntity,
|
||||
ERPSystemEntity,
|
||||
InventoryHistoryEntity,
|
||||
InventoryRecordEntity,
|
||||
MedicationCatalogEntryEntity,
|
||||
MedicationEntity,
|
||||
PharmacyEntity,
|
||||
ReservationEntity,
|
||||
SyncJobEntity,
|
||||
SyncLogEntity,
|
||||
TechnicalUserEntity,
|
||||
)
|
||||
|
||||
|
||||
class IPharmacyRepository(ABC):
|
||||
@abstractmethod
|
||||
async def get_by_id(self, pharmacy_id: uuid.UUID) -> PharmacyEntity | None: ...
|
||||
|
||||
@abstractmethod
|
||||
async def get_by_code(self, code: str) -> PharmacyEntity | None: ...
|
||||
|
||||
@abstractmethod
|
||||
async def list_pharmacies(
|
||||
self,
|
||||
*,
|
||||
status: str | None = None,
|
||||
erp_type: str | None = None,
|
||||
offset: int = 0,
|
||||
limit: int = 50,
|
||||
) -> tuple[Sequence[PharmacyEntity], int]: ...
|
||||
|
||||
@abstractmethod
|
||||
async def create(self, entity: PharmacyEntity) -> PharmacyEntity: ...
|
||||
|
||||
@abstractmethod
|
||||
async def update(self, entity: PharmacyEntity) -> PharmacyEntity: ...
|
||||
|
||||
@abstractmethod
|
||||
async def delete(self, pharmacy_id: uuid.UUID) -> bool: ...
|
||||
|
||||
|
||||
class IERPSystemRepository(ABC):
|
||||
@abstractmethod
|
||||
async def get_by_id(self, erp_id: uuid.UUID) -> ERPSystemEntity | None: ...
|
||||
|
||||
@abstractmethod
|
||||
async def list_erp_systems(self, *, erp_type: str | None = None, offset: int = 0, limit: int = 50) -> tuple[Sequence[ERPSystemEntity], int]: ...
|
||||
|
||||
@abstractmethod
|
||||
async def create(self, entity: ERPSystemEntity) -> ERPSystemEntity: ...
|
||||
|
||||
@abstractmethod
|
||||
async def update(self, entity: ERPSystemEntity) -> ERPSystemEntity: ...
|
||||
|
||||
@abstractmethod
|
||||
async def delete(self, erp_id: uuid.UUID) -> bool: ...
|
||||
|
||||
|
||||
class IConnectorRepository(ABC):
|
||||
@abstractmethod
|
||||
async def get_by_id(self, connector_id: uuid.UUID) -> ConnectorEntity | None: ...
|
||||
|
||||
@abstractmethod
|
||||
async def list_connectors(self, *, erp_system_id: uuid.UUID | None = None, pharmacy_id: uuid.UUID | None = None, status: str | None = None, offset: int = 0, limit: int = 50) -> tuple[Sequence[ConnectorEntity], int]: ...
|
||||
|
||||
@abstractmethod
|
||||
async def create(self, entity: ConnectorEntity) -> ConnectorEntity: ...
|
||||
|
||||
@abstractmethod
|
||||
async def update(self, entity: ConnectorEntity) -> ConnectorEntity: ...
|
||||
|
||||
@abstractmethod
|
||||
async def delete(self, connector_id: uuid.UUID) -> bool: ...
|
||||
|
||||
|
||||
class IConnectorVersionRepository(ABC):
|
||||
@abstractmethod
|
||||
async def get_latest(self, connector_type: str) -> ConnectorVersionEntity | None: ...
|
||||
|
||||
@abstractmethod
|
||||
async def list_versions(self, *, connector_type: str | None = None, offset: int = 0, limit: int = 50) -> tuple[Sequence[ConnectorVersionEntity], int]: ...
|
||||
|
||||
@abstractmethod
|
||||
async def create(self, entity: ConnectorVersionEntity) -> ConnectorVersionEntity: ...
|
||||
|
||||
|
||||
class IConnectorConfigRepository(ABC):
|
||||
@abstractmethod
|
||||
async def list_by_connector(self, connector_id: uuid.UUID) -> Sequence[ConnectorConfigEntity]: ...
|
||||
|
||||
@abstractmethod
|
||||
async def get_by_key(self, connector_id: uuid.UUID, key: str) -> ConnectorConfigEntity | None: ...
|
||||
|
||||
@abstractmethod
|
||||
async def upsert(self, entity: ConnectorConfigEntity) -> ConnectorConfigEntity: ...
|
||||
|
||||
@abstractmethod
|
||||
async def delete(self, config_id: uuid.UUID) -> bool: ...
|
||||
|
||||
|
||||
class IMedicationRepository(ABC):
|
||||
@abstractmethod
|
||||
async def get_by_id(self, medication_id: uuid.UUID) -> MedicationEntity | None: ...
|
||||
|
||||
@abstractmethod
|
||||
async def get_by_nregistro(self, nregistro: str) -> MedicationEntity | None: ...
|
||||
|
||||
@abstractmethod
|
||||
async def search(self, query: str, *, offset: int = 0, limit: int = 50) -> tuple[Sequence[MedicationEntity], int]: ...
|
||||
|
||||
@abstractmethod
|
||||
async def create(self, entity: MedicationEntity) -> MedicationEntity: ...
|
||||
|
||||
@abstractmethod
|
||||
async def update(self, entity: MedicationEntity) -> MedicationEntity: ...
|
||||
|
||||
@abstractmethod
|
||||
async def delete(self, medication_id: uuid.UUID) -> bool: ...
|
||||
|
||||
|
||||
class IMedicationCatalogRepository(ABC):
|
||||
@abstractmethod
|
||||
async def get_entry(self, pharmacy_id: uuid.UUID, medication_id: uuid.UUID) -> MedicationCatalogEntryEntity | None: ...
|
||||
|
||||
@abstractmethod
|
||||
async def list_by_pharmacy(self, pharmacy_id: uuid.UUID, *, offset: int = 0, limit: int = 50) -> tuple[Sequence[MedicationCatalogEntryEntity], int]: ...
|
||||
|
||||
@abstractmethod
|
||||
async def upsert(self, entity: MedicationCatalogEntryEntity) -> MedicationCatalogEntryEntity: ...
|
||||
|
||||
|
||||
class IInventoryRepository(ABC):
|
||||
@abstractmethod
|
||||
async def get_record(self, pharmacy_id: uuid.UUID, medication_id: uuid.UUID) -> InventoryRecordEntity | None: ...
|
||||
|
||||
@abstractmethod
|
||||
async def list_by_pharmacy(self, pharmacy_id: uuid.UUID, *, offset: int = 0, limit: int = 50) -> tuple[Sequence[InventoryRecordEntity], int]: ...
|
||||
|
||||
@abstractmethod
|
||||
async def upsert(self, entity: InventoryRecordEntity) -> InventoryRecordEntity: ...
|
||||
|
||||
@abstractmethod
|
||||
async def add_history(self, entity: InventoryHistoryEntity) -> InventoryHistoryEntity: ...
|
||||
|
||||
@abstractmethod
|
||||
async def get_history(self, pharmacy_id: uuid.UUID, medication_id: uuid.UUID, *, offset: int = 0, limit: int = 50) -> Sequence[InventoryHistoryEntity]: ...
|
||||
|
||||
|
||||
class IReservationRepository(ABC):
|
||||
@abstractmethod
|
||||
async def get_by_id(self, reservation_id: uuid.UUID) -> ReservationEntity | None: ...
|
||||
|
||||
@abstractmethod
|
||||
async def get_by_idempotency_key(self, key: str) -> ReservationEntity | None: ...
|
||||
|
||||
@abstractmethod
|
||||
async def list_by_pharmacy(self, pharmacy_id: uuid.UUID, *, status: str | None = None, offset: int = 0, limit: int = 50) -> tuple[Sequence[ReservationEntity], int]: ...
|
||||
|
||||
@abstractmethod
|
||||
async def create(self, entity: ReservationEntity) -> ReservationEntity: ...
|
||||
|
||||
@abstractmethod
|
||||
async def update(self, entity: ReservationEntity) -> ReservationEntity: ...
|
||||
|
||||
|
||||
class ISyncJobRepository(ABC):
|
||||
@abstractmethod
|
||||
async def get_by_id(self, job_id: uuid.UUID) -> SyncJobEntity | None: ...
|
||||
|
||||
@abstractmethod
|
||||
async def list_by_pharmacy(self, pharmacy_id: uuid.UUID, *, status: str | None = None, offset: int = 0, limit: int = 50) -> tuple[Sequence[SyncJobEntity], int]: ...
|
||||
|
||||
@abstractmethod
|
||||
async def create(self, entity: SyncJobEntity) -> SyncJobEntity: ...
|
||||
|
||||
@abstractmethod
|
||||
async def update(self, entity: SyncJobEntity) -> SyncJobEntity: ...
|
||||
|
||||
|
||||
class ISyncLogRepository(ABC):
|
||||
@abstractmethod
|
||||
async def add(self, entity: SyncLogEntity) -> SyncLogEntity: ...
|
||||
|
||||
@abstractmethod
|
||||
async def list_by_job(self, job_id: uuid.UUID, *, level: str | None = None, offset: int = 0, limit: int = 100) -> Sequence[SyncLogEntity]: ...
|
||||
|
||||
|
||||
class IAuditLogRepository(ABC):
|
||||
@abstractmethod
|
||||
async def add(self, entity: AuditLogEntity) -> AuditLogEntity: ...
|
||||
|
||||
@abstractmethod
|
||||
async def list_logs(self, *, actor_id: uuid.UUID | None = None, action: str | None = None, resource_type: str | None = None, offset: int = 0, limit: int = 50) -> tuple[Sequence[AuditLogEntity], int]: ...
|
||||
|
||||
|
||||
class ITechnicalUserRepository(ABC):
|
||||
@abstractmethod
|
||||
async def get_by_id(self, user_id: uuid.UUID) -> TechnicalUserEntity | None: ...
|
||||
|
||||
@abstractmethod
|
||||
async def get_by_username(self, username: str) -> TechnicalUserEntity | None: ...
|
||||
|
||||
@abstractmethod
|
||||
async def list_users(self, *, role: str | None = None, is_active: bool | None = None, offset: int = 0, limit: int = 50) -> tuple[Sequence[TechnicalUserEntity], int]: ...
|
||||
|
||||
@abstractmethod
|
||||
async def create(self, entity: TechnicalUserEntity, password_hash: str) -> TechnicalUserEntity: ...
|
||||
|
||||
@abstractmethod
|
||||
async def update(self, entity: TechnicalUserEntity) -> TechnicalUserEntity: ...
|
||||
|
||||
|
||||
class IAPIClientRepository(ABC):
|
||||
@abstractmethod
|
||||
async def get_by_id(self, client_id: uuid.UUID) -> APIClientEntity | None: ...
|
||||
|
||||
@abstractmethod
|
||||
async def list_clients(self, *, is_active: bool | None = None, offset: int = 0, limit: int = 50) -> tuple[Sequence[APIClientEntity], int]: ...
|
||||
|
||||
@abstractmethod
|
||||
async def create(self, entity: APIClientEntity) -> APIClientEntity: ...
|
||||
|
||||
@abstractmethod
|
||||
async def update(self, entity: APIClientEntity) -> APIClientEntity: ...
|
||||
|
||||
|
||||
class IAPIKeyRepository(ABC):
|
||||
@abstractmethod
|
||||
async def get_by_prefix(self, key_prefix: str) -> APIKeyEntity | None: ...
|
||||
|
||||
@abstractmethod
|
||||
async def list_by_client(self, api_client_id: uuid.UUID) -> Sequence[APIKeyEntity]: ...
|
||||
|
||||
@abstractmethod
|
||||
async def create(self, entity: APIKeyEntity) -> APIKeyEntity: ...
|
||||
|
||||
@abstractmethod
|
||||
async def update_last_used(self, key_id: uuid.UUID) -> None: ...
|
||||
Reference in New Issue
Block a user