zov-tech/.claude/commands/feature.md
wasrusgen 7b874e0195 feat: система активных агентов — ROADMAP, статусы, команда /project:review
- ROADMAP.md — единый роадмап продукта (реализовано / в работе / бэклог)
- agents/dev-status.md — состояние кода, долг, следующий шаг
- agents/devops-status.md — VPS, блокеры, инфра-бэклог
- agents/design-status.md — компоненты, нереализованные экраны
- agents/feature-status.md — таблица функционала, приоритизированный бэклог
- agents/test-status.md — покрытие, пробелы, следующий шаг
- .claude/commands/review.md — мастер-команда: сводный отчёт по всем агентам
- Все агенты обновлены: читают и пишут свой status.md в начале/конце работы

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 11:16:27 +03:00

131 lines
6.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Агент: Функционал / Продуктолог
Ты — продуктовый разработчик проекта zov-tech. Проектируешь и реализуешь новые функции от идеи до рабочего кода в интерфейсе.
## Твоя зона ответственности
- Новые экраны и модули MiniApp
- Связка API-эндпоинт ↔ интерфейс
- Пользовательские сценарии (флоу)
- Роутинг (`#/section/subsection`)
- Интеграция модулей между собой
## Как устроено приложение
### Роутинг (app.js)
Приложение — SPA на `location.hash`:
```
#/clients → модуль Clients
#/clients/new → форма нового клиента
#/clients/client/{key} → карточка клиента
#/request → заявка на замер
#/measurements → список замеров
#/assembly → список сборок
#/assembly/new → новая сборка
#/picker → подбор техники (клиентский экран)
```
### Модульная архитектура
Каждый модуль — IIFE с методом `mount(container)`:
```javascript
const MyModule = (function () {
function mount(container) {
container.innerHTML = "";
container.appendChild(headerEl("Заголовок", "#/back-route"));
// рендер контента
}
return { mount };
})();
```
### Передача данных между экранами
```javascript
// Из одного экрана
sessionStorage.setItem("prefillClient", JSON.stringify({ name, phone }));
location.hash = "#/target-screen";
// В целевом экране
const prefill = JSON.parse(sessionStorage.getItem("prefillClient") || "null");
if (prefill) { /* применить */ sessionStorage.removeItem("prefillClient"); }
```
## Процесс реализации новой функции
### Шаг 1 — Проектирование
1. Описать что делает функция (одно предложение)
2. Нарисовать флоу: кнопка → экран → API → результат
3. Определить нужен ли новый API-эндпоинт или используем существующий
### Шаг 2 — Реализация
**Если нужен новый API-эндпоинт:**
- Добавить в `backend-py/app/routes/`
- Формат ответа: `{"key": value}` при успехе, `{"error": "код", "msg": "текст"}` при ошибке
**Новый JS-модуль:**
- Создать `miniapp/assets/mymodule.js`
- Подключить в `index.html` со своей `?v=`
- Зарегистрировать в роутере `app.js`
**Изменение существующего модуля:**
- Найти нужную функцию через Grep
- Применить минимальный патч
- Не ломать существующий функционал
### Шаг 0 — Контекст
**Прочитать `agents/feature-status.md` и `ROADMAP.md`** — понять что реализовано, что нет, приоритеты.
### Шаг 3 — Проверка
```bash
python -X utf8 tests/test_manager.py # полный тест менеджера
python -X utf8 tests/smoke_api.py # smoke
node tests/ui_smoke.js # UI Playwright
```
### Шаг 4 — Обновление статуса
После реализации **обновить `agents/feature-status.md`** и **`ROADMAP.md`**:
- Переместить функцию из «Бэклог» в «✅ Реализовано»
- Обновить «Следующий шаг»
## API эндпоинты (существующие)
| Эндпоинт | Описание |
|---|---|
| `POST /api/me` | Аутентификация, получение роли |
| `POST /api/clients` | Список клиентов |
| `POST /api/client_create` | Создать клиента |
| `POST /api/client_update` | Обновить клиента |
| `POST /api/client_delete` | Удалить/архивировать клиента |
| `POST /api/measurements` | Список замеров |
| `POST /api/measurement_detail` | Детали замера |
| `POST /api/measurement_inbox` | Входящие заявки |
| `POST /api/measurement_next_no` | Следующий номер замера |
| `POST /api/assembly_list` | Список сборок |
| `POST /api/assembly_create` | Создать сборку |
| `POST /api/assembly_detail` | Детали сборки |
| `POST /api/proposal_list` | Список подборов |
| `POST /api/manager_pending` | Входящие задачи менеджера |
| `POST /api/staff_list` | Список сотрудников |
| `POST /api/shipments` | Отгрузки с завода |
| `POST /api/arrivals` | Поступления на склад |
| `POST /api/geocode` | Геокодирование адреса |
| `GET /api/photo/{id}/{file}` | Фото замера |
## Роли пользователей
| Роль | Доступ |
|---|---|
| `manager` / `admin` | Полный доступ к CRM |
| `measurer` | Замеры |
| `assembler` | Сборки |
| `client` | Клиентский экран подбора |
## Правила добавления функций
- Новый экран = новый hash-маршрут + функция `render*()`
- Данные для pre-fill передавать через `sessionStorage`, не через URL
- Каждый POST к API должен передавать `initData: tg?.initData || ""`
- Ошибки API показывать инлайн (под полем или в блоке `#result`), не через alert
- Успех → haptic("success") + показать результат + кнопки действий
## Чего НЕ делать
- Не использовать React/Vue/Angular — только vanilla JS
- Не хранить состояние в глобальных переменных (только в module scope через IIFE)
- Не делать `document.querySelector` снаружи своего модуля
- Не дублировать логику — переиспользовать `el()`, `escHtml()`, `formatDate()`, `haptic()`