Fix: Implement proper deletion of order items with confirmation dialog
Fixes deletion functionality for order items across frontend and backend: - Remove restriction preventing deletion of last item - Add confirmation dialog before deletion - Properly track and send deleted item IDs to backend via autosave - Update backend to handle item deletion by ID instead of index - Fix visual feedback: deleted items are hidden immediately - Auto-recalculate total sum after deletion Technical changes: - order_form.html: Add confirmation dialog, trigger autosave on delete - autosave.js: Collect deleted item IDs, send to backend - draft_service.py: Process deleted_item_ids, update items by ID 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
{% load l10n %}
|
||||
|
||||
{% block title %}{{ title }}{% endblock %}
|
||||
|
||||
@@ -227,11 +228,11 @@
|
||||
<label class="form-label">Цена</label>
|
||||
<div class="position-relative">
|
||||
{% if item_form.instance.product %}
|
||||
<input type="number" name="{{ item_form.price.name }}" step="0.01" min="0" class="form-control" id="{{ item_form.price.id_for_label }}" value="{% if item_form.instance.price %}{{ item_form.instance.price }}{% else %}{{ item_form.instance.product.actual_price }}{% endif %}" data-original-price="{{ item_form.instance.product.actual_price }}">
|
||||
<input type="text" name="{{ item_form.prefix }}-price" step="0.01" min="0" class="form-control" id="{{ item_form.price.id_for_label }}" value="{% if item_form.instance.price and item_form.instance.price != 0 %}{{ item_form.instance.price }}{% else %}{{ item_form.instance.product.actual_price }}{% endif %}" data-original-price="{{ item_form.instance.product.actual_price }}">
|
||||
{% elif item_form.instance.product_kit %}
|
||||
<input type="number" name="{{ item_form.price.name }}" step="0.01" min="0" class="form-control" id="{{ item_form.price.id_for_label }}" value="{% if item_form.instance.price %}{{ item_form.instance.price }}{% else %}{{ item_form.instance.product_kit.actual_price }}{% endif %}" data-original-price="{{ item_form.instance.product_kit.actual_price }}">
|
||||
<input type="text" name="{{ item_form.prefix }}-price" step="0.01" min="0" class="form-control" id="{{ item_form.price.id_for_label }}" value="{% if item_form.instance.price and item_form.instance.price != 0 %}{{ item_form.instance.price }}{% else %}{{ item_form.instance.product_kit.actual_price }}{% endif %}" data-original-price="{{ item_form.instance.product_kit.actual_price }}">
|
||||
{% else %}
|
||||
{{ item_form.price }}
|
||||
<input type="text" name="{{ item_form.prefix }}-price" step="0.01" min="0" class="form-control" id="{{ item_form.price.id_for_label }}" value="{{ item_form.instance.price|default:'' }}" data-original-price="0">
|
||||
{% endif %}
|
||||
<span class="custom-price-badge badge bg-warning position-absolute top-0 end-0 mt-1 me-1" style="display: none;">
|
||||
Изменена
|
||||
@@ -302,7 +303,7 @@
|
||||
<div class="mb-2">
|
||||
<label class="form-label">Цена</label>
|
||||
<div class="position-relative">
|
||||
<input type="number" name="items-__prefix__-price" step="0.01" min="0" class="form-control" id="id_items-__prefix__-price">
|
||||
<input type="text" name="items-__prefix__-price" step="0.01" min="0" class="form-control" id="id_items-__prefix__-price">
|
||||
<span class="custom-price-badge badge bg-warning position-absolute top-0 end-0 mt-1 me-1" style="display: none;">
|
||||
Изменена
|
||||
</span>
|
||||
@@ -1001,18 +1002,34 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
let total = 0;
|
||||
|
||||
console.log('[TOTAL] Calculating total for', visibleForms.length, 'forms');
|
||||
|
||||
// Для каждого товара: количество × цена
|
||||
visibleForms.forEach(form => {
|
||||
visibleForms.forEach((form, index) => {
|
||||
const quantityField = form.querySelector('[name$="-quantity"]');
|
||||
const priceField = form.querySelector('[name$="-price"]');
|
||||
|
||||
console.log(`[TOTAL] Form ${index}:`, form);
|
||||
console.log(`[TOTAL] Form ${index}: quantityField=${quantityField}, priceField=${priceField}`);
|
||||
const allInputs = form.querySelectorAll('input');
|
||||
console.log(`[TOTAL] Form ${index}: All inputs:`, allInputs);
|
||||
allInputs.forEach((input, i) => {
|
||||
console.log(` Input ${i}: name="${input.name}", id="${input.id}", type="${input.type}"`);
|
||||
});
|
||||
|
||||
if (quantityField && priceField) {
|
||||
const quantity = parseFloat(quantityField.value) || 0;
|
||||
const price = parseFloat(priceField.value) || 0;
|
||||
// Заменяем запятую на точку для корректного парсинга
|
||||
const priceValue = priceField.value.replace(',', '.');
|
||||
const price = parseFloat(priceValue) || 0;
|
||||
console.log(`[TOTAL] Form ${index}: quantity=${quantityField.value} (parsed: ${quantity}), price="${priceField.value}" (parsed: ${price}), subtotal=${quantity * price}`);
|
||||
total += quantity * price;
|
||||
} else {
|
||||
console.log(`[TOTAL] Form ${index}: SKIPPED - missing fields!`);
|
||||
}
|
||||
});
|
||||
|
||||
console.log('[TOTAL] Final total:', total);
|
||||
return total;
|
||||
}
|
||||
|
||||
@@ -1129,25 +1146,26 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
// Функция для удаления формы
|
||||
function removeForm(form) {
|
||||
// Показываем диалог подтверждения
|
||||
if (!confirm('Вы действительно хотите удалить этот товар из заказа?')) {
|
||||
return; // Пользователь отменил удаление
|
||||
}
|
||||
|
||||
const deleteCheckbox = form.querySelector('input[name$="-DELETE"]');
|
||||
const idField = form.querySelector('input[name$="-id"]');
|
||||
|
||||
// Проверяем, не последняя ли это форма
|
||||
const visibleForms = Array.from(container.querySelectorAll('.order-item-form'))
|
||||
.filter(f => !f.classList.contains('deleted'));
|
||||
|
||||
if (visibleForms.length <= 1) {
|
||||
alert('Нельзя удалить единственную позицию. Добавьте новую позицию перед удалением этой.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Если форма уже сохранена (есть ID), помечаем на удаление
|
||||
if (idField && idField.value) {
|
||||
deleteCheckbox.checked = true;
|
||||
form.classList.add('deleted');
|
||||
console.log('Form marked for deletion');
|
||||
form.style.display = 'none'; // Скрываем форму визуально
|
||||
console.log('Form marked for deletion, id:', idField.value);
|
||||
// Обновляем итоговую сумму после удаления
|
||||
updateOrderItemsTotal();
|
||||
// Триггерим автосохранение для отправки изменений
|
||||
if (typeof window.orderAutosave !== 'undefined' && window.orderAutosave.scheduleAutosave) {
|
||||
window.orderAutosave.scheduleAutosave();
|
||||
}
|
||||
} else {
|
||||
// Если форма новая, просто удаляем из DOM
|
||||
form.remove();
|
||||
|
||||
Reference in New Issue
Block a user