diff --git a/ACCESS_RIGHTS.md b/ACCESS_RIGHTS.md
deleted file mode 100644
index dd994ff..0000000
--- a/ACCESS_RIGHTS.md
+++ /dev/null
@@ -1,217 +0,0 @@
-# 🔐 ПРАВА ДОСТУПА - МАТРИЦЫ РАЗРЕШЕНИЙ
-
-**Версия**: v4.1.17
-**Дата**: 2026-01-14
-**Обновление**: Уточнены права доступа User и Guest
-
----
-
-## 🔐 МАТРИЦА ПРАВ ДОСТУПА - РЕДАКТИРОВАНИЕ
-
-| Поле | Admin | User | Guest |
-|------|-------|------|-------|
-| **MAT-1** календарь | ✅ | ❌ | ❌ |
-| **MAT-1** подтверждение | ✅ | ✅ | ❌ |
-| **MAT-2** календарь | ✅ | ❌ | ❌ |
-| **MAT-2** подтверждение | ✅ | ✅ | ❌ |
-| **PAKETT** календарь | ✅ | ❌ | ❌ |
-| **Töölehti** toggle | ✅ | ✅ | ❌ |
-| **LÕIKUS** toggle | ✅ | ✅ | ❌ |
-| **KLAAS** toggle | ✅ | ✅ | ❌ |
-| **VALMIS** toggle | ✅* | ✅* | ❌ |
-| **VÄLJAS** toggle | ✅* | ✅* | ❌ |
-
-*Блокируется при наличии проблем/ошибок
-
----
-
-## 👁️ МАТРИЦА ПРАВ ДОСТУПА - ПРОСМОТР
-
-| Поле | Admin | User | Guest |
-|------|-------|------|-------|
-| **MAT-1** дата | ✅ | ✅ | ✅ |
-| **MAT-1** кнопка ✓ | ✅ | ✅ | ❌ |
-| **MAT-2** дата | ✅ | ✅ | ✅ |
-| **MAT-2** кнопка ✓ | ✅ | ✅ | ❌ |
-| **PAKETT** дата | ✅ | ✅ | ✅ |
-| **Töölehti** дата+статус | ✅ | ✅ | ✅ |
-| **LÕIKUS** дата | ✅ | ✅ | ✅ |
-| **KLAAS** дата | ✅ | ✅ | ✅ |
-| **VALMIS** дата | ✅ | ✅ | ✅ |
-| **VÄLJAS** дата | ✅ | ✅ | ✅ |
-
----
-
-## 👤 РОЛИ ПОЛЬЗОВАТЕЛЕЙ
-
-### **Admin** (admin, aknaproff)
-
-#### Редактирование:
-- ✅ **MAT-1**: выбор даты через календарь
-- ✅ **MAT-1**: подтверждение (кнопка ✓)
-- ✅ **MAT-2**: выбор даты через календарь
-- ✅ **MAT-2**: подтверждение (кнопка ✓)
-- ✅ **PAKETT**: выбор даты через календарь
-- ✅ **Töölehti**: полный контроль 3-шагового цикла
-- ✅ **LÕIKUS**: toggle даты
-- ✅ **KLAAS**: toggle даты
-- ✅ **VALMIS**: toggle даты (если нет блокировки)
-- ✅ **VÄLJAS**: toggle даты (если нет блокировки)
-- ✅ Добавление записей
-- ✅ Редактирование записей
-- ✅ Удаление записей
-- ✅ Изменение проблем и ошибок
-
-#### Просмотр:
-- ✅ Все поля видны полностью
-
----
-
-### **User** (kasutaja)
-
-#### Редактирование:
-- ❌ **MAT-1**: НЕТ доступа к календарю
-- ✅ **MAT-1**: ЕСТЬ доступ к подтверждению (кнопка ✓)
-- ❌ **MAT-2**: НЕТ доступа к календарю
-- ✅ **MAT-2**: ЕСТЬ доступ к подтверждению (кнопка ✓)
-- ❌ **PAKETT**: нет доступа к календарю
-- ✅ **Töölehti**: полный контроль 3-шагового цикла
-- ✅ **LÕIKUS**: toggle даты
-- ✅ **KLAAS**: toggle даты
-- ✅ **VALMIS**: toggle даты (если нет блокировки)
-- ✅ **VÄLJAS**: toggle даты (если нет блокировки)
-- ❌ Добавление/редактирование/удаление записей
-
-#### Просмотр:
-- ✅ **MAT-1, MAT-2**: видит дату + кнопку подтверждения
-- ✅ **PAKETT**: видит дату
-- ✅ **Töölehti, LÕIKUS, KLAAS, VALMIS, VÄLJAS**: видит дату
-
----
-
-### **Guest** (неавторизованный пользователь)
-
-#### Редактирование:
-- ❌ **Все поля**: нет доступа к редактированию
-
-#### Просмотр:
-- ✅ **MAT-1, MAT-2**: видит только дату (БЕЗ кнопки подтверждения)
-- ✅ **PAKETT**: видит дату
-- ✅ **Töölehti, LÕIKUS, KLAAS, VALMIS, VÄLJAS**: видит дату
-
----
-
-## 📊 ДЕТАЛЬНОЕ ОПИСАНИЕ
-
-### **MAT-1 (Material)**
-- **Admin**: открывает календарь + подтверждает
-- **User**: только подтверждает (кнопка ✓)
-- **Guest**: только просмотр даты
-
-### **MAT-2 (Material2)**
-- **Admin**: открывает календарь + подтверждает
-- **User**: только подтверждает (кнопка ✓)
-- **Guest**: только просмотр даты
-- **Блокировка**: если MAT-1 пустая
-
-### **PAKETT (Package)**
-- **Admin**: открывает календарь
-- **User**: только просмотр
-- **Guest**: только просмотр
-
-### **Töölehti (Worksheets)**
-- **Admin**: полный контроль 3-цикла
-- **User**: полный контроль 3-цикла
-- **Guest**: только просмотр
-
-### **LÕIKUS (Cutting)**
-- **Admin**: toggle (добавить/удалить дату)
-- **User**: toggle (добавить/удалить дату)
-- **Guest**: только просмотр
-
-### **KLAAS (Glazing)**
-- **Admin**: toggle (добавить/удалить дату)
-- **User**: toggle (добавить/удалить дату)
-- **Guest**: только просмотр
-
-### **VALMIS (Ready)**
-- **Admin**: toggle (если нет проблем/ошибок)
-- **User**: toggle (если нет проблем/ошибок)
-- **Guest**: только просмотр
-- **Блокировка**: при наличии проблем или ошибок
-
-### **VÄLJAS (Issued)**
-- **Admin**: toggle (если нет проблем/ошибок)
-- **User**: toggle (если нет проблем/ошибок)
-- **Guest**: только просмотр
-- **Блокировка**: при наличии проблем или ошибок
-
----
-
-## 🔑 ТЕХНИЧЕСКИЕ ДЕТАЛИ
-
-### **Backend проверка прав:**
-```typescript
-// optionalAuthMiddleware - разрешает Guest просмотр
-// authMiddleware - требует авторизацию
-
-// Календари (MAT-1, MAT-2, PAKETT)
-if (userRole !== 'admin') {
- return c.json({ error: 'Only admin can change dates' }, 403)
-}
-
-// Подтверждение (MAT-1, MAT-2)
-// Разрешено всем авторизованным (Admin + User)
-
-// Toggle (Töölehti, LÕIKUS, KLAAS, VALMIS, VÄLJAS)
-// Разрешено всем авторизованным (Admin + User)
-```
-
-### **Frontend проверка прав:**
-```javascript
-// canEditRecords() - проверяет наличие токена и роль
-// Для Admin + User = true
-// Для Guest = false
-
-// MAT-1/MAT-2 календарь
-if (currentUser.role !== 'admin') {
- // Скрыть календарь
-}
-
-// MAT-1/MAT-2 подтверждение
-if (!token) {
- // Скрыть кнопку ✓
-}
-
-// Toggle поля
-if (!canEditRecords()) {
- // Отключить клик
-}
-```
-
----
-
-## ✅ СВОДКА
-
-### **Что может Admin:**
-- 📅 Выбирать даты через календарь (MAT-1, MAT-2, PAKETT)
-- ✓ Подтверждать материалы
-- 🔄 Управлять всеми toggle-полями
-- ➕ Добавлять/редактировать/удалять записи
-
-### **Что может User:**
-- ❌ НЕ может выбирать даты через календарь
-- ✓ МОЖЕТ подтверждать материалы (MAT-1, MAT-2)
-- 🔄 МОЖЕТ управлять toggle-полями (Töölehti, LÕIKUS, KLAAS, VALMIS, VÄLJAS)
-- ❌ НЕ может добавлять/редактировать/удалять записи
-
-### **Что может Guest:**
-- 👁️ Только просмотр всех дат
-- ❌ НЕ видит кнопки подтверждения
-- ❌ НЕ может редактировать ничего
-
----
-
-**Статус**: ✅ Права доступа корректны
-**Версия**: v4.1.17
-**Дата**: 2026-01-14
diff --git a/CHANGELOG.md b/CHANGELOG.md
deleted file mode 100644
index 2e6eb63..0000000
--- a/CHANGELOG.md
+++ /dev/null
@@ -1,232 +0,0 @@
-# AKNAPROFF Tootmine - CHANGELOG
-
-## v4.1.10 - 2025-12-31 (HOTFIX - КРИТИЧЕСКИЕ ИСПРАВЛЕНИЯ)
-
-### 🔥 Критические исправления
-
-#### 1. Исправлена потеря данных при рестарте Docker
-- **Проблема:** Миграции пересоздавали БД при каждом запуске
-- **Симптомы:**
- - Существующая БД с 38 записями терялась
- - При обновлении страницы старые данные появлялись на секунду
-- **Решение:**
- - Добавлен флаг `SKIP_MIGRATIONS=true` в `docker-entrypoint.sh`
- - Добавлена переменная `SKIP_MIGRATIONS: "true"` в `docker-compose.yml`
- - Миграции теперь пропускаются по умолчанию
- - Используется готовая БД из `data/` директории
-- **Файлы:** `docker-entrypoint.sh`, `docker-compose.yml`
-
-#### 2. Исправлена ошибка 500 при добавлении записи
-- **Проблема:** `POST /api/records` возвращал 500 Internal Server Error
-- **Симптомы:**
- ```
- POST http://komo.aknaproff.ee:8180/api/records
- [HTTP/1.1 500 Internal Server Error]
- Save record error: "Failed to create record"
- ```
-- **Причина:** Таблица `production_records` требует поля `created_by` и `updated_by`, но они не передавались
-- **Решение:**
- - Добавлены поля `created_by` и `updated_by` в INSERT запрос
- - Добавлено поле `updated_by` в UPDATE запрос
- - Значения берутся из `userId` (из JWT токена)
-- **Файлы:** `src/index.tsx`, `dist/_worker.js`
-
-#### 3. Исправлена неработающая кнопка "Lisa uus rida"
-- **Проблема:** Admin не мог добавить новую запись
-- **Причина:** Ошибка 500 в backend (см. пункт 2)
-- **Решение:** Исправлен backend код
-- **Статус:** ✅ Теперь работает
-
-### 📝 Изменённые файлы
-
-#### Backend
-- **src/index.tsx**
- - `POST /api/records`: добавлены поля `created_by, updated_by` в INSERT
- - `PUT /api/records/:id`: добавлено поле `updated_by` в UPDATE
-
-- **dist/_worker.js**
- - Пересобран с исправлениями
-
-#### Docker
-- **docker-entrypoint.sh**
- - Добавлен флаг `SKIP_MIGRATIONS` (по умолчанию `true`)
- - Добавлена логика проверки `SKIP_MIGRATIONS`
- - При `SKIP_MIGRATIONS=true` миграции пропускаются
-
-- **docker-compose.yml**
- - Добавлена переменная `SKIP_MIGRATIONS: "true"`
-
-#### Frontend
-- **public/original.html**
- - Cache version обновлена: `app.js?v=4.1.10`
-
-### ⚠️ Breaking Changes
-Нет breaking changes. Полная обратная совместимость с v4.1.9.
-
-### 🔄 Миграция с v4.1.9
-1. Остановить контейнер: `docker-compose down`
-2. **КРИТИЧНО:** Сделать бэкап: `cp -r data data.backup.$(date +%Y%m%d_%H%M%S)`
-3. Заменить файлы (НЕ трогать `data/`)
-4. Проверить `SKIP_MIGRATIONS: "true"` в `docker-compose.yml`
-5. Запустить: `docker-compose up -d --build`
-6. Проверить данные: 38 записей должны остаться
-
-### ✅ Тесты
-- [x] Данные сохраняются между рестартами
-- [x] Миграции пропускаются (логи: "Skipping migrations")
-- [x] POST /api/records работает (200 OK)
-- [x] Кнопка "Lisa uus rida" работает
-- [x] created_by/updated_by записываются в БД
-- [x] Admin может добавлять записи
-- [x] User НЕ может добавлять записи
-- [x] User НЕ может редактировать заметки
-- [x] User может редактировать проблемы
-
-### 📦 Архивы
-- `aknaproff_production_v4.1.10_arm.tar.gz` (278 KB)
-- `aknaproff_production_v4.1.10_arm.zip` (318 KB)
-
----
-
-## v4.1.9 - 2025-12-30
-
-### 🔒 Исправлены права доступа
-
-#### 1. User теперь может только просматривать заметки (read-only)
-- **Проблема:** User мог редактировать заметки
-- **Решение:**
- - Frontend: `openNotesModal()` использует `canEditRecords()` (только admin)
- - Frontend: кнопка "Salvesta" скрыта для user
- - Backend: `PATCH /api/records/:id/notes` → Admin only (403 для user)
-- **Статус:** ✅ Исправлено
-
-#### 2. User может редактировать проблемы
-- **Backend:** `PATCH /api/records/:id/problems` → Admin + User
-- **Frontend:** UI показывает возможность редактирования
-- **Статус:** ✅ Работает
-
-#### 3. Кнопка "Lisa uus rida" скрыта для User и Guest
-- **Frontend:** Кнопка скрыта через `role-admin` CSS класс
-- **Backend:** Проверка роли перед созданием записи
-- **Статус:** ✅ Работает
-
-### 📊 Матрица прав доступа
-
-| Функция | Admin | User | Guest |
-|----------------------|-------|------|-------|
-| Просмотр записей | ✅ | ✅ | ✅ |
-| Добавить запись | ✅ | ❌ | ❌ |
-| Редактировать запись | ✅ | ❌ | ❌ |
-| Удалить запись | ✅ | ❌ | ❌ |
-| Просмотр заметок | ✅ | ✅ | ✅ |
-| Редактировать заметки| ✅ | ❌ | ❌ |
-| Просмотр проблем | ✅ | ✅ | ✅ |
-| Редактировать проблемы| ✅ | ✅ | ❌ |
-
-### 📝 Изменённые файлы
-- `public/static/app.js`: изменены `openNotesModal()`, `saveNotes()`
-- `src/index.tsx`: добавлены проверки роли в API
-- `public/original.html`: cache v4.1.9
-
----
-
-## v4.1.8 - 2025-12-30
-
-### 🐛 Исправления
-
-#### 1. Исправлены права пользователей
-- **Проблема:** User не мог редактировать Problems
-- **Решение:** Изменён `openProblemsModal()` на использование `canEditProblems()`
-
-#### 2. Скрыта кнопка "Lisa uus rida" для non-admin
-- **Frontend:** Кнопка скрыта для User и Guest ролей
-- **CSS:** Использован класс `.role-admin`
-
-#### 3. Добавлены колонки problems
-- **База данных:**
- - `problems` TEXT DEFAULT NULL
- - `problems_date` DATE DEFAULT NULL
-- **Миграции:** Применены в локальной БД
-
-#### 4. Исправлены названия полей audit_log
-- **Было:** `field_name`, `action_type`
-- **Стало:** `field`, `action`
-- **Файлы:** `src/index.tsx`
-
-### 📦 Изменения БД
-```sql
-ALTER TABLE production_records ADD COLUMN problems TEXT DEFAULT NULL;
-ALTER TABLE production_records ADD COLUMN problems_date DATE DEFAULT NULL;
-```
-
----
-
-## v4.1.7 - 2025-12-30
-
-### 🔐 Исправлена аутентификация
-
-#### 1. Исправлена система входа (bcrypt → SHA-256)
-- **Проблема:** Login failed - несовместимость хэшей
-- **Было:** Бэкап использовал bcrypt ($2a$)
-- **Стало:** Все пароли SHA-256
-- **Решение:** Обновлены все password_hash в БД
-
-#### 2. Удалён дубликат пользователя
-- **Удалён:** user `tootmine` (дубликат kasutaja)
-- **Причина:** Один человек, два аккаунта
-- **Статус:** ✅ Удалён
-
-#### 3. Добавлена колонка deleted_at
-- **Таблица:** `users`
-- **Тип:** `DATETIME DEFAULT NULL`
-- **Причина:** Код использовал `WHERE deleted_at IS NULL`, но колонки не было
-- **Статус:** ✅ Добавлена
-
-### 📊 База данных
-- **Записей:** 38 production records
-- **Пользователей:** 3 active
- - `admin` / `demo123` (admin)
- - `aknaproff` / `demo123` (admin)
- - `kasutaja` / `tootmine` (user)
-
-### 🔒 Учётные данные
-Все пароли теперь SHA-256:
-```
-admin: d3ad9315b7be5dd53b31a273b3b3aba5defe700808305aa16a3062b76658a791
-aknaproff: d3ad9315b7be5dd53b31a273b3b3aba5defe700808305aa16a3062b76658a791
-kasutaja: a1026b7bd143f7190248bc79901e9a357a408e208f2d8e4d38fccf184754f35f
-```
-
----
-
-## v4.1.6 и ранее
-
-См. файлы:
-- `CHANGES_v4.1.6.md`
-- `CHANGES_v4.1.5.md`
-- `CHANGES_v4.1.4.md`
-- `CHANGES_v4.1.3.md`
-- `CHANGES_v4.1.2.md`
-- `CHANGES_v4.1.0.md`
-
----
-
-## Легенда
-
-- 🔥 Критическое исправление
-- 🐛 Исправление бага
-- ✨ Новая функция
-- 🔒 Безопасность
-- 📝 Документация
-- 🔧 Конфигурация
-- 📊 База данных
-- 🎨 UI/UX
-- ⚡ Производительность
-- 🔄 Рефакторинг
-
----
-
-**Текущая версия:** v4.1.10
-**Дата:** 2025-12-31
-**Статус:** Production Ready ✅
-**Архитектура:** ARM64/AMD64 (Synology Compatible)
diff --git a/DATE_FIELDS_LOGIC.md b/DATE_FIELDS_LOGIC.md
deleted file mode 100644
index 31ff002..0000000
--- a/DATE_FIELDS_LOGIC.md
+++ /dev/null
@@ -1,381 +0,0 @@
-# 📋 ЛОГИКА ДАТ И ЧЕКБОКСОВ - ПОЛНОЕ РУКОВОДСТВО
-
-**Версия**: 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":"..."}`
-
----
diff --git a/Dockerfile b/Dockerfile
old mode 100755
new mode 100644
index 96d7451..a03395a
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,40 +1,58 @@
-# syntax=docker/dockerfile:1
+# Multi-stage build для оптимизации размера образа
+
+# Stage 1: Build
+FROM node:20-alpine AS builder
-# ---------- Build stage ----------
-FROM node:20-bookworm-slim AS builder
WORKDIR /app
-COPY package.json package-lock.json ./
-RUN npm install
+# Копировать package files
+COPY package*.json ./
+# Установить зависимости
+RUN npm ci --only=production
+
+# Копировать исходники
COPY . .
+
+# Собрать проект
RUN npm run build
-# ---------- Runtime stage ----------
-FROM node:20-bookworm-slim
+# Stage 2: Runtime
+FROM node:20-alpine
+
WORKDIR /app
-ENV NODE_ENV=production \
- WRANGLER_SEND_METRICS=false \
- PORT=3000 \
- D1_BINDING=aknaproff-db \
- PERSIST_PATH=/data
+# Установить dumb-init для правильной обработки сигналов
+RUN apk add --no-cache dumb-init
-# Copy everything from builder (includes node_modules, dist, migrations, etc.)
-COPY --from=builder /app /app
+# Создать пользователя без root
+RUN addgroup -g 1001 -S nodejs && \
+ adduser -S nodejs -u 1001
-# Create data directory
-RUN mkdir -p /data
+# Копировать зависимости из builder
+COPY --from=builder --chown=nodejs:nodejs /app/node_modules ./node_modules
+COPY --from=builder --chown=nodejs:nodejs /app/dist ./dist
+COPY --from=builder --chown=nodejs:nodejs /app/package.json ./
+COPY --from=builder --chown=nodejs:nodejs /app/wrangler.jsonc ./
+COPY --from=builder --chown=nodejs:nodejs /app/migrations ./migrations
+COPY --from=builder --chown=nodejs:nodejs /app/seed.sql ./
+# Создать директорию для локальной БД
+RUN mkdir -p .wrangler/state/v3/d1 && \
+ chown -R nodejs:nodejs .wrangler
+
+# Переключиться на непривилегированного пользователя
+USER nodejs
+
+# Открыть порт
EXPOSE 3000
-# Persist D1 SQLite data between restarts
-VOLUME ["/data"]
+# Health check
+HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
+ CMD wget --quiet --tries=1 --spider http://localhost:3000 || exit 1
-# Start wrangler directly (no bash script needed)
-CMD ["npx", "wrangler", "pages", "dev", "dist", \
- "--local", \
- "--d1=aknaproff-db", \
- "--persist-to=/data", \
- "--ip=0.0.0.0", \
- "--port=3000"]
+# Запуск с dumb-init
+ENTRYPOINT ["dumb-init", "--"]
+
+# Команда запуска
+CMD ["sh", "-c", "npm run db:reset && npx wrangler pages dev dist --d1=webapp-production --local --ip 0.0.0.0 --port 3000"]
diff --git a/FILES_TO_COPY.txt b/FILES_TO_COPY.txt
new file mode 100644
index 0000000..fe0d8dc
--- /dev/null
+++ b/FILES_TO_COPY.txt
@@ -0,0 +1,147 @@
+# 📦 Файлы для копирования на production сервер
+
+## Версия: v4.1.6 (Märkused Visual Indicators)
+## Дата: 2025-11-28
+
+---
+
+## 🆕 Что нового в v4.1.6
+
+### Визуальная индикация в поле "Märkused" (Notes)
+- **Желтый фон с ℹ️**: Когда есть текст заметки
+- **Иконка info-circle**: Информационная иконка "i"
+- **Tooltip**: При наведении курсора показывается полный текст заметки
+- **Пустое поле**: Прочерк `-` когда нет заметок
+
+### Предыдущие изменения (v4.1.5)
+- Восстановление визуальной индикации "Probleemid" (красный с ⚠️)
+
+### Предыдущие изменения (v4.1.4)
+- Упрощение формы логина: "Administrator Login" → "Login"
+
+### ⚠️ Для v4.1.3 требовалось обновление БД!
+
+Если обновляетесь с версии до v4.1.3, нужно применить seed.sql:
+- Добавлен новый пользователь **kasutaja** (password: tootmine)
+- Убрано слово "Sorteerimine" над кнопкой ID
+- Уточнена система ролей
+
+---
+
+## 🔥 Deployment
+
+### Вариант A: Обновление только v4.1.4 (БД уже обновлена)
+
+Если вы уже применили seed.sql в v4.1.3, просто обновите код:
+
+```bash
+# Быстрый вариант
+scp dist/_worker.js user@server:/path/to/webapp/dist/
+docker-compose restart
+
+# ИЛИ полный вариант
+scp public/original.html user@server:/path/to/webapp/public/
+scp src/original-html.ts user@server:/path/to/webapp/src/
+# На сервере: npm run build && docker-compose restart
+```
+
+### Вариант B: Полное обновление (с БД из v4.1.3)
+
+Если обновляетесь впервые или нужно добавить пользователя kasutaja:
+
+```bash
+# 1. Обновить базу данных
+scp seed.sql user@server:/path/to/webapp/
+docker-compose exec aknaproff-backend sh -c "
+ cd /app &&
+ npx wrangler d1 execute webapp-production --local --file=./seed.sql
+"
+
+# Проверить
+docker-compose exec aknaproff-backend sh -c "
+ npx wrangler d1 execute webapp-production --local \
+ --command='SELECT username, full_name, role FROM users'
+"
+
+# 2. Обновить код
+scp dist/_worker.js user@server:/path/to/webapp/dist/
+docker-compose restart
+```
+
+### Проверка после deployment
+```bash
+curl -I http://localhost:8180
+# Браузер: Ctrl+Shift+R, проверить текст "Login" и "Sisesta kasutajaandmed"
+```
+
+---
+
+## 📝 Список файлов для копирования
+
+### Для v4.1.6:
+- `dist/_worker.js` (быстрый вариант) **← рекомендуется**
+- ИЛИ `public/static/app.js` + `public/original.html` + `src/original-html.ts` (полный вариант)
+
+### Если также нужен пользователь kasutaja из v4.1.3:
+- `seed.sql` - добавляет kasutaja (tootmine)
+
+---
+
+## ✅ Проверка после deployment
+
+1. **HTTP**: `curl -I http://localhost:8180` → 200 OK
+
+2. **Браузер**:
+ - Открыть http://localhost:8180
+ - Нажать **Ctrl+Shift+R** (сброс кэша)
+ - Войти под любым пользователем (kasutaja/tootmine, aknaproff/demo123, admin/demo123)
+ - **Проверить поле "Probleemid"**:
+ - Запись с галочками → 🔴 красный фон с ⚠️
+ - Запись с текстом → ⚪ серый фон с ℹ️
+ - Запись без проблем → серый фон с `-`
+ - Навести курсор → показывает tooltip с текстом проблемы
+ - **Проверить поле "Märkused"**:
+ - Запись с заметкой (ID 2, 4) → 🟡 желтый фон с ℹ️
+ - Запись без заметки → серый фон с `-`
+ - Навести курсор → показывает tooltip с текстом заметки
+
+---
+
+## 🔐 Учётные данные
+
+| Username | Password | Role | Доступ |
+|----------|----------|------|--------|
+| kasutaja | tootmine | user | Просмотр + проблемы |
+| aknaproff | demo123 | admin | Полный доступ |
+| admin | demo123 | admin | Полный доступ |
+| guest | (без входа) | guest | Только просмотр |
+
+---
+
+## 📊 История версий
+
+| Версия | Изменения |
+|--------|-----------|
+| v4.1.6 | Визуальная индикация Märkused (желтый с ℹ️, tooltip) |
+| v4.1.5 | Восстановление визуальной индикации Probleemid (красный с ⚠️, tooltip) |
+| v4.1.4 | Упрощение текста формы логина |
+| v4.1.3 | Убрано "Sorteerimine", добавлен kasutaja, уточнены роли |
+| v4.1.2 | Кнопка Sorteerimine в Kiir otsing |
+| v4.1.1 | HOTFIX: continueAsGuest global access |
+| v4.1.0 | Auth система (guest/user/admin), сортировка по ID |
+
+---
+
+## 🔗 Документация
+
+- **CHANGES_v4.1.6.md** - детали v4.1.6 (Märkused визуализация)
+- **CHANGES_v4.1.5.md** - детали v4.1.5 (восстановление Probleemid визуализации)
+- **CHANGES_v4.1.4.md** - детали v4.1.4 (упрощение формы логина)
+- **CHANGES_v4.1.3.md** - детали v4.1.3 (UI + новый пользователь)
+- **CHANGES_v4.1.2.md** - детали v4.1.2 (перемещение кнопки)
+- **CHANGES_v4.1.0.md** - детали v4.1.0 (auth система)
+- **HOTFIX_v4.1.1.md** - hotfix continueAsGuest
+
+---
+
+**💡 Заметка**: v4.1.6 - добавление визуальной индикации в поле Märkused (желтый с ℹ️). БД не затронута.
diff --git a/HOTFIX_v4.1.11.md b/HOTFIX_v4.1.11.md
deleted file mode 100644
index c8b8cde..0000000
--- a/HOTFIX_v4.1.11.md
+++ /dev/null
@@ -1,181 +0,0 @@
-# AKNAPROFF v4.1.11 - HOTFIX
-
-**Дата:** 2025-12-31
-**Тип:** HOTFIX - Критическое исправление
-**Статус:** Production Ready ✅
-
----
-
-## 🐛 Исправленная проблема
-
-### ❌ Ошибка: "NOT NULL constraint failed: production_records.price"
-
-**Симптомы:**
-```
-POST /api/records
-[HTTP/2 500 Internal Server Error]
-Save record error: Failed to create record
-```
-
-**Консоль браузера:**
-```javascript
-Viga salvestamisel: Failed to create record
-Save record error: Request failed with status code 500
-```
-
-**Логи сервера:**
-```
-Error creating record: D1_ERROR: NOT NULL constraint failed: production_records.price: SQLITE_CONSTRAINT
-```
-
-**Причина:**
-В реальной БД колонка `price` имеет ограничение `NOT NULL`, но код передавал `null` вместо `0`.
-
-**Схема БД:**
-```sql
-CREATE TABLE production_records (
- ...
- price REAL NOT NULL, -- ⚠️ NOT NULL!
- ...
-);
-```
-
-**Старый код (v4.1.10):**
-```typescript
-const price = data.price ? parseFloat(data.price) : null // ❌ null вызывает ошибку
-```
-
-**Новый код (v4.1.11):**
-```typescript
-const price = data.price ? parseFloat(data.price) : 0 // ✅ 0 соответствует схеме
-```
-
----
-
-## ✅ Решение
-
-### Изменённые файлы:
-
-**src/index.tsx:**
-- POST /api/records: изменено `null` → `0` для price
-- PUT /api/records/:id: изменено `null` → `0` для price
-
-**public/original.html:**
-- Cache version: v4.1.11
-
-**dist/_worker.js:**
-- Пересобран с исправлениями
-
----
-
-## 🧪 Тестирование
-
-### Тест 1: Добавление записи без цены
-```bash
-curl -X POST http://localhost:3000/api/records \
- -H "Authorization: Bearer $TOKEN" \
- -H "Content-Type: application/json" \
- -d '{
- "month":"1",
- "year":"2025",
- "client_name":"Test Client",
- "offer_number":"TEST-001",
- "work_number":"WRK-001",
- "quantity":"5"
- }'
-```
-
-**Результат v4.1.10:** ❌ 500 Internal Server Error
-**Результат v4.1.11:** ✅ `{"success":true,"id":49}`
-
-### Тест 2: Проверка сохранённой записи
-```bash
-SELECT id, client_name, price FROM production_records WHERE id = 49
-```
-
-**Результат:**
-```
-id: 49
-client_name: "Test Client"
-price: 0 ✅
-```
-
-### Тест 3: Добавление записи с ценой
-```bash
-curl -X POST http://localhost:3000/api/records \
- -d '{"month":"1","year":"2025","client_name":"Test","offer_number":"123","work_number":"456","quantity":"1","price":"100.50"}'
-```
-
-**Результат:** ✅ `{"success":true,"id":50}`, price = 100.5
-
----
-
-## 🔄 Миграция с v4.1.10
-
-### Обновление не требует изменений БД
-
-Просто замените файлы:
-```bash
-# 1. Остановить
-docker-compose down
-
-# 2. Заменить код
-cp /path/to/new/dist/_worker.js dist/
-cp /path/to/new/src/index.tsx src/
-cp /path/to/new/public/original.html public/
-
-# 3. Запустить
-docker-compose up -d --build
-```
-
-**⚠️ НЕ трогайте data/ директорию!**
-
----
-
-## 📊 Сравнение версий
-
-| Параметр | v4.1.10 | v4.1.11 |
-|----------|---------|---------|
-| price default | null ❌ | 0 ✅ |
-| Добавление без цены | 500 ошибка ❌ | Работает ✅ |
-| Добавление с ценой | Работает ✅ | Работает ✅ |
-| NOT NULL constraint | Нарушается ❌ | Соблюдается ✅ |
-
----
-
-## ✅ Все проверки пройдены
-
-- [x] Добавление записи без цены → ✅ price = 0
-- [x] Добавление записи с ценой → ✅ price сохраняется
-- [x] Редактирование записи → ✅ price обновляется
-- [x] NOT NULL constraint → ✅ соблюдается
-- [x] Кнопка "Lisa uus rida" → ✅ работает
-- [x] Права доступа → ✅ admin может добавлять
-- [x] Cache version → ✅ v4.1.11
-
----
-
-## 🎯 Статус
-
-**Версия:** v4.1.11
-**Тип:** HOTFIX
-**Критичность:** Высокая (блокировала добавление записей)
-**Совместимость:** Полная обратная совместимость
-**Требуется миграция БД:** Нет
-**Статус:** Production Ready ✅
-
----
-
-## 📝 Changelog Summary
-
-```
-v4.1.11 (2025-12-31) - HOTFIX
-- Fixed: NOT NULL constraint failed for price column
-- Changed: price default value from null to 0
-- Files: src/index.tsx, dist/_worker.js, public/original.html
-- Status: Production Ready
-```
-
----
-
-**ПРОБЛЕМА ИСПРАВЛЕНА! Добавление записей теперь работает корректно.** ✅
diff --git a/HOTFIX_v4.1.12.md b/HOTFIX_v4.1.12.md
deleted file mode 100644
index 32be0a5..0000000
--- a/HOTFIX_v4.1.12.md
+++ /dev/null
@@ -1,211 +0,0 @@
-# AKNAPROFF v4.1.12 - HOTFIX: Редактирование записей
-
-**Дата:** 2025-12-31
-**Тип:** HOTFIX - Критическое исправление
-**Статус:** Production Ready ✅
-
----
-
-## 🐛 Исправленная проблема
-
-### ❌ Редактирование записей не сохранялось
-
-**Симптомы:**
-- При редактировании записи (клик на строку) модальное окно открывается
-- После изменения данных и сохранения - запись не обновляется
-- Идёт GET запрос, но данные остаются прежними
-- После перезагрузки страницы изменения не видны
-- **В модальном окне изменение даты тоже не сохраняется**
-
-**Проблема:**
-1. Backend НЕ обновлял таблицу `status_checkboxes` (где хранятся даты)
-2. Frontend передавал `null` для price вместо `0`
-
----
-
-## ✅ Решение
-
-### 1. Backend: Добавлено обновление status_checkboxes
-
-**Было (v4.1.11):**
-```typescript
-app.put('/api/records/:id', async (c) => {
- // Обновляется только production_records
- await c.env.DB.prepare(`
- UPDATE production_records
- SET client_name = ?, ...
- WHERE id = ?
- `).run()
-
- return c.json({ success: true })
-})
-```
-
-**Стало (v4.1.12):**
-```typescript
-app.put('/api/records/:id', async (c) => {
- // Обновляется production_records
- await c.env.DB.prepare(`
- UPDATE production_records
- SET client_name = ?, ...
- WHERE id = ?
- `).run()
-
- // ✅ Добавлено: Обновление status_checkboxes (даты)
- if (data.material_date !== undefined ||
- data.material2_date !== undefined ||
- data.package_date !== undefined) {
- await c.env.DB.prepare(`
- UPDATE status_checkboxes
- SET material_date = ?,
- material2_date = ?,
- package_date = ?,
- updated_at = CURRENT_TIMESTAMP
- WHERE record_id = ?
- `).bind(
- data.material_date || null,
- data.material2_date || null,
- data.package_date || null,
- id
- ).run()
- }
-
- return c.json({ success: true })
-})
-```
-
-### 2. Frontend: Исправлено значение по умолчанию для price
-
-**Было:**
-```javascript
-price: parseFloat(document.getElementById('price').value) || null // ❌
-```
-
-**Стало:**
-```javascript
-price: parseFloat(document.getElementById('price').value) || 0 // ✅
-```
-
----
-
-## 🧪 Тестирование
-
-### Тест 1: Обновление записи с датами
-```bash
-PUT /api/records/1
-{
- "client_name": "Updated Client",
- "offer_number": "UPD-001",
- "price": "250.50",
- "material_date": "2025-01-15",
- "material2_date": "2025-01-16",
- "package_date": "2025-01-17"
-}
-```
-
-**Результат v4.1.11:** ❌ Даты НЕ сохраняются
-**Результат v4.1.12:** ✅ Даты сохраняются
-
-### Тест 2: Проверка сохранённых данных
-
-**production_records:**
-```sql
-SELECT client_name, offer_number, price FROM production_records WHERE id = 1
--- Результат: Updated Client, UPD-001, 250.5 ✅
-```
-
-**status_checkboxes:**
-```sql
-SELECT material_date, material2_date, package_date
-FROM status_checkboxes WHERE record_id = 1
--- Результат: 2025-01-15, 2025-01-16, 2025-01-17 ✅
-```
-
-### Тест 3: UI - Редактирование через модальное окно
-1. Открыть запись (клик на строку)
-2. Изменить имя клиента
-3. Изменить даты (material_date, material2_date, package_date)
-4. Сохранить
-
-**Результат:** ✅ Все изменения сохраняются
-
----
-
-## 📝 Изменённые файлы
-
-| Файл | Изменения |
-|------|-----------|
-| **src/index.tsx** | Добавлен UPDATE для status_checkboxes |
-| **public/static/app.js** | price: null → 0 |
-| **public/original.html** | Cache v4.1.12 |
-| **dist/_worker.js** | Пересобран |
-
----
-
-## 🔄 Миграция с v4.1.11
-
-### Обновление не требует изменений БД
-
-```bash
-# 1. Остановить
-docker-compose down
-
-# 2. Заменить код
-cp new/dist/_worker.js dist/
-cp new/src/index.tsx src/
-cp new/public/ public/
-
-# 3. Запустить
-docker-compose up -d --build
-```
-
----
-
-## 📊 Сравнение версий
-
-| Параметр | v4.1.11 | v4.1.12 |
-|----------|---------|---------|
-| Редактирование записей | Не работает ❌ | Работает ✅ |
-| Сохранение дат | Не работает ❌ | Работает ✅ |
-| status_checkboxes UPDATE | Нет ❌ | Есть ✅ |
-| price default | null ❌ | 0 ✅ |
-
----
-
-## ✅ Все проверки пройдены
-
-- [x] Редактирование записей работает
-- [x] Даты сохраняются (material_date, material2_date, package_date)
-- [x] production_records обновляется
-- [x] status_checkboxes обновляется
-- [x] price = 0 по умолчанию
-- [x] UI модальное окно работает корректно
-- [x] После перезагрузки изменения видны
-
----
-
-## 🎯 Статус
-
-**Версия:** v4.1.12
-**Тип:** HOTFIX
-**Критичность:** Высокая (блокировала редактирование)
-**Совместимость:** Полная обратная совместимость
-**Требуется миграция БД:** Нет
-**Статус:** Production Ready ✅
-
----
-
-## 📝 Changelog Summary
-
-```
-v4.1.12 (2025-12-31) - HOTFIX
-- Fixed: Record editing not saving changes
-- Added: status_checkboxes UPDATE in PUT endpoint
-- Fixed: Date fields (material_date, material2_date, package_date) now save
-- Changed: price default from null to 0 in frontend
-- Status: Production Ready
-```
-
----
-
-**ПРОБЛЕМА ИСПРАВЛЕНА! Редактирование записей и дат теперь работает корректно.** ✅
diff --git a/HOTFIX_v4.1.15.md b/HOTFIX_v4.1.15.md
deleted file mode 100644
index b34197e..0000000
--- a/HOTFIX_v4.1.15.md
+++ /dev/null
@@ -1,196 +0,0 @@
-# 🔧 HOTFIX v4.1.15 - DATE FIELDS DISPLAY FIX
-
-**Release Date**: 2026-01-14
-**Priority**: CRITICAL - Fixes invisible date fields
-**Status**: ✅ Production Ready
-
----
-
-## 🐛 ПРОБЛЕМА
-
-**Симптомы:**
-- Даты НЕ отображаются в полях: PAKETT, Töölehti, LÕIKUS, KLAAS, VALMIS, VÄLJAS
-- Клик по ячейке не показывает дату
-- API запросы проходят без ошибок
-- Frontend получает `null` вместо дат
-
-**Причина:**
-1. **Строковые "null"** вместо SQL NULL в БД
-2. Backend записывал строку `"null"` вместо настоящего NULL
-3. Toggle отправлял `date: null`, что интерпретировалось как "установить NULL"
-
----
-
-## ✅ ИСПРАВЛЕНИЯ
-
-### 1. Backend UPDATE для status_checkboxes (v4.1.12 → v4.1.13)
-**Файл:** `src/index.tsx`
-
-```typescript
-// ❌ БЫЛО:
-data.material_date || null,
-data.material2_date || null,
-data.package_date || null,
-
-// ✅ СТАЛО:
-const materialDate = (data.material_date && data.material_date !== 'null') ? data.material_date : null
-const material2Date = (data.material2_date && data.material2_date !== 'null') ? data.material2_date : null
-const packageDate = (data.package_date && data.package_date !== 'null') ? data.package_date : null
-```
-
-### 2. Backend PATCH /api/records/:id/status (v4.1.13 → v4.1.14)
-**Файл:** `src/index.tsx`
-
-```typescript
-// ❌ БЫЛО:
-const newDate = date !== undefined ? date : (oldRecord?.[dbField] ? null : new Date().toISOString().split('T')[0])
-
-// ✅ СТАЛО:
-let newDate: string | null
-if (date !== undefined) {
- // Явная конвертация строки "null" в NULL
- newDate = (date && date !== 'null') ? date : null
-} else {
- // Toggle: если дата есть → удалить, если нет → установить сегодня
- newDate = oldRecord?.[dbField] ? null : new Date().toISOString().split('T')[0]
-}
-```
-
-### 3. Frontend toggleDate (v4.1.14 → v4.1.15)
-**Файл:** `public/static/app.js`
-
-```javascript
-// ❌ БЫЛО:
-{ field, date: currentDate } // Передавался null, блокируя toggle
-
-// ✅ СТАЛО:
-{ field } // НЕ передаётся date, активируется toggle логика
-```
-
-### 4. Database Fix
-**Исправлены все строковые "null" в БД:**
-```sql
-UPDATE status_checkboxes SET material_date = NULL WHERE material_date = 'null';
-UPDATE status_checkboxes SET material2_date = NULL WHERE material2_date = 'null';
-UPDATE status_checkboxes SET package_date = NULL WHERE package_date = 'null';
-UPDATE status_checkboxes SET worksheets_date = NULL WHERE worksheets_date = 'null';
-UPDATE status_checkboxes SET cutting_date = NULL WHERE cutting_date = 'null';
-UPDATE status_checkboxes SET glazing_date = NULL WHERE glazing_date = 'null';
-UPDATE status_checkboxes SET ready_date = NULL WHERE ready_date = 'null';
-UPDATE status_checkboxes SET issued_date = NULL WHERE issued_date = 'null';
-```
-
----
-
-## ✅ РЕЗУЛЬТАТ
-
-### Протестировано:
-1. **MAT-1, MAT-2, PAKETT** - календари работают ✅
-2. **Töölehti, LÕIKUS, KLAAS** - toggle работает ✅
-3. **VALMIS, VÄLJAS** - toggle с блокировкой работает ✅
-4. **Даты отображаются** в API и таблице ✅
-5. **Toggle ON/OFF** корректно работает ✅
-
-### Тестовые команды:
-```bash
-# Toggle ON
-curl -X PATCH "http://localhost:3000/api/records/49/status" \
- -H "Authorization: Bearer $TOKEN" \
- -d '{"field":"worksheets"}'
-# Результат: worksheets_date = "2026-01-14"
-
-# Toggle OFF
-curl -X PATCH "http://localhost:3000/api/records/49/status" \
- -H "Authorization: Bearer $TOKEN" \
- -d '{"field":"worksheets"}'
-# Результат: worksheets_date = null
-```
-
----
-
-## 🚀 РАЗВЁРТЫВАНИЕ
-
-### Быстрое обновление:
-```bash
-# 1. Остановить сервис
-docker-compose down
-
-# 2. Бэкап данных
-cp -r data data.backup.$(date +%Y%m%d)
-
-# 3. Распаковать v4.1.15
-unzip aknaproff_production_v4.1.15_FINAL.zip
-cd backend
-
-# 4. Исправить БД (ВАЖНО!)
-cat > /tmp/fix_nulls.sql << 'EOF'
-UPDATE status_checkboxes SET material_date = NULL WHERE material_date = 'null';
-UPDATE status_checkboxes SET material2_date = NULL WHERE material2_date = 'null';
-UPDATE status_checkboxes SET package_date = NULL WHERE package_date = 'null';
-UPDATE status_checkboxes SET worksheets_date = NULL WHERE worksheets_date = 'null';
-UPDATE status_checkboxes SET cutting_date = NULL WHERE cutting_date = 'null';
-UPDATE status_checkboxes SET glazing_date = NULL WHERE glazing_date = 'null';
-UPDATE status_checkboxes SET ready_date = NULL WHERE ready_date = 'null';
-UPDATE status_checkboxes SET issued_date = NULL WHERE issued_date = 'null';
-EOF
-
-# Применить исправление (если используется SQLite напрямую)
-sqlite3 data/v3/d1/miniflare-D1DatabaseObject/*.sqlite < /tmp/fix_nulls.sql
-
-# 5. Запустить сервис
-docker-compose up -d --build
-
-# 6. Проверить
-curl http://localhost:8180/api/records?month=1&year=2025
-```
-
----
-
-## 📊 СРАВНЕНИЕ ВЕРСИЙ
-
-| Функция | v4.1.12 | v4.1.15 |
-|---------|---------|---------|
-| Даты отображаются | ❌ Все NULL | ✅ Корректно |
-| Toggle работает | ❌ Не работает | ✅ Работает |
-| Редактирование дат | ❌ Строковые "null" | ✅ Настоящие NULL |
-| Backend UPDATE | ❌ `\|\| null` | ✅ Явная конвертация |
-| Frontend toggle | ❌ Передаёт `date: null` | ✅ Не передаёт date |
-| БД целостность | ❌ Строковые "null" | ✅ SQL NULL |
-
----
-
-## 📝 CHANGELOG
-
-### v4.1.15 (2026-01-14) - HOTFIX
-- ✅ Frontend: toggleDate НЕ передаёт date параметр
-- ✅ Cache version обновлён до 4.1.15
-
-### v4.1.14 (2026-01-14) - HOTFIX
-- ✅ Backend: улучшена логика toggle с явной конвертацией "null"
-- ✅ БД: исправлены все строковые "null" → SQL NULL
-
-### v4.1.13 (2026-01-14) - HOTFIX
-- ✅ Backend: добавлена конвертация "null" строк в UPDATE status_checkboxes
-- ✅ Frontend: price default изменён с null на 0
-
-### v4.1.12 (2026-01-14)
-- ✅ Backend: UPDATE теперь обновляет ОБЕ таблицы
-- ✅ Frontend: исправлен price || null → || 0
-
----
-
-## 🎯 СТАТУС
-
-**ВСЁ РАБОТАЕТ!**
-- ✅ Даты видны в таблице
-- ✅ Toggle работает (ON/OFF)
-- ✅ Календари работают (MAT-1, MAT-2, PAKETT)
-- ✅ Блокировка VALMIS/VÄLJAS работает
-- ✅ Audit log записывается
-- ✅ Права доступа корректны
-
----
-
-**Version**: v4.1.15 FINAL
-**Build Date**: 2026-01-14
-**Status**: Production Ready ✅
diff --git a/HOTFIX_v4.1.16.md b/HOTFIX_v4.1.16.md
deleted file mode 100644
index 79069ce..0000000
--- a/HOTFIX_v4.1.16.md
+++ /dev/null
@@ -1,172 +0,0 @@
-# 🔧 HOTFIX v4.1.16 - КРИТИЧЕСКИЕ ИСПРАВЛЕНИЯ
-
-**Дата**: 2026-01-14
-**Тип**: Critical Bugfix Release
-**Статус**: ✅ Production Ready
-
----
-
-## 🚨 **КРИТИЧЕСКИЕ ПРОБЛЕМЫ ИСПРАВЛЕНЫ**
-
-### **Проблема 1: Даты не отображаются** ❌➡️✅
-**Симптом:**
-- Поля Töölehti, LÕIKUS, KLAAS, VALMIS, VÄLJAS показывали пустые ячейки
-- Даты были в БД, но не отображались в UI
-- API возвращал даты, но frontend их не показывал
-
-**Причина:**
-```
-database disk image is malformed: SQLITE_CORRUPT
-```
-База данных была повреждена из-за WAL-файлов
-
-**Решение:**
-```bash
-# Удалить поврежденную БД
-rm -rf .wrangler/state/v3/d1/miniflare-D1DatabaseObject/*.sqlite*
-
-# Восстановить чистую копию
-cp tootmine-aknaprof-dump.sqlite .wrangler/state/v3/d1/miniflare-D1DatabaseObject/
-```
-
-**Результат:** ✅ Все даты теперь видны
-
----
-
-### **Проблема 2: Töölehti цикл неправильный** ❌➡️✅
-**Симптом:**
-- При 1-м клике: дата появляется
-- При 2-м клике: исчезает (должен быть серый фон!)
-- При 3-м клике: появляется снова
-- При 4-м клике: исчезает
-
-**Старая логика (НЕПРАВИЛЬНО):**
-```typescript
-// Step 1: empty -> confirmed (NO date) ❌
-if (!worksheets_date && !worksheets_confirmed) {
- newConfirmed = 1
- newDate = null
-}
-
-// Step 2: confirmed -> add date ❌
-else if (!worksheets_date && worksheets_confirmed) {
- newConfirmed = 1
- newDate = TODAY
-}
-
-// Step 3: with date -> empty ✅
-else {
- newConfirmed = 0
- newDate = null
-}
-```
-
-**Новая логика (ПРАВИЛЬНО):**
-```typescript
-// Step 1: empty -> gray with date ✅
-if (!worksheets_date) {
- newConfirmed = 0
- newDate = TODAY
-}
-
-// Step 2: gray -> green (KEEP date) ✅
-else if (worksheets_confirmed === 0) {
- newConfirmed = 1
- newDate = worksheets_date // Keep existing!
-}
-
-// Step 3: green -> empty ✅
-else {
- newConfirmed = 0
- newDate = null
-}
-```
-
-**Результат:**
-- ✅ 1-й клик: дата + серый фон
-- ✅ 2-й клик: дата + зеленый фон
-- ✅ 3-й клик: пусто
-
----
-
-## 📋 **ТЕСТИРОВАНИЕ**
-
-### **Test 1: Даты видны**
-```bash
-curl "http://localhost:3000/api/records?month=1&year=2025" | jq '.[0]'
-```
-**Результат:**
-```json
-{
- "id": 1,
- "worksheets_date": "2025-11-26",
- "worksheets_confirmed": 1,
- "cutting_date": "2025-01-10",
- "glazing_date": "2025-01-12",
- "ready_date": "2025-01-14",
- "issued_date": "2025-01-15"
-}
-```
-✅ Все даты возвращаются
-
-### **Test 2: Töölehti 3-step цикл**
-```bash
-# Step 1: Empty -> Gray
-PATCH /api/records/2/worksheets-cycle
-→ {"date": "2026-01-14", "confirmed": 0}
-
-# Step 2: Gray -> Green
-PATCH /api/records/2/worksheets-cycle
-→ {"date": "2026-01-14", "confirmed": 1}
-
-# Step 3: Green -> Empty
-PATCH /api/records/2/worksheets-cycle
-→ {"date": null, "confirmed": 0}
-```
-✅ Цикл работает идеально
-
----
-
-## 📦 **ЧТО ИЗМЕНЕНО**
-
-### **Изменённые файлы:**
-1. `src/index.tsx` - исправлена логика worksheets-cycle
-2. `dist/_worker.js` - пересобран с новой логикой
-3. `data/.../2b35d4d42e3c9f6b5ad5b5579a7b1470c66e69f6b33a31e3f5a0095cc6d18656.sqlite` - восстановлена чистая БД
-
----
-
-## 🎯 **БЫСТРОЕ ОБНОВЛЕНИЕ**
-
-### **На сервере:**
-```bash
-# 1. Остановить сервисы
-docker-compose down
-
-# 2. Распаковать новый архив
-unzip aknaproff_production_v4.1.16_FINAL.zip
-
-# 3. Заменить файлы
-cd backend/
-docker-compose up -d --build
-
-# 4. Проверить
-curl http://localhost:8180/api/records?month=1&year=2025 | jq '.[0]'
-```
-
----
-
-## ✅ **СТАТУС**
-
-- ✅ Даты видны во всех полях
-- ✅ Töölehti цикл работает правильно (серый → зеленый → пусто)
-- ✅ База данных восстановлена (48 записей)
-- ✅ Все тесты проходят
-- ✅ Production ready
-
----
-
-**Версия**: AKNAPROFF v4.1.16
-**Архив**: aknaproff_production_v4.1.16_FINAL.tar.gz (292 KB)
-**База данных**: 48 реальных записей (2025-2026)
-**Docker**: ARM Synology ready ✅
diff --git a/HOTFIX_v4.1.17.md b/HOTFIX_v4.1.17.md
deleted file mode 100644
index 07a7999..0000000
--- a/HOTFIX_v4.1.17.md
+++ /dev/null
@@ -1,204 +0,0 @@
-# 🔧 HOTFIX v4.1.17 - TOGGLE FIX (LÕIKUS, KLAAS, VALMIS, VÄLJAS)
-
-**Дата**: 2026-01-14
-**Тип**: Critical Bugfix Release
-**Статус**: ✅ Production Ready
-
----
-
-## 🚨 **КРИТИЧЕСКАЯ ПРОБЛЕМА ИСПРАВЛЕНА**
-
-### **Проблема: LÕIKUS, KLAAS, VALMIS, VÄLJAS не работали** ❌
-
-**Симптом:**
-- Клик по ячейке есть
-- API запрос уходит (200 OK)
-- Даты НЕ появляются после клика
-- Даты исчезают после первого клика
-
-**Причина 1: Frontend не передавал `date`**
-
-В текущем коде:
-```javascript
-// app.js:1123 (❌ НЕПРАВИЛЬНО)
-{ field } // date отсутствует!
-```
-
-В оригинальном коде:
-```javascript
-// original app.js:1047 (✅ ПРАВИЛЬНО)
-{ field, date: currentDate }
-```
-
-**Причина 2: Backend toggle логика неправильная**
-
-Старая логика:
-```typescript
-if (date === oldRecord?.[dbField]) {
- newDate = null // Clear
-} else if (!date) {
- newDate = TODAY // Add today
-}
-```
-
-Проблема: `null === null` → true → очищает вместо добавления!
-
-**Новая логика:**
-```typescript
-if (!date || date === 'null') {
- // null/empty clicked
- if (oldRecord?.[dbField]) {
- newDate = null // Cell has date → clear it
- } else {
- newDate = TODAY // Cell is empty → add today
- }
-} else if (date === oldRecord?.[dbField]) {
- newDate = null // Same date → toggle off
-} else {
- newDate = date // Different date → use it
-}
-```
-
----
-
-## ✅ **РЕШЕНИЕ**
-
-### **1. Frontend: Передавать `currentDate`**
-
-```javascript
-// public/static/app.js:1121
-const response = await axios.patch(
- `${API_BASE}/api/records/${recordId}/status`,
- { field, date: currentDate }, // ✅ Добавлен date
- { headers }
-);
-```
-
-### **2. Backend: Правильная toggle логика**
-
-```typescript
-// src/index.tsx:329
-if (!date || date === 'null') {
- // Пустая ячейка кликнута
- if (oldRecord?.[dbField]) {
- newDate = null // Есть дата → удалить
- } else {
- newDate = new Date().toISOString().split('T')[0] // Нет даты → добавить сегодня
- }
-} else if (date === oldRecord?.[dbField]) {
- // Та же дата → toggle off
- newDate = null
-} else {
- // Другая дата → использовать её
- newDate = date
-}
-```
-
----
-
-## 🧪 **ТЕСТИРОВАНИЕ**
-
-### ✅ **Test 1: Toggle с датой**
-```bash
-# Initial: has date (2025-01-11)
-GET /api/records → glazing_date: "2025-01-11"
-
-# Click: same date → should clear
-PATCH /api/records/2/status {"field":"glazing","date":"2025-01-11"}
-→ Result: null ✅
-```
-
-### ✅ **Test 2: Toggle пустой ячейки**
-```bash
-# Initial: empty
-GET /api/records → glazing_date: null
-
-# Click: null → should add today
-PATCH /api/records/2/status {"field":"glazing","date":null}
-→ Result: "2026-01-14" ✅
-```
-
-### ✅ **Test 3: Toggle сегодняшней даты**
-```bash
-# Initial: has today
-GET /api/records → glazing_date: "2026-01-14"
-
-# Click: today's date → should clear
-PATCH /api/records/2/status {"field":"glazing","date":"2026-01-14"}
-→ Result: null ✅
-```
-
----
-
-## 📊 **СРАВНЕНИЕ**
-
-| Действие | v4.1.16 | v4.1.17 |
-|---------|---------|---------|
-| **Клик по пустой ячейке** | ❌ Ничего | ✅ Добавляет сегодня |
-| **Клик по ячейке с датой** | ❌ Не меняется / исчезает | ✅ Удаляет дату |
-| **Передача date в API** | ❌ Не передавалось | ✅ Передается currentDate |
-| **Toggle логика** | ❌ Неправильная (null === null) | ✅ Правильная (проверяет oldRecord) |
-
----
-
-## 📦 **ИЗМЕНЁННЫЕ ФАЙЛЫ**
-
-1. **public/static/app.js** (строка 1121-1125)
- - Добавлен `date: currentDate` в PATCH запрос
-
-2. **src/index.tsx** (строка 329-348)
- - Исправлена toggle логика
- - Добавлена проверка oldRecord перед toggle
-
-3. **dist/_worker.js** (133.43 kB)
- - Пересобран с новой логикой
-
----
-
-## 🚀 **ОБНОВЛЕНИЕ**
-
-### **На сервере:**
-```bash
-# 1. Остановить
-docker-compose down
-
-# 2. Распаковать v4.1.17
-unzip aknaproff_production_v4.1.17_FINAL.zip
-
-# 3. Запустить
-cd backend/
-docker-compose up -d --build
-
-# 4. Проверить
-curl http://localhost:8180/api/records?month=1&year=2025 | jq '.[0]'
-```
-
-### **Проверка:**
-```bash
-# Даты видны
-→ worksheets_date: "2025-11-26"
-→ cutting_date: "2025-01-10"
-→ glazing_date: "2025-01-12"
-→ ready_date: "2025-01-14"
-→ issued_date: "2025-01-15"
-```
-
----
-
-## ✅ **СТАТУС**
-
-- ✅ LÕIKUS toggle работает
-- ✅ KLAAS toggle работает
-- ✅ VALMIS toggle работает
-- ✅ VÄLJAS toggle работает
-- ✅ Töölehti 3-цикл работает
-- ✅ MAT-1, MAT-2, PAKETT календари работают
-- ✅ 48 реальных записей на месте
-- ✅ Production ready
-
----
-
-**Версия**: AKNAPROFF v4.1.17 FINAL
-**Дата**: 2026-01-14
-**Архив**: aknaproff_production_v4.1.17_FINAL.tar.gz
-**Статус**: ✅ Production Ready
diff --git a/HOTFIX_v4.1.18.md b/HOTFIX_v4.1.18.md
deleted file mode 100644
index 0e32ca4..0000000
--- a/HOTFIX_v4.1.18.md
+++ /dev/null
@@ -1,203 +0,0 @@
-# 🔧 HOTFIX v4.1.18 - USER PERMISSIONS FIX
-
-**Дата**: 2026-01-14
-**Тип**: Critical Bugfix Release
-**Статус**: ✅ Production Ready
-
----
-
-## 🚨 **КРИТИЧЕСКАЯ ПРОБЛЕМА ИСПРАВЛЕНА**
-
-### **Проблема: User (kasutaja) не мог toggle поля**
-
-**Симптом:**
-```
-Логин: kasutaja / tootmine
-Клик по Töölehti → Ошибка: "Sul pole õigust töölehe staatust muuta. Palun logi sisse administraatorina."
-Клик по LÕIKUS → Ошибка: "Sul pole õigust andmeid muuta. Palun logi sisse administraatorina."
-```
-
-**По документации User ДОЛЖЕН иметь доступ:**
-- ✅ Подтверждение MAT-1/MAT-2
-- ✅ Toggle полей (Töölehti, LÕIKUS, KLAAS, VALMIS, VÄLJAS)
-
----
-
-## 🔍 **ПРИЧИНА**
-
-### **Frontend проверка прав была неправильной:**
-
-**Старый код (app.js:28):**
-```javascript
-function canEditRecords() {
- // Only admin can edit records
- return currentUser && currentUser.role === 'admin'; // ❌ Только admin!
-}
-
-// В toggleDate и toggleWorksheetsStep:
-if (!canEditRecords()) { // ❌ Блокирует User!
- alert('Sul pole õigust...');
- return;
-}
-```
-
-**Проблема:**
-- `canEditRecords()` разрешает ТОЛЬКО `admin`
-- `toggleDate()` и `toggleWorksheetsStep()` используют `canEditRecords()`
-- User (kasutaja) не может toggle!
-
----
-
-## ✅ **РЕШЕНИЕ**
-
-### **Создана новая функция `canToggleDates()`:**
-
-**Новый код (app.js:28-36):**
-```javascript
-function canEditRecords() {
- // Only admin can edit records (add/edit/delete)
- return currentUser && currentUser.role === 'admin';
-}
-
-function canToggleDates() {
- // Admin and User can toggle dates
- return currentUser && (currentUser.role === 'admin' || currentUser.role === 'user');
-}
-
-function isGuest() {
- // Check if user is guest (read-only)
- return !currentUser || currentUser.role === 'guest';
-}
-```
-
-### **Обновлены функции toggle:**
-
-**toggleDate (app.js:1111):**
-```javascript
-async function toggleDate(recordId, field, currentDate) {
- // Check permissions - admin and user can toggle dates
- if (!canToggleDates()) { // ✅ Использует canToggleDates()
- alert('Sul pole õigust andmeid muuta. Palun logi sisse.');
- return;
- }
- // ...
-}
-```
-
-**toggleWorksheetsStep (app.js:1647):**
-```javascript
-async function toggleWorksheetsStep(recordId) {
- // Check permissions - admin and user can toggle
- if (!canToggleDates()) { // ✅ Использует canToggleDates()
- alert('Sul pole õigust töölehe staatust muuta. Palun logi sisse.');
- return;
- }
- // ...
-}
-```
-
----
-
-## 🧪 **ТЕСТИРОВАНИЕ**
-
-### ✅ **Test: User (kasutaja) permissions**
-
-```bash
-# Login as User
-TOKEN=$(curl -s -X POST http://localhost:3000/api/auth/login \
- -H "Content-Type: application/json" \
- -d '{"username":"kasutaja","password":"tootmine"}' | jq -r '.token')
-
-# Test 1: Toggle Töölehti
-curl -s -X PATCH http://localhost:3000/api/records/2/worksheets-cycle \
- -H "Authorization: Bearer $TOKEN" | jq
-→ {"success": true, "date": "2026-01-14", "confirmed": 0} ✅
-
-# Test 2: Toggle LÕIKUS
-curl -s -X PATCH http://localhost:3000/api/records/3/status \
- -H "Authorization: Bearer $TOKEN" \
- -H "Content-Type: application/json" \
- -d '{"field":"cutting","date":"2025-01-12"}' | jq
-→ {"success": true} ✅
-
-# Test 3: Toggle KLAAS
-curl -s -X PATCH http://localhost:3000/api/records/3/status \
- -H "Authorization: Bearer $TOKEN" \
- -H "Content-Type: application/json" \
- -d '{"field":"glazing","date":"2025-01-13"}' | jq
-→ {"success": true} ✅
-```
-
----
-
-## 📊 **СРАВНЕНИЕ**
-
-| Действие | v4.1.17 (User) | v4.1.18 (User) |
-|---------|----------------|----------------|
-| **Toggle Töölehti** | ❌ Ошибка | ✅ Работает |
-| **Toggle LÕIKUS** | ❌ Ошибка | ✅ Работает |
-| **Toggle KLAAS** | ❌ Ошибка | ✅ Работает |
-| **Toggle VALMIS** | ❌ Ошибка | ✅ Работает |
-| **Toggle VÄLJAS** | ❌ Ошибка | ✅ Работает |
-| **Добавление записи** | ❌ Нет доступа | ❌ Нет доступа (правильно) |
-| **Календарь MAT-1** | ❌ Нет доступа | ❌ Нет доступа (правильно) |
-| **Подтверждение MAT-1** | ✅ Работает | ✅ Работает |
-
----
-
-## 📦 **ИЗМЕНЁННЫЕ ФАЙЛЫ**
-
-1. **public/static/app.js** (строки 28-36, 1113, 1648)
- - Добавлена функция `canToggleDates()`
- - Обновлена проверка в `toggleDate()`
- - Обновлена проверка в `toggleWorksheetsStep()`
-
-2. **dist/_worker.js** (133.43 kB)
- - Пересобран с новой логикой
-
----
-
-## 🚀 **ОБНОВЛЕНИЕ**
-
-### **На сервере:**
-```bash
-# 1. Остановить
-docker-compose down
-
-# 2. Распаковать v4.1.18
-unzip aknaproff_production_v4.1.18_FINAL.zip
-
-# 3. Запустить
-cd backend/
-docker-compose up -d --build
-```
-
-### **Проверка:**
-```bash
-# Логин под User
-curl -X POST http://localhost:8180/api/auth/login \
- -H "Content-Type: application/json" \
- -d '{"username":"kasutaja","password":"tootmine"}'
-→ {"success":true,"token":"...","user":{"username":"kasutaja","role":"user"}}
-
-# Открыть браузер → http://localhost:8180
-# Логин: kasutaja / tootmine
-# Кликнуть Töölehti → должно работать без ошибки
-```
-
----
-
-## ✅ **СТАТУС**
-
-- ✅ User (kasutaja) может toggle все поля
-- ✅ Admin (admin, aknaproff) работает как раньше
-- ✅ Guest может только просматривать
-- ✅ Права доступа корректны
-- ✅ Production ready
-
----
-
-**Версия**: AKNAPROFF v4.1.18 FINAL
-**Дата**: 2026-01-14
-**Архив**: aknaproff_production_v4.1.18_FINAL.tar.gz
-**Статус**: ✅ Production Ready
diff --git a/HOTFIX_v4.1.19.md b/HOTFIX_v4.1.19.md
deleted file mode 100644
index 6f152d0..0000000
--- a/HOTFIX_v4.1.19.md
+++ /dev/null
@@ -1,138 +0,0 @@
-# 🔧 HOTFIX v4.1.19 - ИСПРАВЛЕНА ЛОГИКА БЛОКИРОВКИ VALMIS/VÄLJAS
-
-**Дата**: 2026-01-14
-**Версия**: v4.1.19 FINAL
-**Приоритет**: HIGH (Критическая ошибка в логике)
-
----
-
-## 📋 **ПРОБЛЕМА**
-
-### **Неправильная блокировка VALMIS/VÄLJAS**
-
-**Ожидаемое поведение:**
-- VALMIS/VÄLJAS блокируются **ТОЛЬКО** если установлены error флаги (красные галочки ✗)
-- Текст в поле "Probleemid" (серая метка ⚠️) **НЕ** должен блокировать
-
-**Фактическое поведение (до v4.1.19):**
-- ❌ В документации было написано что блокируется и по тексту problems
-- ❌ В коде проверка была правильная, но документация - неправильная
-- ❌ Пользователи не понимали когда будет блокировка
-
----
-
-## ✅ **ИСПРАВЛЕНИЯ**
-
-### **1. Обновлена документация DATE_FIELDS_LOGIC.md**
-
-Секции VALMIS и VÄLJAS теперь чётко указывают:
-
-```markdown
-### **ВАЖНО: ТЕКСТ ПРОБЛЕМЫ НЕ БЛОКИРУЕТ!**
-Текст в поле "Probleemid" (серая метка ⚠️) **НЕ** блокирует VALMIS!
-
-### **Блокировка:**
-Поле **ЗАБЛОКИРОВАНО ТОЛЬКО**, если установлен **ЛЮБОЙ error флаг** (красная галочка ✗):
- - `worksheets_error = 1`
- - `cutting_error = 1`
- - `glazing_error = 1`
- - `ready_error = 1`
- - `issued_error = 1`
-
-**НЕ блокируется**, если:
-- Есть только текст в `production_records.problems` (серая метка ⚠️)
-- Все error флаги = 0
-```
-
-### **2. Добавлена новая секция в конец документа**
-
-Создана секция "🔒 ВАЖНО: ПРАВИЛО БЛОКИРОВКИ VALMIS/VÄLJAS" с:
-- Подробным описанием правил
-- Код проверки блокировки из backend
-- Результаты тестирования
-
-### **3. Обновлена таблица прав доступа**
-
-```markdown
-| VALMIS | Toggle | Admin/User | Появляется/Исчезает | Нет | ТОЛЬКО если error флаги (НЕ текст проблемы) |
-| VÄLJAS | Toggle | Admin/User | Появляется/Исчезает | Нет | ТОЛЬКО если error флаги (НЕ текст проблемы) |
-```
-
----
-
-## 🧪 **ТЕСТИРОВАНИЕ**
-
-### **Test 1: Только текст problems (должно НЕ блокироваться)**
-```bash
-# Установить problems text БЕЗ error флагов
-curl -X PATCH http://localhost:3000/api/records/3/problems \
- -d '{"problems":"Only text","errorFlags":{"worksheets":false,...}}'
-
-# Попытка toggle VALMIS
-curl -X PATCH http://localhost:3000/api/records/3/status \
- -d '{"field":"ready","date":null}'
-
-# Результат: {"success":true} ✅ НЕ БЛОКИРУЕТСЯ
-```
-
-### **Test 2: С error flag (должно блокироваться)**
-```bash
-# Установить error flag
-curl -X PATCH http://localhost:3000/api/records/3/problems \
- -d '{"problems":"Text","errorFlags":{"worksheets":true,...}}'
-
-# Попытка toggle VALMIS
-curl -X PATCH http://localhost:3000/api/records/3/status \
- -d '{"field":"ready","date":null}'
-
-# Результат: {"error":"blocked","message":"Vigade märked on seatud..."} ✅ БЛОКИРУЕТСЯ
-```
-
----
-
-## 📦 **ФАЙЛЫ**
-
-**Изменённые файлы:**
-- `/home/user/production_backup/backend/DATE_FIELDS_LOGIC.md` - обновлена документация
-
-**Без изменений (код уже правильный):**
-- `src/index.tsx` - backend логика была правильной
-- `public/static/app.js` - frontend логика была правильной
-
----
-
-## 🚀 **РАЗВЁРТЫВАНИЕ**
-
-**Изменения только в документации**, код не менялся!
-
-```bash
-# 1. Распаковать архив
-unzip aknaproff_production_v4.1.19_FINAL.zip
-
-# 2. Запустить как обычно
-cd backend
-docker-compose up -d --build
-```
-
----
-
-## ✅ **РЕЗУЛЬТАТ**
-
-- ✅ Документация теперь **ЧЁТКО** описывает правила блокировки
-- ✅ Добавлена отдельная секция с примерами кода и тестирования
-- ✅ Обновлена таблица прав доступа
-- ✅ Все тесты пройдены успешно
-
----
-
-## 📝 **ЗАМЕТКИ**
-
-- Код backend/frontend **НЕ** менялся - он уже был правильным
-- Изменения только в документации для ясности
-- Версия обновлена с v4.1.18 → v4.1.19 для отслеживания изменений
-
----
-
-**Статус**: ✅ ГОТОВО
-**Тестирование**: ✅ ПРОЙДЕНО
-**Развёртывание**: ГОТОВО К ИСПОЛЬЗОВАНИЮ
diff --git a/HOTFIX_v4.1.20.md b/HOTFIX_v4.1.20.md
deleted file mode 100644
index 1d064f5..0000000
--- a/HOTFIX_v4.1.20.md
+++ /dev/null
@@ -1,240 +0,0 @@
-# 🔧 HOTFIX v4.1.20 - ИСПРАВЛЕНА ФОРМА НАСТРОЕК (СМЕНА ПАРОЛЯ)
-
-**Дата**: 2026-01-14
-**Версия**: v4.1.20 FINAL
-**Приоритет**: HIGH (Критическая ошибка - невозможно использовать настройки)
-
----
-
-## 📋 **ПРОБЛЕМА**
-
-### **Форма настроек не работала**
-
-**Симптомы:**
-- Ошибка 400 при попытке сохранить настройки
-- Консоль: `PATCH /api/users/profile [HTTP/2 400 153ms]`
-- Невозможно изменить ни имя, ни пароль
-
-**Причины:**
-1. **Несоответствие форматов полей**: Frontend отправлял `full_name`, `current_password`, `new_password` (snake_case), а backend ожидал `fullName`, `currentPassword`, `newPassword` (camelCase)
-2. **Обязательный currentPassword**: Backend требовал текущий пароль **ВСЕГДА**, даже если пользователь только меняет имя
-3. **Frontend валидация**: Требовал `currentPassword` всегда, даже если пароль не меняется
-
----
-
-## ✅ **ИСПРАВЛЕНИЯ**
-
-### **1. Backend: Поддержка обоих форматов + опциональный пароль**
-
-**Файл:** `src/index.tsx`, строки 63-93
-
-```typescript
-app.patch('/api/users/profile', authMiddleware, async (c) => {
- try {
- const body = await c.req.json()
- // Support both snake_case and camelCase
- const fullName = body.full_name || body.fullName
- const currentPassword = body.current_password || body.currentPassword
- const newPassword = body.new_password || body.newPassword
- const userId = c.get('userId')
-
- console.log('[PROFILE UPDATE]', { userId, fullName, hasCurrentPwd: !!currentPassword, hasNewPwd: !!newPassword })
-
- // Get user from database
- const user = await c.env.DB.prepare(
- 'SELECT password_hash, full_name FROM users WHERE id = ?'
- ).bind(userId).first()
-
- if (!user) {
- return c.json({ error: 'Kasutajat ei leitud' }, 404)
- }
-
- // If changing password
- if (newPassword) {
- // Verify current password is provided
- if (!currentPassword) {
- return c.json({ error: 'Praegune parool on kohustuslik parooli muutmiseks' }, 400)
- }
-
- // Verify current password
- if (!await verifyPassword(currentPassword, user.password_hash as string)) {
- return c.json({ error: 'Vale praegune parool' }, 400)
- }
-
- // Update password and full name
- const newHash = await hashPassword(newPassword)
- await c.env.DB.prepare(
- 'UPDATE users SET password_hash = ?, full_name = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?'
- ).bind(newHash, fullName, userId).run()
- } else {
- // Only update full name (no password change)
- await c.env.DB.prepare(
- 'UPDATE users SET full_name = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?'
- ).bind(fullName, userId).run()
- }
-
- return c.json({
- success: true,
- message: 'Profiil uuendatud',
- user: {
- full_name: fullName
- }
- })
- } catch (error) {
- console.error('Profile update error:', error)
- return c.json({ error: 'Profiili uuendamine ebaõnnestus' }, 500)
- }
-})
-```
-
-**Изменения:**
-- ✅ Поддержка обоих форматов полей (snake_case и camelCase)
-- ✅ `currentPassword` требуется **ТОЛЬКО** если меняется пароль
-- ✅ Можно обновить только имя без смены пароля
-- ✅ Добавлено логирование для отладки
-
-### **2. Frontend: Опциональный currentPassword**
-
-**Файл:** `public/static/app.js`, строки 1458-1476
-
-```javascript
- // Validation
- if (!fullName.trim()) {
- errorDiv.textContent = 'Nimi ei saa olla tühi';
- errorDiv.classList.remove('hidden');
- return;
- }
-
- // If changing password, current password is required
- if (newPassword && !currentPassword) {
- errorDiv.textContent = 'Praegune parool on kohustuslik parooli muutmiseks';
- errorDiv.classList.remove('hidden');
- return;
- }
-
- // Check if passwords match (only if new password is provided)
- if (newPassword && newPassword !== confirmPassword) {
- errorDiv.textContent = 'Uued paroolid ei kattu';
- errorDiv.classList.remove('hidden');
- return;
- }
-```
-
-**Изменения:**
-- ✅ `currentPassword` требуется **ТОЛЬКО** если указан `newPassword`
-- ✅ Можно оставить поле "Praegune parool" пустым если не меняется пароль
-- ✅ Более понятное сообщение об ошибке
-
----
-
-## 🧪 **ТЕСТИРОВАНИЕ**
-
-### **Test 1: Изменить только имя (БЕЗ пароля) ✅**
-```bash
-curl -X PATCH /api/users/profile \
- -d '{"full_name":"New Name","current_password":"","new_password":""}'
-
-# Результат: {"success":true,"message":"Profiil uuendatud"}
-```
-
-### **Test 2: Изменить имя + пароль ✅**
-```bash
-curl -X PATCH /api/users/profile \
- -d '{"full_name":"Name","current_password":"demo123","new_password":"demo123"}'
-
-# Результат: {"success":true,"message":"Profiil uuendatud"}
-```
-
-### **Test 3: Попытка сменить пароль без currentPassword ✅**
-```bash
-curl -X PATCH /api/users/profile \
- -d '{"full_name":"Name","current_password":"","new_password":"newpass"}'
-
-# Результат: {"error":"Praegune parool on kohustuslik parooli muutmiseks"}
-```
-
-### **Test 4: Неверный текущий пароль ✅**
-```bash
-curl -X PATCH /api/users/profile \
- -d '{"full_name":"Name","current_password":"wrong","new_password":"newpass"}'
-
-# Результат: {"error":"Vale praegune parool"}
-```
-
----
-
-## 📦 **ФАЙЛЫ**
-
-**Изменённые файлы:**
-- `src/index.tsx` - endpoint `/api/users/profile`
-- `public/static/app.js` - функция `updateSettings()`
-
-**Версия:**
-- `public/original.html` - обновлена до v4.1.20
-
----
-
-## 🚀 **РАЗВЁРТЫВАНИЕ**
-
-```bash
-# 1. Распаковать архив
-unzip aknaproff_production_v4.1.20_FINAL.zip
-
-# 2. Запустить
-cd backend
-docker-compose up -d --build
-
-# 3. Проверить форму настроек
-# Открыть веб-интерфейс → Seaded → изменить имя → сохранить
-```
-
----
-
-## 📝 **СЦЕНАРИИ ИСПОЛЬЗОВАНИЯ**
-
-### **Сценарий 1: Изменить только имя**
-1. Открыть форму "Seaded"
-2. Изменить "Nimi"
-3. Оставить поля паролей **ПУСТЫМИ**
-4. Нажать "Salvesta"
-5. ✅ Имя обновлено
-
-### **Сценарий 2: Изменить пароль**
-1. Открыть форму "Seaded"
-2. Ввести "Praegune parool"
-3. Ввести "Uus parool"
-4. Ввести "Kinnita uus parool"
-5. Нажать "Salvesta"
-6. ✅ Пароль изменён
-
-### **Сценарий 3: Изменить имя + пароль**
-1. Открыть форму "Seaded"
-2. Изменить "Nimi"
-3. Ввести все поля паролей
-4. Нажать "Salvesta"
-5. ✅ Имя и пароль обновлены
-
----
-
-## ✅ **РЕЗУЛЬТАТ**
-
-- ✅ Форма настроек работает корректно
-- ✅ Можно изменить только имя (без пароля)
-- ✅ Можно изменить пароль (с проверкой текущего)
-- ✅ Правильная валидация на frontend и backend
-- ✅ Понятные сообщения об ошибках на эстонском языке
-
----
-
-## 🔄 **ИСТОРИЯ ВЕРСИЙ**
-
-| Версия | Изменения |
-|--------|-----------|
-| v4.1.19 | Документирована логика блокировки VALMIS/VÄLJAS |
-| **v4.1.20** | **Исправлена форма настроек (смена пароля)** |
-
----
-
-**Статус**: ✅ ГОТОВО
-**Тестирование**: ✅ ПРОЙДЕНО
-**Развёртывание**: ГОТОВО К ИСПОЛЬЗОВАНИЮ
diff --git a/HOTFIX_v4.1.21.md b/HOTFIX_v4.1.21.md
deleted file mode 100644
index 9d18359..0000000
--- a/HOTFIX_v4.1.21.md
+++ /dev/null
@@ -1,91 +0,0 @@
-# 🔧 HOTFIX v4.1.21 - УБРАНО ОГРАНИЧЕНИЕ ДЛИНЫ ПОЛЯ "VÄRV"
-
-**Дата**: 2026-01-14
-**Версия**: v4.1.21 FINAL
-**Приоритет**: LOW (Косметическое улучшение)
-
----
-
-## 📋 **ПРОБЛЕМА**
-
-### **Текст в поле "Värv" обрезался**
-
-**Симптомы:**
-- Поле "Värv" показывало только 10 символов + "..."
-- Пример: "7016 matt-..." вместо полного текста
-- Поле достаточно широкое для отображения полного текста
-
-**Причина:**
-- Искусственное ограничение в 10 символов на строке 648 в `app.js`
-
----
-
-## ✅ **ИСПРАВЛЕНИЕ**
-
-**Файл:** `public/static/app.js`, строка 648
-
-**Было:**
-```javascript
-${record.color ? (record.color.length > 10 ? record.color.substring(0, 10) + '...' : record.color) : '-'}
-```
-
-**Стало:**
-```javascript
-${record.color || '-'}
-```
-
-**Изменения:**
-- ✅ Убрано ограничение в 10 символов
-- ✅ Отображается полный текст цвета
-- ✅ Tooltip остался для длинных названий
-
----
-
-## 🎨 **РЕЗУЛЬТАТ**
-
-**Было:**
-- "7016 matt-..."
-- "Anthrazit-..."
-
-**Стало:**
-- "7016 matt-anthrazit"
-- "Anthrazit-grau RAL 7016"
-
----
-
-## 📦 **ФАЙЛЫ**
-
-**Изменённые файлы:**
-- `public/static/app.js` - убрано ограничение длины
-
-**Версия:**
-- `public/original.html` - обновлена до v4.1.21
-
----
-
-## 🚀 **РАЗВЁРТЫВАНИЕ**
-
-Простая замена файлов, перезапуск не требуется:
-
-```bash
-# 1. Распаковать архив
-unzip aknaproff_production_v4.1.21_FINAL.zip
-
-# 2. Запустить
-cd backend
-docker-compose up -d --build
-```
-
----
-
-## ✅ **РЕЗУЛЬТАТ**
-
-- ✅ Поле "Värv" показывает полный текст
-- ✅ Нет обрезания до 10 символов
-- ✅ Tooltip остался для справки
-
----
-
-**Статус**: ✅ ГОТОВО
-**Тестирование**: ✅ ПРОЙДЕНО
-**Развёртывание**: ГОТОВО К ИСПОЛЬЗОВАНИЮ
diff --git a/HOTFIX_v4.1.22.md b/HOTFIX_v4.1.22.md
deleted file mode 100644
index e4bf565..0000000
--- a/HOTFIX_v4.1.22.md
+++ /dev/null
@@ -1,124 +0,0 @@
-# 🔧 HOTFIX v4.1.22 - ИСПРАВЛЕНО УДАЛЕНИЕ ЗАПИСЕЙ
-
-**Дата**: 2026-01-14
-**Версия**: v4.1.22 FINAL
-**Приоритет**: HIGH (Критическая функция не работала)
-
----
-
-## 📋 **ПРОБЛЕМА**
-
-### **Не работало удаление записей**
-
-**Симптомы:**
-- Ошибка 500 при попытке удалить запись
-- Консоль: `DELETE /api/records/50 [HTTP/1.1 500 Internal Server Error]`
-- Ошибка в логах: `D1_ERROR: no such column: deleted_by: SQLITE_ERROR`
-
-**Причина:**
-- Backend пытался записать в несуществующую колонку `deleted_by`
-- Таблица `production_records` имеет только `deleted_at`, но не `deleted_by`
-
----
-
-## ✅ **ИСПРАВЛЕНИЕ**
-
-**Файл:** `src/index.tsx`, endpoint `DELETE /api/records/:id`
-
-**Было:**
-```typescript
-await c.env.DB.prepare(`
- UPDATE production_records
- SET deleted_at = CURRENT_TIMESTAMP, deleted_by = ?
- WHERE id = ?
-`).bind(userId || null, id).run()
-```
-
-**Стало:**
-```typescript
-await c.env.DB.prepare(`
- UPDATE production_records
- SET deleted_at = CURRENT_TIMESTAMP, deleted = 1
- WHERE id = ?
-`).bind(id).run()
-```
-
-**Изменения:**
-- ✅ Убрана попытка записи в `deleted_by` (колонки нет в БД)
-- ✅ Добавлена установка флага `deleted = 1`
-- ✅ Добавлено логирование для отладки
-
----
-
-## 🧪 **ТЕСТИРОВАНИЕ**
-
-### **Test: Удаление записи ✅**
-
-```bash
-# Было записей: 6
-DELETE /api/records/49
-# Результат: {"success":true}
-# Стало записей: 5
-```
-
-**Проверка в БД:**
-```sql
-SELECT id, deleted, deleted_at FROM production_records WHERE id = 49;
--- Результат: 49|1|2026-01-14 20:30:54
-```
-
----
-
-## 📦 **ФАЙЛЫ**
-
-**Изменённые файлы:**
-- `src/index.tsx` - endpoint `DELETE /api/records/:id`
-
-**Версия:**
-- `public/original.html` - обновлена до v4.1.22
-
----
-
-## 🚀 **РАЗВЁРТЫВАНИЕ**
-
-### **ARM Synology:**
-
-```bash
-# 1. Остановить контейнер
-sudo docker-compose down
-
-# 2. Распаковать новый архив
-unzip aknaproff_production_v4.1.22_ARM_FINAL.zip
-
-# 3. Запустить с пересборкой
-cd backend
-sudo docker-compose up -d --build
-
-# 4. Проверить что удаление работает
-# Войти как admin → удалить запись → проверить что удалилась
-```
-
----
-
-## ✅ **РЕЗУЛЬТАТ**
-
-- ✅ Удаление записей работает корректно
-- ✅ Записи помечаются как удалённые (soft delete)
-- ✅ `deleted = 1` и `deleted_at` устанавливаются правильно
-- ✅ Ошибка "no such column: deleted_by" исправлена
-
----
-
-## 📊 **ИСТОРИЯ ВЕРСИЙ**
-
-| Версия | Изменения |
-|--------|-----------|
-| v4.1.20 | Исправлена форма настроек (смена пароля) |
-| v4.1.21 | Убрано ограничение длины поля "Värv" |
-| **v4.1.22** | **Исправлено удаление записей** |
-
----
-
-**Статус**: ✅ ГОТОВО
-**Тестирование**: ✅ ПРОЙДЕНО
-**Развёртывание**: ГОТОВО К ИСПОЛЬЗОВАНИЮ
diff --git a/HOTFIX_v4.1.23.md b/HOTFIX_v4.1.23.md
deleted file mode 100644
index 55d7c67..0000000
--- a/HOTFIX_v4.1.23.md
+++ /dev/null
@@ -1,191 +0,0 @@
-# 🔧 HOTFIX v4.1.23 - ДВА УЛУЧШЕНИЯ UX
-
-**Дата**: 2026-01-15
-**Версия**: v4.1.23 FINAL
-**Приоритет**: MEDIUM (Улучшения UX)
-
----
-
-## 📋 **ПРОБЛЕМЫ И РЕШЕНИЯ**
-
-### **1. Проверка сохранения дат MAT-1 и MAT-2**
-
-**Проблема:**
-- Была неясность - сохраняются ли даты при создании нового ряда
-
-**Проверка:**
-- Backend УЖЕ правильно сохраняет даты
-- Если пользователь вводит даты → они сохраняются
-- Если даты не введены → сохраняется NULL
-
-**Файл:** `src/index.tsx`, endpoint `POST /api/records` (строки 210-218)
-
-```typescript
-// Create status checkboxes entry with dates if provided
-const materialDate = (data.material_date && data.material_date !== 'null') ? data.material_date : null
-const material2Date = (data.material2_date && data.material2_date !== 'null') ? data.material2_date : null
-const packageDate = (data.package_date && data.package_date !== 'null') ? data.package_date : null
-
-await c.env.DB.prepare(`
- INSERT INTO status_checkboxes (
- record_id, material_date, material2_date, package_date
- ) VALUES (?, ?, ?, ?)
-`).bind(result.meta.last_row_id, materialDate, material2Date, packageDate).run()
-```
-
-**Результат:** ✅ Код работал правильно, просто нужна была проверка
-
----
-
-### **2. Контроль ввода цены - принимать и запятую, и точку**
-
-**Проблема:**
-- Нужно было обязательно ставить точку между евро и центами
-- Пользователь не мог вводить запятую (европейский формат)
-
-**Решение:**
-- Добавлен автоматический перевод запятой в точку при вводе
-- Пользователь может вводить как `1500,50` так и `1500.50`
-
-**Файл:** `public/static/app.js`, обработчик поля price
-
-```javascript
-// Add listener for price field to auto-format (accept both comma and dot)
-const priceField = document.getElementById('price');
-if (priceField) {
- priceField.addEventListener('input', function(e) {
- // Replace comma with dot automatically
- let value = e.target.value;
- if (value.includes(',')) {
- e.target.value = value.replace(',', '.');
- }
- });
-}
-```
-
-**Результат:** ✅ Цена принимает и запятую, и точку (автопреобразование)
-
----
-
-### **3. Время сессии - 4 часа (уже было)**
-
-**Проверка:**
-- Время сессии УЖЕ БЫЛО установлено на 4 часа
-- Проверено и подтверждено
-
-**Файл:** `src/utils/auth.ts`
-
-```typescript
-const expiry = Date.now() + (240 * 60 * 1000) // 4 hours = 240 minutes
-```
-
-**Результат:** ✅ Сессия длится 4 часа (240 минут)
-
----
-
-## 🧪 **ТЕСТИРОВАНИЕ**
-
-### **Test 1: Даты сохраняются если введены ✅**
-
-```bash
-POST /api/records
-{
- "material_date": "2026-01-15",
- "material2_date": "2026-01-16",
- "package_date": "2026-01-15"
-}
-
-Результат:
-✅ MAT-1: 2026-01-15
-✅ MAT-2: 2026-01-16
-✅ PAKETT: 2026-01-15
-```
-
-### **Test 2: Даты NULL если не введены ✅**
-
-```bash
-POST /api/records
-{
- // Без полей дат
-}
-
-Результат:
-✅ MAT-1: null
-✅ MAT-2: null
-```
-
-### **Test 3: Цена с запятой и точкой ✅**
-
-```javascript
-Ввод: "1500,50"
-Результат после автозамены: "1500.50"
-✅ Работает корректно
-```
-
-### **Test 4: Сессия 4 часа ✅**
-
-```bash
-Token expires in: 239 minutes
-✅ Session duration is ~4 hours (240 min)
-```
-
----
-
-## 📦 **ФАЙЛЫ**
-
-**Изменённые файлы:**
-- `public/static/app.js` - обработчик price (автозамена запятой)
-
-**Проверенные файлы (код был правильный):**
-- `src/index.tsx` - endpoint POST /api/records (даты сохраняются)
-- `src/utils/auth.ts` - время сессии (уже 4 часа)
-
-**Версия:**
-- `public/original.html` - v4.1.23
-
----
-
-## 🚀 **РАЗВЁРТЫВАНИЕ**
-
-### **ARM Synology:**
-
-```bash
-# 1. Остановить контейнер
-sudo docker-compose down
-
-# 2. Распаковать новый архив
-unzip aknaproff_production_v4.1.23_ARM_FINAL.zip
-
-# 3. Запустить с пересборкой
-cd backend
-sudo docker-compose up -d --build
-
-# 4. Проверить
-# - Создать новый ряд с датами → должны сохраниться
-# - Ввести цену с запятой → автозамена на точку
-# - Сессия длится 4 часа
-```
-
----
-
-## ✅ **РЕЗУЛЬТАТ**
-
-- ✅ Подтверждено: даты сохраняются правильно
-- ✅ Цена принимает и запятую, и точку
-- ✅ Сессия длится 4 часа
-- ✅ Минимальное вмешательство в код
-
----
-
-## 📊 **ИСТОРИЯ ВЕРСИЙ**
-
-| Версия | Изменения |
-|--------|-----------|
-| v4.1.22 | Исправлено удаление записей |
-| **v4.1.23** | **Цена с запятой + проверка сохранения дат** |
-
----
-
-**Статус**: ✅ ГОТОВО
-**Тестирование**: ✅ ПРОЙДЕНО
-**Развёртывание**: ГОТОВО К ИСПОЛЬЗОВАНИЮ
diff --git a/HOTFIX_v4.1.24.md b/HOTFIX_v4.1.24.md
new file mode 100644
index 0000000..a1b9514
--- /dev/null
+++ b/HOTFIX_v4.1.24.md
@@ -0,0 +1,194 @@
+# 🔥 HOTFIX v4.1.24 - ARVE ПОЛЯ НЕ СОХРАНЯЛИСЬ
+
+**Дата**: 2026-01-15
+**Версия**: v4.1.24 FINAL
+**Приоритет**: CRITICAL 🔥
+
+---
+
+## 🚨 **КРИТИЧНАЯ ПРОБЛЕМА**
+
+### **Симптомы:**
+- ❌ Бухгалтер не может добавить номер счёта (arve_makstud)
+- ❌ Не работает галочка "Arve makstud" (arve_checked)
+- ❌ При создании/редактировании записей эти поля просто не сохраняются
+
+### **Причина:**
+**Backend не включал поля `arve_checked` и `arve_makstud` в SQL запросы!**
+
+Поля были в форме, отправлялись с фронтенда, но backend **игнорировал их полностью**.
+
+---
+
+## 🔧 **РЕШЕНИЕ**
+
+### **Файл:** `src/index.tsx`
+
+#### **1. POST /api/records - добавление записи**
+
+**Было (строка 196-207):**
+```typescript
+const result = await c.env.DB.prepare(`
+ INSERT INTO production_records (
+ month, year, client_name, type, offer_number, work_number,
+ quantity, color, notes, problems, installer, price,
+ created_by, updated_by
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+`).bind(
+ data.month, data.year, data.client_name, data.type || null,
+ data.offer_number, data.work_number, quantity, data.color || null,
+ data.notes || null, data.problems || null, data.installer || null,
+ price, userId, userId
+).run()
+```
+
+**Стало:**
+```typescript
+const arveChecked = data.arve_checked ? parseInt(data.arve_checked, 10) : 0
+
+const result = await c.env.DB.prepare(`
+ INSERT INTO production_records (
+ month, year, client_name, type, offer_number, work_number,
+ quantity, color, notes, problems, installer, price,
+ arve_checked, arve_makstud,
+ created_by, updated_by
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+`).bind(
+ data.month, data.year, data.client_name, data.type || null,
+ data.offer_number, data.work_number, quantity, data.color || null,
+ data.notes || null, data.problems || null, data.installer || null,
+ price, arveChecked, data.arve_makstud || null,
+ userId, userId
+).run()
+```
+
+#### **2. PUT /api/records/:id - обновление записи**
+
+**Было (строка 238-248):**
+```typescript
+await c.env.DB.prepare(`
+ UPDATE production_records
+ SET client_name = ?, type = ?, offer_number = ?, work_number = ?,
+ quantity = ?, color = ?, notes = ?, problems = ?, installer = ?, price = ?,
+ updated_by = ?, updated_at = CURRENT_TIMESTAMP
+ WHERE id = ? AND deleted_at IS NULL
+`).bind(
+ data.client_name, data.type || null, data.offer_number, data.work_number,
+ quantity, data.color || null, data.notes || null, data.problems || null,
+ data.installer || null, price, userId, id
+).run()
+```
+
+**Стало:**
+```typescript
+const arveChecked = data.arve_checked ? parseInt(data.arve_checked, 10) : 0
+
+await c.env.DB.prepare(`
+ UPDATE production_records
+ SET client_name = ?, type = ?, offer_number = ?, work_number = ?,
+ quantity = ?, color = ?, notes = ?, problems = ?, installer = ?, price = ?,
+ arve_checked = ?, arve_makstud = ?,
+ updated_by = ?, updated_at = CURRENT_TIMESTAMP
+ WHERE id = ? AND deleted_at IS NULL
+`).bind(
+ data.client_name, data.type || null, data.offer_number, data.work_number,
+ quantity, data.color || null, data.notes || null, data.problems || null,
+ data.installer || null, price, arveChecked, data.arve_makstud || null,
+ userId, id
+).run()
+```
+
+---
+
+## 🧪 **ТЕСТИРОВАНИЕ**
+
+### **Test 1: Создать запись с arve полями ✅**
+
+```bash
+POST /api/records
+{
+ "arve_checked": 1,
+ "arve_makstud": "INV-2025-001"
+}
+
+Результат:
+✅ id: 56
+✅ arve_checked: 1
+✅ arve_makstud: INV-2025-001
+```
+
+### **Test 2: Обновить arve поля ✅**
+
+```bash
+PUT /api/records/56
+{
+ "arve_checked": 0,
+ "arve_makstud": "INV-2025-002"
+}
+
+Результат:
+✅ arve_checked: 0 → обновилось
+✅ arve_makstud: INV-2025-002 → обновилось
+```
+
+---
+
+## 📦 **ФАЙЛЫ**
+
+**Изменённые файлы:**
+- `src/index.tsx` - endpoint POST /api/records (строки 196-207)
+- `src/index.tsx` - endpoint PUT /api/records/:id (строки 238-248)
+
+**Версия:**
+- `public/original.html` - v4.1.24
+
+---
+
+## 🚀 **РАЗВЁРТЫВАНИЕ**
+
+### **ARM Synology:**
+
+```bash
+# 1. Остановить контейнер
+sudo docker-compose down
+
+# 2. Распаковать новый архив
+unzip aknaproff_production_v4.1.24_ARM_FINAL.zip
+
+# 3. Запустить с пересборкой
+cd backend
+sudo docker-compose up -d --build
+
+# 4. Проверить
+# - Создать новый ряд
+# - Ввести номер счёта в "Arve Nr"
+# - Поставить галочку "Arve makstud"
+# - Сохранить
+# - ✅ Поля должны сохраниться!
+```
+
+---
+
+## ✅ **РЕЗУЛЬТАТ**
+
+- ✅ arve_checked сохраняется при создании
+- ✅ arve_makstud сохраняется при создании
+- ✅ arve_checked обновляется при редактировании
+- ✅ arve_makstud обновляется при редактировании
+- ✅ Бухгалтер может работать с полями счёта!
+
+---
+
+## 📊 **ИСТОРИЯ ВЕРСИЙ**
+
+| Версия | Изменения |
+|--------|-----------|
+| v4.1.23 | Цена с запятой + проверка дат |
+| **v4.1.24** | **ИСПРАВЛЕНЫ ПОЛЯ СЧЁТА (arve)** 🔥 |
+
+---
+
+**Статус**: ✅ ГОТОВО
+**Тестирование**: ✅ ПРОЙДЕНО
+**Критичность**: 🔥 ВЫСОКАЯ
+**Развёртывание**: СРОЧНО РЕКОМЕНДУЕТСЯ
diff --git a/backup.sh b/backup.sh
new file mode 100755
index 0000000..9bb298f
--- /dev/null
+++ b/backup.sh
@@ -0,0 +1,80 @@
+#!/bin/bash
+
+# AKNAPROFF Tootmine Database Backup Script
+# Создаёт бэкапы БД с timestamp
+
+set -e # Exit on error
+
+# Цвета для вывода
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+NC='\033[0m' # No Color
+
+# Настройки
+DATE=$(date +%Y%m%d_%H%M%S)
+BACKUP_DIR="./backups"
+DEV_DB_PATH=".wrangler/state/v3/d1/webapp-production.sqlite"
+PROD_DB_PATH="data/db/webapp-production.sqlite"
+
+# Создать папку для бэкапов
+mkdir -p "$BACKUP_DIR"
+
+echo "🗄️ AKNAPROFF Database Backup"
+echo "=============================="
+echo ""
+
+# Проверить и бэкапить Development БД
+if [ -f "$DEV_DB_PATH" ]; then
+ DEV_BACKUP="$BACKUP_DIR/webapp-dev-$DATE.sqlite"
+ cp "$DEV_DB_PATH" "$DEV_BACKUP"
+
+ # Размер файла
+ SIZE=$(du -h "$DEV_BACKUP" | cut -f1)
+
+ echo -e "${GREEN}✅ Development DB backed up${NC}"
+ echo " File: $DEV_BACKUP"
+ echo " Size: $SIZE"
+ echo ""
+else
+ echo -e "${YELLOW}⚠️ Development DB not found${NC}"
+ echo " Path: $DEV_DB_PATH"
+ echo ""
+fi
+
+# Проверить и бэкапить Production БД
+if [ -f "$PROD_DB_PATH" ]; then
+ PROD_BACKUP="$BACKUP_DIR/webapp-prod-$DATE.sqlite"
+ cp "$PROD_DB_PATH" "$PROD_BACKUP"
+
+ # Размер файла
+ SIZE=$(du -h "$PROD_BACKUP" | cut -f1)
+
+ echo -e "${GREEN}✅ Production DB backed up${NC}"
+ echo " File: $PROD_BACKUP"
+ echo " Size: $SIZE"
+ echo ""
+else
+ echo -e "${YELLOW}⚠️ Production DB not found${NC}"
+ echo " Path: $PROD_DB_PATH"
+ echo ""
+fi
+
+# Показать все бэкапы
+echo "📦 All backups:"
+echo "---------------"
+ls -lh "$BACKUP_DIR"/*.sqlite 2>/dev/null | awk '{print " " $9 " (" $5 ")"}'
+
+echo ""
+echo "=============================="
+
+# Подсчитать количество бэкапов
+BACKUP_COUNT=$(ls -1 "$BACKUP_DIR"/*.sqlite 2>/dev/null | wc -l)
+if [ "$BACKUP_COUNT" -gt 10 ]; then
+ echo -e "${YELLOW}💡 Tip: You have $BACKUP_COUNT backups${NC}"
+ echo " Consider cleaning old backups:"
+ echo " rm $BACKUP_DIR/webapp-*-2024*.sqlite"
+ echo ""
+fi
+
+echo -e "${GREEN}✅ Backup completed!${NC}"
diff --git a/data/v3/d1/miniflare-D1DatabaseObject/2b35d4d42e3c9f6b5ad5b5579a7b1470c66e69f6b33a31e3f5a0095cc6d18656.sqlite b/data/v3/d1/miniflare-D1DatabaseObject/2b35d4d42e3c9f6b5ad5b5579a7b1470c66e69f6b33a31e3f5a0095cc6d18656.sqlite
deleted file mode 100755
index 53023ef..0000000
Binary files a/data/v3/d1/miniflare-D1DatabaseObject/2b35d4d42e3c9f6b5ad5b5579a7b1470c66e69f6b33a31e3f5a0095cc6d18656.sqlite and /dev/null differ
diff --git a/dist/_worker.js b/dist/_worker.js
index 5d93d17..d9aa836 100644
--- a/dist/_worker.js
+++ b/dist/_worker.js
@@ -1252,30 +1252,32 @@ var je=Object.defineProperty;var Ft=t=>{throw TypeError(t)};var Se=(t,e,r)=>e in
LEFT JOIN status_checkboxes sc ON pr.id = sc.record_id
WHERE pr.month = ? AND pr.year = ? AND pr.deleted_at IS NULL
ORDER BY pr.created_at DESC
- `).bind(e,r).all();return t.json(o.results||[])}catch(e){return console.error("Error fetching records:",e),t.json({error:"Failed to fetch records"},500)}});f.post("/api/records",A,async t=>{try{const e=await t.req.json(),r=t.get("userId"),o=e.quantity?parseInt(e.quantity,10):0,s=e.price?parseFloat(e.price):0,a=await t.env.DB.prepare(`
+ `).bind(e,r).all();return t.json(o.results||[])}catch(e){return console.error("Error fetching records:",e),t.json({error:"Failed to fetch records"},500)}});f.post("/api/records",A,async t=>{try{const e=await t.req.json(),r=t.get("userId"),o=e.quantity?parseInt(e.quantity,10):0,s=e.price?parseFloat(e.price):0,a=e.arve_checked?parseInt(e.arve_checked,10):0,i=await t.env.DB.prepare(`
INSERT INTO production_records (
month, year, client_name, type, offer_number, work_number,
quantity, color, notes, problems, installer, price,
+ arve_checked, arve_makstud,
created_by, updated_by
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
- `).bind(e.month,e.year,e.client_name,e.type||null,e.offer_number,e.work_number,o,e.color||null,e.notes||null,e.problems||null,e.installer||null,s,r,r).run(),i=e.material_date&&e.material_date!=="null"?e.material_date:null,l=e.material2_date&&e.material2_date!=="null"?e.material2_date:null,n=e.package_date&&e.package_date!=="null"?e.package_date:null;return await t.env.DB.prepare(`
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+ `).bind(e.month,e.year,e.client_name,e.type||null,e.offer_number,e.work_number,o,e.color||null,e.notes||null,e.problems||null,e.installer||null,s,a,e.arve_makstud||null,r,r).run(),l=e.material_date&&e.material_date!=="null"?e.material_date:null,n=e.material2_date&&e.material2_date!=="null"?e.material2_date:null,c=e.package_date&&e.package_date!=="null"?e.package_date:null;return await t.env.DB.prepare(`
INSERT INTO status_checkboxes (
record_id, material_date, material2_date, package_date
) VALUES (?, ?, ?, ?)
- `).bind(a.meta.last_row_id,i,l,n).run(),t.json({success:!0,id:a.meta.last_row_id})}catch(e){return console.error("Error creating record:",e),t.json({error:"Failed to create record"},500)}});f.put("/api/records/:id",A,async t=>{try{const e=t.req.param("id"),r=await t.req.json(),o=t.get("userId"),s=r.quantity?parseInt(r.quantity,10):0,a=r.price?parseFloat(r.price):0;if(await t.env.DB.prepare(`
+ `).bind(i.meta.last_row_id,l,n,c).run(),t.json({success:!0,id:i.meta.last_row_id})}catch(e){return console.error("Error creating record:",e),t.json({error:"Failed to create record"},500)}});f.put("/api/records/:id",A,async t=>{try{const e=t.req.param("id"),r=await t.req.json(),o=t.get("userId"),s=r.quantity?parseInt(r.quantity,10):0,a=r.price?parseFloat(r.price):0,i=r.arve_checked?parseInt(r.arve_checked,10):0;if(await t.env.DB.prepare(`
UPDATE production_records
SET client_name = ?, type = ?, offer_number = ?, work_number = ?,
quantity = ?, color = ?, notes = ?, problems = ?, installer = ?, price = ?,
+ arve_checked = ?, arve_makstud = ?,
updated_by = ?, updated_at = CURRENT_TIMESTAMP
WHERE id = ? AND deleted_at IS NULL
- `).bind(r.client_name,r.type||null,r.offer_number,r.work_number,s,r.color||null,r.notes||null,r.problems||null,r.installer||null,a,o,e).run(),r.material_date!==void 0||r.material2_date!==void 0||r.package_date!==void 0){const i=r.material_date&&r.material_date!=="null"?r.material_date:null,l=r.material2_date&&r.material2_date!=="null"?r.material2_date:null,n=r.package_date&&r.package_date!=="null"?r.package_date:null;await t.env.DB.prepare(`
+ `).bind(r.client_name,r.type||null,r.offer_number,r.work_number,s,r.color||null,r.notes||null,r.problems||null,r.installer||null,a,i,r.arve_makstud||null,o,e).run(),r.material_date!==void 0||r.material2_date!==void 0||r.package_date!==void 0){const l=r.material_date&&r.material_date!=="null"?r.material_date:null,n=r.material2_date&&r.material2_date!=="null"?r.material2_date:null,c=r.package_date&&r.package_date!=="null"?r.package_date:null;await t.env.DB.prepare(`
UPDATE status_checkboxes
SET material_date = ?,
material2_date = ?,
package_date = ?,
updated_at = CURRENT_TIMESTAMP
WHERE record_id = ?
- `).bind(i,l,n,e).run()}return t.json({success:!0})}catch(e){return console.error("Error updating record:",e),t.json({error:"Failed to update record"},500)}});f.get("/api/records/:id",A,async t=>{try{const e=t.req.param("id"),r=await t.env.DB.prepare(`
+ `).bind(l,n,c,e).run()}return t.json({success:!0})}catch(e){return console.error("Error updating record:",e),t.json({error:"Failed to update record"},500)}});f.get("/api/records/:id",A,async t=>{try{const e=t.req.param("id"),r=await t.env.DB.prepare(`
SELECT * FROM production_records WHERE id = ? AND deleted_at IS NULL
`).bind(e).first();return r?t.json(r):t.json({error:"Record not found"},404)}catch(e){return console.error("Error fetching record:",e),t.json({error:"Failed to fetch record"},500)}});f.delete("/api/records/:id",A,async t=>{try{const e=t.req.param("id"),r=t.get("userId");return console.log("[DELETE] Deleting record:",e,"by user:",r),await t.env.DB.prepare(`
UPDATE production_records
diff --git a/dist/original.html b/dist/original.html
index f90c94a..72f82fc 100644
--- a/dist/original.html
+++ b/dist/original.html
@@ -1225,7 +1225,7 @@
-
+