добавил объединение повторных активностей Clockify
This commit is contained in:
@@ -4,11 +4,48 @@ import logging
|
||||
|
||||
from colorama import Fore
|
||||
|
||||
from classes import Activity, AggregatedActivity
|
||||
from utils import format_date, format_hours
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def aggregate_activities(activities: list[Activity]) -> list[AggregatedActivity]:
|
||||
"""Объединяет одинаковые активности и суммирует их трудозатраты."""
|
||||
grouped_activities = {}
|
||||
for activity in activities:
|
||||
key = (
|
||||
activity.author_id,
|
||||
activity.task_id,
|
||||
activity.tag_id,
|
||||
activity.project_id,
|
||||
activity.vetro_project_id,
|
||||
activity.date_start.date(),
|
||||
)
|
||||
grouped_activities.setdefault(key, []).append(activity)
|
||||
|
||||
result = []
|
||||
for grouped in grouped_activities.values():
|
||||
descriptions = list(
|
||||
dict.fromkeys(
|
||||
description.rstrip(".")
|
||||
for activity in grouped
|
||||
if (description := activity.description.strip())
|
||||
)
|
||||
)
|
||||
result.append(
|
||||
AggregatedActivity(
|
||||
**{
|
||||
**grouped[0].__dict__,
|
||||
"description": ". ".join(descriptions),
|
||||
"time_spent": sum(activity.time_spent for activity in grouped),
|
||||
},
|
||||
source_activities=tuple(grouped),
|
||||
)
|
||||
)
|
||||
return result
|
||||
|
||||
|
||||
class TrackingService:
|
||||
"""Координирует загрузку, сохранение и перенос активностей в Redmine."""
|
||||
|
||||
@@ -35,13 +72,20 @@ class TrackingService:
|
||||
if not activities:
|
||||
logger.info(Fore.YELLOW + "Нет задач для занесения трудочасов" + Fore.RESET)
|
||||
return []
|
||||
activities_to_track = aggregate_activities(
|
||||
[
|
||||
activity
|
||||
for activity in activities
|
||||
if not activity.is_tracked and activity.date_end
|
||||
]
|
||||
)
|
||||
if self.is_dry_run:
|
||||
self._log_preview(activities)
|
||||
self._log_preview(activities, activities_to_track)
|
||||
return activities
|
||||
|
||||
self.db.insert_activities(activities)
|
||||
self.red.track_activities(
|
||||
activities,
|
||||
activities_to_track,
|
||||
on_success=None if self.is_debug else self._save_tracked_activity,
|
||||
)
|
||||
return activities
|
||||
@@ -66,22 +110,20 @@ class TrackingService:
|
||||
|
||||
def _save_tracked_activity(self, activity):
|
||||
"""Сохраняет активность как успешно перенесенную в Redmine."""
|
||||
self.db.insert_activities([activity])
|
||||
self.db.insert_time_entries([activity])
|
||||
source_activities = list(activity.source_activities or (activity,))
|
||||
for source_activity in source_activities:
|
||||
source_activity.is_tracked = True
|
||||
self.db.insert_activities(source_activities)
|
||||
self.db.insert_time_entries(source_activities)
|
||||
|
||||
def _log_preview(self, activities):
|
||||
def _log_preview(self, activities, activities_to_track):
|
||||
"""Выводит план переноса активностей без сохранения и отправки."""
|
||||
total_hours = sum(activity.time_spent for activity in activities if activity.date_end)
|
||||
trackable_activities = [
|
||||
activity
|
||||
for activity in activities
|
||||
if not activity.is_tracked and activity.date_end
|
||||
]
|
||||
total_hours = sum(activity.time_spent for activity in activities_to_track)
|
||||
logger.info(f"{Fore.YELLOW}Предпросмотр переноса трудочасов{Fore.RESET}")
|
||||
logger.info(f"Найдено активностей: {len(activities)}")
|
||||
logger.info(f"Готово к переносу: {len(trackable_activities)}")
|
||||
logger.info(f"Готово к переносу: {len(activities_to_track)}")
|
||||
logger.info(f"Всего часов: {format_hours(total_hours)}")
|
||||
for activity in trackable_activities:
|
||||
for activity in activities_to_track:
|
||||
logger.info(
|
||||
f"{activity.date_start.date()} | #{activity.task_id} | "
|
||||
f"{format_hours(activity.time_spent)} | {activity.description}"
|
||||
|
||||
Reference in New Issue
Block a user