< Summary

Information
Class: AspNetCoreGeneratedDocument.Areas_Studio2_Views_ShippedBySupplierTransaction_CreateShippedBySupplierTransaction
Assembly: OzonOrdersWeb
File(s): /home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Areas/Studio2/Views/ShippedBySupplierTransaction/CreateShippedBySupplierTransaction.cshtml
Line coverage
0%
Covered lines: 0
Uncovered lines: 32
Coverable lines: 32
Total lines: 408
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 64
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%272160%
<ExecuteAsync()0%1980440%
<ExecuteAsync()0%620%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Areas/Studio2/Views/ShippedBySupplierTransaction/CreateShippedBySupplierTransaction.cshtml

#LineLine coverage
 1@using OzonDomains.Models
 2@using OzonOrdersWeb.ViewModels.OrderViewModels
 3
 4
 5@model OzonOrdersWeb.Areas.Studio2.ViewModels.ShippedBySupplierTransaction.CreateShippedBySupplierTransactionModel
 6
 7@{
 08    var viewModel = Model!;
 09    var orders = viewModel.Orders;
 010    var ordersCount = orders.Count;
 011    ViewData["Title"] = $"Отгружен поставщиком ({ordersCount} заказов)";
 012    Layout = "~/Views/Shared/_Layout.cshtml";
 13
 14    // Склад прихода: по умолчанию склад клиента Ozon из настроек. Если у выбранных заказов клиенты с разными
 15    // складами, поле остаётся пустым и склад выбирают руками.
 016    var clientWarehouses = orders
 017        .Select(o => o.OzonClient?.WarehouseName?.Trim())
 018        .Where(n => !string.IsNullOrEmpty(n))
 019        .Distinct(StringComparer.OrdinalIgnoreCase)
 020        .ToList();
 021    var defaultReceiptWarehouse = clientWarehouses.Count == 1 ? clientWarehouses[0] : string.Empty;
 22}
 23
 24<partial name="~/Areas/Studio2/Views/Partials/Transaction/_TransactionPageStyles.cshtml"/>
 25<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
 26
 27<script src="~/js/Studio2/Orders/CreateOrderToSupplierTransactionV2/generateInfoRow.js"></script>
 28
 29<div id="messageContainer" class="position-fixed top-0 end-0 p-3" style="z-index: 1050;">
 30    <div id="flashMessage" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
 31        <div class="toast-header">
 32            <strong class="me-auto">Сообщение</strong>
 33            <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
 34        </div>
 35        <div class="toast-body">
 36            <span id="flashMessageText"></span>
 37        </div>
 38    </div>
 39</div>
 40
 41<div class="modal fade" id="cartModal" tabindex="-1" aria-labelledby="cartModalLabel" aria-hidden="true">
 42    <div class="modal-dialog modal-lg modal-dialog-scrollable">
 43        <div class="modal-content rounded-3 shadow">
 44            <div class="modal-header">
 45                <h5 class="modal-title" id="cartModalLabel">Корзина</h5>
 46                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Закрыть"></button>
 47            </div>
 48            <div class="modal-body" id="cartModalBody">
 49                <!-- Контент корзины будет вставлен сюда -->
 50            </div>
 51            <div class="modal-footer">
 52                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button>
 53            </div>
 54        </div>
 55    </div>
 56</div>
 57
 058@if (orders.Count > 0)
 59{
 60    <form asp-area="Studio2" asp-controller="ShippedBySupplierTransaction"
 61          asp-action="CreateShippedBySupplierTransaction" id="createOrderForm">
 62        <div asp-validation-summary="ModelOnly" class="text-danger"></div>
 63        <input type="hidden" asp-for="RedirectPage"/>
 64        <input type="hidden" asp-for="TrackingKey"/>
 65
 066        @await Html.PartialAsync("_ShippedBySupplierTransactionTable", Model)
 67
 68        <div class="d-flex flex-wrap align-items-center gap-3">
 69            <div class="form-check ms-3">
 70                <input class="form-check-input" type="checkbox" id="ProcessIn1C" name="ProcessIn1C" value="true" checked
 71                <label class="form-check-label" for="ProcessIn1C">
 72                    <i class="fas fa-database me-1"></i>
 73                    Провести в 1С
 74                </label>
 75            </div>
 076            @await Html.PartialAsync("_OneCOrgSelector", Model)
 77        </div>
 78
 79
 80        <!-- ================== МОДАЛЬНОЕ ОКНО ================== -->
 81        <div class="modal fade" id="transactionModal" tabindex="-1" aria-labelledby="transactionModalLabel"
 82             aria-hidden="true">
 83            <div class="modal-dialog modal-dialog-centered" style="max-width:500px">
 84                <div class="modal-content shadow">
 85
 86                    <div class="modal-header py-3">
 87                        <h5 class="modal-title text-white mb-0" id="transactionModalLabel">
 88                            <i class="fas fa-file-invoice me-2"></i>Данные приходного документа
 89                        </h5>
 90                        <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Закр
 91                    </div>
 92
 93                    <div class="modal-body px-4 pt-3 pb-2">
 94
 095                        @if (!string.IsNullOrEmpty(ViewData["ContractsWarning"] as string))
 96                        {
 97                            <div class="alert alert-warning alert-dismissible py-2 small mb-3">
 098                                <i class="fas fa-exclamation-triangle me-1"></i>@ViewData["ContractsWarning"]
 099                                @if (!string.IsNullOrEmpty(ViewData["SupplierEditUrl"] as string))
 100                                {
 101                                    <div class="mt-2">
 102                                        <a href="@ViewData["SupplierEditUrl"]" class="btn btn-sm btn-warning" target="_b
 103                                            <i class="fas fa-pen me-1"></i>Заполнить ИНН поставщика
 104                                        </a>
 105                                    </div>
 106                                }
 107                            </div>
 108                        }
 109
 110                        <!-- Обязательные поля -->
 111                        <p class="section-label mb-1"><i class="fas fa-asterisk required-star me-1"></i>Обязательные</p>
 112                        <hr class="mt-0 mb-3"/>
 113
 114                        <div class="mb-3">
 115                            <label for="ContractLink" class="form-label fw-semibold mb-1">
 116                                Договор <span class="required-star">*</span>
 117                            </label>
 0118                            @if (viewModel.Treaties != null && viewModel.Treaties.Any())
 119                            {
 120                                <select id="ContractLink" name="ContractLink" class="form-select">
 121                                    <option value="">— выберите договор —</option>
 0122                                    @foreach (var t in viewModel.Treaties)
 123                                    {
 0124                                        <option value="@t.Link">
 0125                                            @t.Name@(!string.IsNullOrEmpty(t.Partner) ? $" ({t.Partner})" : "")
 126                                        </option>
 127                                    }
 128                                </select>
 129                            }
 130                            else
 131                            {
 132                                <input type="text" id="ContractLink" name="ContractLink" class="form-control font-monosp
 133                                       placeholder="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx">
 134                                <div class="form-text text-muted small">Договоры не загружены — вставьте Ref_Key из 1С.<
 135                            }
 136                            <div class="field-error" id="errContract">Выберите или введите договор</div>
 137                        </div>
 138
 139                        <div class="mb-3">
 140                            <label for="ReceiptWarehouse" class="form-label fw-semibold mb-1">
 141                                Склад прихода <span class="required-star">*</span>
 142                            </label>
 143                            <input type="text" id="ReceiptWarehouse" name="ReceiptWarehouse" class="form-control"
 144                                   list="receiptWarehouseList" autocomplete="off"
 145                                   value="@defaultReceiptWarehouse"
 146                                   placeholder="Начните вводить название склада">
 147                            <datalist id="receiptWarehouseList">
 0148                                @foreach (var warehouse in viewModel.ZasylValues.Distinct(StringComparer.OrdinalIgnoreCa
 149                                {
 0150                                    <option value="@warehouse"></option>
 151                                }
 152                            </datalist>
 153                            <div class="form-text text-muted small">
 0154                                @(clientWarehouses.Count == 0
 0155                                    ? "У клиента в настройках склад не указан — выберите склад из списка."
 0156                                    : $"Склад клиента из настроек: {string.Join(", ", clientWarehouses)}. Можно выбрать 
 157                            </div>
 158                            <div class="field-error" id="errWarehouse">Выберите склад из списка 1С</div>
 159                        </div>
 160
 161                        <div class="row g-2 mb-3">
 162                            <div class="col-7">
 163                                <label for="NumberVh" class="form-label fw-semibold mb-1">
 164                                    Номер вх. документа <span class="required-star">*</span>
 165                                </label>
 166                                <input type="text" id="NumberVh" name="NumberVh" class="form-control"
 167                                       list="numberVhSuggestions" autocomplete="off"
 168                                       placeholder="Напр. УПД-2026/001">
 169                                <datalist id="numberVhSuggestions"></datalist>
 170                                <div class="form-text text-muted small" id="numberVhHint"></div>
 171                                <div class="field-error" id="errNumber">Введите номер документа</div>
 172                            </div>
 173                            <div class="col-5">
 174                                <label for="DateVh" class="form-label fw-semibold mb-1">
 175                                    Дата <span class="required-star">*</span>
 176                                </label>
 177                                <input type="date" id="DateVh" name="DateVh" class="form-control"
 178                                       value="@DateTime.Now.ToString("yyyy-MM-dd")">
 179                                <div class="field-error" id="errDate">Укажите дату</div>
 180                            </div>
 181                        </div>
 182
 183                        <div class="mb-3">
 184                            <button type="button" id="lookupInvoiceOrigin" class="btn btn-outline-secondary btn-sm">Пров
 185                            <div id="invoiceOriginPreview" class="small mt-2" role="status" aria-live="polite"></div>
 186                        </div>
 187
 188                        <!-- Дополнительные поля -->
 189                        <p class="section-label mb-1 mt-3">Дополнительные</p>
 190                        <hr class="mt-0 mb-3"/>
 191
 192                        <div class="mb-3">
 193                            <label for="VatRate" class="form-label fw-semibold mb-1">Ставка НДС</label>
 194                            <select id="VatRate" name="VatRate" class="form-select">
 195                                <option value="">Без НДС</option>
 196                                <option value="20">20%</option>
 197                                <option value="22" selected>22%</option>
 198                            </select>
 199                        </div>
 200
 201                        <div class="mb-1">
 202                            <label for="TransactionComment" class="form-label fw-semibold mb-1 d-flex justify-content-be
 203                                <span>Комментарий к документу 1С</span>
 204                                <button type="button" id="regenComment" class="btn btn-link p-0 text-muted text-decorati
 205                                    <i class="fas fa-rotate-right me-1"></i><small>Сгенерировать</small>
 206                                </button>
 207                            </label>
 208                            <textarea id="TransactionComment" name="TransactionComment" class="form-control" rows="2"
 209                                      placeholder="Автоматически заполнится при открытии"></textarea>
 210                            <div class="form-text text-muted" style="font-size:.75rem">
 211                                Формат: Отгружен поставщиком | пользователь | заказы
 212                            </div>
 213                        </div>
 214
 215                    </div>
 216
 217                    <div class="modal-footer bg-light py-2 px-4">
 218                        <button type="button" class="btn btn-outline-secondary btn-sm" data-bs-dismiss="modal">
 219                            <i class="fas fa-times me-1"></i>Отмена
 220                        </button>
 221                        <button type="button" id="confirmSubmit" class="btn btn-primary btn-sm px-4">
 222                            <i class="fas fa-check me-1"></i>Провести
 223                        </button>
 224                    </div>
 225                </div>
 226            </div>
 227        </div>
 228
 229        <input type="hidden" name="UserName" id="UserName" value="@(User.Identity?.Name ?? "")"/>
 230        <input type="hidden" name="Page" id="Page" value="@Model.RedirectPage"/>
 231
 232        <div class="tx-page-footer">
 233            <div class="input-group">
 234                <span class="input-group-btn">
 235                    <input type="button" value="Сохранить" id="openModalBtn"
 236                           style="width: 170px;"
 237                           class="btn btn-primary"
 238                           data-bs-toggle="modal"
 239                           data-bs-target="#transactionModal"/>
 240                </span>
 241            </div>
 242        </div>
 243    </form>
 244}
 245else
 246{
 0247    @await Html.PartialAsync("_TransactionErrorPanel")
 248}
 249
 250<div class="modal fade" id="staticBackdrop" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1"
 251     aria-labelledby="staticBackdropLabel" aria-hidden="true">
 252    <div class="modal-dialog">
 253        <div class="modal-content orders-modal orders-modal--primary">
 254            <div class="modal-header">
 255                <h5 class="modal-title" id="staticBackdropLabel">Создание журнала документов</h5>
 256                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Закрыть"></button>
 257            </div>
 258            <div class="modal-body">
 259                <div class="d-flex justify-content-center">
 260                    <div class="spinner-border text-primary" role="status">
 261                        <span class="sr-only">.</span>
 262                    </div>
 263                </div>
 264            </div>
 265        </div>
 266    </div>
 267</div>
 268
 269<div>
 270    <a asp-action="Index" class="tx-page-back-link">← К списку заказов</a>
 271</div>
 272
 273<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
 274    <div class="modal-dialog" role="document">
 275        <div class="modal-content orders-modal orders-modal--warning">
 276            <div class="modal-header">
 277                <h4 class="modal-title" id="myModalLabel">Поля не заполнены</h4>
 278            </div>
 279            <div class="modal-body">
 280                Одно или несколько полей не заполнены. Пожалуйста, заполните все поля перед отправкой формы.
 281            </div>
 282        </div>
 283    </div>
 284</div>
 285
 286
 287<!-- Модальное окно для отображения увеличенного изображения -->
 288<div class="modal fade" id="imageModal" tabindex="-1" aria-labelledby="imageModalLabel" aria-hidden="true">
 289    <div class="modal-dialog modal-dialog-centered">
 290        <div class="modal-content">
 291            <div class="modal-header">
 292                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
 293            </div>
 294            <div class="modal-body text-center">
 295                <img id="modalImage" src="" alt="Full Image" class="img-fluid rounded border">
 296            </div>
 297        </div>
 298    </div>
 299</div>
 300
 301<input type="hidden" id="DeletedOrders" name="DeletedOrders"/>
 302@* Скрипты таблицы нужны только когда она отрисована; на панели ошибки они падали на пустом DOM *@
 0303@if (orders.Count > 0)
 304{
 0305@await Html.PartialAsync("_TransactionScript", Model)
 306<script src="~/js/Studio2/receipt-invoice-origin.js" asp-append-version="true"></script>
 307
 308<script>
 309    document.addEventListener("DOMContentLoaded", function () {
 310        const openModalBtn       = document.getElementById("openModalBtn");
 311        const processIn1CChk     = document.getElementById("ProcessIn1C");
 312        const form               = document.getElementById("createOrderForm");
 313        const transactionModalEl = document.getElementById("transactionModal");
 314        const transactionModal   = new bootstrap.Modal(transactionModalEl);
 315        const unifiedOverlay     = document.getElementById("txSubmitOverlay");
 316
 317        // Данные заказов для авто-комментария
 0318        const orderNumbers = @Html.Raw(System.Text.Json.JsonSerializer.Serialize(
 0319            orders.Select(o => o.ShipmentNumber).Where(n => !string.IsNullOrEmpty(n)).ToList()
 0320        ));
 321        const userName = document.getElementById("UserName").value || "пользователь";
 322
 323        function buildAutoComment() {
 324            const nums = orderNumbers.length <= 8
 325                ? orderNumbers.join(", ")
 326                : orderNumbers.slice(0, 8).join(", ") + ` +${orderNumbers.length - 8}`;
 327            return `Отгружен поставщиком | ${userName} | ${nums}`;
 328        }
 329
 330        // === Авто-заполнение при открытии модалки ===
 331        transactionModalEl.addEventListener("show.bs.modal", function () {
 332            const dateEl = document.getElementById("DateVh");
 333            if (dateEl && !dateEl.value)
 334                dateEl.value = new Date().toISOString().split("T")[0];
 335
 336            const commentEl = document.getElementById("TransactionComment");
 337            if (commentEl && !commentEl.value.trim())
 338                commentEl.value = buildAutoComment();
 339
 340            // Сбрасываем состояния валидации при открытии
 341            ["ContractLink","ReceiptWarehouse","NumberVh","DateVh"].forEach(id => setValid(id, null));
 342        });
 343
 344        // === Кнопка «Сгенерировать» комментарий ===
 345        document.getElementById("regenComment").addEventListener("click", function () {
 346            document.getElementById("TransactionComment").value = buildAutoComment();
 347        });
 348
 349        // === Live-валидация обязательных полей ===
 350        function setValid(fieldId, valid) {
 351            const el  = document.getElementById(fieldId);
 352            const err = document.getElementById("err" + fieldId.replace("ContractLink","Contract")
 353                                                              .replace("ReceiptWarehouse","Warehouse")
 354                                                              .replace("NumberVh","Number")
 355                                                              .replace("DateVh","Date"));
 356            if (!el) return;
 357            el.classList.remove("is-invalid", "is-valid");
 358            if (err) err.classList.remove("visible");
 359            if (valid === true)  el.classList.add("is-valid");
 360            if (valid === false) { el.classList.add("is-invalid"); if (err) err.classList.add("visible"); }
 361        }
 362
 363        // Склад прихода принимаем только из справочника 1С (если он загружен): иначе 1С не найдёт склад по имени.
 364        const receiptWarehouseNames = new Set(Array.from(document.querySelectorAll("#receiptWarehouseList option"))
 365            .map(o => o.value.trim().toLowerCase()));
 366
 367        function validateField(fieldId) {
 368            const val = (document.getElementById(fieldId)?.value || "").trim();
 369            let valid = val.length > 0;
 370            if (valid && fieldId === "ReceiptWarehouse" && receiptWarehouseNames.size > 0)
 371                valid = receiptWarehouseNames.has(val.toLowerCase());
 372            setValid(fieldId, valid);
 373            return valid;
 374        }
 375
 376        ["ContractLink","ReceiptWarehouse","NumberVh","DateVh"].forEach(id => {
 377            const el = document.getElementById(id);
 378            if (el) el.addEventListener("input", () => validateField(id));
 379            if (el) el.addEventListener("change", () => validateField(id));
 380        });
 381
 382        // === Кнопка «Сохранить» ===
 383        openModalBtn.addEventListener("click", function (e) {
 384            e.preventDefault();
 385            if (processIn1CChk.checked) transactionModal.show();
 386            else { showLoadingModal(); form.submit(); }
 387        });
 388
 389        // === Подтверждение из модалки ===
 390        document.getElementById("confirmSubmit").addEventListener("click", async function () {
 391            const ok = ["ContractLink","ReceiptWarehouse","NumberVh","DateVh"].map(validateField);
 392            if (ok.includes(false)) return;   // остаёмся в модалке, показываем ошибки
 393            if (!await window.receiptInvoiceOrigin.ensureReady()) return;
 394            transactionModal.hide();
 395            showLoadingModal();
 396            form.submit();
 397        });
 398
 399        function showLoadingModal() {
 400            if (unifiedOverlay) unifiedOverlay.style.display = "flex";
 401        }
 402
 403        window.addEventListener("pageshow", () => {
 404            if (unifiedOverlay) unifiedOverlay.style.display = "none";
 405        });
 406    });
 407</script>
 408}