89 lines
3.5 KiB
Python
89 lines
3.5 KiB
Python
"""Сервис переноса трудочасов из Clockify в Redmine."""
|
||
|
||
import logging
|
||
|
||
from colorama import Fore
|
||
|
||
from utils import format_date
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
|
||
class TrackingService:
|
||
"""Координирует загрузку, сохранение и перенос активностей в Redmine."""
|
||
|
||
def __init__(self, clock, red, db, is_debug: bool, is_dry_run: bool = False):
|
||
self.clock = clock
|
||
self.red = red
|
||
self.db = db
|
||
self.is_debug = is_debug
|
||
self.is_dry_run = is_dry_run
|
||
|
||
def track_period(self, start, end, page_size: int | None):
|
||
"""Переносит активности за период и возвращает список найденных активностей."""
|
||
self._save_current_user()
|
||
activities = sorted(
|
||
self.clock.get_activities(
|
||
**{
|
||
"start": format_date(start),
|
||
"end": format_date(end),
|
||
"page-size": page_size,
|
||
},
|
||
),
|
||
key=lambda x: x.date_start,
|
||
)
|
||
if not activities:
|
||
logger.info(Fore.YELLOW + "Нет задач для занесения трудочасов" + Fore.RESET)
|
||
return []
|
||
if self.is_dry_run:
|
||
self._log_preview(activities)
|
||
return activities
|
||
|
||
self.db.insert_activities(activities)
|
||
self.red.track_activities(
|
||
activities,
|
||
on_success=None if self.is_debug else self._save_tracked_activity,
|
||
)
|
||
return activities
|
||
|
||
def _save_current_user(self):
|
||
"""Сохраняет связку текущих пользователей Clockify и Redmine."""
|
||
user = self.clock.get_user()
|
||
clock_user = {
|
||
"clockify_user_id": user["id"],
|
||
"clockify_email": user["email"],
|
||
"clockify_username": user["username"],
|
||
}
|
||
user = self.red.get_user()
|
||
red_user = {
|
||
"redmine_user_id": user["id"],
|
||
"redmine_email": user["email"],
|
||
"first_name": user["first_name"],
|
||
"last_name": user["last_name"],
|
||
"redmine_username": user["username"],
|
||
}
|
||
self.db.insert_user(**clock_user, **red_user)
|
||
|
||
def _save_tracked_activity(self, activity):
|
||
"""Сохраняет активность как успешно перенесенную в Redmine."""
|
||
self.db.insert_activities([activity])
|
||
self.db.insert_time_entries([activity])
|
||
|
||
def _log_preview(self, activities):
|
||
"""Выводит план переноса активностей без сохранения и отправки."""
|
||
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
|
||
]
|
||
logger.info(f"{Fore.YELLOW}Предпросмотр переноса трудочасов{Fore.RESET}")
|
||
logger.info(f"Найдено активностей: {len(activities)}")
|
||
logger.info(f"Готово к переносу: {len(trackable_activities)}")
|
||
logger.info(f"Всего часов: {total_hours}")
|
||
for activity in trackable_activities:
|
||
logger.info(
|
||
f"{activity.date_start.date()} | #{activity.task_id} | "
|
||
f"{activity.time_spent} ч | {activity.description}"
|
||
)
|