Initial commit MKD fixes
This commit is contained in:
224
docs/DEVELOPMENT_PIPELINE_AUTOMATION.md
Executable file
224
docs/DEVELOPMENT_PIPELINE_AUTOMATION.md
Executable file
@@ -0,0 +1,224 @@
|
||||
# Архитектура автоматизации воронки развития
|
||||
|
||||
## Обзор
|
||||
Воронка развития должна автоматически управлять жизненным циклом потенциальных объектов от момента обнаружения до передачи в управление.
|
||||
|
||||
## Источники данных для воронки
|
||||
|
||||
### 1. Ручное добавление (реализовано)
|
||||
- Менеджер вручную добавляет объект через форму
|
||||
- Статус: `analysis` (по умолчанию)
|
||||
|
||||
### 2. Импорт из файлов (CSV/Excel)
|
||||
- Массовый импорт объектов из внешних источников
|
||||
- Парсинг адресов, характеристик, контактов
|
||||
- Автоматическое создание записей в воронке
|
||||
|
||||
### 3. Интеграция с внешними API
|
||||
- Парсинг публичных реестров (Росреестр, ГИС ЖКХ)
|
||||
- Мониторинг сайтов конкурентов
|
||||
- Интеграция с CRM системами
|
||||
|
||||
### 4. Автоматическое обнаружение
|
||||
- Анализ отзывов жильцов (модуль PR)
|
||||
- Выявление недовольства текущей УК
|
||||
- Мониторинг социальных сетей и форумов
|
||||
|
||||
## Автоматическое перемещение по стадиям
|
||||
|
||||
### Стадии воронки:
|
||||
1. **analysis** (Анализ) - начальная стадия
|
||||
2. **negotiation** (Переговоры) - активная работа с собственниками
|
||||
3. **preparation** (Подготовка) - подготовка к ОСС
|
||||
4. **voting** (Голосование) - идет ОСС
|
||||
5. **transfer** (Передача) - объект передан в управление
|
||||
|
||||
### Правила автоматического перехода:
|
||||
|
||||
#### 1. Analysis → Negotiation
|
||||
**Триггеры:**
|
||||
- Probability >= 30% (автоматически)
|
||||
- Создана маркетинговая активность для объекта
|
||||
- Проведена первая встреча с активистами
|
||||
|
||||
**Условия:**
|
||||
- Минимум 3 контакта с собственниками
|
||||
- Наличие хотя бы 1 активиста
|
||||
|
||||
#### 2. Negotiation → Preparation
|
||||
**Триггеры:**
|
||||
- Probability >= 60%
|
||||
- Собрано >= 5 активистов
|
||||
- Проведено >= 3 встреч
|
||||
|
||||
**Условия:**
|
||||
- Технический аудит завершен
|
||||
- Подготовлен проект договора управления
|
||||
|
||||
#### 3. Preparation → Voting
|
||||
**Триггеры:**
|
||||
- Создано ОСС для объекта (автоматически)
|
||||
- Probability >= 70%
|
||||
|
||||
**Условия:**
|
||||
- ОСС создано и запланировано
|
||||
- Подготовлены все документы
|
||||
|
||||
#### 4. Voting → Transfer
|
||||
**Триггеры:**
|
||||
- ОСС завершено успешно (quorum > 50%, решение "за")
|
||||
- Probability >= 90%
|
||||
|
||||
**Условия:**
|
||||
- ОСС статус = 'completed'
|
||||
- Результат голосования положительный
|
||||
|
||||
#### 5. Откат стадий
|
||||
**Negotiation → Analysis:**
|
||||
- Нет активности > 30 дней
|
||||
- Probability < 20%
|
||||
|
||||
**Preparation → Negotiation:**
|
||||
- ОСС отменено
|
||||
- Probability < 50%
|
||||
|
||||
## Автоматический расчет probability
|
||||
|
||||
### Формула расчета:
|
||||
```
|
||||
probability = baseProbability +
|
||||
(activistsCount * 5) +
|
||||
(meetingsHeld * 3) +
|
||||
(adsDistributed / 10) +
|
||||
(auditScore * 0.2) -
|
||||
(daysInactive * 0.5)
|
||||
```
|
||||
|
||||
Где:
|
||||
- `baseProbability` = 20% (для новых объектов)
|
||||
- `activistsCount` = количество активистов (макс 10)
|
||||
- `meetingsHeld` = количество встреч (макс 10)
|
||||
- `adsDistributed` = количество розданных листовок (макс 500)
|
||||
- `auditScore` = оценка технического аудита (0-100)
|
||||
- `daysInactive` = дней без активности (макс 60)
|
||||
|
||||
### Обновление probability:
|
||||
- При каждом изменении маркетинговых метрик
|
||||
- При завершении технического аудита
|
||||
- Ежедневно (cron job) для пересчета по времени
|
||||
|
||||
## События и триггеры
|
||||
|
||||
### 1. Создание ОСС
|
||||
```sql
|
||||
-- При создании ОСС автоматически:
|
||||
-- 1. Обновить статус pipeline на 'voting'
|
||||
-- 2. Связать ОСС с pipeline объектом
|
||||
-- 3. Отправить уведомление менеджеру
|
||||
```
|
||||
|
||||
### 2. Завершение ОСС
|
||||
```sql
|
||||
-- При завершении ОСС:
|
||||
-- 1. Если quorum > 50% и решение "за":
|
||||
-- - Обновить статус pipeline на 'transfer'
|
||||
-- - Создать запись в buildings (если еще нет)
|
||||
-- - Связать building_id с pipeline
|
||||
-- 2. Если ОСС провалено:
|
||||
-- - Обновить probability (-20%)
|
||||
-- - Вернуть статус на 'preparation' или 'negotiation'
|
||||
```
|
||||
|
||||
### 3. Завершение технического аудита
|
||||
```sql
|
||||
-- При завершении аудита:
|
||||
-- 1. Обновить probability на основе wear_percent и projected_margin
|
||||
-- 2. Если wear_percent > 70%:
|
||||
-- - Уменьшить probability на 15%
|
||||
-- 3. Если projected_margin < 10%:
|
||||
-- - Уменьшить probability на 10%
|
||||
```
|
||||
|
||||
### 4. Обновление маркетинговых метрик
|
||||
```sql
|
||||
-- При обновлении метрик:
|
||||
-- 1. Пересчитать probability
|
||||
-- 2. Проверить условия для перехода на следующую стадию
|
||||
-- 3. Автоматически перевести, если условия выполнены
|
||||
```
|
||||
|
||||
## Deadlines и напоминания
|
||||
|
||||
### Автоматические напоминания:
|
||||
- **7 дней в стадии** - напомнить менеджеру о необходимости действий
|
||||
- **30 дней без активности** - предупреждение о риске потери объекта
|
||||
- **Deadline ОСС** - напоминание за 3 дня до окончания
|
||||
- **Просроченные задачи** - ежедневные уведомления
|
||||
|
||||
## Интеграция с другими модулями
|
||||
|
||||
### Связь с модулями:
|
||||
1. **ОСС модуль** - автоматическое создание ОСС при переходе в 'preparation'
|
||||
2. **Аудит модуль** - автоматическое создание задачи на аудит при 'negotiation'
|
||||
3. **Маркетинг модуль** - автоматическое создание активности при добавлении объекта
|
||||
4. **Buildings модуль** - автоматическое создание здания при 'transfer'
|
||||
|
||||
## Реализация
|
||||
|
||||
### 1. Таблица для истории переходов
|
||||
```sql
|
||||
CREATE TABLE development_pipeline_history (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
pipeline_id VARCHAR(50) REFERENCES development_pipeline(id) ON DELETE CASCADE,
|
||||
from_status VARCHAR(20),
|
||||
to_status VARCHAR(20),
|
||||
reason TEXT,
|
||||
triggered_by VARCHAR(50), -- 'auto' | 'manual' | user_id
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
```
|
||||
|
||||
### 2. Таблица для правил автоматизации
|
||||
```sql
|
||||
CREATE TABLE development_automation_rules (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
rule_name VARCHAR(100) NOT NULL,
|
||||
from_status VARCHAR(20),
|
||||
to_status VARCHAR(20),
|
||||
conditions JSONB, -- условия для срабатывания
|
||||
enabled BOOLEAN DEFAULT TRUE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
```
|
||||
|
||||
### 3. Cron задачи (Node.js)
|
||||
- Ежедневная проверка условий для автоматических переходов
|
||||
- Пересчет probability для всех объектов
|
||||
- Проверка deadlines и отправка уведомлений
|
||||
|
||||
### 4. Триггеры в БД
|
||||
- Автоматическое обновление статуса при создании ОСС
|
||||
- Автоматическое обновление при завершении ОСС
|
||||
- Логирование всех изменений статуса
|
||||
|
||||
## Примеры workflow
|
||||
|
||||
### Сценарий 1: Успешный объект
|
||||
1. Объект добавлен вручную → `analysis` (probability: 20%)
|
||||
2. Проведена встреча, найдены активисты → probability: 35% → `negotiation`
|
||||
3. Проведено 3 встречи, 5 активистов → probability: 65% → `preparation`
|
||||
4. Создан технический аудит → probability: 70%
|
||||
5. Создано ОСС → автоматически `voting`
|
||||
6. ОСС завершено успешно → автоматически `transfer` + создан building
|
||||
|
||||
### Сценарий 2: Потеря объекта
|
||||
1. Объект в `negotiation` 45 дней без активности
|
||||
2. Автоматическое снижение probability до 15%
|
||||
3. Автоматический откат в `analysis`
|
||||
4. Уведомление менеджеру о риске потери
|
||||
|
||||
### Сценарий 3: Импорт из файла
|
||||
1. Загружен CSV с 50 объектами
|
||||
2. Автоматическое создание записей в `analysis`
|
||||
3. Автоматическое создание маркетинговых активностей
|
||||
4. Распределение по менеджерам (round-robin или по районам)
|
||||
209
docs/DOMA_AI_INTEGRATION.md
Executable file
209
docs/DOMA_AI_INTEGRATION.md
Executable file
@@ -0,0 +1,209 @@
|
||||
# Интеграция с Doma AI API
|
||||
|
||||
Этот документ описывает интеграцию приложения с Doma AI для автоматической синхронизации заявок.
|
||||
|
||||
## Обзор
|
||||
|
||||
Модуль заявок (`ApplicationsModule`) интегрирован с Doma AI через GraphQL API. Все заявки автоматически загружаются из Doma AI и отображаются в разделе "Заявки".
|
||||
|
||||
## Настройка
|
||||
|
||||
### 1. Получение доступа к Doma AI
|
||||
|
||||
**Для продакшена:**
|
||||
1. Получите доступ к вашему продакшн инстансу Doma AI
|
||||
2. Убедитесь, что у вас есть учетные данные для API
|
||||
3. Получите URL API вашего инстанса (обычно: `https://your-domain.doma.ai/admin/api`)
|
||||
|
||||
**Для тестирования (опционально):**
|
||||
1. Перейдите на [тестовый стенд Doma AI](https://condo.d.doma.ai/)
|
||||
2. Зарегистрируйтесь, указав email и пароль
|
||||
3. Создайте новую организацию в системе
|
||||
|
||||
### 2. Настройка переменных окружения
|
||||
|
||||
Создайте файл `.env.local` в корне проекта и добавьте:
|
||||
|
||||
```env
|
||||
# URL API Doma AI (PRODUCTION)
|
||||
# ВАЖНО: Укажите URL вашего продакшн инстанса Doma AI
|
||||
# Пример: https://your-domain.doma.ai/admin/api
|
||||
VITE_DOMA_AI_API_URL=https://your-domain.doma.ai/admin/api
|
||||
|
||||
# Учетные данные (используйте email ИЛИ телефон)
|
||||
# Для продакшена используйте учетные данные вашей организации
|
||||
VITE_DOMA_AI_EMAIL=your-email@example.com
|
||||
VITE_DOMA_AI_PASSWORD=your-password
|
||||
|
||||
# ИЛИ используйте телефон:
|
||||
# VITE_DOMA_AI_PHONE=+79991234567
|
||||
# VITE_DOMA_AI_PASSWORD=your-password
|
||||
```
|
||||
|
||||
**Для продакшена:**
|
||||
- Укажите URL вашего инстанса Doma AI (не тестовый стенд)
|
||||
- Используйте учетные данные вашей организации в Doma AI
|
||||
- Убедитесь, что URL доступен из вашего окружения
|
||||
|
||||
### 3. Авторизация
|
||||
|
||||
При первом открытии раздела "Заявки" приложение автоматически:
|
||||
- Проверяет наличие сохраненного токена
|
||||
- Если токена нет, выполняет авторизацию с использованием учетных данных из переменных окружения
|
||||
- Сохраняет токен в localStorage для последующих запросов
|
||||
|
||||
## Архитектура
|
||||
|
||||
### Компоненты
|
||||
|
||||
1. **`domaGraphQLClient.ts`** - GraphQL клиент для работы с Doma AI API
|
||||
- Управление авторизацией (токены)
|
||||
- Выполнение GraphQL запросов и мутаций
|
||||
- Обработка ошибок
|
||||
|
||||
2. **`domaService.ts`** - Сервис для работы с заявками
|
||||
- Инициализация подключения
|
||||
- Получение заявок из Doma AI
|
||||
- Преобразование данных из формата Doma AI в формат приложения
|
||||
- Fallback на бэкенд или мок-данные при ошибках
|
||||
|
||||
3. **`ApplicationsModule.tsx`** - UI компонент модуля заявок
|
||||
- Отображение заявок
|
||||
- Инициализация подключения при загрузке
|
||||
|
||||
## Работа с API
|
||||
|
||||
### Получение заявок
|
||||
|
||||
```typescript
|
||||
import { domaService } from './services/domaService';
|
||||
|
||||
// Инициализация (выполняется автоматически при первом использовании)
|
||||
await domaService.initialize();
|
||||
|
||||
// Получение всех заявок
|
||||
const applications = await domaService.getApplications();
|
||||
|
||||
// Получение заявок с фильтрами
|
||||
const applications = await domaService.getApplications({
|
||||
status: 'new',
|
||||
limit: 50
|
||||
});
|
||||
```
|
||||
|
||||
### Авторизация вручную
|
||||
|
||||
```typescript
|
||||
import { domaGraphQLClient } from './services/domaGraphQLClient';
|
||||
|
||||
// Через email
|
||||
await domaGraphQLClient.authenticate('email@example.com', 'password');
|
||||
|
||||
// Через телефон
|
||||
await domaGraphQLClient.authenticateWithPhone('+79991234567', 'password');
|
||||
```
|
||||
|
||||
## Маппинг данных
|
||||
|
||||
Данные из Doma AI автоматически преобразуются в формат приложения:
|
||||
|
||||
| Doma AI | Приложение |
|
||||
|---------|------------|
|
||||
| `ticket.id` | `application.id` |
|
||||
| `ticket.number` | `application.number` |
|
||||
| `ticket.status.type` | `application.status` (new/in_progress/done/canceled) |
|
||||
| `ticket.description` | `application.description` |
|
||||
| `ticket.property.address` | `application.address` |
|
||||
| `ticket.property.unitName` | `application.apartment` |
|
||||
| `ticket.client.name` | `application.clientName` |
|
||||
| `ticket.assignee.name` | `application.performer.name` |
|
||||
| `ticket.createdAt` | `application.createdAt` |
|
||||
| `ticket.deadline` | `application.deadlineAt` |
|
||||
|
||||
## Обработка ошибок
|
||||
|
||||
Сервис имеет многоуровневую систему fallback:
|
||||
|
||||
1. **Doma AI API** - основной источник данных
|
||||
2. **Backend API** - если Doma AI недоступен
|
||||
3. **Мок-данные** - если оба источника недоступны
|
||||
|
||||
Это обеспечивает работу приложения даже при проблемах с подключением.
|
||||
|
||||
## Отладка
|
||||
|
||||
Для отладки интеграции откройте консоль браузера. Сервис выводит подробные логи:
|
||||
|
||||
- `[domaService]` - логи сервиса заявок
|
||||
- `[DomaGraphQLClient]` - логи GraphQL клиента
|
||||
|
||||
### Типичные проблемы
|
||||
|
||||
1. **Ошибка авторизации**
|
||||
- Проверьте правильность email/телефона и пароля
|
||||
- Убедитесь, что учетная запись создана в Doma AI
|
||||
|
||||
2. **Заявки не загружаются**
|
||||
- Проверьте URL API в переменных окружения
|
||||
- Убедитесь, что токен сохранен (проверьте localStorage)
|
||||
- Проверьте консоль на наличие ошибок GraphQL
|
||||
|
||||
3. **Неправильные данные**
|
||||
- Возможно, схема GraphQL в Doma AI отличается от ожидаемой
|
||||
- Проверьте структуру ответа в Network вкладке DevTools
|
||||
- Может потребоваться обновление запросов в `domaGraphQLClient.ts`
|
||||
|
||||
## Документация Doma AI
|
||||
|
||||
- [Общая документация](https://developers.doma.ai/ru/docs/index)
|
||||
- [API Playground](https://condo.d.doma.ai/admin/api)
|
||||
- [Примеры использования](https://developers.doma.ai/ru/docs/api/examples)
|
||||
|
||||
## Расширение функциональности
|
||||
|
||||
### Добавление новых запросов
|
||||
|
||||
Для добавления новых запросов к Doma AI:
|
||||
|
||||
1. Добавьте метод в `domaGraphQLClient.ts`:
|
||||
|
||||
```typescript
|
||||
async getCustomData(): Promise<CustomData> {
|
||||
const query = `
|
||||
query GetCustomData {
|
||||
customData {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const response = await this.request<{ customData: CustomData }>(query);
|
||||
return response.data?.customData;
|
||||
}
|
||||
```
|
||||
|
||||
2. Используйте его в `domaService.ts`:
|
||||
|
||||
```typescript
|
||||
async getCustomData(): Promise<CustomData> {
|
||||
await this.initialize();
|
||||
return await domaGraphQLClient.getCustomData();
|
||||
}
|
||||
```
|
||||
|
||||
### Обновление статуса заявки
|
||||
|
||||
Для реализации обновления статуса заявки в Doma AI:
|
||||
|
||||
1. Изучите схему GraphQL в API Playground
|
||||
2. Создайте мутацию в `domaGraphQLClient.ts`
|
||||
3. Реализуйте метод в `domaService.ts`
|
||||
|
||||
## Безопасность
|
||||
|
||||
⚠️ **Важно**: Не коммитьте файлы `.env.local` с реальными учетными данными в репозиторий!
|
||||
|
||||
- Используйте `.env.example` для примера конфигурации
|
||||
- Добавьте `.env.local` в `.gitignore`
|
||||
- Для продакшена используйте переменные окружения сервера
|
||||
244
docs/PIPELINE_AUTOMATION_FLOW.md
Executable file
244
docs/PIPELINE_AUTOMATION_FLOW.md
Executable file
@@ -0,0 +1,244 @@
|
||||
# Схема автоматизации воронки развития
|
||||
|
||||
## Обзор потока данных
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ ИСТОЧНИКИ ДАННЫХ │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ Ручное │ │ Импорт │ │ Интеграция │ │
|
||||
│ │ добавление │ │ из файлов │ │ с API │ │
|
||||
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
|
||||
│ │ │ │ │
|
||||
│ └──────────────────┼──────────────────┘ │
|
||||
│ │ │
|
||||
│ ┌───────▼────────┐ │
|
||||
│ │ ВОРОНКА │ │
|
||||
│ │ (analysis) │ │
|
||||
│ └───────┬────────┘ │
|
||||
└────────────────────────────┼────────────────────────────────────┘
|
||||
│
|
||||
│ Автоматические переходы
|
||||
│
|
||||
┌────────────────────┼────────────────────┐
|
||||
│ │ │
|
||||
┌───────▼────────┐ ┌────────▼────────┐ ┌────────▼────────┐
|
||||
│ NEGOTIATION │ │ PREPARATION │ │ VOTING │
|
||||
│ │ │ │ │ │
|
||||
│ Триггеры: │ │ Триггеры: │ │ Триггеры: │
|
||||
│ • probability │ │ • probability │ │ • ОСС создано │
|
||||
│ >= 30% │ │ >= 60% │ │ (автоматически│
|
||||
│ • активисты │ │ • аудит готов │ │ через триггер│
|
||||
│ • встречи │ │ • документы │ │ БД) │
|
||||
└───────┬────────┘ └────────┬───────┘ └────────┬────────┘
|
||||
│ │ │
|
||||
│ │ │
|
||||
└────────────────────┼────────────────────┘
|
||||
│
|
||||
┌────────▼────────┐
|
||||
│ TRANSFER │
|
||||
│ │
|
||||
│ Триггеры: │
|
||||
│ • ОСС успешно │
|
||||
│ (кворум > 50%)│
|
||||
│ • probability │
|
||||
│ >= 90% │
|
||||
└────────┬────────┘
|
||||
│
|
||||
┌────────▼────────┐
|
||||
│ Создание │
|
||||
│ Building │
|
||||
│ (автоматически)│
|
||||
└─────────────────┘
|
||||
```
|
||||
|
||||
## Детальная схема автоматических переходов
|
||||
|
||||
### 1. Analysis → Negotiation
|
||||
|
||||
**Условия:**
|
||||
- `probability >= 30%` ИЛИ
|
||||
- Создана маркетинговая активность с `activists_count >= 1` ИЛИ
|
||||
- Проведена первая встреча (`meetings_held >= 1`)
|
||||
|
||||
**Действия:**
|
||||
- Автоматический переход статуса
|
||||
- Создание маркетинговой активности (если еще нет)
|
||||
- Уведомление менеджеру
|
||||
|
||||
**Код:**
|
||||
```javascript
|
||||
// В pipelineAutomation.js
|
||||
if (pipeline.status === 'analysis' &&
|
||||
(probability >= 30 || marketing.activists_count >= 1 || marketing.meetings_held >= 1)) {
|
||||
await transitionStatus(pipeline.id, 'analysis', 'negotiation', 'Автоматический переход: условия выполнены', 'auto');
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Negotiation → Preparation
|
||||
|
||||
**Условия:**
|
||||
- `probability >= 60%` И
|
||||
- `activists_count >= 5` И
|
||||
- `meetings_held >= 3` И
|
||||
- Технический аудит завершен (`development_audits` существует)
|
||||
|
||||
**Действия:**
|
||||
- Автоматический переход статуса
|
||||
- Создание задачи на подготовку ОСС
|
||||
- Уведомление менеджеру
|
||||
|
||||
### 3. Preparation → Voting
|
||||
|
||||
**Условия:**
|
||||
- Создано ОСС со статусом `active` (триггер БД)
|
||||
- `probability >= 70%`
|
||||
|
||||
**Действия:**
|
||||
- **Триггер БД** автоматически переводит в `voting`
|
||||
- Логирование в `development_pipeline_history`
|
||||
- Уведомление менеджеру
|
||||
|
||||
**SQL Триггер:**
|
||||
```sql
|
||||
-- Автоматически срабатывает при создании ОСС
|
||||
CREATE TRIGGER trigger_auto_transition_to_voting
|
||||
AFTER INSERT OR UPDATE ON development_oss_sessions
|
||||
WHEN (NEW.status = 'active')
|
||||
EXECUTE FUNCTION auto_transition_to_voting();
|
||||
```
|
||||
|
||||
### 4. Voting → Transfer
|
||||
|
||||
**Условия:**
|
||||
- ОСС завершено (`status = 'completed'`)
|
||||
- Кворум > 50%
|
||||
- Результат голосования положительный
|
||||
|
||||
**Действия:**
|
||||
- **Триггер БД** автоматически переводит в `transfer`
|
||||
- Создание записи в `buildings` (если еще нет)
|
||||
- Связывание `building_id` с pipeline объектом
|
||||
- Уведомление менеджеру и директору
|
||||
|
||||
**SQL Триггер:**
|
||||
```sql
|
||||
-- Автоматически срабатывает при завершении ОСС
|
||||
CREATE TRIGGER trigger_auto_handle_oss_completion
|
||||
AFTER UPDATE ON development_oss_sessions
|
||||
WHEN (NEW.status = 'completed' AND OLD.status != 'completed')
|
||||
EXECUTE FUNCTION auto_handle_oss_completion();
|
||||
```
|
||||
|
||||
## Автоматический расчет probability
|
||||
|
||||
### Формула:
|
||||
```
|
||||
probability = 20 (базовая) +
|
||||
(activists_count * 5, макс 50) +
|
||||
(meetings_held * 3, макс 30) +
|
||||
(ads_distributed / 10, макс 20) +
|
||||
(audit_score * 0.2, макс 20) -
|
||||
(days_inactive * 0.5, макс 30)
|
||||
```
|
||||
|
||||
### Когда пересчитывается:
|
||||
1. **При обновлении маркетинговых метрик** (PUT /api/development/marketing/:id/metrics)
|
||||
2. **При создании/обновлении аудита** (POST/PUT /api/development/audits)
|
||||
3. **Ежедневно** (cron задача в 9:00)
|
||||
4. **Вручную** (POST /api/development/pipeline/:id/recalculate)
|
||||
|
||||
## Источники попадания в воронку
|
||||
|
||||
### 1. Ручное добавление ✅ (реализовано)
|
||||
- Форма в UI
|
||||
- Статус: `analysis`
|
||||
- Probability: 20%
|
||||
|
||||
### 2. Импорт из файлов (TODO)
|
||||
```javascript
|
||||
// POST /api/development/pipeline/import
|
||||
// Принимает CSV/Excel с колонками:
|
||||
// - address, type, floors, area, apartments, manager
|
||||
// Автоматически создает записи в analysis
|
||||
```
|
||||
|
||||
### 3. Интеграция с PR модулем (TODO)
|
||||
```javascript
|
||||
// При обнаружении негативных отзывов о текущей УК:
|
||||
// - Автоматически создается pipeline объект
|
||||
// - Статус: analysis
|
||||
// - Создается маркетинговая активность
|
||||
```
|
||||
|
||||
### 4. Мониторинг внешних источников (TODO)
|
||||
- Парсинг сайтов конкурентов
|
||||
- Мониторинг ГИС ЖКХ
|
||||
- Интеграция с CRM
|
||||
|
||||
## Откаты стадий
|
||||
|
||||
### Negotiation → Analysis
|
||||
**Условия:**
|
||||
- Нет активности > 30 дней
|
||||
- `probability < 20%`
|
||||
|
||||
### Preparation → Negotiation
|
||||
**Условия:**
|
||||
- ОСС отменено
|
||||
- `probability < 50%`
|
||||
|
||||
### Voting → Preparation
|
||||
**Условия:**
|
||||
- ОСС провалено (кворум < 50%)
|
||||
- Автоматически через триггер БД
|
||||
|
||||
## Уведомления
|
||||
|
||||
### Типы уведомлений:
|
||||
1. **Переход на следующую стадию** - менеджеру объекта
|
||||
2. **Откат стадии** - менеджеру + руководителю отдела
|
||||
3. **Риск потери объекта** (30 дней без активности) - менеджеру + директору
|
||||
4. **ОСС завершено успешно** - менеджеру + директору + финансисту
|
||||
5. **Объект передан в управление** - всем заинтересованным
|
||||
|
||||
## API Endpoints для автоматизации
|
||||
|
||||
### Ручной запуск проверки
|
||||
```
|
||||
POST /api/development/pipeline/auto-check
|
||||
```
|
||||
Запускает ежедневную проверку всех объектов вручную.
|
||||
|
||||
### Пересчет probability
|
||||
```
|
||||
POST /api/development/pipeline/:id/recalculate
|
||||
```
|
||||
Пересчитывает probability для конкретного объекта и проверяет условия для перехода.
|
||||
|
||||
## Мониторинг и логирование
|
||||
|
||||
Все автоматические переходы логируются в `development_pipeline_history`:
|
||||
- `from_status` - предыдущий статус
|
||||
- `to_status` - новый статус
|
||||
- `reason` - причина перехода
|
||||
- `triggered_by` - 'auto' | 'manual' | user_id
|
||||
- `created_at` - время перехода
|
||||
|
||||
## Примеры workflow
|
||||
|
||||
### Успешный сценарий:
|
||||
1. Объект добавлен → `analysis` (20%)
|
||||
2. Встреча + 2 активиста → probability: 35% → `negotiation`
|
||||
3. 3 встречи + 5 активистов + аудит → probability: 68% → `preparation`
|
||||
4. Создано ОСС → автоматически `voting` (триггер БД)
|
||||
5. ОСС успешно (кворум 55%) → автоматически `transfer` (триггер БД)
|
||||
6. Создан Building → объект в управлении
|
||||
|
||||
### Неудачный сценарий:
|
||||
1. Объект в `voting` (ОСС идет)
|
||||
2. ОСС провалено (кворум 45%) → автоматически `preparation` (триггер БД)
|
||||
3. Probability снижен на 20%
|
||||
4. Уведомление менеджеру о необходимости дополнительной работы
|
||||
104
docs/REPORT_01_ROLES_AND_RESTRICTIONS.md
Executable file
104
docs/REPORT_01_ROLES_AND_RESTRICTIONS.md
Executable file
@@ -0,0 +1,104 @@
|
||||
# Отчёт №1 — Роли и ограничения (для согласования с заказчиком)
|
||||
|
||||
Документ описывает роли портала МКД, их ограничения по разделам и данным, связь с базой данных и соотношение с ролями workflow согласования счетов. После согласования используется как основа для отчёта №2 и переработки логики прав.
|
||||
|
||||
---
|
||||
|
||||
## 1. Список ролей портала (после переработки)
|
||||
|
||||
Рекомендуется сохранить текущие коды ролей в БД. Ниже — код, название для UI и краткое описание назначения.
|
||||
|
||||
| Код (БД) | Название для UI | Описание назначения |
|
||||
|------------|-----------------|----------------------|
|
||||
| DIRECTOR | Директор | Полный доступ ко всем разделам портала. Руководство, контроль показателей, настройки. |
|
||||
| ENGINEER | Гл. Инженер | Производство, участки, заявки, офис, развитие. Оперативное управление технической и производственной частью. |
|
||||
| MASTER | Мастер | Участки и заявки. Работа в рамках назначенных участков (дома, заявки, штат участка). |
|
||||
| LAWYER | Юрист | Сводка, юр. отдел, участки, заявки. Работа с договорами, судами, досудебной работой, долгами. |
|
||||
| FINANCIER | Финансист | Сводка, финансы, офис, участки. Реестр счетов, календарь оплат, отчёты, закупки. |
|
||||
| HR_MANAGER | HR-менеджер | Сводка, кадры, офис. Сотрудники, календарь, вакансии, подбор, охрана труда. |
|
||||
| PR_MANAGER | PR-менеджер | Сводка, PR и NPS, заявки. SMM, мероприятия, обратная связь, отчёты, NPS, негатив. |
|
||||
|
||||
---
|
||||
|
||||
## 2. Ограничения по каждой роли
|
||||
|
||||
### 2.1 Разделы по умолчанию
|
||||
|
||||
При пустом поле `permissions` у пользователя применяются разделы по роли (из таблицы ниже). «all» означает доступ ко всем разделам портала.
|
||||
|
||||
| Роль | Разделы по умолчанию |
|
||||
|------------|------------------------|
|
||||
| DIRECTOR | all (все разделы) |
|
||||
| ENGINEER | dashboard, objects, requests, office, development |
|
||||
| MASTER | objects, requests |
|
||||
| LAWYER | dashboard, legal, objects, requests |
|
||||
| FINANCIER | dashboard, finance, office, objects |
|
||||
| HR_MANAGER | dashboard, hr, office |
|
||||
| PR_MANAGER | dashboard, pr, requests |
|
||||
|
||||
Соответствие кодов разделов и названий: dashboard — Сводка; objects — Участки; requests — Заявки; pr — PR и NPS; finance — Финансы; legal — Юр. отдел; development — Развитие; hr — Кадры; office — Офис; admin — Панель управления.
|
||||
|
||||
### 2.2 Уровень доступа по умолчанию
|
||||
|
||||
По умолчанию для роли по всем доступным разделам и подразделам задаётся уровень **«редактирование»** (edit): пользователь может просматривать и изменять данные в рамках своих разделов. Различие «только чтение» / «только своё» задаётся только через кастомные `permissions` у пользователя или через шаблоны прав.
|
||||
|
||||
### 2.3 Ограничение по данным (участки)
|
||||
|
||||
| Роль | Scope по умолчанию | Пояснение |
|
||||
|------------|--------------------|------------|
|
||||
| DIRECTOR | all | Все участки |
|
||||
| ENGINEER | all | Все участки |
|
||||
| MASTER | own_district | Только свои назначенные участки (из employee_districts / assigned_district_id) |
|
||||
| LAWYER | all | Все участки |
|
||||
| FINANCIER | all | Все участки |
|
||||
| HR_MANAGER | all | Все участки |
|
||||
| PR_MANAGER | all | Все участки |
|
||||
|
||||
При `scope = own_district` список разрешённых участков для фильтрации данных (дома, заявки и т.д.) формируется из таблицы **employee_districts** (многие ко многим); при отсутствии записей — из поля **employees.assigned_district_id**.
|
||||
|
||||
### 2.4 Особые ограничения
|
||||
|
||||
- **Счета на оплату:** в API поддерживается параметр `scope=own` — показ только счетов, созданных текущим пользователем (`created_by = employee_id`). Это отдельно от роли портала и может использоваться для любой роли при необходимости.
|
||||
- **Workflow согласования счетов** задаётся таблицей **user_roles** (manager, finance_manager, director и т.д.) и не дублирует роли портала (см. раздел 4).
|
||||
|
||||
При необходимости в будущем можно ввести особые ограничения вида «только свои заявки» через уровень доступа «только своё» (own) по подразделу и проверки на бэкенде.
|
||||
|
||||
---
|
||||
|
||||
## 3. Связь с базой данных
|
||||
|
||||
### 3.1 portal_users
|
||||
|
||||
- **role** (VARCHAR) — код роли портала (DIRECTOR, ENGINEER, MASTER, LAWYER, FINANCIER, HR_MANAGER, PR_MANAGER).
|
||||
- **permissions** (JSONB) — массив строк прав. Если массив не пустой — используются только эти права (разделы/подразделы и уровни); иначе применяются права по роли из единого справочника (ROLE_ACCESS и уровень edit по умолчанию).
|
||||
- **scope** (VARCHAR: 'all' | 'own_district') — ограничение по участкам: все участки или только назначенные сотруднику.
|
||||
|
||||
При пустом `permissions` бэкенд и фронт вычисляют доступ по полю `role` и единому справочнику разделов/уровней по умолчанию.
|
||||
|
||||
### 3.2 employees и участки
|
||||
|
||||
- **employees.assigned_district_id** (VARCHAR, один участок) — для обратной совместимости; используется как fallback, если у сотрудника нет записей в employee_districts.
|
||||
- **employee_districts** (таблица связей employee_id, district_id) — многие ко многим: один сотрудник может быть назначен на несколько участков.
|
||||
|
||||
При **scope = own_district** список доступных district_id для фильтрации данных должен формироваться так: сначала выборка из **employee_districts** по employee_id пользователя; если записей нет — использовать **assigned_district_id** (один участок). Все API, которые фильтруют данные по участку (дома, при необходимости заявки, отчёты и т.д.), должны использовать этот единый список.
|
||||
|
||||
### 3.3 permission_templates
|
||||
|
||||
- Шаблоны хранят: name, description, **permissions** (JSONB), **scope**, for_position, suggested_role. Применение шаблона к пользователю подставляет permissions и scope (и при необходимости suggested_role) в portal_users. Структура БД менять не требуется; при переработке важно сохранять тот же формат permissions и scope.
|
||||
|
||||
### 3.4 Новые поля или таблицы
|
||||
|
||||
- Текущей модели достаточно. Матрица «роль → разделы/уровень/scope» по умолчанию может храниться в едином модуле констант в коде (общий для фронта и бэкенда). При желании в будущем можно вынести матрицу в таблицу (например, role_default_access) для настройки без деплоя.
|
||||
|
||||
---
|
||||
|
||||
## 4. user_roles (workflow) и роли портала
|
||||
|
||||
- **user_roles** — таблица для цепочки согласования счетов на оплату. Роли: manager, finance_manager, financier, finance_director, director, top_management. Используются только в модуле согласования счетов (paymentInvoiceWorkflow и связанные API).
|
||||
- **Роли портала** (portal_users.role) определяют доступ к разделам и данным портала (меню, вкладки, фильтр по участкам). Они не задают права согласования счетов.
|
||||
- Связывать user_roles с portal_users.role не обязательно: один и тот же человек может быть DIRECTOR в портале и не иметь роли в user_roles, или иметь роль manager/finance_manager в user_roles при другой роли в портале.
|
||||
- В админке целесообразно показывать «роль в портале» и «роли в workflow» отдельно (например, в карточке пользователя — раздел «Согласование счетов» с назначением ролей из user_roles).
|
||||
|
||||
---
|
||||
|
||||
После согласования данного отчёта переходим к отчёту №2: большая таблица доступов (раздел × подраздел × роль), рекомендуемые шаблоны прав и пошаговый план переписывания логики прав с чек-листом файлов.
|
||||
204
docs/REPORT_02_ACCESS_TABLE_AND_REWRITE_PLAN.md
Executable file
204
docs/REPORT_02_ACCESS_TABLE_AND_REWRITE_PLAN.md
Executable file
@@ -0,0 +1,204 @@
|
||||
# Отчёт №2 — Таблица доступов и план переписывания прав
|
||||
|
||||
Документ подготовлен после согласования отчёта №1. Содержит: большую таблицу доступов (раздел × подраздел × роль), рекомендуемые шаблоны прав, пошаговый план переписывания логики прав и чек-лист файлов для правок.
|
||||
|
||||
---
|
||||
|
||||
## 1. Большая таблица доступов
|
||||
|
||||
Уровни: **—** нет доступа, **Ч** чтение, **Р** редактирование, **С** только своё. По умолчанию для роли везде, где раздел доступен, используется **Р** (редактирование).
|
||||
|
||||
### 1.1 Сводка (dashboard)
|
||||
|
||||
| Подраздел | DIRECTOR | ENGINEER | MASTER | LAWYER | FINANCIER | HR_MANAGER | PR_MANAGER |
|
||||
|------------------------|----------|----------|--------|--------|-----------|------------|------------|
|
||||
| Стратегические цели | Р | Р | — | Р | Р | Р | Р |
|
||||
| Панель «Производство» | Р | Р | Р¹ | Р | Р | Р | Р |
|
||||
| Панель «PR и клиентский опыт» | Р | Р | — | Р | Р | Р | Р |
|
||||
| Панель «Финансы» | Р | Р | — | Р | Р | Р | Р |
|
||||
| Панель «Развитие» | Р | Р | — | Р | Р | Р | Р |
|
||||
| Панель «Юр. отдел» | Р | Р | — | Р | Р | Р | Р |
|
||||
| Панель «Кадры» | Р | Р | — | Р | Р | Р | Р |
|
||||
| Мои задачи | Р | Р | — | Р | Р | Р | Р |
|
||||
| Новости компании | Р | Р | — | Р | Р | Р | Р |
|
||||
|
||||
### 1.2 Участки (objects)
|
||||
|
||||
| Подраздел | DIRECTOR | ENGINEER | MASTER | LAWYER | FINANCIER | HR_MANAGER | PR_MANAGER |
|
||||
|---------------|----------|----------|--------|--------|-----------|------------|------------|
|
||||
| Обзор участков| Р | Р | Р* | Р | Р | — | — |
|
||||
| Дома | Р | Р | Р* | Р | Р | — | — |
|
||||
| Штат участка | Р | Р | Р* | Р | Р | — | — |
|
||||
|
||||
\* MASTER: по умолчанию scope = только свой участок (см. п. 1.10).
|
||||
|
||||
### 1.3 Заявки (requests)
|
||||
|
||||
| Подраздел | DIRECTOR | ENGINEER | MASTER | LAWYER | FINANCIER | HR_MANAGER | PR_MANAGER |
|
||||
|-------------|----------|----------|--------|--------|-----------|------------|------------|
|
||||
| Сводка | Р | Р | Р* | Р | — | — | Р |
|
||||
| Реестр заявок | Р | Р | Р* | Р | — | — | Р |
|
||||
| Контроль | Р | Р | Р* | Р | — | — | Р |
|
||||
| Качество | Р | Р | Р* | Р | — | — | Р |
|
||||
| Привязки | Р | Р | Р* | Р | — | — | Р |
|
||||
| Отключения | Р | Р | Р* | Р | — | — | Р |
|
||||
|
||||
### 1.4 PR и NPS (pr)
|
||||
|
||||
| Подраздел | DIRECTOR | ENGINEER | MASTER | LAWYER | FINANCIER | HR_MANAGER | PR_MANAGER |
|
||||
|----------------|----------|----------|--------|--------|-----------|------------|------------|
|
||||
| Сводка | Р | — | — | — | — | — | Р |
|
||||
| SMM | Р | — | — | — | — | — | Р |
|
||||
| Мероприятия | Р | — | Р¹ | — | — | — | Р |
|
||||
| Обратная связь | Р | — | — | — | — | — | Р |
|
||||
| Отчёты | Р | — | — | — | — | — | Р |
|
||||
| Фото работ | Р | — | Р¹ | — | — | — | Р |
|
||||
| NPS | Р | — | — | — | — | — | Р |
|
||||
| Негатив | Р | — | — | — | — | — | Р |
|
||||
|
||||
### 1.5 Финансы (finance)
|
||||
|
||||
| Подраздел | DIRECTOR | ENGINEER | MASTER | LAWYER | FINANCIER | HR_MANAGER | PR_MANAGER |
|
||||
|-----------------|----------|----------|--------|--------|-----------|------------|------------|
|
||||
| Сводка | Р | — | — | — | Р | — | — |
|
||||
| Реестр счетов | Р | — | С¹ | — | Р | — | — |
|
||||
| Календарь оплат | Р | — | Р¹ | — | Р | — | — |
|
||||
| Отчёты | Р | — | — | — | Р | — | — |
|
||||
|
||||
### 1.6 Юр. отдел (legal)
|
||||
|
||||
| Подраздел | DIRECTOR | ENGINEER | MASTER | LAWYER | FINANCIER | HR_MANAGER | PR_MANAGER |
|
||||
|---------------------|----------|----------|--------|--------|-----------|------------|------------|
|
||||
| Сводка | Р | — | — | Р | — | — | — |
|
||||
| Взыскание долгов | Р | — | — | Р | — | — | — |
|
||||
| Договоры | Р | — | — | Р | — | — | — |
|
||||
| Судебные дела | Р | — | — | Р | — | — | — |
|
||||
| Досудебная работа | Р | — | — | Р | — | Р | — |
|
||||
| Соответствие | Р | — | — | Р | — | — | — |
|
||||
|
||||
### 1.7 Развитие (development)
|
||||
|
||||
| Подраздел | DIRECTOR | ENGINEER | MASTER | LAWYER | FINANCIER | HR_MANAGER | PR_MANAGER |
|
||||
|---------------|----------|----------|--------|--------|-----------|------------|------------|
|
||||
| Сводка | Р | Р | — | — | — | — | — |
|
||||
| Реестр объектов | Р | Р | — | — | — | — | — |
|
||||
| ОСС | Р | Р | — | — | — | — | — |
|
||||
| Техаудит | Р | Р | — | — | — | — | — |
|
||||
| Маркетинг | Р | Р | — | — | — | — | — |
|
||||
|
||||
### 1.8 Кадры (hr)
|
||||
|
||||
| Подраздел | DIRECTOR | ENGINEER | MASTER | LAWYER | FINANCIER | HR_MANAGER | PR_MANAGER |
|
||||
|--------------|----------|----------|--------|--------|-----------|------------|------------|
|
||||
| Сводка | Р | — | — | — | — | Р | — |
|
||||
| Сотрудники | Р | — | — | — | — | Р | — |
|
||||
| Календарь | Р | — | — | — | — | Р | — |
|
||||
| Вакансии | Р | — | — | — | — | Р | — |
|
||||
| Подбор | Р | — | — | — | — | Р | — |
|
||||
| Охрана труда | Р | — | — | — | — | Р | — |
|
||||
|
||||
### 1.9 Офис (office)
|
||||
|
||||
| Подраздел | DIRECTOR | ENGINEER | MASTER | LAWYER | FINANCIER | HR_MANAGER | PR_MANAGER |
|
||||
|------------|----------|----------|--------|--------|-----------|------------|------------|
|
||||
| Сводка | Р | Р | — | — | Р | Р | — |
|
||||
| Закупки | Р | Р | Р¹ | — | Р | Р | — |
|
||||
| Документы | Р | Р | — | — | Р | Р | — |
|
||||
| Объекты | Р | Р | — | — | Р | Р | — |
|
||||
| Ремонты | Р | Р | Р¹ | — | Р | Р | — |
|
||||
| База знаний| Р | Р | — | — | Р | Р | — |
|
||||
| Встречи | Р | Р | — | — | Р | Р | — |
|
||||
| Новости | Р | Р | — | — | Р | Р | — |
|
||||
|
||||
### 1.10 Панель управления (admin)
|
||||
|
||||
| Подраздел | DIRECTOR | ENGINEER | MASTER | LAWYER | FINANCIER | HR_MANAGER | PR_MANAGER |
|
||||
|----------------------|----------|----------|--------|--------|-----------|------------|------------|
|
||||
| Все подразделы | Р | — | — | — | — | — | — |
|
||||
|
||||
Только роль DIRECTOR по умолчанию имеет доступ к разделу admin. Остальные роли — нет доступа (при необходимости доступ задаётся кастомными permissions).
|
||||
|
||||
### 1.11 Ограничение по участкам
|
||||
|
||||
| Роль | Ограничение по участкам |
|
||||
|------------|---------------------------|
|
||||
| DIRECTOR | Все участки |
|
||||
| ENGINEER | Все участки |
|
||||
| MASTER | Только свой участок (свои назначенные участки) |
|
||||
| LAWYER | Все участки |
|
||||
| FINANCIER | Все участки |
|
||||
| HR_MANAGER | Все участки |
|
||||
| PR_MANAGER | Все участки |
|
||||
|
||||
Список «своих» участков формируется из employee_districts с fallback на employees.assigned_district_id.
|
||||
|
||||
¹ MASTER: доступ по шаблону «Мастер участка (расширенный)» — при назначении шаблона подставляются permissions (в т.ч. dashboard_production, finance_invoices:own, finance_calendar, office_supply, office_repair, pr_events, pr_photos), scope = own_district. Реестр счетов для мастера — уровень «только своё» (С): видны только счета, созданные им (scope=own в API).
|
||||
|
||||
---
|
||||
|
||||
## 2. Шаблоны прав
|
||||
|
||||
Рекомендуемые шаблоны для быстрого назначения прав пользователям. Каждый шаблон задаёт permissions (массив ключей раздел/подраздел:уровень), scope и suggested_role.
|
||||
|
||||
| Название шаблона | Разделы и подразделы (уровень) | Рекомендуемая роль | Scope | Назначение |
|
||||
|--------------------|--------------------------------|--------------------|--------------|------------|
|
||||
| Мастер участка | objects (все подразделы), requests (все подразделы) | MASTER | own_district | Мастер: участки и заявки только по своим участкам. |
|
||||
| Мастер участка (расширенный) | objects, requests, dashboard_production, finance_invoices:own, finance_calendar, office_supply, office_repair, pr_events, pr_photos | MASTER | own_district | Мастер: участки, заявки, сводка (производство), реестр счетов (только свои), календарь оплат, закупки ТМЦ, ремонт техники, мероприятия и фото отчёты по своим домам. |
|
||||
| Гл. инженер | dashboard, objects, requests, office, development (все подразделы — edit) | ENGINEER | all | Производство, участки, заявки, офис, развитие. |
|
||||
| Начальник PR | dashboard, pr, requests (все подразделы — edit) | PR_MANAGER | all | PR и NPS, заявки, сводка. |
|
||||
| Финансист | dashboard, finance, office, objects (все подразделы — edit) | FINANCIER | all | Финансы, офис, участки (для отчётности). |
|
||||
| HR-менеджер | dashboard, hr, office (все подразделы — edit) | HR_MANAGER | all | Кадры, офис. |
|
||||
| Юрист | dashboard, legal, objects, requests (все подразделы — edit) | LAWYER | all | Юр. отдел, участки, заявки. |
|
||||
| Только чтение (сводка и участки) | dashboard:read, objects:read (подразделы — read) | ENGINEER или MASTER | all / own_district | Просмотр без редактирования. |
|
||||
|
||||
В интерфейсе админки шаблоны отображаются как справочник: при создании/редактировании пользователя можно применить шаблон — подставляются permissions, scope и при необходимости suggested_role. Таблица доступов (раздел × подраздел) остаётся единой; шаблон — это готовый набор строк этой таблицы для выбранной роли и scope.
|
||||
|
||||
---
|
||||
|
||||
## 3. План переписывания прав
|
||||
|
||||
### 3.1 Единый источник прав
|
||||
|
||||
- Создать один модуль констант: коды ролей, названия ролей (ROLE_NAMES), список разделов (SECTION_IDS / ALL_SECTION_KEYS), матрица «роль → разделы по умолчанию» (ROLE_ACCESS), матрица «роль → scope по умолчанию» (например ROLE_DEFAULT_SCOPE).
|
||||
- Варианты реализации: (1) общий файл в репозитории, импортируемый и на фронте (TypeScript), и на бэкенде (через require/импорт JS-версии или общий JSON); (2) генерация из одного JSON/YAML в constants для фронта и в константы для Node. Цель: убрать дублирование ROLE_ACCESS, ROLE_NAMES, SECTION_IDS в App.tsx, Navigation.tsx, server.js, UsersSection.tsx, PermissionsSection.tsx.
|
||||
- В constants/permissions.ts оставить SECTION_LABELS, SECTION_SUBS, функции canAccessSub, getPermissionLevel, allowedSubsForSection и т.д.; роли и ROLE_ACCESS импортировать из единого источника.
|
||||
|
||||
### 3.2 Изменения в БД
|
||||
|
||||
- Миграции при необходимости: структура portal_users (role, permissions, scope) и permission_templates не меняется. При scope=own_district во всех API, где идёт фильтр по участку, единообразно использовать список district_id из employee_districts с fallback на assigned_district_id (см. п. 3.4).
|
||||
|
||||
### 3.3 Фронт
|
||||
|
||||
- Заменить все проверки «по роли» на единые функции из общего модуля прав с учётом permissions и scope. Логика уже опирается на allowedSections и userPermissions из /auth/me; нужно убрать локальные константы и импортировать ROLE_ACCESS, ROLE_NAMES (и при необходимости SECTION_IDS) из единого источника.
|
||||
- Компоненты, использующие allowedSubsForSection, canAccessSub, useSubPermission, оставить без изменения логики; источник констант — общий.
|
||||
|
||||
### 3.4 Бэкенд
|
||||
|
||||
- Все API, отдающие данные в зависимости от прав: использовать единую функцию вычисления allowedSections (и при необходимости уровней по подразделам) из констант. Для фильтра по участку при scope=own_district — единая функция: получить разрешённые district_id из employee_districts по employee_id пользователя; если пусто — взять assigned_district_id. Применять этот список в запросах (buildings — фильтр домов по district_id IN (...), при необходимости заявки, отчёты и т.д.).
|
||||
- В backend/routes/buildings.js заменить текущую логику (только assigned_district_id) на получение списка участков через employee_districts + fallback и фильтр WHERE (data->>'districtId') = ANY($1).
|
||||
|
||||
### 3.5 Админка
|
||||
|
||||
- Создание/редактирование пользователей и шаблонов — сохранение в текущем формате (role, permissions, scope); при необходимости расширить под полную матрицу или подсказки по шаблонам. ROLE_NAMES брать из единого источника.
|
||||
|
||||
---
|
||||
|
||||
## 4. Чек-лист файлов для правок
|
||||
|
||||
| Файл | Что менять |
|
||||
|------|------------|
|
||||
| **Единый источник (новый файл)** | Создать модуль с ролями, ROLE_NAMES, ROLE_ACCESS, SECTION_IDS, ROLE_DEFAULT_SCOPE. Вариант: `constants/roleAccess.ts` (фронт) + использование на бэкенде через копию или общий пакет. |
|
||||
| constants/permissions.ts | Импорт SECTION_IDS/ALL_SECTION_KEYS и ролей из единого источника при необходимости; оставить SECTION_LABELS, SECTION_SUBS, все функции. |
|
||||
| types.ts | UserRole синхронизировать с единым источником (экспорт типа из источника или дублировать список). |
|
||||
| App.tsx | Удалить локальные ROLE_ACCESS, ROLE_NAMES; импорт из единого модуля. |
|
||||
| components/Navigation.tsx | Удалить ROLE_ACCESS; импорт из единого модуля. |
|
||||
| components/admin/UsersSection.tsx | Удалить ROLE_NAMES; импорт из единого модуля. |
|
||||
| components/admin/PermissionsSection.tsx | Удалить ROLE_NAMES; импорт из единого модуля. |
|
||||
| backend/server.js | Удалить локальные ROLE_ACCESS, SECTION_IDS; подключать константы из общего модуля (например shared/roleAccess.js или сгенерированный файл). Функцию allowedSectionsFromPermissions оставить, секции брать из констант. |
|
||||
| backend/routes/buildings.js | При scope=own_district: получать список district_id из employee_districts по employee_id пользователя; при пустом — [assigned_district_id]. Фильтр домов: WHERE (data->>'districtId') = ANY($1::text[]). |
|
||||
| Другие API в server.js | Найти все места фильтра по участку или проверки раздела; подключить единую функцию получения списка участков для scope=own_district. |
|
||||
| Миграции | При появлении новых полей или таблиц ролей по умолчанию — добавить миграции. Текущий план миграций не требует. |
|
||||
|
||||
---
|
||||
|
||||
После выполнения пунктов чек-листа логика прав будет приведена к единому источнику, дубли убраны, фильтр по участкам для scope=own_district будет учитывать все назначенные участки (employee_districts).
|
||||
Reference in New Issue
Block a user