';
}
popup('bad', 'Ошибка!', 'Запись данных невозможна! Обнаружено совпадение ИНН/КПП по клиенту/ам:
' + clientDublicateInnKpp, true, false);
clearInterval(waitResult);
dataResult = {};
}
}, 1);
return;
break;
case 'send_request':
// Если отправка данных заявки
send_request(datas, formId);
return;
break;
case 'add_furniture':
// Если добавление фурнитуры
saveFurniture(datas);
return;
break;
case 'send_purchase_payment':
// Если запрос отчета по взаиморасчетам
send_request(datas, formId);
return;
break;
case 'tasks_form':
case 'events_form':
// Если форма добавления задач
send_request(datas, 'data-exchange', 'data-add-task', formId, files);
return;
break;
default:
dataSend(formId, datas, getFormFiles(form));
}
} else {
preloader();
}
}
});
// Функция отправки данных и файлов
window.dataSend = function(url, datas, files) {
// Отображаем прелоадер
preloader();
preloader('show');
// Создадим данные формы и добавим в них данные файлов из files
var data = new FormData();
$.each(files, function(key, value) {
data.append(key, value);
});
// Создадим данные формы и добавим в них данные из других полей ввода
$.each(datas, function(key, value) {
data.append(value.name, value.value);
});
// Вывод отправляемых данных
//for (var pair of data.entries()) {
// console.log(pair[0]+ ', ' + pair[1]);
//}
// Правило для форм с файлами договоров
if (url.indexOf('file-vehicles') > -1) url = 'file-vehicles';
// Правило для формы авторизации
var uri = (url == 'login_form' || url == 'recover_form' || url == 'registry_form') ? '/' : '/' + module + '/' + url;
// Правило для форм с классическим типом отправки данных
if (url == 'filter' || url == 'search') {
$('#' + url).unbind('submit').submit();
return;
}
// Отправляем запрос
$.ajax({
url: uri + '?sharkey=' + sharkey,
type: 'POST',
data: data,
cache: false,
async: false,
processData: false,
contentType: false,
success: function(respond, textStatus, jqXHR) {
switch (url) {
case 'get_price':
var date = new Date();
var dd = date.getDate();
if (dd < 10) dd = '0' + dd;
var mm = date.getMonth() + 1;
if (mm < 10) mm = '0' + mm;
var yy = date.getFullYear();
if (yy < 10) yy = '0' + yy;
popup('good', 'Успешно!', 'Файл доступен для скачивания по этой ссылке.', true, false);
break;
case 'recover_form':
sessionStorage.removeItem('JustCRM-LastLogin');
try {
var clientmail = JSON.parse(respond);
console.log('Отправлено на e-mail:', clientmail)
popup('good', 'Отправлено', 'Отправлено на e-mail: '+clientmail['clientmail']+'!', true, false);
} catch (e) {
console.log('Ошибка:', e)
}
setTimeout(function() {
location.reload();
}, 3000);
break;
case 'registry_form':
popup('good', 'Успешно!', 'Вам на указанную почту отправлена информация по вашей заявке!', true, false);
setTimeout(function() {
location.reload();
}, 10000);
break;
case 'login_form':
sessionStorage.removeItem('JustCRM-LastLogin');
localStorage.removeItem('JustCRM_lastURL');
// В просмотрщике Я.Метрики (кросс-доменный top) уход на корень сайта
// перестраивает цепочку фреймов и даёт белый экран — вместо этого
// перезагружаем текущий URL: сессия уже создана, откроется та же страница.
var foreignTop = false;
try { void window.top.document; } catch (e) { foreignTop = true; }
if (foreignTop) {
window.location.reload();
} else {
window.location.href = window.location.origin;
}
break;
case 'file_upload':
popup('good', 'Успешно!', 'Файл данных загружен и обработан.', true, false);
break;
case 'mail_new_form':
popup('good', 'Успешно!', 'Письмо отправлено.', true, false);
delayClosePopup(1000);
delayReload(1000, '/' + curUrl[1] + '/' + curUrl[2] + '/' + curUrl[3]);
break;
case 'test_mail_form':
popup('good', 'Успешно!', 'Письмо отправлено.', true, false);
delayClosePopup(1000);
delayReload(1000, '/' + curUrl[1] + '/' + curUrl[2] + '/' + curUrl[3] + '/' + curUrl[4]);
break;
case 'utm_form':
case 'client_contacts_form':
case 'client_comments_form':
case 'document_comment_form':
case 'files-order':
case 'client_file_cat_form':
case 'client_file_form':
case 'client_vehicles_form':
case 'client_vehicles_new_form':
case 'client_add_phone_form':
case 'client_needs_form':
case 'client_budjet_form':
case 'client_features_form':
case 'file-vehicles':
popup('good', 'Успешно!', 'Данные обработаны.', true, false);
delayClosePopup(1000);
delayReload(1000, '/' + curUrl[1] + '/' + curUrl[2] + '/' + curUrl[3]);
break;
case 'client_all_file_cat_form':
case 'client_all_file_form':
popup('good', 'Успешно!', 'Данные обработаны.', true, false);
delayClosePopup(1000);
// Добавляем строку параметров в конце (если они есть)
delayReload(1000, '/' + curUrl[1] + '?' + location.href.split('?')[1]);
break;
//case 'client_form':
//popup ('bad', 'Ошибка!', 'Добавление клиентов c одинаковыми ИНН/КПП запрещено! '+innKppDublicate, true, false);
//location.href = '/'+module+'/_details/'+curUrl[3];
//break;
case 'draw_form':
delayClosePopup(1000);
delayReload(1000, '/' + curUrl[1]);
break;
default:
// Закомментировать, или сделать условие для своего IP, чтобы после отправки данных формы страница не перезагружалась.
//if (userIP != '85.236.191.169') {
// Если редактировали форму на странице полной информации, то возвращаемся обратно на эту страницу
if (document.referrer.indexOf('/_') >= 0 && data.get('GUID') != '') {
window.location.href = document.referrer;
} else {
delayClosePopup(100);
delayReload(100, uri);
}
//}
}
return;
},
error: function(jqxhr) {
switch (url) {
case 'login_form':
switch (jqxhr.status) {
case 401:
popup('bad', 'Ошибка!', 'Неверное значение в поле логин/пароль.', true, false);
var lastLogin = sessionStorage['JustCRM-LastLogin'];
if (typeof lastLogin == 'undefined') {
sessionStorage['JustCRM-LastLogin'] = 1;
} else {
lastLogin = Number(lastLogin);
lastLogin = lastLogin + 1;
sessionStorage['JustCRM-LastLogin'] = lastLogin++;
if (lastLogin >= 5) {
delayClosePopup(0);
setTimeout(function() {
popup ('small', '', 'recover');
$('#login_to_recover').val($('#login_username').val());
}, 500);
}
}
break;
case 501:
popup('bad', 'Ошибка!', 'Ваш аккаунт еще не активирован администрацией.', true, false);
break;
case 423:
popup('bad', 'Ошибка!', 'Аккаунт заблокирован! Свяжитесь с Вашим менеджером.', false, true);
break;
case 412:
popup('bad', 'Ошибка!', 'Неверное значение поля защиты от спама!', true, false);
break;
case 405:
popup('bad', 'Ошибка!', 'Вход в мобильный интерфейс возможен только для клиентов!', true, false);
break;
case 413:
popup('bad', 'Ошибка!', 'Для указанного логина отсутсвует e-mail!', true, false);
break;
case 414:
popup('bad', 'Ошибка!', 'Ваш логин не найден!', true, false);
break;
case 415:
popup('bad', 'Ошибка!', 'Ошибка отправки e-mail!', true, false);
break;
}
break;
case 'recover_form':
switch (jqxhr.status) {
case 401:
popup('bad', 'Ошибка!', 'Неверное значение в поле логин.', true, false);
break;
case 501:
popup('bad', 'Ошибка!', 'Ваш аккаунт еще не активирован администрацией.', true, false);
break;
case 423:
popup('bad', 'Ошибка!', 'Аккаунт заблокирован! Свяжитесь с Вашим менеджером.', false, true);
break;
case 412:
popup('bad', 'Ошибка!', 'Неверное значение поля защиты от спама!', true, false);
break;
case 405:
popup('bad', 'Ошибка!', 'Вход в мобильный интерфейс возможен только для клиентов!', true, false);
break;
case 413:
popup('bad', 'Ошибка!', 'Логин не найден, либо отсутсвует e-mail!', true, false);
break;
case 414:
popup('bad', 'Ошибка!', 'Ваш логин не найден!', true, false);
break;
case 415:
popup('bad', 'Ошибка!', 'Ошибка отправки e-mail!', true, false);
break;
case 416:
popup('bad', 'Ошибка!', 'Пользователь не уникален!', true, false);
break;
}
break;
case 'file_upload':
switch (jqxhr.status) {
case 409:
popup('bad', 'Ошибка!', 'Число файлов не может превышать 1-го.', true, false);
break;
case 500:
popup('bad', 'Отправка прервана!', 'Один, или несколько файлов невозможно обработать. Размер файлов не должен превышать 3Mb.', true, false);
break;
case 413:
popup('bad', 'Ошибка!', 'Размер файлов не должен превышать 3Mb!', true, false);
break;
case 406:
popup('bad', 'Ошибка!', 'Нет файла для обработки!', true, false);
break;
default:
popup('bad', '', 'Неизвестная ошибка!', true, false);
}
break;
case 'user_form':
switch (jqxhr.status) {
case 412:
popup('bad', 'Ошибка!', 'Данное Ф.И.О/E-mail уже зарегистрирован/ы.', true, false);
break;
default:
popup('bad', '', 'Неизвестная ошибка!', true, false);
}
break;
case 'registry_form':
switch (jqxhr.status) {
case 415:
popup('bad', 'Ошибка!', 'Ошибка отправки e-mail!', true, false);
break;
default:
popup('bad', '', 'Неизвестная ошибка!', true, false);
}
break;
case 'client_lidas_form':
var responceLidas = JSON.parse(jqxhr.responseText);
if (Object.keys(responceLidas.error).length > 0) {
var errorLidasContent = '
№ строки:
Перечень ошибок:
';
for (key in responceLidas.error) {
//console.log(responceLidas.error[key].error, responceLidas.error[key].str_num);
errorLidasContent += '
' + responceLidas.error[key].str_num + '
';
if (Array.isArray(responceLidas.error[key].error)) {
for (keyArr in responceLidas.error[key].error) {
errorLidasContent += '
' + responceLidas.error[key].error[keyArr] + '
';
}
}
errorLidasContent += '
';
}
errorLidasContent += '
'
popup('bad', 'Ошибка при загрузке файла!', errorLidasContent, true, false);
}
break;
case 'addComparizon_form':
var responceComparizon = JSON.parse(jqxhr.responseText);
var responceKey = Object.keys(responceComparizon.error)[0];
popup('bad', 'В базе уже есть данное сопоставление!', 'Артикулы: '+responceComparizon.error[responceKey].originalCode+' и '+responceComparizon.error[responceKey].targetCode, true, false);
break;
case 'addComparizonInFile_form':
popup('bad', 'Внимание!', 'Ошибка при парсинге файла сопоставлений.', true, false);
break;
default:
popup('bad', '', 'Нет связи с сервером!', true, false);
}
return;
},
complete: function() {
preloader();
}
});
}
//---- Формы - Конец
});
// Часы
function digitalClock() {
var tag = 'div.time';
var dots = digits = '';
var digit = tag + ' span';
var span = digit + ':nth-child';
for (i = 1; i < 6; i++)
for (k = 1; k < 6; k++) dots += '';
for (i = 0; i < 8; i++) digits += '';
jQuery(tag).append(digits);
jQuery(digit).append(dots);
jQuery(span + '(3), ' + span + '(6)').removeAttr('class').addClass('colon');
function time() {
var date = new Date();
var hou = date.getHours().toString();
var min = date.getMinutes().toString();
var sec = date.getSeconds().toString();
hou = (hou < 10) ? 0 + hou : hou;
min = (min < 10) ? 0 + min : min;
sec = (sec < 10) ? 0 + sec : sec;
jQuery(digit + '.colon').css({ opacity: 1 }).each(function() {
jQuery(this).delay(400).animate({ opacity: 0 }, 250);
})
jQuery(digit).removeAttr('class');
jQuery(span + '(1)').addClass('d' + hou.slice(0, 1));
jQuery(span + '(2)').addClass('d' + hou.slice(1, 2));
jQuery(span + '(3)').addClass('colon');
jQuery(span + '(4)').addClass('d' + min.slice(0, 1));
jQuery(span + '(5)').addClass('d' + min.slice(1, 2));
jQuery(span + '(6)').addClass('colon');
jQuery(span + '(7)').addClass('d' + sec.slice(0, 1));
jQuery(span + '(8)').addClass('d' + sec.slice(1, 2));
setTimeout(time, 1000);
}
time();
}
// Действия при события загрузки, изменения размера и ориентации страницы
$(window).on('load resize orientationchange', function() {
resize();
});
function resize() {
var allW = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
var allH = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
$('#main-content').height(allH - $('#main-footer').innerHeight());
// Показываем/скрываем левый блок меню и данных в зависимости от ширины экрана
if ($('.l-menu').is(':visible') && allW < 900) {
$('#slideOut').trigger('click');
}
if (!$('.l-menu').is(':visible') && allW > 900 && getCookie("hideMenu") != "true") {
$('#slideIn').trigger('click');
}
}
// Генерация GUID
function newGuid() {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
s4() + '-' + s4() + s4() + s4();
}
// Снимает все checkbox
function uncheckAll() {
var w = document.getElementsByTagName('input');
for (var i = 0; i < w.length; i++) {
if ($(w[i]).attr('data-command') == 'no-clear') continue;
if (w[i].type == 'checkbox') {
w[i].checked = false;
}
}
}
//---- Popup-окна
function popup(type, head, message, fix, background, obj, func, storage, command) {
$('html').css({ 'overflow-y': 'hidden' });
var backPop = (background) ? 'background: transparent' : '';
var backWind = (background) ? 'top: 20% !important; margin: auto; width: 40%;' : '';
var icon = (!background) ? '' : '';
var fixe = (fix) ? 'width: 40%;' : '';
$('body').append('
' + icon + '
');
var thisH = $('.popup .wind .head').last();
var thisC = $('.popup .wind .cont').last();
switch (type) {
case 'good':
thisH.addClass('good').append(head);
thisC.append(message);
break;
case 'bad':
thisH.addClass('bad').append(head);
thisC.append(message);
break;
case 'atten':
thisH.addClass('atten').append(head);
thisC.append(message);
thisC.append('');
break;
case 'form':
if ($('#' + message + '_head')) {
head = $('#' + message + '_head').html();
}
thisH.addClass('form').append(head);
thisC.append($('#' + message));
break;
case 'small-image':
thisH.append(head);
thisH.parent('.wind').css({ 'width': '50%' });
thisC.append(message);
break;
case 'small':
if ($('#' + message + '_head')) {
head = $('#' + message + '_head').html();
}
thisH.addClass('form').append(head);
thisH.parent('.wind').css({ 'width': '40%' });
thisC.append($('#' + message));
break;
case 'big-image':
thisH.append(head);
thisH.parent('.wind').css({ 'width': '80%' });
thisC.append(message);
break;
default:
thisH.append(head);
thisC.append(message);
}
// Проверяем наличие поля, и если оно есть, то даем ему фокус
//$('.popup').last().find('input').first().focus().select();
}
function delayClosePopup(time) {
setTimeout(function() { $('.popup').last().find('.close').trigger('click'); }, time);
}
function delayReload(time, url) {
setTimeout(function() {
if (url) {
window.location.href = url;
} else {
window.location.reload();
}
}, time);
}
// Закрываем окно
$(document).on('click', '.close-popup', function(e) {
$(this).closest('.wind').find('.close').trigger('click');
});
$(document).on('click', '.close', function(e) {
if ($(this).closest('.popup').find('#ordercard_form').data('order-submitting')) {
e.preventDefault();
e.stopImmediatePropagation();
return;
}
var formGuid = $('.popup').find('[name="GUID"]').val();
try {
var form = $(this).attr('style').indexOf('transparent');
} catch (e) {}
var obj = e.target.className;
if ((obj !== 'close' && obj !== 'popup' && obj !== 'close-but') || form > 0) return;
$('html').css({ 'overflow-y': 'unset' });
var t = $(this).closest('.popup').last();
if (t.find('#ordercard_form').length) cancelCartWarehouse();
var closeRedirect = t.attr('data-close-redirect');
if (closeRedirect) {
window.location.href = closeRedirect;
return;
}
t.children('.wind').removeClass('zoomIn').addClass('zoomOut');
t.fadeOut('slow', function() { t.remove(); });
var curClass = $('.popup .wind .head').last().attr('class');
if (typeof curClass != 'undefined' && curClass.indexOf('good') < 0 && curClass.indexOf('bad') < 0 && curClass.indexOf('atten') < 0) {
$('#_wrap').append(t.find('article'));
}
// Подменяем текущий URL на предыдущий (если это не справочник), чтобы при нажатии кнопки Back в браузере не открывалось окно
var uri = window.location;
if (uri.pathname.indexOf('/_') < 0) window.history.replaceState({}, window.location, uri.protocol + '//' + uri.host + '/' + module);
// Если был использован режим отображения одного документа без учета фильтров в справочнике,
// ограничивающий доступ к документам, то запоминаем ?one=true и добавляем у URL
var oneDoc = '';
if (document.referrer.indexOf('one=true') >= 0) oneDoc = '?one=true';
// Если форма открыта для создания документа, то остаемся на этой страницы
if (typeof formGuid == "undefined" || formGuid == '') return;
// Если вызвали документ на редактирование со страницы полной информациии и popup-окно было открыто одно
if (document.referrer.indexOf('/_') >= 0 && $('.popup').length < 2 && $('.popup').find('.form').length > 0) {
console.log(curUrl, document.referrer);
if (document.referrer.indexOf('/_details-templates') >= 0) {
// Если это раздел с несколькими тимплейтами/карточками документов нескольких типов, например рассылки
location.href = '/' + module + '/_details-templates/' + curUrl[3] + '/' + curUrl[4] + oneDoc;
} else {
// Для все остальных
location.href = '/' + module + '/_details/' + curUrl[3] + oneDoc;
}
//window.history.go(-1);
}
});
// Если изображение
$(document).on('click', '.img', function(e) {
e.stopImmediatePropagation();
e.stopPropagation();
if (!$('img').is('#popupImg')) {
var i = new Image();
i.src = $(this).attr('src');
var width = i.width;
var height = i.height;
popup('small-image', '', '');
}
});
$(document).on('click', '.img-big', function(e) {
e.stopImmediatePropagation();
e.stopPropagation();
if (!$('img').is('#popupImg')) {
var i = new Image();
i.src = $(this).attr('src');
var width = i.width;
var height = i.height;
popup('big-image', '', '');
}
});
// Подтверждение действия
function popupConfirmYes(fName, one, two, three, four, five) {
try {
eval(fName)(one, two, three, four, five);
} catch (e) {
console.log('Ошибка при вызове: ' + fName + ' | ' + e.name);
}
}
// Если в окне форма и она вызвана для добавления документа, то обнуляем её поля
$(document).on('click', '.clear', function(e) {
uncheckAll();
$('.editable').html('');
$('.popup').last().find('input, textarea, select').each(function(indx, element) {
// Удаляем аттрибут disabled
if (typeof($(this).attr('disabled')) != 'undefined' && $(this).attr('data-command-d') != 'no-clear-d') $(this).removeAttr('disabled');
// Если поле имеет аттрибут data-command="no-clear", то не удаляем из него значение
if ($(this).attr('data-command') == 'no-clear') return;
$(this).find('.input-imitation').html('');
if ($(this)[0].type != 'radio') $(this).val('');
if ($(this)[0].nodeName == 'TEXTAREA') {
$(this).html('');
$(this).text('');
}
if ($(this)[0].nodeName == 'SELECT') {
if ($(this).attr('data-new') == 'new') $(this).children('option').remove();
$(this)[0].selectedIndex = 0;
$(this).change();
// Условие при добавлении задач
if ($(this).attr('id') == 'tasks_object' && $(this)[0].length > 1) {
$(this).val(2).change();
} else if ($(this).attr('id') == 'tasks_object') {
$(this).val(1).change();
}
}
});
// Если есть список телефонов, то чистим специфические атрибуты
if ($('[data-call]')) $('[data-call]').attr('data-call', '');
});
//---- Popup-окна - Конец
// Пангинация
function page(direction) {
var url = Number($('#page_counter').val());
if (isNaN(Number($('#page_counter').val()))) return;
var uri = window.location;
if (direction == 'left') {
if ((url - 1) < 1) return;
uri.href = uri.protocol + '//' + uri.host + '/' + module + '/page/' + (url - 1);
} else {
if (url > (maxPage - 1)) return;
uri.href = uri.protocol + '//' + uri.host + '/' + module + '/page/' + (url + 1);
}
}
function page_arr(direction) {
var url = Number($('#page_counter').val());
if (isNaN(Number($('#page_counter').val()))) return;
var uri = window.location;
if (direction == 'left') {
if ((url - 1) < 1) return;
uri.href = uri.protocol + '//' + uri.hostname + uri.pathname + '?page=' + (url - 1);
} else {
if (url > (maxPage - 1)) return;
uri.href = uri.protocol + '//' + uri.hostname + uri.pathname + '?page=' + (url + 1);
}
}
// Сохранение списка
function save_select(obj, form) {
if ($('#' + form).validationEngine('validate')) {
var content = '';
var elements = $('#' + form).find('input, select');
var val = [];
for (i = 0; i < elements.length; i++) {
if ((i + 1) % 2 && elements[i].value != '') {
content += '';
var temp = [elements[i].value, elements[i + 1].value];
val.push(temp);
} else {
continue;
}
}
$('#' + obj).html(content);
$('#' + obj).parents('form').find('#' + obj + 'JSON').val(JSON.stringify(val));
delayClosePopup(100);
}
}
// Preloader
function preloader(action, obj) {
if (action === 'show') {
var objToView = (obj) ? obj : 'body';
var objClass = (obj) ? 'preloader preloader-obj' : 'preloader';
$(objToView).append('
Подождите...
');
} else {
var obj = $('.preloader');
obj.fadeOut('fast', function() { obj.remove(); });
}
}
// Preloader - Конец
// Функции для работы с куки
function setCookie(name, value, url, days) {
var path = (typeof(url) != 'undefined') ? url : '/';
var expires = '';
if (typeof days !== 'undefined') {
var d = new Date();
d.setTime(d.getTime() + (days * 24 * 60 * 60 * 1000));
expires = '; expires=' + d.toGMTString();
}
document.cookie = name + '=' + value + '; path=' + path + expires + ';';
}
function getCookie(name) {
var r = document.cookie.match("(^|;) ?" + name + "=([^;]*)(;|$)");
if (r) return r[2];
else return "";
}
function deleteCookie(name) {
var date = new Date(); // Берём текущую дату
date.setTime(date.getTime() - 100); // Возвращаемся в "прошлое"
document.cookie = name + "=; path=/; expires=" + date.toGMTString(); // Устанавливаем cookie пустое значение и срок действия до прошедшего уже времени
}
// Функции для работы с куки - Конец
// Иерархическое дерево с вложениями
var data = [];
$(document).on('click', '#tree li', function(e) {
if (this.className == 'plus') {
$(this).siblings().each(function(index, element) {
if (element.tagName == 'UL') {
$(element).show();
}
});
// Добавляем название объекта по которому был клик
data.push('
' + $(this).text() + '
');
// Рекурсивно перебираем все остальные объекты
eachObj($(this).siblings());
// Добавляем данные в таблицу
$('#tree-data').html(data);
data = [];
}
if (this.className == 'minus') {
$(this).siblings().each(function(index, element) {
$(element).hide();
});
}
$(this).toggleClass('plus').toggleClass('minus');
});
// Перебираем все вложенные объекты
function eachObj(obj) {
obj.each(function(index, element) {
if ($(element).find('*').length > 1) {
eachObj($(element).find('*'));
} else {
if (this.className != 'hold' && !$(element).prev().hasClass('hold')) {
var temp;
//var tempFlag = [];
var tempFlag;
if ($(element).attr('data-art')) {
var e = $(element);
//var pres = e.attr('data-pres').replace('[', '').replace(']', '').split(',');
//for (key in pres) {
// tempFlag[key] = (pres[key] == '1') ? '' : '';
//}
tempFlag = (e.attr('data-pres') == '1') ? 'Да' : 'Нет';
temp = '
' +
'
' + e.attr('data-art') + '
' +
'
' + e.text() + '
' +
'
' + e.attr('data-unit') + '
' +
'
' + tempFlag + '
' +
'
';
} else {
temp = '
' + $(element).text() + '
';
}
data.push(temp);
}
}
});
}
// Иерархическое дерево с вложениями - Конец
// Корзина заказа
$(document).on('dblclick', '[data-form="new_request"] tr', function(e) {
if (!$(this).attr('data-ids')) return;
var guid = $(this).attr('data-ids');
// Показываем всплывающее сообщение для добавления кол-ва
popup('atten', 'Добавить в корзину?', $('li[data-ids="' + guid + '"]').text() + '', true, false, guid, 'add_position');
});
// Добавляем номенклатуру в корзину
function add_position(itemGuid) {
var quant = $('#cur_quant').val();
var items = {};
var crmCurCart = {};
// Если есть запись в хранилище, то извлекаем чтобы можно было туда добавить новую
if (localStorage.getItem('crmCartTemp')) {
var crmCurCart = JSON.parse(localStorage.getItem('crmCartTemp'));
}
// Формируем новую запись
var guid = itemGuid;
var nomen = $('li[data-ids="' + guid + '"]');
items['data-ids'] = guid;
items['data-art'] = nomen.attr('data-art');
items['data-unit'] = nomen.attr('data-unit');
items['data-cur'] = nomen.attr('data-cur');
items['data-price'] = nomen.attr('data-price');
items['data-pres'] = nomen.attr('data-pres');
items['data-quantity'] = (quant > 1) ? quant : 1;
items['data-name'] = nomen.text();
crmCurCart[guid] = items;
localStorage.setItem('crmCartTemp', JSON.stringify(crmCurCart));
viewCartTemp('tree-data-temp');
delayClosePopup(100);
}
// Если корзина не пуста, то выводим её
$(function() {
if (curUrl[1] == 'request') {
viewCartTemp('tree-data-cart');
viewCartTemp('tree-data-temp');
viewFurniture();
}
});
function viewCartTemp(table) {
// Если есть запись в хранилище, то извлекаем все для вывода
var storageObj = (table == 'tree-data-temp') ? 'crmCartTemp' : 'crmCart';
var crmCurCart = {};
if (localStorage.getItem(storageObj)) {
crmCurCart = JSON.parse(localStorage.getItem(storageObj));
} else {
if (storageObj == 'crmCartTemp') {
clearCartTemp();
} else {
clearCart();
}
return;
}
var temp = '';
for (key in crmCurCart) {
var price = (crmCurCart[key]['data-quantity'] > 1) ? crmCurCart[key]['data-price'] * crmCurCart[key]['data-quantity'] : crmCurCart[key]['data-price'];
var prices = (!isNaN(price)) ? Number(price).toFixed(2) : '-';
//var pres = crmCurCart[key]['data-pres'].replace('[', '').replace(']', '').split(',');
var tempFlag;
//for (k in pres) {
// tempFlag[k] = (pres[k] == '1') ? '' : '';
//}
tempFlag = (crmCurCart[key]['data-pres'] == '1') ? 'Да' : 'Нет';
temp += '
' +
'
' + crmCurCart[key]['data-art'] + '
' +
'
' + crmCurCart[key]['data-name'] + '
' +
'
' + crmCurCart[key]['data-unit'] + '
' +
'
' + tempFlag + '
' +
'
' +
'' +
'
' +
'
' +
'
';
}
// Добавляем данные в таблицу
$('#' + table).html(temp);
}
// Очистка временной корзины
function clearCartTemp() {
localStorage.removeItem('crmCartTemp');
$('#tree-data-temp').html('
'
+ (hasAvailable ? 'Будет создано два заказа' : 'Будет создан заказ со статусом «Ожидается поставка»') + '
'
+ (hasAvailable ? 'Доступные товары оформятся сразу, а недостающее количество попадёт в отдельный заказ и в лист ожидания.' : 'Все товары попадут в лист ожидания, чтобы вы получили уведомление о поступлении.')
+ '
Найти его можно: Меню → Номенклатура → Лист ожидания.'
+ '
';
if (typeof clients[key].delivery_addresses != 'undefined' && Object.keys(clients[key].delivery_addresses).length > 0) {
var delAddrStr = '';
for (var k in clients[key].delivery_addresses) {
delAddrStr += '';
}
delAddrObj[clients[key].UID] = delAddrStr;
}
}
$result.html(result).addClass('who').fadeIn();
}).fail(function(jqXHR, status) {
if (status !== 'abort') $result.empty().fadeOut();
}).always(function() {
if (clientSearchRequest === request) clientSearchRequest = null;
});
});
$(document).off('mousedown.orderClientSearch', '.search-result.who span').on('mousedown.orderClientSearch', '.search-result.who span', function(e) {
if ($(this).hasClass('blocked')) return;
e.preventDefault();
var $choice = $(this);
var $result = $choice.parent();
var $input = $result.prev('input');
var clientId = $choice.attr('data-clients');
var orderFormId = $input.attr('id');
$input.val($choice.text()).css({ 'background': 'lightgreen' });
$result.next().val(clientId);
$result.next().next().val($choice.attr('data-cat-price'));
if (orderFormId == 'order-client') {
setCookie('cat_search_price_client_uid', decodeURIComponent(clientId));
} else {
setCookie('cat_search_price_client_uid_list', decodeURIComponent(clientId));
}
if (typeof delAddrObj[clientId] != 'undefined') {
if (orderFormId == 'order-client') {
$('#delivery_places').html('' + delAddrObj[clientId]);
} else {
$('#delivery_places_list').html('' + delAddrObj[clientId]);
}
}
$result.removeClass('who').fadeOut();
$('#order_client_comments').trigger('input');
});
$(document).off('focusout.orderClientSearch', targetInputClient).on('focusout.orderClientSearch', targetInputClient, function() {
var $input = $(this);
if ($input.nextAll('input').val() == '') {
$input.val('').css({ 'background': '#F8F9FB' });
}
$input.next('.search-result').fadeOut();
});
$(document).off('keydown.orderClientSearch', targetInputClient).on('keydown.orderClientSearch', targetInputClient, function(e) {
var keycode = (e.keyCode ? e.keyCode : e.which);
if (keycode === 13) $(this).nextAll('input').trigger('focusout');
});
})();
// --- Промокоды: хелперы ---
function promoGetCodes() {
try {
var v = localStorage['JustCRM-OrderCart-promocode'];
if (!v) return [];
var parsed = JSON.parse(v);
return Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);
} catch(e) { return []; }
}
function promoSetCodes(arr) {
localStorage['JustCRM-OrderCart-promocode'] = JSON.stringify(arr);
$('#order-promocode').val(arr.join(','));
}
function promoGetData() {
try { return JSON.parse(localStorage['JustCRM-OrderCart-promocode-data'] || '{}'); } catch(e) { return {}; }
}
function promoSetData(obj) {
localStorage['JustCRM-OrderCart-promocode-data'] = JSON.stringify(obj);
}
function promoRenderTags() {
var codes = promoGetCodes();
var $tags = $('#promo-codes-tags');
$tags.empty();
codes.forEach(function(code) {
$tags.append(
$('').text(code)
.append($('').html('×').attr('data-code', code))
);
});
$('#order-promocode').val(codes.join(','));
}
function applyPromoInput() {
var val = $.trim($('#order-promocode-input').val()).toUpperCase();
if (val.length < 3) return;
var existingCodes = promoGetCodes();
if (existingCodes.indexOf(val) !== -1) {
popup('bad', 'Промокод уже применён', 'Этот промокод уже добавлен в заказ.', true, false);
return;
}
dataResult = {};
send_request(val, 'data-exchange', 'data-promocode-search');
var waitTicks = 0;
var waitResult = setInterval(function() {
waitTicks++;
if (waitTicks > 50) {
clearInterval(waitResult);
popup('bad', 'Промокод не найден', 'Промокод '+val+' не найден или недействителен.', true, false);
return;
}
if (!$.isEmptyObject(dataResult) && typeof dataResult.code !== 'undefined') {
if (dataResult.code.toUpperCase() !== val) {
clearInterval(waitResult);
popup('bad', 'Промокод не найден', 'Промокод '+val+' не найден или недействителен.', true, false);
return;
}
clearInterval(waitResult);
var positions = JSON.parse(dataResult.positions);
// Merge positions (последний введённый перекрывает предыдущий)
var existingData = promoGetData();
$.extend(existingData, positions);
promoSetData(existingData);
// Добавляем код в список
var codes = promoGetCodes();
codes.push(val);
promoSetCodes(codes);
promoRenderTags();
// Обновляем цены в localStorage корзины, сохраняя исходную цену
var cartAll = JSON.parse(localStorage['JustCRM-OrderCart'] || '{}');
// promoOrig — базовая цена БЕЗ клиентской скидки (для отображения зачёркнутой старой цены)
var promoOrig = {};
try { promoOrig = JSON.parse(localStorage['JustCRM-OrderCart-promoOrig'] || '{}'); } catch(e) {}
// promoRestore — цена ДО промо (со скидкой клиента, если была) для восстановления при удалении кода
var promoRestore = {};
try { promoRestore = JSON.parse(localStorage['JustCRM-OrderCart-promoRestore'] || '{}'); } catch(e) {}
for (var k in positions) {
if (typeof cartAll[k] !== 'undefined') {
if (typeof promoOrig[k] === 'undefined') {
// Берём original-price [15] (до клиентской скидки); если нет — берём текущую [10]
var _basePrice = (typeof cartAll[k][15] !== 'undefined' && cartAll[k][15]['value'] !== '')
? cartAll[k][15]['value']
: cartAll[k][10]['value'];
promoOrig[k] = _basePrice; // для отображения "старой" цены
promoRestore[k] = cartAll[k][10]['value']; // для восстановления при удалении промо
}
cartAll[k][10]['value'] = positions[k];
}
}
localStorage['JustCRM-OrderCart-promoOrig'] = JSON.stringify(promoOrig);
localStorage['JustCRM-OrderCart-promoRestore'] = JSON.stringify(promoRestore);
localStorage['JustCRM-OrderCart'] = JSON.stringify(cartAll);
// Показываем popup с изменёнными ценами
var priceList = '';
for (var k in positions) {
var oldPrice = $('#ordercard-list').find('[data-id-pos="'+k+'"]').children('.base-price').html();
if (typeof oldPrice === 'undefined') continue;
var posName = $('#ordercard-list').find('[data-id-pos="'+k+'"]').children('.name').html();
priceList += '
'+posName+'
'+oldPrice+' > '+positions[k]+' руб.
';
}
if (priceList) {
popup('good', 'Промокод применён!',
'
Применён промокод: '+val+'
'+priceList+'
',
false, false);
}
$('#order-promocode-input').val('');
dataResult = {};
orderStat();
}
}, 100);
}
// Применяем промокод
$('body').on('click', '.reload-basket', function() {
$('.popup').find('.close').trigger('click');
setTimeout(function() {
$('#marker-cart').trigger('click');
}, 500);
})
function editOrder(orderId, isCopy = false) {
send_request(orderId, 'data-exchange', 'data-edit-order');
var waitOrder = setInterval(function() {
if (typeof dataResultThree != 'undefined' && !$.isEmptyObject(dataResultThree)) {
clearInterval(waitOrder);
// Если это копирование заказа, то удаляем 12 элемент массива, где содержится GUID заказа
if (isCopy === true) delete dataResultThree.data[12];
// Записываем все данные по основным полям
localStorage['JustCRM-OrderCart-field'] = JSON.stringify(dataResultThree.data);
localStorage['JustCRM-OrderCart'] = JSON.stringify(dataResultThree.table);
localStorage['JustCRM-OrderCart-Sort'] = JSON.stringify(dataResultThree.sort);
localStorage['JustCRM-OrderCart-Shipment'] = JSON.stringify(dataResultThree.shipment);
// Если есть промокод(ы)
var editCodes = dataResultThree.promo_code ? dataResultThree.promo_code.split(',').filter(Boolean) : [];
promoSetCodes(editCodes);
promoSetData(dataResultThree.promo_code_data || {});
// Устанавливаем куки клиента
setCookie('cat_search_price_client_uid', decodeURIComponent(dataResultThree.data[1]));
setCookie('cat_search_price_uid', decodeURIComponent(dataResultThree.data[2]));
// Вы водим полный список адресов доставки по клиенту
var deliveryAddressStr = '';
if (Object.keys(dataResultThree.delivery_address).length > 0) {
for (key in dataResultThree.delivery_address) {
var selectedAddr = '';
if (dataResultThree.data[3][0] == dataResultThree.delivery_address[key]['UID']) selectedAddr = 'selected="selected"';
deliveryAddressStr += ''
}
}
$('#delivery_places').html(deliveryAddressStr);
// Выбираем склад
$('#order-warehouse option[value="' + dataResultThree.data[8] + '"]').prop('selected', true);
// Выбираем время доставки
$('#order-delivery-time option[value="' + dataResultThree.data[12] + '"]').prop('selected', true);
// Выбираем тип оплаты
$('#order-pay option[value="' + dataResultThree.data[13] + '"]').prop('selected', true);
dataResultThree = '{}';
//orderStat(); // Последние изменения
orderMarkerView();
setTimeout(function() {
$('#marker-cart').trigger('click');
}, 1000);
}
}, 500);
}
// function editOrderList(orderId) {
// sessionStorage['JustCRM-EditOrderList'] = orderId;
// location.href = '/nomendraw';
// }
// function editOrderListView(orderId) {
// sessionStorage.removeItem('JustCRM-EditOrderList');
// send_request(orderId, 'data-exchange', 'data-edit-order-list');
// var waitOrder = setInterval(function() {
// if (typeof dataResultThree != 'undefined' && !$.isEmptyObject(dataResultThree)) {
// clearInterval(waitOrder);
// // Записываем все данные по основным полям
// localStorage['JustCRM-OrderCartList-field'] = JSON.stringify(dataResultThree.data);
// localStorage['JustCRM-OrderCartList'] = JSON.stringify(dataResultThree.table);
// // Устанавливаем куки клиента
// setCookie('cat_search_price_client_uid_list', decodeURIComponent(dataResultThree.data[1]));
// // Вы водим полный список адресов доставки по клиенту
// var deliveryAddressStr = '';
// if (Object.keys(dataResultThree.delivery_address).length > 0) {
// for (key in dataResultThree.delivery_address) {
// var selectedAddr = '';
// if (dataResultThree.data[3][0] == dataResultThree.delivery_address[key]['UID']) selectedAddr = 'selected="selected"';
// deliveryAddressStr += ''
// }
// }
// $('#delivery_places_list').html(deliveryAddressStr);
// // Выбираем время доставки
// $('#order-delivery-time-list option[value="' + dataResultThree.data[12] + '"]').prop('selected', true);
// // Выбираем тип оплаты
// $('#order-pay-list option[value="' + dataResultThree.data[13] + '"]').prop('selected', true);
// dataResultThree = '{}';
// orderStatList(); // Последние изменения
// orderMarkerView();
// setTimeout(function() {
// $('#marker-cart-list').trigger('click');
// }, 1000);
// }
// }, 500);
// }
function editOrderList(orderId) {
sessionStorage['JustCRM-EditOrderList'] = orderId;
send_request(orderId, 'data-exchange', 'data-edit-order-list');
var waitOrder = setInterval(function() {
if (typeof dataResultThree != 'undefined' && !$.isEmptyObject(dataResultThree)) {
clearInterval(waitOrder);
// Записываем все данные по основным полям
localStorage['JustCRM-OrderCartList-field'] = JSON.stringify(dataResultThree.data);
localStorage['JustCRM-OrderCartList'] = JSON.stringify(dataResultThree.table);
// Устанавливаем куки клиента
setCookie('cat_search_price_client_uid_list', decodeURIComponent(dataResultThree.data[1]));
setCookie('cat_search_price_uid_list', decodeURIComponent(dataResultThree.data[2]));
dataResultThree = '{}';
setTimeout(function() {
location.href = '/nomendraw';
}, 1000);
}
}, 500);
}
function editOrderListView(orderId) {
sessionStorage.removeItem('JustCRM-EditOrderList');
orderStatList(); // Последние изменения
orderMarkerView();
setTimeout(function() {
$('#marker-cart-list').trigger('click');
}, 1000);
}
// Предпоказ стоимости доставки в корзине: строка «Доставка» в таблице товаров + учёт в подитоге.
// Дебаунс + кэш ответа, чтобы не дёргать сервер без изменений
var deliveryPreviewTimer = null;
var deliveryPreviewLast = '';
var deliveryPreviewData = null;
// Пересчёт подитога корзины (та же логика, что в orderStat) с добавлением строки доставки
function deliveryTotalsRender() {
var allQuant = 0;
var allSumm = 0;
var allSummOrig = 0;
$('body').find('#ordercard-list').find('.ordercard-quantity').each(function(index, element) {
var qty = Number($(element)[0].value);
allQuant += qty;
allSumm += Number($(element).parent().next().children('input').val().replace(',', '.'));
var origPriceStr = $(element).closest('.position').find('.price').attr('data-orig-price') || '';
var origPrice = parseFloat(origPriceStr.replace(',', '.'));
if (!isNaN(origPrice) && origPrice > 0) {
allSummOrig += origPrice * qty;
}
});
var deliveryPrice = 0;
if (deliveryPreviewData && deliveryPreviewData.status == 'ok' && Number(deliveryPreviewData.price) > 0) {
// Стоимость доставки округляется вверх до целых рублей (как и на бэке в dz_clamp_min_price)
deliveryPrice = Math.ceil(Number(deliveryPreviewData.price));
allQuant += 1; // доставка — одна позиция, как и в заказе после сохранения
} else if (deliveryPreviewData && deliveryPreviewData.status == 'no_zone' && Number(deliveryPreviewData.tk_price) > 0) {
// Адрес вне зон — доставка до транспортной компании (тариф от суммы товаров, бэк: dz_tk_price)
deliveryPrice = Math.ceil(Number(deliveryPreviewData.tk_price));
allQuant += 1;
}
$('.all-quant').children('strong').html(allQuant.toFixed(2));
var summHtml = (allSumm + deliveryPrice).toFixed(2).replace('.', ',');
if (allSummOrig > 0 && allSummOrig > allSumm + 0.01) {
summHtml += ' ' + (allSummOrig + deliveryPrice).toFixed(2).replace('.', ',') + '';
}
$('.all-summ').children('strong').html(summHtml);
}
// Текст подсказки «как считается доставка» у строки «Доставка» в корзине
var deliveryHelpTooltip = 'Стоимость доставки рассчитывается автоматически: адрес определяется на карте и попадает в одну из зон доставки. У каждой зоны свой тариф — фиксированная сумма или процент от суммы товаров в заказе, но не меньше минимальной стоимости доставки — 800 руб. Если адрес не попал ни в одну зону, доставка выполняется до терминала выбранной транспортной компании: при сумме заказа до 50 000 руб. — 3% от суммы, но не менее 800 руб.; свыше 50 000 руб. — фиксированно 1 500 руб.';
// Показ селекта транспортной компании (только для адресов вне всех зон доставки)
function deliveryTkToggle(show) {
var wrap = $('#order-delivery-tk-wrap');
if (!wrap.length) return;
if (show) {
wrap.show();
$('#order-delivery-tk').attr('class', 'validate[required]');
} else {
wrap.hide();
$('#order-delivery-tk').attr('class', 'validate[optional]');
}
}
// Отрисовка строки «Доставка» в таблице товаров корзины по кэшу deliveryPreviewData
function deliveryRowRender() {
var box = $('#delivery-price-preview');
$('#ordercard-list').children('.delivery-position').remove();
var d = deliveryPreviewData;
if (!d) {
deliveryTkToggle(false);
box.hide().empty();
deliveryTotalsRender();
return;
}
if (d.status == 'ok' && Number(d.price) > 0) {
deliveryTkToggle(false);
// Округление вверх до целых рублей — дублирует бэковое dz_clamp_min_price
var priceStr = Math.ceil(Number(d.price)).toFixed(2).replace('.', ',').replace(/\B(?=(\d{3})+(?!\d))/g, ' ');
// Строка в формате товарной позиции, но без input-полей — при сохранении её добавит сервер
var row = $('
' +
'
' +
'
' +
'
Доставка
' +
'
' + priceStr + '
' +
'
услуга
' +
'
' +
'
' +
'
' +
'
' +
'
1
' +
'
' + priceStr + '
' +
'
');
// Производственные колонки — в том же состоянии, что и у шапки таблицы.
// Явный css(): по умолчанию .prod-field скрыт стилями, и при включённой
// галочке производства ячейкам нужен инлайновый table-cell, иначе строка съезжает
row.find('.prod-field').css('display', ($('#ordercard_form th.prod-field').first().css('display') != 'none') ? 'table-cell' : 'none');
$('#ordercard-list').append(row);
box.hide().empty();
} else if (d.status == 'pickup') {
deliveryTkToggle(false);
box.hide().empty();
} else if (d.status == 'no_zone' && Number(d.tk_price) > 0) {
// Адрес вне всех зон — доставка до транспортной компании: тариф от суммы товаров
// (бэк: dz_tk_price), показываем селект выбора ТК рядом с датой доставки
deliveryTkToggle(true);
var tkPriceStr = Math.ceil(Number(d.tk_price)).toFixed(2).replace('.', ',').replace(/\B(?=(\d{3})+(?!\d))/g, ' ');
var tkRow = $('
' +
'
' +
'
' +
'
Доставка до транспортной компании
' +
'
' + tkPriceStr + '
' +
'
услуга
' +
'
' +
'
' +
'
' +
'
' +
'
1
' +
'
' + tkPriceStr + '
' +
'
');
tkRow.find('.prod-field').css('display', ($('#ordercard_form th.prod-field').first().css('display') != 'none') ? 'table-cell' : 'none');
$('#ordercard-list').append(tkRow);
box.hide().empty();
} else {
// no_coords / geo_error — адрес не распознан: строка «Доставка» без цены,
// стоимость посчитает менеджер при обработке заказа
deliveryTkToggle(false);
var infoRow = $('
' +
'
' +
'
' +
'
Доставка дополнительно будет рассчитана менеджером
' +
'
' +
'
услуга
' +
'
' +
'
' +
'
' +
'
' +
'
' +
'
' +
'
');
infoRow.find('.prod-field').css('display', ($('#ordercard_form th.prod-field').first().css('display') != 'none') ? 'table-cell' : 'none');
$('#ordercard-list').append(infoRow);
box.hide().empty();
}
deliveryTotalsRender();
}
function deliveryPricePreview(delay) {
if ($('#delivery-price-preview').length === 0) return;
clearTimeout(deliveryPreviewTimer);
deliveryPreviewTimer = setTimeout(function() {
var places = $('#delivery_places').val() || '%';
var address = $.trim($('#order-delivery-address').val());
var coords = $.trim($('#order-delivery-coords').val());
// Сумма товаров корзины — база для процентных зон (строка доставки не участвует: в ней нет input-полей)
var summ = 0;
$('#ordercard-list').children('.position').each(function() {
var v = Number(String($(this).find('.ordercard-price').val()).replace(',', '.').replace(/\s/g, ''));
if (!isNaN(v)) summ += v;
});
// Самовывоз или адрес ещё не указан
if ((places == '%' || places == '%%') && address == '' && coords == '') {
deliveryPreviewLast = '';
deliveryPreviewData = null;
deliveryRowRender();
return;
}
var signature = [places, address, coords, summ.toFixed(2)].join('|');
if (signature === deliveryPreviewLast) {
// Данные не менялись — только перерисовываем (корзина могла быть перестроена)
deliveryRowRender();
return;
}
deliveryPreviewLast = signature;
$.post('/ajax-send/data-delivery-price.php?guid=' + guid, { places: places, address: address, coords: coords, summ: summ.toFixed(2) }, function(data) {
deliveryPreviewData = (data && data.ok === true) ? data : null;
deliveryRowRender();
}, 'json').fail(function() {
deliveryPreviewLast = '';
deliveryPreviewData = null;
deliveryRowRender();
});
}, (typeof delay != 'undefined') ? delay : 600);
}
// === Шаблоны заказов (crm_cart_templates) ===
// Открываются пунктом меню «Номенклатура → Шаблоны заказов» (/nomen?cart_templates=true):
// сохранение текущей корзины под именем и применение сохранённого шаблона.
// Применение ЗАМЕНЯЕТ корзину; цены в шаблоне не хранятся —
// подтягиваются актуальные через data-cart-recalc.php (см. data-cart-templates.php)
function cartTplEsc(s) {
return String(s == null ? '' : s).replace(/[&<>"']/g, function(c) {
return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c];
});
}
function cartTplRenderList(templates) {
var box = $('#cart-templates-list');
if (!box.length) return;
if (!templates || !templates.length) {
box.html('
Сохранённых шаблонов пока нет.
');
return;
}
var html = '';
for (var i = 0; i < templates.length; i++) {
var t = templates[i];
html += '
', true, false);
$('.popup').last().find('.wind').css('width', '65%');
}, 'json').fail(function() {
popup('bad', 'Ошибка!', 'Не удалось открыть шаблон.', true, false);
});
});
// Пересчёт «шт × длина = кол-во» у производственных позиций
$('body').on('input', '#cart-tpl-edit-body .ct-pqty, #cart-tpl-edit-body .ct-plen', function() {
var $tr = $(this).closest('tr');
var q = Number(String($tr.find('.ct-pqty').val()).replace(',', '.')) || 0;
var l = Number(String($tr.find('.ct-plen').val()).replace(',', '.')) || 0;
$tr.find('.ct-q-calc').text(String(+(q * l).toFixed(2)));
});
// Удаление позиции из шаблона (до нажатия «Сохранить» — только в окне)
$('body').on('click', '.cart-tpl-row-del', function() {
$(this).closest('tr').remove();
});
$('body').on('click', '#cart-tpl-edit-save', function() {
var $editor = $('#cart-tpl-editor');
var tplGuid = $editor.attr('data-tpl-guid');
var name = $.trim($('#cart-tpl-edit-name').val());
if (name === '') {
popup('bad', 'Ошибка!', 'Укажите название шаблона.', true, false);
return;
}
var positions = [];
$('#cart-tpl-edit-body').children('tr').each(function() {
var $tr = $(this);
var id = Number($tr.attr('data-id'));
if (!id) return;
var prod = $tr.attr('data-prod') == '2' ? '2' : '1';
var quantity, qty = '1', length = '1', numOrder = $tr.attr('data-num') || '';
if (prod == '2') {
qty = String(Number(String($tr.find('.ct-pqty').val()).replace(',', '.')) || 1);
length = String(Number(String($tr.find('.ct-plen').val()).replace(',', '.')) || 1);
quantity = String(+(Number(qty) * Number(length)).toFixed(2));
numOrder = $tr.find('.ct-pnum').val() || '';
} else {
quantity = String(Number(String($tr.find('.ct-q').val()).replace(',', '.')) || 1);
}
positions.push({ id: id, quantity: quantity, prod: prod, qty: qty, length: length, num_order: numOrder });
});
if (!positions.length) {
popup('bad', 'Ошибка!', 'В шаблоне не осталось позиций — если он не нужен, удалите его целиком.', true, false);
return;
}
$.post('/ajax-send/data-cart-templates.php?guid=' + guid, { action: 'update', template_guid: tplGuid, name: name, positions: JSON.stringify(positions) }, function(resp) {
if (!resp || !resp.ok) {
popup('bad', 'Ошибка!', (resp && resp.error) ? resp.error : 'Не удалось сохранить изменения.', true, false);
return;
}
cartTplRenderList(resp.templates);
$('#cart-tpl-editor').closest('.popup').find('.close').trigger('click');
popup('good', 'Готово!', 'Шаблон «' + cartTplEsc(name) + '» сохранён.', true, false);
}, 'json').fail(function() {
popup('bad', 'Ошибка!', 'Не удалось сохранить изменения.', true, false);
});
});
// После применения шаблона страница перезагружается — открываем корзину автоматически
$(function() {
try {
if (sessionStorage.getItem('JustCRM-open-cart') === '1') {
sessionStorage.removeItem('JustCRM-open-cart');
setTimeout(function() { $('#marker-cart').trigger('click'); }, 800);
}
} catch (e) {}
});
var _warehouseRemainsCache = [];
var _warehouseRemainsPending = [];
var _warehouseRemainsSequence = 0;
function loadWarehouseRemains(warehouse, nomenIds, options) {
options = options || {};
var ids = [];
$.each(nomenIds, function(_, value) {
var id = Number(value);
if (id > 0 && id % 1 === 0 && ids.indexOf(id) === -1) ids.push(id);
});
function covers(record) {
return record.warehouse === warehouse && record.guid === guid && ids.every(function(id) { return record.ids.indexOf(id) !== -1; });
}
var now = Date.now();
_warehouseRemainsCache = _warehouseRemainsCache.filter(function(record) { return now - record.time < 30000; });
var record = null;
if (!options.force) {
$.each(_warehouseRemainsPending, function(_, pending) {
if (covers(pending) && (!record || pending.sequence > record.sequence)) record = pending;
});
for (var index = _warehouseRemainsCache.length - 1; index >= 0; index--) {
if (covers(_warehouseRemainsCache[index]) && (!record || _warehouseRemainsCache[index].sequence > record.sequence)) {
var cached = $.Deferred().resolve(_warehouseRemainsCache[index].result).promise();
cached.abort = function() {};
return cached;
}
}
}
if (!record) {
record = { warehouse: warehouse, guid: guid, ids: ids, users: 0, sequence: ++_warehouseRemainsSequence, request: requestWarehouseRemains(warehouse, ids) };
_warehouseRemainsPending.push(record);
record.request.done(function(result) {
function overlaps(cached) {
return cached.warehouse === warehouse && cached.guid === record.guid && ids.some(function(id) { return cached.ids.indexOf(id) !== -1; });
}
if (_warehouseRemainsCache.some(function(cached) { return overlaps(cached) && cached.sequence > record.sequence; })) return;
_warehouseRemainsCache = _warehouseRemainsCache.filter(function(cached) { return !overlaps(cached); });
_warehouseRemainsCache.push({ warehouse: warehouse, guid: record.guid, ids: ids, result: result, time: Date.now(), sequence: record.sequence });
_warehouseRemainsCache = _warehouseRemainsCache.slice(-16);
}).always(function() {
_warehouseRemainsPending = _warehouseRemainsPending.filter(function(pending) { return pending !== record; });
});
}
var result = $.Deferred();
var active = true;
record.users++;
var promise = result.promise();
promise.abort = function() {
if (!active) return;
active = false;
record.users--;
result.reject('abort');
if (!record.users && record.request.state() === 'pending') record.request.abort();
};
record.request.done(function(response) {
if (active) result.resolve(response);
}).fail(function(message) {
if (active) result.reject(message);
});
result.always(function() {
if (active) {
active = false;
record.users--;
}
});
return promise;
}
function requestWarehouseRemains(warehouse, nomenIds) {
var result = $.Deferred();
var request = null;
var cancelled = false;
var retryTimer = null;
var retryDelays = [2000, 5000];
var attempt = 0;
var requestGuid = guid;
var ids = [];
$.each(nomenIds, function(_, id) {
id = Number(id);
if (id > 0 && id % 1 === 0 && ids.indexOf(id) === -1) ids.push(id);
});
var promise = result.promise();
promise.abort = function() {
if (cancelled || result.state() !== 'pending') return;
cancelled = true;
clearTimeout(retryTimer);
retryTimer = null;
if (request) request.abort();
result.reject('abort');
};
if (!warehouse || warehouse === 'all' || !ids.length) {
result.resolve({ remains: {}, source: 'crm', message: '' });
return promise;
}
function validQuantity(entry) {
return entry && (typeof entry.quantity === 'number' || typeof entry.quantity === 'string') &&
String(entry.quantity).trim() !== '' && isFinite(Number(entry.quantity));
}
function failedResponse(response) {
return response && ((response.error && response.error !== 'false' && response.error !== '0') ||
response.success === false || response.success === 'false' || response.success === 0 || response.success === '0' ||
response.code === 'unauthorized' || response.code === 'invalid_request');
}
function fetchRemains(endpoint, timeout) {
return $.ajax({
url: '/ajax-send/' + endpoint + '.php?guid=' + encodeURIComponent(requestGuid),
type: 'POST',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
data: JSON.stringify({ warehouse: warehouse, nomen: ids }),
timeout: timeout
});
}
function fallback(live, received) {
if (cancelled) return;
request = fetchRemains('send_request_remains', 10000);
request.done(function(cached) {
if (cancelled) return;
if (failedResponse(cached)) {
result.reject('Не удалось проверить наличие товаров. Попробуйте позже.');
return;
}
var map = {};
var liveCount = 0;
var complete = true;
$.each(ids, function(_, id) {
if (validQuantity(live[id])) {
map[id] = live[id];
liveCount++;
} else if (cached && validQuantity(cached[id])) {
map[id] = cached[id];
} else {
complete = false;
}
});
if (!complete) {
result.reject('Не удалось проверить наличие товаров. Попробуйте позже.');
return;
}
result.resolve({
remains: map,
source: liveCount ? 'mixed' : 'crm',
message: received ? '1С вернула неполные остатки. Для недостающих товаров показаны сохранённые данные выбранного склада.' :
'1С недоступна. Показаны сохранённые остатки выбранного склада; уточните наличие у менеджера.'
});
}).fail(function(_, status) {
if (!cancelled) result.reject(status === 'abort' ? 'abort' : 'Не удалось проверить наличие товаров. Попробуйте позже.');
});
}
function retry(live, received) {
if (cancelled) return;
if (attempt > retryDelays.length) {
fallback(live, received);
return;
}
retryTimer = setTimeout(fetchLive, retryDelays[attempt - 1]);
}
function fetchLive() {
retryTimer = null;
if (cancelled) return;
attempt++;
request = fetchRemains('send_request_remains_1C', 28000);
request.done(function(live) {
if (cancelled) return;
if (live && (live.code === 'unauthorized' || live.code === 'invalid_request')) {
result.reject('Не удалось выполнить запрос остатков. Обновите страницу.');
return;
}
var failed = failedResponse(live);
var map = {};
var complete = !failed;
$.each(ids, function(_, id) {
if (!failed && live && validQuantity(live[id])) map[id] = live[id];
else complete = false;
});
if (complete) result.resolve({ remains: map, source: '1c', message: 'Остатки обновлены из 1С.' });
else retry(map, Boolean(live && !failed));
}).fail(function(xhr, status) {
if (cancelled) return;
if (status === 'abort') result.reject('abort');
else if (xhr.status === 400 || xhr.status === 401 || xhr.status === 403) result.reject('Не удалось выполнить запрос остатков. Обновите страницу.');
else retry({}, false);
});
}
fetchLive();
return promise;
}
var _cartWarehouseRequest = null;
var _cartWarehouseSequence = 0;
function cancelCartWarehouse() {
_cartWarehouseSequence++;
var request = _cartWarehouseRequest;
_cartWarehouseRequest = null;
if (request) request.abort();
}
function cartWarehouseFields() {
var fields;
try { fields = JSON.parse(localStorage['JustCRM-OrderCart-field'] || '[]'); } catch (e) { fields = []; }
if (!Array.isArray(fields)) fields = [];
if (!fields.length) {
fields = [$('#order-client').val() || '', $('#id_client').val() || '', $('#client_cat_price').val() || '',
[$('#delivery_places').val() || '%', $('#delivery_places option:selected').text() || ''],
$('#order_client_comments').val() || '', $('#order-delivery-address').val() || '',
$('#order-delivery-coords').val() || '', $('#order_status').val() || '', $('#order-warehouse').val() || '',
$('#order-delivery-date').val() || '', $('#order-delivery-time').val() || '', $('#order-pay').val() || '',
$('#ordercard-edit-flag').val() || '', $('#order_prod').prop('checked') ? 1 : 0, $('#order-delivery-tk').val() || ''];
}
return fields;
}
function cartWarehouseStatus(message, state) {
var $select = $('#order-warehouse');
var $form = $('#ordercard_form');
var clientCart = $form.data('client-cart') === true;
var $status = $('#order-warehouse-status');
if (!$status.length && $select.length && !clientCart) {
$status = $('
', { id: 'order-warehouse-status', role: 'status', 'aria-live': 'polite' });
$status.append($(''));
$select.closest('form').find('.add-order').first().before($status);
}
$status.attr('data-state', state).toggleClass('red', state === 'error');
$status.children('span').text(message);
$status.toggle(!clientCart && Boolean(message));
$('#ordercard-list').attr('aria-busy', state === 'loading' ? 'true' : 'false');
$('#ordercard_form .add-order').prop('disabled', Boolean($('#ordercard_form').data('order-submitting')) || state === 'loading' || state === 'error');
}
function cartWarehouseApply(remains, loading) {
var cart;
try { cart = JSON.parse(localStorage['JustCRM-OrderCart'] || '{}'); } catch (e) { cart = {}; }
$.each(cart, function(key, row) {
if (!row || !row[1] || !row[6]) return;
var entry = remains[String(row[1].value)];
var quantity = entry && entry.quantity !== null ? Number(entry.quantity) : null;
row[6].value = quantity;
});
localStorage['JustCRM-OrderCart'] = JSON.stringify(cart);
$('#ordercard-list').children('.position').each(function() {
var $row = $(this);
var entry = remains[String($row.attr('data-id-pos'))];
var quantity = entry && entry.quantity !== null ? Number(entry.quantity) : null;
$row.children('.remains').text(quantity === null ? (loading ? '…' : '—') : quantity)
.attr('data-warehouse-unknown', quantity === null ? '1' : '0');
$row.css('background-color', quantity === 0 ? 'tomato' : 'unset');
});
}
function refreshCartWarehouse(warehouse, options) {
options = options || {};
warehouse = warehouse || '';
var sequence = ++_cartWarehouseSequence;
var previousRequest = _cartWarehouseRequest;
_cartWarehouseRequest = null;
var fields = cartWarehouseFields();
fields[8] = warehouse;
localStorage['JustCRM-OrderCart-field'] = JSON.stringify(fields);
$('#order-warehouse').val(warehouse);
if (!warehouse) {
if (previousRequest) previousRequest.abort();
cartWarehouseApply({}, false);
cartWarehouseStatus('Выберите склад, чтобы обновить остатки.', 'idle');
return;
}
var cart;
try { cart = JSON.parse(localStorage['JustCRM-OrderCart'] || '{}'); } catch (e) { cart = {}; }
var ids = [];
$.each(cart, function(_, row) {
if (row && row[1] && ids.indexOf(Number(row[1].value)) === -1) ids.push(Number(row[1].value));
});
if (!ids.length) {
if (previousRequest) previousRequest.abort();
cartWarehouseStatus('', 'idle');
return;
}
cartWarehouseApply({}, true);
cartWarehouseStatus('Обновляем остатки выбранного склада…', 'loading');
var pending = loadWarehouseRemains(warehouse, ids, options);
if (previousRequest) previousRequest.abort();
_cartWarehouseRequest = pending;
pending.done(function(result) {
if (sequence !== _cartWarehouseSequence) return;
var currentCart;
try { currentCart = JSON.parse(localStorage['JustCRM-OrderCart'] || '{}'); } catch (e) { currentCart = {}; }
var added = false;
$.each(currentCart, function(_, row) {
if (row && row[1] && ids.indexOf(Number(row[1].value)) === -1) added = true;
});
if (added) {
refreshCartWarehouse(warehouse, options);
return;
}
cartWarehouseApply(result.remains, false);
cartWarehouseStatus(result.message, result.source);
}).fail(function(message) {
if (sequence !== _cartWarehouseSequence || message === 'abort') return;
cartWarehouseApply({}, false);
cartWarehouseStatus(message, 'error');
if (!options.silent && $('#ordercard_form').data('client-cart') !== true && $('#ordercard_form').is(':visible')) popup('bad', 'Внимание!', message, true, false);
}).always(function() {
if (sequence === _cartWarehouseSequence) _cartWarehouseRequest = null;
});
return pending;
}
function orderStat(quantityField, flag) {
console.log('Обновление корзины:', quantityField, flag)
// Отображаем применённые промокоды
promoRenderTags();
// Все позиции корзины
if (typeof localStorage['JustCRM-OrderCart'] == 'undefined') localStorage['JustCRM-OrderCart'] = '{}';
if (typeof localStorage['JustCRM-OrderCart-field'] == 'undefined') localStorage['JustCRM-OrderCart-field'] = '[]';
var orderCartAll = JSON.parse(localStorage['JustCRM-OrderCart']);
var orderCartAllField = JSON.parse(localStorage['JustCRM-OrderCart-field']);
var orderCartAllShipment = JSON.parse(localStorage['JustCRM-OrderCart-Shipment']);
updateOrderCardAction();
if (typeof quantityField != 'undefined') {
// Изменение кол-ва товара c пересчетом
if (quantityField.hasClass('ordercard-quantity')) {
// Проверки только если установлен нужый флаг
if (typeof flag != 'undefined' && flag == 'minShipment') {
// Проверяем мин. отгрузочную норму
var minShipment = quantityField.parents('tr').find('.ordercard-min-shipment').val();
if (Number(quantityField.val()) < Number(minShipment)) {
popup('bad', 'Ошибка!', 'Кол-во не может быть менее отгрузочной нормы! Минимум: ' + minShipment + ' ед.', true, false);
quantityField.attr('value', minShipment);
quantityField.val(minShipment);
}
// Округляем к большему исходя из кратности — с подтверждением
var currentVal = parseNomenQuantityValue(quantityField.val());
var roundedVal = roundMultiple(currentVal, minShipment);
if (roundedVal !== currentVal) {
var prevVal = quantityField.data('prev-val') || currentVal;
window.nomenRoundConfirm = { $input: quantityField, originalVal: currentVal, roundedVal: roundedVal, minShip: parseNomenQuantityValue(minShipment), prevVal: prevVal };
popup('atten', 'Округление количества', 'Значение ' + formatNomenQuantityValue(currentVal) + ' будет округлено до ' + formatNomenQuantityValue(roundedVal) + ' ед. (кратность/партия: ' + formatNomenQuantityValue(minShipment) + ' ед.). Применить?', false, false, '', 'nomenRoundConfirmAcceptCart', '', '');
$('.popup').last().find('.wind').css('width', '25%');
// «Нет» или закрытие крестиком — вернуть предыдущее кратное значение
$('.popup').last().find('.close-popup').one('click', function() {
nomenRoundConfirmRejectCart();
});
$(document).one('click.nomenRoundCart', '.close', function() {
nomenRoundConfirmRejectCart();
});
return;
}
orderCartAll[quantityField.parents('.position').data('id-pos-prefix')][0].value = quantityField.val();
}
// Пересчитываем цену в связи с изменениями кол-ва
var summPos = Number(quantityField.parent().next('[data-price]').attr('data-price').replace(',', '.').replace(' ', '')) * Number(quantityField.val());
quantityField.parent().next('.price').children('input').val(summPos.toFixed(2).replace('.', ',').replace(' ', ''));
}
// Изменение кол-ва и длины для нарезки в производство
if (quantityField.hasClass('ordercard-qty')) {
orderCartAll[quantityField.parents('.position').data('id-pos-prefix')][12].value = quantityField.val().replace(',', '.').replace(' ', '');
}
if (quantityField.hasClass('ordercard-length')) {
orderCartAll[quantityField.parents('.position').data('id-pos-prefix')][13].value = Number(quantityField.val().replace(',', '.').replace(' ', '')).toFixed(2);
}
if (quantityField.hasClass('ordercard-qty') || quantityField.hasClass('ordercard-length')) {
var curPosLine = quantityField.parents('.position');
var prodQty = Number(curPosLine.find('.ordercard-qty').val().replace(',', '.').replace(' ', ''));
var prodLength = Number(curPosLine.find('.ordercard-length').val().replace(',', '.').replace(' ', '')).toFixed(2);
var fullQty = prodQty * prodLength;
var fullSumm = fullQty * Number(curPosLine.find('[data-price]').attr('data-price').replace(',', '.').replace(' ', ''));
if (!isNaN(fullQty) && fullQty !== 0) curPosLine.find('.ordercard-quantity').val(String(fullQty.toFixed(2)).replace(',', '.'));
if (!isNaN(fullSumm)) curPosLine.find('.ordercard-price').val(String(fullSumm.toFixed(2)).replace(',', '.'));
// Пересчитываем цену в связи с изменениями кол-ва
orderCartAll[quantityField.parents('.position').data('id-pos-prefix')][0].value = curPosLine.find('.ordercard-quantity').val();
}
// Включение/Отключение режима заказов для производства
if (quantityField.hasClass('order_prod')) {
var orderProd = 0;
if (quantityField.prop('checked')) {
orderProd = 1;
}
orderCartAllField[13] = orderProd;
}
// Комментарий - номер заказа (в строке товара)
if (quantityField.hasClass('ordercard-num-order')) {
orderCartAll[quantityField.parents('.position').data('id-pos-prefix')][14].value = quantityField.val();
}
}
// Если включена галочка производства, то увеличиваем сумму на 10%
// По всем позициям, где указано, что они для производства
var curPriceProd = 0;
var newPriceProd = 0;
function calcPrice(el) {
var curPosLine = el.parents('.position');
var prodQty = Number(curPosLine.find('.ordercard-qty').val().replace(',', '.').replace(' ', ''));
var prodLength = Number(curPosLine.find('.ordercard-length').val().replace(',', '.').replace(' ', '')).toFixed(2);
var fullQty = prodQty * prodLength;
var fullSumm = fullQty * Number(curPosLine.find('[data-price]').attr('data-price').replace(',', '.').replace(' ', ''));
// Добавляем наценку в 10%
if (orderCartAllField[13] == '1') fullSumm = fullSumm * 1.1;
if (!isNaN(fullQty) && fullQty !== 0) curPosLine.find('.ordercard-quantity').val(String(fullQty.toFixed(2)).replace(',', '.'));
return (!isNaN(fullSumm)) ? String(fullSumm.toFixed(2)).replace(',', '.') : 0;
}
// Блокируем/разблокируем поле ввода кол-во позиций, которые заказываются на производство
// если стоит галочка для производства
// Пересчитываем цену
$('#ordercard-list').find('.ordercard-prod[value="2"]').each(function(i, el) {
if (orderCartAllField[13] == '1' || (typeof quantityField != 'undefined' && !quantityField.hasClass('ordercard-quantity'))) {
if (typeof quantityField == 'undefined' || (typeof quantityField != 'undefined' && !quantityField.hasClass('ordercard-price'))) {
$(el).parents('.position').find('.ordercard-price').val(calcPrice($(el)));
}
}
if (orderCartAllField[13] == '1') {
$(el).parents('.position').find('.ordercard-quantity').prop('readonly', true);
} else {
$(el).parents('.position').find('.ordercard-quantity').prop('readonly', false);
}
});
// Скрываем поля ввода позиций, которые заказываются на производство
$('#ordercard-list').find('.ordercard-prod[value="1"]').each(function(index, element) {
$(element).parents('.position').find('.ordercard-qty').hide();
$(element).parents('.position').find('.ordercard-length').hide();
$(element).parents('.position').find('.ordercard-num-order').hide();
});
// Сохранение остатков — только по товарным позициям: у строки предпоказа
// «Доставка» (tr.delivery-position) тоже есть td.remains, но её нет в orderCartAll
$('body').find('#ordercard-list').children('.position').find('.remains').each(function(index, element) {
var searchKey = $(element).parents('.position').attr('data-id-pos-prefix');
if (typeof searchKey == 'undefined' || typeof orderCartAll[searchKey] == 'undefined') return;
orderCartAll[searchKey][6].value = $(element).attr('data-warehouse-unknown') === '1' ? null : Number($(element).text());
// Если нет доступного остатка, то подсвечиваем строку
if (Number($(element).text()) === 0) {
$(element).parent('tr').css({ 'background-color': 'tomato' });
} else {
$(element).parent('tr').css({ 'background-color': 'unset' });
}
});
// Записываем изменения
localStorage['JustCRM-OrderCart-field'] = JSON.stringify(orderCartAllField);
localStorage['JustCRM-OrderCart'] = JSON.stringify(orderCartAll);
// Пересчет сумм: подытог сразу с учётом закэшированной строки доставки
deliveryTotalsRender();
// Сумма корзины могла измениться — обновляем предпоказ стоимости доставки:
// у процентных зон стоимость зависит от суммы, строка «Доставка» и подытог
// перерисуются в deliveryRowRender (дебаунс и кэш внутри deliveryPricePreview)
deliveryPricePreview();
// Изменение полей кроме списка товаров
if (typeof localStorage['JustCRM-OrderCart-field'] != 'undefined' && localStorage['JustCRM-OrderCart-field'] != '[]') {
var orderFAll = JSON.parse(localStorage['JustCRM-OrderCart-field']);
if (orderFAll[0] != '') $('#order-client').val(orderFAll[0]);
if (orderFAll[1] != '') $('#id_client').val(orderFAll[1]);
if (orderFAll[2] != '') $('#client_cat_price').val(orderFAll[2]);
// Удаляем старое значение и добавляем новое
//console.log(orderFAll, orderFAll[3][0]);
if (typeof orderFAll[3] != 'undefined' && orderFAll[3] !== null && typeof orderFAll[3][0] != 'undefined' && orderFAll[3][0] != '') {
$('#delivery_places').children('[value="' + orderFAll[3][0] + '"]').remove();
$('#delivery_places').append('');
}
$('#order_client_comments').val(orderFAll[4]);
$('#order-delivery-address').val(orderFAll[5]);
$('#order-delivery-coords').val(orderFAll[6]);
if (typeof orderFAll[7] == 'undefined' && orderFAll[7] == '') {
$('#order_status option[value="1"]').prop('selected', true);
} else {
$('#order_status option[value="' + orderFAll[7] + '"]').prop('selected', true);
}
$('#order_status').trigger('change');
/*
if (typeof orderFAll[8] == 'undefined' && orderFAll[8] == '') {
$('#order-warehouse option[value="1"]').prop('selected', true);
} else {
$('#order-warehouse option[value="'+orderFAll[8]+'"]').prop('selected', true);
console.log('adasdasd');
}
*/
//$('#order-warehouse').trigger('change');
/*
if (typeof orderFAll[3][0] == 'undefined' || orderFAll[3][0] == '') {
$('#delivery_places[value=""]').prop('selected', true);
} else {
$('#delivery_places[value="'+orderFAll[3][0]+'"]').prop('selected', true);
}
$('#delivery_places').trigger('change');
*/
$('#order-delivery-date').val(orderFAll[9]);
if (typeof orderFAll[10] == 'undefined' && orderFAll[10] == '') {
$('#order-delivery-time option[value=""]').prop('selected', true);
} else {
$('#order-delivery-time option[value="' + orderFAll[10] + '"]').prop('selected', true);
}
$('#order-delivery-time').trigger('change');
if (typeof orderFAll[11] == 'undefined' && orderFAll[11] == '') {
$('#order-pay option[value=""]').prop('selected', true);
} else {
$('#order-pay option[value="' + orderFAll[11] + '"]').prop('selected', true);
}
$('#order-pay').trigger('change');
$('#ordercard-edit-flag').val(orderFAll[12]);
updateOrderCardAction();
// Если поле нового адреса заполнено, то выбираем Новый адрес доставки из списка
if ($.trim($('#order-delivery-address').val()) != '') {
$('#delivery_places option[value="%%"]').prop('selected', true);
}
/*else {
$('#delivery_places option[value="%"]').prop('selected', true);
}*/
// Восстанавливаем транспортную компанию (адрес вне зон доставки);
// видимость селекта выставит deliveryRowRender по статусу предпоказа
if (typeof orderFAll[14] != 'undefined' && orderFAll[14] != '') {
$('#order-delivery-tk option[value="' + orderFAll[14] + '"]').prop('selected', true);
}
// Заполняем значение производства
if (orderFAll[13] == '1') {
$('#order_prod').prop('checked', true);
$('.prod-field').show();
$('#order-colspan').attr('colspan', '9');
} else {
$('#order_prod').prop('checked', false);
$('.prod-field').hide();
$('#order-colspan').attr('colspan', '6');
}
}
$('#ordercard-sort').val(localStorage['JustCRM-OrderCart-Sort'] || '{}');
$('#ordercard-shipment').val(localStorage['JustCRM-OrderCart-Shipment'] || '{}');
// Поле «Дата доставки» должно быть видно сразу при открытии корзины, если выбрана
// доставка (не самовывоз) или заполнен адрес. На загрузке страницы блок скрывается
// по дефолтному «Самовывозу», а восстановление полей выше change не триггерит
if ($('#delivery_places').val() == '%' && $.trim($('#order-delivery-address').val()) == '') {
$('#order-delivery-date').parent('div').hide();
} else {
$('#order-delivery-date').parent('div').show();
}
// Предпоказ стоимости доставки при каждом обновлении корзины
deliveryPricePreview();
}
function searchKeyInOrder(searchKey, orderObj) {
for (key in orderObj) {
if (searchKey == key) {
return key;
}
if (key.indexOf(searchKey + '_') > -1) {
return key;
}
}
}
function addOrder(orderClient, idClient, clientCatPrice, first, isFranchiseeClient = false) {
if (isFranchiseeClient === true) {
var orderF4 = ["%", "Самовывоз"],
orderF5 = '',
orderF6 = '',
orderF7 = '',
orderF8 = '',
orderF9 = '',
orderF10 = '',
orderF11 = '',
orderF12 = '',
orderF13 = '',
orderF14 = '';
var orderFAll = [decodeURIComponent(orderClient), decodeURIComponent(idClient), decodeURIComponent(clientCatPrice), orderF4, orderF5, orderF6, orderF7, orderF8, orderF9, orderF10, orderF11, orderF12, orderF13, orderF14];
localStorage['JustCRM-OrderCart-field-Franchisee'] = JSON.stringify(orderFAll);
console.log('Вызов на добавление данных.', orderClient, idClient, clientCatPrice, first)
location.href = '/nomen?cat_price=' + encodeURI(clientCatPrice) + '&cat_price_client_uid=' + encodeURI(idClient);
}
if (!first) {
var orderF4 = ["%", "Самовывоз"],
orderF5 = '',
orderF6 = '',
orderF7 = '',
orderF8 = '',
orderF9 = '',
orderF10 = '',
orderF11 = '',
orderF12 = '',
orderF13 = '',
orderF14 = '';
var orderFAll = [decodeURIComponent(orderClient), decodeURIComponent(idClient), decodeURIComponent(clientCatPrice), orderF4, orderF5, orderF6, orderF7, orderF8, orderF9, orderF10, orderF11, orderF12, orderF13, orderF14];
localStorage['JustCRM-OrderCart-field'] = JSON.stringify(orderFAll);
console.log('Вызов на добавление данных.', orderClient, idClient, clientCatPrice, first)
location.href = '/nomen?cat_price=' + encodeURI(clientCatPrice) + '&cat_price_client_uid=' + encodeURI(idClient);
} else {
console.log('Обновление данных для заказа:', orderClient, idClient, clientCatPrice, first);
if (typeof localStorage['JustCRM-OrderCart-field'] == 'undefined') localStorage['JustCRM-OrderCart-field'] = '[]';
try {
var orderFAll = JSON.parse(localStorage['JustCRM-OrderCart-field']);
} catch (e) {
var orderFAll = [];
}
orderFAll[0] = decodeURIComponent(orderClient);
orderFAll[1] = decodeURIComponent(idClient);
orderFAll[2] = decodeURIComponent(clientCatPrice);
orderFAll[3] = ["%", "Самовывоз"];
orderFAll[4] = '';
orderFAll[5] = '';
orderFAll[6] = '';
orderFAll[7] = '1';
orderFAll[8] = '';
orderFAll[9] = '';
orderFAll[10] = '';
orderFAll[11] = '';
orderFAll[12] = '';
orderFAll[13] = 0;
localStorage['JustCRM-OrderCart-field'] = JSON.stringify(orderFAll);
}
}
function addOrderList(orderClient, idClient, clientCatPrice, first, isFranchiseeClient = false) {
if (isFranchiseeClient === true) {
var orderF4 = ["%", "Самовывоз"],
orderF5 = '',
orderF6 = '',
orderF7 = '',
orderF8 = '',
orderF9 = '',
orderF10 = '',
orderF11 = '',
orderF12 = '',
orderF13 = '',
orderF14 = '';
var orderFAll = [decodeURIComponent(orderClient), decodeURIComponent(idClient), decodeURIComponent(clientCatPrice), orderF4, orderF5, orderF6, orderF7, orderF8, orderF9, orderF10, orderF11, orderF12, orderF13, orderF14];
localStorage['JustCRM-OrderCartList-field-Franchisee'] = JSON.stringify(orderFAll);
console.log('Вызов на добавление данных (клиент франчайзи).', orderClient, idClient, clientCatPrice, first)
location.href = '/nomendraw?cat_price=' + encodeURI(clientCatPrice) + '&cat_price_client_uid=' + encodeURI(idClient);
}
if (!first) {
var orderF4 = ["%", "Самовывоз"],
orderF5 = '',
orderF6 = '',
orderF7 = '',
orderF8 = '',
orderF9 = '',
orderF10 = '',
orderF11 = '',
orderF12 = '',
orderF13 = '',
orderF14 = '';
var orderFAll = [decodeURIComponent(orderClient), decodeURIComponent(idClient), decodeURIComponent(clientCatPrice), orderF4, orderF5, orderF6, orderF7, orderF8, orderF9, orderF10, orderF11, orderF12, orderF13, orderF14];
localStorage['JustCRM-OrderCartList-field'] = JSON.stringify(orderFAll);
console.log('Вызов на добавление данных.', orderClient, idClient, clientCatPrice, first)
location.href = '/nomendraw?cat_price=' + encodeURI(clientCatPrice) + '&cat_price_client_uid=' + encodeURI(idClient);
} else {
console.log('Обновление данных для заказа:', orderClient, idClient, clientCatPrice, first);
if (typeof localStorage['JustCRM-OrderCartList-field'] == 'undefined') localStorage['JustCRM-OrderCartList-field'] = '[]';
try {
var orderFAll = JSON.parse(localStorage['JustCRM-OrderCartList-field']);
} catch (e) {
var orderFAll = [];
}
orderFAll[0] = decodeURIComponent(orderClient);
orderFAll[1] = decodeURIComponent(idClient);
orderFAll[2] = decodeURIComponent(clientCatPrice);
orderFAll[3] = ["%", "Самовывоз"];
orderFAll[4] = '';
orderFAll[5] = '';
orderFAll[6] = '';
orderFAll[7] = '1';
orderFAll[8] = '';
orderFAll[9] = '';
orderFAll[10] = '';
orderFAll[11] = '';
orderFAll[12] = '';
orderFAll[13] = 0;
localStorage['JustCRM-OrderCartList-field'] = JSON.stringify(orderFAll);
}
}
function deleteOrderAllPos(skipReload) {
cancelCartWarehouse();
// Удаляем выбранного клиента и сведения о нём
$('.client_warning').hide();
deleteCookie('cat_search_price_client_uid');
deleteCookie('cat_search_price_client_uid_franchisee');
deleteCookie('JustCRM_open_master_order');
// Очищаем корзину заказа
$('#ordercard_form').find('#ordercard-list').children().remove();
localStorage['JustCRM-OrderCart'] = '{}';
localStorage['JustCRM-OrderCart-Sort'] = '{}';
localStorage['JustCRM-OrderCart-Shipment'] = '{}';
localStorage['JustCRM-OrderCart-field'] = '[]';
localStorage['JustCRM-OrderCart-field-Franchisee'] = '[]';
delete localStorage['JustCRM-OrderCart-promocode'];
delete localStorage['JustCRM-OrderCart-promocode-data'];
delete localStorage['JustCRM-OrderCart-promoOrig'];
delete localStorage['JustCRM-OrderCart-promoRestore'];
$('body').find('.select-cart-pos').removeClass('select-cart-pos');
orderMarkerView();
// skipReload: при переходе на страницу созданного заказа перезагрузку не планируем —
// отложенный location.reload() отменял уже начатую навигацию, и вместо заказа открывалась номенклатура
if (skipReload === true) return;
delayClosePopup(0);
setTimeout(function() {
delayClosePopup(500);
setTimeout(function() {
location.reload();
}, 500);
}, 500);
}
function deleteOrderAllPosList(skipReload) {
$('.client_warning').hide();
deleteCookie('cat_search_price_client_uid_list');
deleteCookie('cat_search_price_client_uid_list_franchisee');
deleteCookie('JustCRM_open_master_order_list');
// Очищаем корзину заказа
$('#ordercardlist_form').find('#ordercardlist-list').children().remove();
localStorage['JustCRM-OrderCartList'] = '{}';
localStorage['JustCRM-OrderCartList-field'] = '{}';
localStorage['JustCRM-OrderCartList-field-Franchisee'] = '[]';
$('body').find('.select-cart-pos').removeClass('select-cart-pos');
// skipReload: см. deleteOrderAllPos — reload отменял навигацию на страницу созданного заказа
if (skipReload === true) return;
delayClosePopup(0);
setTimeout(function() {
delayClosePopup(500);
setTimeout(function() {
location.reload();
}, 500);
}, 500);
}
function deleteOrderPos(storeVarId, storeVar, templateId) {
var orderCartAll = JSON.parse(localStorage['JustCRM-OrderCart']);
var orderCartAllSort = JSON.parse(localStorage['JustCRM-OrderCart-Sort']);
var orderCartAllShipment = JSON.parse(localStorage['JustCRM-OrderCart-Shipment']);
delete orderCartAll[storeVarId];
delete orderCartAllSort[storeVarId];
delete orderCartAllShipment[storeVarId];
localStorage['JustCRM-OrderCart'] = JSON.stringify(orderCartAll);
localStorage['JustCRM-OrderCart-Sort'] = JSON.stringify(orderCartAllSort);
localStorage['JustCRM-OrderCart-Shipment'] = JSON.stringify(orderCartAllShipment);
if (!Object.keys(orderCartAll).length) cancelCartWarehouse();
//$(templateId).children('[data-id-pos="' + storeVarId + '"]').remove();
$(templateId).children('[data-id-pos-prefix="' + storeVarId + '"]').remove();
$(this).parents('td').first().find('input').removeClass('select-cart-pos');
$('#toBackAncor_' + storeVarId).children('[data-add-cart]').find('input').removeClass('select-cart-pos');
orderMarkerView();
delayClosePopup(0);
setTimeout(function() {
if ($(templateId).children('tr').length === 0) {
delete localStorage['JustCRM-OrderCart-promocode'];
delete localStorage['JustCRM-OrderCart-promocode-data'];
delete localStorage['JustCRM-OrderCart-promoOrig'];
delete localStorage['JustCRM-OrderCart-promoRestore'];
delayClosePopup(500);
}
}, 500);
orderStat();
}
function orderMarkerView() {
if (typeof localStorage['JustCRM-OrderCart'] != 'undefined') {
var orderCartAll = JSON.parse(localStorage['JustCRM-OrderCart']);
if (Object.keys(orderCartAll).length > 0) {
$('#marker-cart').show();
$('#marker-cart').find('.marker').html(Object.keys(orderCartAll).length);
} else {
$('#marker-cart').hide();
}
}
}
function updateOrderCardAction() {
var $form = $('#ordercard_form');
if (!$form.length) return;
var isEditing = $.trim($form.find('#ordercard-edit-flag').val()) !== '';
var shouldMakeInvoice = $form.data('auto-invoice') === true && !isEditing;
$form.find('.add-order').text(isEditing ? 'Изменить заказ' : (shouldMakeInvoice ? 'Сформировать счёт' : 'Создать заказ'));
}
// Корзина заказа - НОВАЯ КОРЗИНА - Конец
// Корзина изделий из листового металла
function orderListMarkerView() {
if (typeof localStorage['JustCRM-OrderCartList'] != 'undefined') {
var orderCartAllList = JSON.parse(localStorage['JustCRM-OrderCartList']);
if (Object.keys(orderCartAllList).length > 0) {
$('#marker-cart-list').show();
$('#marker-cart-list').find('.marker').html(Object.keys(orderCartAllList).length);
} else {
$('#marker-cart-list').hide();
}
}
}
// Телефон - вызов номера
function makeCall(phone) {
var phoneNumber = (typeof(phone) == 'object') ? $(phone).parent('div').children('input').val() : phone;
if (/^\+?\d{10,18}$/.test(phoneNumber)) {
send_request(phoneNumber, 'data-exchange', 'data-make-call');
delayClosePopup(1000);
delayClosePopup(2000);
} else {
popup('bad', 'Ошибка!', 'Номер некорректен! Исправьте для успешного набора.', true, false);
}
}
// Уведомления
// Проверка и запрос разрешений на уведомления
function notifyMe(subj, mess, tag) {
// Теперь давайте проверим есть ли у нас разрешение для отображения уведомления
if (Notification.permission === "granted") {
// Если все в порядке, то создадим уведомление
notify(subj, mess, tag);
}
// В противном случае, мы должны спросить у пользователя разрешение
else if (Notification.permission === 'default') {
Notification.requestPermission(function(permission) {
// Не зависимо от ответа, сохраняем его в настройках
if (!('permission' in Notification)) {
Notification.permission = permission;
}
// Если разрешение получено, то создадим уведомление
if (permission === "granted") {
notify(subj, mess, tag);
}
});
}
}
// Вывод уведомления
function notify(subj, mess, tag) {
var notification = new Notification(subj, {
lang: 'ru-RU',
body: mess,
icon: '/img-vendor/logo_note.png',
tag: tag,
requireInteraction: true
});
// Действие по клику
notification.onclick = function() {
var info = JSON.parse(notification.tag);
// Формируем ссылку на Юр.лиц, Физ. лиц, либо Лидов в зависимости от clientType и lidasType
var linkType = (info.clientType != '2') ? 'clients' : 'fiz';
if (info.lidasType == '1') linkType = 'lidas';
// Если клиент идентифицирован, то открываен форму редактирования
if (info.clientId && info.clientId != 'new') {
window.location.href = '/' + linkType + '/_details/' + info.clientId;
} else if (info.clientId == 'new') {
// Иначе пустая форма клиента c входящим номером
setCookie('call_client', info.clientNumber);
location.href = '/lidas/client';
}
// Если иные события
if (info.command) {
switch (info.command) {
case 'new_task':
window.location.href = info.task_url;
break;
case 'dropped_call':
window.location.href = '/tasks';
break;
case 'new_letter':
window.location.href = '/mailbox?filter_parametres=filter_all';
break;
}
}
}
}
// Уведомления - Конец
// Вывод на печать
function toPrint(obj, zag, nologo) {
var objPrint = $(obj).clone();
if (!nologo) {
var newWin = window.open('/components/inc/print.html', 'Печать и сохранение', 'width=1200,height=600,resizable=yes,scrollbars=yes,status=no,toolbar=no,location=no,menubar=no');
} else {
var newWin = window.open('/components/inc/print.html', 'Печать и сохранение', 'width=1200,height=600,resizable=yes,scrollbars=yes,status=no,toolbar=no,location=no,menubar=yes');
}
newWin.onload = function() {
var div = newWin.document.createElement('div');
body = newWin.document.body;
div.innerHTML = objPrint[0].innerHTML;
body.insertBefore(div, body.firstChild);
$(body).find('.print').remove();
$(body).find('.delete-print').remove();
$(body).find('.clear-print').attr('class', '').attr('id', '').attr('style', '');
$(body).children('div').css({ 'margin': '5em' });
$(body).children('div').prepend('
' + zag + '
');
if (!nologo) {
$(body).children('div').prepend('');
setTimeout(function() {
newWin.print();
}, 500);
}
}
}
// Скролл до объекта
function scr(obj, delay) {
try {
if (!delay) var delay = 0;
setTimeout(function() {
$('html, body').animate({ scrollTop: $('#' + obj).offset().top }, 250, 'swing');
preloader();
}, delay);
} catch (e) {
console.log('Нет объекта для возврата.');
}
}
function scrInDiv(obj, delay) {
try {
if (!delay) var delay = 0;
var container = $('#' + obj).parents('.scroll');
$('html, body').animate({ scrollTop: container.offset().top }, 250, 'swing'); //jqBar.position().top
setTimeout(function() {
container.animate({ scrollTop: document.getElementById(obj).offsetTop }, 250, 'swing');
}, delay);
} catch (e) {
console.log('Нет объекта для возврата.');
}
}
/*
setTimeout(function() {
sendSocket('{"command":"new_task", "id_client":"'+guid+'"}');
}, 2000);
*/
// Отправка сообщения в сокет
function sendSocket(command) {
if (window.parent.socket) window.parent.socket.send(command);
}
// Декодирование HTML-сущностей
function htmlDecode(input) {
var e = document.createElement('div');
e.innerHTML = input;
return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
}
// Парсинг параметров GET
function findGetParameter(findGet) {
var result = {},
temp = null,
findGetValue = false;
location.search.substr(1).split('&').forEach(function(item) {
item.split('=').forEach(function(item, i) {
if (i === 0) {
temp = decodeURIComponent(item);
if (temp != '') result[temp] = 0;
};
if (i === 1) result[temp] = decodeURIComponent(item);
// Если задан параметр поиска значения GET по ключу
if (typeof(findGet) != 'undefined' && findGet == temp && result[temp] != '') {
findGetValue = true;
return false;
}
});
});
if (findGet && findGetValue) {
return result[temp];
} else {
if (Object.keys(result).length !== 0 && !findGet) return result;
else return false;
}
}
// Переход по указанному URL
function proceedURL(url) {
location.href = url;
}
function parseNomenQuantityValue(value) {
return Number(String(value).replace(/\s/g, '').replace(',', '.'));
}
function formatNomenQuantityValue(value) {
var quantity = parseNomenQuantityValue(value);
if (isNaN(quantity)) return '';
return String(Number(quantity.toFixed(10))).replace('.', ',');
}
function formatNomenQuantityInputValue(value) {
var quantity = parseNomenQuantityValue(value);
if (isNaN(quantity)) return '';
return String(Number(quantity.toFixed(10)));
}
// Округление в большую сторону к требуемому числу
function roundMultiple(num, multiple) {
var rounded = Math.ceil(parseNomenQuantityValue(num) / parseNomenQuantityValue(multiple)) * parseNomenQuantityValue(multiple);
return Number(rounded.toFixed(10));
}
// «Да» в попапе округления количества в корзине — принять округлённое значение и пересчитать
window.nomenRoundConfirmAcceptCart = function() {
var $input = null;
if (window.nomenRoundConfirm && window.nomenRoundConfirm.$input) {
$input = window.nomenRoundConfirm.$input;
$input.val(formatNomenQuantityInputValue(window.nomenRoundConfirm.roundedVal));
}
// Очищаем состояние ДО закрытия попапа, чтобы обработчик «Нет» не сработал повторно
window.nomenRoundConfirm = null;
$(document).off('click.nomenRoundCart');
// Пересчитываем корзину с округлённым значением
if ($input) {
orderStat($input, 'minShipment');
}
$('.popup').last().find('.close').trigger('click');
};
// «Нет» в попапе округления количества в корзине — вернуть предыдущее кратное значение
window.nomenRoundConfirmRejectCart = function() {
if (!window.nomenRoundConfirm) return; // уже обработано (Да или повторный вызов)
if (window.nomenRoundConfirm.$input) {
// Возвращаем значение, которое было до редактирования
window.nomenRoundConfirm.$input.val(formatNomenQuantityInputValue(window.nomenRoundConfirm.prevVal));
}
window.nomenRoundConfirm = null;
};
// Управление видимостью столбцов таблиц
// Инициализация компонента для всех таблиц с классом col-toggle-table
function initColumnToggle() {
$('.col-toggle-table').each(function() {
var $table = $(this);
var tableId = $table.attr('id') || 'table_' + Math.random().toString(36).substr(2, 9);
// Если уже инициализирована - пропускаем
if ($table.data('col-toggle-init')) return;
$table.data('col-toggle-init', true);
// Создаем обертку с кнопкой
var $wrapper = $('');
var $btn = $('');
var $popup = $('');
// Заголовок popup
var $popupHeader = $('
Настройка столбцов
');
var $popupBody = $('');
// Получаем заголовки столбцов
var $headers = $table.find('thead th, tr:first-child th');
var settings = loadColumnSettings(tableId);
$headers.each(function(index) {
var $th = $(this);
var colName = $th.text().trim();
// Пропускаем пустые столбцы (действия) - не показываем в списке
if (colName === '') {
return true; // continue
}
// Проверяем сохраненное состояние
var isVisible = settings[index] !== false;
// Создаем элемент списка
var $item = $('');
var $label = $('' + colName + '');
var $toggle = $('');
$item.append($label).append($toggle);
$popupBody.append($item);
// Применяем начальное состояние через классы
if (!isVisible) {
toggleColumn($table, index, false);
}
});
$popup.append($popupHeader).append($popupBody);
$wrapper.append($btn).append($popup);
// Вставляем в блок пагинации (если есть) или перед таблицей
var $container = $table.closest('#headcol-fix').length ? $table.closest('#headcol-fix') : $table;
var $paging = $container.prevAll('.paging').first();
if ($paging.length) {
// Вставляем в пагинацию справа
$paging.append($wrapper);
} else {
// Иначе перед таблицей
$container.before($wrapper);
}
// Обработчик кнопки
$btn.on('click', function(e) {
e.stopPropagation();
$('.col-toggle-popup').not($popup).removeClass('active');
$popup.toggleClass('active');
});
// Закрытие по крестику
$popupHeader.find('.fa-times').on('click', function() {
$popup.removeClass('active');
});
// Обработчик тумблеров (сохраняем ссылки в closure)
(function(tbl, tblId) {
$popupBody.on('change', 'input[type="checkbox"]', function() {
var colIdx = parseInt($(this).attr('data-col-idx'));
var isChecked = $(this).is(':checked');
toggleColumn(tbl, colIdx, isChecked);
// Обновляем настройки напрямую
var settings = loadColumnSettings(tblId);
settings[colIdx] = isChecked;
saveColumnSettings(tblId, settings);
});
})($table, tableId);
});
// Закрытие popup при клике вне его
$(document).on('click', function(e) {
if (!$(e.target).closest('.col-toggle-wrap').length) {
$('.col-toggle-popup').removeClass('active');
}
});
}
// Переключение видимости столбца (классы)
function toggleColumn($table, colIndex, isVisible) {
// Используем CSS селектор nth-child для надёжности
var nthChild = colIndex + 1;
var selector = 'tr th:nth-child(' + nthChild + '), tr td:nth-child(' + nthChild + ')';
var $cells = $table.find(selector);
if (isVisible) {
$cells.removeClass('col-hidden');
} else {
$cells.addClass('col-hidden');
}
}
// Получение текущих настроек столбцов
function getColumnSettings($table) {
var settings = {};
var $headers = $table.find('thead th, tr:first-child th');
$headers.each(function(index) {
var $th = $(this);
settings[index] = !$th.hasClass('col-hidden');
});
return settings;
}
// Сохранение настроек в localStorage
function saveColumnSettings(tableId, settings) {
localStorage['JustCRM_colToggle_' + tableId] = JSON.stringify(settings);
}
// Загрузка настроек из localStorage
function loadColumnSettings(tableId) {
var stored = localStorage['JustCRM_colToggle_' + tableId];
if (stored) {
try {
return JSON.parse(stored);
} catch (e) {
return {};
}
}
return {};
}
// Сброс настроек столбцов для таблицы
function resetColumnSettings(tableId) {
delete localStorage['JustCRM_colToggle_' + tableId];
location.reload();
}
// Инициализация при загрузке страницы
$(document).ready(function() {
initColumnToggle();
});
// Управление видимостью столбцов таблиц - Конец
// Сообщить об ошибке - Начало
$(document).ready(function() {
// popup('form', ...) переносит узел #report-error-form внутрь окна, а закрытие
// попапа (Отмена/крестик) этот узел удаляет — поэтому сохраняем исходную разметку
// один раз и восстанавливаем её перед каждым открытием (иначе со второго раза
// и на страницах, где узел уже был перемещён/удалён, попап открывается пустым).
var reportErrorFormHTML = (function() {
var el = document.getElementById('report-error-form');
return el ? el.outerHTML : null;
})();
// Обработчик клика по кнопке "Сообщить об ошибке"
$('#report-error-btn').on('click', function() {
if (reportErrorFormHTML) {
$('#report-error-form').remove(); // убираем возможный «осиротевший» экземпляр
$('body').append(reportErrorFormHTML); // свежая копия формы (поля чистые)
}
popup('form', '', 'report-error-form', false, false);
});
// Обработчик клика по кнопке отправки (основной обработчик, минуя submit формы)
$(document).on('click', '#report-error-form_form button[type="submit"], #report-error-form_form .orange-but', function(e) {
console.log('Кнопка отправки нажата');
e.preventDefault();
e.stopImmediatePropagation();
e.stopPropagation();
// Находим форму
var $form = $(this).closest('form');
if (!$form.length || $form.attr('id') !== 'report-error-form_form') {
console.log('Форма не найдена!');
return;
}
console.log('Форма найдена, начинаем обработку');
// Отключаем validationEngine
try {
if ($form.data('jqv')) {
$form.validationEngine('detach');
}
$form.validationEngine('detach');
$form.find('input, textarea, select').removeClass('validate');
$form.off('submit.validationEngine');
} catch(e) {
console.log('Ошибка при отключении validationEngine:', e);
}
// Ищем textarea в контексте этой формы
var description = $form.find('#error-description').val().trim();
console.log('Описание:', description, 'Длина:', description.length);
if (!description || description.length < 20) {
popup('bad', 'Ошибка!', 'Пожалуйста, опишите проблему. Минимальная длина описания - 20 символов.', true, false);
return;
}
// Собираем данные формы
var formData = new FormData();
formData.append('error_description', description);
// Добавляем файлы
var fileInput = $form.find('#error-files')[0];
console.log('File input:', fileInput, 'Files:', fileInput ? fileInput.files : 'не найден');
if (fileInput && fileInput.files && fileInput.files.length > 0) {
var files = fileInput.files;
console.log('Файлов выбрано:', files.length);
for (var i = 0; i < files.length; i++) {
formData.append('error_files[]', files[i]);
}
} else {
console.log('Файлы не выбраны');
}
// Получаем информацию о системе
var os = navigator.platform || 'Неизвестно';
var browser = navigator.userAgent || 'Неизвестно';
var url = window.location.href;
var user = (typeof id !== 'undefined' && typeof guid !== 'undefined') ? 'ID: ' + id + ', GUID: ' + guid : 'Неизвестно';
var time = new Date().toLocaleString('ru-RU');
formData.append('os', os);
formData.append('browser', browser);
formData.append('url', url);
formData.append('user', user);
formData.append('time', time);
// Отправляем данные
console.log('Начинаем отправку AJAX запроса');
preloader();
preloader('show');
// Проверяем наличие guid
var requestGuid = (typeof guid !== 'undefined' && guid) ? guid : '';
var requestUrl = '/ajax-send/data-report-error.php' + (requestGuid ? '?guid=' + requestGuid : '');
console.log('URL запроса:', requestUrl);
$.ajax({
url: requestUrl,
type: 'POST',
data: formData,
cache: false,
processData: false,
contentType: false,
success: function(response) {
console.log('Ответ сервера:', response);
preloader();
// Закрываем попап с формой напрямую, без лишних обработчиков
var formPopup = $('.popup').has('#report-error-form_form').last();
if (formPopup.length) {
// Возвращаем форму обратно и скрываем
var reportErrorForm = formPopup.find('#report-error-form');
if (reportErrorForm.length) {
reportErrorForm.css('display', 'none');
$('body').append(reportErrorForm);
}
formPopup.find('.wind').removeClass('zoomIn').addClass('zoomOut');
formPopup.fadeOut('slow', function() {
formPopup.remove();
$('html').css({ 'overflow-y': 'unset' });
});
}
if (response && response.indexOf('Успешно') !== -1) {
popup('good', 'Успешно!', 'Сообщение об ошибке отправлено. Спасибо за обратную связь!', true, false);
} else {
popup('bad', 'Ошибка!', 'Не удалось отправить сообщение. Попробуйте позже.', true, false);
}
},
error: function(xhr, status, error) {
console.log('Ошибка AJAX:', status, error, xhr.responseText);
preloader();
var errorMsg = 'Произошла ошибка при отправке сообщения.';
if (xhr.responseText) {
errorMsg += ' ' + xhr.responseText.substring(0, 100);
}
popup('bad', 'Ошибка!', errorMsg, true, false);
}
});
return false;
});
// Обработчик отправки формы (делегирование для динамически добавленных элементов)
// Используем более высокий приоритет, чтобы перехватить до validationEngine
$(document).on('submit', '#report-error-form_form', function(e) {
console.log('Обработчик submit сработал для #report-error-form_form');
// Останавливаем событие сразу, чтобы validationEngine не перехватил
e.preventDefault();
e.stopImmediatePropagation();
e.stopPropagation();
// Отключаем validationEngine для этой формы, если он еще активен
var $form = $(this);
// Отключаем validationEngine несколькими способами для надежности
try {
if ($form.data('jqv')) {
$form.validationEngine('detach');
}
$form.validationEngine('detach');
$form.find('input, textarea, select').removeClass('validate');
// Удаляем все обработчики validationEngine
$form.off('submit.validationEngine');
$form.unbind('submit');
} catch(e) {
// Игнорируем ошибки при отключении validationEngine
}
// Ищем textarea в контексте этой формы
var description = $form.find('#error-description').val().trim();
if (!description || description.length < 20) {
popup('bad', 'Ошибка!', 'Пожалуйста, опишите проблему. Минимальная длина описания - 20 символов.', true, false);
return;
}
// Проверяем, что форма найдена
if (!$form.length) {
popup('bad', 'Ошибка!', 'Форма не найдена.', true, false);
return;
}
// Собираем данные формы
var formData = new FormData();
formData.append('error_description', description);
// Добавляем файлы
// Форма не клонируется, а перемещается, поэтому файлы должны быть доступны
var fileInput = $form.find('#error-files')[0];
if (fileInput && fileInput.files && fileInput.files.length > 0) {
var files = fileInput.files;
for (var i = 0; i < files.length; i++) {
formData.append('error_files[]', files[i]);
}
}
// Получаем информацию о системе
var os = navigator.platform || 'Неизвестно';
var browser = navigator.userAgent || 'Неизвестно';
var url = window.location.href;
var user = (typeof id !== 'undefined' && typeof guid !== 'undefined') ? 'ID: ' + id + ', GUID: ' + guid : 'Неизвестно';
var time = new Date().toLocaleString('ru-RU');
formData.append('os', os);
formData.append('browser', browser);
formData.append('url', url);
formData.append('user', user);
formData.append('time', time);
// Отправляем данные
preloader();
preloader('show');
// Проверяем наличие guid
var requestGuid = (typeof guid !== 'undefined' && guid) ? guid : '';
var requestUrl = '/ajax-send/data-report-error.php' + (requestGuid ? '?guid=' + requestGuid : '');
$.ajax({
url: requestUrl,
type: 'POST',
data: formData,
cache: false,
processData: false,
contentType: false,
success: function(response) {
preloader();
// Закрываем попап с формой напрямую, без лишних обработчиков
var formPopup = $('.popup').has('#report-error-form_form').last();
if (formPopup.length) {
// Возвращаем форму обратно и скрываем
var reportErrorForm = formPopup.find('#report-error-form');
if (reportErrorForm.length) {
reportErrorForm.css('display', 'none');
$('body').append(reportErrorForm);
}
formPopup.find('.wind').removeClass('zoomIn').addClass('zoomOut');
formPopup.fadeOut('slow', function() {
formPopup.remove();
$('html').css({ 'overflow-y': 'unset' });
});
}
if (response && response.indexOf('Успешно') !== -1) {
popup('good', 'Успешно!', 'Сообщение об ошибке отправлено. Спасибо за обратную связь!', true, false);
} else {
popup('bad', 'Ошибка!', 'Не удалось отправить сообщение. Попробуйте позже.', true, false);
}
},
error: function(xhr, status, error) {
preloader();
var errorMsg = 'Произошла ошибка при отправке сообщения.';
if (xhr.responseText) {
errorMsg += ' ' + xhr.responseText.substring(0, 100);
}
popup('bad', 'Ошибка!', errorMsg, true, false);
}
});
});
});
// Сообщить об ошибке - Конец