feat: доменный нейминг изменен
This commit is contained in:
@@ -18,9 +18,11 @@ class MockDatabase:
|
||||
self.target_channels_by_telegram_id: dict[int, domain.TargetChannel] = {}
|
||||
self.external_channels: dict[uuid.UUID, domain.ExternalChannel] = {}
|
||||
self.creatives: dict[uuid.UUID, domain.Creative] = {}
|
||||
self.purchases: dict[uuid.UUID, domain.Purchase] = {}
|
||||
self.placements: dict[uuid.UUID, domain.Placement] = {}
|
||||
self.subscribers: dict[uuid.UUID, domain.Subscriber] = {}
|
||||
self.subscribers_by_telegram_id: dict[int, domain.Subscriber] = {}
|
||||
self.subscriptions: dict[uuid.UUID, domain.Subscription] = {}
|
||||
self.views_snapshots: dict[uuid.UUID, domain.ViewsSnapshot] = {}
|
||||
self.placement_views_histories: dict[uuid.UUID, domain.PlacementViewsHistory] = {}
|
||||
self.m2m_target_external: dict[uuid.UUID, list[uuid.UUID]] = {}
|
||||
|
||||
def transaction(self) -> AbstractAsyncContextManager[None]:
|
||||
@@ -159,8 +161,8 @@ class MockDatabase:
|
||||
creative.created_at = datetime.datetime.now(datetime.UTC)
|
||||
if not hasattr(creative, 'updated_at') or creative.updated_at is None:
|
||||
creative.updated_at = datetime.datetime.now(datetime.UTC)
|
||||
if not hasattr(creative, 'purchases_count') or creative.purchases_count is None:
|
||||
creative.purchases_count = 0
|
||||
if not hasattr(creative, 'placements_count') or creative.placements_count is None:
|
||||
creative.placements_count = 0
|
||||
target_ch = self.target_channels.get(creative.target_channel_id)
|
||||
if target_ch:
|
||||
creative.target_channel = target_ch
|
||||
@@ -196,43 +198,43 @@ class MockDatabase:
|
||||
async def delete_creative(self, creative_id: uuid.UUID) -> None:
|
||||
self.creatives.pop(creative_id, None)
|
||||
|
||||
async def create_purchase(self, purchase: domain.Purchase) -> domain.Purchase:
|
||||
if not purchase.id:
|
||||
purchase.id = uuid.uuid4()
|
||||
if not hasattr(purchase, 'created_at') or purchase.created_at is None:
|
||||
purchase.created_at = datetime.datetime.now(datetime.UTC)
|
||||
if not hasattr(purchase, 'updated_at') or purchase.updated_at is None:
|
||||
purchase.updated_at = datetime.datetime.now(datetime.UTC)
|
||||
if not hasattr(purchase, 'subscriptions_count') or purchase.subscriptions_count is None:
|
||||
purchase.subscriptions_count = 0
|
||||
if not hasattr(purchase, 'status') or purchase.status is None:
|
||||
purchase.status = domain.PurchaseStatus.ACTIVE
|
||||
if not hasattr(purchase, 'views_availability') or purchase.views_availability is None:
|
||||
purchase.views_availability = domain.PostViewsAvailability.UNKNOWN
|
||||
async def create_placement(self, placement: domain.Placement) -> domain.Placement:
|
||||
if not placement.id:
|
||||
placement.id = uuid.uuid4()
|
||||
if not hasattr(placement, 'created_at') or placement.created_at is None:
|
||||
placement.created_at = datetime.datetime.now(datetime.UTC)
|
||||
if not hasattr(placement, 'updated_at') or placement.updated_at is None:
|
||||
placement.updated_at = datetime.datetime.now(datetime.UTC)
|
||||
if not hasattr(placement, 'subscriptions_count') or placement.subscriptions_count is None:
|
||||
placement.subscriptions_count = 0
|
||||
if not hasattr(placement, 'status') or placement.status is None:
|
||||
placement.status = domain.PlacementStatus.ACTIVE
|
||||
if not hasattr(placement, 'views_availability') or placement.views_availability is None:
|
||||
placement.views_availability = domain.PostViewsAvailability.UNKNOWN
|
||||
# Загружаем связанные объекты
|
||||
target_ch = self.target_channels.get(purchase.target_channel_id)
|
||||
target_ch = self.target_channels.get(placement.target_channel_id)
|
||||
if target_ch:
|
||||
purchase.target_channel = target_ch
|
||||
ext_ch = self.external_channels.get(purchase.external_channel_id)
|
||||
placement.target_channel = target_ch
|
||||
ext_ch = self.external_channels.get(placement.external_channel_id)
|
||||
if ext_ch:
|
||||
purchase.external_channel = ext_ch
|
||||
creative = self.creatives.get(purchase.creative_id)
|
||||
placement.external_channel = ext_ch
|
||||
creative = self.creatives.get(placement.creative_id)
|
||||
if creative:
|
||||
purchase.creative = creative
|
||||
self.purchases[purchase.id] = purchase
|
||||
return purchase
|
||||
placement.creative = creative
|
||||
self.placements[placement.id] = placement
|
||||
return placement
|
||||
|
||||
async def get_purchase(self, user_id: uuid.UUID, purchase_id: uuid.UUID) -> domain.Purchase | None:
|
||||
purchase = self.purchases.get(purchase_id)
|
||||
if purchase and purchase.user_id == user_id:
|
||||
return purchase
|
||||
async def get_placement(self, user_id: uuid.UUID, placement_id: uuid.UUID) -> domain.Placement | None:
|
||||
placement = self.placements.get(placement_id)
|
||||
if placement and placement.user_id == user_id:
|
||||
return placement
|
||||
return None
|
||||
|
||||
async def update_purchase(self, purchase: domain.Purchase) -> domain.Purchase:
|
||||
self.purchases[purchase.id] = purchase
|
||||
return purchase
|
||||
async def update_placement(self, placement: domain.Placement) -> domain.Placement:
|
||||
self.placements[placement.id] = placement
|
||||
return placement
|
||||
|
||||
async def get_user_purchases(
|
||||
async def get_user_placements(
|
||||
self,
|
||||
user_id: uuid.UUID,
|
||||
*,
|
||||
@@ -240,8 +242,8 @@ class MockDatabase:
|
||||
external_channel_id: uuid.UUID | None = None,
|
||||
creative_id: uuid.UUID | None = None,
|
||||
include_archived: bool = False,
|
||||
) -> list[domain.Purchase]:
|
||||
result = [p for p in self.purchases.values() if p.user_id == user_id]
|
||||
) -> list[domain.Placement]:
|
||||
result = [p for p in self.placements.values() if p.user_id == user_id]
|
||||
if target_channel_id:
|
||||
result = [p for p in result if p.target_channel_id == target_channel_id]
|
||||
if external_channel_id:
|
||||
@@ -249,24 +251,47 @@ class MockDatabase:
|
||||
if creative_id:
|
||||
result = [p for p in result if p.creative_id == creative_id]
|
||||
if not include_archived:
|
||||
result = [p for p in result if p.status == domain.PurchaseStatus.ACTIVE]
|
||||
result = [p for p in result if p.status == domain.PlacementStatus.ACTIVE]
|
||||
return sorted(result, key=lambda p: p.placement_date, reverse=True)
|
||||
|
||||
async def delete_purchase(self, purchase_id: uuid.UUID) -> None:
|
||||
self.purchases.pop(purchase_id, None)
|
||||
async def delete_placement(self, placement_id: uuid.UUID) -> None:
|
||||
self.placements.pop(placement_id, None)
|
||||
|
||||
async def check_creative_in_use(self, creative_id: uuid.UUID) -> bool:
|
||||
for purchase in self.purchases.values():
|
||||
if purchase.creative_id == creative_id and purchase.status == domain.PurchaseStatus.ACTIVE:
|
||||
for placement in self.placements.values():
|
||||
if placement.creative_id == creative_id and placement.status == domain.PlacementStatus.ACTIVE:
|
||||
return True
|
||||
return False
|
||||
|
||||
async def get_purchase_by_invite_link(self, invite_link: str) -> domain.Purchase | None:
|
||||
for purchase in self.purchases.values():
|
||||
if purchase.invite_link == invite_link:
|
||||
return purchase
|
||||
async def get_placement_by_invite_link(self, invite_link: str) -> domain.Placement | None:
|
||||
for placement in self.placements.values():
|
||||
if placement.invite_link == invite_link:
|
||||
return placement
|
||||
return None
|
||||
|
||||
async def get_subscriber(self, telegram_id: int) -> domain.Subscriber | None:
|
||||
return self.subscribers_by_telegram_id.get(telegram_id)
|
||||
|
||||
async def create_subscriber(self, subscriber: domain.Subscriber) -> domain.Subscriber:
|
||||
if not subscriber.id:
|
||||
subscriber.id = uuid.uuid4()
|
||||
if not hasattr(subscriber, 'created_at') or subscriber.created_at is None:
|
||||
subscriber.created_at = datetime.datetime.now(datetime.UTC)
|
||||
if not hasattr(subscriber, 'updated_at') or subscriber.updated_at is None:
|
||||
subscriber.updated_at = datetime.datetime.now(datetime.UTC)
|
||||
self.subscribers[subscriber.id] = subscriber
|
||||
self.subscribers_by_telegram_id[subscriber.telegram_id] = subscriber
|
||||
return subscriber
|
||||
|
||||
async def upsert_subscriber(self, subscriber: domain.Subscriber) -> domain.Subscriber:
|
||||
existing = await self.get_subscriber(subscriber.telegram_id)
|
||||
if existing:
|
||||
existing.username = subscriber.username
|
||||
existing.first_name = subscriber.first_name
|
||||
existing.last_name = subscriber.last_name
|
||||
return existing
|
||||
return await self.create_subscriber(subscriber)
|
||||
|
||||
async def create_subscription(self, subscription: domain.Subscription) -> domain.Subscription:
|
||||
if not subscription.id:
|
||||
subscription.id = uuid.uuid4()
|
||||
@@ -274,47 +299,52 @@ class MockDatabase:
|
||||
subscription.created_at = datetime.datetime.now(datetime.UTC)
|
||||
if not hasattr(subscription, 'updated_at') or subscription.updated_at is None:
|
||||
subscription.updated_at = datetime.datetime.now(datetime.UTC)
|
||||
# Загружаем связанный объект
|
||||
purchase = self.purchases.get(subscription.purchase_id)
|
||||
if purchase:
|
||||
subscription.purchase = purchase
|
||||
# Загружаем связанные объекты
|
||||
placement = self.placements.get(subscription.placement_id)
|
||||
if placement:
|
||||
subscription.placement = placement
|
||||
subscriber = self.subscribers.get(subscription.subscriber_id)
|
||||
if subscriber:
|
||||
subscription.subscriber = subscriber
|
||||
self.subscriptions[subscription.id] = subscription
|
||||
return subscription
|
||||
|
||||
async def get_subscription_by_user_and_purchase(
|
||||
self, user_telegram_id: int, purchase_id: uuid.UUID
|
||||
async def get_subscription_by_subscriber_and_placement(
|
||||
self, subscriber_id: uuid.UUID, placement_id: uuid.UUID
|
||||
) -> domain.Subscription | None:
|
||||
for subscription in self.subscriptions.values():
|
||||
if subscription.user_telegram_id == user_telegram_id and subscription.purchase_id == purchase_id:
|
||||
if subscription.subscriber_id == subscriber_id and subscription.placement_id == placement_id:
|
||||
return subscription
|
||||
return None
|
||||
|
||||
async def create_views_snapshot(self, snapshot: domain.ViewsSnapshot) -> domain.ViewsSnapshot:
|
||||
if not snapshot.id:
|
||||
snapshot.id = uuid.uuid4()
|
||||
if not hasattr(snapshot, 'created_at') or snapshot.created_at is None:
|
||||
snapshot.created_at = datetime.datetime.now(datetime.UTC)
|
||||
if not hasattr(snapshot, 'updated_at') or snapshot.updated_at is None:
|
||||
snapshot.updated_at = datetime.datetime.now(datetime.UTC)
|
||||
purchase = self.purchases.get(snapshot.purchase_id)
|
||||
if purchase:
|
||||
snapshot.purchase = purchase
|
||||
self.views_snapshots[snapshot.id] = snapshot
|
||||
return snapshot
|
||||
async def create_placement_views_history(
|
||||
self, history: domain.PlacementViewsHistory
|
||||
) -> domain.PlacementViewsHistory:
|
||||
if not history.id:
|
||||
history.id = uuid.uuid4()
|
||||
if not hasattr(history, 'created_at') or history.created_at is None:
|
||||
history.created_at = datetime.datetime.now(datetime.UTC)
|
||||
if not hasattr(history, 'updated_at') or history.updated_at is None:
|
||||
history.updated_at = datetime.datetime.now(datetime.UTC)
|
||||
placement = self.placements.get(history.placement_id)
|
||||
if placement:
|
||||
history.placement = placement
|
||||
self.placement_views_histories[history.id] = history
|
||||
return history
|
||||
|
||||
async def get_views_history(
|
||||
self,
|
||||
purchase_id: uuid.UUID,
|
||||
placement_id: uuid.UUID,
|
||||
*,
|
||||
from_date: datetime.datetime | None = None,
|
||||
to_date: datetime.datetime | None = None,
|
||||
) -> list[domain.ViewsSnapshot]:
|
||||
result = [s for s in self.views_snapshots.values() if s.purchase_id == purchase_id]
|
||||
) -> list[domain.PlacementViewsHistory]:
|
||||
result = [h for h in self.placement_views_histories.values() if h.placement_id == placement_id]
|
||||
if from_date:
|
||||
result = [s for s in result if s.fetched_at >= from_date]
|
||||
result = [h for h in result if h.fetched_at >= from_date]
|
||||
if to_date:
|
||||
result = [s for s in result if s.fetched_at <= to_date]
|
||||
return sorted(result, key=lambda s: s.fetched_at)
|
||||
result = [h for h in result if h.fetched_at <= to_date]
|
||||
return sorted(result, key=lambda h: h.fetched_at)
|
||||
|
||||
|
||||
class MockTelegramWriter:
|
||||
|
||||
Reference in New Issue
Block a user