Большой рефактор. Обновление тегов, задач и типов деятельности при сохранении активностей в БД
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import logging
|
import logging
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
from colorama import Fore
|
from colorama import Fore
|
||||||
import requests
|
import requests
|
||||||
@@ -52,17 +53,28 @@ class ClockifyAPI(ClockifyConfig):
|
|||||||
start = datetime.strptime(activity["timeInterval"]["start"], config.DATETIME_FORMAT)
|
start = datetime.strptime(activity["timeInterval"]["start"], config.DATETIME_FORMAT)
|
||||||
end = datetime.strptime(activity["timeInterval"]["end"], config.DATETIME_FORMAT) if activity["timeInterval"]["end"] else None
|
end = datetime.strptime(activity["timeInterval"]["end"], config.DATETIME_FORMAT) if activity["timeInterval"]["end"] else None
|
||||||
time_worked_out_total += time_to_hour((end if end else datetime.utcnow()) - start)
|
time_worked_out_total += time_to_hour((end if end else datetime.utcnow()) - start)
|
||||||
|
|
||||||
|
|
||||||
tag = [tag for tag in tags if tag.id == tag_id]
|
tag = [tag for tag in tags if tag.id == tag_id]
|
||||||
|
|
||||||
if not tag:
|
if not tag:
|
||||||
logging.info(f"{Fore.YELLOW}В базе данных нет нужного тега {Fore.GREEN}{tag_id}{Fore.YELLOW}! Обновите БД при помощи флага -i [--init-db]{Fore.RESET}")
|
tag = self.get_tags(True, tag_id=tag_id)
|
||||||
break
|
if tag:
|
||||||
else:
|
db.insert_tags([tag])
|
||||||
tag = tag[0]
|
from config import red
|
||||||
try:
|
try:
|
||||||
task_id = parse_task_id(tag.title)
|
task_id = parse_task_id(tag.title)
|
||||||
except ValueError:
|
except Exception as e:
|
||||||
logger.info(f'{activity["timeInterval"]["start"]}: {activity["description"]} - Неправильный формат тега {tag}')
|
logger.error(e)
|
||||||
continue
|
continue
|
||||||
|
task = red.get_issue(task_id)
|
||||||
|
if task:
|
||||||
|
db.insert_tasks([task])
|
||||||
|
else:
|
||||||
|
logger.error(f"{Fore.RED} Тег не найден: {tag_id}{Fore.RESET}")
|
||||||
|
else:
|
||||||
|
tag = tag[0]
|
||||||
|
task_id = parse_task_id(tag.title)
|
||||||
|
|
||||||
author = db.get_user_by("clockify_user_id", activity["userId"])
|
author = db.get_user_by("clockify_user_id", activity["userId"])
|
||||||
|
|
||||||
@@ -86,7 +98,7 @@ class ClockifyAPI(ClockifyConfig):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def get_tags(self, is_updating=False, **kwargs) -> list[Tag]:
|
def get_tags(self, is_updating=False, tag_id="", **kwargs) -> Union[list[Tag], Tag]:
|
||||||
"""
|
"""
|
||||||
Получает с сервера Clockify теги
|
Получает с сервера Clockify теги
|
||||||
name: str - optional
|
name: str - optional
|
||||||
@@ -95,7 +107,14 @@ class ClockifyAPI(ClockifyConfig):
|
|||||||
"""
|
"""
|
||||||
if is_updating:
|
if is_updating:
|
||||||
tags = requests.get(self.base_url + self.tags_url, params={"sort-column": "name", "sort-order": "descending", **kwargs}, headers={"X-API-KEY": self.token}).json()
|
tags = requests.get(self.base_url + self.tags_url, params={"sort-column": "name", "sort-order": "descending", **kwargs}, headers={"X-API-KEY": self.token}).json()
|
||||||
logging.debug(f"{Fore.YELLOW}Получено тегов: {len(tags)}.{Fore.RESET}")
|
if tag_id:
|
||||||
|
for tag in tags:
|
||||||
|
if tag_id == tag["id"]:
|
||||||
|
return Tag(
|
||||||
|
id=tag["id"],
|
||||||
|
title=tag["name"]
|
||||||
|
)
|
||||||
|
logger.debug(f"{Fore.YELLOW}Получено тегов: {len(tags)}.{Fore.RESET}")
|
||||||
return [Tag(
|
return [Tag(
|
||||||
id=tag["id"],
|
id=tag["id"],
|
||||||
title=tag["name"]
|
title=tag["name"]
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ class RedmineAPI(RedmineConfig):
|
|||||||
def get_issues(self) -> list[Task]:
|
def get_issues(self) -> list[Task]:
|
||||||
"""Получает задачи с сервера Redmine"""
|
"""Получает задачи с сервера Redmine"""
|
||||||
issues = []
|
issues = []
|
||||||
for i in range(15):
|
for i in range(25):
|
||||||
resp = requests.get(
|
resp = requests.get(
|
||||||
self.base_url + self.issues,
|
self.base_url + self.issues,
|
||||||
headers={"X-Redmine-Api-Key": self.token},
|
headers={"X-Redmine-Api-Key": self.token},
|
||||||
|
|||||||
@@ -80,3 +80,13 @@ def configure_argument_parser():
|
|||||||
arg_parser = configure_argument_parser()
|
arg_parser = configure_argument_parser()
|
||||||
config = Config()
|
config = Config()
|
||||||
db = Database(config.DB_NAME, config.SQL_PATH)
|
db = Database(config.DB_NAME, config.SQL_PATH)
|
||||||
|
|
||||||
|
from api.clockify import ClockifyAPI
|
||||||
|
from api.redmine import RedmineAPI
|
||||||
|
|
||||||
|
clock = ClockifyAPI(
|
||||||
|
token=config.CLOCKIFY_TOKEN,
|
||||||
|
workspace_id=config.WORKSPACE_ID,
|
||||||
|
user_id=config.USER_ID
|
||||||
|
)
|
||||||
|
red = RedmineAPI(config.REDMINE_TOKEN)
|
||||||
|
|||||||
100
db/db.py
100
db/db.py
@@ -32,16 +32,7 @@ class Database:
|
|||||||
|
|
||||||
def insert_activities(self, activities: list[Activity]):
|
def insert_activities(self, activities: list[Activity]):
|
||||||
"""Сохраняет в базу данных активности Clockify"""
|
"""Сохраняет в базу данных активности Clockify"""
|
||||||
is_updated = True
|
|
||||||
for act in activities:
|
for act in activities:
|
||||||
if is_updated:
|
|
||||||
tags = self.cursor.execute("SELECT * FROM tag WHERE id = ?", (act.tag_id, )).fetchall()
|
|
||||||
vetro_project_id = act.vetro_project_id
|
|
||||||
if vetro_project_id:
|
|
||||||
vetro_projects = self.cursor.execute("SELECT * FROM vetro_project WHERE id = ?", (vetro_project_id, )).fetchall()
|
|
||||||
is_updated = tags or vetro_projects
|
|
||||||
else:
|
|
||||||
is_updated = bool(tags)
|
|
||||||
try:
|
try:
|
||||||
self.cursor.execute(
|
self.cursor.execute(
|
||||||
"""INSERT INTO activity(
|
"""INSERT INTO activity(
|
||||||
@@ -91,8 +82,6 @@ class Database:
|
|||||||
)
|
)
|
||||||
finally:
|
finally:
|
||||||
self.con.commit()
|
self.con.commit()
|
||||||
if not is_updated:
|
|
||||||
logging.info(Fore.YELLOW + "База данных устарела. Рекомендуем обновить с помощью флага -i [--init-db]" + Fore.RESET)
|
|
||||||
|
|
||||||
def insert_time_entries(self, activities: list[Activity]):
|
def insert_time_entries(self, activities: list[Activity]):
|
||||||
"""Сохраняет в базу данных трудочасы Redmine"""
|
"""Сохраняет в базу данных трудочасы Redmine"""
|
||||||
@@ -196,39 +185,6 @@ class Database:
|
|||||||
finally:
|
finally:
|
||||||
self.con.commit()
|
self.con.commit()
|
||||||
|
|
||||||
def get_user_by(self, by_field: str, value: str):
|
|
||||||
"""Получает пользователя из бд"""
|
|
||||||
try:
|
|
||||||
user = self.cursor.execute(f"SELECT * FROM user WHERE {by_field} = ?", (value,)).fetchone()
|
|
||||||
return {
|
|
||||||
"id": user[0],
|
|
||||||
"first_name": user[1],
|
|
||||||
"last_name": user[2],
|
|
||||||
"clockify_user_id": user[3],
|
|
||||||
"redmine_user_id": user[4],
|
|
||||||
"clockify_email": user[5],
|
|
||||||
"clockify_username": user[6],
|
|
||||||
"redmine_email": user[7],
|
|
||||||
"redmine_username": user[8]
|
|
||||||
}
|
|
||||||
except Exception as e:
|
|
||||||
logging.error(e)
|
|
||||||
|
|
||||||
|
|
||||||
def get_tags(self) -> list[Tag]:
|
|
||||||
"""Получает теги из бд"""
|
|
||||||
try:
|
|
||||||
tags = self.cursor.execute("SELECT * FROM tag").fetchall()
|
|
||||||
return [
|
|
||||||
Tag(
|
|
||||||
id=tag[0],
|
|
||||||
title=tag[1]
|
|
||||||
)
|
|
||||||
for tag in tags
|
|
||||||
]
|
|
||||||
except Exception as e:
|
|
||||||
logging.error(e)
|
|
||||||
|
|
||||||
def insert_tasks(self, tasks: list[Task]):
|
def insert_tasks(self, tasks: list[Task]):
|
||||||
"""Сохраняет в БД Задачи из Redmine"""
|
"""Сохраняет в БД Задачи из Redmine"""
|
||||||
for task in tasks:
|
for task in tasks:
|
||||||
@@ -280,6 +236,38 @@ class Database:
|
|||||||
finally:
|
finally:
|
||||||
self.con.commit()
|
self.con.commit()
|
||||||
|
|
||||||
|
def get_user_by(self, by_field: str, value: str):
|
||||||
|
"""Получает пользователя из бд"""
|
||||||
|
try:
|
||||||
|
user = self.cursor.execute(f"SELECT * FROM user WHERE {by_field} = ?", (value,)).fetchone()
|
||||||
|
return {
|
||||||
|
"id": user[0],
|
||||||
|
"first_name": user[1],
|
||||||
|
"last_name": user[2],
|
||||||
|
"clockify_user_id": user[3],
|
||||||
|
"redmine_user_id": user[4],
|
||||||
|
"clockify_email": user[5],
|
||||||
|
"clockify_username": user[6],
|
||||||
|
"redmine_email": user[7],
|
||||||
|
"redmine_username": user[8]
|
||||||
|
}
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(e)
|
||||||
|
|
||||||
|
|
||||||
|
def get_tags(self) -> list[Tag]:
|
||||||
|
"""Получает теги из бд"""
|
||||||
|
try:
|
||||||
|
return [
|
||||||
|
Tag(
|
||||||
|
id=tag[0],
|
||||||
|
title=tag[1]
|
||||||
|
)
|
||||||
|
for tag in self.cursor.execute("SELECT * FROM tag").fetchall()
|
||||||
|
]
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(e)
|
||||||
|
|
||||||
def get_tasks(self) -> list[Task]:
|
def get_tasks(self) -> list[Task]:
|
||||||
"""Получает задачи из бд"""
|
"""Получает задачи из бд"""
|
||||||
try:
|
try:
|
||||||
@@ -297,3 +285,27 @@ class Database:
|
|||||||
]
|
]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(e)
|
logging.error(e)
|
||||||
|
|
||||||
|
def get_vetro_projects(self) -> list[VetroProject]:
|
||||||
|
"""Получает Проекты Ветро из бд"""
|
||||||
|
try:
|
||||||
|
return [
|
||||||
|
VetroProject(**{
|
||||||
|
"id": vetro_project[0],
|
||||||
|
"title": vetro_project[1]
|
||||||
|
}) for vetro_project in self.cursor.execute("SELECT * FROM vetro_project").fetchall()
|
||||||
|
]
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(e)
|
||||||
|
|
||||||
|
def get_activity_types(self) -> list[ActivityType]:
|
||||||
|
"""Получает Виды деятельности из бд"""
|
||||||
|
try:
|
||||||
|
return [
|
||||||
|
ActivityType(**{
|
||||||
|
"id": activity_type[0],
|
||||||
|
"title": activity_type[1]
|
||||||
|
}) for activity_type in self.cursor.execute("SELECT * FROM activity_type").fetchall()
|
||||||
|
]
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(e)
|
||||||
|
|||||||
101
track.py
101
track.py
@@ -1,5 +1,4 @@
|
|||||||
import logging
|
import logging
|
||||||
import os.path
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
@@ -14,13 +13,8 @@ logging.basicConfig(
|
|||||||
|
|
||||||
from colorama import Fore # noqa: E402
|
from colorama import Fore # noqa: E402
|
||||||
|
|
||||||
from api import ClockifyAPI, RedmineAPI # noqa: E402
|
from config import arg_parser, clock, db, red # noqa: E402
|
||||||
from config import arg_parser, config, db # noqa: E402
|
from utils import check_envs, db_update, format_date, get_start_end_dates # noqa: E402
|
||||||
from utils import format_date, str_to_date, today_start, today_end, parse_task_id # noqa: E402
|
|
||||||
|
|
||||||
|
|
||||||
WORKSPACE_ID = config.WORKSPACE_ID
|
|
||||||
USER_ID = config.USER_ID
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@@ -31,40 +25,11 @@ def main():
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
start, end = None, None
|
start, end = get_start_end_dates(args)
|
||||||
if args.start:
|
|
||||||
start = str_to_date(args.start)
|
|
||||||
if args.end:
|
|
||||||
end = str_to_date(args.end)
|
|
||||||
if args.start is None and args.end is None:
|
|
||||||
logger.info("Парсим задачи за сегодняшний день")
|
|
||||||
start = today_start()
|
|
||||||
end = today_end()
|
|
||||||
else:
|
|
||||||
if start:
|
|
||||||
from_ = f"{start.day} {config.MONTHS.get(start.month)} {start.year} г."
|
|
||||||
|
|
||||||
if end:
|
if not check_envs():
|
||||||
to_ = f"{end.day} {config.MONTHS.get(end.month)} {end.year} г."
|
|
||||||
|
|
||||||
if start == end:
|
|
||||||
logger.info(f"{Fore.YELLOW}Парсим задачи за {from_}{Fore.RESET}")
|
|
||||||
else:
|
|
||||||
logger.info(Fore.YELLOW + "Парсим задачи" + (f" с {from_} " if start else " ") + (f"до {to_}" if end else "") + Fore.RESET)
|
|
||||||
|
|
||||||
clock = ClockifyAPI(
|
|
||||||
token=config.CLOCKIFY_TOKEN,
|
|
||||||
workspace_id=WORKSPACE_ID,
|
|
||||||
user_id=USER_ID
|
|
||||||
)
|
|
||||||
if not WORKSPACE_ID or not USER_ID:
|
|
||||||
if not os.path.exists(config.ENV_TXT):
|
|
||||||
logger.info(f"{Fore.YELLOW}Необходимые переменные не были обнаружены. Попытка получения...{Fore.RESET}")
|
|
||||||
clock.getenvs()
|
|
||||||
else:
|
|
||||||
logger.info(f'{Fore.YELLOW}Проверьте файл "{config.ENV_TXT}". Если необходимых переменных в нём нет, то просто удалите его.{Fore.RESET}')
|
|
||||||
return
|
return
|
||||||
red = RedmineAPI(config.REDMINE_TOKEN)
|
|
||||||
user = clock.get_user()
|
user = clock.get_user()
|
||||||
clock_user = {
|
clock_user = {
|
||||||
"clockify_user_id": user["id"],
|
"clockify_user_id": user["id"],
|
||||||
@@ -81,61 +46,7 @@ def main():
|
|||||||
}
|
}
|
||||||
db.insert_user(**clock_user, **red_user)
|
db.insert_user(**clock_user, **red_user)
|
||||||
if args.init_db:
|
if args.init_db:
|
||||||
logger.info(Fore.YELLOW + "Обновление базы данных..." + Fore.RESET)
|
db_update()
|
||||||
|
|
||||||
try:
|
|
||||||
# Обновление Тегов
|
|
||||||
logger.info(f"{Fore.YELLOW}Обновление Тегов...\n{Fore.RESET}")
|
|
||||||
|
|
||||||
clock_tags = clock.get_tags(is_updating=True, **{"page-size": clock.tags_count})
|
|
||||||
db_tags = db.get_tags()
|
|
||||||
new_tags = [tag for tag in clock_tags if tag not in db_tags]
|
|
||||||
|
|
||||||
if new_tags:
|
|
||||||
try:
|
|
||||||
db.insert_tags(new_tags)
|
|
||||||
logger.info(f"{Fore.GREEN}Обновлено тегов: {len(new_tags)}{Fore.RESET}")
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"{Fore.RED}Ошибка при сохранении тегов!{Fore.RESET}")
|
|
||||||
else:
|
|
||||||
logger.info(f"{Fore.YELLOW}Обновление тегов не требуется.\n{Fore.RESET}")
|
|
||||||
|
|
||||||
|
|
||||||
# Обновление Задач
|
|
||||||
logger.info(f"{Fore.YELLOW}Обновление Задач...\n{Fore.RESET}")
|
|
||||||
|
|
||||||
db_tasks = db.get_tasks()
|
|
||||||
red_tasks = red.get_issues()
|
|
||||||
clock_tasks = [task for task in red_tasks if task.id in [parse_task_id(tag.title) for tag in [*db_tags, *new_tags]]]
|
|
||||||
new_tasks = [task for task in clock_tasks if task not in db_tasks]
|
|
||||||
|
|
||||||
if new_tasks:
|
|
||||||
try:
|
|
||||||
db.insert_tasks(new_tasks)
|
|
||||||
logger.info(f"{Fore.GREEN}Обновлено задач: {len(new_tasks)}{Fore.RESET}")
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"{Fore.RED}Ошибка при сохранении задач!{Fore.RESET}")
|
|
||||||
else:
|
|
||||||
logger.info(f"{Fore.YELLOW}Обновление задач не требуется\n{Fore.RESET}")
|
|
||||||
|
|
||||||
# # Обновление Проектов Ветро
|
|
||||||
# logger.info(f"{Fore.YELLOW}Получение Проектов Ветро{Fore.RESET}")
|
|
||||||
# vetro_projects = clock.get_vetro_projects()
|
|
||||||
|
|
||||||
# logger.info(f"{Fore.YELLOW}Получение Типов деятельности{Fore.RESET}")
|
|
||||||
# activity_types = red.get_time_entry_activities()
|
|
||||||
|
|
||||||
# if vetro_projects:
|
|
||||||
# logger.info(f"{Fore.YELLOW}Сохранение Проектов Ветро{Fore.RESET}")
|
|
||||||
# db.insert_vetro_projects(vetro_projects)
|
|
||||||
|
|
||||||
# if activity_types:
|
|
||||||
# logger.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:
|
|
||||||
logger.info(Fore.GREEN + "База данных теперь актуальна." + Fore.RESET)
|
|
||||||
|
|
||||||
activities = sorted(clock.get_activities(
|
activities = sorted(clock.get_activities(
|
||||||
**{
|
**{
|
||||||
|
|||||||
115
utils.py
115
utils.py
@@ -1,9 +1,16 @@
|
|||||||
|
from argparse import Namespace
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
import re
|
import re
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
|
from colorama import Fore
|
||||||
|
|
||||||
from config import config
|
from config import config
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
def time_to_hour(time: timedelta) -> float:
|
def time_to_hour(time: timedelta) -> float:
|
||||||
return time.total_seconds() / 3600
|
return time.total_seconds() / 3600
|
||||||
|
|
||||||
@@ -32,3 +39,111 @@ def format_date(date: datetime) -> datetime:
|
|||||||
|
|
||||||
def parse_task_id(tag: str) -> int:
|
def parse_task_id(tag: str) -> int:
|
||||||
return int(re.search(r"^(?P<task_id>\d{5})", tag).group("task_id"))
|
return int(re.search(r"^(?P<task_id>\d{5})", tag).group("task_id"))
|
||||||
|
|
||||||
|
def db_update():
|
||||||
|
from config import clock, db, red
|
||||||
|
logger.info(Fore.YELLOW + "Обновление базы данных..." + Fore.RESET)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Обновление Тегов
|
||||||
|
logger.info(f"{Fore.YELLOW}Обновление Тегов...\n{Fore.RESET}")
|
||||||
|
|
||||||
|
clock_tags = clock.get_tags(is_updating=True, **{"page-size": clock.tags_count})
|
||||||
|
db_tags = db.get_tags()
|
||||||
|
new_tags = [tag for tag in clock_tags if tag not in db_tags]
|
||||||
|
|
||||||
|
if new_tags:
|
||||||
|
try:
|
||||||
|
db.insert_tags(new_tags)
|
||||||
|
logger.info(f"{Fore.GREEN}Обновлено тегов: {len(new_tags)}{Fore.RESET}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"{Fore.RED}Ошибка при сохранении тегов!{Fore.RESET}")
|
||||||
|
else:
|
||||||
|
logger.info(f"{Fore.YELLOW}Обновление тегов не требуется.\n{Fore.RESET}")
|
||||||
|
|
||||||
|
|
||||||
|
# Обновление Задач
|
||||||
|
logger.info(f"{Fore.YELLOW}Обновление Задач...\n{Fore.RESET}")
|
||||||
|
|
||||||
|
db_tasks = db.get_tasks()
|
||||||
|
red_tasks = red.get_issues()
|
||||||
|
clock_tasks = [task for task in red_tasks if task.id in [parse_task_id(tag.title) for tag in [*db_tags, *new_tags]]]
|
||||||
|
new_tasks = [task for task in clock_tasks if task not in db_tasks]
|
||||||
|
|
||||||
|
if new_tasks:
|
||||||
|
try:
|
||||||
|
db.insert_tasks(new_tasks)
|
||||||
|
logger.info(f"{Fore.GREEN}Обновлено задач: {len(new_tasks)}{Fore.RESET}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"{Fore.RED}Ошибка при сохранении задач!{Fore.RESET}")
|
||||||
|
else:
|
||||||
|
logger.info(f"{Fore.YELLOW}Обновление задач не требуется\n{Fore.RESET}")
|
||||||
|
|
||||||
|
# Обновление Проектов Ветро
|
||||||
|
logger.info(f"{Fore.YELLOW}Обновление Проектов Ветро{Fore.RESET}")
|
||||||
|
clock_projects = clock.get_vetro_projects()
|
||||||
|
db_projects = db.get_vetro_projects()
|
||||||
|
new_projects = [project for project in clock_projects if project not in db_projects]
|
||||||
|
|
||||||
|
if new_projects:
|
||||||
|
try:
|
||||||
|
db.insert_vetro_projects(new_projects)
|
||||||
|
logger.info(f"{Fore.GREEN}Обновлено Проектов Ветро: {len(new_projects)}{Fore.RESET}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"{Fore.RED}Ошибка при сохранении Проектов Ветро!{Fore.RESET}")
|
||||||
|
else:
|
||||||
|
logger.info(f"{Fore.YELLOW}Обновление Проектов Ветро не требуется\n{Fore.RESET}")
|
||||||
|
|
||||||
|
# Обновление Типов деятельности
|
||||||
|
logger.info(f"{Fore.YELLOW}Обновление Типов деятельности{Fore.RESET}")
|
||||||
|
red_types = red.get_time_entry_activities()
|
||||||
|
db_types = db.get_activity_types()
|
||||||
|
new_types = [type_ for type_ in red_types if type_ not in db_types]
|
||||||
|
|
||||||
|
if new_types:
|
||||||
|
try:
|
||||||
|
db.insert_activity_types(new_types)
|
||||||
|
logger.info(f"{Fore.GREEN}Обновлено Типов деятельности: {len(new_types)}{Fore.RESET}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"{Fore.RED}Ошибка при сохранении Типов деятельности!{Fore.RESET}")
|
||||||
|
else:
|
||||||
|
logger.info(f"{Fore.YELLOW}Обновление Типов деятельности не требуется\n{Fore.RESET}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(Fore.RED + f"Ошибка при обновлении базы данных: {e}" + Fore.RESET)
|
||||||
|
else:
|
||||||
|
logger.info(Fore.GREEN + "База данных теперь актуальна." + Fore.RESET)
|
||||||
|
|
||||||
|
def get_start_end_dates(args: Namespace):
|
||||||
|
if args.start:
|
||||||
|
start = str_to_date(args.start)
|
||||||
|
if args.end:
|
||||||
|
end = str_to_date(args.end)
|
||||||
|
if args.start is None and args.end is None:
|
||||||
|
logger.info("Парсим задачи за сегодняшний день")
|
||||||
|
start = today_start()
|
||||||
|
end = today_end()
|
||||||
|
else:
|
||||||
|
if start:
|
||||||
|
from_ = f"{start.day} {config.MONTHS.get(start.month)} {start.year} г."
|
||||||
|
|
||||||
|
if end:
|
||||||
|
to_ = f"{end.day} {config.MONTHS.get(end.month)} {end.year} г."
|
||||||
|
|
||||||
|
if start == end:
|
||||||
|
logger.info(f"{Fore.YELLOW}Парсим задачи за {from_}{Fore.RESET}")
|
||||||
|
else:
|
||||||
|
logger.info(Fore.YELLOW + "Парсим задачи" + (f" с {from_} " if start else " ") + (f"до {to_}" if end else "") + Fore.RESET)
|
||||||
|
|
||||||
|
return start, end
|
||||||
|
|
||||||
|
def check_envs():
|
||||||
|
from config import config, clock
|
||||||
|
if not config.WORKSPACE_ID or not config.USER_ID:
|
||||||
|
if not os.path.exists(config.ENV_TXT):
|
||||||
|
logger.info(f"{Fore.YELLOW}Необходимые переменные не были обнаружены. Попытка получения...{Fore.RESET}")
|
||||||
|
clock.getenvs()
|
||||||
|
else:
|
||||||
|
logger.info(f'{Fore.YELLOW}Проверьте файл "{config.ENV_TXT}". Если необходимых переменных в нём нет, то просто удалите его.{Fore.RESET}')
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|||||||
Reference in New Issue
Block a user