Compare commits
2 Commits
3c995e0618
...
5909f0d80a
| Author | SHA1 | Date | |
|---|---|---|---|
| 5909f0d80a | |||
| a5f86563fa |
@@ -93,6 +93,28 @@ class RedmineAPI(RedmineConfig):
|
||||
"email": json["mail"],
|
||||
"username": json["login"]
|
||||
}
|
||||
|
||||
def get_issue(self, issue_id: int) -> dict:
|
||||
"""Получает задачу по её id с сервера Redmine"""
|
||||
resp = requests.get(
|
||||
self.base_url + self.issues.format(**{"id": issue_id}),
|
||||
headers={"X-Redmine-Api-Key": self.token},
|
||||
timeout=None
|
||||
)
|
||||
if not resp.ok:
|
||||
logger.error("Ошибка RedmineAPI")
|
||||
return {}
|
||||
issue = resp.json()["issue"]
|
||||
return {
|
||||
"id": issue["id"],
|
||||
"subject": issue["subject"],
|
||||
"description": issue["description"],
|
||||
"status": issue["status"]["name"],
|
||||
"priority": issue["priority"]["name"],
|
||||
"author": issue["author"]["name"],
|
||||
"tracker": issue["tracker"]["name"],
|
||||
"project": issue["project"]["name"]
|
||||
}
|
||||
|
||||
def _check_token(self):
|
||||
user = self.get_user()
|
||||
|
||||
@@ -8,9 +8,12 @@ CREATE TABLE IF NOT EXISTS "activity" (
|
||||
"is_tracked" BOOLEAN NOT NULL DEFAULT false,
|
||||
"vetro_project_id" VARCHAR,
|
||||
"tag_id" VARCHAR NOT NULL,
|
||||
"task_id" INTEGER,
|
||||
"project_id" VARCHAR NOT NULL,
|
||||
PRIMARY KEY("id"),
|
||||
FOREIGN KEY ("author_id") REFERENCES "user"("id")
|
||||
ON UPDATE NO ACTION ON DELETE NO ACTION,
|
||||
FOREIGN KEY ("task_id") REFERENCES "task"("id")
|
||||
ON UPDATE NO ACTION ON DELETE NO ACTION
|
||||
);
|
||||
|
||||
@@ -32,6 +35,18 @@ CREATE TABLE IF NOT EXISTS "activity_type" (
|
||||
PRIMARY KEY("id")
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "task" (
|
||||
"id" INTEGER,
|
||||
"subject" TEXT,
|
||||
"description" TEXT,
|
||||
"status" TEXT,
|
||||
"priority" TEXT,
|
||||
"author" TEXT,
|
||||
"tracker" TEXT,
|
||||
"project" TEXT,
|
||||
PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "time_entry" (
|
||||
"id" INTEGER,
|
||||
"author_id" INTEGER NOT NULL,
|
||||
@@ -43,6 +58,9 @@ CREATE TABLE IF NOT EXISTS "time_entry" (
|
||||
"activity_type_id" INTEGER NOT NULL,
|
||||
PRIMARY KEY("id"),
|
||||
FOREIGN KEY ("author_id") REFERENCES "user"("id")
|
||||
ON UPDATE NO ACTION ON DELETE NO ACTION,
|
||||
FOREIGN KEY ("task_id") REFERENCES "task"("id")
|
||||
ON UPDATE NO ACTION ON DELETE NO ACTION,
|
||||
FOREIGN KEY ("activity_type_id") REFERENCES "activity_type"("id")
|
||||
ON UPDATE NO ACTION ON DELETE NO ACTION
|
||||
);
|
||||
|
||||
@@ -5,3 +5,4 @@ class RedmineConfig:
|
||||
self.my_account_url = "/my/account.json"
|
||||
self.datetime_format = "%Y-%m-%d"
|
||||
self.time_entry_activities = "/enumerations/time_entry_activities.json"
|
||||
self.issues = "/issues/{id}.json"
|
||||
|
||||
49
db/db.py
49
db/db.py
@@ -43,7 +43,7 @@ class Database:
|
||||
is_updated = bool(tags)
|
||||
try:
|
||||
self.cursor.execute(
|
||||
"INSERT INTO activity VALUES(?,?,?,?,?,?,?,?,?,?)",
|
||||
"INSERT INTO activity VALUES(?,?,?,?,?,?,?,?,?,?,?)",
|
||||
(
|
||||
act.id,
|
||||
act.description,
|
||||
@@ -54,13 +54,14 @@ class Database:
|
||||
act.is_tracked,
|
||||
act.vetro_project_id,
|
||||
act.tag_id,
|
||||
act.task_id,
|
||||
act.project_id,
|
||||
)
|
||||
)
|
||||
except sq.IntegrityError:
|
||||
self.cursor.execute(
|
||||
"""UPDATE activity
|
||||
SET description = ?, time_spent = ?, date_start = ?, date_end = ?, is_tracked = ?, vetro_project_id = ?, tag_id = ?, project_id = ?
|
||||
SET description = ?, time_spent = ?, date_start = ?, date_end = ?, is_tracked = ?, vetro_project_id = ?, tag_id = ?, task_id = ?, project_id = ?
|
||||
WHERE id = ?""",
|
||||
(
|
||||
act.description,
|
||||
@@ -70,6 +71,7 @@ class Database:
|
||||
act.is_tracked,
|
||||
act.vetro_project_id,
|
||||
act.tag_id,
|
||||
act.task_id,
|
||||
act.project_id,
|
||||
act.id,
|
||||
)
|
||||
@@ -211,3 +213,46 @@ class Database:
|
||||
]
|
||||
except Exception as e:
|
||||
logging.error(e)
|
||||
|
||||
def insert_tasks(self, tasks: list[dict]):
|
||||
"""Сохраняет в БД Задачи из Redmine"""
|
||||
for task in tasks:
|
||||
try:
|
||||
self.cursor.execute("""
|
||||
INSERT INTO task(
|
||||
"id",
|
||||
"subject",
|
||||
"description",
|
||||
"status",
|
||||
"priority",
|
||||
"author",
|
||||
"tracker",
|
||||
"project"
|
||||
)
|
||||
VALUES(?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||
[v for k, v in task.items()])
|
||||
except sq.IntegrityError:
|
||||
self.cursor.execute("""
|
||||
UPDATE task
|
||||
SET "subject" = ?,
|
||||
"description" = ?,
|
||||
"status" = ?,
|
||||
"priority" = ?,
|
||||
"author" = ?,
|
||||
"tracker" = ?,
|
||||
"project" = ?
|
||||
WHERE "id" = ?""",
|
||||
(
|
||||
task["subject"],
|
||||
task["description"],
|
||||
task["status"],
|
||||
task["priority"],
|
||||
task["author"],
|
||||
task["tracker"],
|
||||
task["project"],
|
||||
task["id"]
|
||||
)
|
||||
)
|
||||
finally:
|
||||
self.con.commit()
|
||||
|
||||
|
||||
21
track.py
21
track.py
@@ -16,7 +16,7 @@ from colorama import Fore # noqa: E402
|
||||
|
||||
from api import ClockifyAPI, RedmineAPI # noqa: E402
|
||||
from config import arg_parser, config, db # noqa: E402
|
||||
from utils import format_date, str_to_date, today_start, today_end # noqa: E402
|
||||
from utils import format_date, str_to_date, today_start, today_end, parse_task_id # noqa: E402
|
||||
|
||||
|
||||
WORKSPACE_ID = config.WORKSPACE_ID
|
||||
@@ -80,9 +80,22 @@ def main():
|
||||
if args.init_db:
|
||||
logger.info(Fore.YELLOW + "Обновление базы данных..." + Fore.RESET)
|
||||
try:
|
||||
db.insert_tags(clock.get_tags(is_updating=True, **{"page-size": clock.tags_count}))
|
||||
db.insert_vetro_projects(clock.get_vetro_projects())
|
||||
db.insert_activity_types(red.get_time_entry_activities())
|
||||
logging.info(f"{Fore.YELLOW}Получение Тегов{Fore.RESET}")
|
||||
tags = clock.get_tags(is_updating=True, **{"page-size": clock.tags_count})
|
||||
logging.info(f"{Fore.YELLOW}Получение Задач с Redmine{Fore.RESET}")
|
||||
issues = [red.get_issue(parse_task_id(tag.title)) for tag in tags]
|
||||
logging.info(f"{Fore.YELLOW}Получение Проектов Ветро{Fore.RESET}")
|
||||
vetro_projects = clock.get_vetro_projects()
|
||||
logging.info(f"{Fore.YELLOW}Получение Типов деятельности{Fore.RESET}")
|
||||
activity_types = red.get_time_entry_activities()
|
||||
logging.info(f"{Fore.YELLOW}Сохранение Тегов{Fore.RESET}")
|
||||
db.insert_tags(tags)
|
||||
logging.info(f"{Fore.YELLOW}Сохранение Задач Redmine{Fore.RESET}")
|
||||
db.insert_tasks(issues)
|
||||
logging.info(f"{Fore.YELLOW}Сохранение Проектов Ветро{Fore.RESET}")
|
||||
db.insert_vetro_projects(vetro_projects)
|
||||
logging.info(f"{Fore.YELLOW}Сохранение Типов деятелности{Fore.RESET}")
|
||||
db.insert_activity_types(activity_types)
|
||||
except Exception as e:
|
||||
logger.error(Fore.RED + f"Ошибка при обновлении базы данных: {e}" + Fore.RESET)
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user