""" =============================================================================== FILE: main_etl.py PROJECT: SCUD Orion AI (Unified Architecture) ROLE: Главная CLI-точка входа для запуска ежедневного контроллинга СКУД ⟷ 1С. AI-CONTEXT-ANCHORS: - ANCHOR[MAIN_CLI_ENTRY]: Парсинг CLI-флагов и запуск конвейера. =============================================================================== """ import sys import argparse from datetime import datetime from core.database import init_db, get_latest_snapshot_time from services.share_copier import copy_1c_files_from_share from services.data_validator import check_file_freshness from services.scud_export import run_export from services.scud_etl.pipeline import run_controlling_pipeline # ANCHOR[MAIN_CLI_ENTRY] def main(): help_text = """ Система автоматизированного контроллинга СКУД ⟷ 1С:ЗУП (scud_orion_ai) ПРИМЕРЫ ЗАПУСКА: python main_etl.py -- Обычный дневной запуск python main_etl.py --skip-export -- Расчет отчета по ПОСЛЕДНЕМУ имеющемуся снапшоту из SQLite python main_etl.py --snapshot 20260820-001 -- Расчет отчета строго по ID снапшота python main_etl.py -d -- Запуск в режиме расширенной отладки (DEBUG) """ parser = argparse.ArgumentParser(description=help_text, formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument('-d', '--debug', action='store_true', help="Режим отладки (DEBUG)") parser.add_argument('--skip-export', action='store_true', help="Расчет отчета по последнему снапшоту из SQLite") parser.add_argument('--snapshot', type=str, default=None, help="ID конкретного снапшота") args = parser.parse_args() print("=" * 60) print(f"ЗАПУСК СИСТЕМЫ МОДУЛЬНОГО КОНТРОЛЛИНГА СКУД ⟷ 1С {'[DEBUG MODE]' if args.debug else ''}") print("=" * 60) init_db() # Определение режима работы и вывод статусов if args.snapshot: print(f"[📸] РЕЖИМ СНАПШОТА: Расчет отчета строго по срезу '{args.snapshot}'") elif args.skip_export: last_snap = get_latest_snapshot_time() print(f"[📸] РЕЖИМ --skip-export: Используем последний снапшот из SQLite ('{last_snap}')") else: current_snap = datetime.now().strftime("%Y-%m-%d %H:%M:%S") print(f"[📸] СФОРМИРОВАН НОВЫЙ СНАПШОТ: '{current_snap}'") has_today_1c = True # Прямой экспорт и проверка сетевой шары (если не режим снапшотов) if not args.skip_export and not args.snapshot: try: run_export(save_xlsx=True, debug=args.debug) except Exception as e: print(f"[⚠️] Ошибка автоэкспорта из MS SQL: {e}. Переходим к записям SQLite.") copy_1c_files_from_share() print("[1/5] Проверка актуальности и свежести входных данных...") is_valid, warnings, errors, has_today_1c = check_file_freshness() if warnings: print("\n--- ⚠️ ПРЕДУПРЕЖДЕНИЯ ОБ АКТУАЛЬНОСТИ ---") for w in warnings: print(f" • {w}") print("-" * 45) if not is_valid: print("🛑 ОСТАНОВКА: Отсутствуют критически важные файлы за вчера!") for e in errors: print(f" {e}") sys.exit(1) print("[✓] Проверка доступности данных успешно пройдена!\n") else: print("[0/5] Пропуск прямого экспорта из MS SQL (чтение из базы SQLite)...") print("[1/5] Пропуск проверки сетевой шары (все данные читаются из SQLite)...") # Запуск конвейера run_controlling_pipeline( snapshot_param=args.snapshot, skip_export=args.skip_export, debug=args.debug, has_today_1c=has_today_1c ) if __name__ == "__main__": main()