Merge pull request 'Новая таблица tasks' (#6) from dev into master

Reviewed-on: #6
This commit was merged in pull request #6.
This commit is contained in:
2025-06-20 16:47:57 +03:00
5 changed files with 105 additions and 6 deletions

View File

@@ -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()

View File

@@ -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
);

View File

@@ -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"

View File

@@ -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()

View File

@@ -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: