fix(products): исправить калькулятор цены и выбор единицы продажи при создании комплекта

- Добавить объявление salesUnitSelect в calculateFinalPrice
- Добавить обновление Select2 после загрузки единиц продажи
- Добавить вызов updateSalesUnitsOptions при выборе товара
- Получать цену единицы продажи из DOM option элемента
- Исправить опечатку в заголовке списка товаров

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-21 22:45:36 +03:00
parent 07a9de040f
commit 391d48640b
2 changed files with 73 additions and 9 deletions

View File

@@ -574,7 +574,21 @@ document.addEventListener('DOMContentLoaded', function() {
return cachedPrice;
}
// Пытаемся получить из Select2 data (приоритет: actual_price > price)
// Пытаемся получить цену из выбранного option элемента (приоритет)
const selectedOption = $(selectElement).find('option:selected');
if (selectedOption.length > 0) {
const priceData = selectedOption.data('actual_price') || selectedOption.data('price');
if (priceData) {
const price = parseFloat(priceData) || 0;
if (price > 0) {
priceCache[cacheKey] = price;
console.log('getSalesUnitPrice: from option data', salesUnitId, price);
return price;
}
}
}
// Пытаемся получить из Select2 data
const $select = $(selectElement);
const selectedData = $select.select2('data');
if (selectedData && selectedData.length > 0) {
@@ -661,6 +675,8 @@ document.addEventListener('DOMContentLoaded', function() {
salesUnitSelect.appendChild(option);
});
salesUnitSelect.disabled = false;
// Обновляем Select2
$(salesUnitSelect).trigger('change');
}
}
} catch (error) {
@@ -680,9 +696,21 @@ document.addEventListener('DOMContentLoaded', function() {
form.attr('data-product-id', numericId);
// Загружаем цену и пересчитываем
await getProductPrice(this);
// Обновляем список единиц продажи для выбранного товара
const salesUnitSelect = form.find('[name$="-sales_unit"]')[0];
if (salesUnitSelect) {
await updateSalesUnitsOptions(salesUnitSelect, this.value);
}
calculateFinalPrice();
}
}).on('select2:unselect', function() {
const form = $(this).closest('.kititem-form');
// Очищаем список единиц продажи
const salesUnitSelect = form.find('[name$="-sales_unit"]')[0];
if (salesUnitSelect) {
salesUnitSelect.innerHTML = '<option value="">---------</option>';
$(salesUnitSelect).trigger('change');
}
calculateFinalPrice();
});
@@ -758,6 +786,7 @@ document.addEventListener('DOMContentLoaded', function() {
for (const form of forms) {
const productSelect = form.querySelector('[name$="-product"]');
const variantGroupSelect = form.querySelector('[name$="-variant_group"]');
const salesUnitSelect = form.querySelector('[name$="-sales_unit"]');
const quantity = parseFloat(form.querySelector('[name$="-quantity"]')?.value || '1');
const deleteCheckbox = form.querySelector('[name$="-DELETE"]');
@@ -943,15 +972,23 @@ document.addEventListener('DOMContentLoaded', function() {
const fieldName = $(this).attr('name');
const preloadedData = selectedProducts[fieldName] || null;
initSelect2(this, 'product', preloadedData);
// Добавляем обработчик для пересчета цены при изменении товара
$(this).on('select2:select select2:unselect', calculateFinalPrice);
// Обработчик уже добавлен выше (строки 673-701)
});
$('[name$="-variant_group"]').each(function() {
const fieldName = $(this).attr('name');
const preloadedData = selectedVariants[fieldName] || null;
initSelect2(this, 'variant', preloadedData);
$(this).on('select2:select select2:unselect', calculateFinalPrice);
// При выборе варианта очищаем единицу продажи
$(this).on('select2:select', function() {
const form = $(this).closest('.kititem-form');
const salesUnitSelect = form.find('[name$="-sales_unit"]')[0];
if (salesUnitSelect) {
salesUnitSelect.innerHTML = '<option value="">---------</option>';
$(salesUnitSelect).trigger('change');
}
calculateFinalPrice();
}).on('select2:unselect', calculateFinalPrice);
});
$('[name$="-sales_unit"]').each(function() {
@@ -1086,16 +1123,43 @@ document.addEventListener('DOMContentLoaded', function() {
const productSelect = newForm.querySelector('[name$="-product"]');
const variantSelect = newForm.querySelector('[name$="-variant_group"]');
const salesUnitSelect = newForm.querySelector('[name$="-sales_unit"]');
initSelect2(productSelect, 'product');
initSelect2(variantSelect, 'variant');
initSelect2(salesUnitSelect, 'sales_unit');
// Добавляем обработчики для новой формы
$(productSelect).on('select2:select select2:unselect', calculateFinalPrice);
$(variantSelect).on('select2:select select2:unselect', calculateFinalPrice);
// Добавляем обработчики для новой формы (как в основном коде)
$(productSelect).on('select2:select', async function() {
const form = $(this).closest('.kititem-form');
if (this.value) {
let numericId = this.value;
if (this.value.includes('_')) {
numericId = this.value.split('_')[1];
}
form.attr('data-product-id', numericId);
await getProductPrice(this);
if (salesUnitSelect) {
await updateSalesUnitsOptions(salesUnitSelect, this.value);
}
}
calculateFinalPrice();
}).on('select2:unselect', function() {
if (salesUnitSelect) {
salesUnitSelect.innerHTML = '<option value="">---------</option>';
$(salesUnitSelect).trigger('change');
}
calculateFinalPrice();
});
$(variantSelect).on('select2:select', function() {
if (salesUnitSelect) {
salesUnitSelect.innerHTML = '<option value="">---------</option>';
$(salesUnitSelect).trigger('change');
}
calculateFinalPrice();
}).on('select2:unselect', calculateFinalPrice);
$(salesUnitSelect).on('select2:select select2:unselect', calculateFinalPrice);
initializeForm(newForm);

View File

@@ -7,7 +7,7 @@
{% csrf_token %}
<div class="container-fluid mt-4">
<h2 class="mb-4">
<i class="bi bi-box-seam"></i> Товары я они все комплекты
<i class="bi bi-box-seam"></i> Товары и комплекты
</h2>
<!-- Панель фильтрации и действий -->