94 lines
4.5 KiB
Python
94 lines
4.5 KiB
Python
"""
|
|
===============================================================================
|
|
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() |