< Summary

Information
Class: AspNetCoreGeneratedDocument.Areas_Studio2_Views_Orders__CreateOrderScript
Assembly: OzonOrdersWeb
File(s): /home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Areas/Studio2/Views/Orders/_CreateOrderScript.cshtml
Line coverage
0%
Covered lines: 0
Uncovered lines: 14
Coverable lines: 14
Total lines: 1366
Line coverage: 0%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
ExecuteAsync()100%210%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Areas/Studio2/Views/Orders/_CreateOrderScript.cshtml

#LineLine coverage
 1@using OzonOrdersWeb.ViewModels.OrderViewModels
 2@model CreateOrderViewModel
 3
 4<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
 5
 6<script>
 7    // Сохранение значений в куки (по аналогии с _TransactionScript.cshtml)
 8    document.addEventListener('DOMContentLoaded', (event) => {
 9        function saveToCookies(key, value) {
 10            document.cookie = key + "=" + encodeURIComponent(value) + "; path=/";
 11            console.log(`Сохранено: поле ${key}, значение ${value}`);
 12        }
 13
 14        function loadFromCookies(key) {
 15            const name = key + "=";
 16            const decodedCookie = decodeURIComponent(document.cookie);
 17            const ca = decodedCookie.split(';');
 18            for (let i = 0; i < ca.length; i++) {
 19                let c = ca[i].trim();
 20                if (c.indexOf(name) === 0) {
 21                    return c.substring(name.length, c.length);
 22                }
 23            }
 24            return "";
 25        }
 26
 27        // Для каждого select с классом 'status-select'
 28        document.querySelectorAll('.status-select').forEach(select => {
 29            const id = select.id || 'status-select';
 30            const savedValue = loadFromCookies(id);
 31
 32            if (savedValue) {
 33                select.value = savedValue;
 34                console.log(`Загружено из куки: поле ${id}, значение ${savedValue}`);
 35            }
 36
 37            select.addEventListener('change', function () {
 38                saveToCookies(id, this.value);
 39            });
 40        });
 41
 42        // Для скрытого поля SupplierId
 43        const supplierIdField = document.getElementById('Order_SupplierId');
 44        if (supplierIdField) {
 45            const savedValue = loadFromCookies('Order_SupplierId');
 46            if (savedValue) {
 47                supplierIdField.value = savedValue;
 48                console.log(`Загружено из куки: поле Order_SupplierId, значение ${savedValue}`);
 49            }
 50            supplierIdField.addEventListener('change', function () {
 51                saveToCookies('Order_SupplierId', this.value);
 52            });
 53        }
 54
 55        // Для скрытого поля OrderNumberToSupplier
 56        const orderNumberToSupplierField = document.getElementById('Order_OrderNumberToSupplier');
 57        if (orderNumberToSupplierField) {
 58            const savedValue = loadFromCookies('Order_OrderNumberToSupplier');
 59            if (savedValue) {
 60                orderNumberToSupplierField.value = savedValue;
 61                console.log(`Загружено из куки: поле Order_OrderNumberToSupplier, значение ${savedValue}`);
 62            }
 63            orderNumberToSupplierField.addEventListener('input', function () {
 64                saveToCookies('Order_OrderNumberToSupplier', this.value);
 65            });
 66        }
 67
 68        // Для каждого input с классом 'purchase-price-field'
 69        document.querySelectorAll('.purchase-price-field').forEach(input => {
 70            const id = input.id || 'purchase-price';
 71            const savedValue = loadFromCookies(id);
 72
 73            if (savedValue) {
 74                input.value = savedValue;
 75                console.log(`Загружено из куки: поле ${id}, значение ${savedValue}`);
 76            }
 77
 78            input.addEventListener('input', function () {
 79                saveToCookies(id, this.value);
 80            });
 81        });
 82    });
 83</script>
 84
 85<script>
 86    // Функция для извлечения числового значения из строки
 87    function extractNumber(text) {
 88        if (typeof text !== 'string') {
 89            text = String(text);
 90        }
 91        const number = parseFloat(text.replace(/\s/g, '').replace(',', '.'));
 92        return isNaN(number) ? null : number;
 93    }
 94</script>
 95
 96<script>
 97    $(document).ready(function () {
 98        // Получаем значения курсов валют из Razor View
 099        var rateUSD = @Model.RateUSD.ToString().Replace(',', '.');
 0100        var rateEUR = @Model.RateEUR.ToString().Replace(',', '.');
 0101        var rateBYN = @Model.RateBYN.ToString().Replace(',', '.');
 102
 103        // Сохраняем курсы валют в глобальной области видимости
 104        if (typeof window.rateUSD === 'undefined') {
 105            window.rateUSD = rateUSD;
 106            window.rateEUR = rateEUR;
 107            window.rateBYN = rateBYN;
 108        }
 109
 110        // Сохраняем данные о поставщиках для работы со скрытым полем
 0111        window.suppliersData = @Html.Raw(Json.Serialize(Model.Suppliers.Select(s => new
 0112                               {
 0113                                   id = s.Id,
 0114                                   currencyCode = s.CurrencyCode.ToString(),
 0115                                   costFactor = s.CostFactor,
 0116                                   weightFactor = s.WeightFactor,
 0117                                   weightFactorCurrencyCode = s.WeightFactorCurrencyCode.ToString(),
 0118                                   site = s.Site,
 0119                                   isReSeller = s.IsReSeller
 0120                               })));
 121
 122        // Обработка изменения поставщика (скрытое поле)
 123        $('#Order_SupplierId').on('change', function () {
 124            var supplierId = $(this).val();
 125            if (!supplierId) return;
 126
 127            // Находим данные поставщика из скрытого списка
 128            var supplierData = window.suppliersData && window.suppliersData.find(s => s.id == supplierId);
 129            if (!supplierData) return;
 130
 131            var currencyCode = supplierData.currencyCode;
 132            var isReSeller = supplierData.isReSeller;
 133            var orderId = 'new';
 134
 135            // Обновляем валюту
 136            if (currencyCode) {
 137                $('#CurrencyCode_' + orderId).text(currencyCode);
 138            } else {
 139                $('#CurrencyCode_' + orderId).text('');
 140            }
 141
 142            // Если поставщик — реализатор → меняем статус заказа
 143            if (isReSeller === true || isReSeller === "True") {
 144                var statusSelect = $('#Order_AppStatusId');
 145                if (statusSelect.length && statusSelect[0]) {
 146                    var statusOptions = statusSelect[0].options;
 147                    var resellerStatusValue = null;
 148
 149                    for (var i = 0; i < statusOptions.length; i++) {
 150                        var optionText = statusOptions[i].text.trim();
 151                        if (optionText === "Заказан реализатору") {
 152                            resellerStatusValue = statusOptions[i].value;
 153                            break;
 154                        }
 155                    }
 156
 157                    if (resellerStatusValue) {
 158                        statusSelect[0].value = resellerStatusValue;
 159                        statusSelect.trigger('change');
 160                    }
 161                }
 162            }
 163        });
 164
 165        // Обработка изменения цены закупки
 166        $('.purchase-price-field').on('input', function () {
 167            var supplierId = $('#Order_SupplierId').val();
 168            if (!supplierId) return;
 169
 170            var supplierData = window.suppliersData && window.suppliersData.find(s => s.id == supplierId);
 171            if (!supplierData) return;
 172
 173            var currencyCode = supplierData.currencyCode;
 174            var costFactor = extractNumber(supplierData.costFactor.toString()) || 1;
 175
 176            if (currencyCode && costFactor) {
 177                var purchasePrice = parseFloat($(this).val()) || 0;
 178                var purchasePriceInRub = 0;
 179
 180                switch (currencyCode) {
 181                    case 'USD':
 182                        purchasePriceInRub = purchasePrice * costFactor * rateUSD;
 183                        break;
 184                    case 'EUR':
 185                        purchasePriceInRub = purchasePrice * costFactor * rateEUR;
 186                        break;
 187                    case 'BYN':
 188                        purchasePriceInRub = purchasePrice * costFactor * rateBYN;
 189                        break;
 190                    default:
 191                        purchasePriceInRub = purchasePrice * costFactor;
 192                        break;
 193                }
 194
 195                // Обновляем отображение цены закупки в RUB (если есть элемент для отображения)
 196                var purchasePriceRubElement = $('#PurchasePriceRub_new');
 197                if (purchasePriceRubElement.length) {
 198                    purchasePriceRubElement.text(!isNaN(purchasePriceInRub) ? Math.round(purchasePriceInRub) + ' RUB' : 
 199                }
 200            }
 201        });
 202
 203        // Обработка изменения поставщика для заполнения CurrencyId (скрытое поле)
 204        $('#Order_SupplierId').on('change', function () {
 205            var supplierId = $(this).val();
 206            if (!supplierId) {
 207                $('#Order_СurrencyId').val('');
 208                return;
 209            }
 210
 211            var supplierData = window.suppliersData && window.suppliersData.find(s => s.id == supplierId);
 212            if (!supplierData || !supplierData.currencyCode) {
 213                $('#Order_СurrencyId').val('');
 214                return;
 215            }
 216
 217            // Загружаем Currency по коду через AJAX
 218            $.ajax({
 219                url: '/Studio2/Orders/GetCurrencyByCode',
 220                type: 'GET',
 221                data: {currencyCode: supplierData.currencyCode},
 222                success: function (data) {
 223                    if (data && data.currencyId) {
 224                        $('#Order_СurrencyId').val(data.currencyId);
 225                    }
 226                },
 227                error: function () {
 228                    console.log('Не удалось загрузить Currency для валюты');
 229                }
 230            });
 231        });
 232
 233        // Функция для расчета суммы отправления
 234        function calculateShipmentAmount() {
 235            var price = parseFloat($('#Order_Price').val()) || 0;
 236            var quantity = parseFloat($('#Order_Quantity').val()) || 0;
 237            var shipmentAmount = price * quantity;
 238
 239            $('#Order_ShipmentAmount').val(shipmentAmount > 0 ? shipmentAmount.toFixed(2) : '');
 240        }
 241
 242        // Обработка изменения цены и количества для расчета суммы отправления
 243        $('#Order_Price, #Order_Quantity').on('input change', function () {
 244            calculateShipmentAmount();
 245        });
 246
 247        // Инициализация расчета при загрузке страницы
 248        calculateShipmentAmount();
 249
 250        // Получаем данные о клиентах из Razor View
 0251        window.ozonClientsData = @Html.Raw(Json.Serialize(Model.OzonClients.Select(c => new { c.Id, c.WarehouseName, c.C
 252
 253        // Обработка изменения клиента для загрузки статусов клиента и автозаполнения полей
 254        $('.ozon-client-select').on('change', function () {
 255            var selectedClientId = $(this).val();
 256            var selectedOption = $(this).find('option:selected');
 257            var clientTypeId = selectedOption.data('client-type');
 258            var clientStatusSelect = $('#Order_ClientStatusId');
 259
 260            // Очищаем список статусов
 261            clientStatusSelect.empty();
 262            clientStatusSelect.append('<option value="">Статус клиента</option>');
 263
 264            // Автозаполнение склада и валюты на основе клиента
 265            if (selectedClientId && window.ozonClientsData) {
 266                var selectedClient = window.ozonClientsData.find(c => c.id == selectedClientId);
 267                if (selectedClient) {
 268                    // Автозаполнение склада по WarehouseName клиента
 269                    if (selectedClient.warehouseName) {
 270                        var warehouseSelect = $('#Order_ShipmentWarehouseId');
 271                        var warehouseOptions = warehouseSelect.find('option');
 272                        var matchingWarehouse = warehouseOptions.filter(function () {
 273                            return $(this).text().trim() === selectedClient.warehouseName.trim();
 274                        });
 275                        if (matchingWarehouse.length > 0) {
 276                            warehouseSelect.val(matchingWarehouse.first().val());
 277                        }
 278                    }
 279
 280                    // Автозаполнение валюты по CurrencyCode клиента
 281                    if (selectedClient.currencyCode) {
 282                        $.ajax({
 283                            url: '/Studio2/Orders/GetCurrencyByCode',
 284                            type: 'GET',
 285                            data: {currencyCode: selectedClient.currencyCode},
 286                            success: function (data) {
 287                                if (data && data.success && data.currencyId) {
 288                                    $('#Order_СurrencyId').val(data.currencyId);
 289                                }
 290                            },
 291                            error: function () {
 292                                console.log('Не удалось загрузить валюту для клиента');
 293                            }
 294                        });
 295                    }
 296                }
 297            }
 298
 299            if (clientTypeId !== undefined && clientTypeId !== null) {
 300                // Загружаем статусы клиента напрямую из ClientStatusDataServices по типу клиента
 301                $.ajax({
 302                    url: '/Studio2/Orders/GetClientStatusesByClientType',
 303                    type: 'GET',
 304                    data: {clientTypeId: clientTypeId},
 305                    success: function (data) {
 306                        if (data && data.success && data.statuses) {
 307                            // Заполняем список статусов из ClientStatusDataServices
 308                            data.statuses.forEach(function (status) {
 309                                clientStatusSelect.append(
 310                                    $('<option></option>')
 311                                        .attr('value', status.id)
 312                                        .text(status.name)
 313                                );
 314                            });
 315                        }
 316                    },
 317                    error: function () {
 318                        console.log('Не удалось загрузить статусы клиента из ClientStatusDataServices');
 319                    }
 320                });
 321            }
 322        });
 323
 324        // Автодополнение для производителя (EtProducer)
 325        var etProducerInput = $('#Order_EtProducerName');
 326        var etProducerDropdown = $('#etProducerDropdown');
 327        var etProducerIdField = $('#Order_EtProducerId');
 328        var searchTimeout = null;
 329        var selectedIndex = -1;
 330        var selectedProducerMarketPrefix = ''; // Сохраняем MarketPrefix выбранного производителя
 331        var isShowingArticleSuggestions = false; // Флаг для отслеживания показа предложений по артикулу
 332
 333        function searchEtProducers(query) {
 334            if (query.length < 1) {
 335                etProducerDropdown.hide();
 336                etProducerIdField.val('');
 337                return;
 338            }
 339
 340            clearTimeout(searchTimeout);
 341            searchTimeout = setTimeout(function () {
 342                $.ajax({
 343                    url: '/Studio2/Orders/SearchEtProducers',
 344                    type: 'GET',
 345                    data: {query: query},
 346                    success: function (data) {
 347                        if (data && data.success && data.producers && data.producers.length > 0) {
 348                            etProducerDropdown.empty();
 349                            selectedIndex = -1;
 350
 351                            data.producers.forEach(function (producer) {
 352                                var li = $('<li></li>');
 353                                var a = $('<a></a>')
 354                                    .addClass('dropdown-item')
 355                                    .css({
 356                                        'font-weight': 'normal',
 357                                        'cursor': 'pointer',
 358                                        'padding': '0.375rem 0.75rem'
 359                                    })
 360                                    .html(producer.marketPrefix ?
 361                                        '<strong>' + producer.name + '</strong> <small class="text-muted">(' + producer.
 362                                        producer.name
 363                                    )
 364                                    .on('click', function (e) {
 365                                        e.preventDefault();
 366                                        etProducerInput.val(producer.name);
 367                                        etProducerIdField.val(producer.id);
 368                                        selectedProducerMarketPrefix = producer.marketPrefix || ''; // Сохраняем MarketP
 369                                        etProducerDropdown.hide();
 370                                        selectedIndex = -1;
 371                                        updateProductKey(); // Обновляем ProductKey при выборе производителя
 372                                    })
 373                                    .on('mouseenter', function () {
 374                                        etProducerDropdown.find('a').removeClass('active');
 375                                        $(this).addClass('active');
 376                                        selectedIndex = $(this).parent().index();
 377                                    });
 378                                li.append(a);
 379                                etProducerDropdown.append(li);
 380                            });
 381
 382                            // Позиционируем dropdown относительно поля ввода
 383                            var inputOffset = etProducerInput.offset();
 384                            var inputWidth = etProducerInput.outerWidth();
 385
 386                            etProducerDropdown.css({
 387                                'display': 'block',
 388                                'position': 'fixed',
 389                                'top': (inputOffset.top + etProducerInput.outerHeight()) + 'px',
 390                                'left': inputOffset.left + 'px',
 391                                'width': inputWidth + 'px',
 392                                'z-index': '9999',
 393                                'max-height': '200px',
 394                                'overflow-y': 'auto',
 395                                'background-color': '#fff',
 396                                'border': '1px solid #ced4da',
 397                                'border-radius': '0.25rem',
 398                                'box-shadow': '0 4px 6px rgba(0, 0, 0, 0.1)',
 399                                'list-style': 'none',
 400                                'margin': '0',
 401                                'padding': '0'
 402                            });
 403                        } else {
 404                            etProducerDropdown.hide();
 405                        }
 406                    },
 407                    error: function () {
 408                        console.log('Не удалось выполнить поиск производителей');
 409                        etProducerDropdown.hide();
 410                    }
 411                });
 412            }, 300); // Задержка 300мс для уменьшения количества запросов
 413        }
 414
 415        // Обработчик ввода текста
 416        etProducerInput.on('input', function () {
 417            var value = $(this).val().trim();
 418            selectedIndex = -1;
 419
 420            // Скрываем индикатор загрузки, если пользователь начал вводить
 421            $('#producerLoadingSpinner').hide();
 422
 423            // Если показываются предложения по артикулу и пользователь начал вводить, скрываем их
 424            if (isShowingArticleSuggestions && value.length > 0) {
 425                isShowingArticleSuggestions = false;
 426                etProducerDropdown.empty();
 427            }
 428
 429            // Если пользователь начал вводить производителя, переключаемся на обычный поиск
 430            if (value.length > 0) {
 431                searchEtProducers(value);
 432            } else {
 433                // Если поле пустое, скрываем dropdown
 434                etProducerDropdown.hide();
 435            }
 436        });
 437
 438        // Обработчик фокуса
 439        etProducerInput.on('focus', function () {
 440            var value = $(this).val().trim();
 441            var article = $('#Order_Article').val() || '';
 442            var producerId = etProducerIdField.val();
 443
 444            // Если поле производителя пустое и артикул заполнен - показываем предложения по артикулу
 445            if (!value && !producerId && article.trim()) {
 446                console.log('Focus on producer field with article filled, searching producers by article');
 447                searchProducerByArticle(article.trim());
 448            } else if (value.length >= 1) {
 449                // Если в поле уже есть текст - ищем по нему
 450                searchEtProducers(value);
 451            }
 452        });
 453
 454        // Обработчик клавиатуры для навигации по подсказкам
 455        etProducerInput.on('keydown', function (e) {
 456            var items = etProducerDropdown.find('a');
 457            if (items.length === 0) return;
 458
 459            if (e.key === 'ArrowDown') {
 460                e.preventDefault();
 461                selectedIndex = (selectedIndex < items.length - 1) ? selectedIndex + 1 : 0;
 462                items.removeClass('active');
 463                items.eq(selectedIndex).addClass('active');
 464                etProducerDropdown.scrollTop(items.eq(selectedIndex).position().top + etProducerDropdown.scrollTop() - e
 465            } else if (e.key === 'ArrowUp') {
 466                e.preventDefault();
 467                selectedIndex = (selectedIndex > 0) ? selectedIndex - 1 : items.length - 1;
 468                items.removeClass('active');
 469                items.eq(selectedIndex).addClass('active');
 470                etProducerDropdown.scrollTop(items.eq(selectedIndex).position().top + etProducerDropdown.scrollTop() - e
 471            } else if (e.key === 'Enter') {
 472                e.preventDefault();
 473                if (selectedIndex >= 0 && selectedIndex < items.length) {
 474                    items.eq(selectedIndex).click();
 475                }
 476            } else if (e.key === 'Escape') {
 477                etProducerDropdown.hide();
 478                selectedIndex = -1;
 479            }
 480        });
 481
 482        // Скрываем dropdown при клике вне его
 483        $(document).on('click', function (e) {
 484            if (!$(e.target).closest('.et-producer-autocomplete, #etProducerDropdown').length) {
 485                isShowingArticleSuggestions = false;
 486                etProducerDropdown.hide();
 487                selectedIndex = -1;
 488            }
 489        });
 490
 491        // Обработчик изменения значения вручную (если пользователь ввел текст, но не выбрал из списка)
 492        etProducerInput.on('blur', function () {
 493            var producerName = $(this).val().trim();
 494
 495            // Если производитель введен вручную (не выбран из списка), пытаемся найти его MarketPrefix
 496            if (producerName && !etProducerIdField.val()) {
 497                $.ajax({
 498                    url: '/Studio2/Orders/GetEtProducerMarketPrefix',
 499                    type: 'GET',
 500                    data: {producerName: producerName},
 501                    success: function (data) {
 502                        if (data && data.success && data.marketPrefix) {
 503                            selectedProducerMarketPrefix = data.marketPrefix;
 504                            updateProductKey();
 505                        } else {
 506                            selectedProducerMarketPrefix = '';
 507                            updateProductKey();
 508                        }
 509                    },
 510                    error: function () {
 511                        console.log('Не удалось найти MarketPrefix для производителя');
 512                        selectedProducerMarketPrefix = '';
 513                        updateProductKey();
 514                    }
 515                });
 516            } else if (!producerName) {
 517                selectedProducerMarketPrefix = '';
 518                updateProductKey();
 519            }
 520        });
 521
 522        // Функция для автоматического формирования ProductKey в формате "артикул=код_производителя"
 523        function updateProductKey() {
 524            var article = $('#Order_Article').val() || '';
 525            var marketPrefix = selectedProducerMarketPrefix || '';
 526
 527            if (article && marketPrefix) {
 528                var productKey = article + '=' + marketPrefix;
 529                $('#Order_ProductKey').val(productKey);
 530            } else {
 531                $('#Order_ProductKey').val('');
 532            }
 533        }
 534
 535        // Обработчик изменения артикула для обновления ProductKey
 536        $('#Order_Article').on('input change', function () {
 537            updateProductKey();
 538        });
 539
 540        // Поиск производителя по артикулу, если производитель не заполнен
 541        var articleSearchTimeout = null;
 542        $('#Order_Article').on('input', function () {
 543            var article = $(this).val().trim();
 544            var producerId = etProducerIdField.val();
 545            var producerName = etProducerInput.val().trim();
 546
 547            // Если артикул заполнен, а производитель нет - ищем производителя по артикулу
 548            if (article && !producerId && !producerName) {
 549                clearTimeout(articleSearchTimeout);
 550                articleSearchTimeout = setTimeout(function () {
 551                    searchProducerByArticle(article);
 552                }, 500); // Задержка 500мс для уменьшения количества запросов
 553            }
 554        });
 555
 556        // Функция поиска производителя по артикулу
 557        function searchProducerByArticle(article) {
 558            if (!article || article.length < 2) {
 559                return;
 560            }
 561
 562            // Показываем индикатор загрузки
 563            $('#producerLoadingSpinner').show();
 564
 565            $.ajax({
 566                url: '/Studio2/Orders/GetEtProducersByArticle',
 567                type: 'GET',
 568                data: {article: article},
 569                success: function (data) {
 570                    console.log('GetEtProducersByArticle response:', data);
 571                    // Скрываем индикатор загрузки
 572                    $('#producerLoadingSpinner').hide();
 573
 574                    if (data && data.success && data.producers && data.producers.length > 0) {
 575                        console.log('Found', data.producers.length, 'producers');
 576                        // Проверяем, что производитель все еще не заполнен
 577                        if (!etProducerIdField.val() && !etProducerInput.val().trim()) {
 578                            console.log('Calling showProducerSuggestion');
 579                            showProducerSuggestion(data.producers);
 580                        } else {
 581                            console.log('Producer already filled, not showing suggestions');
 582                        }
 583                        updateProductKey();
 584                    } else {
 585                        console.log('No producers found for article:', article);
 586                    }
 587                },
 588                error: function (xhr, status, error) {
 589                    // Скрываем индикатор загрузки при ошибке
 590                    $('#producerLoadingSpinner').hide();
 591                    console.error('Не удалось найти производителя по артикулу:', error);
 592                    console.error('Response:', xhr.responseText);
 593                }
 594            });
 595        }
 596
 597        // Функция показа предложения выбрать производителя
 598        function showProducerSuggestion(producers) {
 599            console.log('showProducerSuggestion called with:', producers);
 600
 601            // Проверяем, что производитель все еще не заполнен
 602            if (etProducerIdField.val() || etProducerInput.val().trim()) {
 603                console.log('Producer already filled, skipping suggestion');
 604                return;
 605            }
 606
 607            // Устанавливаем флаг, что показываем предложения по артикулу
 608            isShowingArticleSuggestions = true;
 609
 610            // Показываем список производителей в dropdown
 611            etProducerDropdown.empty();
 612            selectedIndex = -1;
 613
 614            // Проверяем, что элементы существуют
 615            if (!etProducerDropdown.length || !etProducerInput.length) {
 616                console.error('Dropdown or input elements not found');
 617                isShowingArticleSuggestions = false;
 618                return;
 619            }
 620
 621            // Добавляем заголовок
 622            var headerLi = $('<li></li>');
 623            var header = $('<div></div>')
 624                .css({
 625                    'padding': '0.5rem 0.75rem',
 626                    'font-size': '0.75rem',
 627                    'font-weight': 'bold',
 628                    'color': '#6c757d',
 629                    'border-bottom': '1px solid #dee2e6'
 630                })
 631                .text('Найдены производители для артикула "' + $('#Order_Article').val() + '":');
 632            headerLi.append(header);
 633            etProducerDropdown.append(headerLi);
 634
 635            producers.forEach(function (producer) {
 636                var li = $('<li></li>');
 637                var a = $('<a></a>')
 638                    .addClass('dropdown-item')
 639                    .css({
 640                        'font-weight': 'normal',
 641                        'cursor': 'pointer',
 642                        'padding': '0.375rem 0.75rem'
 643                    })
 644                    .html('<strong>' + producer.name + '</strong>' +
 645                        (producer.marketPrefix ? ' <small class="text-muted">(' + producer.marketPrefix + ')</small>' : 
 646                        ' <small class="text-info">(' + producer.orderCount + ' заказов)</small>')
 647                    .on('click', function (e) {
 648                        e.preventDefault();
 649                        e.stopPropagation(); // Останавливаем всплытие события
 650                        etProducerInput.val(producer.name);
 651                        etProducerIdField.val(producer.id);
 652                        selectedProducerMarketPrefix = producer.marketPrefix || '';
 653
 654                        // Заполняем ProductName, если он есть
 655                        if (producer.productName) {
 656                            $('#Order_ProductName').val(producer.productName);
 657                            console.log('ProductName filled:', producer.productName);
 658                        }
 659
 660                        isShowingArticleSuggestions = false;
 661                        etProducerDropdown.hide();
 662                        selectedIndex = -1;
 663                        updateProductKey();
 664                        console.log('Producer selected:', producer.name, 'ID:', producer.id);
 665                    })
 666                    .on('mouseenter', function () {
 667                        etProducerDropdown.find('a').removeClass('active');
 668                        $(this).addClass('active');
 669                        selectedIndex = $(this).parent().index();
 670                    });
 671                li.append(a);
 672                etProducerDropdown.append(li);
 673            });
 674
 675            // Показываем dropdown и устанавливаем правильное позиционирование относительно поля ввода
 676            var inputOffset = etProducerInput.offset();
 677            var inputWidth = etProducerInput.outerWidth();
 678
 679            etProducerDropdown.css({
 680                'display': 'block',
 681                'position': 'fixed',
 682                'top': (inputOffset.top + etProducerInput.outerHeight()) + 'px',
 683                'left': inputOffset.left + 'px',
 684                'width': inputWidth + 'px',
 685                'z-index': '9999',
 686                'max-height': '200px',
 687                'overflow-y': 'auto',
 688                'background-color': '#fff',
 689                'border': '1px solid #ced4da',
 690                'border-radius': '0.25rem',
 691                'box-shadow': '0 4px 6px rgba(0, 0, 0, 0.1)',
 692                'list-style': 'none',
 693                'margin': '0',
 694                'padding': '0'
 695            });
 696
 697            console.log('Dropdown shown with', producers.length, 'producers');
 698            console.log('Dropdown element:', etProducerDropdown);
 699            console.log('Dropdown is visible:', etProducerDropdown.is(':visible'));
 700            console.log('Dropdown display:', etProducerDropdown.css('display'));
 701            console.log('Dropdown items count:', etProducerDropdown.find('li').length);
 702
 703            // Показываем подсказку пользователю
 704            if (etProducerInput.length) {
 705                etProducerInput.attr('placeholder', 'Выберите производителя из списка ниже');
 706                setTimeout(function () {
 707                    etProducerInput.attr('placeholder', 'Производитель');
 708                }, 5000);
 709            }
 710        }
 711
 712        // Инициализация ProductKey при загрузке страницы
 713        updateProductKey();
 714
 715        // Проверка уникальности заказа по ShipmentNumber + ProductKey
 716        var uniquenessCheckTimeout = null;
 717        var lastCheckedKey = '';
 718
 719        function checkOrderUniqueness() {
 720            var shipmentNumber = $('#Order_ShipmentNumber').val() || '';
 721            var productKey = $('#Order_ProductKey').val() || '';
 722
 723            // Проверяем только если оба поля заполнены
 724            if (!shipmentNumber.trim() || !productKey.trim()) {
 725                // Очищаем сообщение об ошибке, если поля не заполнены
 726                $('#Order_ShipmentNumber').removeClass('is-invalid');
 727                $('#shipmentNumberUniquenessMessage').remove();
 728                return;
 729            }
 730
 731            // Формируем ключ для проверки
 732            var checkKey = shipmentNumber.trim() + productKey.trim();
 733
 734            // Пропускаем проверку, если ключ не изменился
 735            if (checkKey === lastCheckedKey) {
 736                return;
 737            }
 738
 739            lastCheckedKey = checkKey;
 740
 741            clearTimeout(uniquenessCheckTimeout);
 742            uniquenessCheckTimeout = setTimeout(function () {
 743                $.ajax({
 744                    url: '/Studio2/Orders/CheckOrderUnique',
 745                    type: 'GET',
 746                    data: {
 747                        shipmentNumber: shipmentNumber.trim(),
 748                        productKey: productKey.trim()
 749                    },
 750                    success: function (data) {
 751                        // Удаляем предыдущее сообщение
 752                        $('#shipmentNumberUniquenessMessage').remove();
 753                        $('#Order_ShipmentNumber').removeClass('is-invalid');
 754
 755                        if (data && data.success) {
 756                            if (!data.isUnique) {
 757                                // Заказ уже существует
 758                                $('#Order_ShipmentNumber').addClass('is-invalid');
 759                                var messageDiv = $('<div></div>')
 760                                    .attr('id', 'shipmentNumberUniquenessMessage')
 761                                    .addClass('text-danger small mt-1')
 762                                    .text(data.message || 'Заказ с таким номером отправления и ключом продукта уже сущес
 763                                $('#Order_ShipmentNumber').closest('.d-flex').append(messageDiv);
 764                                console.warn('Order uniqueness check failed:', data.message);
 765                            } else {
 766                                console.log('Order is unique');
 767                            }
 768                        }
 769                    },
 770                    error: function (xhr, status, error) {
 771                        console.error('Не удалось проверить уникальность заказа:', error);
 772                    }
 773                });
 774            }, 500); // Задержка 500мс для уменьшения количества запросов
 775        }
 776
 777        // Обработчики для проверки уникальности
 778        $('#Order_ShipmentNumber, #Order_ProductKey').on('input change blur', function () {
 779            checkOrderUniqueness();
 780        });
 781
 782        // Также проверяем при изменении ProductKey через updateProductKey
 783        var originalUpdateProductKey = updateProductKey;
 784        updateProductKey = function () {
 785            originalUpdateProductKey();
 786            checkOrderUniqueness();
 787        };
 788
 789        // Валидация дат: ProcessingDate должна быть меньше ShippingDate
 790        function validateDates() {
 791            var processingDate = $('#Order_ProcessingDate').val();
 792            var shippingDate = $('#Order_ShippingDate').val();
 793
 794            // Удаляем предыдущие сообщения об ошибке
 795            $('#dateValidationMessage').remove();
 796            $('#Order_ProcessingDate, #Order_ShippingDate').removeClass('is-invalid');
 797
 798            // Проверяем только если обе даты заполнены
 799            if (processingDate && shippingDate) {
 800                var processing = new Date(processingDate);
 801                var shipping = new Date(shippingDate);
 802
 803                if (processing >= shipping) {
 804                    // Дата принятия должна быть меньше даты отгрузки
 805                    $('#Order_ProcessingDate, #Order_ShippingDate').addClass('is-invalid');
 806                    var messageDiv = $('<div></div>')
 807                        .attr('id', 'dateValidationMessage')
 808                        .addClass('text-danger small mt-1')
 809                        .text('Дата принятия должна быть меньше даты отгрузки');
 810                    $('#Order_ShippingDate').closest('.d-flex').append(messageDiv);
 811                    return false;
 812                }
 813            }
 814            return true;
 815        }
 816
 817        // Обработчики для валидации дат
 818        $('#Order_ProcessingDate, #Order_ShippingDate').on('input change blur', function () {
 819            validateDates();
 820        });
 821
 822        // Валидация перед отправкой формы
 823        $('#createOrderForm').on('submit', function (e) {
 824            if (!validateDates()) {
 825                e.preventDefault();
 826                alert('Дата принятия должна быть меньше даты отгрузки');
 827                return false;
 828            }
 829        });
 830
 831        // Автоматическое копирование значения из "Цена" в "Цена с." (CurrentPriceWithDiscount)
 832        $('#Order_Price').on('input change', function () {
 833            var priceValue = $(this).val();
 834            var priceField = $('input[name="Order.ProductInfo.CurrentPriceWithDiscount"]');
 835            if (priceValue && priceField.length) {
 836                priceField.val(priceValue);
 837            }
 838        });
 839
 840        // Автозаполнение категории и веса из ProductInfo при заполнении ProductKey
 841        $('#Order_ProductKey').on('change blur', function () {
 842            var productKey = $(this).val();
 843            if (!productKey) return;
 844
 845            // Извлекаем артикул из ProductKey
 846            var article = productKey.split('=')[0].trim();
 847            if (!article) return;
 848
 849            // Ищем продукт по артикулу через AJAX
 850            $.ajax({
 851                url: '/Studio2/Orders/GetProductByArticle',
 852                type: 'GET',
 853                data: {article: article},
 854                success: function (data) {
 855                    if (data && data.success && data.product) {
 856                        // Заполняем категорию
 857                        if (data.product.commercialCategory) {
 858                            $('input[name="Order.ProductInfo.CommercialCategory"]').val(data.product.commercialCategory)
 859                        }
 860                        // Заполняем объемный вес
 861                        if (data.product.volumetricWeight) {
 862                            $('input[name="Order.ProductInfo.VolumetricWeight"]').val(data.product.volumetricWeight);
 863                        }
 864                        // Заполняем цену сайта, если она есть
 865                        if (data.product.currentPriceWithDiscount) {
 866                            $('input[name="Order.ProductInfo.CurrentPriceWithDiscount"]').val(data.product.currentPriceW
 867                        }
 868                    }
 869                },
 870                error: function () {
 871                    console.log('Не удалось загрузить данные продукта');
 872                }
 873            });
 874        });
 875
 876        // Функции для работы с localStorage
 877        function saveToLocalStorage(key, value) {
 878            try {
 879                localStorage.setItem('createOrder_' + key, value);
 880            } catch (e) {
 881                console.error('Ошибка сохранения в localStorage:', e);
 882            }
 883        }
 884
 885        function loadFromLocalStorage(key) {
 886            try {
 887                return localStorage.getItem('createOrder_' + key) || '';
 888            } catch (e) {
 889                console.error('Ошибка чтения из localStorage:', e);
 890                return '';
 891            }
 892        }
 893
 894        // Сохранение и загрузка значений из localStorage для всех полей
 895        var fieldsToSave = [
 896            'Order_ShipmentNumber', 'Order_DeliveryId', 'Order_OzonClientId', 'Order_DeliveryCity',
 897            'Order_ProcessingDate', 'Order_ShippingDate', 'Order_ProductKey', 'Order_EtProducerId',
 898            'Order_EtProducerName', 'Order_Article', 'Order_ProductName', 'Order_ClientStatusId', 'Order_AppStatusId',
 899            'Order_ShipmentWarehouseId', 'Order_ProductInfo_CommercialCategory',
 900            'Order_ProductInfo_VolumetricWeight', 'Order_ProductInfo_CurrentPriceWithDiscount',
 901            'Order_Quantity', 'Order_Price', 'Order_MinOzonCommission', 'Order_MaxOzonCommission'
 902        ];
 903
 904        // Загрузка сохраненных значений при загрузке страницы
 905        fieldsToSave.forEach(function (fieldId) {
 906            var field = $('#' + fieldId);
 907            if (field.length) {
 908                var savedValue = loadFromLocalStorage(fieldId);
 909                if (savedValue) {
 910                    if (field.is('select')) {
 911                        field.val(savedValue);
 912                    } else {
 913                        field.val(savedValue);
 914                    }
 915                    // Триггерим событие change для обновления зависимых полей
 916                    field.trigger('change');
 917                }
 918            }
 919        });
 920
 921        // Сохранение значений при изменении полей
 922        fieldsToSave.forEach(function (fieldId) {
 923            var field = $('#' + fieldId);
 924            if (field.length) {
 925                field.on('input change', function () {
 926                    saveToLocalStorage(fieldId, $(this).val() || '');
 927                });
 928            }
 929        });
 930
 931        // Специальная обработка для поля производителя (текстовое поле)
 932        $('#Order_EtProducerName').on('input change blur', function () {
 933            saveToLocalStorage('Order_EtProducerName', $(this).val() || '');
 934        });
 935
 936        // Загрузка сохраненного производителя при загрузке страницы
 937        var savedProducerName = loadFromLocalStorage('Order_EtProducerName');
 938        if (savedProducerName) {
 939            $('#Order_EtProducerName').val(savedProducerName);
 940        }
 941
 942        // Функция вычисления срока доставки и оставшегося времени
 943        function calculateDeliveryPeriodAndTimeLeft() {
 944            var processingDate = $('#Order_ProcessingDate').val();
 945            var shippingDate = $('#Order_ShippingDate').val();
 946
 947            var deliveryPeriodDisplay = $('#deliveryPeriodDisplay');
 948            var timeLeftDisplay = $('#timeLeftDisplay');
 949
 950            // Вычисление срока доставки (DeliveryPeriod)
 951            if (processingDate && shippingDate) {
 952                var processing = new Date(processingDate);
 953                var shipping = new Date(shippingDate);
 954
 955                if (shipping >= processing) {
 956                    var diff = shipping - processing;
 957                    var days = Math.floor(diff / (1000 * 60 * 60 * 24));
 958                    var hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
 959                    var minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
 960
 961                    var periodText = days + ' д.';
 962                    deliveryPeriodDisplay.html('<span>' + periodText + '</span>');
 963                } else {
 964                    deliveryPeriodDisplay.html('<span class="text-danger">-</span>');
 965                }
 966            } else {
 967                deliveryPeriodDisplay.html('<span class="text-muted">-</span>');
 968            }
 969
 970            // Вычисление оставшегося времени (TimeLeft)
 971            if (shippingDate) {
 972                var shipping = new Date(shippingDate);
 973                var now = new Date();
 974                var diff = shipping - now;
 975
 976                if (diff > 0) {
 977                    var days = Math.floor(diff / (1000 * 60 * 60 * 24));
 978                    var hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
 979
 980                    var timeLeftText = days + ' д.';
 981                    if (days < 0) {
 982                        timeLeftDisplay.html('<span class="text-danger">Просрочено</span>');
 983                    } else if (days === 0) {
 984                        timeLeftDisplay.html('<span class="text-warning">Сегодня</span>');
 985                    } else {
 986                        timeLeftDisplay.html('<span>' + timeLeftText + '</span>');
 987                    }
 988                } else {
 989                    timeLeftDisplay.html('<span class="text-danger">Просрочено</span>');
 990                }
 991            } else {
 992                timeLeftDisplay.html('<span class="text-muted">-</span>');
 993            }
 994        }
 995
 996        // Обновление отображения срока доставки и оставшегося времени при изменении дат
 997        $('#Order_ProcessingDate, #Order_ShippingDate').on('input change', function () {
 998            calculateDeliveryPeriodAndTimeLeft();
 999            validateDates();
 1000        });
 1001
 1002        // Инициализация при загрузке страницы
 1003        calculateDeliveryPeriodAndTimeLeft();
 1004
 1005        // Предотвращение отправки формы по Enter в полях ввода
 1006        $('#createOrderForm').on('keydown', 'input, select, textarea', function (e) {
 1007            if (e.key === 'Enter' || e.keyCode === 13) {
 1008                // Если это не кнопка отправки, предотвращаем отправку формы
 1009                if (!$(e.target).is('button[type="submit"], input[type="submit"]')) {
 1010                    e.preventDefault();
 1011                    // Переходим к следующему полю
 1012                    var fields = $('#createOrderForm').find('input, select, textarea').not(':disabled, :hidden');
 1013                    var index = fields.index(this);
 1014                    if (index < fields.length - 1) {
 1015                        fields.eq(index + 1).focus();
 1016                    }
 1017                    return false;
 1018                }
 1019            }
 1020        });
 1021
 1022        // Обновление индикатора заполненности для обязательных полей
 1023        function updateFieldIndicator(fieldId) {
 1024            var field = $('#' + fieldId);
 1025            if (field.length && field.attr('required')) {
 1026                var value = field.val();
 1027                if (value && value !== '') {
 1028                    field.addClass('field-filled');
 1029                } else {
 1030                    field.removeClass('field-filled');
 1031                }
 1032            }
 1033        }
 1034
 1035        // Обновление индикатора для поля производителя (скрытое поле)
 1036        function updateProducerIndicator() {
 1037            var producerName = $('#Order_EtProducerName').val();
 1038            var producerId = $('#Order_EtProducerId').val();
 1039            var producerField = $('#Order_EtProducerName');
 1040
 1041            if (producerName && producerName.trim() !== '' && producerId && producerId !== '') {
 1042                producerField.addClass('field-filled');
 1043            } else {
 1044                producerField.removeClass('field-filled');
 1045            }
 1046        }
 1047
 1048        // Отслеживание изменений для обновления индикаторов
 1049        $('#createOrderForm').find('input[required], select[required]').on('input change blur', function () {
 1050            updateFieldIndicator($(this).attr('id'));
 1051        });
 1052
 1053        // Специальная обработка для поля производителя
 1054        $('#Order_EtProducerName, #Order_EtProducerId').on('input change blur', function () {
 1055            updateProducerIndicator();
 1056        });
 1057
 1058        // Инициализация индикаторов при загрузке страницы
 1059        $('#createOrderForm').find('input[required], select[required]').each(function () {
 1060            updateFieldIndicator($(this).attr('id'));
 1061        });
 1062        updateProducerIndicator();
 1063
 1064        // Валидация всех полей перед отправкой формы
 1065        $('#createOrderForm').on('submit', function (e) {
 1066            e.preventDefault();
 1067
 1068            var errors = [];
 1069            var form = $(this);
 1070
 1071            // Проверка обязательных полей
 1072            form.find('[required]').each(function () {
 1073                var field = $(this);
 1074                var value = field.val();
 1075
 1076                if (!value || (field.is('select') && value === '')) {
 1077                    var fieldName = field.attr('title') || field.attr('placeholder') || field.attr('name');
 1078                    errors.push('Поле "' + fieldName + '" обязательно для заполнения');
 1079                    field.addClass('is-invalid');
 1080                } else {
 1081                    field.removeClass('is-invalid');
 1082                }
 1083            });
 1084
 1085            // Специальная проверка для поля производителя
 1086            var producerName = $('#Order_EtProducerName').val();
 1087            var producerId = $('#Order_EtProducerId').val();
 1088            if (!producerName || producerName.trim() === '' || !producerId || producerId === '') {
 1089                errors.push('Поле "Производитель" обязательно для заполнения');
 1090                $('#Order_EtProducerName').addClass('is-invalid');
 1091            } else {
 1092                $('#Order_EtProducerName').removeClass('is-invalid');
 1093            }
 1094
 1095            // Проверка дат
 1096            if (!validateDates()) {
 1097                errors.push('Дата принятия должна быть меньше даты отгрузки');
 1098            }
 1099
 1100            // Проверка уникальности заказа
 1101            var shipmentNumber = $('#Order_ShipmentNumber').val();
 1102            var productKey = $('#Order_ProductKey').val();
 1103            if (shipmentNumber && productKey) {
 1104                // Проверка уникальности выполняется асинхронно, поэтому нужно проверить наличие ошибки
 1105                var uniquenessMessage = $('#shipmentNumberUniquenessMessage');
 1106                if (uniquenessMessage.length && uniquenessMessage.is(':visible')) {
 1107                    errors.push(uniquenessMessage.text());
 1108                }
 1109            }
 1110
 1111            // Если есть ошибки, показываем их все сразу
 1112            if (errors.length > 0) {
 1113                // Удаляем предыдущие сообщения об ошибках
 1114                $('#validationErrors').remove();
 1115
 1116                var errorHtml = '<div id="validationErrors" class="alert alert-danger mt-3"><strong>Обнаружены ошибки:</
 1117                errors.forEach(function (error) {
 1118                    errorHtml += '<li>' + error + '</li>';
 1119                });
 1120                errorHtml += '</ul></div>';
 1121
 1122                // Вставляем сообщения об ошибках перед кнопками
 1123                $('.form-group.mt-3').before(errorHtml);
 1124
 1125                // Прокручиваем к ошибкам
 1126                $('html, body').animate({
 1127                    scrollTop: $('#validationErrors').offset().top - 100
 1128                }, 500);
 1129
 1130                return false;
 1131            }
 1132
 1133            // Если ошибок нет, показываем модальное окно предпросмотра
 1134            showOrderPreview();
 1135            return false;
 1136        });
 1137
 1138        // Обработчик для кнопки подтверждения в модальном окне
 1139        $('#confirmCreateOrder').on('click', function () {
 1140            $('#orderPreviewModal').modal('hide');
 1141            // Отправляем форму после закрытия модального окна
 1142            setTimeout(function () {
 1143                $('#createOrderForm').off('submit').submit();
 1144            }, 300);
 1145        });
 1146
 1147        // Кастомный dropdown для статусов
 1148        var appStatusDropdown = $('#appStatusDropdown');
 1149        var appStatusCustomSelect = $('#appStatusCustomSelect');
 1150        var appStatusSelectedText = $('#appStatusSelectedText');
 1151        var appStatusHiddenInput = $('#Order_AppStatusId');
 1152
 1153        // Функция для позиционирования dropdown
 1154        function positionAppStatusDropdown() {
 1155            var selectOffset = appStatusCustomSelect.offset();
 1156            var selectWidth = appStatusCustomSelect.outerWidth();
 1157
 1158            appStatusDropdown.css({
 1159                'top': (selectOffset.top + appStatusCustomSelect.outerHeight() + 2) + 'px',
 1160                'left': selectOffset.left + 'px',
 1161                'min-width': selectWidth + 'px'
 1162            });
 1163        }
 1164
 1165        // Открытие/закрытие dropdown
 1166        appStatusCustomSelect.on('click', function (e) {
 1167            e.stopPropagation();
 1168            if (appStatusDropdown.is(':visible')) {
 1169                appStatusDropdown.hide();
 1170            } else {
 1171                positionAppStatusDropdown();
 1172                appStatusDropdown.show();
 1173            }
 1174        });
 1175
 1176        // Выбор опции из dropdown
 1177        appStatusDropdown.find('li a').on('click', function (e) {
 1178            e.preventDefault();
 1179            e.stopPropagation();
 1180            var link = $(this);
 1181            var value = link.data('value');
 1182            var bgColor = link.data('color') || '#ffffff';
 1183            var statusName = link.data('status-name') || link.text().trim();
 1184
 1185            // Определяем контрастный цвет текста
 1186            var textColor = getContrastColor(bgColor);
 1187
 1188            // Устанавливаем значение в скрытое поле
 1189            appStatusHiddenInput.val(value || '');
 1190
 1191            // Обновляем отображение
 1192            if (value && value !== '') {
 1193                appStatusSelectedText.html('<span style="background-color: ' + bgColor + '; color: ' + textColor + '; pa
 1194                appStatusCustomSelect.addClass('field-filled');
 1195            } else {
 1196                appStatusSelectedText.text('Статус');
 1197                appStatusCustomSelect.removeClass('field-filled');
 1198            }
 1199
 1200            // Закрываем dropdown
 1201            appStatusDropdown.hide();
 1202
 1203            // Триггерим событие change для валидации
 1204            appStatusHiddenInput.trigger('change');
 1205        });
 1206
 1207        // Закрытие dropdown при клике вне его
 1208        $(document).on('click', function (e) {
 1209            if (!$(e.target).closest('#appStatusCustomSelect, #appStatusDropdown').length) {
 1210                appStatusDropdown.hide();
 1211            }
 1212        });
 1213
 1214        // Функция для определения контрастного цвета текста
 1215        function getContrastColor(hexColor) {
 1216            if (!hexColor || hexColor === 'transparent') return '#000000';
 1217
 1218            hexColor = hexColor.trim().toLowerCase();
 1219            if (!hexColor.startsWith('#')) return '#000000';
 1220
 1221            hexColor = hexColor.substring(1);
 1222            if (hexColor.length === 3) {
 1223                hexColor = hexColor[0] + hexColor[0] + hexColor[1] + hexColor[1] + hexColor[2] + hexColor[2];
 1224            }
 1225
 1226            try {
 1227                var r = parseInt(hexColor.substring(0, 2), 16);
 1228                var g = parseInt(hexColor.substring(2, 4), 16);
 1229                var b = parseInt(hexColor.substring(4, 6), 16);
 1230                var luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
 1231                return luminance > 0.5 ? '#000000' : '#ffffff';
 1232            } catch (e) {
 1233                return '#000000';
 1234            }
 1235        }
 1236
 1237        // Инициализация отображения статуса при загрузке
 1238        var savedStatusId = appStatusHiddenInput.val();
 1239        if (savedStatusId) {
 1240            var savedLink = appStatusDropdown.find('li a[data-value="' + savedStatusId + '"]');
 1241            if (savedLink.length) {
 1242                var bgColor = savedLink.data('color') || '#ffffff';
 1243                var textColor = getContrastColor(bgColor);
 1244                var statusName = savedLink.data('status-name') || savedLink.text().trim();
 1245                appStatusSelectedText.html('<span style="background-color: ' + bgColor + '; color: ' + textColor + '; pa
 1246                appStatusCustomSelect.addClass('field-filled');
 1247            }
 1248        } else {
 1249            // Если статус не установлен, пытаемся найти "Не указан" и установить его по умолчанию
 1250            var defaultStatusLink = appStatusDropdown.find('li a[data-status-name="Не указан"]');
 1251            if (defaultStatusLink.length) {
 1252                var defaultStatusId = defaultStatusLink.data('value');
 1253                var defaultBgColor = defaultStatusLink.data('color') || '#ffffff';
 1254                var defaultTextColor = getContrastColor(defaultBgColor);
 1255                var defaultStatusName = defaultStatusLink.data('status-name') || 'Не указан';
 1256
 1257                appStatusHiddenInput.val(defaultStatusId);
 1258                appStatusSelectedText.html('<span style="background-color: ' + defaultBgColor + '; color: ' + defaultTex
 1259                appStatusCustomSelect.addClass('field-filled');
 1260            }
 1261        }
 1262
 1263        // Функция для показа предпросмотра заказа
 1264        function showOrderPreview() {
 1265            // Получаем значения из формы
 1266            var shipmentNumber = $('#Order_ShipmentNumber').val() || '-';
 1267            var deliveryText = $('#Order_DeliveryId option:selected').text() || '-';
 1268            var clientText = $('#Order_OzonClientId option:selected').text() || '-';
 1269            var deliveryCity = $('#Order_DeliveryCity').val() || '-';
 1270            var processingDate = $('#Order_ProcessingDate').val() || '-';
 1271            var shippingDate = $('#Order_ShippingDate').val() || '-';
 1272            var deliveryPeriod = $('#deliveryPeriodDisplay').text().trim() || '-';
 1273            var timeLeft = $('#timeLeftDisplay').text().trim() || '-';
 1274            var productKey = $('#Order_ProductKey').val() || '-';
 1275            var etProducer = $('#Order_EtProducerName').val() || '-';
 1276            var article = $('#Order_Article').val() || '-';
 1277            var productName = $('#Order_ProductName').val() || '-';
 1278            var clientStatus = $('#Order_ClientStatusId option:selected').text() || '-';
 1279            var appStatusId = $('#Order_AppStatusId').val();
 1280            var appStatus = '-';
 1281            if (appStatusId) {
 1282                var statusLink = $('#appStatusDropdown').find('li a[data-value="' + appStatusId + '"]');
 1283                if (statusLink.length) {
 1284                    appStatus = statusLink.data('status-name') || statusLink.text().trim();
 1285                }
 1286            }
 1287            var warehouse = $('#Order_ShipmentWarehouseId option:selected').text() || '-';
 1288            var category = $('#Order_ProductInfo_CommercialCategory').val() || '-';
 1289            var volumetricWeight = $('#Order_ProductInfo_VolumetricWeight').val() || '-';
 1290            var quantity = $('#Order_Quantity').val() || '-';
 1291            var price = $('#Order_Price').val() || '-';
 1292            var currentPrice = $('#Order_ProductInfo_CurrentPriceWithDiscount').val() || '-';
 1293            var shipmentAmount = $('#Order_ShipmentAmount').val() || '-';
 1294            var minCommission = $('#Order_MinOzonCommission').val() || '-';
 1295            var maxCommission = $('#Order_MaxOzonCommission').val() || '-';
 1296
 1297            // Форматируем даты
 1298            if (processingDate !== '-') {
 1299                var procDate = new Date(processingDate);
 1300                processingDate = procDate.toLocaleString('ru-RU');
 1301            }
 1302            if (shippingDate !== '-') {
 1303                var shipDate = new Date(shippingDate);
 1304                shippingDate = shipDate.toLocaleString('ru-RU');
 1305            }
 1306
 1307            // Заполняем модальное окно
 1308            $('#preview_ShipmentNumber').text(shipmentNumber);
 1309            $('#preview_Delivery').text(deliveryText);
 1310            $('#preview_OzonClient').text(clientText);
 1311            $('#preview_DeliveryCity').text(deliveryCity);
 1312            $('#preview_ProcessingDate').text(processingDate);
 1313            $('#preview_ShippingDate').text(shippingDate);
 1314            $('#preview_DeliveryPeriod').text(deliveryPeriod);
 1315            $('#preview_TimeLeft').text(timeLeft);
 1316            $('#preview_ProductKey').text(productKey);
 1317            $('#preview_EtProducer').text(etProducer);
 1318            $('#preview_Article').text(article);
 1319            $('#preview_ProductName').text(productName);
 1320            $('#preview_ClientStatus').text(clientStatus);
 1321
 1322            // Отображаем статус заказа с цветом
 1323            var appStatusId = $('#Order_AppStatusId').val();
 1324            var appStatusHtml = appStatus;
 1325            if (appStatusId && appStatusId !== '') {
 1326                var statusLink = $('#appStatusDropdown').find('li a[data-value="' + appStatusId + '"]');
 1327                if (statusLink.length) {
 1328                    var bgColor = statusLink.data('color') || '#ffffff';
 1329                    var textColor = getContrastColor(bgColor);
 1330                    appStatusHtml = '<span style="background-color: ' + bgColor + '; color: ' + textColor + '; padding: 
 1331                }
 1332            }
 1333            $('#preview_AppStatus').html(appStatusHtml);
 1334
 1335            $('#preview_ShipmentWarehouse').text(warehouse);
 1336            $('#preview_CommercialCategory').text(category);
 1337            $('#preview_VolumetricWeight').text(volumetricWeight);
 1338            $('#preview_Quantity').text(quantity);
 1339            $('#preview_Price').text(price);
 1340            $('#preview_CurrentPriceWithDiscount').text(currentPrice);
 1341            $('#preview_ShipmentAmount').text(shipmentAmount);
 1342            $('#preview_MinOzonCommission').text(minCommission);
 1343            $('#preview_MaxOzonCommission').text(maxCommission);
 1344
 1345            // Показываем модальное окно
 1346            var modal = new bootstrap.Modal(document.getElementById('orderPreviewModal'));
 1347            modal.show();
 1348        }
 1349    });
 1350
 1351    // Функция для установки сегодняшней даты
 1352    function setDateToday(fieldId) {
 1353        var now = new Date();
 1354        var year = now.getFullYear();
 1355        var month = String(now.getMonth() + 1).padStart(2, '0');
 1356        var day = String(now.getDate()).padStart(2, '0');
 1357        var hours = String(now.getHours()).padStart(2, '0');
 1358        var minutes = String(now.getMinutes()).padStart(2, '0');
 1359        var dateTimeString = year + '-' + month + '-' + day + 'T' + hours + ':' + minutes;
 1360        $('#' + fieldId).val(dateTimeString);
 1361
 1362        // Триггерим событие change для валидации и обновления расчетов
 1363        $('#' + fieldId).trigger('change');
 1364    }
 1365</script>
 1366

Methods/Properties

ExecuteAsync()