This commit is contained in:
Artem Tsyrulnikov
2026-01-18 13:35:46 +03:00
parent c304ba4ec7
commit 68e7dc4158
44 changed files with 383 additions and 387 deletions

View File

@@ -47,7 +47,7 @@ def _format_period_label(dt: datetime.datetime, grouping: dto.DateGrouping) -> s
if week_start.month == week_end.month:
return f'{week_start.day}-{week_end.day} {month_names[week_start.month - 1]}'
else:
return f'{week_start.day} {month_names[week_start.month - 1]}-{week_end.day} {month_names[week_end.month - 1]}'
return f'{week_start.day} {month_names[week_start.month - 1]}-{week_end.day} {month_names[week_end.month - 1]}' # noqa: E501
case dto.DateGrouping.MONTH:
# "дек 2024"
month_names = ['янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек']
@@ -60,20 +60,20 @@ def _format_period_label(dt: datetime.datetime, grouping: dto.DateGrouping) -> s
raise ValueError('Invalid date grouping')
def _get_grouping_date(publication: domain.Publication, date_grouping: dto.DateGroupingType) -> datetime.datetime:
def _get_grouping_date(placement_post: domain.PlacementPost, date_grouping: dto.DateGroupingType) -> datetime.datetime:
match date_grouping:
case dto.DateGroupingType.PLACEMENT_DATE:
return publication.wanted_placement_date
return placement_post.wanted_placement_date
case dto.DateGroupingType.PURCHASE_DATE:
if publication.placement:
return publication.placement.created_at
return publication.wanted_placement_date # Fallback
if placement_post.placement:
return placement_post.placement.created_at
return placement_post.wanted_placement_date # Fallback
case dto.DateGroupingType.LINK_DATE:
if publication.placement:
return publication.placement.created_at
return publication.wanted_placement_date # Fallback
if placement_post.placement:
return placement_post.placement.created_at
return placement_post.wanted_placement_date # Fallback
case _:
return publication.wanted_placement_date
return placement_post.wanted_placement_date
@dataclass
@@ -183,7 +183,7 @@ async def get_projects_analytics(
else:
allowed_project_ids = set(input.project_ids)
placements = await self.database.get_workspace_publications(
placements = await self.database.get_workspace_placement_posts(
input.workspace_id,
project_id=None,
include_archived=False,
@@ -194,28 +194,28 @@ async def get_projects_analytics(
# Фильтрация по датам на основе date_grouping
filtered_placements = []
for publication in placements:
grouping_date = _get_grouping_date(publication, input.date_grouping)
for placement_post in placements:
grouping_date = _get_grouping_date(placement_post, input.date_grouping)
if input.date_from and grouping_date < input.date_from:
continue
if input.date_to and grouping_date > input.date_to:
continue
filtered_placements.append(publication)
filtered_placements.append(placement_post)
# Batch fetch views data
post_ids = [p.post.id for p in filtered_placements if p.post]
views_map = await self.database.get_latest_views_data_batch(post_ids) if post_ids else {}
# Batch fetch subscriptions counts
publication_ids = [p.id for p in filtered_placements]
subscriptions_counts = await self.database.count_subscriptions_by_publication_batch(publication_ids)
placement_post_ids = [p.id for p in filtered_placements]
subscriptions_counts = await self.database.count_subscriptions_by_placement_post_batch(placement_post_ids)
# Группировка по периодам
period_data: dict[str, PeriodMetrics] = defaultdict(PeriodMetrics)
total_metrics = PeriodMetrics()
for publication in filtered_placements:
grouping_date = _get_grouping_date(publication, input.date_grouping)
for placement_post in filtered_placements:
grouping_date = _get_grouping_date(placement_post, input.date_grouping)
period = _format_period(grouping_date, input.grouping)
pd = period_data[period]
@@ -223,25 +223,25 @@ async def get_projects_analytics(
pd.purchases_count += 1
total_metrics.purchases_count += 1
cost = publication.cost or 0.0
cost = placement_post.cost or 0.0
pd.total_cost += cost
total_metrics.total_cost += cost
subs_count = subscriptions_counts.get(publication.id, 0)
subs_count = subscriptions_counts.get(placement_post.id, 0)
pd.total_subscriptions += subs_count
pd.clicks_count += subs_count
total_metrics.total_subscriptions += subs_count
total_metrics.clicks_count += subs_count
if publication.post and publication.post.id in views_map:
views_count = views_map[publication.post.id][0]
if placement_post.post and placement_post.post.id in views_map:
views_count = views_map[placement_post.post.id][0]
pd.total_views += views_count
pd.reach_volume += views_count
total_metrics.total_views += views_count
total_metrics.reach_volume += views_count
# Расчет скидок
placement = publication.placement
placement = placement_post.placement
if placement and placement.cost_before_bargain and placement.cost_before_bargain > cost:
discount = placement.cost_before_bargain - cost
discount_percent = (