v4.1.21: Реструктуризация проекта для Synology ARM

- Реструктуризация: src/ разбит на middleware/, utils/, repositories/ (удалены), routes/ (удалены)
- Добавлен src/original-html.ts — полный HTML с reportModal
- Добавлен src/index.tsx.backup — React-компонент с reportModal
- Миграции переименованы (0001_initial_schema.sql)
- Добавлена миграция 0018 (удалена позже)
- Docker: multi-stage build, wrangler.toml
- Frontend: public/static/app.js + style.css
- seed.sql добавлен
- Документация: CHANGELOG, CHANGES_v4.1.0-4.1.9, PROJECT_STRUCTURE
This commit is contained in:
Deploy Bot
2026-01-14 18:37:00 +02:00
parent 4898f5ec7f
commit 64403d6fd6
113 changed files with 19231 additions and 3084 deletions

381
DATE_FIELDS_LOGIC.md Normal file
View File

@@ -0,0 +1,381 @@
# 📋 ЛОГИКА ДАТ И ЧЕКБОКСОВ - ПОЛНОЕ РУКОВОДСТВО
**Версия**: v4.1.17
**Дата**: 2026-01-14
**Обновление**: Исправлены права доступа (см. ACCESS_RIGHTS.md)
---
## ⚠️ **ВАЖНО: ПРАВА ДОСТУПА**
**Детальная информация о правах доступа находится в файле:**
📄 **[ACCESS_RIGHTS.md](./ACCESS_RIGHTS.md)**
**Краткая сводка:**
- **Admin**: полный доступ (календари + toggle)
- **User**: подтверждение MAT-1/MAT-2 + toggle всех полей
- **Guest**: только просмотр
---
## 🔄 **TÖÖLEHTI (WORKSHEETS) - 3-ШАГОВЫЙ ЦИКЛ**
### **Как работает:**
#### **ШАГ 1: Пусто → Серый фон с датой**
- **Состояние**: Пустая ячейка `-`
- **Действие**: Клик по ячейке
- **Результат**:
- Появляется **текущая дата**
- Фон **СЕРЫЙ** (не подтверждено)
- `worksheets_date` = TODAY
- `worksheets_confirmed` = 0
#### **ШАГ 2: Серый → Зеленый фон (подтверждение)**
- **Состояние**: Дата с серым фоном
- **Действие**: Клик по ячейке
- **Результат**:
- Дата **остается**
- Фон становится **ЗЕЛЕНЫЙ** (подтверждено)
- `worksheets_date` = **сохраняется**
- `worksheets_confirmed` = 1
#### **ШАГ 3: Зеленый → Пусто (сброс)**
- **Состояние**: Дата с зеленым фоном
- **Действие**: Клик по ячейке
- **Результат**:
- Дата **удаляется**
- Ячейка становится **пустой** `-`
- `worksheets_date` = NULL
- `worksheets_confirmed` = 0
### **Визуальная схема:**
```
┌─────────────┐ ┌──────────────────┐ ┌──────────────────┐ ┌─────────────┐
│ ПУСТО │ Клик 1 │ СЕРЫЙ ФОН │ Клик 2 │ ЗЕЛЕНЫЙ ФОН │ Клик 3 │ ПУСТО │
│ - │ ──────> │ 14.01.2026 │ ──────> │ 14.01.2026 │ ──────> │ - │
│ │ │ (не подтверждено)│ │ (подтверждено) │ │ │
└─────────────┘ └──────────────────┘ └──────────────────┘ └─────────────┘
^ │
│ │
└─────────────────────────────────────────────────────────────────────────────────────┘
Цикл повторяется
```
---
## 🟢 **MAT-1 (MATERIAL) - КАЛЕНДАРЬ + ПОДТВЕРЖДЕНИЕ**
### **Функционал:**
- **Календарь**: Клик по ячейке → открывается календарь
- **Выбор даты**: Выбрать дату → сохраняется `material_date`
- **Кнопка подтверждения** ✓: Клик → зеленая рамка
- `material_confirmed` = 1
- Ячейка с зеленой рамкой
### **Кто может изменять:**
- ✅ Admin
- ✅ Public User (все)
### **База данных:**
- `status_checkboxes.material_date` (TEXT)
- `status_checkboxes.material_confirmed` (INTEGER, 0 или 1)
---
## 🔒 **MAT-2 (MATERIAL2) - ЗАВИСИТ ОТ MAT-1**
### **Блокировка:**
- **Заблокировано**: Если MAT-1 пустая
- **Показывается**: 🔒 с подсказкой "MAT-1 peab olema täidetud"
- **Разблокировано**: Когда MAT-1 заполнена
### **Функционал (когда разблокирована):**
- **Календарь**: Клик → открывается календарь
- **Выбор даты**: Выбрать дату → сохраняется `material2_date`
- **Кнопка подтверждения** ✓: Клик → зеленая рамка
- `material2_confirmed` = 1
### **Кто может изменять:**
- ✅ Admin
- ✅ Public User (если MAT-1 заполнена)
### **База данных:**
- `status_checkboxes.material2_date` (TEXT)
- `status_checkboxes.material2_confirmed` (INTEGER, 0 или 1)
---
## 📦 **PAKETT (PACKAGE) - КАЛЕНДАРЬ**
### **Функционал:**
- **Календарь**: Клик → открывается календарь
- **Выбор даты**: Выбрать дату → сохраняется `package_date`
- **Нет подтверждения**: Только дата (без кнопки ✓)
### **Кто может изменять:**
- ✅ Admin
- ✅ Public User (все)
### **База данных:**
- `status_checkboxes.package_date` (TEXT)
---
## 🔴 **LÕIKUS (CUTTING) - ТОЛЬКО ADMIN**
### **Функционал:**
- **Toggle**: Клик → дата появляется/исчезает
- **Автоматическая дата**: Устанавливается на **сегодня**
- **Ошибка-флаг** 🚫: `cutting_error`
- Если установлена → красная метка
- Блокирует **VALMIS** и **VÄLJAS**
### **Кто может изменять:**
- 🔴 **ТОЛЬКО Admin**
### **База данных:**
- `status_checkboxes.cutting_date` (TEXT)
- `status_checkboxes.cutting_error` (INTEGER, 0 или 1)
---
## 🔴 **KLAAS (GLAZING) - ТОЛЬКО ADMIN**
### **Функционал:**
- **Toggle**: Клик → дата появляется/исчезает
- **Автоматическая дата**: Устанавливается на **сегодня**
- **Ошибка-флаг** 🚫: `glazing_error`
- Если установлена → красная метка
- Блокирует **VALMIS** и **VÄLJAS**
### **Кто может изменять:**
- 🔴 **ТОЛЬКО Admin**
### **База данных:**
- `status_checkboxes.glazing_date` (TEXT)
- `status_checkboxes.glazing_error` (INTEGER, 0 или 1)
---
## 🔒 **VALMIS (READY) - Admin/User Toggle + БЛОКИРОВКА ТОЛЬКО ПО ERROR ФЛАГАМ**
### **ВАЖНО: ТЕКСТ ПРОБЛЕМЫ НЕ БЛОКИРУЕТ!**
Текст в поле "Probleemid" (серая метка ⚠️) **НЕ** блокирует VALMIS!
### **Блокировка:**
Поле **ЗАБЛОКИРОВАНО ТОЛЬКО**, если установлен **ЛЮБОЙ error флаг** (красная галочка ✗):
- `worksheets_error = 1`
- `cutting_error = 1`
- `glazing_error = 1`
- `ready_error = 1`
- `issued_error = 1`
**НЕ блокируется**, если:
- Есть только текст в `production_records.problems` (серая метка ⚠️)
- Все error флаги = 0
### **Визуальное отображение:**
- **Заблокировано**: 🔒 + сообщение "Vigade märked on seatud (punased kolmnurgad)"
- **Разблокировано**: Toggle как обычно
### **Функционал (когда разблокирована):**
- **Toggle**: Клик → дата появляется/исчезает
- **Автоматическая дата**: Устанавливается на **сегодня**
### **Кто может изменять:**
-**Admin + User** (изменено в v4.1.18)
### **База данных:**
- `status_checkboxes.ready_date` (TEXT)
- `status_checkboxes.ready_error` (INTEGER, 0 или 1)
---
## 🔒 **VÄLJAS (ISSUED) - Admin/User Toggle + БЛОКИРОВКА ТОЛЬКО ПО ERROR ФЛАГАМ**
### **ВАЖНО: ТЕКСТ ПРОБЛЕМЫ НЕ БЛОКИРУЕТ!**
Текст в поле "Probleemid" (серая метка ⚠️) **НЕ** блокирует VÄLJAS!
### **Блокировка:**
**ТА ЖЕ ЛОГИКА** что и **VALMIS**:
- Блокируется **ТОЛЬКО** если установлен **ЛЮБОЙ error флаг** (красная галочка ✗)
- **НЕ** блокируется если есть только текст в `production_records.problems`
### **Функционал (когда разблокирована):**
- **Toggle**: Клик → дата появляется/исчезает
- **Автоматическая дата**: Устанавливается на **сегодня**
### **Кто может изменять:**
-**Admin + User** (изменено в v4.1.18)
### **Кто может изменять:**
- 🔴 **ТОЛЬКО Admin**
### **База данных:**
- `status_checkboxes.issued_date` (TEXT)
- `status_checkboxes.issued_error` (INTEGER, 0 или 1)
---
## 📊 **СВОДНАЯ ТАБЛИЦА**
| Поле | Тип | Доступ | Логика | Подтверждение | Блокировка |
|------|-----|--------|--------|---------------|-----------|
| **MAT-1** | Календарь | Все | Календарь | ✓ Да | Нет |
| **MAT-2** | Календарь | Все | Календарь | ✓ Да | Если MAT-1 пуста |
| **PAKETT** | Календарь | Все | Календарь | Нет | Нет |
| **Töölehti** | 3-цикл | Admin | Серый→Зеленый→Пусто | Да | Нет |
| **LÕIKUS** | Toggle | Admin | Появляется/Исчезает | Нет | Нет |
| **KLAAS** | Toggle | Admin | Появляется/Исчезает | Нет | Нет |
| **VALMIS** | Toggle | Admin/User | Появляется/Исчезает | Нет | ТОЛЬКО если error флаги (НЕ текст проблемы) |
| **VÄLJAS** | Toggle | Admin/User | Появляется/Исчезает | Нет | ТОЛЬКО если error флаги (НЕ текст проблемы) |
---
## 🔐 **ПРАВА ДОСТУПА**
### **Admin** (admin, aknaproff):
-Все поля (MAT-1, MAT-2, PAKETT, Töölehti, LÕIKUS, KLAAS, VALMIS, VÄLJAS)
- ✅ Добавление записей
- ✅ Редактирование записей
- ✅ Удаление записей
- ✅ Изменение проблем и ошибок
### **Public User** (kasutaja):
- ✅ MAT-1 (календарь + подтверждение)
- ✅ MAT-2 (календарь + подтверждение, если MAT-1 заполнена)
- ✅ PAKETT (календарь)
- ❌ Töölehti, LÕIKUS, KLAAS, VALMIS, VÄLJAS (только просмотр)
- ❌ Добавление/редактирование/удаление записей
---
## 🎨 **ВИЗУАЛЬНЫЕ ИНДИКАТОРЫ**
### **Цвета:**
- 🟢 **Зеленая рамка**: MAT-1/MAT-2 подтверждены
- 🟢 **Зеленый фон**: Töölehti подтверждено (confirmed=1)
-**Серый фон**: Töölehti не подтверждено (confirmed=0)
- 🔴 **Красная метка**: Ошибка-флаг установлен
- 🔒 **Замок**: Поле заблокировано
### **Подсказки:**
- **MAT-2 заблокирована**: "MAT-1 peab olema täidetud"
- **VALMIS/VÄLJAS заблокированы**: Текст проблемы из `production_records.problems`
- **Töölehti Шаг 1**: "Klõps 1: Lisa kuupäev"
- **Töölehti Шаг 2**: "Klõps 2: Kinnita"
- **Töölehti Шаг 3**: "Klõps 3: Tühjenda"
---
## 📝 **AUDIT LOG**
Каждое изменение даты записывается в таблицу `audit_log`:
```sql
INSERT INTO audit_log (user_id, record_id, field, old_value, new_value, action)
VALUES (?, ?, ?, ?, ?, 'toggle_status')
```
**Поля:**
- `user_id`: ID пользователя (1=admin, 2=aknaproff, 4=kasutaja)
- `record_id`: ID записи
- `field`: Название поля (worksheets, cutting, glazing, ready, issued)
- `old_value`: Старое значение даты
- `new_value`: Новое значение даты
- `action`: Тип действия ('toggle_status', 'worksheets_cycle')
---
## ✅ **ПРОВЕРКА**
### **Test Töölehti 3-цикл:**
```bash
# Шаг 1: Пусто → Серый
PATCH /api/records/2/worksheets-cycle
{"date": "2026-01-14", "confirmed": 0}
# Шаг 2: Серый → Зеленый
PATCH /api/records/2/worksheets-cycle
{"date": "2026-01-14", "confirmed": 1}
# Шаг 3: Зеленый → Пусто
PATCH /api/records/2/worksheets-cycle
{"date": null, "confirmed": 0}
```
### **Test блокировка MAT-2:**
```bash
# MAT-1 пустая → MAT-2 заблокирована
SELECT material_date FROM status_checkboxes WHERE record_id = 5
→ NULL
# UI показывает: 🔒 "MAT-1 peab olema täidetud"
```
### **Test блокировка VALMIS:**
```bash
# Есть проблемы → VALMIS заблокирована
SELECT problems FROM production_records WHERE id = 10
"Aken vajab parandust"
# UI показывает: 🔒 + текст проблемы
```
---
**Версия**: v4.1.16
**Статус**: ✅ Работает корректно
**Дата**: 2026-01-14
---
## 🔒 **ВАЖНО: ПРАВИЛО БЛОКИРОВКИ VALMIS/VÄLJAS**
### **Версия**: v4.1.19
### **Дата изменения**: 2026-01-14
**КРИТИЧЕСКИ ВАЖНО**: Блокировка VALMIS/VÄLJAS работает **ТОЛЬКО** по error флагам!
### **Блокируется**, если установлен **ЛЮБОЙ** из error флагов (красная галочка ✗):
- `worksheets_error = 1`
- `cutting_error = 1`
- `glazing_error = 1`
- `ready_error = 1`
- `issued_error = 1`
### **НЕ БЛОКИРУЕТСЯ**, если:
- Есть **ТОЛЬКО** текст в `production_records.problems` (серая метка ⚠️)
- Все error флаги = 0
### **Визуальные индикаторы:**
- **VALMIS/VÄLJAS заблокированы**: 🔒 + сообщение "Vigade märked on seatud (punased kolmnurgad)"
- **Серая метка с ⚠️**: Указывает на текст проблемы в поле "Probleemid", **НЕ блокирует** VALMIS/VÄLJAS
### **Код проверки блокировки** (backend):
```typescript
if (field === 'ready' || field === 'issued') {
const statusCheckbox = await c.env.DB.prepare(
'SELECT worksheets_error, cutting_error, glazing_error, ready_error, issued_error FROM status_checkboxes WHERE record_id = ?'
).bind(recordId).first()
const hasErrorFlags = statusCheckbox && (
statusCheckbox.worksheets_error ||
statusCheckbox.cutting_error ||
statusCheckbox.glazing_error ||
statusCheckbox.ready_error ||
statusCheckbox.issued_error
)
if (hasErrorFlags) {
return c.json({
error: 'blocked',
message: 'Vigade märked on seatud (punased kolmnurgad)'
}, 403)
}
}
```
### **Тестирование** (результаты от 2026-01-14):
**Test 1**: Только текст problems → НЕ блокируется → `{"success":true}`
**Test 2**: Установлен error flag → БЛОКИРУЕТСЯ → `{"error":"blocked","message":"..."}`
---