правки имен

This commit is contained in:
Artem Tsyrulnikov
2026-01-18 13:18:00 +03:00
parent 4705e88663
commit c304ba4ec7
10 changed files with 108 additions and 146 deletions

View File

@@ -97,17 +97,17 @@ from .error import (
WorkspaceNotFound, WorkspaceNotFound,
) )
from .login_token import LoginToken from .login_token import LoginToken
from .placement import PostViewsAvailability, Publication, PublicationStatus from .placement import (
from .post import Post
from .post_views_history import PostViewsHistory
from .project import Project, ProjectStatus
from .purchase import (
CostType, CostType,
InviteLinkType, InviteLinkType,
Placement, Placement,
PlacementStatus, PlacementStatus,
PlacementType, PlacementType,
) )
from .post import Post
from .post_views_history import PostViewsHistory
from .project import Project, ProjectStatus
from .publication import PostViewsAvailability, Publication, PublicationStatus
from .subscription import Subscription, SubscriptionStatus from .subscription import Subscription, SubscriptionStatus
from .telegram_user import TelegramUser from .telegram_user import TelegramUser
from .user import User from .user import User

View File

@@ -1,60 +1,71 @@
import enum import enum
import uuid
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from uuid import UUID
from tortoise import fields from tortoise import fields
from .base import TimestampedModel from .base import TimestampedModel
if TYPE_CHECKING: if TYPE_CHECKING:
from .channel import Channel
from .creative import Creative from .creative import Creative
from .post import Post
from .project import Project from .project import Project
from .purchase import Placement
__all__ = ['Publication', 'PublicationStatus', 'PostViewsAvailability'] __all__ = ['Placement', 'PlacementStatus', 'PlacementType', 'InviteLinkType', 'CostType']
class PublicationStatus(str, enum.Enum): class CostType(enum.StrEnum):
ACTIVE = 'active' # Пост найден и отслеживается FIXED = 'fixed'
ARCHIVED = 'archived' # Вручную архивировано CPM = 'cpm'
class PostViewsAvailability(str, enum.Enum): class PlacementStatus(enum.StrEnum):
UNKNOWN = 'unknown' # Ещё не проверялось PLANNED = 'planned'
AVAILABLE = 'available' # Просмотры доступны APPROVED = 'approved'
UNAVAILABLE = 'unavailable' # Нет доступа / битая ссылка / приватный канал REJECTED = 'rejected'
MANUAL = 'manual' # Просмотры вводятся вручную IN_PROGRESS = 'in_progress'
COMPLETED = 'completed'
class Publication(TimestampedModel): class PlacementType(enum.StrEnum):
"""Публикация, мониторимая системой (бывший Placement)""" SELF_PROMO = 'self_promo'
STANDARD = 'standard'
wanted_placement_date = fields.DatetimeField(db_column='placement_date')
cost = fields.FloatField(null=True) class InviteLinkType(enum.StrEnum):
PUBLIC = 'public' # открытая ссылка
APPROVAL = 'approval' # с одобрением ботом
class Placement(TimestampedModel):
status = fields.CharEnumField(PlacementStatus, default=PlacementStatus.PLANNED)
placement_at = fields.DatetimeField(null=True)
payment_at = fields.DatetimeField(null=True)
cost_type = fields.CharEnumField(CostType, null=True, max_length=8)
cost_value = fields.FloatField(null=True)
cost_before_bargain = fields.FloatField(null=True)
placement_type = fields.CharEnumField(PlacementType, null=True, max_length=16)
format = fields.TextField(null=True)
comment = fields.TextField(null=True) comment = fields.TextField(null=True)
status = fields.CharEnumField(PublicationStatus, default=PublicationStatus.ACTIVE) invite_link = fields.CharField(max_length=512)
invite_link_type = fields.CharEnumField(InviteLinkType)
project: fields.ForeignKeyRelation['Project'] = fields.ForeignKeyField( project: fields.ForeignKeyRelation['Project'] = fields.ForeignKeyField(
'models.Project', related_name='publications', on_delete=fields.CASCADE, index=True 'models.Project', related_name='placements', on_delete=fields.CASCADE, index=True
) )
creative: fields.ForeignKeyRelation['Creative'] = fields.ForeignKeyField( creative: fields.ForeignKeyRelation['Creative'] = fields.ForeignKeyField(
'models.Creative', related_name='publications', on_delete=fields.CASCADE, index=True 'models.Creative', related_name='placements', on_delete=fields.CASCADE, index=True
) )
placement: fields.ForeignKeyRelation['Placement'] = fields.ForeignKeyField( channel: fields.ForeignKeyRelation['Channel'] = fields.ForeignKeyField(
'models.Placement', related_name='publications', on_delete=fields.CASCADE, index=True 'models.Channel', related_name='placements', on_delete=fields.CASCADE, index=True
)
post: fields.ForeignKeyRelation['Post'] | None = fields.ForeignKeyField(
'models.Post', related_name='publications', on_delete=fields.SET_NULL, null=True, index=True
) )
if TYPE_CHECKING: if TYPE_CHECKING:
project_id: UUID project_id: uuid.UUID
creative_id: UUID creative_id: uuid.UUID
post_id: UUID | None channel_id: uuid.UUID
placement_id: UUID
class Meta: class Meta:
table = 'publication' table = 'placement'
indexes = (('project', 'status'),)

