bablo / стройплощадка
← Все сессии
Дата: 2026-05-20
Часов: 4
Кто:

Work-log: Document workflow — Phase 1 fixes + 4 new features

Date: 2026-05-20
Duration: ~4 hours
Engineer: Claude Code


Что сделано

Fixes по обратной связи Руслана (Phase 1 pilot)

  1. “Body exceeded 1 MB limit” — все загрузки файлов через веб падали с этой ошибкой.
    Корень: Next.js Server Actions имеет дефолтный лимит 1MB.
    Исправление: experimental.serverActions.bodySizeLimit: "25mb" в next.config.ts.

  2. Суммы с запятыми/копейками — поле type="number" не принимает русскую запятую.
    Исправление: type="text" inputMode="decimal" + .replace(",", ".") в parseFloat на бэке (app/lib/actions/contracts.ts).

  3. История поступлений и договоров с удалением — добавлены deleteRevenueEvent и deleteContract server actions, в UI проекта — кнопки удаления с DeleteForm компонентом.

  4. Secure cookie на HTTP — на rigabase без HTTPS кука не устанавливалась.
    Исправление: secure: process.env.APP_URL?.startsWith("https") ?? false вместо NODE_ENV === "production" в app/lib/auth/lucia.ts.

  5. docker-compose порт — изменён 127.0.0.1:3010:3000 на 0.0.0.0:3010:3000 для доступа через IP.

Новые фичи (design spec: docs/superpowers/specs/2026-05-20-document-workflow-design.md)

1. Multi-file upload (веб)

  • Новый компонент app/components/documents/MultiUpload.tsx — клиентский, последовательный upload с прогрессом “Загружаю N из M: filename”.
  • API route app/app/api/documents/upload/route.ts — POST, аутентификация + проверка ownership проекта.
  • Shared logic app/lib/upload/uploadSingle.ts — валидация MIME/размера (20MB), S3 upload, DB insert с rollback (DeleteObjectCommand при ошибке DB).

2. Telegram bot: выбор объекта перед сохранением

  • tg-bot/src/state.ts — in-memory Map с TTL 5 минут.
  • tg-bot/src/handlers/projectSelect.ts — callback_query handler, читает pending из Map, сохраняет в БД с выбранным projectId (или null).
  • tg-bot/src/handlers/file.ts — полный рерайт: загрузка → MinIO → inline keyboard с активными проектами организации + ”📂 Без объекта”.
  • Фоновый sweep каждые 60с: просроченные pending сохраняются с projectId = NULL.

3. Каталог поставщиков (фильтр без объекта)

  • Фильтр-табы в /documents: Все | По объектам | Без объекта через ?filter=all|bound|unbound URL-параметр.
  • Серверная условная query в app/app/(app)/documents/page.tsx.

4. Статусы согласования документов

  • Миграция БД: approval_status enum (pending_review | approved | rejected | paid), колонка в document.
  • StatusButtons.tsx — клиентский компонент с useActionState, badge + контекстные кнопки по состоянию.
  • updateDocumentStatus server action — проверка ownership + state machine переходов.

Файлы затронутые

Новые:

  • app/lib/upload/uploadSingle.ts
  • app/app/api/documents/upload/route.ts
  • app/components/documents/MultiUpload.tsx
  • app/components/documents/StatusButtons.tsx
  • app/components/ui/DeleteForm.tsx
  • app/drizzle/0001_lowly_hellion.sql
  • tg-bot/src/state.ts
  • tg-bot/src/handlers/projectSelect.ts

Изменены:

  • app/next.config.ts
  • app/lib/db/schema.ts
  • app/lib/actions/documents.ts
  • app/lib/actions/contracts.ts
  • app/lib/auth/lucia.ts
  • app/app/(app)/documents/page.tsx
  • app/app/(app)/projects/[id]/page.tsx
  • tg-bot/src/handlers/file.ts
  • tg-bot/src/index.ts
  • docker-compose.yml

Что не сделано / отложено

  • Детальная страница документа со статусом (Phase 2)
  • История переходов статусов (Phase 2)
  • Webhook вместо long-polling для бота (Phase 2)
  • Голосовые сообщения в боте (Phase 2)
  • Telegram bot: кнопки должны автоматически исчезать после выбора (UX-улучшение)

Технические решения

  • In-memory Map для bot state — намеренно, без внешнего Redis, достаточно для Phase 1 с одним пользователем. Принятие: риск потери state при рестарте контейнера приемлем (TTL 5 минут, auto-sweep).
  • Sequential upload — Server Actions не поддерживают промежуточные события прогресса, поэтому клиентский sequential fetch loop.
  • Supplier catalog без нового раздела — фильтр-табы в существующем /documents, минимально достаточно.

Статус деплоя

Все изменения задеплоены на rigabase:

  • bablo-app: Up (healthy), пересобран после всех коммитов
  • bablo-tg-bot: Up (healthy), пересобран после 3d862d1
  • Стройплощадка: передеплоена на Vercel (vercel deploy --prod)