Skip to content

Настройка Google Sheets

Dinary server хранит runtime-данные в локальной SQLite-базе, а не в Google Sheets. В пользовательской и админской эксплуатации Google Sheets нужны только для опционального append-only sheet logging. Для работы нужен сервисный аккаунт Google и таблица, расшаренная на него.

1. Создание проекта Google Cloud

  1. Перейдите на console.cloud.google.com.
  2. Нажмите Выберите проектНовый проект → назовите его (например, dinary) → Создать.
  3. Выберите созданный проект.

2. Включение необходимых API

  1. Перейдите в APIs & ServicesLibrary.
  2. Найдите Google Sheets API → нажмите → Enable.
  3. Вернитесь в Library, найдите Google Drive API → нажмите → Enable.

3. Создание сервисного аккаунта

  1. Перейдите в APIs & ServicesCredentialsCreate CredentialsService account.
  2. Заполните:
    • Name: dinary (или любое имя)
    • ID: генерируется автоматически
  3. Нажмите Create and Continue → пропустите необязательные шаги → Done.

4. Скачивание JSON-ключа

  1. В разделе Credentials нажмите на созданный сервисный аккаунт.
  2. Перейдите в KeysAdd KeyCreate new keyJSONCreate.
  3. Сохраните скачанный файл как ~/.config/gspread/service_account.json:
mkdir -p ~/.config/gspread
mv ~/Downloads/your-project-*.json ~/.config/gspread/service_account.json

Warning

Храните этот файл в секрете. Никогда не коммитьте его в Git — он уже добавлен в .gitignore.

5. Создание и расшаривание таблицы

  1. Перейдите на sheets.google.com → создайте новую таблицу.
  2. Назовите её (например, Dinary Expenses).
  3. Скопируйте ID таблицы из URL: https://docs.google.com/spreadsheets/d/<SPREADSHEET_ID>/edit.
  4. Нажмите Поделиться → вставьте email сервисного аккаунта (из JSON-ключа, поле client_email, вида dinary@project-id.iam.gserviceaccount.com) → роль РедакторОтправить.

6. Настройка dinary

Runtime-настройки Google Sheets живут в .deploy/.env (переменные окружения):

Переменная Значение
DINARY_GOOGLE_SHEETS_CREDENTIALS_PATH путь к service_account.json (по умолчанию: ~/.config/gspread/service_account.json)
DINARY_SHEET_LOGGING_SPREADSHEET опциональный ID или URL таблицы для append-only логгинга runtime-расходов (см. ниже)

7. Логгинг в таблицу (опционально)

Sheet logging автоматически добавляет каждый новый расход в Google Sheets в реальном времени. Это удобно, если вы хотите строить сводные таблицы или графики в Google Sheets параллельно со встроенной аналитикой Dinary.

Как это работает

  • Каждый POST /api/expenses добавляет строку в первый лист указанной таблицы.
  • 3D-категория/событие/теги проецируются в 2D (sheet_category, sheet_group) через таблицу logging_mapping. Если маппинг для категории не найден, название категории используется как fallback.
  • Один и тот же лист может хранить несколько лет одновременно. Строки сортируются по (год, месяц, sheet_category, sheet_group), новые блоки (год, месяц) уходят наверх. Год берётся из реального значения колонки A (Google показывает её как, например, Apr-1, но хранит 2026-04-01), поэтому январь 2026 и январь 2027 не путаются между собой.
  • В колонке J каждой добавленной строки лежит непрозрачный маркер [exp:<expense_id>]. Если предыдущая попытка добавления для того же расхода уже дошла до Google, но ответ был потерян (тайм-аут), следующая попытка увидит маркер и пропустит дублирующую запись.
  • Если запись не удалась (ошибка сети, квота), задание остаётся в очереди и повторяется автоматически встроенным периодическим drain'ом (раз в DINARY_SHEET_LOGGING_DRAIN_INTERVAL_SEC секунд, по умолчанию 300; 0 отключает периодический drain).

Включение

Установите DINARY_SHEET_LOGGING_SPREADSHEET — ID таблицы или полный URL из браузера:

# Просто ID таблицы:
DINARY_SHEET_LOGGING_SPREADSHEET=YOUR_SPREADSHEET_ID_HERE

# Или полный URL (ID извлекается автоматически):
DINARY_SHEET_LOGGING_SPREADSHEET=https://docs.google.com/spreadsheets/d/YOUR_SPREADSHEET_ID_HERE/edit

Таблица должна быть расшарена с сервисным аккаунтом из шага 4 (роль «Редактор»).

Отключение

Оставьте DINARY_SHEET_LOGGING_SPREADSHEET пустой или не задавайте. Расходы по-прежнему сохраняются в SQLite; пропускается только запись в Google Sheets.

Повторы автоматические

Отложенные задания обрабатываются автоматически встроенным периодическим drain-таском внутри процесса FastAPI. При запуске сервера все накопленные задания обрабатываются сразу; после этого drain повторяется каждые DINARY_SHEET_LOGGING_DRAIN_INTERVAL_SEC секунд (по умолчанию 300). Внешней CLI-команды для запуска нет — восстановление полностью автоматическое.

Ограничение скорости. За одну итерацию drain обрабатывает не более DINARY_SHEET_LOGGING_DRAIN_MAX_ATTEMPTS_PER_ITERATION строк (по умолчанию 15) с паузой DINARY_SHEET_LOGGING_DRAIN_INTER_ROW_DELAY_SEC секунд между попытками (по умолчанию 1.0). Одна попытка делает 1-3 вызова Google Sheets API (чтение маркера идемпотентности, при необходимости append, при необходимости очистка дубликата), поэтому установившийся темп обращений — от ~3 до ~9 вызовов в минуту, что комфортно укладывается в квоту 60/min на пользователя. Очередь из 60 записей после рестарта разбирается примерно за 20 минут; 1000 записей — несколько часов. Повышайте cap только если уверены в запасе по квотам Sheets API.

TTL. Записи для расходов старше DINARY_SHEET_LOGGING_DRAIN_MAX_AGE_DAYS дней (по умолчанию 90) молча пропускаются и остаются в sheet_logging_jobs. Чтобы записать старый расход в таблицу вручную, пересоздайте его или удалите соответствующую строку из очереди через CLI sqlite3 при остановленном сервере.

Warning

Внешней CLI-команды для обработки очереди при работающем сервере нет. SQLite разрешает одновременно только одного писателя на файл, поэтому внешний drainer пришлось бы координировать с остановкой сервера. Lifespan-таск — единственный поддерживаемый recovery-путь.