diff --git a/api/clockify.py b/api/clockify.py index 802681c..499d3b5 100644 --- a/api/clockify.py +++ b/api/clockify.py @@ -6,7 +6,7 @@ import requests from tqdm import tqdm from config import ClockifyConfig, config -from classes import Activity, ActivityType, Tag +from classes import Activity, Tag, VetroProject from exceptions import InvalidToken from utils import time_to_hour @@ -79,6 +79,16 @@ class ClockifyAPI(ClockifyConfig): title=tag["name"] ) for tag in tags] + def get_vetro_projects(self) -> list[VetroProject]: + projects = requests.get(self.base_url + self.projects_url, headers={"X-API-KEY": self.token}).json() + for project in projects: + if not project.get("archived"): + vetro_projects = requests.get(self.base_url + self.tasks_url(project.get("id")), headers={"X-API-KEY": self.token}).json() + return [VetroProject( + id=vetro_project["id"], + title=vetro_project["name"] + ) for vetro_project in vetro_projects] + def mark_tracked(self, activities: list[Activity]): for activity in activities: try: diff --git a/api/redmine.py b/api/redmine.py index 4cef47e..d7076bb 100644 --- a/api/redmine.py +++ b/api/redmine.py @@ -5,7 +5,7 @@ from tqdm import tqdm from config import RedmineConfig, config from classes import Activity, ActivityType -from enums import ActivityType as ActivityTypeEnum +from enums import ActivityTypes from exceptions import InvalidToken logger = logging.getLogger(__name__) @@ -34,7 +34,7 @@ class RedmineAPI(RedmineConfig): "time_entry": { "issue_id": activity.task_id, "hours": activity.time_spent, - "activity_id": ActivityTypeEnum.DEVELOPMENT, + "activity_id": ActivityTypes.DEVELOPMENT, "comments": activity.description, "spent_on": activity.date_start.strftime(self.datetime_format) } @@ -56,7 +56,7 @@ class RedmineAPI(RedmineConfig): logger.info(f"Не все задачи были занесены в Redmine. Занесено {len(tracked)}") return tracked - def get_time_entry_activities(self): + def get_time_entry_activities(self) -> list[ActivityTypes]: resp = requests.get(self.base_url + self.time_entry_activities, headers={"X-Redmine-API-KEY": self.token}) logging.debug(resp.json()) if resp.ok: diff --git a/classes/__init__.py b/classes/__init__.py index 2562cf6..fb524b5 100644 --- a/classes/__init__.py +++ b/classes/__init__.py @@ -1 +1 @@ -from .classes import Activity, ActivityType, Tag # noqa: F401 +from .classes import Activity, ActivityType, Tag, VetroProject # noqa: F401 diff --git a/classes/classes.py b/classes/classes.py index cd21170..cbe1a7c 100644 --- a/classes/classes.py +++ b/classes/classes.py @@ -34,6 +34,14 @@ class Tag: @dataclass class ActivityType: + id: int + title: str + + def __str__(self): + return self.title + +@dataclass +class VetroProject: id: str title: str diff --git a/config/__init__.py b/config/__init__.py index d5908d0..90012cc 100644 --- a/config/__init__.py +++ b/config/__init__.py @@ -66,6 +66,12 @@ def configure_argument_parser(): action="store_true", help='Режим отладки. Не загружает трудочасы в Redmine' ) + parser.add_argument( + '-i', + '--init-db', + action="store_true", + help='Режим инициализации бд.\nПодгружает с серверов теги, виды деятельности и проекты Ветро' + ) return parser arg_parser = configure_argument_parser() diff --git a/config/clockify.py b/config/clockify.py index 176574a..63773c3 100644 --- a/config/clockify.py +++ b/config/clockify.py @@ -25,3 +25,10 @@ class ClockifyConfig: def update_time_entry(self, activity_id): return f"/workspaces/{self.workspace_id}/time-entries/{activity_id}" + + @property + def projects_url(self): + return f"/workspaces/{self.workspace_id}/projects" + + def tasks_url(self, project_id: str): + return f"{self.projects_url}/{project_id}/tasks" diff --git a/db/db.py b/db/db.py index 6291db6..76e03fa 100644 --- a/db/db.py +++ b/db/db.py @@ -1,8 +1,8 @@ import logging import sqlite3 as sq -from classes import Activity, ActivityType, Tag -from enums import ActivityType as ActivityTypeEnum +from classes import Activity, ActivityType, Tag, VetroProject +from enums import ActivityTypes logger = logging.getLogger(__name__) @@ -60,7 +60,7 @@ class Database: act.id, act.time_spent, act.task_id, - ActivityTypeEnum.DEVELOPMENT + ActivityTypes.DEVELOPMENT ) ) self.con.commit() @@ -84,11 +84,11 @@ class Database: logger.debug(e) - def insert_vetro_projects(self, vetro_projects: dict): + def insert_vetro_projects(self, vetro_projects: list[VetroProject]): cur = self.con.cursor() - for k, v in vetro_projects.items(): + for vetro_project in vetro_projects: try: - cur.execute("INSERT INTO vetro_projects VALUES(?, ?)", (k, v)) + cur.execute("INSERT INTO vetro_projects VALUES(?, ?)", (vetro_project.id, vetro_project.title)) self.con.commit() except Exception as e: logger.debug(e) diff --git a/enums.py b/enums.py index 9718dc9..0a983a5 100644 --- a/enums.py +++ b/enums.py @@ -1,7 +1,7 @@ from enum import IntEnum, StrEnum -class ActivityType(IntEnum): +class ActivityTypes(IntEnum): DEVELOPMENT = 9 BUSINESS_ANALYZE = 8 CODE_REVIEW = 57 diff --git a/track.py b/track.py index 032161c..92ab2f4 100644 --- a/track.py +++ b/track.py @@ -47,8 +47,12 @@ def main(): ) red = RedmineAPI(config.REDMINE_TOKEN) - db.insert_tags(clock.get_tags()) - db.insert_vetro_projects(config.VETRO_PROJECTS) + if args.init_db: + logger.info("Обновление базы данных...") + db.insert_tags(clock.get_tags()) + db.insert_vetro_projects(clock.get_vetro_projects()) + db.insert_activity_types(red.get_time_entry_activities()) + activities = clock.get_activities( **{ "start": format_date(start), @@ -57,7 +61,6 @@ def main(): }, ) db.insert_activities(activities) - db.insert_activity_types(red.get_time_entry_activities()) if args.debug: logger.debug("Пропускаем этап загрузки трудочасов") return