добавил систему миграций и связь одной записи Redmine с несколькими активностями Clockify и запретил отправку трудочасов при инициализации базы данных

This commit is contained in:
2026-07-14 15:54:26 +03:00
parent 5dca3ae446
commit 49286d0fcf
14 changed files with 297 additions and 72 deletions

View File

@@ -11,7 +11,6 @@ from utils import format_hours
from .constants import (
ACTIVITY_TYPE_BY_VETRO_PROJECT,
DEFAULT_ACTIVITY_TYPE,
REDMINE_ISSUES_LIMIT,
REQUEST_TIMEOUT,
)
@@ -60,7 +59,7 @@ class RedmineAPI(RedmineConfig):
if config.is_debug or resp.ok:
activity.is_tracked = True
if on_success:
on_success(activity)
on_success(activity, resp.json()["time_entry"]["id"])
tracked.append(activity)
logger.info(
f"{Fore.GREEN}{self.format_activity_result(activity, is_beginner)}"
@@ -139,11 +138,19 @@ class RedmineAPI(RedmineConfig):
def get_issue(self, issue_id: int) -> Task | None:
"""Получает задачу по её id с сервера Redmine"""
resp = requests.get(
self.base_url + self.issue.format(**{"id": issue_id}),
headers={"X-Redmine-Api-Key": self.token},
timeout=REQUEST_TIMEOUT,
)
try:
resp = requests.get(
self.base_url + self.issue.format(**{"id": issue_id}),
headers={"X-Redmine-Api-Key": self.token},
timeout=REQUEST_TIMEOUT,
)
except requests.RequestException as error:
logger.error(
"Не удалось загрузить задачу #%s из Redmine: %s",
issue_id,
error,
)
return None
if not resp.ok:
logger.error(f"Ошибка RedmineAPI: {resp.text} {resp.status_code}")
return None
@@ -159,38 +166,13 @@ class RedmineAPI(RedmineConfig):
"project": issue["project"]["name"]
})
def get_issues(self) -> list[Task]:
"""Получает задачи с сервера Redmine"""
issues = []
offset = 0
total_count = None
while total_count is None or offset < total_count:
resp = requests.get(
self.base_url + self.issues,
headers={"X-Redmine-Api-Key": self.token},
params={"limit": REDMINE_ISSUES_LIMIT, "offset": offset, "status_id": "*"},
timeout=REQUEST_TIMEOUT,
)
if not resp.ok:
logger.error(f"Ошибка RedmineAPI: {resp.text} {resp.status_code}")
return []
data = resp.json()
if not data:
logger.error("Ошибка RedmineAPI: пустой ответ")
return []
issues.extend(data["issues"])
total_count = data.get("total_count", len(issues))
offset += data.get("limit", REDMINE_ISSUES_LIMIT)
return [Task(**{
"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"]
}) for issue in issues]
def get_issues(self, issue_ids: set[int]) -> list[Task]:
"""Получает с сервера Redmine только задачи с указанными номерами."""
return [
task
for issue_id in sorted(issue_ids)
if (task := self.get_issue(issue_id))
]
def _check_token(self):
user = self.get_user()