feat: добавлена интеграция синхронизации с Recommerce
This commit is contained in:
128
myproject/products/static/products/js/recommerce-sync.js
Normal file
128
myproject/products/static/products/js/recommerce-sync.js
Normal file
@@ -0,0 +1,128 @@
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const syncBtn = document.getElementById('bulk-recommerce-sync');
|
||||
const modalEl = document.getElementById('recommerceSyncModal');
|
||||
const startBtn = document.getElementById('startRecommerceSyncBtn');
|
||||
|
||||
if (!syncBtn || !modalEl) return;
|
||||
|
||||
const modal = new bootstrap.Modal(modalEl);
|
||||
|
||||
syncBtn.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
// Получаем выбранные элементы
|
||||
// Предполагается, что на странице есть механизм BatchSelection или просто чекбоксы
|
||||
let selectedItems = [];
|
||||
|
||||
// Проверяем глобальный объект BatchSelection (из batch-selection.js)
|
||||
if (window.BatchSelection && typeof window.BatchSelection.getSelectedItems === 'function') {
|
||||
selectedItems = window.BatchSelection.getSelectedItems();
|
||||
} else {
|
||||
// Fallback: собираем вручную
|
||||
document.querySelectorAll('.item-checkbox:checked').forEach(cb => {
|
||||
selectedItems.push(cb.value);
|
||||
});
|
||||
}
|
||||
|
||||
// Фильтруем только товары (формат value="product:123")
|
||||
// Комплекты (kit:123) пока игнорируем, так как бэкенд ожидает Product ID
|
||||
const productIds = selectedItems
|
||||
.filter(val => val.startsWith('product:'))
|
||||
.map(val => val.split(':')[1]);
|
||||
|
||||
if (productIds.length === 0) {
|
||||
// Если выбраны только комплекты или ничего не выбрано
|
||||
if (selectedItems.length > 0) {
|
||||
alert('Для синхронизации с Recommerce выберите товары (комплекты пока не поддерживаются).');
|
||||
} else {
|
||||
alert('Выберите товары для синхронизации.');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Обновляем UI модального окна
|
||||
document.getElementById('recommerceSyncCount').textContent = productIds.length;
|
||||
|
||||
// Сохраняем ID для отправки
|
||||
startBtn.dataset.productIds = JSON.stringify(productIds);
|
||||
|
||||
modal.show();
|
||||
});
|
||||
|
||||
startBtn.addEventListener('click', function() {
|
||||
const productIds = JSON.parse(this.dataset.productIds || '[]');
|
||||
|
||||
const options = {
|
||||
fields: [],
|
||||
create_if_missing: document.getElementById('syncCreateNew').checked
|
||||
};
|
||||
|
||||
if (document.getElementById('syncPrice').checked) options.fields.push('price');
|
||||
if (document.getElementById('syncStock').checked) options.fields.push('count');
|
||||
if (document.getElementById('syncContent').checked) options.fields.push('content');
|
||||
if (document.getElementById('syncImages').checked) options.fields.push('images');
|
||||
|
||||
// Блокируем кнопку
|
||||
startBtn.disabled = true;
|
||||
const originalText = startBtn.innerHTML;
|
||||
startBtn.innerHTML = '<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Запуск...';
|
||||
|
||||
fetch('/settings/integrations/recommerce/sync/', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRFToken': getCsrfToken()
|
||||
},
|
||||
body: JSON.stringify({
|
||||
product_ids: productIds,
|
||||
options: options
|
||||
})
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
modal.hide();
|
||||
// Используем стандартный alert или toast, если есть
|
||||
alert(`Синхронизация запущена успешно!\nID задачи: ${data.task_id}\nОбрабатывается товаров: ${productIds.length}`);
|
||||
|
||||
// Снимаем выделение
|
||||
if (window.BatchSelection && typeof window.BatchSelection.clearSelection === 'function') {
|
||||
window.BatchSelection.clearSelection();
|
||||
}
|
||||
} else {
|
||||
alert('Ошибка при запуске: ' + (data.error || 'Неизвестная ошибка'));
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
alert('Ошибка сети или сервера');
|
||||
})
|
||||
.finally(() => {
|
||||
startBtn.disabled = false;
|
||||
startBtn.innerHTML = originalText;
|
||||
});
|
||||
});
|
||||
|
||||
// Helper для получения CSRF токена
|
||||
function getCsrfToken() {
|
||||
// Сначала пробуем получить из скрытого поля (для CSRF_USE_SESSIONS = True)
|
||||
const csrfInput = document.querySelector('[name=csrfmiddlewaretoken]');
|
||||
if (csrfInput) {
|
||||
return csrfInput.value;
|
||||
}
|
||||
// Fallback: из куки
|
||||
const name = 'csrftoken';
|
||||
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;
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user