📄 ГЕНЕРАЛЬНЫЙ ТЕХНИЧЕСКИЙ МАНИФЕСТ АРХИТЕКТУРЫ BALLOON CRM v50.0
ОФИЦИАЛЬНЫЙ СТАТУС: ВЫПУСК SaaS ОБНОВЛЕНИЯ «MULTI-TENANT СИНХРОНИЗАЦИЯ»
Инструкция для разработчика и ИИ: Данный манифест содержит исчерпывающее, плотное и финальное описание логики, структуры базы данных, интерфейса и сквозных протоколов безопасности платформы Balloon CRM после масштабного обновления v50.0. Манифест полностью заменяет и отменяет версии v40.0 и v49.0. Загружайте этот текст в память при старте любой новой сессии разработки для мгновенной синхронизации контекста и исключения архитектурных ошибок.1. Архитектурная концепция и Принцип SaaS-изоляции (Multi-Tenant)
Balloon CRM — это высокопроизводительная Multi-tenant CRM-система для студий аэродизайна и праздничного декора. Платформа спроектирована по принципу No-Server / No-SQL / No-Library Architecture. Это полностью исключает расходы на сторонние базы данных, а также полностью ликвидирует использование старых нестабильных Google-библиотек (таких как BalloonCore), которые ранее требовали ручного добавления и ломали права доступа у клиентов.
- Фронтенд (Клиентский интерфейс): Моностраничное приложение (SPA), развернутое на базе конструктора Tilda (Custom HTML/CSS/JS в блоках T123). Отвечает за рендеринг, калькулятор, живую фильтрацию, постраничную пагинацию и хранение состояния сессии в памяти устройства.
- Бэкенд (Ядро платформы): Скрипт Google Apps Script (baza.gs), развернутый как единое независимое веб-приложение (Web App) с правами запуска от имени Администратора платформы и доступом Anyone, even anonymous. Выступает в роли API-шлюза, диспетчера контекстов и фонового робота-рассыльщика.
- Изолированная база данных (Tenant DB): В качестве хранилища данных каждого клиента выступает его индивидуальная копия Google Таблицы. Клиенты физически изолированы друг от друга на уровне файлов и никогда не имеют доступа к чужим записям.
2. Схема работы и Протокол обмена данными (JSONP / POST)
Обмен данными между Tilda (Клиент) и Google Cloud (Бэкенд) реализован по двухвекторной схеме в зависимости от типа операции:
[ Tilda Фронтенд (Интерфейс) ] │ ├─► (GET / JSONP API) ──► [ Apps Script Ядро ] ──► Чтение [ Мастер-Таблица ] │ (Вычисление Sheet ID, Роли, Триала) │ ▼ │◄─── (Пакет данных CRM) ◄───────────────────────── Чтение [ Таблица Клиента ] │ └─► (POST / Raw API) ───► [ Apps Script Ядро ] ──► Запись [ Таблица Клиента ] (Сохранение, SaaS-Регистрация)
А. Чтение данных, Авторизация и Фиксация сессии (JSONP)
- Авторизация и Фоновый запуск: Фронтенд Tilda динамически генерирует на странице тег <script> с параметрами авторизации. Функция checkSavedSession() при загрузке страницы проверяет все варианты ключей в памяти браузера (sheetId, balloon_sheet_id, crm_sheet_id), дублирует их параметры, защищая сессию от внезапных сбросов и вылетов при обновлении страницы.
- Метод doGet(e) в Ядре: Принимает запрос, открывает защищенную Мастер-Таблицу управления (MASTER_CONTROL_ID) на листе «Пользователи» и сверяет пару логин/пароль.
- Контроль подписки и Триал-периода: Ядро автоматически считывает дату окончания триала/подписки. Если текущая дата превышает заданную, или статус аккаунта изменен на заблокированный, фронтенд Tilda мгновенно стирает интерфейс CRM и выводит белую заглушку с кнопкой «Продлить доступ через WhatsApp».
- Сброс кэша Google: Перед выгрузкой данных Ядро принудительно вызывает команду SpreadsheetApp.flush(), что заставляет сервера Google сбрасывать внутренний кэш (V8 Engine) и гарантирует моментальное появление в CRM тех заказов, которые менеджер внес в таблицу вручную.
- Фикс Ролей и Передача данных: Сервер считывает из Мастера точную роль пользователя (owner / staff) и имя компании, собирает все сделки и упаковывает их в единый JSON-пакет. JSON оборачивается в вызов callback-функции и отдается браузеру. Блок фикса ролей на Tilda считывает эти параметры и открывает полные права Владельца только для роли owner, активируя вкладки Команды, Аналитики и Расходов.
Б. Запись данных (Классический POST-шлюз и Сетевой Мост)
Любые операции изменения данных выполняются фронтендом Tilda через асинктронные POST-запросы. Метод doPost(e) в Ядре выступает единой точкой распределения потоков:
- Сценарий SaaS-регистрации (action === "register"): Ядро на лету берет идеальную таблицу-шаблон (донор) по её ID, делает независимый дубликат на Google Диске, бесшумно выдает новому пользователю права редактора через Drive.Permissions.create (Drive API v3) со строгим отключением встроенных уведомлений (sendNotificationEmail: false), исключая генерацию серых системных писем от роботов Google Диска. Строка нового клиента записывается в Мастер-Таблицу со статусом письма PENDING.
- Сценарий калькулятора (action === "get_sidebar"): Когда клиент в своей личной таблице выбирает верхнее меню 🛠 CRM Платформа ➔ 🎈 Открыть Калькулятор, таблица через Сетевой Мост (callSaaSMethod) обращается к Ядру. Ядро считывает локальный файл Sidebar.html, передает его текст по сети, и у клиента в таблице разворачивается оригинальный калькулятор. Сам код калькулятора при этом надежно защищен от копирования внутри вашего Ядра.
- Сценарий импорта YML Tilda (action === "update_tilda_export"): Таблица клиента отправляет свой ID, Ядро перехватывает его через объект checkData.sheetId, скачивает XML-дерево товаров с сайта Tilda и за 1 секунду обновляет лист Связка Tilda.
- Сценарий сохранения заказа (action === "save_deal"): Отрабатывает оригинальный код сохранения чеков и расходов напрямую в личную таблицу клиента. Кнопка сохранения на Tilda блокируется от повторных кликов (disabled = true) во избежание дублирования данных, а скролл страницы намертво фиксируется переменной window.saveScrollPos, предотвращая дергание экрана.
В. Фоновый робот-рассыльщик писем
Раз в минуту по независимому временному триггеру Google Apps Script просыпается автономная функция crmBackgroundMailSender. Она сканирует Мастер-Таблицу, находит новые записи со статусом PENDING, отправляет от вашего имени красивое брендовое HTML-письмо через GmailApp (включающее персональную ссылку на созданную копию таблицы, логин, пароль, дату триала и ссылки на видеоинструкции) и переключает статус в Мастере на SENT.
3. Структура Базы Данных Клиента (Спецификация Таблицы)
Личная таблица каждого пользователя является строго структурированной реляционной СУБД и содержит следующие зарезервированные листы:
🟢 Лист 1: база_crm (Реестр сделок — Строго 23 колонки)
Каждая строка — это отдельный заказ. Смещение или удаление колонок запрещено:
- A (1): ID заказа (Уникальный хэш-код: буква B + 6 случайных цифр, например B513038).
- B (2): Дата создания заявки (Записывается сервером автоматически в формате Date()).
- C (3): Имя клиента.
- D (4): Номер телефона (В сыром формате текста, например +79241292216).
- E (5): Текущий статус воронки продаж (Текст).
- F (6): Тип/Событие праздника (Например: День рождения, Выпускной).
- G (7): Дата проведения праздника.
- H (8): Дата доставки заказа (Системный формат ГГГГ-ММ-ДД).
- I (9): Время доставки (Строго текстовый формат @, например 12:00 или в течение дня).
- J (10): Текстовый состав шаров и услуг (Сгенерированный Калькулятором прайс-листа).
- K (11): Комментарий / Детали заказа.
- L (12): Точный адрес доставки.
- M (13): Стоимость состава шаров (Число, до скидки и доставки).
- N (14): Процент скидки (Число в формате формата #).
- O (15): Стоимость доставки (Число).
- P (16): Итоговая сумма к оплате (Рассчитывается сервером: Состав - Скидка + Доставка).
- Q (17): Фактически внесенная предоплата / Касса (Число).
- R (18): Финансовый остаток долга (Математическая дебиторка: Итого - Предоплата).
- S (19): Логин менеджера, оформившего или изменившего сделку.
- T (20): Стек URL-ссылок на вложенные файлы/чеки, загруженные на Диск (Строка через запятую).
- U (21): Канал привлечения трафика (Маркетинг-источник, например ВКонтакте, Инстаграм).
- V (22): Кастомная пометка / Тег (Бейдж карточки, например Срочно, VIP).
- W (23): Уникальный текстовый ID события внутри личного Google Календаря логистики курьеров.
🟡 Остальные зарезервированные листы таблицы:
- Товары: Прайс-лист студии. Колонка A — Наименование, B — Цена. Если ячейка цены пустая, строка парсится системой как Заголовок Категории (Папка аккордеона калькулятора на Tilda).
- Статусы: Справочник этапов и правил воронки: Название | В реализации (ДА/НЕТ) | В оборот (ДА/НЕТ) | В дебиторку (ДА/НЕТ).
- Каналы: Линейный список источников рекламы. В случае отсутствия или задержки данных с бэкенда, фронтенд Tilda автоматически подставляет защищенный базовый список из 5 главных каналов (ВКонтакте, WhatsApp, Instagram, Сайт Tilda, Рекомендация).
- реестр_платежей: Финансовый лог входящего потока денег. Строка дописывается автоматически, только если при сохранении заказа текущая предоплата (Q) превысила старое значение из этой ячейки.
- расходы: Журнал операционных трат компании: Дата | Статья трат | Сумма.
- Настройки: Служебные параметры. Ячейка F2 строго зарезервирована под хранение ID личной папки Google Диска владельца, куда скрипты загружают картинки. Папка создается в облаке самого клиента при первом клике на меню «Настроить личный Диск», полностью исключая расход свободного места на диске Администратора платформы.
4. Логика Интерфейса и Валидация Инпутов (Фронтенд Tilda)
Интерфейс спроектирован как реактивное веб-приложение (SPA), оперирующее глобальным кэшем состояния window.st.
- Алгоритм живого поиска: Строки поиска на вкладках работают на лету по событию oninput. Поиск по заказам сканирует массив ОЗУ одновременно по 4 индексам: ID сделки, имя клиента, состав шаров и цифры телефона. Поиск по клиентам сужает базу по имени и номеру телефона, автоматически очищая запросы от пробелов и скобок.
- Динамическая фильтрация дат и Кнопка сброса: Фильтр календарей «с ... по ...» переведен на дату создания сделки (date_created). Контейнер фильтров снабжен адаптивным CSS-свойством display: flex; flex-wrap: wrap; gap: 8px;. На ПК элементы стоят в одну линию, на смартфонах кнопка сброса аккуратно смещается на следующую строку, занимая полную ширину. Фирменная интерактивная кнопка 🧹 Сбросить все фильтры и поиск (с эффектом Hover и легким фоном) стирает буквы из поиска, очищает календари и возвращает общую ленту за весь период.
- Динамический пересчет табов и Изоляция: При выборе диапазона дат на календарях счетчики на кнопках этапов воронки автоматически пересчитываются прямо на экране. Кнопка «Все заказы (Х)» жестко изолирована от внутренних статусных переключений: она выступает стабильным якорем и всегда отображает суммарное количество сделок за выбранный период.
- Умная валидация полей бланка: При открытии бланка создания заказа числовые поля (Скидка, Доставка, Предоплата) автоматически очищаются от системных нулей при клике, избавляя менеджера от необходимости стирать 0 вручную. Поле времени доставки по умолчанию пустое, исключая ложные дефолтные значения 12:00.
- Форматирование дат (ДД.ММ.ГГГГ): На стороне Tilda развернута функция-транслятор window.formatCrmDateToRu. Все системные даты формата ISO (2026-06-05), прилетающие из таблиц, на лету конвертируются в привычный вид через точки (05.06.2026) на превью карточки, внутри бланка редактирования и в истории клиента.
- Кликабельная история LTV покупателей: Вкладка «Клиенты» выводит профили, группируя их по телефонам, и рассчитывает сквозную сумму LTV. При нажатии «Все заказы» раскрывается история прошлых праздников. Каждая строчка старого заказа кликабельна и привязана к триггеру window.editDealInline(row_num), который переключает вкладку интерфейса на Форму и открывает этот заказ на редактирование.
- Динамический расчет остатка долга (Дебиторки): Инпут остатка долга привязан к выпадающему списку Статусов. Когда менеджер выбирает статус, скрипт проверяет его настройки в матрице правил из Excel. Если у выбранного статуса флаг «В дебиторку» равен НЕТ (например, этапы «Отказ» или «Не целевой»), поле «Остаток долга» на экране автоматически обнуляется, предотвращая раздувание ложной дебиторской задолженности студии.
- Модернизация вкладки «Расходы»: Расходы группируются по раскрывающимся блокам-аккордеонам месяцев (например, «Июнь 2026»), в заголовке каждого выводится общая сумма трат. Наверху вкладки размещен компактный календарь одного дня. При выборе конкретного дня аккордеоны скрываются, и система выводит детальный список трат строго за эти 24 часа.
- Интерактивный переход из Аналитики к должникам: Внутри блока Дебиторки на вкладке «Аналитика» размещена кликабельная подпись [ Посмотреть должников ]. При клике на неё скрипт сам переключает вкладку интерфейса на «Заказы» и принудительно активирует таб «Задолженности», отсекая всех, кто оплатил.
- Связь через официальный API WhatsApp: Все ссылки чатов и триггеры отправки состава шаров переведены на международный URL-шлюз https://whatsapp.com. Номер телефона перед отправкой принудительно очищается от масок, регулярных выражений, а первая цифра 8 автоматически заменяется на международную 7.
5. Логика Безопасности и Прав Доступа (SaaS Security)
- Изоляция Ролей (owner / staff): Разграничение прав выполняется силами фронтенда Tilda на базе роли текущей сессии (window.st.role). Для линейных менеджеров (staff) вкладки Расходов, Финансовой Аналитики и блок управления сотрудниками в Профиле полностью вырезаются из DOM-дерева страницы. Интерфейс админки рендерится на экране только для роли owner. Для главного логина системы admin права Владельца выдаются принудительно на уровне Ядра.
- Защита кнопок от залипания кликов: Все кнопки отправки транзакций в Excel («Сохранить изменения», «Записать статус» и т.д.) снабжены механикой моментальной блокировки. При первом клике кнопка переводится в статус disabled = true, окрашивается в серый цвет и меняет текст на ⏳ Секунду, сохраняю.... Это полностью исключает создание дублирующих строк из-за повторных кликов пользователя.
- Сохранение фокуса вкладок: При клике на любое верхнее меню имя активного таба сохраняется в память браузера (localStorage.setItem('active_crm_tab', tabName)). При принудительной перезагрузке страницы после сохранения данных система автоматически открывает ту вкладку, на которой находился пользователь, предотвращая сброс фокуса на вкладку «Заказы».
- Защита воронки от "заказов-сирот": При попытке удалить кастомный статус из таблицы в Профиле, JS-код сканирует текущий массив сделок в ОЗУ. Если в удаляемой группе находится хотя бы один активный заказ, удаление жестко блокируется алертом: «🛑 БЛОКИРОВКА УДАЛЕНИЯ ЭТАПА! В статусе сейчас находится заказов: Х шт...», предотвращая потерю контроля над сделками.
Контекст обновления v50.0 запечатан, архитектура зафиксирована в памяти.
👤 Модуль №4: Интеграция быстрого добавления контактов на Tilda
SaaS-инфраструктура платформы полностью описана, зафиксирована и работает. Теперь мы переходим к реализации первой крупной фичи из нашего бэклога — Модулю №4. Нам нужно добавить кнопку «+ Добавить клиента» во вкладку «Клиенты» на Tilda и связать её со всплывающим окном.
Давайте определимся с типом отображения формы:
- Вариант А: Делаем её в виде красивого всплывающего модального окна поверх списка клиентов.
- Вариант Б: Закрепляем её постоянным аккуратным блоком полей ввода в самом верху вкладки «Клиенты».
Напишите, какой вариант интерфейса выбираем, и я пришлю готовый код разметки для интеграции на Tilda!