Files
octopus/ADJUSTMENT_VALUE_FIX_TESTING.md
Andrey Smakotin 8bec5823f3 docs: Добавить документацию по исправлению race condition при загрузке корректировки цены
Добавлены три документа:
1. FINAL_FIX_SUMMARY.md - Финальное резюме исправления
2. ADJUSTMENT_VALUE_FIX_TESTING.md - План тестирования и проверки
3. TECHNICAL_RACE_CONDITION_FIX.md - Глубокий технический анализ проблемы и решения

Документы включают:
- Описание проблемы и решения
- Пошаговый план тестирования (4 сценария)
- Анализ race condition на примере JS event loop
- Трёхуровневая защита от race condition
- Логирование для отладки
- Сравнение подходов синхронизации

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-02 20:29:06 +03:00

266 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Тестирование исправления загрузки сохранённых значений корректировки цены
## Дата исправления: 2025-11-02
## Коммит: c7bf23c
---
## Описание проблемы (которая была исправлена)
**Проблема:** Сохранённые значения корректировки цены не отображались на странице редактирования комплекта.
- Отображались только в 1 из 10 случаев
- Большую часть времени поля были пустыми
- Когда отображались, то сразу затирались какой-то переинициализацией
**URL для воспроизведения:** `http://grach.localhost:8000/products/kits/4/update/`
**Корневая причина:**
1. При загрузке значений в input-поля срабатывают события `input` и `change`
2. Эти события вызывают `calculateFinalPrice()` и `validateSingleAdjustment()`
3. Функция `calculateFinalPrice()` перезаписывает скрытые поля (`id_price_adjustment_type`, `id_price_adjustment_value`) со значениями по умолчанию
4. Получается race condition: значения загружаются → события срабатывают → значения стираются
---
## Что было исправлено
### Решение: Два уровня защиты от перезаписи
**Уровень 1: Флаг `isLoadingAdjustmentValues`**
- Подавляет события `input` и `change` во время загрузки значений
- Код видит эти события, но пропускает обработку
- Логирует в консоль: "Skipping event during adjustment value loading"
**Уровень 2: Флаг `isInitializing`**
- Даже если событие обработается, `calculateFinalPrice()` не перезапишет скрытые поля
- Проверка: `if (!isInitializing) { adjustmentTypeInput.value = ...; }`
**Уровень 3: `requestAnimationFrame`**
- Гарантирует что `isInitializing = false` устанавливается в конце frame
- Синхронизация с браузерным rendering cycle
### Файлы изменены
**`productkit_edit.html`** (строки 435, 683-696, 912-935)
```javascript
// Строка 435: Добавлен новый флаг
let isLoadingAdjustmentValues = false;
// Строки 683-696: Добавлена проверка в event listeners
input.addEventListener('input', () => {
if (isLoadingAdjustmentValues) {
console.log('Skipping event during adjustment value loading');
return;
}
validateSingleAdjustment();
calculateFinalPrice();
});
// Строки 912-935: Используется флаг во время загрузки значений
isLoadingAdjustmentValues = true;
console.log('isLoadingAdjustmentValues = true, suppressing input/change events');
// Загрузка значений
// ...
isLoadingAdjustmentValues = false;
console.log('isLoadingAdjustmentValues = false, events are enabled again');
```
---
## Как тестировать исправление
### Тестовые данные
Используются комплекты в тенанте "grach":
- **Kit #4:** "Комплект Роза" с корректировкой `increase_percent: 10.00`
- **Kit #2:** "Комплект белые розы" с корректировкой `increase_amount: 5.00`
### Сценарий 1: Проверка отображения на странице редактирования (10 раз)
**Цель:** Убедиться что значение отображается ВСЕГДА, а не 1 раз из 10
**Шаги:**
1. Открыть http://grach.localhost:8000/products/kits/4/update/
2. Нажать Ctrl+F5 (очистить кэш и перезагрузить)
3. Найти блок "НА СКОЛЬКО БЫЛА ИЗМЕНЕНА ЦЕНА"
4. Должно отображаться: поле "Увеличить на %" с значением **10**
5. Повторить шаги 2-4 ещё 9 раз (всего 10 раз)
**Ожидаемый результат:** 10/10 раз значение 10 отображается в поле
**Признаки успеха:**
- ✅ Поле не пустое
- ✅ Значение = 10
- ✅ Остальные 3 поля (Увеличить на сумму, Уменьшить на %, Уменьшить на сумму) - отключены (disabled)
- ✅ Они помечены серым цветом (не активны)
### Сценарий 2: Проверка логирования в консоли браузера
**Цель:** Убедиться что логирование показывает правильный порядок выполнения
**Шаги:**
1. Открыть http://grach.localhost:8000/products/kits/4/update/
2. Нажать F12 (открыть DevTools)
3. Перейти на вкладку **Console**
4. Нажать Ctrl+F5
5. В консоли должны появиться логи (отсортировать по времени вверх):
**Ожидаемые логи (в таком порядке):**
```
Loading saved adjustment values: {type: 'increase_percent', value: 10}
isLoadingAdjustmentValues = true, suppressing input/change events
Loaded increase_percent: 10
isLoadingAdjustmentValues = false, events are enabled again
calculateFinalPrice: calculating...
[несколько логов о расчётах цен]
Initialization complete, isInitializing = false
```
**Признаки успеха:**
-`isLoadingAdjustmentValues = true` появляется ДО загрузки значений
-`Loaded increase_percent: 10` показывает что значение загружено
-`isLoadingAdjustmentValues = false` появляется ПОСЛЕ загрузки
-`Initialization complete` появляется в конце
- ✅ Нет ошибок в консоли (красных сообщений)
### Сценарий 3: Проверка редактирования корректировки
**Цель:** Убедиться что можно изменить значение и оно сохраняется
**Шаги:**
1. Открыть http://grach.localhost:8000/products/kits/4/update/
2. В поле "Увеличить на %" изменить значение с 10 на 15
3. Нажать кнопку "Сохранить"
4. Открыть страницу редактирования снова (F5)
5. Проверить что значение = 15
**Ожидаемый результат:**
- ✅ Значение измененo на 15
- ✅ Сохранилось в БД
- ✅ При перезагрузке отображается 15
### Сценарий 4: Проверка другого комплекта (с decrease_percent)
**Цель:** Убедиться что исправление работает для всех 4 типов корректировки
**Шаги:**
1. Создать новый комплект
2. Добавить товар
3. В блоке "НА СКОЛЬКО БЫЛА ИЗМЕНЕНА ЦЕНА" выбрать "Уменьшить на %" и ввести 20
4. Сохранить
5. Открыть для редактирования
6. Проверить что "Уменьшить на %" = 20
7. Повторить 5 раз
**Ожидаемый результат:** 5/5 раз значение отображается правильно
---
## Что смотреть в консоли браузера (для отладки)
**F12 → Console → Filter (Фильтр)**
Полезные логи:
```javascript
// Загрузка сохранённых значений
"Loading saved adjustment values:"
"isLoadingAdjustmentValues = true"
"Loaded increase_percent: 10"
"isLoadingAdjustmentValues = false"
// События которые подавляются
"Skipping event during adjustment value loading"
// Инициализация завершена
"Initialization complete, isInitializing = false"
```
**Если видите эти логи в консоли - значит исправление работает правильно.**
---
## Возможные проблемы и решения
### Проблема: Значение всё ещё не отображается
**Решение:**
1. Откройте консоль (F12)
2. Проверьте логи - есть ли ошибки?
3. Проверьте что комплект в БД имеет значение `price_adjustment_value` > 0
4. Очистите браузерный кэш (Ctrl+Shift+Delete)
5. Нажмите Ctrl+F5 на странице редактирования
### Проблема: Логи не появляются
**Решение:**
1. Проверьте что консоль не отфильтрована (нет активного фильтра)
2. Нажмите Ctrl+F5 (hard refresh)
3. Проверьте что в productkit_edit.html есть код с логами (смотрите коммит c7bf23c)
### Проблема: Значение загружается но потом исчезает
**Решение:**
1. Это была исходная проблема
2. Если она всё ещё есть - значит исправление не развернулось
3. Проверьте git статус: `git log -1`
4. Должен быть коммит "c7bf23c fix: Улучшить загрузку сохранённых значений"
5. Если коммита нет - обновите файл productkit_edit.html вручную
---
## Результаты тестирования
Заполните после выполнения тестов:
| Сценарий | Попыток | Успешных | Результат |
|----------|---------|----------|-----------|
| 1. Отображение (10 раз) | 10 | __/10 | ✅ / ❌ |
| 2. Логирование | 1 | __/1 | ✅ / ❌ |
| 3. Редактирование | 1 | __/1 | ✅ / ❌ |
| 4. Другой тип коррекции | 5 | __/5 | ✅ / ❌ |
**Итоговый результат:** ✅ ПРОЙДЕНО / ❌ НЕ ПРОЙДЕНО
---
## Архитектура исправления
```
Загрузка страницы редактирования
1. DOMContentLoaded срабатывает
2. Инициализация переменных
- isInitializing = true
- isLoadingAdjustmentValues = false
- priceCache = {}
3. Регистрация event listeners (с проверкой isLoadingAdjustmentValues)
4. setTimeout 500ms → Загрузка сохранённых значений
5a. Устанавливаем isLoadingAdjustmentValues = true
5b. Заполняем поля (input события ПОДАВЛЯЮТСЯ благодаря флагу)
5c. Вызываем validateSingleAdjustment()
5d. Устанавливаем isLoadingAdjustmentValues = false
6. calculateFinalPrice() с isInitializing = true
(не перезапишет скрытые поля даже если они обновятся)
7. requestAnimationFrame × 2 → isInitializing = false
(в конце frame cycle, после всех events)
8. ГОТОВО: значения загружены, события обрабатываются, скрытые поля защищены
```
---
## Заключение
Исправление использует трёхуровневую защиту:
1. **Подавление событий** (isLoadingAdjustmentValues) во время загрузки
2. **Защита скрытых полей** (isInitializing) от перезаписи
3. **Синхронизация с браузером** (requestAnimationFrame) для надёжности
Это должно полностью исправить проблему с надёжностью загрузки сохранённых значений корректировки цены.
🎉 **Готово к тестированию!**