From 2bdc07951ac59562147768ce37a3b2a102374868 Mon Sep 17 00:00:00 2001 From: manoraga Date: Tue, 4 Aug 2026 19:09:31 +0300 Subject: [PATCH] refactor: modular structure, core and services directories --- api/__init__.py | 0 core/__init__.py | 0 frontend/__init__.py | 0 main.py | 20 ++++++------- migrate_structure.py | 62 +++++++++++++++++++++++++++++++++++++++ scripts/__init__.py | 0 services/__init__.py | 0 services/ai_verifier.py | 2 +- services/data_loader.py | 2 +- services/feedback_loop.py | 6 ++-- services/scud_export.py | 2 +- services/text_reporter.py | 4 +-- test.txt | 1 + update_imports.py | 41 ++++++++++++++++++++++++++ 14 files changed, 122 insertions(+), 18 deletions(-) create mode 100644 api/__init__.py create mode 100644 core/__init__.py create mode 100644 frontend/__init__.py create mode 100644 migrate_structure.py create mode 100644 scripts/__init__.py create mode 100644 services/__init__.py create mode 100644 test.txt create mode 100644 update_imports.py diff --git a/api/__init__.py b/api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/core/__init__.py b/core/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/frontend/__init__.py b/frontend/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/main.py b/main.py index e03dac9..87a6c87 100644 --- a/main.py +++ b/main.py @@ -6,16 +6,16 @@ import pandas as pd sys.path.append(os.path.dirname(os.path.abspath(__file__))) from config import DATE_TODAY, DATE_YESTERDAY, OUTPUT_DIR, DATA_DIR, normalize_fio -from modules.scud_export import run_export -from modules.share_copier import copy_1c_files_from_share -from modules.data_validator import check_file_freshness -from modules.data_loader import load_all_data -from modules.excel_exporter import generate_summary_excel, generate_detailed_excel -from modules.ai_verifier import ai_verify_scud_against_staff -from modules.text_reporter import generate_markdown_report -from modules.feedback_loop import review_ai_decisions -from modules.knowledge_base import load_knowledge_base -from modules.database import ( +from services.scud_export import run_export +from services.share_copier import copy_1c_files_from_share +from services.data_validator import check_file_freshness +from services.data_loader import load_all_data +from services.excel_exporter import generate_summary_excel, generate_detailed_excel +from services.ai_verifier import ai_verify_scud_against_staff +from services.text_reporter import generate_markdown_report +from services.feedback_loop import review_ai_decisions +from services.knowledge_base import load_knowledge_base +from core.database import ( init_db, save_scud_to_db, save_staff_to_db, diff --git a/migrate_structure.py b/migrate_structure.py new file mode 100644 index 0000000..a3f9cb3 --- /dev/null +++ b/migrate_structure.py @@ -0,0 +1,62 @@ +import os +import subprocess + +def run_git_move(): + print("=== Безопасная миграция файлов в структуру проекта ===") + + # Словарь: имя файла -> целевая папка + file_mapping = { + "database.py": "core/database.py", + "scud_export.py": "services/scud_export.py", + "share_copier.py": "services/share_copier.py", + "data_loader.py": "services/data_loader.py", + "data_validator.py": "services/data_validator.py", + "zup_extractor.py": "services/zup_extractor.py", + "ai_verifier.py": "services/ai_verifier.py", + "excel_exporter.py": "services/excel_exporter.py", + "text_reporter.py": "services/text_reporter.py", + "feedback_loop.py": "services/feedback_loop.py", + "knowledge_base.py": "services/knowledge_base.py", + "db_cli.py": "scripts/db_cli.py" + } + + # Убедимся, что папки существуют и содержат __init__.py + for folder in ["core", "services", "api", "frontend", "scripts"]: + os.makedirs(folder, exist_ok=True) + init_file = os.path.join(folder, "__init__.py") + if not os.path.exists(init_file): + open(init_file, 'w').close() + + for filename, dest in file_mapping.items(): + # Проверим, где файл может находиться: в корне или уже в папке назначения + if os.path.exists(filename): + src = filename + elif os.path.exists(dest): + print(f"[ℹ️ Уже на месте] {dest}") + continue + else: + # Попробуем поискать файл рекурсивно + found = None + for root, dirs, files in os.walk("."): + if filename in files and "venv" not in root: + found = os.path.join(root, filename) + break + src = found + + if src and os.path.exists(src): + if src == dest: + continue + dest_dir = os.path.dirname(dest) + os.makedirs(dest_dir, exist_ok=True) + try: + subprocess.run(["git", "mv", src, dest], check=True) + print(f"[git mv] Успешно перемещен: {src} -> {dest}") + except subprocess.CalledProcessError as e: + print(f"[⚠️ Ошибка] Не удалось переместить через git mv {src}: {e}") + else: + print(f"[❌ Не найден] Файл {filename} не обнаружен в репозитории.") + + print("\n=== Миграция завершена. Выполните 'git status' для проверки ===") + +if __name__ == "__main__": + run_git_move() \ No newline at end of file diff --git a/scripts/__init__.py b/scripts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/services/__init__.py b/services/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/services/ai_verifier.py b/services/ai_verifier.py index a1441eb..a1f0f79 100644 --- a/services/ai_verifier.py +++ b/services/ai_verifier.py @@ -2,7 +2,7 @@ import json import re import requests from config import OLLAMA_URL, OLLAMA_MODEL -from modules.database import get_all_rules_from_db +from core.database import get_all_rules_from_db def ask_ollama(prompt, system_prompt=None): diff --git a/services/data_loader.py b/services/data_loader.py index 3378002..56ca277 100644 --- a/services/data_loader.py +++ b/services/data_loader.py @@ -6,7 +6,7 @@ from config import ( DATE_TODAY, DATE_YESTERDAY, find_dated_file, ZUP_1C_DIR, SCUD_DIR ) # Импортируем прямую SQL-выгрузку отсутствий из 1С -from modules.zup_extractor import fetch_zup_absences_from_sql +from services.zup_extractor import fetch_zup_absences_from_sql warnings.filterwarnings('ignore', category=UserWarning, module='pandas') diff --git a/services/feedback_loop.py b/services/feedback_loop.py index 83dc612..785fa73 100644 --- a/services/feedback_loop.py +++ b/services/feedback_loop.py @@ -1,12 +1,12 @@ import os import json -from modules.database import add_rule_to_db +from core.database import add_rule_to_db try: - from modules.knowledge_base import save_rule + from services.knowledge_base import save_rule except ImportError: try: - from modules.knowledge_base import add_rule as save_rule + from services.knowledge_base import add_rule as save_rule except ImportError: save_rule = None diff --git a/services/scud_export.py b/services/scud_export.py index 7b726ae..84e21cf 100644 --- a/services/scud_export.py +++ b/services/scud_export.py @@ -16,7 +16,7 @@ import pyodbc from openpyxl.utils import get_column_letter from config import SCUD_DIR, clean_scud_fio_light, load_exceptions -from modules.database import save_scud_to_db +from core.database import save_scud_to_db warnings.filterwarnings("ignore", message="pandas only supports SQLAlchemy connectable") diff --git a/services/text_reporter.py b/services/text_reporter.py index 34b333c..c26e298 100644 --- a/services/text_reporter.py +++ b/services/text_reporter.py @@ -1,8 +1,8 @@ import json import difflib import re -from modules.ai_verifier import ask_ollama -from modules.knowledge_base import load_knowledge_base +from services.ai_verifier import ask_ollama +from services.knowledge_base import load_knowledge_base def find_python_fuzzy_matches(unexplained_df, raw_absent_df): diff --git a/test.txt b/test.txt new file mode 100644 index 0000000..5e6ff73 --- /dev/null +++ b/test.txt @@ -0,0 +1 @@ +122222222222222222222222222222 \ No newline at end of file diff --git a/update_imports.py b/update_imports.py new file mode 100644 index 0000000..17ec348 --- /dev/null +++ b/update_imports.py @@ -0,0 +1,41 @@ +import os + +def update_file_imports(filepath): + with open(filepath, 'r', encoding='utf-8') as f: + content = f.read() + + # Заменяем старые пути на новые + new_content = content + new_content = new_content.replace("from modules.database", "from core.database") + new_content = new_content.replace("import modules.database", "import core.database") + + # Все остальные модули уехали в services/ + service_modules = [ + "ai_verifier", "data_loader", "data_validator", "excel_exporter", + "feedback_loop", "knowledge_base", "scud_export", "share_copier", + "text_reporter", "zup_extractor" + ] + + for mod in service_modules: + new_content = new_content.replace(f"from modules.{mod}", f"from services.{mod}") + new_content = new_content.replace(f"import modules.{mod}", f"import services.{mod}") + # Также на случай относительных или прямых импортов внутри сервисов друг на друга + new_content = new_content.replace(f"from {mod}", f"from services.{mod}") + + if content != new_content: + with open(filepath, 'w', encoding='utf-8') as f: + f.write(new_content) + print(f"[Обновлено] Импорты в файле: {filepath}") + +def run_update(): + print("=== Автоматическое обновление импортов ===") + for root, dirs, files in os.walk("."): + if "venv" in root or ".git" in root: + continue + for file in files: + if file.endswith(".py") and file != "migrate_structure.py" and file != "update_imports.py": + update_file_imports(os.path.join(root, file)) + print("=== Обновление завершено ===") + +if __name__ == "__main__": + run_update() \ No newline at end of file