diff --git a/app/main.py b/app/main.py index 560e72a..652f556 100644 --- a/app/main.py +++ b/app/main.py @@ -1,6 +1,43 @@ import working_database import parse_saby +from dateutil import parser + +def parse_data_for_bd(dict_data: dict) -> list[list]: + """ + Фуннкция приминмает словарь и парсит его в лист листов + для передачи в БД. Каждый лист должен состоять из 6 элементов + """ + result_list = [] + for key_id, value_data in dict_data.items(): + if len(value_data) != 5: + continue + organ, names, date_from_str, date_to_str, ver = value_data + # Парсим даты + if date_from_str: + date_from = parser.parse(date_from_str).date() + date_from = str(date_from.strftime('%d.%m.%Y')) + #TODO date_from cannot be NULL\NONE + else: + print(f"Отсутсвует дата: {key_id}: {organ} {names}") + continue + if date_to_str: + date_to = parser.parse(date_to_str).date() + date_to = str(date_to.strftime('%d.%m.%Y')) + #TODO change to NULL + else: date_to = None + parametrs_list = [int(key_id), organ, names, date_to, date_from, ver] + result_list.append(parametrs_list) + + print("Отправляемых агрументов: ", *parametrs_list) + print("Типо данных: ", list(map(type, parametrs_list))) + return result_list result_dict_data = parse_saby.process_reports_parse() -test = working_database.SimpleDB() -test.data_transfer_in_database(result_dict_data) \ No newline at end of file +list_data = parse_data_for_bd(result_dict_data) +PushDB = working_database.SimpleDB() +PushDB.data_transfer_in_database(list_data) + +if __name__ in "__main__": + result_dict_data = parse_saby.process_reports_parse() + list_data = parse_data_for_bd(result_dict_data) + print(list_data) \ No newline at end of file diff --git a/app/working_database.py b/app/working_database.py index 6ca7013..7beeeb9 100644 --- a/app/working_database.py +++ b/app/working_database.py @@ -1,46 +1,73 @@ -from os import getenv, environ +from os import environ import hvac -from oracledb import Error, create_pool, init_oracle_client, DatabaseError -from fastapi import HTTPException -from dateutil import parser -import datetime +import hvac.exceptions +from oracledb import Error, create_pool, init_oracle_client + init_oracle_client() class SimpleDB: def __init__(self): - self._connect_hvac() + self._create_db_pool_from_vault() self.pool init_oracle_client() - #TODO: rename - def _connect_hvac(self): + + def _handle_vault_exception(self, e: Exception, message: str): """ - Подключение к Vault и получение параметров БД + Обработка исключений Vault с возвратом понятного сообщения. + """ + print(message) + if isinstance(e, hvac.exceptions.InvalidPath): + raise hvac.exceptions.InvalidPath("Database configuration not found in Vault") + elif isinstance(e, hvac.exceptions.Forbidden): + raise hvac.exceptions.Forbidden("Permission denied to access Vault secrets") + elif isinstance(e, hvac.exceptions.Unauthorized): + raise hvac.exceptions.Unauthorized("Invalid Vault token") + elif isinstance(e, hvac.exceptions.VaultError): + raise hvac.exceptions.VaultError(f"Vault secret retrieval failed: {e}") + elif isinstance(e, hvac.exceptions.InvalidRequest): + raise hvac.exceptions.InvalidRequest(f"Missing database parameter in Vault response: {e}") + elif isinstance(e, hvac.exceptions.VaultDown): + raise hvac.exceptions.VaultDown(f"Database server not available: {e}") + else: + raise Exception (f'Unexpected error reading from Vault: {e}') + + #TODO: rename + + def _create_db_pool_from_vault(self): + """ + Подключение к Vault и получение параметров для подключеник к БД """ #TODO разнести в разные try_exception try: + # Подключение к Vault client = hvac.Client( url='https://vlt.dataekb.ru:8222', token=environ.get('VAULT_TOKEN'), ) - - read_response = client.secrets.kv.v2.read_secret_version( + except Exception as e: + self._handle_vault_exception(e, "Ошибка при создание покдлючения c Vault") + try: + # Чтение секретов из Vault + secret_read_response = client.secrets.kv.v2.read_secret_version( path='oracledb', mount_point='kv' ) - + except Exception as e: + self._handle_vault_exception(e, "Ошибка чтение скретов из Vault") + + try: # Создаем пул соединений self.pool = create_pool( - user=read_response['data']['data']['user'], - password=read_response['data']['data']['password'], - dsn=read_response['data']['data']['cs'], + user=secret_read_response['data']['data']['user'], + password=secret_read_response['data']['data']['password'], + dsn=secret_read_response['data']['data']['cs'], min=2, max=10, increment=1 ) except Exception as e: - raise HTTPException(status_code=500, detail=f"Database connection failed: {e}") - - def data_transfer_in_database(self, dict_data: dict): + self._handle_vault_exception(e, "Ошибка при создание пула для подключение к Oracle") + + def data_transfer_in_database(self, list_data: list): """ Передача данных в базу Процедура на вставку: @@ -55,33 +82,16 @@ class SimpleDB: VERS IN VARCHAR2) """ if not self.pool: - raise HTTPException(status_code=500, detail="Database pool not initialized") - - if not dict_data: - raise ValueError(dict_data, "No data to process") + raise ValueError(self.pool, "Database pool not initialized") + if not list_data: + raise ValueError(list_data, "No data to process") try: with self.pool.acquire() as connection: with connection.cursor() as cursor: - # Передача данных в БД - for id, value in dict_data.items(): - if len(value) != 5: - continue - organ, names, date_from_str, date_to_str, ver = value - # Парсим даты - if date_from_str: - date_from = parser.parse(date_from_str).date() - #date_from = str(date_from.strftime('%d.%m.%Y')) - #TODO date_from cannot be NULL\NONE - else: date_from = parser.parse('01.01.2000') - if date_to_str: - date_to = parser.parse(date_to_str).date() - #date_to = str(date_to.strftime('%d.%m.%Y')) - #TODO change to NULL - else: date_to = parser.parse('01.01.2000') - print("Вывод отправляемых агрументов: ", id, organ, names, date_from, date_to, ver) - print(type(int(id)), type(organ), type(names), type(date_from), type(date_to), type(ver)) - + for list_argument_bd in list_data: + id, organ, names, date_from, date_to, ver = list_argument_bd + cursor.callproc('P_RK_GOVERNMENT_REPORTS_INSERS', [ int(id), organ, @@ -92,5 +102,6 @@ class SimpleDB: ]) except Error as e: - raise HTTPException(status_code=500, detail=f"Database error: {e}") - + raise Error(f'Ошибка при отправке данных в БД: {e}') + except Exception as e: + raise Error(f'Неожиданная ошибка: {e}')