"""Сервис переноса трудочасов из Clockify в Redmine.""" import logging from colorama import Fore from utils import format_date, format_hours 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"Всего часов: {format_hours(total_hours)}") for activity in trackable_activities: logger.info( f"{activity.date_start.date()} | #{activity.task_id} | " f"{format_hours(activity.time_spent)} | {activity.description}" )