Files
vk-sales-bot/core/exporter.py
T

76 lines
3.3 KiB
Python

import pandas as pd
from pathlib import Path
from filelock import FileLock
from datetime import datetime
from loguru import logger
from core.models import LeadData
from config import settings
import shutil
class ExcelExporter:
def __init__(self, file_path: Path):
self.file_path = file_path
self.lock_path = file_path.with_suffix('.lock')
self._init_file()
def _init_file(self):
"""Создаёт файл с заголовками, если не существует"""
if not self.file_path.exists():
df = pd.DataFrame(columns=[
"timestamp", "user_id", "full_name", "phone",
"preferred_time", "status", "consent_given",
"parent_full_name", "parent_phone"
])
df.to_excel(self.file_path, index=False, engine='openpyxl')
def save_lead(self, lead: LeadData):
"""Атомарная дозапись с блокировкой"""
lock = FileLock(self.lock_path)
with lock:
try:
# Читаем существующий DataFrame
df = pd.read_excel(self.file_path, engine='openpyxl')
# Добавляем новую строку
new_row = pd.DataFrame([{
"timestamp": lead.timestamp,
"user_id": lead.user_id,
"full_name": lead.full_name,
"phone": lead.phone,
"preferred_time": lead.preferred_time,
"status": lead.status,
"consent_given": lead.consent_given,
"parent_full_name": lead.parent_full_name,
"parent_phone": lead.parent_phone
}])
df = pd.concat([df, new_row], ignore_index=True)
# Записываем обратно
df.to_excel(self.file_path, index=False, engine='openpyxl')
logger.info(f"Lead saved for user {lead.user_id}")
except Exception as e:
logger.error(f"Failed to save lead: {e}")
raise
def backup(self):
"""Создаёт копию файла с меткой времени"""
if self.file_path.exists():
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
backup_path = settings.BACKUP_DIR / f"leads_backup_{timestamp}.xlsx"
shutil.copy2(self.file_path, backup_path)
logger.info(f"Backup created: {backup_path}")
def get_stats(self) -> dict:
"""Возвращает статистику по лидам"""
if not self.file_path.exists():
return {"total": 0, "today": 0, "statuses": {}}
df = pd.read_excel(self.file_path, engine='openpyxl')
total = len(df)
today = len(df[pd.to_datetime(df['timestamp']).dt.date == datetime.now().date()])
statuses = df['status'].value_counts().to_dict()
return {"total": total, "today": today, "statuses": statuses}
def export(self, target_path: Path = None):
"""Принудительный экспорт (копия)"""
if target_path is None:
target_path = settings.DATA_DIR / f"export_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx"
shutil.copy2(self.file_path, target_path)
return target_path