< Summary

Information
Class: AspNetCoreGeneratedDocument.Areas_Studio2_Views_ShippedToSellerTransaction_CreateShippedToSellerTransaction
Assembly: OzonOrdersWeb
File(s): /home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Areas/Studio2/Views/ShippedToSellerTransaction/CreateShippedToSellerTransaction.cshtml
Line coverage
0%
Covered lines: 0
Uncovered lines: 40
Coverable lines: 40
Total lines: 558
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 52
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
ExecuteAsync()0%1332360%
<ExecuteAsync()0%342180%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Areas/Studio2/Views/ShippedToSellerTransaction/CreateShippedToSellerTransaction.cshtml

#LineLine coverage
 1@using OzonOrdersWeb.Areas.Studio2.Helpers
 2@using OzonDomains.Models
 3@using OzonOrdersWeb.ViewModels.OrderViewModels
 4
 5@model MultiplayEditOrderViewModel
 6
 7@{
 08    var viewModel = Model!;
 09    var ordersCount = Model?.Orders?.Count ?? 0;
 010    var orders = Model?.Orders ?? new List<OzonDomains.Models.Order>();
 011    ViewData["Title"] = $"Отгружен продавцу ({ordersCount} заказов)";
 012    Layout = "~/Views/Shared/_Layout.cshtml";
 013    var transitGroups = ViewData["TransitWarehouseGroups"] as List<TransitWarehouseDisplayInfo>;
 014    var anyFound = transitGroups?.Any(g => g.FoundIn1C) ?? false;
 015    var orderInfoMapRaw = ViewData["OrderInfoMap"];
 016    var senderByOrderId = ViewData["StockCheckSenderByOrderId"] as IDictionary<int, string>;
 017    var senderByOrderIdJson = senderByOrderId != null && senderByOrderId.Count > 0
 018        ? Newtonsoft.Json.JsonConvert.SerializeObject(
 019            senderByOrderId.ToDictionary(kv => kv.Key.ToString(), kv => kv.Value))
 020        : "{}";
 021    var zasylOptionsJson = ViewData["ZasylSenderOptionsByOrderId"] != null
 022        ? Newtonsoft.Json.JsonConvert.SerializeObject(
 023            ViewData["ZasylSenderOptionsByOrderId"],
 024            new Newtonsoft.Json.JsonSerializerSettings
 025            {
 026                ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver()
 027            })
 028        : "{}";
 029    var warehouseMappingCreateUrl = Url.Action("Create", "WarehouseMapping", new { area = "Studio2" });
 30}
 31
 32<partial name="~/Areas/Studio2/Views/Partials/Transaction/_TransactionPageStyles.cshtml"/>
 33<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
 34<script src="~/js/Studio2/Orders/CreateOrderToSupplierTransactionV2/generateInfoRow.js"></script>
 35<script>window.fillPriceFromWarehouseStock = true;</script>
 36
 37<div id="loadingSpinner" class="spinner-overlay" style="display: none;">
 38    <div class="spinner-border text-primary" role="status">
 39        <span class="sr-only"></span>
 40    </div>
 41</div>
 42
 43<div id="messageContainer" class="position-fixed top-0 end-0 p-3" style="z-index: 1050;">
 44    <div id="flashMessage" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
 45        <div class="toast-header">
 46            <strong class="me-auto">Сообщение</strong>
 47            <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
 48        </div>
 49        <div class="toast-body">
 50            <span id="flashMessageText"></span>
 51        </div>
 52    </div>
 53</div>
 54
 55<div class="modal fade" id="cartModal" tabindex="-1" aria-labelledby="cartModalLabel" aria-hidden="true">
 56    <div class="modal-dialog modal-lg modal-dialog-scrollable">
 57        <div class="modal-content rounded-3 shadow">
 58            <div class="modal-header">
 59                <h5 class="modal-title" id="cartModalLabel">Корзина</h5>
 60                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Закрыть"></button>
 61            </div>
 62            <div class="modal-body" id="cartModalBody">
 63            </div>
 64            <div class="modal-footer">
 65                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button>
 66            </div>
 67        </div>
 68    </div>
 69</div>
 70
 071@if (orders.Count > 0)
 72{
 73    <form asp-area="Studio2" asp-controller="ShippedToSellerTransaction" asp-action="CreateShippedToSellerTransaction"
 74          id="createOrderForm">
 75        <div asp-validation-summary="ModelOnly" class="text-danger"></div>
 76        <input type="hidden" asp-for="RedirectPage"/>
 77        <input type="hidden" asp-for="TrackingKey"/>
 78
 079        @for (var i = 0; i < orders.Count; i++)
 80        {
 81            <input type="hidden"
 82                   name="manufacturerByOrderId[@orders[i].Id]"
 83                   value="@(orders[i].EtProducer?.Name ?? "")"/>
 84        }
 85
 86        @* Склад списания в 1С: засыл перебивает склад отгрузки, поэтому показываем,
 87           с какого склада реально уйдёт перемещение. *@
 88        <div id="zasylSenderNotice" class="tx-zasyl-notice" role="status" style="display:none;">
 89            <i class="fas fa-truck-ramp-box tx-zasyl-notice__icon" aria-hidden="true"></i>
 90            <div class="tx-zasyl-notice__body">
 91                <div class="tx-zasyl-notice__title">Списание в 1С пойдёт со склада засыла</div>
 92                <div class="tx-zasyl-notice__chips" id="zasylSenderChips"></div>
 93                <div class="tx-zasyl-notice__hint">
 94                    Засыл перебивает склад отгрузки: склад 1С определяется по связям складов для
 95                    выбранного значения, и остаток спишется именно с него.
 96                </div>
 97                <div class="tx-zasyl-unmapped" id="zasylSenderUnmapped" style="display:none;"></div>
 98            </div>
 99        </div>
 100
 0101        @await Html.PartialAsync("_TransactionTable", Model)
 102
 103        <div class="d-flex flex-wrap align-items-center gap-3 ms-3 mt-3">
 104            <div class="form-check">
 105                <input class="form-check-input" type="checkbox" id="processIn1C" name="processIn1C" value="true" checked
 106                <label class="form-check-label" for="processIn1C">
 107                    <i class="fas fa-database me-1"></i>
 108                    Провести в 1С
 109                </label>
 110            </div>
 0111            @await Html.PartialAsync("_OneCOrgSelector", Model)
 112            <div class="small text-warning-emphasis">
 113                <i class="fas fa-circle-info me-1"></i>
 114                Если номенклатура не найдена, новая карточка в 1С не создаётся: документ будет сохранён черновиком и не 
 115            </div>
 116        </div>
 117
 118        <div id="otsProcessIn1CBlock" class="ms-3 mt-2" style="display:none;">
 0119            @if (anyFound)
 120            {
 121                <div class="small text-muted">
 122                    <i class="fas fa-route me-1 text-primary"></i>
 123                    Заказы с количеством 0 будут проведены как <strong>«Утерян реализатором»</strong> через транзитный с
 0124                    (@(string.Join(", ", transitGroups!.Where(g => g.FoundIn1C).Select(g => g.TransitWarehouse))))
 125                </div>
 126            }
 0127            else if (transitGroups != null && transitGroups.Count > 0)
 128            {
 129                <div class="d-flex align-items-start gap-2 p-2 rounded"
 130                     style="background-color:#fff3cd; border:1px solid #ffc107; max-width:600px;">
 131                    <i class="fas fa-exclamation-triangle text-warning mt-1" style="font-size:1.1em;flex-shrink:0;"></i>
 132                    <div>
 133                        <div class="fw-semibold" style="color:#664d03;">Проведение «Утерян реализатором» в 1С недоступно
 134                        <div class="small" style="color:#664d03;">
 135                            Транзитные склады
 0136                            (@(string.Join(", ", transitGroups.Where(g => !g.FoundIn1C).Select(g => g.TransitWarehouse))
 137                            не настроены в WarehouseMapping или отсутствуют в 1С. Заполните поле «Транзитный склад (1С)»
 138                        </div>
 139                    </div>
 140                </div>
 141            }
 142        </div>
 143
 144        <div class="tx-page-footer">
 145            <div class="input-group">
 146                <span class="input-group-btn">
 147                    <input type="submit" value="Сохранить" class="btn btn-primary"
 148                           data-bs-target="#staticBackdrop"/>
 149                </span>
 150            </div>
 151        </div>
 152    </form>
 153}
 154else
 155{
 0156    @await Html.PartialAsync("_TransactionErrorPanel")
 157}
 158
 159<div class="modal fade" id="staticBackdrop" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1"
 160     aria-labelledby="staticBackdropLabel" aria-hidden="true">
 161    <div class="modal-dialog">
 162        <div class="modal-content orders-modal orders-modal--primary">
 163            <div class="modal-header">
 164                <h5 class="modal-title" id="staticBackdropLabel">Создание журнала документов</h5>
 165                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Закрыть"></button>
 166            </div>
 167            <div class="modal-body">
 168                <div class="d-flex justify-content-center">
 169                    <div class="spinner-border text-primary" role="status">
 170                        <span class="sr-only">.</span>
 171                    </div>
 172                </div>
 173            </div>
 174        </div>
 175    </div>
 176</div>
 177
 178<div>
 179    <a asp-action="Index" class="tx-page-back-link">← К списку заказов</a>
 180</div>
 181
 182<div class="modal fade" id="imageModal" tabindex="-1" aria-labelledby="imageModalLabel" aria-hidden="true">
 183    <div class="modal-dialog modal-dialog-centered">
 184        <div class="modal-content">
 185            <div class="modal-header">
 186                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
 187            </div>
 188            <div class="modal-body text-center">
 189                <img id="modalImage" src="" alt="Full Image" class="img-fluid rounded border">
 190            </div>
 191        </div>
 192    </div>
 193</div>
 194
 195<input type="hidden" id="deletedOrders" name="deletedOrders"/>
 196@* Скрипты таблицы нужны только когда она отрисована; на панели ошибки они падали на пустом DOM *@
 0197@if (orders.Count > 0)
 198{
 0199@await Html.PartialAsync("_TransactionScript", Model)
 200
 201<script>
 202    // Панель «склад списания в 1С»: засыл выбирают в строке, а в документ уходит склад из связей
 203    // складов — показываем результат резолва и отдельно те засылы, для которых связи нет.
 204    (function () {
 0205        var MAPPED_SENDER = @Html.Raw(senderByOrderIdJson);
 0206        var ZASYL_OPTIONS = @Html.Raw(zasylOptionsJson);
 0207        var CREATE_MAPPING_URL = '@warehouseMappingCreateUrl';
 208        var notice = document.getElementById('zasylSenderNotice');
 209        var chips = document.getElementById('zasylSenderChips');
 210        var unmappedBox = document.getElementById('zasylSenderUnmapped');
 211        if (!notice || !chips) return;
 212
 213        function zasylInputs() {
 214            return Array.prototype.slice.call(
 215                document.querySelectorAll('input.zasyl-input[id^="orderSupplierMap_"]'));
 216        }
 217
 218        function orderIdOf(input) {
 219            return input.id.replace('orderSupplierMap_', '');
 220        }
 221
 222        function isRowActive(input) {
 223            var row = input.closest('tr');
 224            return !row || row.style.display !== 'none';
 225        }
 226
 227        function plural(count) {
 228            var tail = count % 100;
 229            if (tail > 10 && tail < 20) return 'заказов';
 230            switch (count % 10) {
 231                case 1: return 'заказ';
 232                case 2:
 233                case 3:
 234                case 4: return 'заказа';
 235                default: return 'заказов';
 236            }
 237        }
 238
 239        function esc(value) {
 240            return (value || '').replace(/[&<>"']/g, function (c) {
 241                return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c];
 242            });
 243        }
 244
 245        // Тот же ключ, что строит сервер: короткие коды приводятся к латинице («М2» → «m2»).
 246        function optionKey(value) {
 247            var name = (value || '').trim();
 248            if (name.length !== 2 || !/\d/.test(name[1])) return name.toLowerCase();
 249            var prefix = { 'М': 'M', 'В': 'B' }[name[0].toUpperCase()] || name[0].toUpperCase();
 250            return (prefix + name[1]).toLowerCase();
 251        }
 252
 253        function resolveZasyl(orderId, zasyl) {
 254            var option = ZASYL_OPTIONS[String(orderId)]
 255                && ZASYL_OPTIONS[String(orderId)].options
 256                && ZASYL_OPTIONS[String(orderId)].options[optionKey(zasyl)];
 257            return option
 258                ? { warehouse: option.warehouse, mapped: option.mapped }
 259                : { warehouse: zasyl, mapped: false };
 260        }
 261
 262        function createMappingLink(orderId, zasyl) {
 263            var info = ZASYL_OPTIONS[String(orderId)] || {};
 264            var params = new URLSearchParams();
 265            if (info.clientId) params.set('ozonClientId', info.clientId);
 266            params.set('ozonWarehouseName', zasyl);
 267            if (info.deliveryType) params.set('deliveryType', info.deliveryType);
 268            return CREATE_MAPPING_URL + '?' + params.toString();
 269        }
 270
 271        function render() {
 272            var byPair = {};
 273            var byMapping = {};
 274            var unmapped = {};
 275
 276            zasylInputs().forEach(function (input) {
 277                if (!isRowActive(input)) return;
 278
 279                var orderId = orderIdOf(input);
 280                var value = (input.value || '').trim();
 281                if (!value) {
 282                    input.title = 'Засыл не указан: склад списания определится по складу отгрузки и связям складов.';
 283                    var mapped = MAPPED_SENDER[orderId];
 284                    if (mapped) byMapping[mapped] = (byMapping[mapped] || 0) + 1;
 285                    return;
 286                }
 287
 288                var resolution = resolveZasyl(orderId, value);
 289                var pairKey = value + ' → ' + resolution.warehouse;
 290                if (!byPair[pairKey]) {
 291                    byPair[pairKey] = { zasyl: value, warehouse: resolution.warehouse, mapped: resolution.mapped, count:
 292                }
 293                byPair[pairKey].count += 1;
 294
 295                input.title = resolution.mapped
 296                    ? 'Склад списания в 1С: ' + resolution.warehouse + ' (по связи складов для засыла ' + value + ').'
 297                    : 'Для засыла ' + value + ' нет связи складов — в 1С уйдёт склад с этим же именем.';
 298
 299                if (!resolution.mapped) {
 300                    var info = ZASYL_OPTIONS[String(orderId)] || {};
 301                    var key = orderId + '|' + value;
 302                    unmapped[key] = {
 303                        orderId: orderId,
 304                        zasyl: value,
 305                        clientName: info.clientName || '',
 306                        deliveryType: info.deliveryType || ''
 307                    };
 308                }
 309            });
 310
 311            var pairKeys = Object.keys(byPair);
 312            if (pairKeys.length === 0) {
 313                notice.style.display = 'none';
 314                chips.innerHTML = '';
 315                if (unmappedBox) { unmappedBox.innerHTML = ''; unmappedBox.style.display = 'none'; }
 316                return;
 317            }
 318
 319            var html = pairKeys.sort().map(function (key) {
 320                var item = byPair[key];
 321                var cls = item.mapped ? 'tx-zasyl-chip' : 'tx-zasyl-chip tx-zasyl-chip--unmapped';
 322                return '<span class="' + cls + '"><i class="fas fa-warehouse"></i>' +
 323                    esc(item.zasyl) + ' <i class="fas fa-arrow-right-long tx-zasyl-chip-arrow"></i> ' +
 324                    esc(item.warehouse) + '<b>' + item.count + ' ' + plural(item.count) + '</b></span>';
 325            }).join('');
 326
 327            var mappingNames = Object.keys(byMapping).sort();
 328            if (mappingNames.length > 0) {
 329                html += mappingNames.map(function (name) {
 330                    return '<span class="tx-zasyl-chip tx-zasyl-chip--mapped">' +
 331                        '<i class="fas fa-link"></i>' + esc(name) +
 332                        '<b>' + byMapping[name] + ' ' + plural(byMapping[name]) + ' без засыла</b></span>';
 333                }).join('');
 334            }
 335
 336            chips.innerHTML = html;
 337            notice.style.display = '';
 338
 339            if (!unmappedBox) return;
 340
 341            // Одна строка на пару «засыл + клиент»: заказов с одинаковым засылом может быть много,
 342            // а связь складов для них нужна одна.
 343            var seen = {};
 344            var warnings = Object.keys(unmapped).map(function (key) {
 345                var item = unmapped[key];
 346                var groupKey = item.zasyl + '|' + item.clientName + '|' + item.deliveryType;
 347                if (seen[groupKey]) return '';
 348                seen[groupKey] = true;
 349
 350                var context = [item.clientName, item.deliveryType].filter(Boolean).map(esc).join(', ');
 351                return '<div class="tx-zasyl-unmapped-row">' +
 352                    '<i class="fas fa-triangle-exclamation"></i>' +
 353                    '<span>Для засыла <b>' + esc(item.zasyl) + '</b>' +
 354                    (context ? ' (' + context + ')' : '') +
 355                    ' не настроена связь складов — в 1С уйдёт склад с этим же именем.</span>' +
 356                    '<a class="tx-zasyl-unmapped-link" target="_blank" rel="noopener" href="' +
 357                    esc(createMappingLink(item.orderId, item.zasyl)) + '">' +
 358                    '<i class="fas fa-plus"></i>Создать связь</a></div>';
 359            }).join('');
 360
 361            unmappedBox.innerHTML = warnings;
 362            unmappedBox.style.display = warnings ? '' : 'none';
 363        }
 364
 365        document.addEventListener('DOMContentLoaded', function () {
 366            zasylInputs().forEach(function (input) {
 367                input.addEventListener('input', render);
 368                input.addEventListener('change', render);
 369            });
 370            render();
 371        });
 372    })();
 373</script>
 374
 375<script>
 0376    var otsOrderInfoMap = @Html.Raw(System.Text.Json.JsonSerializer.Serialize(orderInfoMapRaw ?? new object()));
 377    var otsWarehouseFieldMap = { 'M2': 'm2Qty', 'M3': 'm3Qty', 'B1': 'b1Qty', 'B2': 'b2Qty' };
 378    var otsStockBadgeCache = {};
 379
 380    function insertOtsStockBadge(orderId, stockQty, senderWarehouse, fuzzyManufacturer) {
 381        var zasylInput = document.getElementById('orderSupplierMap_' + orderId);
 382        if (!zasylInput) return;
 383
 384        var formGroup = zasylInput.closest('.form-group');
 385        if (!formGroup) return;
 386
 387        var parent = formGroup.parentNode;
 388        var existing = parent.querySelector('.ws-ots-badge-' + orderId);
 389        if (existing) existing.remove();
 390
 391        var quantityInput = document.querySelector('.quantity-input-field[data-order-id="' + orderId + '"]');
 392        var originalQty = quantityInput ? parseInt(quantityInput.dataset.originalQuantity, 10) || 0 : 0;
 393        var currentQty = quantityInput ? parseInt(quantityInput.value, 10) || 0 : 0;
 394
 395        if (currentQty !== 0 || originalQty <= 0) return;
 396
 397        formGroup.style.display = 'none';
 398
 399        var transitWarehouse = senderWarehouse ? senderWarehouse + ' (transit)' : null;
 400        var arrow = ' → ';
 401
 402        var badge = document.createElement('span');
 403        badge.className = 'ws-sender-badge ws-ots-badge-' + orderId;
 404
 405        if (!senderWarehouse) {
 406            badge.style.cssText = 'background-color:#f8d7da;color:#842029;';
 407            badge.title = 'Склад отправителя не определён';
 408            badge.textContent = '⚠ склад не определён';
 409        } else if (stockQty === null) {
 410            badge.style.cssText = 'background-color:#e2e3e5;color:#41464b;';
 411            badge.title = 'Артикул не найден в WarehouseStock — заказ будет пропущен';
 412            badge.textContent = senderWarehouse + arrow + transitWarehouse + ': не в WS';
 413        } else if (stockQty > 0) {
 414            badge.style.cssText = 'background-color:#cfe2ff;color:#084298;';
 415            var fuzzySuffix = fuzzyManufacturer ? ' ⚠ не по производителю' : '';
 416            badge.title = fuzzyManufacturer
 417                ? 'Найдено по артикулу, производитель не совпал — проверьте вручную'
 418                : 'Перемещение ' + senderWarehouse + ' → ' + transitWarehouse + ' — будет передано в 1С';
 419            badge.textContent = senderWarehouse + arrow + transitWarehouse + ': ' + stockQty.toLocaleString('ru-RU') + '
 420        } else {
 421            badge.style.cssText = 'background-color:#fff3cd;color:#664d03;';
 422            badge.title = 'Остаток ' + senderWarehouse + ' = 0 — заказ будет пропущен';
 423            badge.textContent = senderWarehouse + arrow + transitWarehouse + ': 0 (пропуск)';
 424        }
 425
 426        parent.appendChild(badge);
 427    }
 428
 429    function removeOtsStockBadge(orderId) {
 430        var badge = document.querySelector('.ws-ots-badge-' + orderId);
 431        if (badge) badge.remove();
 432        var zasylInput = document.getElementById('orderSupplierMap_' + orderId);
 433        if (zasylInput) {
 434            var formGroup = zasylInput.closest('.form-group');
 435            if (formGroup) formGroup.style.display = '';
 436        }
 437    }
 438
 439    async function loadOtsStockBadge(orderId) {
 440        var info = otsOrderInfoMap && otsOrderInfoMap[orderId];
 441        if (!info) return;
 442
 443        if (Object.prototype.hasOwnProperty.call(otsStockBadgeCache, orderId)) {
 444            var cached = otsStockBadgeCache[orderId];
 445            insertOtsStockBadge(orderId, cached.qty, info.senderWarehouse, cached.fuzzy);
 446            return;
 447        }
 448
 449        if (!info.article) {
 450            insertOtsStockBadge(orderId, null, info.senderWarehouse, false);
 451            return;
 452        }
 453
 454        try {
 455            var params = new URLSearchParams();
 456            params.set('article', info.article);
 457            if (info.manufacturer) params.set('manufacturer', info.manufacturer);
 458            var resp = await fetch('/Studio2/WarehouseStock/lookup?' + params.toString());
 459            if (!resp.ok) {
 460                insertOtsStockBadge(orderId, null, info.senderWarehouse, false);
 461                return;
 462            }
 463            var data = await resp.json();
 464            var stockQty = null;
 465            if (data.found) {
 466                var senderUpper = (info.senderWarehouse || '').trim().toUpperCase();
 467                var fieldKey = otsWarehouseFieldMap[senderUpper];
 468                stockQty = fieldKey != null ? (data[fieldKey] ?? 0) : null;
 469            }
 470            otsStockBadgeCache[orderId] = { qty: stockQty, fuzzy: !!data.fuzzyManufacturer };
 471            insertOtsStockBadge(orderId, stockQty, info.senderWarehouse, !!data.fuzzyManufacturer);
 472        } catch (e) {
 473            insertOtsStockBadge(orderId, null, info.senderWarehouse);
 474        }
 475    }
 476
 477    function updateOtsProcessIn1CBlock() {
 478        var block = document.getElementById('otsProcessIn1CBlock');
 479        if (!block) return;
 480
 481        var hasZeroQty = false;
 482        document.querySelectorAll('.quantity-input-field').forEach(function (input) {
 483            var originalQty = parseInt(input.dataset.originalQuantity, 10) || 0;
 484            var currentQty = parseInt(input.value, 10) || 0;
 485            if (originalQty > 0 && currentQty === 0) hasZeroQty = true;
 486        });
 487
 488        block.style.display = hasZeroQty ? '' : 'none';
 489    }
 490
 491    function handleOtsQuantityChange(input) {
 492        var orderId = input.dataset.orderId;
 493        var originalQty = parseInt(input.dataset.originalQuantity, 10) || 0;
 494        var currentQty = parseInt(input.value, 10) || 0;
 495
 496        if (originalQty > 0 && currentQty === 0) {
 497            loadOtsStockBadge(orderId);
 498        } else {
 499            removeOtsStockBadge(orderId);
 500        }
 501
 502        updateOtsProcessIn1CBlock();
 503    }
 504
 505    document.addEventListener('DOMContentLoaded', function () {
 506        document.querySelectorAll('.quantity-input-field').forEach(function (input) {
 507            input.addEventListener('input', function () { handleOtsQuantityChange(input); });
 508            input.addEventListener('change', function () { handleOtsQuantityChange(input); });
 509            handleOtsQuantityChange(input);
 510        });
 511    });
 512</script>
 513
 514<script>
 515    document.addEventListener('DOMContentLoaded', function () {
 516        var form = document.getElementById('createOrderForm');
 517        if (!form) return;
 518
 519        var isSubmitting = false;
 520
 521        form.addEventListener('submit', function (e) {
 522            e.preventDefault();
 523            if (isSubmitting) return;
 524            isSubmitting = true;
 525
 526            $('#staticBackdrop').modal('show');
 527
 528            var formData = $(form).serialize();
 0529            formData += '&userName=' + encodeURIComponent('@(User.Identity?.Name ?? "")')
 530                + '&comment=' + encodeURIComponent(txGetCommentFieldValue())
 0531                + '&page=' + encodeURIComponent('@(Model?.RedirectPage ?? 1)');
 532
 533            $.ajax({
 534                url: form.action,
 535                type: 'POST',
 536                data: formData,
 537                success: function (result) {
 538                    if (result.redirectTo) {
 539                        window.location.href = result.redirectTo;
 540                    } else {
 541                        isSubmitting = false;
 542                        $('#staticBackdrop').modal('hide');
 543                        alert('Произошла ошибка: не удалось получить URL для перенаправления.');
 544                    }
 545                },
 546                error: function (xhr, status, error) {
 547                    isSubmitting = false;
 548                    showFriendlyRequestError(xhr, status, error, 'Ошибка при отправке формы');
 549                    $('#staticBackdrop').modal('hide');
 550                }
 551            });
 552        });
 553    });
 554</script>
 555
 556
 0557@await Html.PartialAsync("_OneCStockCheckScript")
 558}

Methods/Properties

ExecuteAsync()
<ExecuteAsync()