Рефакторинг: перенос логики создания временных комплектов в сервис
Изменения: - Удалена функция create_temporary_kit из myproject/orders/views.py - Перенесена в новый сервис myproject/products/services/kit_service.py - Добавлен API endpoint products:api-temporary-kit-create для создания временных комплектов - Обновлены URL-ы соответственно Преимущества: - Логика временных комплектов теперь находится в соответствующем приложении (products) - Упрощена архитектура orders приложения - Сервис может быть переиспользован в других контекстах - Лучшее разделение ответственности между приложениями 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
{% for kititem_form in kititem_formset %}
|
||||
<div class="card mb-2 kititem-form border"
|
||||
data-form-index="{{ forloop.counter0 }}"
|
||||
data-product-id="{% if kititem_form.instance.product %}{{ kititem_form.instance.product.id }}{% endif %}"
|
||||
data-product-price="{% if kititem_form.instance.product %}{{ kititem_form.instance.product.actual_price|default:0 }}{% else %}0{% endif %}">
|
||||
{{ kititem_form.id }}
|
||||
<div class="card-body p-2">
|
||||
@@ -61,7 +62,7 @@
|
||||
<!-- УДАЛЕНИЕ -->
|
||||
<div class="col-md-1 text-end">
|
||||
{% if kititem_form.DELETE %}
|
||||
<button type="button" class="btn btn-sm btn-link text-danger p-0" onclick="this.previousElementSibling.checked = true; this.closest('.kititem-form').style.display='none';" title="Удалить">
|
||||
<button type="button" class="btn btn-sm btn-link text-danger p-0" onclick="this.nextElementSibling.checked = true; this.closest('.kititem-form').style.display='none'; if(typeof calculateFinalPrice === 'function') calculateFinalPrice();" title="Удалить">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
{{ kititem_form.DELETE }}
|
||||
|
||||
@@ -442,10 +442,23 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const productId = parseInt(selectElement.value);
|
||||
const rawValue = selectElement.value;
|
||||
if (!rawValue) {
|
||||
console.warn('getProductPrice: no value');
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!selectElement.value || isNaN(productId) || productId <= 0) {
|
||||
console.warn('getProductPrice: no valid product id', selectElement.value);
|
||||
// Извлекаем числовой ID из значения (может быть "product_123" или "123")
|
||||
let productId;
|
||||
if (rawValue.includes('_')) {
|
||||
const parts = rawValue.split('_');
|
||||
productId = parseInt(parts[1]);
|
||||
} else {
|
||||
productId = parseInt(rawValue);
|
||||
}
|
||||
|
||||
if (isNaN(productId) || productId <= 0) {
|
||||
console.warn('getProductPrice: invalid product id', rawValue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -471,15 +484,19 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
}
|
||||
}
|
||||
|
||||
// Пытаемся получить из Select2 option data (сначала actual_price, потом price)
|
||||
const selectedOption = $(selectElement).find('option:selected');
|
||||
let priceData = selectedOption.data('actual_price') || selectedOption.data('price');
|
||||
if (priceData) {
|
||||
const price = parseFloat(priceData) || 0;
|
||||
if (price > 0) {
|
||||
priceCache[productId] = price;
|
||||
console.log('getProductPrice: from select2 data', productId, price);
|
||||
return price;
|
||||
// Пытаемся получить из Select2 data (приоритет: actual_price > price)
|
||||
const $select = $(selectElement);
|
||||
const selectedData = $select.select2('data');
|
||||
if (selectedData && selectedData.length > 0) {
|
||||
const itemData = selectedData[0];
|
||||
const priceData = itemData.actual_price || itemData.price;
|
||||
if (priceData) {
|
||||
const price = parseFloat(priceData) || 0;
|
||||
if (price > 0) {
|
||||
priceCache[productId] = price;
|
||||
console.log('getProductPrice: from select2 data', productId, price);
|
||||
return price;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -514,7 +531,12 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
$('[name$="-product"]').on('select2:select', async function() {
|
||||
const form = $(this).closest('.kititem-form');
|
||||
if (this.value) {
|
||||
form.attr('data-product-id', this.value);
|
||||
// Извлекаем числовой ID из "product_123"
|
||||
let numericId = this.value;
|
||||
if (this.value.includes('_')) {
|
||||
numericId = this.value.split('_')[1];
|
||||
}
|
||||
form.attr('data-product-id', numericId);
|
||||
// Загружаем цену и пересчитываем
|
||||
await getProductPrice(this);
|
||||
calculateFinalPrice();
|
||||
|
||||
Reference in New Issue
Block a user