Добавлены три документа: 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>
12 KiB
Тестирование исправления загрузки сохранённых значений корректировки цены
Дата исправления: 2025-11-02
Коммит: c7bf23c
Описание проблемы (которая была исправлена)
Проблема: Сохранённые значения корректировки цены не отображались на странице редактирования комплекта.
- Отображались только в 1 из 10 случаев
- Большую часть времени поля были пустыми
- Когда отображались, то сразу затирались какой-то переинициализацией
URL для воспроизведения: http://grach.localhost:8000/products/kits/4/update/
Корневая причина:
- При загрузке значений в input-поля срабатывают события
inputиchange - Эти события вызывают
calculateFinalPrice()иvalidateSingleAdjustment() - Функция
calculateFinalPrice()перезаписывает скрытые поля (id_price_adjustment_type,id_price_adjustment_value) со значениями по умолчанию - Получается 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)
// Строка 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
Шаги:
- Открыть http://grach.localhost:8000/products/kits/4/update/
- Нажать Ctrl+F5 (очистить кэш и перезагрузить)
- Найти блок "НА СКОЛЬКО БЫЛА ИЗМЕНЕНА ЦЕНА"
- Должно отображаться: поле "Увеличить на %" с значением 10
- Повторить шаги 2-4 ещё 9 раз (всего 10 раз)
Ожидаемый результат: 10/10 раз значение 10 отображается в поле
Признаки успеха:
- ✅ Поле не пустое
- ✅ Значение = 10
- ✅ Остальные 3 поля (Увеличить на сумму, Уменьшить на %, Уменьшить на сумму) - отключены (disabled)
- ✅ Они помечены серым цветом (не активны)
Сценарий 2: Проверка логирования в консоли браузера
Цель: Убедиться что логирование показывает правильный порядок выполнения
Шаги:
- Открыть http://grach.localhost:8000/products/kits/4/update/
- Нажать F12 (открыть DevTools)
- Перейти на вкладку Console
- Нажать Ctrl+F5
- В консоли должны появиться логи (отсортировать по времени вверх):
Ожидаемые логи (в таком порядке):
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: Проверка редактирования корректировки
Цель: Убедиться что можно изменить значение и оно сохраняется
Шаги:
- Открыть http://grach.localhost:8000/products/kits/4/update/
- В поле "Увеличить на %" изменить значение с 10 на 15
- Нажать кнопку "Сохранить"
- Открыть страницу редактирования снова (F5)
- Проверить что значение = 15
Ожидаемый результат:
- ✅ Значение измененo на 15
- ✅ Сохранилось в БД
- ✅ При перезагрузке отображается 15
Сценарий 4: Проверка другого комплекта (с decrease_percent)
Цель: Убедиться что исправление работает для всех 4 типов корректировки
Шаги:
- Создать новый комплект
- Добавить товар
- В блоке "НА СКОЛЬКО БЫЛА ИЗМЕНЕНА ЦЕНА" выбрать "Уменьшить на %" и ввести 20
- Сохранить
- Открыть для редактирования
- Проверить что "Уменьшить на %" = 20
- Повторить 5 раз
Ожидаемый результат: 5/5 раз значение отображается правильно
Что смотреть в консоли браузера (для отладки)
F12 → Console → Filter (Фильтр)
Полезные логи:
// Загрузка сохранённых значений
"Loading saved adjustment values:"
"isLoadingAdjustmentValues = true"
"Loaded increase_percent: 10"
"isLoadingAdjustmentValues = false"
// События которые подавляются
"Skipping event during adjustment value loading"
// Инициализация завершена
"Initialization complete, isInitializing = false"
Если видите эти логи в консоли - значит исправление работает правильно.
Возможные проблемы и решения
Проблема: Значение всё ещё не отображается
Решение:
- Откройте консоль (F12)
- Проверьте логи - есть ли ошибки?
- Проверьте что комплект в БД имеет значение
price_adjustment_value> 0 - Очистите браузерный кэш (Ctrl+Shift+Delete)
- Нажмите Ctrl+F5 на странице редактирования
Проблема: Логи не появляются
Решение:
- Проверьте что консоль не отфильтрована (нет активного фильтра)
- Нажмите Ctrl+F5 (hard refresh)
- Проверьте что в productkit_edit.html есть код с логами (смотрите коммит
c7bf23c)
Проблема: Значение загружается но потом исчезает
Решение:
- Это была исходная проблема
- Если она всё ещё есть - значит исправление не развернулось
- Проверьте git статус:
git log -1 - Должен быть коммит "c7bf23c fix: Улучшить загрузку сохранённых значений"
- Если коммита нет - обновите файл 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. ГОТОВО: значения загружены, события обрабатываются, скрытые поля защищены
Заключение
Исправление использует трёхуровневую защиту:
- Подавление событий (isLoadingAdjustmentValues) во время загрузки
- Защита скрытых полей (isInitializing) от перезаписи
- Синхронизация с браузером (requestAnimationFrame) для надёжности
Это должно полностью исправить проблему с надёжностью загрузки сохранённых значений корректировки цены.
🎉 Готово к тестированию!