diff --git a/bot.py b/bot.py index 1856d89..0fb967d 100644 --- a/bot.py +++ b/bot.py @@ -729,6 +729,7 @@ class VKBotApplication: self._baza_started(user_id) db.set_profile_field(user_id, "source", "Основное меню") db.add_metka(user_id, "source_main_menu") + db.set_profile_field(user_id, "lead_recorded", False) # новый заход = новая возможная заявка p = db.get_profile(user_id) if any(p.get(f) for f in ("role", "age", "game", "level")): self.send_message( @@ -954,12 +955,26 @@ class VKBotApplication: self._baza_to_manager(user_id, reason="Нужен совет по формату", client_text="Менеджер скоро подключится к диалогу. Можете дополнить запрос здесь.") + def _baza_record_lead(self, user_id: int): + """Фиксирует заявку в журнале leads (для статистики) — один раз на заход воронки.""" + p = db.get_profile(user_id) + if p.get("lead_recorded"): + return + name = self._vk_name(user_id) or "—" + service = p.get("tariff") or p.get("format") or p.get("game") or "—" + try: + db.add_lead(user_id, source="bot", name=name, phone="", service=service) + db.set_profile_field(user_id, "lead_recorded", True) + except Exception as e: + logger.error(f"Не удалось записать лид в статистику: {e}") + def _baza_send_payment(self, user_id: int, link_key: str, tariff_label: str, campaign: str = "main"): """Показывает ссылку на оплату/запись + кнопки «проблема с оплатой» / «вопрос менеджеру».""" link = self._utm(self._link(link_key), campaign) db.set_profile_field(user_id, "tariff", tariff_label) db.add_metka(user_id, "clicked_payment") db.add_metka(user_id, "lead_hot") + self._baza_record_lead(user_id) db.update_user_state(user_id, "BAZA_PAY") kb = VkKeyboard(inline=True) kb.add_openlink_button("Перейти к оплате 💳", link) @@ -1001,6 +1016,7 @@ class VKBotApplication: db.set_profile_field(user_id, "keyword", "лето") db.set_profile_field(user_id, "interest_summer", True) db.add_metka(user_id, "interest_summer_intensive") + db.set_profile_field(user_id, "lead_recorded", False) # новый заход = новая возможная заявка db.update_user_state(user_id, "BAZA_INT_INFO") self.send_message( user_id, @@ -1179,6 +1195,7 @@ class VKBotApplication: db.add_metka(user_id, "manager_requested") from datetime import datetime db.set_profile_field(user_id, "manager_at", datetime.now().strftime("%Y-%m-%d %H:%M")) + self._baza_record_lead(user_id) card = self._baza_manager_card(user_id, reason) self._notify_operators("💬 Запрос менеджеру\n\n" + card) try: @@ -1413,9 +1430,6 @@ class VKBotApplication: ls = db.get_lead_stats() ds = db.get_dialogue_stats() - total = ls["total"] - marketing_pct = round(ls["marketing_yes"] / total * 100) if total else 0 - service_lines = "" if ls["by_service"]: for svc_name, cnt in ls["by_service"]: @@ -1425,19 +1439,15 @@ class VKBotApplication: msg = ( "📊 Статистика Кибершколы БАЗА\n\n" - "🗂 Заявки (всего): {total}\n" + "🗂 Заявки из бота (всего): {total}\n" " • сегодня: {today}\n" - " • за 7 дней: {last7}\n" - " • из бота: {from_bot}\n\n" - "📨 Согласны на рассылку: {mk_yes} из {total} ({mk_pct}%)\n\n" - "🎮 По направлениям:\n{services}\n" + " • за 7 дней: {last7}\n\n" + "🎯 По выбранному тарифу/формату:\n{services}\n" "💬 Диалоги:\n" " • уникальных пользователей: {uniq}\n" " • сообщений от клиентов: {umsg}" ).format( - total=total, today=ls["today"], last7=ls["last7"], - from_bot=ls["from_bot"], - mk_yes=ls["marketing_yes"], mk_pct=marketing_pct, + total=ls["total"], today=ls["today"], last7=ls["last7"], services=service_lines, uniq=ds["unique_users"], umsg=ds["user_messages"] ) self.send_message(user_id, msg) diff --git a/tests/test_flow.py b/tests/test_flow.py index 724d973..3259571 100644 --- a/tests/test_flow.py +++ b/tests/test_flow.py @@ -62,6 +62,18 @@ def test_baza_other_game_goes_to_manager(app): assert "Valorant" in _prof(u)["game"] +def test_baza_records_lead_once(app): + """Воронка пишет заявку в leads при конверсии; оплата+проблема = 1 заявка (без дублей).""" + u = 70030 + for m in ["Подобрать тренировку 🎯", "Для себя", "16 лет и старше", "CS2", + "Играет для себя", "Групповые тренировки", "Купить 4 тренировки"]: + app.handle_message(u, m) + app.handle_message(u, "Проблема с оплатой") # тот же заход → не должно создать вторую + s = bot.db.get_lead_stats() + assert s["total"] == 1 and s["from_bot"] == 1 + assert any("Групповой" in name for name, _ in s["by_service"]) + + def test_baza_smart_skip_known_fields(app): """§15: уже сохранённые ответы не переспрашиваются.""" u = 70020