feat: переименование доменной области

This commit is contained in:
Artem Tsyrulnikov
2025-12-14 12:21:35 +03:00
parent 3cb3da4dbe
commit f3e09a08eb
75 changed files with 1624 additions and 1417 deletions

View File

@@ -19,6 +19,9 @@ class Postgres(DatabaseBase):
async def create_user(self, user: domain.User) -> None:
await user.save()
async def update_user(self, user: domain.User) -> None:
await user.save()
async def create_workspace(self, workspace: domain.Workspace) -> None:
await workspace.save()
@@ -28,10 +31,12 @@ class Postgres(DatabaseBase):
async def delete_workspace(self, workspace_id: uuid.UUID) -> None:
await domain.Workspace.filter(id=workspace_id).delete()
async def add_user_to_workspace(
self, workspace_id: uuid.UUID, user_id: uuid.UUID, *, is_owner: bool = False
) -> None:
await domain.WorkspaceUser.create(workspace_id=workspace_id, user_id=user_id, is_owner=is_owner)
async def add_user_to_workspace(self, workspace_id: uuid.UUID, user_id: uuid.UUID) -> None:
await domain.WorkspaceUser.create(
workspace_id=workspace_id,
user_id=user_id,
status=domain.WorkspaceUserStatus.ACTIVE,
)
async def get_user_workspaces(self, user_id: uuid.UUID) -> list[domain.WorkspaceUser]:
return (
@@ -71,9 +76,6 @@ class Postgres(DatabaseBase):
async def create_login_token(self, login_token: domain.LoginToken) -> None:
await login_token.save()
async def create_external_channel(self, channel: domain.ExternalChannel) -> None:
await channel.save()
async def create_creative(self, creative: domain.Creative) -> None:
await creative.save()
@@ -94,120 +96,165 @@ class Postgres(DatabaseBase):
if updated == 0:
raise domain.LoginTokenAlreadyUsed() # либо нет токена, либо он уже использован
async def get_target_channel(
self, workspace_id: uuid.UUID, channel_id: uuid.UUID | None = None, telegram_id: int | None = None
) -> domain.TargetChannel | None:
if not channel_id and not telegram_id:
raise ValueError('Either channel_id or telegram_id must be provided')
q = domain.TargetChannel.filter(workspace_id=workspace_id)
if channel_id:
q = q.filter(id=channel_id)
if telegram_id:
q = q.filter(telegram_id=telegram_id)
return await q.first()
async def get_target_channel_for_user_by_telegram(
self, user_id: uuid.UUID, telegram_id: int
) -> domain.TargetChannel | None:
return (
await domain.TargetChannel.filter(telegram_id=telegram_id, workspace__workspace_users__user_id=user_id)
.prefetch_related('workspace')
.first()
)
async def upsert_target_channel(self, channel: domain.TargetChannel) -> None:
existing = await self.get_target_channel(workspace_id=channel.workspace_id, telegram_id=channel.telegram_id)
if not existing:
await channel.save()
return
existing.title = channel.title
existing.username = channel.username
existing.workspace_id = channel.workspace_id
existing.status = channel.status
existing.deleted_at = None
existing.updated_at = timezone.now()
await existing.save()
async def get_workspace_target_channels(self, workspace_id: uuid.UUID) -> list[domain.TargetChannel]:
return await domain.TargetChannel.filter(
workspace_id=workspace_id, status=domain.TargetChannelStatus.ACTIVE
).all()
async def update_target_channel(self, channel: domain.TargetChannel) -> None:
await channel.save()
async def get_external_channel(
self, workspace_id: uuid.UUID, channel_id: uuid.UUID | None = None, telegram_id: int | None = None
) -> domain.ExternalChannel | None:
query = domain.ExternalChannel.filter(workspace_id=workspace_id)
async def get_channel(
self,
workspace_id: uuid.UUID,
channel_id: uuid.UUID | None = None,
telegram_id: int | None = None,
username: str | None = None,
) -> domain.Channel | None:
query = domain.Channel.filter(workspace_id=workspace_id)
if channel_id:
query = query.filter(id=channel_id)
if telegram_id:
query = query.filter(telegram_id=telegram_id)
if username:
query = query.filter(username=username)
return await query.first()
async def get_external_channels_for_target(self, target_channel_id: uuid.UUID) -> list[domain.ExternalChannel]:
return await domain.ExternalChannel.filter(target_channels__id=target_channel_id).all()
async def get_workspace_channels(self, workspace_id: uuid.UUID) -> list[domain.Channel]:
return await domain.Channel.filter(workspace_id=workspace_id).all()
async def get_workspace_external_channels(self, workspace_id: uuid.UUID) -> list[domain.ExternalChannel]:
return await domain.ExternalChannel.filter(workspace_id=workspace_id).all()
async def add_external_channel_to_targets(
self, external_channel: domain.ExternalChannel, target_channel_ids: list[uuid.UUID]
) -> None:
target_channels = await domain.TargetChannel.filter(id__in=target_channel_ids).all()
await external_channel.target_channels.add(*target_channels)
async def remove_external_channel_from_target(
self, external_channel_id: uuid.UUID, target_channel_id: uuid.UUID
) -> None:
external_channel = await domain.ExternalChannel.get_or_none(id=external_channel_id)
if not external_channel:
raise ValueError(f'ExternalChannel {external_channel_id} not found')
target_channel = await domain.TargetChannel.get_or_none(id=target_channel_id)
if target_channel:
await external_channel.target_channels.remove(target_channel)
async def delete_external_channel(self, channel_id: uuid.UUID) -> None:
await domain.ExternalChannel.filter(id=channel_id).delete()
async def update_external_channel(self, channel: domain.ExternalChannel) -> None:
async def create_channel(self, channel: domain.Channel) -> None:
await channel.save()
async def update_channel(self, channel: domain.Channel) -> None:
await channel.save()
async def delete_channel(self, channel_id: uuid.UUID) -> None:
await domain.Channel.filter(id=channel_id).delete()
async def search_channels(self, username_query: str | None = None) -> list[domain.Channel]:
query = domain.Channel.all()
if username_query:
# Частичный поиск (case-insensitive)
query = query.filter(username__icontains=username_query)
return await query.all()
async def get_project(
self, workspace_id: uuid.UUID, project_id: uuid.UUID | None = None, channel_id: uuid.UUID | None = None
) -> domain.Project | None:
query = domain.Project.filter(workspace_id=workspace_id).prefetch_related('channel')
if project_id:
query = query.filter(id=project_id)
if channel_id:
query = query.filter(channel_id=channel_id)
return await query.first()
async def get_project_for_user_by_telegram(
self, user_id: uuid.UUID, channel_telegram_id: int
) -> domain.Project | None:
return (
await domain.Project.filter(
channel__telegram_id=channel_telegram_id, workspace__workspace_users__user_id=user_id
)
.prefetch_related('channel')
.first()
)
async def get_project_by_channel_telegram(self, channel_telegram_id: int) -> domain.Project | None:
return await domain.Project.filter(channel__telegram_id=channel_telegram_id).prefetch_related('channel').first()
async def create_project(self, project: domain.Project) -> None:
await project.save()
async def update_project(self, project: domain.Project) -> None:
await project.save()
async def get_workspace_projects(self, workspace_id: uuid.UUID) -> list[domain.Project]:
return (
await domain.Project.filter(workspace_id=workspace_id)
.prefetch_related('channel')
.order_by('created_at')
.all()
)
async def get_active_purchase_plan(self, project_id: uuid.UUID) -> domain.PurchasePlan | None:
return await domain.PurchasePlan.get_or_none(project_id=project_id, status=domain.PurchasePlanStatus.ACTIVE)
async def get_purchase_plan(self, workspace_id: uuid.UUID, plan_id: uuid.UUID) -> domain.PurchasePlan | None:
return await domain.PurchasePlan.get_or_none(id=plan_id, workspace_id=workspace_id)
async def create_purchase_plan(self, plan: domain.PurchasePlan) -> None:
await plan.save()
async def get_purchase_plan_channels(self, plan_id: uuid.UUID) -> list[domain.PurchasePlanChannel]:
return await domain.PurchasePlanChannel.filter(purchase_plan_id=plan_id).prefetch_related('channel').all()
async def get_purchase_plan_channel(
self, plan_channel_id: uuid.UUID, plan_id: uuid.UUID
) -> domain.PurchasePlanChannel | None:
return (
await domain.PurchasePlanChannel.filter(id=plan_channel_id, purchase_plan_id=plan_id)
.prefetch_related('channel')
.first()
)
async def add_channel_to_purchase_plan(
self,
plan_id: uuid.UUID,
channel_id: uuid.UUID,
*,
status: domain.PurchasePlanChannelStatus | None = None,
planned_cost: float | None = None,
comment: str | None = None,
) -> domain.PurchasePlanChannel:
defaults: dict[str, object | None] = {}
if status is not None:
defaults['status'] = status
if planned_cost is not None:
defaults['planned_cost'] = planned_cost
if comment is not None:
defaults['comment'] = comment
plan_channel, created = await domain.PurchasePlanChannel.get_or_create(
purchase_plan_id=plan_id,
channel_id=channel_id,
defaults=defaults,
)
if not created and defaults:
for field, value in defaults.items():
setattr(plan_channel, field, value)
await plan_channel.save()
return plan_channel
async def update_purchase_plan_channel(self, plan_channel: domain.PurchasePlanChannel) -> None:
await plan_channel.save()
async def remove_channel_from_purchase_plan(self, plan_id: uuid.UUID, channel_id: uuid.UUID) -> None:
await domain.PurchasePlanChannel.filter(purchase_plan_id=plan_id, channel_id=channel_id).delete()
async def get_creative(self, workspace_id: uuid.UUID, creative_id: uuid.UUID) -> domain.Creative | None:
return await domain.Creative.get_or_none(id=creative_id, workspace_id=workspace_id).prefetch_related(
'target_channel'
'project', 'project__channel'
)
async def update_creative(self, creative: domain.Creative) -> None:
await creative.save()
async def get_workspace_creatives(
self, workspace_id: uuid.UUID, target_channel_id: uuid.UUID | None = None, include_archived: bool = False
self, workspace_id: uuid.UUID, project_id: uuid.UUID | None = None, include_archived: bool = False
) -> list[domain.Creative]:
query = domain.Creative.filter(workspace_id=workspace_id)
if target_channel_id:
query = query.filter(target_channel_id=target_channel_id)
if project_id:
query = query.filter(project_id=project_id)
if not include_archived:
query = query.filter(status=domain.CreativeStatus.ACTIVE)
return await query.prefetch_related('target_channel').order_by('-created_at').all()
return await query.prefetch_related('project', 'project__channel').order_by('-created_at').all()
async def delete_creative(self, creative_id: uuid.UUID) -> None:
await domain.Creative.filter(id=creative_id).delete()
async def get_placement(self, workspace_id: uuid.UUID, placement_id: uuid.UUID) -> domain.Placement | None:
return await domain.Placement.get_or_none(id=placement_id, workspace_id=workspace_id).prefetch_related(
'target_channel', 'external_channel', 'creative'
'project', 'project__channel', 'placement_channel', 'creative'
)
async def create_placement(self, placement: domain.Placement) -> None:
@@ -219,17 +266,17 @@ class Postgres(DatabaseBase):
async def get_workspace_placements(
self,
workspace_id: uuid.UUID,
target_channel_id: uuid.UUID | None = None,
external_channel_id: uuid.UUID | None = None,
project_id: uuid.UUID | None = None,
placement_channel_id: uuid.UUID | None = None,
creative_id: uuid.UUID | None = None,
include_archived: bool = False,
) -> list[domain.Placement]:
query = domain.Placement.filter(workspace_id=workspace_id)
if target_channel_id:
query = query.filter(target_channel_id=target_channel_id)
if external_channel_id:
query = query.filter(external_channel_id=external_channel_id)
if project_id:
query = query.filter(project_id=project_id)
if placement_channel_id:
query = query.filter(placement_channel_id=placement_channel_id)
if creative_id:
query = query.filter(creative_id=creative_id)
@@ -237,7 +284,7 @@ class Postgres(DatabaseBase):
query = query.filter(status=domain.PlacementStatus.ACTIVE)
return (
await query.prefetch_related('target_channel', 'external_channel', 'creative')
await query.prefetch_related('project', 'project__channel', 'placement_channel', 'creative')
.order_by('-placement_date')
.all()
)
@@ -247,23 +294,9 @@ class Postgres(DatabaseBase):
async def get_placement_by_invite_link(self, invite_link: str) -> domain.Placement | None:
return await domain.Placement.get_or_none(invite_link=invite_link).prefetch_related(
'target_channel', 'external_channel', 'creative'
'project', 'project__channel', 'placement_channel', 'creative'
)
async def get_subscriber(self, telegram_id: int) -> domain.Subscriber | None:
return await domain.Subscriber.get_or_none(telegram_id=telegram_id)
async def upsert_subscriber(self, subscriber: domain.Subscriber) -> None:
existing = await self.get_subscriber(subscriber.telegram_id)
if not existing:
await subscriber.save()
return
existing.username = subscriber.username
existing.first_name = subscriber.first_name
existing.last_name = subscriber.last_name
await existing.save()
async def create_subscription(self, subscription: domain.Subscription) -> None:
await subscription.save()
@@ -275,26 +308,26 @@ class Postgres(DatabaseBase):
async def update_subscription(self, subscription: domain.Subscription) -> None:
await subscription.save()
async def get_active_subscriptions_by_subscriber_and_channel(
self, subscriber_id: uuid.UUID, channel_telegram_id: int
async def get_active_subscriptions_by_subscriber_and_project(
self, subscriber_id: uuid.UUID, project_id: uuid.UUID
) -> list[domain.Subscription]:
return (
await domain.Subscription.filter(
subscriber_id=subscriber_id,
target_channel__telegram_id=channel_telegram_id,
placement__project_id=project_id,
status=domain.SubscriptionStatus.ACTIVE,
)
.prefetch_related('placement', 'subscriber')
.all()
)
async def get_active_subscription_by_subscriber_and_channel(
self, subscriber_id: uuid.UUID, channel_telegram_id: int
async def get_active_subscription_by_subscriber_and_project(
self, subscriber_id: uuid.UUID, project_id: uuid.UUID
) -> domain.Subscription | None:
return (
await domain.Subscription.filter(
subscriber_id=subscriber_id,
target_channel__telegram_id=channel_telegram_id,
placement__project_id=project_id,
status=domain.SubscriptionStatus.ACTIVE,
)
.prefetch_related('placement', 'subscriber')