View File

@@ -5,7 +5,7 @@ from uuid import UUID
from tortoise import fields from tortoise import fields
from .base import TimestampedModel from .base import TimestampedModel
from .purchase import InviteLinkType from .placement import InviteLinkType
if TYPE_CHECKING: if TYPE_CHECKING:
from .channel import Channel from .channel import Channel

58
src/domain/publication.py Normal file
View File

@@ -0,0 +1,58 @@
import enum
from typing import TYPE_CHECKING
from uuid import UUID
from tortoise import fields
from .base import TimestampedModel
if TYPE_CHECKING:
from .creative import Creative
from .placement import Placement
from .post import Post
from .project import Project
__all__ = ['Publication', 'PublicationStatus', 'PostViewsAvailability']
class PublicationStatus(str, enum.Enum):
ACTIVE = 'active' # Пост найден и отслеживается
ARCHIVED = 'archived' # Вручную архивировано
class PostViewsAvailability(str, enum.Enum):
UNKNOWN = 'unknown' # Ещё не проверялось
AVAILABLE = 'available' # Просмотры доступны
UNAVAILABLE = 'unavailable' # Нет доступа / битая ссылка / приватный канал
MANUAL = 'manual' # Просмотры вводятся вручную
class Publication(TimestampedModel):
wanted_placement_date = fields.DatetimeField(db_column='placement_date')
cost = fields.FloatField(null=True)
comment = fields.TextField(null=True)
status = fields.CharEnumField(PublicationStatus, default=PublicationStatus.ACTIVE)
project: fields.ForeignKeyRelation['Project'] = fields.ForeignKeyField(
'models.Project', related_name='publications', on_delete=fields.CASCADE, index=True
)
creative: fields.ForeignKeyRelation['Creative'] = fields.ForeignKeyField(
'models.Creative', related_name='publications', on_delete=fields.CASCADE, index=True
)
placement: fields.ForeignKeyRelation['Placement'] = fields.ForeignKeyField(
'models.Placement', related_name='publications', on_delete=fields.CASCADE, index=True
)
post: fields.ForeignKeyRelation['Post'] | None = fields.ForeignKeyField(
'models.Post', related_name='publications', on_delete=fields.SET_NULL, null=True, index=True
)
if TYPE_CHECKING:
project_id: UUID
creative_id: UUID
post_id: UUID | None
placement_id: UUID
class Meta:
table = 'publication'

View File

