Реализован функционал создания временных комплектов на витрину из POS

- Добавлен API endpoint для создания временного комплекта из корзины
- Реализован endpoint получения списка активных витрин
- Создано модальное окно для настройки комплекта и выбора витрины
- JavaScript логика: валидация корзины, отправка данных, очистка после успеха
- Автоматическая генерация названия комплекта с датой и временем
- Агрегация дубликатов товаров в корзине перед созданием
- Резервирование компонентов на витрину через ShowcaseManager
- Расчёт и отображение итоговой цены комплекта
This commit is contained in:
2025-11-16 21:24:07 +03:00
parent 8f6acfb364
commit 156f646252
4 changed files with 403 additions and 3 deletions

View File

@@ -285,9 +285,200 @@ document.getElementById('clearCart').onclick = clearCart;
// Кнопка "На витрину" - функционал будет добавлен позже
document.getElementById('addToShowcaseBtn').onclick = () => {
alert('Функционал "На витрину" будет реализован позже');
openCreateTempKitModal();
};
// Функция открытия модального окна для создания временного комплекта
async function openCreateTempKitModal() {
// Проверяем что корзина не пуста
if (cart.size === 0) {
alert('Корзина пуста. Добавьте товары перед созданием комплекта.');
return;
}
// Проверяем что в корзине только товары (не комплекты)
let hasKits = false;
for (const [cartKey, item] of cart) {
if (item.type === 'kit') {
hasKits = true;
break;
}
}
if (hasKits) {
alert('В корзине есть комплекты. Для витрины добавляйте только отдельные товары.');
return;
}
// Генерируем название по умолчанию
const now = new Date();
const defaultName = `Витрина — ${now.toLocaleDateString('ru-RU')} ${now.toLocaleTimeString('ru-RU', {hour: '2-digit', minute: '2-digit'})}`;
document.getElementById('tempKitName').value = defaultName;
// Загружаем список витрин
await loadShowcases();
// Заполняем список товаров из корзины
renderTempKitItems();
// Открываем модальное окно
const modal = new bootstrap.Modal(document.getElementById('createTempKitModal'));
modal.show();
}
// Загрузка списка витрин
async function loadShowcases() {
try {
const response = await fetch('/pos/api/get-showcases/');
const data = await response.json();
const select = document.getElementById('showcaseSelect');
select.innerHTML = '<option value="">Выберите витрину...</option>';
if (data.success && data.showcases.length > 0) {
data.showcases.forEach(showcase => {
const option = document.createElement('option');
option.value = showcase.id;
option.textContent = `${showcase.name} (${showcase.warehouse_name})`;
select.appendChild(option);
});
} else {
select.innerHTML = '<option value="">Нет доступных витрин</option>';
}
} catch (error) {
console.error('Error loading showcases:', error);
alert('Ошибка загрузки витрин');
}
}
// Отображение товаров из корзины в модальном окне
function renderTempKitItems() {
const container = document.getElementById('tempKitItemsList');
container.innerHTML = '';
let estimatedTotal = 0;
cart.forEach((item, cartKey) => {
// Только товары (не комплекты)
if (item.type !== 'product') return;
const itemDiv = document.createElement('div');
itemDiv.className = 'd-flex justify-content-between align-items-center mb-2 pb-2 border-bottom';
itemDiv.innerHTML = `
<div>
<strong>${item.name}</strong>
<br>
<small class="text-muted">${item.qty} шт × ${formatMoney(item.price)} руб.</small>
</div>
<div class="text-end">
<strong>${formatMoney(item.qty * item.price)} руб.</strong>
</div>
`;
container.appendChild(itemDiv);
estimatedTotal += item.qty * item.price;
});
document.getElementById('tempKitEstimatedPrice').textContent = formatMoney(estimatedTotal);
}
// Подтверждение создания временного комплекта
document.getElementById('confirmCreateTempKit').onclick = async () => {
const kitName = document.getElementById('tempKitName').value.trim();
const showcaseId = document.getElementById('showcaseSelect').value;
// Валидация
if (!kitName) {
alert('Введите название комплекта');
return;
}
if (!showcaseId) {
alert('Выберите витрину');
return;
}
// Собираем товары из корзины
const items = [];
cart.forEach((item, cartKey) => {
if (item.type === 'product') {
items.push({
product_id: item.id,
quantity: item.qty
});
}
});
if (items.length === 0) {
alert('Нет товаров для создания комплекта');
return;
}
// Отправляем запрос на сервер
const confirmBtn = document.getElementById('confirmCreateTempKit');
confirmBtn.disabled = true;
confirmBtn.innerHTML = '<span class="spinner-border spinner-border-sm me-2"></span>Создание...';
try {
const response = await fetch('/pos/api/create-temp-kit/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': getCookie('csrftoken')
},
body: JSON.stringify({
kit_name: kitName,
showcase_id: parseInt(showcaseId),
items: items,
price_adjustment_type: 'none',
price_adjustment_value: 0
})
});
const data = await response.json();
if (data.success) {
// Успех!
alert(`${data.message}
Комплект: ${data.kit_name}
Цена: ${data.kit_price} руб.
Зарезервировано компонентов: ${data.reservations_count}`);
// Очищаем корзину
clearCart();
// Закрываем модальное окно
const modal = bootstrap.Modal.getInstance(document.getElementById('createTempKitModal'));
modal.hide();
} else {
alert(`Ошибка: ${data.error}`);
}
} catch (error) {
console.error('Error creating temp kit:', error);
alert('Ошибка при создании комплекта');
} finally {
confirmBtn.disabled = false;
confirmBtn.innerHTML = '<i class="bi bi-check-circle"></i> Создать и зарезервировать';
}
};
// Вспомогательная функция для получения CSRF токена
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim();
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
// Заглушки для функционала (будет реализовано позже)
document.getElementById('checkoutNow').onclick = async () => {
alert('Функционал будет подключен позже: создание заказа и списание со склада.');