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:
@@ -93,6 +93,28 @@ class RedmineAPI(RedmineConfig):
|
|||||||
"email": json["mail"],
|
"email": json["mail"],
|
||||||
"username": json["login"]
|
"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):
|
def _check_token(self):
|
||||||
user = self.get_user()
|
user = self.get_user()
|
||||||
|
|||||||
@@ -8,9 +8,12 @@ CREATE TABLE IF NOT EXISTS "activity" (
|
|||||||
"is_tracked" BOOLEAN NOT NULL DEFAULT false,
|
"is_tracked" BOOLEAN NOT NULL DEFAULT false,
|
||||||
"vetro_project_id" VARCHAR,
|
"vetro_project_id" VARCHAR,
|
||||||
"tag_id" VARCHAR NOT NULL,
|
"tag_id" VARCHAR NOT NULL,
|
||||||
|
"task_id" INTEGER,
|
||||||
"project_id" VARCHAR NOT NULL,
|
"project_id" VARCHAR NOT NULL,
|
||||||
PRIMARY KEY("id"),
|
PRIMARY KEY("id"),
|
||||||
FOREIGN KEY ("author_id") REFERENCES "user"("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
|
ON UPDATE NO ACTION ON DELETE NO ACTION
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -32,6 +35,18 @@ CREATE TABLE IF NOT EXISTS "activity_type" (
|
|||||||
PRIMARY KEY("id")
|
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" (
|
CREATE TABLE IF NOT EXISTS "time_entry" (
|
||||||
"id" INTEGER,
|
"id" INTEGER,
|
||||||
"author_id" INTEGER NOT NULL,
|
"author_id" INTEGER NOT NULL,
|
||||||
@@ -43,6 +58,9 @@ CREATE TABLE IF NOT EXISTS "time_entry" (
|
|||||||
"activity_type_id" INTEGER NOT NULL,
|
"activity_type_id" INTEGER NOT NULL,
|
||||||
PRIMARY KEY("id"),
|
PRIMARY KEY("id"),
|
||||||
FOREIGN KEY ("author_id") REFERENCES "user"("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")
|
FOREIGN KEY ("activity_type_id") REFERENCES "activity_type"("id")
|
||||||
ON UPDATE NO ACTION ON DELETE NO ACTION
|
ON UPDATE NO ACTION ON DELETE NO ACTION
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,3 +5,4 @@ class RedmineConfig:
|
|||||||
self.my_account_url = "/my/account.json"
|
self.my_account_url = "/my/account.json"
|
||||||
self.datetime_format = "%Y-%m-%d"
|
self.datetime_format = "%Y-%m-%d"
|
||||||
self.time_entry_activities = "/enumerations/time_entry_activities.json"
|
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)
|
is_updated = bool(tags)
|
||||||
try:
|
try:
|
||||||
self.cursor.execute(
|
self.cursor.execute(
|
||||||
"INSERT INTO activity VALUES(?,?,?,?,?,?,?,?,?,?)",
|
"INSERT INTO activity VALUES(?,?,?,?,?,?,?,?,?,?,?)",
|
||||||
(
|
(
|
||||||
act.id,
|
act.id,
|
||||||
act.description,
|
act.description,
|
||||||
@@ -54,13 +54,14 @@ class Database:
|
|||||||
act.is_tracked,
|
act.is_tracked,
|
||||||
act.vetro_project_id,
|
act.vetro_project_id,
|
||||||
act.tag_id,
|
act.tag_id,
|
||||||
|
act.task_id,
|
||||||
act.project_id,
|
act.project_id,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
except sq.IntegrityError:
|
except sq.IntegrityError:
|
||||||
self.cursor.execute(
|
self.cursor.execute(
|
||||||
"""UPDATE activity
|
"""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 = ?""",
|
WHERE id = ?""",
|
||||||
(
|
(
|
||||||
act.description,
|
act.description,
|
||||||
@@ -70,6 +71,7 @@ class Database:
|
|||||||
act.is_tracked,
|
act.is_tracked,
|
||||||
act.vetro_project_id,
|
act.vetro_project_id,
|
||||||
act.tag_id,
|
act.tag_id,
|
||||||
|
act.task_id,
|
||||||
act.project_id,
|
act.project_id,
|
||||||
act.id,
|
act.id,
|
||||||
)
|
)
|
||||||
@@ -211,3 +213,46 @@ class Database:
|
|||||||
]
|
]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(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 api import ClockifyAPI, RedmineAPI # noqa: E402
|
||||||
from config import arg_parser, config, db # 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
|
WORKSPACE_ID = config.WORKSPACE_ID
|
||||||
@@ -80,9 +80,22 @@ def main():
|
|||||||
if args.init_db:
|
if args.init_db:
|
||||||
logger.info(Fore.YELLOW + "Обновление базы данных..." + Fore.RESET)
|
logger.info(Fore.YELLOW + "Обновление базы данных..." + Fore.RESET)
|
||||||
try:
|
try:
|
||||||
db.insert_tags(clock.get_tags(is_updating=True, **{"page-size": clock.tags_count}))
|
logging.info(f"{Fore.YELLOW}Получение Тегов{Fore.RESET}")
|
||||||
db.insert_vetro_projects(clock.get_vetro_projects())
|
tags = clock.get_tags(is_updating=True, **{"page-size": clock.tags_count})
|
||||||
db.insert_activity_types(red.get_time_entry_activities())
|
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:
|
except Exception as e:
|
||||||
logger.error(Fore.RED + f"Ошибка при обновлении базы данных: {e}" + Fore.RESET)
|
logger.error(Fore.RED + f"Ошибка при обновлении базы данных: {e}" + Fore.RESET)
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user