fix: Улучшения системы ценообразования комплектов

Исправлены 4 проблемы:
1. Расчёт цены первого товара - улучшена валидация в getProductPrice и calculateFinalPrice
2. Отображение actual_price в Select2 вместо обычной цены
3. Количество по умолчанию = 1 для новых форм компонентов
4. Auto-select текста при клике на поле количества для удобства редактирования

Изменённые файлы:
- products/forms.py: добавлен __init__ в KitItemForm для quantity.initial = 1
- products/templates/includes/select2-product-init.html: обновлена formatSelectResult
- products/templates/productkit_create.html: добавлен focus handler для auto-select
- products/templates/productkit_edit.html: добавлен focus handler для auto-select

🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-02 19:04:03 +03:00
parent c84a372f98
commit 6c8af5ab2c
120 changed files with 9035 additions and 3036 deletions

View File

@@ -0,0 +1,103 @@
/**
* Select2 Product Search Module
* Переиспользуемый модуль для инициализации Select2 с AJAX поиском товаров
*/
(function(window) {
'use strict';
// Форматирование результата в выпадающем списке
function formatSelectResult(item) {
if (item.loading) return item.text;
var $container = $('<div class="select2-result-item">');
$container.text(item.text);
if (item.price) {
$container.append($('<div class="text-muted small">').text(item.price + ' руб.'));
}
return $container;
}
// Форматирование выбранного элемента
function formatSelectSelection(item) {
return item.text || item.id;
}
/**
* Инициализирует Select2 для элемента с AJAX поиском товаров
* @param {Element|jQuery} element - DOM элемент или jQuery объект select
* @param {string} type - Тип поиска ('product' или 'variant')
* @param {string} apiUrl - URL API для поиска
* @param {Object} preloadedData - Предзагруженные данные товара
*/
window.initProductSelect2 = function(element, type, apiUrl, preloadedData) {
if (!element) return;
// Преобразуем в jQuery если нужно
var $element = $(element);
// Если уже инициализирован, пропускаем
if ($element.data('select2')) {
return;
}
var placeholders = {
'product': 'Начните вводить название товара...',
'variant': 'Начните вводить название группы...'
};
var config = {
theme: 'bootstrap-5',
placeholder: placeholders[type] || 'Выберите...',
allowClear: true,
language: 'ru',
minimumInputLength: 0,
ajax: {
url: apiUrl,
dataType: 'json',
delay: 250,
data: function (params) {
return {
q: params.term || '',
type: type,
page: params.page || 1
};
},
processResults: function (data) {
return {
results: data.results,
pagination: {
more: data.pagination.more
}
};
},
cache: true
},
templateResult: formatSelectResult,
templateSelection: formatSelectSelection
};
// Если есть предзагруженные данные, создаем option с ними
if (preloadedData) {
var option = new Option(preloadedData.text, preloadedData.id, true, true);
$element.append(option);
}
$element.select2(config);
};
/**
* Инициализирует Select2 для всех элементов с данным селектором
* @param {string} selector - CSS селектор элементов
* @param {string} type - Тип поиска ('product' или 'variant')
* @param {string} apiUrl - URL API для поиска
*/
window.initAllProductSelect2 = function(selector, type, apiUrl) {
document.querySelectorAll(selector).forEach(function(element) {
window.initProductSelect2(element, type, apiUrl);
});
};
})(window);