< Summary

Information
Class: AspNetCoreGeneratedDocument.Areas_Studio2_Views_LostByCommissionerTransaction_CreateLostByCommissionerTransaction
Assembly: OzonOrdersWeb
File(s): /home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Areas/Studio2/Views/LostByCommissionerTransaction/CreateLostByCommissionerTransaction.cshtml
Line coverage
0%
Covered lines: 0
Uncovered lines: 22
Coverable lines: 22
Total lines: 328
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 40
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%812280%
<ExecuteAsync()0%342180%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Areas/Studio2/Views/LostByCommissionerTransaction/CreateLostByCommissionerTransaction.cshtml

#LineLine coverage
 1@using OzonDomains.Models
 2@using OzonOrdersWeb.ViewModels.OrderViewModels
 3@using OzonOrdersWeb.Areas.Studio2.Helpers
 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"];
 16}
 17
 18<partial name="~/Areas/Studio2/Views/Partials/Transaction/_TransactionPageStyles.cshtml"/>
 19<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
 20<script src="~/js/Studio2/Orders/CreateOrderToSupplierTransactionV2/generateInfoRow.js"></script>
 21
 22<div id="loadingSpinner" class="spinner-overlay" style="display: none;">
 23    <div class="spinner-border text-primary" role="status"><span class="sr-only"></span></div>
 24</div>
 25
 26<div id="messageContainer" class="position-fixed top-0 end-0 p-3" style="z-index: 1050;">
 27    <div id="flashMessage" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
 28        <div class="toast-header">
 29            <strong class="me-auto">Сообщение</strong>
 30            <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
 31        </div>
 32        <div class="toast-body"><span id="flashMessageText"></span></div>
 33    </div>
 34</div>
 35
 36<div class="modal fade" id="cartModal" tabindex="-1" aria-hidden="true">
 37    <div class="modal-dialog modal-lg modal-dialog-scrollable">
 38        <div class="modal-content rounded-3 shadow">
 39            <div class="modal-header">
 40                <h5 class="modal-title">Корзина</h5>
 41                <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
 42            </div>
 43            <div class="modal-body" id="cartModalBody"></div>
 44            <div class="modal-footer">
 45                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button>
 46            </div>
 47        </div>
 48    </div>
 49</div>
 50
 051@if (orders.Count > 0)
 52{
 53
 54    <form asp-area="Studio2" asp-controller="LostByCommissionerTransaction"
 55          asp-action="CreateLostByCommissionerTransaction"
 56          id="createOrderForm" class="lbc-form">
 57        <div asp-validation-summary="ModelOnly" class="text-danger"></div>
 58        <input type="hidden" asp-for="RedirectPage"/>
 59        <input type="hidden" asp-for="TrackingKey"/>
 60
 61        @* Manufacturer per order → server-side stock lookup *@
 062        @for (var i = 0; i < orders.Count; i++)
 63        {
 64            <input type="hidden"
 65                   name="manufacturerByOrderId[@orders[i].Id]"
 66                   value="@(orders[i].EtProducer?.Name ?? "")"/>
 67        }
 68
 069        @await Html.PartialAsync("_TransactionTable", Model)
 70
 71        @* Блок проведения в 1С *@
 72        <div class="ms-3 mt-3">
 073            @if (anyFound)
 74            {
 75                <div class="d-flex flex-wrap align-items-center gap-3">
 76                    <div class="form-check">
 77                        <input class="form-check-input" type="checkbox" id="processIn1C" name="processIn1C" value="true"
 78                        <label class="form-check-label" for="processIn1C">
 79                            <i class="fas fa-database me-1 text-primary"></i>
 80                            <strong>Провести в 1С</strong>
 81                            <span class="text-muted small ms-1">— количество из WarehouseStock по складу отправителя</sp
 82                        </label>
 83                    </div>
 084                    @await Html.PartialAsync("_OneCOrgSelector", Model)
 85                    <div class="small text-warning-emphasis">
 86                        <i class="fas fa-circle-info me-1"></i>
 87                        Если номенклатура не найдена, новая карточка в 1С не создаётся: документ будет сохранён черновик
 88                    </div>
 89                </div>
 90            }
 91            else
 92            {
 93                <div class="d-flex align-items-start gap-2 p-2 rounded"
 94                     style="background-color:#fff3cd; border:1px solid #ffc107; max-width:600px;">
 95                    <i class="fas fa-exclamation-triangle text-warning mt-1" style="font-size:1.1em;flex-shrink:0;"></i>
 96                    <div>
 97                        <div class="fw-semibold" style="color:#664d03;">Проведение в 1С недоступно</div>
 98                        <div class="small" style="color:#664d03;">
 99                            Транзитные склады
 0100                            (@(string.Join(", ", transitGroups?.Where(g => !g.FoundIn1C).Select(g => g.TransitWarehouse)
 101                            не настроены в WarehouseMapping или отсутствуют в 1С. Заполните поле «Транзитный склад (1С)»
 102                        </div>
 103                        <input type="hidden" name="processIn1C" value="false"/>
 104                    </div>
 105                </div>
 106            }
 107        </div>
 108
 109        <div class="tx-page-footer">
 110            <div class="input-group">
 111                <span class="input-group-btn">
 112                    <input type="submit" value="Сохранить" class="btn btn-primary"/>
 113                </span>
 114            </div>
 115        </div>
 116    </form>
 117}
 118else
 119{
 0120    @await Html.PartialAsync("_TransactionErrorPanel")
 121}
 122
 123<div class="modal fade" id="staticBackdrop" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1"
 124     aria-hidden="true">
 125    <div class="modal-dialog">
 126        <div class="modal-content orders-modal orders-modal--primary">
 127            <div class="modal-header">
 128                <h5 class="modal-title">Создание журнала документов</h5>
 129                <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
 130            </div>
 131            <div class="modal-body">
 132                <div class="d-flex justify-content-center">
 133                    <div class="spinner-border text-primary" role="status"><span class="sr-only">.</span></div>
 134                </div>
 135            </div>
 136        </div>
 137    </div>
 138</div>
 139
 140<div><a asp-action="Index" class="tx-page-back-link">← К списку заказов</a></div>
 141
 142<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-hidden="true">
 143    <div class="modal-dialog" role="document">
 144        <div class="modal-content orders-modal orders-modal--warning">
 145            <div class="modal-header">
 146                <h4 class="modal-title">Поля не заполнены</h4>
 147            </div>
 148            <div class="modal-body">
 149                <p id="modalErrorMessage">Одно или несколько полей не заполнены.</p>
 150            </div>
 151        </div>
 152    </div>
 153</div>
 154
 155<div class="modal fade" id="imageModal" tabindex="-1" aria-hidden="true">
 156    <div class="modal-dialog modal-dialog-centered">
 157        <div class="modal-content">
 158            <div class="modal-header">
 159                <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
 160            </div>
 161            <div class="modal-body text-center">
 162                <img id="modalImage" src="" alt="Full Image" class="img-fluid rounded border">
 163            </div>
 164        </div>
 165    </div>
 166</div>
 167
 168<input type="hidden" id="deletedOrders" name="deletedOrders"/>
 169@* Скрипты таблицы нужны только когда она отрисована; на панели ошибки они падали на пустом DOM *@
 0170@if (orders.Count > 0)
 171{
 0172@await Html.PartialAsync("_TransactionScript", Model)
 173
 174<script>
 175    // Блокируем поля редактирования (кроме комментария)
 176    document.addEventListener('DOMContentLoaded', function () {
 177        var table = document.getElementById('shipmentTable');
 178        if (!table) return;
 179        table.querySelectorAll('input, select, textarea').forEach(function (el) {
 180            if ((el.name && el.name.includes('[Comment]')) || el.type === 'hidden') return;
 181            el.classList.add('locked-field');
 182            var tag = el.tagName.toLowerCase();
 183            if (tag === 'input' || tag === 'textarea') el.readOnly = true;
 184            if (tag === 'select') {
 185                ['mousedown', 'click', 'keydown', 'focus'].forEach(function (evt) {
 186                    el.addEventListener(evt, function (e) { e.preventDefault(); el.blur(); }, { capture: true });
 187                });
 188            }
 189        });
 190    });
 191</script>
 192
 193<script>
 194    // Карта per-order: { "orderId": { article, manufacturer, senderWarehouse, transitWarehouse } }
 0195    var lbcOrderInfoMap = @Html.Raw(System.Text.Json.JsonSerializer.Serialize(orderInfoMapRaw ?? new object()));
 196
 197    function insertLbcLoadingBadge(orderId, senderWarehouse, transitWarehouse) {
 198        var zasylInput = document.getElementById('orderSupplierMap_' + orderId);
 199        if (!zasylInput) return;
 200        var formGroup = zasylInput.closest('.form-group');
 201        if (!formGroup) return;
 202        formGroup.style.display = 'none';
 203        var parent = formGroup.parentNode;
 204        var existing = parent.querySelector('.ws-lbc-badge-' + orderId);
 205        if (existing) existing.remove();
 206        var badge = document.createElement('span');
 207        badge.className = 'ws-sender-badge ws-lbc-badge-' + orderId;
 208        badge.style.cssText = 'background-color:#e2e3e5;color:#41464b;';
 209        var destination = transitWarehouse || 'не настроен';
 210        badge.innerHTML = (senderWarehouse || '?') + ' → ' + destination + ': ' + (window.txLoadingDotsHtml ? txLoadingD
 211        parent.appendChild(badge);
 212    }
 213
 214    function insertLbcStockBadge(orderId, stockQty, senderWarehouse, transitWarehouse, fuzzyManufacturer) {
 215        var zasylInput = document.getElementById('orderSupplierMap_' + orderId);
 216        if (!zasylInput) return;
 217
 218        var formGroup = zasylInput.closest('.form-group');
 219        if (!formGroup) return;
 220
 221        formGroup.style.display = 'none';
 222
 223        var parent = formGroup.parentNode;
 224        var existing = parent.querySelector('.ws-lbc-badge-' + orderId);
 225        if (existing) existing.remove();
 226
 227        var destination = transitWarehouse || 'не настроен';
 228        var arrow = ' → ';
 229
 230        var badge = document.createElement('span');
 231        badge.className = 'ws-sender-badge ws-lbc-badge-' + orderId;
 232
 233        if (!senderWarehouse) {
 234            badge.style.cssText = 'background-color:#f8d7da;color:#842029;';
 235            badge.title = 'Склад отправителя не определён';
 236            badge.textContent = '⚠ склад не определён';
 237        } else if (stockQty === null) {
 238            badge.style.cssText = 'background-color:#e2e3e5;color:#41464b;';
 239            badge.title = 'Артикул не найден в WarehouseStock — заказ будет пропущен';
 240            badge.textContent = senderWarehouse + arrow + destination + ': не в WS';
 241        } else if (stockQty > 0) {
 242            badge.style.cssText = 'background-color:#cfe2ff;color:#084298;';
 243            var fuzzySuffix = fuzzyManufacturer ? ' ⚠ не по производителю' : '';
 244            badge.title = fuzzyManufacturer
 245                ? 'Найдено по артикулу, производитель не совпал — проверьте вручную'
 246                : 'Перемещение ' + senderWarehouse + ' → ' + destination + ' — будет передано в 1С';
 247            badge.textContent = senderWarehouse + arrow + destination + ': ' + stockQty.toLocaleString('ru-RU') + ' шт.'
 248        } else {
 249            badge.style.cssText = 'background-color:#fff3cd;color:#664d03;';
 250            badge.title = 'Остаток ' + senderWarehouse + ' = 0 — заказ будет пропущен';
 251            badge.textContent = senderWarehouse + arrow + destination + ': 0 (пропуск)';
 252        }
 253
 254        parent.appendChild(badge);
 255    }
 256
 257    async function setupLostByCommissionerStockBadges() {
 258        if (!lbcOrderInfoMap || typeof lbcOrderInfoMap !== 'object') return;
 259
 260        for (var orderId in lbcOrderInfoMap) {
 261            var info = lbcOrderInfoMap[orderId];
 262            if (!info || !info.article) {
 263                insertLbcStockBadge(orderId, null, info && info.senderWarehouse, info && info.transitWarehouse, false);
 264                continue;
 265            }
 266            insertLbcLoadingBadge(orderId, info.senderWarehouse, info.transitWarehouse);
 267            try {
 268                var params = new URLSearchParams();
 269                params.set('article', info.article);
 270                var resp = await fetch('/Studio2/WarehouseStock/onec-lookup?' + params.toString());
 271                if (!resp.ok) { insertLbcStockBadge(orderId, null, info.senderWarehouse, info.transitWarehouse, false); 
 272                var data = await resp.json();
 273
 274                var stockQty = null;
 275                if (data.found && data.stocks) {
 276                    var senderLower = (info.senderWarehouse || '').trim().toLowerCase();
 277                    var match = data.stocks.find(function(s) { return (s.warehouse || '').toLowerCase() === senderLower;
 278                    stockQty = match != null ? match.quantity : 0;
 279                }
 280                insertLbcStockBadge(orderId, stockQty, info.senderWarehouse, info.transitWarehouse, false);
 281            } catch (e) {
 282                insertLbcStockBadge(orderId, null, info.senderWarehouse, info.transitWarehouse, false);
 283            }
 284        }
 285    }
 286
 287    document.addEventListener('DOMContentLoaded', function () {
 288        // Немедленно скрываем засыл через JS (фолбек для :has())
 289        document.querySelectorAll('.zasyl-input').forEach(function (inp) {
 290            var fg = inp.closest('.form-group');
 291            if (fg) fg.style.display = 'none';
 292        });
 293
 294        // Загружаем бейджи с небольшой задержкой после loadWarehouseStock
 295        setTimeout(setupLostByCommissionerStockBadges, 600);
 296    });
 297</script>
 298
 299<script>
 300    $('#createOrderForm').submit(function (e) {
 301        e.preventDefault();
 302        var formData = $(this).serialize();
 0303        formData += '&userName=' + encodeURIComponent('@User.Identity?.Name')
 304            + '&comment=' + encodeURIComponent(txGetCommentFieldValue())
 0305            + '&page=' + '@(Model?.RedirectPage ?? 1)';
 306
 307        $.ajax({
 0308            url: '@Url.Action("CreateLostByCommissionerTransaction", "LostByCommissionerTransaction")',
 309            type: 'POST',
 310            data: formData,
 311            success: function (result) {
 312                if (result && result.redirectTo) {
 313                    window.location.href = result.redirectTo;
 314                } else {
 315                    alert('Произошла ошибка: не удалось получить URL для перенаправления.');
 316                }
 317            },
 318            error: function (xhr, status, error) {
 319                if (window.txHideSubmitOverlay) window.txHideSubmitOverlay();
 320                showFriendlyRequestError(xhr, status, error, 'Ошибка при отправке формы');
 321            }
 322        });
 323    });
 324</script>
 325
 326
 0327@await Html.PartialAsync("_OneCStockCheckScript")
 328}

Methods/Properties

ExecuteAsync()
<ExecuteAsync()