@@ -1,97 +0,0 @@
import enum
import uuid
from typing import TYPE_CHECKING
from tortoise import fields
from .base import TimestampedModel
if TYPE_CHECKING:
from .channel import Channel
from .creative import Creative
from .project import Project
__all__ = ['Placement', 'PlacementStatus', 'PlacementType', 'InviteLinkType', 'CostType']
class CostType(enum.StrEnum):
FIXED = 'fixed'
CPM = 'cpm'
class PlacementStatus(enum.StrEnum):
PLANNED = 'planned'
APPROVED = 'approved'
REJECTED = 'rejected'
IN_PROGRESS = 'in_progress'
COMPLETED = 'completed'
class PlacementType(enum.StrEnum):
SELF_PROMO = 'self_promo'
STANDARD = 'standard'
class InviteLinkType(enum.StrEnum):
PUBLIC = 'public' # открытая ссылка
APPROVAL = 'approval' # с одобрением ботом
class Placement(TimestampedModel):
"""Размещение, управляемое пользователем (бывший PurchaseChannel + Purchase)"""
status = fields.CharEnumField(PlacementStatus, default=PlacementStatus.PLANNED)
placement_at = fields.DatetimeField(null=True)
payment_at = fields.DatetimeField(null=True)
cost_type = fields.CharEnumField(CostType, null=True, max_length=8)
cost_value = fields.FloatField(null=True)
cost_before_bargain = fields.FloatField(null=True)
placement_type = fields.CharEnumField(PlacementType, null=True, max_length=16)
format = fields.TextField(null=True)
comment = fields.TextField(null=True)
invite_link = fields.CharField(max_length=512)
invite_link_type = fields.CharEnumField(InviteLinkType)
project: fields.ForeignKeyRelation['Project'] = fields.ForeignKeyField(
'models.Project', related_name='placements', on_delete=fields.CASCADE, index=True
)
creative: fields.ForeignKeyRelation['Creative'] = fields.ForeignKeyField(
'models.Creative', related_name='placements', on_delete=fields.CASCADE, index=True
)
channel: fields.ForeignKeyRelation['Channel'] = fields.ForeignKeyField(
'models.Channel', related_name='placements', on_delete=fields.CASCADE, index=True
)
if TYPE_CHECKING:
project_id: uuid.UUID
creative_id: uuid.UUID
channel_id: uuid.UUID
class Meta:
table = 'placement'
indexes = (('project', 'status'),)
# DEPRECATED: старые модели, будут удалены после миграции
# class PurchaseStatus(enum.StrEnum):
# ACTIVE = 'active'
# ARCHIVED = 'archived'
#
# class PurchaseChannelStatus(enum.StrEnum):
# PLANNED = 'planned'
# APPROVED = 'approved'
# REJECTED = 'rejected'
# IN_PROGRESS = 'in_progress'
# COMPLETED = 'completed'
#
# class PurchaseType(enum.StrEnum):
# SELF_PROMO = 'self_promo'
# STANDARD = 'standard'
#
# class Purchase(TimestampedModel):
# ...
#
# class PurchaseChannel(TimestampedModel):
# ...

View File

@@ -7,7 +7,7 @@ from tortoise import fields
from .base import TimestampedModel from .base import TimestampedModel
if TYPE_CHECKING: if TYPE_CHECKING:
from .placement import Publication from .publication import Publication
from .telegram_user import TelegramUser from .telegram_user import TelegramUser

View File

@@ -11,8 +11,8 @@ from .base import TimestampedModel
if TYPE_CHECKING: if TYPE_CHECKING:
from .channel import Channel from .channel import Channel
from .creative import Creative from .creative import Creative
from .placement import Placement
from .project import Project from .project import Project
from .purchase import Placement
from .user import User from .user import User

View File

@@ -3,7 +3,7 @@ import uuid
import pydantic import pydantic
from src.domain.purchase import CostType, InviteLinkType, PlacementStatus, PlacementType from src.domain.placement import CostType, InviteLinkType, PlacementStatus, PlacementType
from .channel import ChannelOutput from .channel import ChannelOutput

View File

@@ -1,5 +0,0 @@
from .fetch_publication_post_cycle import fetch_publication_post_cycle
from .get_publication import get_publication
from .get_publications import get_publications
__all__ = ['fetch_publication_post_cycle', 'get_publication', 'get_publications']

View File

@@ -1,5 +0,0 @@
from .create_placements import create_placements
from .get_placement import get_placement_user
from .get_placements import get_placements
__all__ = ['create_placements', 'get_placement_user', 'get_placements']