< Summary

Information
Class: AspNetCoreGeneratedDocument.Areas_Studio2_Views_Orders_MultiplayEditV2
Assembly: OzonOrdersWeb
File(s): /home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Areas/Studio2/Views/Orders/MultiplayEditV2.cshtml
Line coverage
0%
Covered lines: 0
Uncovered lines: 221
Coverable lines: 221
Total lines: 2203
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 500
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%4970700%
Col()0%620%
<ExecuteAsync()0%1463063820%
<ExecuteAsync()0%930300%
<ExecuteAsync()0%2040%
<ExecuteAsync()0%7280%
<ExecuteAsync()100%210%
<ExecuteAsync()0%2040%

File(s)

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

#LineLine coverage
 1@using OzonDomains
 2@using OzonDomains.Models
 3@using OzonOrdersWeb.ViewModels.OrderViewModels
 4
 5
 6@model MultiplayEditOrderViewModel
 7
 8@{
 09    var orders = Model.Orders;
 010    var ordersCount = orders.Count;
 011    ViewData["Title"] = $"Массовое редактирование заказов ({ordersCount} шт.)";
 012    Layout = "~/Views/Shared/_Layout.cshtml";
 013    var fieldMap = Model.OrderListFieldReadAccess;
 014    bool Col(string fieldName) => fieldMap == null || fieldMap.GetValueOrDefault(fieldName, true);
 15}
 16@*
 17<script asp-src-include="~/js/**/*.js"></script> *@
 18<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
 19<script src="~/js/copyArticle.js"></script>
 20
 21<partial name="~/Areas/Studio2/Views/Partials/Transaction/_TransactionPageStyles.cshtml"/>
 22<link rel="stylesheet" href="~/css/Studio2/Orders/TransactionsTable.css" asp-append-version="true"/>
 23<link rel="stylesheet" href="~/css/Studio2/Orders/productImageCell.css" asp-append-version="true"/>
 24<link rel="stylesheet" href="~/css/Studio2/Orders/MultiplayEditV2.css" asp-append-version="true"/>
 25<script src="~/js/Studio2/Orders/transaction-row-status.js" asp-append-version="true"></script>
 26
 027@if (Model.ErrorMessage != null)
 28{
 29    <div class="alert alert-dismissible alert-danger">
 30        <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
 031        <p>@Html.Raw(Model.ErrorMessage)</p>
 32    </div>
 33}
 34<div class="form-row d-flex">
 35    <div class="form-group col-sm-3" style="display: none;">
 36        <label for="universalField" class="col-form-label">Цена закупки:</label>
 37        <input type="text" class="form-control" id="universalField"/>
 38    </div>
 39</div>
 40
 41<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
 42    <div class="modal-dialog">
 43        <div class="modal-content">
 44            <div class="modal-header">
 45                <h5 class="modal-title" id="exampleModalLabel">Выберите столбцы для отображения</h5>
 46                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Закрыть"></button>
 47            </div>
 48            <div class="modal-body-checkbox">
 49                <div class="container mt-3">
 50                    <div class="form-group">
 51                        <div class="form-row">
 52                            <button type="button" class="btn btn-danger" onclick="clearSelectedIdsCookie()">Очистить
 53                                выбранные поля для изменения
 54                            </button>
 55                            <br/>
 56                            <br/>
 57                            @{
 058                                int checkboxCounter = 1;
 59                            }
 060                            @if (Col("ShipmentNumber"))
 61                            {
 62                                <div class="form-group col-md-5">
 63                                    <input type="checkbox" class="form-check-input" id="chk@(checkboxCounter)" checked>
 64                                    <label class="form-check-label" for="chk@(checkboxCounter)">Номер заказа</label>
 65                                </div>
 066                                checkboxCounter++;
 67                            }
 068                            @if (Col("OzonClient"))
 69                            {
 70                                <div class="form-group col-md-5">
 71                                    <input type="checkbox" class="form-check-input" id="chk@(checkboxCounter)" checked>
 72                                    <label class="form-check-label" for="chk@(checkboxCounter)">Клиент</label>
 73                                </div>
 074                                checkboxCounter++;
 75                            }
 076                            @if (Col("ProcessingDate"))
 77                            {
 78                                <div class="form-group col-md-5">
 79                                    <input type="checkbox" class="form-check-input" id="chk@(checkboxCounter)" checked>
 80                                    <label class="form-check-label" for="chk@(checkboxCounter)">Принят в
 81                                        обработку</label>
 82                                </div>
 083                                checkboxCounter++;
 84                            }
 085                            @if (Col("ShippingDate"))
 86                            {
 87                                <div class="form-group col-md-5">
 88                                    <input type="checkbox" class="form-check-input" id="chk@(checkboxCounter)" checked>
 89                                    <label class="form-check-label" for="chk@(checkboxCounter)">Дата отгрузки</label>
 90                                </div>
 091                                checkboxCounter++;
 92                            }
 093                            @if (Col("DeliveryPeriod"))
 94                            {
 95                                <div class="form-group col-md-5">
 96                                    <input type="checkbox" class="form-check-input" id="chk@(checkboxCounter)" checked>
 97                                    <label class="form-check-label" for="chk@(checkboxCounter)">Срок доставки</label>
 98                                </div>
 099                                checkboxCounter++;
 100                            }
 0101                            @if (Col("ClientStatus"))
 102                            {
 103                                <div class="form-group col-md-5">
 104                                    <input type="checkbox" class="form-check-input" id="chk@(checkboxCounter)" checked>
 105                                    <label class="form-check-label" for="chk@(checkboxCounter)">Статус клиента</label>
 106                                </div>
 0107                                checkboxCounter++;
 108                            }
 0109                            @if (Col("AppStatus"))
 110                            {
 111                                <div class="form-group col-md-5">
 112                                    <input type="checkbox" class="form-check-input" id="chk@(checkboxCounter)" checked>
 113                                    <label class="form-check-label" for="chk@(checkboxCounter)">Статус</label>
 114                                </div>
 0115                                checkboxCounter++;
 116                            }
 0117                            @if (Col("ProductName"))
 118                            {
 119                                <div class="form-group col-md-7">
 120                                    <input type="checkbox" class="form-check-input" id="chk@(checkboxCounter)" checked>
 121                                    <label class="form-check-label" for="chk@(checkboxCounter)">Наименование
 122                                        товара</label>
 123                                </div>
 0124                                checkboxCounter++;
 125                            }
 0126                            @if (Col("Article"))
 127                            {
 128                                <div class="form-group col-md-5">
 129                                    <input type="checkbox" class="form-check-input" id="chk@(checkboxCounter)" checked>
 130                                    <label class="form-check-label" for="chk@(checkboxCounter)">Артикул</label>
 131                                </div>
 0132                                checkboxCounter++;
 133                            }
 0134                            @if (Col("Manufacturer"))
 135                            {
 136                                <div class="form-group col-md-5">
 137                                    <input type="checkbox" class="form-check-input" id="chk@(checkboxCounter)" checked>
 138                                    <label class="form-check-label" for="chk@(checkboxCounter)">Производитель</label>
 139                                </div>
 0140                                checkboxCounter++;
 141                            }
 0142                            @if (Col("ShipmentWarehouse"))
 143                            {
 144                                <div class="form-group col-md-5">
 145                                    <input type="checkbox" class="form-check-input" id="chk@(checkboxCounter)" checked>
 146                                    <label class="form-check-label" for="chk@(checkboxCounter)">Склад отгрузки</label>
 147                                </div>
 0148                                checkboxCounter++;
 149                            }
 0150                            @if (Col("Supplier"))
 151                            {
 152                                <div class="form-group col-md-5">
 153                                    <input type="checkbox" class="form-check-input" id="chk@(checkboxCounter)" checked>
 154                                    <label class="form-check-label" for="chk@(checkboxCounter)">Поставщик</label>
 155                                </div>
 0156                                checkboxCounter++;
 157                            }
 0158                            @if (Col("SupplierOrderNumber"))
 159                            {
 160                                <div class="form-group col-md-6">
 161                                    <input type="checkbox" class="form-check-input" id="chk@(checkboxCounter)" checked>
 162                                    <label class="form-check-label" for="chk@(checkboxCounter)">Номер заказа
 163                                        поставщику</label>
 164                                </div>
 0165                                checkboxCounter++;
 166                            }
 0167                            @if (Col("SitePrice"))
 168                            {
 169                                <div class="form-group col-md-5">
 170                                    <input type="checkbox" class="form-check-input" id="chk@(checkboxCounter)" checked>
 171                                    <label class="form-check-label" for="chk@(checkboxCounter)">Цена сайта</label>
 172                                </div>
 0173                                checkboxCounter++;
 174                            }
 0175                            @if (Col("Price"))
 176                            {
 177                                <div class="form-group col-md-5">
 178                                    <input type="checkbox" class="form-check-input" id="chk@(checkboxCounter)" checked>
 179                                    <label class="form-check-label" for="chk@(checkboxCounter)">Цена</label>
 180                                </div>
 0181                                checkboxCounter++;
 182                            }
 0183                            @if (Col("Quantity"))
 184                            {
 185                                <div class="form-group col-md-5">
 186                                    <input type="checkbox" class="form-check-input" id="chk@(checkboxCounter)" checked>
 187                                    <label class="form-check-label" for="chk@(checkboxCounter)">Кол.</label>
 188                                </div>
 0189                                checkboxCounter++;
 190                            }
 0191                            @if (Col("ShipmentTotal"))
 192                            {
 193                                <div class="form-group col-md-5">
 194                                    <input type="checkbox" class="form-check-input" id="chk@(checkboxCounter)" checked>
 195                                    <label class="form-check-label" for="chk@(checkboxCounter)">Сумма
 196                                        отправления</label>
 197                                </div>
 0198                                checkboxCounter++;
 199                            }
 0200                            @if (Col("Category"))
 201                            {
 202                                <div class="form-group col-md-5">
 203                                    <input type="checkbox" class="form-check-input" id="chk@(checkboxCounter)" checked>
 204                                    <label class="form-check-label" for="chk@(checkboxCounter)">Категория</label>
 205                                </div>
 0206                                checkboxCounter++;
 207                            }
 0208                            @if (Col("VolumeWeight"))
 209                            {
 210                                <div class="form-group col-md-5">
 211                                    <input type="checkbox" class="form-check-input" id="chk@(checkboxCounter)" checked>
 212                                    <label class="form-check-label" for="chk@(checkboxCounter)">Объемный вес</label>
 213                                </div>
 0214                                checkboxCounter++;
 215                            }
 0216                            @if (Col("PurchasePrice"))
 217                            {
 218                                <div class="form-group col-md-5">
 219                                    <input type="checkbox" class="form-check-input" id="chk@(checkboxCounter)" checked>
 220                                    <label class="form-check-label" for="chk@(checkboxCounter)">Цена закупки</label>
 221                                </div>
 0222                                checkboxCounter++;
 223                            }
 0224                            @if (Col("OzonCommission"))
 225                            {
 226                                <div class="form-group col-md-5">
 227                                    <input type="checkbox" class="form-check-input" id="chk@(checkboxCounter)" checked>
 228                                    <label class="form-check-label" for="chk@(checkboxCounter)">Комиссия Ozon</label>
 229                                </div>
 0230                                checkboxCounter++;
 231                            }
 0232                            @if (Col("Profit"))
 233                            {
 234                                <div class="form-group col-md-5">
 235                                    <input type="checkbox" class="form-check-input" id="chk@(checkboxCounter)" checked>
 236                                    <label class="form-check-label" for="chk@(checkboxCounter)">Прибыль</label>
 237                                </div>
 0238                                checkboxCounter++;
 239                            }
 0240                            @if (Col("MarkupPercent"))
 241                            {
 242                                <div class="form-group col-md-5">
 243                                    <input type="checkbox" class="form-check-input" id="chk@(checkboxCounter)" checked>
 244                                    <label class="form-check-label" for="chk@(checkboxCounter)">Наценка %</label>
 245                                </div>
 0246                                checkboxCounter++;
 247                            }
 0248                            @if (Col("Cost"))
 249                            {
 250                                <div class="form-group col-md-5">
 251                                    <input type="checkbox" class="form-check-input" id="chk@(checkboxCounter)" checked>
 252                                    <label class="form-check-label" for="chk@(checkboxCounter)">Себестоимость</label>
 253                                </div>
 0254                                checkboxCounter++;
 255                            }
 0256                            @if (Col("DeliveryCity"))
 257                            {
 258                                <div class="form-group col-md-5">
 259                                    <input type="checkbox" class="form-check-input" id="chk@(checkboxCounter)" checked>
 260                                    <label class="form-check-label" for="chk@(checkboxCounter)">Город доставки</label>
 261                                </div>
 0262                                checkboxCounter++;
 263                            }
 264                        </div>
 265                    </div>
 266                </div>
 267            </div>
 268
 269            <div class="modal-footer">
 270                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button>
 271            </div>
 272        </div>
 273    </div>
 274</div>
 275
 276<!-- Модальное окно просмотра картинки продукта -->
 277<div id="productImageModal" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true">
 278    <div class="modal-dialog modal-dialog-centered" style="max-width: 600px;">
 279        <div class="modal-content">
 280            <div class="modal-header py-2">
 281                <h6 class="modal-title text-truncate" id="productImageModalTitle"></h6>
 282                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Закрыть"></button>
 283            </div>
 284            <div class="modal-body text-center p-2">
 285                <img id="productImageModalImg" src="" alt=""
 286                     style="max-width: 100%; max-height: 70vh; object-fit: contain;" />
 287            </div>
 288        </div>
 289    </div>
 290</div>
 291
 292<script>
 293    function openProductImage(src, title) {
 294        var img = document.getElementById('productImageModalImg');
 295        var titleEl = document.getElementById('productImageModalTitle');
 296
 297        if (img) {
 298            img.src = src || '';
 299        }
 300
 301        if (titleEl) {
 302            titleEl.textContent = title || '';
 303        }
 304
 305        var modalEl = document.getElementById('productImageModal');
 306        if (modalEl) {
 307            new bootstrap.Modal(modalEl).show();
 308        }
 309    }
 310</script>
 311
 312<form asp-area="Studio2" asp-controller="Orders" asp-action="MultiplayEditV2">
 313    <div asp-validation-summary="ModelOnly" class="text-danger"></div>
 314    <input type="hidden" asp-for="RedirectPage"/>
 315    <div class="tx-transaction-page">
 316    <div class="table-container table-edge-flush">
 317        <table class="table transaction-table multiplay-edit-table" id="shipmentTable">
 318            <colgroup id="tableColgroup"></colgroup>
 319            <partial name="~/Areas/Studio2/Views/Partials/Transaction/_MultiplayEditV2TableHead.cshtml" model="Model"/>
 320            <tbody>
 321
 0322            @for (int i = 0; i < orders.Count; i++)
 323            {
 0324                var order = orders[i];
 0325                string rowClass = "custom-white";
 0326                if ((order.AppStatus?.Name == "Отменен" && (order.ClientStatus?.Name == "Отменён" || order.ClientStatus 
 0327                    order.ClientStatus?.Name is "Отменен" or "Отменён")
 328                {
 0329                    rowClass = "table-danger";
 330                }
 0331                else if (order.IsReturnable == true)
 332                {
 0333                    rowClass = "custom-red";
 334                }
 335                else
 336                {
 0337                    rowClass = order.AppStatus?.Name switch
 0338                    {
 0339                        "Заказан поставщику" => "table-success",
 0340                        "Отгружен поставщиком" => "table-info",
 0341                        "Отгружен реализатору" => "table-warning",
 0342                        "Заказан реализатору" => "table-secondary",
 0343                        _ => rowClass
 0344                    };
 345                }
 346
 347                <tr id="orderRow_@Model.Orders[i].Id" class="@rowClass transaction-order-row"
 0348                    data-original-row-class="@rowClass">
 349                    <div class="form-group" style="display: none">
 350                        <label asp-for="Orders[i].Id" class="control-label"></label><span
 351                            style="margin-left: 10px; color: gray;">/ </span>
 352                        <input asp-for="Orders[i].Id" class="form-control"/>
 353                        <span asp-validation-for="Orders[i].Id" class="text-danger"></span>
 354                    </div>
 355                    <div class="form-group" style="display: none">
 356                        <label asp-for="Orders[i].Key" class="control-label"></label><span
 357                            style="margin-left: 10px; color: gray;">/ </span>
 358                        <input asp-for="Orders[i].Key" class="form-control"/>
 359                        <span asp-validation-for="Orders[i].Key" class="text-danger"></span>
 360                    </div>
 361                    <div class="form-group" style="display: none">
 362                        <label asp-for="Orders[i].ShipmentNumber" class="control-label"></label><span
 363                            style="margin-left: 10px; color: gray;">/ </span>
 364                        <input asp-for="Orders[i].ShipmentNumber" class="form-control"/>
 365                        <span asp-validation-for="Orders[i].ShipmentNumber" class="text-danger"></span>
 366                    </div>
 367                    <div class="form-group" style="display: none">
 368                        <input type="hidden" asp-for="Orders[i].OzonClientId"/>
 369                    </div>
 370                    <div class="form-group" style="display: none">
 371                        <label asp-for="Orders[i].ProcessingDate" class="control-label"></label><span
 372                            style="margin-left: 10px; color: gray;">/ </span>
 373                        <input asp-for="Orders[i].ProcessingDate" class="form-control"/>
 374                        <span asp-validation-for="Orders[i].ProcessingDate" class="text-danger"></span>
 375                    </div>
 376                    <div class="form-group" style="display: none">
 377                        <label asp-for="Orders[i].ShippingDate" class="control-label"></label><span
 378                            style="margin-left: 10px; color: gray;">/ </span>
 379                        <input asp-for="Orders[i].ShippingDate" class="form-control"/>
 380                        <span asp-validation-for="Orders[i].ShippingDate" class="text-danger"></span>
 381                    </div>
 382                    <div class="form-group" style="display: none">
 383                        <label asp-for="Orders[i].Status" class="control-label"></label><span
 384                            style="margin-left: 10px; color: gray;">/ </span>
 385                        <input asp-for="Orders[i].Status" class="form-control"/>
 386                        <span asp-validation-for="Orders[i].Status" class="text-danger"></span>
 387                    </div>
 388                    <div class="form-group" style="display: none">
 389                        <label asp-for="Orders[i].ProductName" class="control-label"></label><span
 390                            style="margin-left: 10px; color: gray;">/ </span>
 391                        <input asp-for="Orders[i].ProductName" class="form-control"/>
 392                        <span asp-validation-for="Orders[i].ProductName" class="text-danger"></span>
 393                    </div>
 394                    <div class="form-group" style="display: none">
 395                        <label asp-for="Orders[i].ProductKey" class="control-label"></label><span
 396                            style="margin-left: 10px; color: gray;">/ </span>
 397                        <input asp-for="Orders[i].ProductKey" class="form-control"/>
 398                        <span asp-validation-for="Orders[i].ProductKey" class="text-danger"></span>
 399                    </div>
 400                    <div class="form-group" style="display: none">
 401                        <label asp-for="Orders[i].Quantity" class="control-label"></label><span
 402                            style="margin-left: 10px; color: gray;">/ </span>
 403                        <input asp-for="Orders[i].Quantity" class="form-control"/>
 404                        <span asp-validation-for="Orders[i].Quantity" class="text-danger"></span>
 405                    </div>
 406                    <div class="form-group" style="display: none">
 407                        <label asp-for="Orders[i].ShipmentAmount" class="control-label"></label><span
 408                            style="margin-left: 10px; color: gray;">/ </span>
 409                        <input asp-for="Orders[i].ShipmentAmount" class="form-control"/>
 410                        <span asp-validation-for="Orders[i].ShipmentAmount" class="text-danger"></span>
 411                    </div>
 412                    <div class="form-group" style="display: none">
 413                        <label asp-for="Orders[i].Price" class="control-label"></label><span
 414                            style="margin-left: 10px; color: gray;">/ </span>
 415                        <input asp-for="Orders[i].Price" class="form-control"/>
 416                        <span asp-validation-for="Orders[i].Price" class="text-danger"></span>
 417                    </div>
 418                    <div class="form-group" style="display: none">
 419                        <label asp-for="Orders[i].MinOzonCommission" class="control-label"></label><span
 420                            style="margin-left: 10px; color: gray;">/ </span>
 421                        <input asp-for="Orders[i].MinOzonCommission" class="form-control"/>
 422                        <span asp-validation-for="Orders[i].MinOzonCommission" class="text-danger"></span>
 423                    </div>
 424                    <div class="form-group" style="display: none">
 425                        <label asp-for="Orders[i].MaxOzonCommission" class="control-label"></label><span
 426                            style="margin-left: 10px; color: gray;">/ </span>
 427                        <input asp-for="Orders[i].MaxOzonCommission" class="form-control"/>
 428                        <span asp-validation-for="Orders[i].MaxOzonCommission" class="text-danger"></span>
 429                    </div>
 430                    <div class="form-group" style="display: none">
 431                        <label asp-for="Orders[i].MaxProfit" class="control-label"></label><span
 432                            style="margin-left: 10px; color: gray;">/ </span>
 433                        <input asp-for="Orders[i].MaxProfit" class="form-control"/>
 434                        <span asp-validation-for="Orders[i].MaxProfit" class="text-danger"></span>
 435                    </div>
 436                    <div class="form-group" style="display: none">
 437                        <label asp-for="Orders[i].MinDiscount" class="control-label"></label><span
 438                            style="margin-left: 10px; color: gray;">/ </span>
 439                        <input asp-for="Orders[i].MinDiscount" class="form-control"/>
 440                        <span asp-validation-for="Orders[i].MinDiscount" class="text-danger"></span>
 441                    </div>
 442                    <div class="form-group" style="display: none">
 443                        <label asp-for="Orders[i].DeliveryCity" class="control-label"></label><span
 444                            style="margin-left: 10px; color: gray;">/ </span>
 445                        <input asp-for="Orders[i].DeliveryCity" class="form-control"/>
 446                        <span asp-validation-for="Orders[i].DeliveryCity" class="text-danger"></span>
 447                    </div>
 448
 449                    <div class="form-group" style="display: none">
 450                        <label asp-for="Orders[i].UpdatedBy" class="control-label"></label><span
 451                            style="margin-left: 10px; color: gray;">/ </span>
 0452                        <input asp-for="Orders[i].UpdatedBy" class="form-control" value="@User.Identity?.Name"/>
 453                        <span asp-validation-for="Orders[i].UpdatedBy" class="text-danger"></span>
 454                    </div>
 455
 456
 457
 458                    <input type="hidden" asp-for="Orders[i].ProductInfoId"/>
 0459                    @if (Col("ShipmentNumber"))
 460                    {
 461                    <td data-column="shipmentNumber">
 462                        <div class="two-row-cell">
 463                            <div class="cell-row" style="justify-content: flex-start;">
 464                            <span onclick="copyArticle(this)" class="ml-2" role="button">
 0465                                @Html.DisplayFor(modelItem => Model.Orders[i].ShipmentNumber)
 0466                                @if (Model.Orders[i].ShipmentNumber is { } shipmentNumV2
 0467                                     && shipmentNumV2 != ""
 0468                                     && Model.UniqueNumbers.TryGetValue(shipmentNumV2.Split('-')[0], out var shipmentCou
 0469                                     && shipmentCount != 1)
 470                                {
 0471                                    <a href="#">(@shipmentCount)</a>
 472                                }
 473                            </span>
 474                            </div>
 475                            <div class="text-muted cell-row" style="white-space: nowrap; justify-content: flex-start;">
 476                                @{
 0477                                    string? delivery = Model.Orders[i].Delivery?.Provider?.Name;
 478
 0479                                    if (!string.IsNullOrEmpty(delivery) && delivery.Length > 20)
 480                                    {
 0481                                        delivery = delivery.Substring(0, 20) + "...";
 482                                    }
 483
 0484                                    <div title="@Model.Orders[i].Delivery?.Name">@delivery</div>
 485                                }
 486                            </div>
 487                        </div>
 488                    </td>
 489                    }
 490                    <td style="vertical-align: middle;">
 491                        <div class="two-row-cell">
 492                            <div class="cell-row" style="justify-content: flex-start;">
 493                                <div title="@Model.Orders[i].OzonClient">
 0494                                    @if (Model.Orders[i].OzonClient != null)
 495                                    {
 0496                                        string? ozonClient = Model.Orders[i].OzonClient?.Name;
 0497                                        if (!string.IsNullOrEmpty(ozonClient) && ozonClient.Length > 18)
 498                                        {
 0499                                            ozonClient = ozonClient.Substring(0, 18) + "...";
 500                                        }
 501
 0502                                        @ozonClient
 503                                    }
 504                                </div>
 505                            </div>
 506
 507                            <div class="cell-row text-muted" style="justify-content: flex-start; white-space: nowrap;">
 0508                                @if (Model.Orders[i].DeliveryCity != null && Model.Orders[i].DeliveryCity != "")
 509                                {
 510                                    <div title="@Model.Orders[i].DeliveryCity">
 511                                        @{
 0512                                            string? deliveryCity = Model.Orders[i].DeliveryCity;
 0513                                            if (!string.IsNullOrEmpty(deliveryCity) && deliveryCity.Length > 11)
 514                                            {
 0515                                                deliveryCity = deliveryCity.Substring(0, 11) + "...";
 516                                            }
 517
 0518                                            @deliveryCity
 519                                        }
 0520                                        @if (Model.Orders[i].DeliveryCity is { } dcKey && Model.UniqueDeliveryCitys.Cont
 521                                        {
 522                                            <a href="#"
 0523                                               style="margin-left: 2px;">(@Model.UniqueDeliveryCitys[dcKey])</a>
 524                                        }
 525                                    </div>
 526                                }
 527                            </div>
 0528                            @if (!string.IsNullOrEmpty(Model.Orders[i].TrackingNumber))
 529                            {
 530                                <div class="cell-row text-muted" style="white-space: nowrap;" title="@Model.Orders[i].Tr
 0531                                    <small>@Model.Orders[i].TrackingNumber</small>
 532                                </div>
 533                            }
 534                        </div>
 535                    </td>
 536
 537                    <td data-column="dates">
 538                        <div class="two-row-cell">
 539                            <div class="cell-row"
 540                                 id="td2ProcessingDate"
 541                                 title="@Html.DisplayFor(modelItem => Model.Orders[i].FullFormattedProcessingDate)">
 0542                                @OrderDateDisplay.FormatTableDateFull(Model.Orders[i].ProcessingDate)
 543                            </div>
 544
 545                            <div class="cell-row text-muted"
 546                                 title="@Html.DisplayFor(modelItem => Model.Orders[i].FullFormattedShippingDate)">
 0547                                @OrderDateDisplay.FormatTableDateFull(Model.Orders[i].ShippingDate)
 548                            </div>
 549                        </div>
 550                    </td>
 551
 552                    <td data-column="period">
 553                        <div class="two-row-cell">
 554                            <div class="cell-row orders-period-row">
 555                                <div title="@Html.DisplayFor(modelItem => Model.Orders[i].FormattedDeliveryDay) @Html.Di
 0556                                    @Html.DisplayFor(modelItem => Model.Orders[i].FormattedDeliveryDay)
 557                                </div>
 558                            </div>
 559
 560                            <div class="cell-row text-muted orders-period-row">
 0561                                <div>@Html.DisplayFor(modelItem => Model.Orders[i].FormattedTimeLeftDay)</div>
 562                            </div>
 563                        </div>
 564                    </td>
 565
 566                    <td class="orders-product-col" data-column="productInfo" style="vertical-align: middle;">
 567                        <div class="d-flex orders-product-cell">
 0568                            @if (!string.IsNullOrEmpty(Model.Orders[i].ProductInfo?.ImageUrl))
 569                            {
 570                                <img src="@Model.Orders[i].ProductInfo?.ImageUrl"
 571                                     alt="@(Model.Orders[i].ProductName ?? Model.Orders[i].Article)"
 572                                     class="product-thumb flex-shrink-0"
 573                                     onclick="openProductImage(this.src, this.alt)"
 574                                     onerror="this.style.display='none'"
 575                                     loading="lazy" />
 576                            }
 577                            <div class="orders-product-text-grid" style="min-width: 0; flex: 1; overflow: hidden; displa
 578                                <div class="orders-product-top-row">
 579                                    <div id="thArticle" class="product-key-cell d-flex align-items-center mb-0"
 580                                         title="@Model.Orders[i].ProductKey">
 581                                        <div style="white-space: nowrap; overflow: hidden; text-overflow: clip;">
 0582                                            @Model.Orders[i].ProductKey
 583                                        </div>
 584                                    </div>
 585
 586                                    <div id="thManufacturer"
 587                                         class="product-manufacturer-cell d-flex flex-column mb-0 nowrap text-center">
 0588                                        @(Model.Orders[i].EtProducer?.Name)
 589                                    </div>
 590
 591                                    <div id="thArticle2"
 592                                         class="article-and-replacement-cell d-flex flex-column mb-0 nowrap text-end ali
 0593                                        @if (Model.Orders[i].Article != null)
 594                                        {
 595                                            <div style="white-space: nowrap; overflow: hidden; text-overflow: clip; min-
 0596                                                @Html.DisplayFor(modelItem => Model.Orders[i].Article)
 597                                            </div>
 598                                        }
 599                                    </div>
 600                                </div>
 601                                <div class="d-flex align-items-center flex-nowrap orders-product-name-row" style="min-wi
 602                                    @{
 0603                                        var productName = Model.Orders[i].ProductName;
 0604                                        var truncatedName = string.IsNullOrEmpty(productName)
 0605                                            ? productName
 0606                                            : (productName.Length > 110 ? productName.Substring(0, 110) + "..." : produc
 607                                    }
 608                                    <div id="thProductName" class="text-muted product-name-cell" title="@productName"
 609                                         style="overflow: hidden; white-space: nowrap; text-overflow: ellipsis; flex: 1 
 0610                                        @truncatedName
 611                                    </div>
 612                                    <button type="button"
 613                                            class="btn btn-link p-0 replacement-link-toggle flex-shrink-0"
 0614                                            data-product-info-id="@Model.Orders[i].ProductInfoId"
 0615                                            data-original-article="@Model.Orders[i].Article"
 616                                            title="Связать с другим продуктом">
 617                                        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"
 618                                             fill="currentColor" class="bi bi-link-45deg" viewBox="0 0 16 16">
 619                                            <path
 620                                                d="M4.715 6.542 3.343 7.914a3 3 0 1 0 4.243 4.243l1.828-1.829A3 3 0 0 0 
 621                                            <path
 622                                                d="M6.586 4.672A3 3 0 0 0 7.414 9.5l.775-.776a2 2 0 0 1-.896-3.346L9.12 
 623                                        </svg>
 624                                    </button>
 625                                    <div class="replacement-input-wrapper flex-shrink-0">
 626                                        <input type="text"
 627                                               class="form-control form-control-sm replacement-article-input"
 628                                               placeholder="Артикул замены"
 0629                                               data-product-info-id="@Model.Orders[i].ProductInfoId"
 0630                                               data-original-article="@Model.Orders[i].Article"
 631                                               data-replacement-article=""
 632                                               title="Введите артикул продукта-замены для связи"/>
 633                                    </div>
 634                                </div>
 635                            </div>
 636                        </div>
 637                    </td>
 638
 639                    <td class="permanent-col actions-col-cell" data-column="actionsCol">
 640                        <span class="visually-hidden">Действия</span>
 641                    </td>
 642
 643                    <td class="vertical-align: middle;" data-column="status">
 644                        <div class="two-row-cell order-status-cell">
 645                            <div class="cell-row order-status-cell__client" style="justify-content: flex-start;">
 646                                <div class="nowrap" title="@Model.Orders[i].Status">
 0647                                    @if (Model.Orders[i].Status != null)
 648                                    {
 0649                                        string? status = Model.Orders[i].Status;
 0650                                        if (!string.IsNullOrEmpty(status) && status.Length > 12)
 651                                        {
 0652                                            status = status.Substring(0, 12) + "...";
 653                                        }
 654
 0655                                        @status
 656                                    }
 657                                    else
 658                                    {
 659                                        <br/>
 660                                    }
 661                                </div>
 662                            </div>
 663
 664                            <div class="cell-row text-muted order-status-cell__app">
 665                                <div class="status-select-stack">
 666                                    <select asp-for="Orders[i].AppStatusId"
 667                                            class="form-control form-control-sm status-select custom-select-init"
 668                                            id="AppStatusId_@Model.Orders[i].Id">
 669                                        <option value="">Выберите значение</option>
 0670                                        @foreach (var status in ViewBag.AppStatuses)
 671                                        {
 0672                                            var color = ViewBag.StatusColors[status.Value] as string;
 0673                                            var isSelected = status.Value == Model.Orders[i].AppStatusId?.ToString();
 0674                                            <option value="@status.Value" data-color="@color" selected="@isSelected"
 675                                                    style="background-color: @color; color: @StatusColorContrast.GetText
 0676                                                @status.Text
 677                                            </option>
 678                                        }
 679                                    </select>
 680                                </div>
 681                            </div>
 682                        </div>
 683                    </td>
 684
 685                    <td>
 686                        <div class="two-row-cell">
 687                            <div class="cell-row">
 688                                <div
 689                                    class="@(Model.Orders[i].UpdatedColumns is { } updatedCols && updatedCols.Contains("
 0690                                    @(Model.Orders[i].ShipmentWarehouse?.Name)
 691                                </div>
 692                            </div>
 693                            <div class="cell-row text-muted">
 0694                                @if (Col("ShipmentWarehouse"))
 695                                {
 696                                    <div class="form-group mb-0" style="width: 100%;">
 697                                        @{
 698                                            // Находим расширение с ключом "Засыл"
 0699                                            var zasylValue = Model.Orders[i].OrderExtensions?
 0700                                                .FirstOrDefault(e => e.Key == "Засыл")?.Value;
 701                                        }
 702
 703                                        <div class="position-relative" style="width: 100%;">
 704                                            <input type="text"
 705                                                   name="orderSupplierMap[@Model.Orders[i].Id]"
 706                                                   id="orderSupplierMap_@Model.Orders[i].Id"
 707                                                   class="form-control form-control-sm zasyl-input combobox-input"
 708                                                   placeholder="Засыл"
 709                                                   value="@(zasylValue ?? string.Empty)"
 710                                                   autocomplete="off"
 711                                                   aria-haspopup="listbox"
 712                                                   aria-expanded="false"
 713                                                   style="width: 100%;"/>
 714
 715                                            <ul class="list-group combobox-menu"
 716                                                id="zasylMenu_@Model.Orders[i].Id"
 717                                                style="position:absolute; z-index:9999; width:100%; max-height:200px; ov
 0718                                                @if (Model.Warehouses != null && Model.Warehouses.Any())
 719                                                {
 0720                                                    @foreach (var w in Model.Warehouses)
 721                                                    {
 722                                                        <li class="list-group-item list-group-item-action combobox-item"
 0723                                                            data-value="@w.Name" role="option">@w.Name</li>
 724                                                    }
 725                                                }
 0726                                                @if (Model.ZasylValues != null && Model.ZasylValues.Any())
 727                                                {
 0728                                                    @foreach (var zasyl in Model.ZasylValues)
 729                                                    {
 730                                                        <li class="list-group-item list-group-item-action combobox-item"
 0731                                                            data-value="@zasyl" role="option">@zasyl</li>
 732                                                    }
 733                                                }
 734                                            </ul>
 735
 736                                            <script>
 737                                                document.addEventListener('DOMContentLoaded', () => {
 0738                                                    new Combobox('orderSupplierMap_@Model.Orders[i].Id', 'zasylMenu_@Mod
 739                                                });
 740                                            </script>
 741
 742                                        </div>
 743                                    </div>
 744                                }
 745                            </div>
 746
 747                        </div>
 748                    </td>
 749
 750
 751                    <td class="vertical-align: middle;" data-column="supplier">
 752                        <div class="two-row-cell" style="gap: 1px; min-width: 0;">
 753                            <div class="form-group cell-row mb-0" style="width: 100%; min-width: 0;">
 754                                <select asp-for="Orders[i].SupplierId" asp-items="@ViewBag.Suppliers"
 755                                        class="form-control form-control-sm supplier-select custom-select-init"
 756                                        id="SupplierId_@Model.Orders[i].Id">
 757                                    <option value="">Выберите поставщика</option>
 0758                                    @foreach (var supplier in Model.Suppliers)
 759                                    {
 0760                                        <option value="@supplier.Id"
 0761                                                data-currency-code="@supplier.CurrencyCode"
 0762                                                data-cost-factor="@supplier.CostFactor"
 0763                                                data-weight-factor="@supplier.WeightFactor"
 0764                                                data-weight-currency-code="@supplier.WeightFactorCurrencyCode">
 0765                                            @supplier.Name (@supplier.CurrencyCode)
 766                                        </option>
 767                                    }
 768                                </select>
 769                            </div>
 770
 771                            <div class="cell-row form-group mb-0" style="width: 100%; min-width: 0;">
 772                                <input asp-for="Orders[i].OrderNumberToSupplier" type="text"
 773                                       class="form-control form-control-sm orderNumberToSupplie-field"
 774                                       id="OrderNumberToSupplier_@Model.Orders[i].Id"/>
 775                                <span asp-validation-for="Orders[i].OrderNumberToSupplier" class="text-danger"
 776                                      id="OrderNumberToSupplierValidation_@Model.Orders[i].Id"></span>
 777                            </div>
 778
 779                        </div>
 780                    </td>
 781
 782                    <td class="vertical-align: middle;" data-column="category">
 783                        <div class="two-row-cell" style="min-width: 0;">
 784                            <div class="cell-row category-name-row">
 0785                                @if (!string.IsNullOrEmpty(Model.Orders[i].ProductInfo?.CommercialCategory))
 786                                {
 787                                    <span class="category-name-text"
 788                                          title="@Model.Orders[i].ProductInfo!.CommercialCategory">
 0789                                        @Model.Orders[i].ProductInfo!.CommercialCategory
 790                                    </span>
 791                                }
 792
 793                                <span class="category-volumetric text-muted">
 0794                                    @(Model.Orders[i].ProductInfo?.VolumetricWeight)
 795                                </span>
 796                            </div>
 797
 0798                            @if (Model.Orders[i].ProductInfo != null)
 799                            {
 800                            <div class="text-muted cell-row product-weight-row">
 801                                <div class="form-group d-flex align-items-center product-weight-wrap mb-0">
 802                                    <div class="form-group mb-0">
 803                                        <input asp-for="Orders[i].ProductInfo.Weight"
 804                                               class="form-control form-control-sm product-weight-field"
 805                                               id="ProductWeight_@Model.Orders[i].Id"
 0806                                               value="@string.Format("{0:N0}", Model.Orders[i].ProductInfo?.Weight).Repl
 807                                        <span asp-validation-for="Orders[i].ProductInfo.Weight"
 808                                              class="text-danger"></span>
 809                                    </div>
 810                                    <div class="product-weight-label">
 811                                        <span>кг.</span>
 812                                    </div>
 813                                </div>
 814                            </div>
 815                            }
 816                        </div>
 817                    </td>
 818
 819                    <td>
 820                        <div class="two-row-cell">
 821                            <div class="cell-row"
 822                                 style="text-align: right; display: flex; align-items: center; justify-content: flex-end
 0823                                @Html.Raw(string.Format("{0:N0}", Model.Orders[i].ProductInfo?.CurrentPriceWithDiscount)
 824                            </div>
 825
 826
 827                            <div class="cell-row text-muted quantity-cell text-end justify-content-end"
 828                                 id="Quantity_@Model.Orders[i].Id">
 829                                <span class="@(Model.Orders[i].Quantity > 1 ? "qty-value--multi" : "")">
 0830                                    @Html.DisplayFor(modelItem => Model.Orders[i].Quantity)
 831                                </span>
 832                            </div>
 833                        </div>
 834                    </td>
 835
 836                    <td>
 837                        <div class="two-row-cell">
 838                            <div class="cell-row" style="text-align: right;" id="Price_@Model.Orders[i].Id">
 0839                                <span id="CurrentPriceWithDiscount_@Model.Orders[i].Id" class="d-none">@Model.Orders[i].
 0840                                @Html.Raw(string.Format("{0:N0}", Model.Orders[i].Price).Replace(",", " "))
 841                            </div>
 842
 843                            <div class="text-muted cell-row" style="text-align: right;" id="shipmentAmount_@i">
 0844                                @Html.Raw(string.Format("{0:N0}", Model.Orders[i].ShipmentAmount).Replace(",", " "))
 845                            </div>
 846                        </div>
 847                    </td>
 848
 849                    <td class="vertical-align: middle;" data-column="purchasePrice">
 850                        <div class="two-row-cell purchase-price-cell">
 851                            <div class="cell-row purchase-price-top-row">
 852                                @{
 0853                                    var currencyCodeForValue = Model.Orders[i].Supplier?.CurrencyCode;
 0854                                    var displayPrice = (currencyCodeForValue != CurrencyCode.RUB)
 0855                                        ? Model.Orders[i].OriginalPurchasePrice
 0856                                        : Model.Orders[i].PurchasePrice;
 0857                                    var formattedPrice = displayPrice.HasValue
 0858                                        ? displayPrice.Value.ToString(System.Globalization.CultureInfo.InvariantCulture)
 0859                                        : string.Empty;
 860                                }
 861                                <input asp-for="Orders[i].PurchasePrice" type="text"
 862                                       class="form-control form-control-sm purchase-price-field"
 863                                       id="PurchasePrice_@Model.Orders[i].Id"
 0864                                       data-order-id="@Model.Orders[i].Id"
 0865                                       value="@formattedPrice"
 866                                       oninput="this.value = this.value.replace(',', '.').replace(/[^0-9.]/g, '').replac
 867                                <span class="purchase-price-rub visually-hidden"
 868                                      id="PurchasePriceRub_@Model.Orders[i].Id"
 869                                      aria-hidden="true"></span>
 870                            </div>
 871                            <div class="cell-row text-muted purchase-price-bottom-row">
 872                                <span id="CostPrice_@Model.Orders[i].Id"></span>
 873                                <a href="javascript:void(0)"
 874                                   class="toggleExtraExpensesLink"
 875                                   onclick="toggleExtraExpensesColumn()"
 876                                   title="Показать/скрыть дополнительные расходы">
 877                                    <i class="fas fa-plus-circle"></i> Доп. расх.
 878                                </a>
 879                            </div>
 880                        </div>
 881                    </td>
 882
 883                    <!-- Столбец дополнительных расходов -->
 884                    <td class="extra-expenses-cell position-relative"
 885                        style="display: none; vertical-align: middle; width: 180px; max-width: 180px;">
 886                        @{
 0887                            var existingExpensesDict = ViewBag.ExistingExpenses as Dictionary<int, List<OrderExtraExpens
 0888                                                           ?? new Dictionary<int, List<OrderExtraExpense>>();
 0889                            var existingExpenses = existingExpensesDict.ContainsKey(Model.Orders[i].Id)
 0890                                ? existingExpensesDict[Model.Orders[i].Id]
 0891                                : new List<OrderExtraExpense>();
 892                        }
 893                        <div id="extraExpensesContainer_@Model.Orders[i].Id" class="extra-expenses-container h-100"
 0894                             data-order-id="@Model.Orders[i].Id" data-order-index="@i">
 0895                            @if (existingExpenses.Any())
 896                            {
 0897                                @for (int expIdx = 0; expIdx < existingExpenses.Count; expIdx++)
 898                                {
 0899                                    var expense = existingExpenses[expIdx];
 0900                                    var isFirst = expIdx == 0;
 0901                                    var hasMultipleExpenses = existingExpenses.Count > 1;
 902
 0903                                    <div class="extra-expense-item two-row-cell" data-expense-index="@expIdx"
 904                                         style="gap: 8px; @(!isFirst ? "border-top: 1px solid #dee2e6; padding-top: 0.3r
 905                                        <div class="cell-row" style="display: flex; gap: 4px; align-items: flex-start;">
 906                                            <select class="form-control form-control-sm expense-type-select"
 907                                                    name="Orders[@i].ExtraExpenses[@expIdx].ExpenseTypeId"
 908                                                    id="ExpenseTypeId_@(Model.Orders[i].Id)_@(expIdx)"
 0909                                                    data-expense-amount-id="ExpenseAmount_@(Model.Orders[i].Id)_@(expIdx
 910                                                    style="width: 70px; font-size: 11px; padding: 0.2rem 0.3rem; height:
 911                                                <option value="">Тип</option>
 0912                                                @if (ViewBag.ExpenseTypes != null)
 913                                                {
 0914                                                    @foreach (var expenseType in ViewBag.ExpenseTypes)
 915                                                    {
 0916                                                        <option value="@expenseType.Id"
 917                                                                selected="@(expense.ExpenseTypeId == expenseType.Id)">
 0918                                                            @expenseType.Name
 919                                                        </option>
 920                                                    }
 921                                                }
 922                                                <option value="__ADD_NEW__"
 923                                                        style="font-style: italic; color: #007bff;">+
 924                                                    Добавить новый...
 925                                                </option>
 926                                            </select>
 927                                            <span class="text-danger expense-type-validation position-absolute"
 928                                                  id="ExpenseTypeValidation_@(Model.Orders[i].Id)_@(expIdx)"
 929                                                  style="display: none; font-size: 10px;">Заполните тип</span>
 930
 931                                            <input type="number"
 932                                                   class="form-control form-control-sm expense-amount-input"
 933                                                   name="Orders[@i].ExtraExpenses[@expIdx].Amount"
 934                                                   id="ExpenseAmount_@(Model.Orders[i].Id)_@(expIdx)"
 0935                                                   data-expense-type-id="ExpenseTypeId_@(Model.Orders[i].Id)_@(expIdx)"
 936                                                   placeholder="₽"
 937                                                   step="0.01"
 938                                                   min="0"
 939                                                   value="@expense.Amount.ToString("0.00", System.Globalization.CultureI
 940                                                   style="width: 70px; font-size: 11px; padding: 0.2rem 0.3rem; height: 
 941                                            <span class="text-danger expense-amount-validation position-absolute"
 942                                                  id="ExpenseAmountValidation_@(Model.Orders[i].Id)_@(expIdx)"
 943                                                  style="display: none; font-size: 10px;">Заполните сумму</span>
 944
 0945                                            @if (!isFirst || hasMultipleExpenses)
 946                                            {
 947                                                <button type="button"
 948                                                        class="btn btn-sm btn-link text-danger remove-expense-btn p-0"
 0949                                                        data-order-id="@Model.Orders[i].Id"
 0950                                                        data-expense-index="@expIdx"
 951                                                        title="Удалить"
 952                                                        style="font-size: 12px; line-height: 1; border: none; background
 953                                                        onmouseover="this.style.textDecoration='none'; this.style.opacit
 954                                                        onmouseout="this.style.textDecoration='none'; this.style.opacity
 955                                                    <i class="fas fa-times"></i>
 956                                                </button>
 957                                            }
 958                                            else
 959                                            {
 960                                                <button type="button"
 961                                                        class="btn btn-sm btn-link text-primary add-expense-btn p-0"
 0962                                                        data-order-id="@Model.Orders[i].Id"
 0963                                                        data-order-index="@i"
 964                                                        title="Добавить расход"
 965                                                        style="font-size: 12px; line-height: 1; border: none; background
 966                                                        onmouseover="this.style.textDecoration='none'; this.style.opacit
 967                                                        onmouseout="this.style.textDecoration='none'; this.style.opacity
 968                                                    <i class="fas fa-plus"></i>
 969                                                </button>
 970                                            }
 971                                        </div>
 972                                        <div class="cell-row align-items-end">
 973                                            <input type="text"
 974                                                   class="form-control form-control-sm expense-comment-input"
 975                                                   name="Orders[@i].ExtraExpenses[@expIdx].Comment"
 976                                                   id="ExpenseComment_@(Model.Orders[i].Id)_@(expIdx)"
 977                                                   placeholder="Комментарий"
 978                                                   maxlength="255"
 979                                                   value="@expense.Comment"
 980                                                   style="width: calc(70px + 70px + 4px + 24px); font-size: 11px; paddin
 981                                        </div>
 982                                        <input type="hidden"
 983                                               name="Orders[@i].ExtraExpenses[@expIdx].OrderId"
 984                                               value="@Model.Orders[i].Id"/>
 985                                    </div>
 0986                                }
 987                            }
 988                            else
 989                            {
 990                                <div class="extra-expense-item two-row-cell" data-expense-index="0" style="gap: 8px;">
 991                                    <div class="cell-row">
 992                                        <div style="display: flex; gap: 4px; align-items: flex-start;">
 993                                            <div>
 994                                                <select class="form-control form-control-sm expense-type-select"
 995                                                        name="Orders[@i].ExtraExpenses[0].ExpenseTypeId"
 996                                                        id="ExpenseTypeId_@(Model.Orders[i].Id)_0"
 0997                                                        data-expense-amount-id="ExpenseAmount_@(Model.Orders[i].Id)_0"
 998                                                        style="width: 70px; font-size: 11px; padding: 0.2rem 0.3rem; hei
 999                                                    <option value="">Тип</option>
 01000                                                    @if (ViewBag.ExpenseTypes != null)
 1001                                                    {
 01002                                                        @foreach (var expenseType in ViewBag.ExpenseTypes)
 1003                                                        {
 01004                                                            <option value="@expenseType.Id">@expenseType.Name</option>
 1005                                                        }
 1006                                                    }
 1007                                                    <option value="__ADD_NEW__"
 1008                                                            style="font-style: italic; color: #007bff;">
 1009                                                        +
 1010                                                        Добавить новый...
 1011                                                    </option>
 1012                                                </select>
 1013                                                <span class="text-danger expense-type-validation position-absolute"
 1014                                                      id="ExpenseTypeValidation_@(Model.Orders[i].Id)_0"
 1015                                                      style="display: none; font-size: 10px;">Заполните тип</span>
 1016                                            </div>
 1017                                            <div>
 1018                                                <input type="number"
 1019                                                       class="form-control form-control-sm expense-amount-input"
 1020                                                       name="Orders[@i].ExtraExpenses[0].Amount"
 1021                                                       id="ExpenseAmount_@(Model.Orders[i].Id)_0"
 01022                                                       data-expense-type-id="ExpenseTypeId_@(Model.Orders[i].Id)_0"
 1023                                                       placeholder="₽"
 1024                                                       step="0.01"
 1025                                                       min="0"
 1026                                                       style="width: 70px; font-size: 11px; padding: 0.2rem 0.3rem; heig
 1027                                                <span class="text-danger expense-amount-validation position-absolute"
 1028                                                      id="ExpenseAmountValidation_@(Model.Orders[i].Id)_0"
 1029                                                      style="display: none; font-size: 10px;">Заполните сумму</span>
 1030                                            </div>
 1031                                            <button type="button"
 1032                                                    class="btn btn-sm btn-link text-primary add-expense-btn p-0"
 01033                                                    data-order-id="@Model.Orders[i].Id"
 01034                                                    data-order-index="@i"
 1035                                                    title="Добавить расход"
 1036                                                    style="font-size: 12px; line-height: 1; border: none; background: no
 1037                                                    onmouseover="this.style.textDecoration='none'; this.style.opacity='0
 1038                                                    onmouseout="this.style.textDecoration='none'; this.style.opacity='1'
 1039                                                <i class="fas fa-plus"></i>
 1040                                            </button>
 1041                                        </div>
 1042                                    </div>
 1043                                    <div class="cell-row align-items-end">
 1044                                        <input type="text"
 1045                                               class="form-control form-control-sm expense-comment-input"
 1046                                               name="Orders[@i].ExtraExpenses[0].Comment"
 1047                                               id="ExpenseComment_@(Model.Orders[i].Id)_0"
 1048                                               placeholder="Комментарий"
 1049                                               maxlength="255"
 1050                                               style="width: calc(70px + 70px + 4px + 24px); font-size: 11px; padding: 0
 1051                                    </div>
 1052                                    <input type="hidden"
 1053                                           name="Orders[@i].ExtraExpenses[0].OrderId"
 1054                                           value="@Model.Orders[i].Id"/>
 1055                                </div>
 1056                            }
 1057                        </div>
 1058                    </td>
 1059
 01060                    <!-- DEBUG: Order @i - Min: @Model.Orders[i].MinOzonCommission, Max: @Model.Orders[i].MaxOzonCommiss
 01061                    @if (Model.Orders[i].MinOzonCommission == 0 && Model.Orders[i].MaxOzonCommission == 0)
 1062                    {
 1063                        <td class="tx-metric-col" data-column="commission" style="text-align: right; vertical-align: mid
 1064                            <div class="two-row-cell">
 1065                                <div class="cell-row justify-content-end">
 1066                                    <div class="form-group d-flex align-items-center justify-content-end mb-0">
 1067                                        <div style="display: flex; align-items: center;">
 1068                                            <input asp-for="Orders[i].MinOzonCommission"
 1069                                                   class="form-control form-control-sm ozon-commission-field"
 1070                                                   id="MinOzonCommission_@Model.Orders[i].Id"
 1071                                                   style="text-align: right;"/>
 1072                                            <span asp-validation-for="Orders[i].MinOzonCommission" class="text-danger"
 1073                                                  id="MinOzonCommissionValidation_@Model.Orders[i].Id"></span>
 1074                                        </div>
 1075                                        <div style="margin-left: 4px; width: 30px; text-align: left;">
 1076                                            <span>min.</span>
 1077                                        </div>
 1078                                    </div>
 1079                                </div>
 1080
 1081
 1082                                <div class="cell-row text-muted" style="justify-content: flex-end;">
 1083                                    <div class="form-group d-flex align-items-center justify-content-end mb-0">
 1084                                        <div style="display: flex; align-items: center;">
 1085                                            <input asp-for="Orders[i].MaxOzonCommission"
 1086                                                   class="form-control form-control-sm ozon-commission-field"
 1087                                                   id="MaxOzonCommission_@Model.Orders[i].Id"
 1088                                                   style="text-align: right;"/>
 1089                                            <span asp-validation-for="Orders[i].MaxOzonCommission" class="text-danger"
 1090                                                  id="MaxOzonCommissionValidation_@Model.Orders[i].Id"></span>
 1091                                        </div>
 1092                                        <div style="margin-left: 4px; width: 30px; text-align: left;">
 1093                                            <span>max.</span>
 1094                                        </div>
 1095                                    </div>
 1096                                </div>
 1097                            </div>
 1098                        </td>
 1099                    }
 1100                    else
 1101                    {
 1102                        <td class="tx-metric-col" data-column="commission" style="text-align: right; vertical-align: mid
 1103                            <div class="two-row-cell">
 1104                                <div class="cell-row justify-content-end">
 1105
 1106                                    <div id="MinOzonCommission_@Model.Orders[i].Id">
 01107                                        @Html.Raw(string.Format("{0:N0}", Model.Orders[i].MinOzonCommission).Replace(","
 1108                                    </div>
 1109                                </div>
 1110
 1111                                <div class="cell-row text-muted justify-content-end">
 1112                                    <div id="MaxOzonCommission_@Model.Orders[i].Id">
 01113                                        @Html.Raw(string.Format("{0:N0}", Model.Orders[i].MaxOzonCommission).Replace(","
 1114                                    </div>
 1115                                </div>
 1116                            </div>
 1117                        </td>
 1118                    }
 1119
 1120                    <td class="tx-metric-col" data-column="profit" style="text-align: right; vertical-align: middle;">
 1121                        <div class="two-row-cell">
 1122
 1123                            <div class="cell-row justify-content-center">
 1124                                <span id="MaxProfit_@Model.Orders[i].Id">
 01125                                    @if (Model.Orders[i].MaxProfit < 0)
 1126                                    {
 01127                                        <span>@Html.DisplayFor(modelItem => Model.Orders[i].MaxProfit)</span>
 1128                                    }
 1129                                    else
 1130                                    {
 01131                                        @Html.DisplayFor(modelItem => Model.Orders[i].MaxProfit)
 1132                                    }
 1133                                </span>
 1134                                <span id="TargetProfit_@Model.Orders[i].Id"
 1135                                      class="text-muted ms-1 tx-metric-suffix"></span>
 1136
 1137                            </div>
 1138                            <div class="cell-row text-muted justify-content-center">
 1139
 1140                                <span id="MinProfit_@Model.Orders[i].Id">
 01141                                    @if (Model.Orders[i].MinProfit < 0)
 1142                                    {
 1143                                        <span
 01144                                            style="color:red">@Html.DisplayFor(modelItem => Model.Orders[i].MinProfit)</
 1145                                    }
 1146                                    else
 1147                                    {
 01148                                        @Html.DisplayFor(modelItem => Model.Orders[i].MinProfit)
 1149                                    }
 1150                                </span>
 1151                                    <span id="TargetProfit2_@Model.Orders[i].Id"
 1152                                          class="text-muted ms-1 tx-metric-suffix"></span>
 1153
 1154                            </div>
 1155                        </div>
 1156                    </td>
 1157
 1158                    <td class="tx-metric-col" data-column="markup" style="text-align: right; vertical-align: middle;">
 1159                        <div class="two-row-cell">
 1160                            <div class="cell-row justify-content-center"
 1161                                 id="MaxDiscount_@Model.Orders[i].Id">
 01162                                @if (Model.Orders[i].MaxDiscount < 0)
 1163                                {
 1164                                    <span
 01165                                        style="color:red">@Html.DisplayFor(modelItem => Model.Orders[i].MaxDiscount)</sp
 1166                                }
 1167                                else
 1168                                {
 01169                                    @Html.DisplayFor(modelItem => Model.Orders[i].MaxDiscount)
 1170                                }
 1171                            </div>
 1172
 1173                            <div class="cell-row text-muted justify-content-center"
 1174                                 id="MinDiscount_@Model.Orders[i].Id">
 01175                                @if (Model.Orders[i].MinDiscount < 0)
 1176                                {
 1177                                    <span
 01178                                        style="color:red">@Html.DisplayFor(modelItem => Model.Orders[i].MinDiscount)</sp
 1179                                }
 1180                                else
 1181                                {
 01182                                    @Html.DisplayFor(modelItem => Model.Orders[i].MinDiscount)
 1183                                }
 1184                            </div>
 1185                        </div>
 1186                    </td>
 1187
 1188                    <input asp-for="Orders[i].MinOzonCommission" type="hidden"/>
 1189                        <input asp-for="Orders[i].MaxOzonCommission" type="hidden"/>
 1190
 1191                </tr>
 01192            }
 1193            </tbody>
 1194
 1195        </table>
 1196    </div>
 1197    </div>
 1198    <div id="selectedSuppliersList"></div>
 1199
 1200    <input type="hidden" asp-for="RedirectPage"/>
 1201
 1202    <div class="tx-page-footer">
 1203        <div class="input-group">
 1204            <span class="input-group-btn">
 1205                <input type="submit" value="Сохранить" class="btn btn-primary"/>
 1206            </span>
 1207        </div>
 1208    </div>
 1209</form>
 1210
 1211
 1212<div>
 1213    <a asp-action="Index" class="tx-page-back-link">← К списку заказов</a>
 1214</div>
 1215
 1216<script>
 1217    // Функция для извлечения числового значения из строки
 1218    function extractNumber(text) {
 1219        if (typeof text !== 'string') {
 1220            text = String(text); // Преобразуем в строку, если это не строка
 1221        }
 1222        const number = parseFloat(text.replace(/\s/g, '').replace(',', '.'));
 1223        return isNaN(number) ? null : number;
 1224    }
 1225</script>
 1226
 1227<script>
 1228    document.addEventListener('DOMContentLoaded', function () {
 1229        const supplierSelects = document.querySelectorAll('.supplier-select');
 1230        const selectedSuppliers = {};
 1231
 1232        function extractNumber(text) {
 1233            const match = text.match(/(\d+(\.\d+)?)/);
 1234            return match ? parseFloat(match[0]) : 0;
 1235        }
 1236
 1237        function updateSelectedSuppliers() {
 1238            // Очистка текущего состояния
 1239            for (const key in selectedSuppliers) {
 1240                if (selectedSuppliers.hasOwnProperty(key)) {
 1241                    selectedSuppliers[key] = {count: 0, totalAmount: 0, totalQuantity: 0, totalPurchasePrice: 0};
 1242                }
 1243            }
 1244
 1245            // Пересчет значений для не удаленных строк
 1246            document.querySelectorAll('#shipmentTable tbody tr').forEach((row) => {
 1247                const supplierSelect = row.querySelector('.supplier-select');
 1248                const shipmentAmount = parseFloat(row.querySelector('[id^="shipmentAmount_"]')?.textContent) || 0;
 1249                const quantity = parseFloat(row.querySelector('[id^="Quantity_"]')?.textContent) || 0;
 1250                const purchasePriceText = row.querySelector('[id^="PurchasePriceRub_"]')?.textContent || '0';
 1251                const purchasePrice = extractNumber(purchasePriceText);
 1252
 1253                const selectedOption = supplierSelect.options[supplierSelect.selectedIndex];
 1254                const supplierName = selectedOption.text;
 1255
 1256                if (selectedOption.value) {
 1257                    if (selectedSuppliers[supplierName]) {
 1258                        selectedSuppliers[supplierName].count++;
 1259                        selectedSuppliers[supplierName].totalAmount += shipmentAmount;
 1260                        selectedSuppliers[supplierName].totalQuantity += quantity;
 1261                        selectedSuppliers[supplierName].totalPurchasePrice += purchasePrice;
 1262                    } else {
 1263                        selectedSuppliers[supplierName] = {
 1264                            count: 1,
 1265                            totalAmount: shipmentAmount,
 1266                            totalQuantity: quantity,
 1267                            totalPurchasePrice: purchasePrice
 1268                        };
 1269                    }
 1270                }
 1271            });
 1272
 1273            const selectedSuppliersList = document.getElementById('selectedSuppliersList');
 1274            selectedSuppliersList.innerHTML = '';
 1275
 1276            // Создаем карточку
 1277            const card = document.createElement('div');
 1278            card.className = 'card app-card mt-3 mb-3';
 1279
 1280            // Заголовок карточки
 1281            const cardHeader = document.createElement('div');
 1282            cardHeader.className = 'card-header app-card-header';
 1283            const cardTitle = document.createElement('h6');
 1284            cardTitle.className = 'app-card-title';
 1285            cardTitle.textContent = 'Сводка по поставщикам';
 1286            cardTitle.dataset.originalText = cardTitle.textContent;
 1287            cardHeader.appendChild(cardTitle);
 1288            card.appendChild(cardHeader);
 1289
 1290            // Тело карточки
 1291            const cardBody = document.createElement('div');
 1292            cardBody.className = 'card-body app-card-body';
 1293
 1294           // Таблица
 1295            const table = document.createElement('table');
 1296            table.className = 'table table-striped table-sm mb-0 app-table'
 1297
 1298            const thead = document.createElement('thead');
 1299            thead.className = 'app-table-head';
 1300
 1301            const headerRow = document.createElement('tr');
 1302
 1303            const headers = [
 1304                {text: 'Поставщик', align: 'left'},
 1305                {text: 'Заказы у поставщика', align: 'center'},
 1306                {text: 'Количество заказов', align: 'center'},
 1307                {text: 'Сумма отправления', align: 'right'},
 1308                {text: 'Цена закупки RUB', align: 'right'}
 1309            ];
 1310
 1311            headers.forEach(header => {
 1312                const th = document.createElement('th');
 1313                th.textContent = header.text;
 1314                th.classList.add(`text-${header.align}`, 'app-th');
 1315                headerRow.appendChild(th);
 1316            });
 1317            thead.appendChild(headerRow);
 1318            table.appendChild(thead);
 1319
 1320            const tbody = document.createElement('tbody');
 1321            for (const [supplier, data] of Object.entries(selectedSuppliers)) {
 1322                if (data.count > 0) {
 1323                    const row = document.createElement('tr');
 1324                    const supplierCell = document.createElement('td');
 1325                    supplierCell.textContent = supplier;
 1326                    row.appendChild(supplierCell);
 1327
 1328                    const countCell = document.createElement('td');
 1329                    countCell.classList.add('text-center');
 1330                    countCell.textContent = data.count;
 1331                    row.appendChild(countCell);
 1332
 1333                    const quantityCell = document.createElement('td');
 1334                    quantityCell.classList.add('text-center');
 1335                    quantityCell.textContent = data.totalQuantity;
 1336                    row.appendChild(quantityCell);
 1337
 1338                    const amountCell = document.createElement('td');
 1339                    amountCell.classList.add('text-right', 'numeric');
 1340                    amountCell.textContent = data.totalAmount.toFixed(2);
 1341                    row.appendChild(amountCell);
 1342
 1343                    const purchasePriceCell = document.createElement('td');
 1344                    purchasePriceCell.classList.add('text-right', 'numeric');
 1345                    purchasePriceCell.textContent = data.totalPurchasePrice.toFixed(2);
 1346                    row.appendChild(purchasePriceCell);
 1347
 1348                    tbody.appendChild(row);
 1349                }
 1350            }
 1351            table.appendChild(tbody);
 1352
 1353            // Добавляем таблицу в карточку
 1354            cardBody.appendChild(table);
 1355            card.appendChild(cardBody);
 1356
 1357            // И ставим карточку в контейнер
 1358            selectedSuppliersList.appendChild(card);
 1359        }
 1360
 1361        // Глобальная функция для обновления списка
 1362        window.updateSupplierList = updateSelectedSuppliers;
 1363
 1364        supplierSelects.forEach((select, index) => {
 1365            select.addEventListener('change', updateSelectedSuppliers);
 1366
 1367            // Инициализация начального состояния
 1368            const initialSelectedOption = select.options[select.selectedIndex];
 1369            if (initialSelectedOption.value) {
 1370                const initialSupplierName = initialSelectedOption.text;
 1371                const initialShipmentAmount = parseFloat(document.querySelector('#shipmentAmount_' + index)?.textContent
 1372                const initialQuantity = parseFloat(document.querySelector('#Quantity_' + index)?.textContent) || 0; // И
 1373                const initialPurchasePriceText = document.querySelector('#PurchasePriceRub_' + index)?.textContent || '0
 1374                const initialPurchasePrice = extractNumber(initialPurchasePriceText);
 1375
 1376                if (selectedSuppliers[initialSupplierName]) {
 1377                    selectedSuppliers[initialSupplierName].count++;
 1378                    selectedSuppliers[initialSupplierName].totalAmount += initialShipmentAmount;
 1379                    selectedSuppliers[initialSupplierName].totalQuantity += initialQuantity;
 1380                    selectedSuppliers[initialSupplierName].totalPurchasePrice += initialPurchasePrice;
 1381                } else {
 1382                    selectedSuppliers[initialSupplierName] = {
 1383                        count: 1,
 1384                        totalAmount: initialShipmentAmount,
 1385                        totalQuantity: initialQuantity,
 1386                        totalPurchasePrice: initialPurchasePrice
 1387                    };
 1388                }
 1389            }
 1390        });
 1391
 1392        // Обновляем список при загрузке страницы
 1393        updateSelectedSuppliers();
 1394    });
 1395
 1396</script>
 1397
 1398
 1399
 1400<script>
 1401    $(document).ready(function () {
 1402        // Обработка изменения поставщика в индивидуальных полях
 1403        $('.supplier-select').on('change', function () {
 1404            var selectedSupplier = $(this).find('option:selected');
 1405            var currencyCode = selectedSupplier.data('currency-code');
 1406            var orderId = $(this).attr('id').split('_')[1];
 1407
 1408            if (currencyCode) {
 1409                $('#CurrencyCode_' + orderId).text(currencyCode);
 1410            } else {
 1411                $('#CurrencyCode_' + orderId).text('');
 1412            }
 1413        });
 1414    });
 1415</script>
 1416
 1417<script>
 1418    $(document).ready(function () {
 1419        // Получаем значения курсов валют из Razor View
 01420        var rateUSD = @Model.RateUSD.ToString().Replace(',', '.');
 01421        var rateEUR = @Model.RateEUR.ToString().Replace(',', '.');
 01422        var rateBYN = @Model.RateBYN.ToString().Replace(',', '.');
 1423
 1424        function readSupplierDataNumber($option, key, fallback) {
 1425            if (!$option || !$option.length) return fallback;
 1426            var raw = $option.data(key);
 1427            if (raw === undefined || raw === null || raw === '') return fallback;
 1428            var parsed = parseFloat(String(raw).replace(',', '.'));
 1429            return isNaN(parsed) ? fallback : parsed;
 1430        }
 1431
 1432        // Обработка изменения поставщика в индивидуальных полях
 1433        $('.supplier-select').on('change', function () {
 1434            var selectedSupplier = $(this).find('option:selected');
 1435            var weightFactor = readSupplierDataNumber(selectedSupplier, 'weight-factor', 0);
 1436            var orderId = $(this).attr('id').split('_')[1]; // Извлекаем ID заказа из ID элемента
 1437            var weightInput = $('#ProductWeight_' + orderId);
 1438
 1439            // Если весовой коэффициент равен 0, устанавливаем поле веса в 0 и делаем его readonly
 1440            if (weightFactor === 0) {
 1441                weightInput.val('0').prop('readonly', true);
 1442            } else {
 1443                weightInput.prop('readonly', false); // Включаем возможность редактирования
 1444            }
 1445
 1446            // Пример: обновляем другие значения на странице
 1447            var currencyCode = selectedSupplier.data('currency-code');
 1448            var weightCurrencyCode = selectedSupplier.data('weight-currency-code');
 1449            var costFactor = readSupplierDataNumber(selectedSupplier, 'cost-factor', 1);
 1450
 1451            if (currencyCode) {
 1452                $('#CurrencyCode_' + orderId).text(currencyCode);
 1453                var purchasePriceInRub = updatePurchasePriceInRub(orderId, currencyCode, costFactor);
 1454                updateCostPriceWithExtraExpenses(orderId);
 1455            } else {
 1456                $('#CurrencyCode_' + orderId).text('');
 1457                $('#PurchasePriceRub_' + orderId).text('');
 1458                $('#CostPrice_' + orderId).text('');
 1459            }
 1460        });
 1461
 1462        // Обработка изменения значения purchase price
 1463        $('.purchase-price-field').on('input', function () {
 1464            var orderId = $(this).attr('id').split('_')[1];
 1465            var selectedSupplier = $('#SupplierId_' + orderId).find('option:selected');
 1466            var currencyCode = selectedSupplier.data('currency-code');
 1467            var weightCurrencyCode = selectedSupplier.data('weight-currency-code');
 1468            var costFactor = readSupplierDataNumber(selectedSupplier, 'cost-factor', 1);
 1469
 1470            var purchasePriceInRub = updatePurchasePriceInRub(orderId, currencyCode, costFactor);
 1471            updateCostPriceWithExtraExpenses(orderId);
 1472            updateCalculations(orderId);
 1473            window.updateSupplierList(); // Используем глобальную переменную
 1474        });
 1475
 1476        // Обработка изменения значения веса
 1477        $('.product-weight-field').on('input', function () {
 1478            var orderId = $(this).attr('id').split('_')[1];
 1479            var selectedSupplier = $('#SupplierId_' + orderId).find('option:selected');
 1480            var currencyCode = selectedSupplier.data('currency-code');
 1481            var weightCurrencyCode = selectedSupplier.data('weight-currency-code');
 1482            var costFactor = readSupplierDataNumber(selectedSupplier, 'cost-factor', 1);
 1483
 1484            var purchasePriceInRub = updatePurchasePriceInRub(orderId, currencyCode, costFactor);
 1485            updateCostPriceWithExtraExpenses(orderId);
 1486            updateCalculations(orderId);
 1487            window.updateSupplierList(); // Используем глобальную переменную
 1488        });
 1489
 1490        // Обработка изменения значения комиссий Ozon
 1491        $('.ozon-commission-field').on('input', function () {
 1492            var orderId = $(this).attr('id').split('_')[1];
 1493            updateCalculations(orderId);
 1494        });
 1495
 1496        // Обработка изменения дополнительных расходов
 1497        $(document).on('input change', '.expense-type-select, .expense-amount-input', function () {
 1498            var orderId = $(this).closest('.extra-expenses-container').data('order-id');
 1499            updateCostPriceWithExtraExpenses(orderId);
 1500        });
 1501
 1502        // Обработка добавления/удаления расходов через кнопки
 1503        $(document).on('click', '.add-expense-btn, .remove-expense-btn', function () {
 1504            // Небольшая задержка чтобы DOM обновился после добавления/удаления полей
 1505            setTimeout(() => {
 1506                var orderId = $(this).data('order-id');
 1507                updateCostPriceWithExtraExpenses(orderId);
 1508            }, 50);
 1509        });
 1510
 1511        // Вызываем обновление при загрузке страницы для каждого элемента
 1512        $('.supplier-select').each(function () {
 1513            var orderId = $(this).attr('id').split('_')[1];
 1514            var selectedSupplier = $(this).find('option:selected');
 1515            var currencyCode = selectedSupplier.data('currency-code');
 1516            var weightCurrencyCode = selectedSupplier.data('weight-currency-code');
 1517            var costFactor = readSupplierDataNumber(selectedSupplier, 'cost-factor', 1);
 1518
 1519            if (currencyCode) {
 1520                $('#CurrencyCode_' + orderId).text(currencyCode);
 1521                var purchasePriceInRub = updatePurchasePriceInRub(orderId, currencyCode, costFactor);
 1522                updateCostPriceWithExtraExpenses(orderId);
 1523            } else {
 1524                $('#CurrencyCode_' + orderId).text('');
 1525                $('#PurchasePriceRub_' + orderId).text('');
 1526                $('#CostPrice_' + orderId).text('');
 1527            }
 1528        });
 1529
 1530        // Вызываем обновление вычислений при загрузке страницы для каждого элемента
 1531        $('.purchase-price-field, .ozon-commission-field').each(function () {
 1532            var orderId = $(this).attr('id').split('_')[1];
 1533            updateCalculations(orderId);
 1534        });
 1535
 1536        // Инициализируем дополнительные расходы при загрузке страницы для каждого заказа
 1537        $('.extra-expenses-container').each(function () {
 1538            var orderId = $(this).data('order-id');
 1539            updateCostPriceWithExtraExpenses(orderId);
 1540        });
 1541
 1542        function updatePurchasePriceInRub(orderId, currencyCode, costFactor) {
 1543            var purchasePrice = parseFloat($('#PurchasePrice_' + orderId).val());
 1544            var purchasePriceInRub = 0;
 1545            var titleText = '';
 1546
 1547            switch (currencyCode) {
 1548                case 'USD':
 1549                    purchasePriceInRub = purchasePrice * costFactor * rateUSD;
 1550                    titleText = `${purchasePrice} (Цена закупки USD) * ${costFactor} (Коэффициент) * ${rateUSD} (Курс US
 1551                    break;
 1552                case 'EUR':
 1553                    purchasePriceInRub = purchasePrice * costFactor * rateEUR;
 1554                    titleText = `${purchasePrice} (Цена закупки EUR) * ${costFactor} (Коэффициент) * ${rateEUR} (Курс EU
 1555                    break;
 1556                case 'BYN':
 1557                    purchasePriceInRub = purchasePrice * costFactor * rateBYN;
 1558                    titleText = `${purchasePrice} (Цена закупки BYN) * ${costFactor} (Коэффициент) * ${rateBYN} (Курс BY
 1559                    break;
 1560                default:
 1561                    purchasePriceInRub = purchasePrice * costFactor;
 1562                    titleText = `${purchasePrice} (Цена закупки RUB) * ${costFactor} = ${purchasePriceInRub}`;
 1563                    break;
 1564            }
 1565
 1566            $('#PurchasePrice_' + orderId).attr('title', titleText);
 1567
 1568            $('#PurchasePriceRub_' + orderId).text(!isNaN(purchasePriceInRub) ? Math.round(purchasePriceInRub) + ' RUB' 
 1569            $('#PurchasePriceRub_' + orderId).attr('title', titleText);
 1570            $('#PurchasePrice_' + orderId).data('purchase-price-rub', purchasePriceInRub);
 1571
 1572            return purchasePriceInRub;
 1573        }
 1574
 1575        function updateCostPrice(orderId, currencyCode, costFactor, weightCurrencyCode, purchasePriceInRub) {
 1576            var weight = parseFloat($('#ProductWeight_' + orderId).val());
 1577            var supplierWeightFactor = readSupplierDataNumber($('#SupplierId_' + orderId).find('option:selected'), 'weig
 1578            var supplierWeightFactorInRub = 0;
 1579
 1580            var supplierWeightFactorInRubTitle = ``;
 1581            switch (weightCurrencyCode) {
 1582                case 'USD':
 1583                    supplierWeightFactorInRub = supplierWeightFactor * rateUSD;
 1584                    supplierWeightFactorInRubTitle = ` = ${supplierWeightFactor} * ${rateUSD}`;
 1585                    break;
 1586                case 'EUR':
 1587                    supplierWeightFactorInRub = supplierWeightFactor * rateEUR;
 1588                    supplierWeightFactorInRubTitle = ` = ${supplierWeightFactor} * ${rateEUR}`;
 1589                    break;
 1590                case 'BYN':
 1591                    supplierWeightFactorInRub = supplierWeightFactor * rateBYN;
 1592                    supplierWeightFactorInRubTitle = ` = ${supplierWeightFactor} * ${rateBYN}`;
 1593                    break;
 1594                default:
 1595                    supplierWeightFactorInRub = supplierWeightFactor;
 1596                    break;
 1597            }
 1598
 1599            var costPrice = 0;
 1600            var titleText = '';
 1601
 1602            if (!isNaN(weight) && !isNaN(supplierWeightFactor) && !isNaN(purchasePriceInRub) && supplierWeightFactorInRu
 1603                costPrice = (weight * supplierWeightFactorInRub) + purchasePriceInRub;
 1604                titleText = `${weight} (Вес) * ${supplierWeightFactorInRub} (Цена за кг. RUB${supplierWeightFactorInRubT
 1605            } else if (!isNaN(purchasePriceInRub)) {
 1606                costPrice = purchasePriceInRub;
 1607                titleText = `${purchasePriceInRub} (Цена закупки RUB) = ${costPrice}`;
 1608            } else {
 1609                $('#CostPrice_' + orderId).text('');
 1610                $('#CostPrice_' + orderId).attr('title', '');
 1611                $('#CostPrice_' + orderId).data('cost-price', '');
 1612                updateCalculations(orderId);
 1613                return;
 1614            }
 1615
 1616            $('#CostPrice_' + orderId).text(Math.round(costPrice) + ' RUB');
 1617            $('#CostPrice_' + orderId).attr('title', titleText);
 1618            $('#CostPrice_' + orderId).data('cost-price', costPrice);
 1619
 1620            updateCalculations(orderId);
 1621        }
 1622
 1623        function updateCostPriceWithExtraExpenses(orderId) {
 1624            var selectedSupplier = $('#SupplierId_' + orderId).find('option:selected');
 1625            var currencyCode = selectedSupplier.data('currency-code');
 1626            var weightCurrencyCode = selectedSupplier.data('weight-currency-code');
 1627            var costFactor = readSupplierDataNumber(selectedSupplier, 'cost-factor', 1);
 1628
 1629            // Сначала рассчитываем базовую себестоимость без расходов
 1630            var purchasePriceInRub = updatePurchasePriceInRub(orderId, currencyCode, costFactor);
 1631            var weight = parseFloat($('#ProductWeight_' + orderId).val());
 1632            var supplierWeightFactor = readSupplierDataNumber(selectedSupplier, 'weight-factor', 0);
 1633            var supplierWeightFactorInRub = 0;
 1634
 1635            switch (weightCurrencyCode) {
 1636                case 'USD':
 1637                    supplierWeightFactorInRub = supplierWeightFactor * rateUSD;
 1638                    break;
 1639                case 'EUR':
 1640                    supplierWeightFactorInRub = supplierWeightFactor * rateEUR;
 1641                    break;
 1642                case 'BYN':
 1643                    supplierWeightFactorInRub = supplierWeightFactor * rateBYN;
 1644                    break;
 1645                default:
 1646                    supplierWeightFactorInRub = supplierWeightFactor;
 1647                    break;
 1648            }
 1649
 1650            var baseCostPrice = 0;
 1651            if (!isNaN(weight) && !isNaN(supplierWeightFactor) && !isNaN(purchasePriceInRub) && supplierWeightFactorInRu
 1652                baseCostPrice = (weight * supplierWeightFactorInRub) + purchasePriceInRub;
 1653            } else if (!isNaN(purchasePriceInRub)) {
 1654                baseCostPrice = purchasePriceInRub;
 1655            }
 1656
 1657            // Определяем количество товара по заказу для распределения доп. расходов
 1658            var quantity = 1;
 1659            var quantityElement = $('#Quantity_' + orderId);
 1660            if (quantityElement.length) {
 1661                var qtyText = (quantityElement.text() || '')
 1662                    .toString()
 1663                    .replace(/\s/g, '')
 1664                    .replace(',', '.');
 1665                var parsedQty = parseFloat(qtyText);
 1666                if (!isNaN(parsedQty) && parsedQty > 0) {
 1667                    quantity = parsedQty;
 1668                }
 1669            }
 1670
 1671            // Суммируем дополнительные расходы в расчете на единицу товара
 1672            var extraExpensesTotal = 0;
 1673            var expensesDetails = [];
 1674
 1675            $('#extraExpensesContainer_' + orderId + ' .expense-amount-input').each(function () {
 1676                var amount = parseFloat($(this).val()) || 0;
 1677                var typeSelect = $(this).data('expense-type-id');
 1678                var typeValue = $('#' + typeSelect).val();
 1679
 1680                // Добавляем только если выбрана сумма и тип
 1681                if (amount > 0 && typeValue && typeValue !== '__ADD_NEW__') {
 1682                    // Распределяем общую сумму доп. расходов по количеству (расход на единицу товара)
 1683                    var amountPerUnit = amount / quantity;
 1684                    extraExpensesTotal += amountPerUnit;
 1685                    expensesDetails.push(amountPerUnit);
 1686                }
 1687            });
 1688
 1689            // Финальная себестоимость = базовая себестоимость + дополнительные расходы
 1690            var finalCostPrice = baseCostPrice + extraExpensesTotal;
 1691
 1692            // Формируем title с учетом расходов
 1693            var titleText = '';
 1694            if (baseCostPrice > 0) {
 1695                titleText = baseCostPrice + ' (Базовая себестоимость)';
 1696                if (extraExpensesTotal > 0) {
 1697                    titleText += ' + ' + extraExpensesTotal + ' (Доп. расходы: ' + expensesDetails.join(' + ') + ')';
 1698                }
 1699                titleText += ' = ' + finalCostPrice;
 1700            }
 1701
 1702            // Обновляем отображение себестоимости
 1703            $('#CostPrice_' + orderId).text(Math.round(finalCostPrice) + ' RUB');
 1704            $('#CostPrice_' + orderId).attr('title', titleText);
 1705            $('#CostPrice_' + orderId).data('cost-price', finalCostPrice);
 1706
 1707            // Пересчитываем прибыль и наценку
 1708            updateCalculations(orderId);
 1709        }
 1710
 1711
 1712        function updateCalculations(orderId) {
 1713            var costPrice = extractNumber($('#CostPrice_' + orderId).data('cost-price'));
 1714            var currentPrice = extractNumber($('#CurrentPriceWithDiscount_' + orderId).text());
 1715            var price = currentPrice !== null && currentPrice > 0
 1716                ? currentPrice
 1717                : extractNumber($('#Price_' + orderId).text());
 1718
 1719            if (costPrice === null || costPrice === 0) {
 1720                // Если costPrice равен null или 0, не выполнять расчеты
 1721                $('#MinProfit_' + orderId).text('');
 1722                $('#MaxProfit_' + orderId).text('');
 1723                $('#MaxDiscount_' + orderId).text('');
 1724                $('#MinDiscount_' + orderId).text('');
 1725                return;
 1726            }
 1727
 1728            var minOzonCommission = extractNumber($('#MinOzonCommission_' + orderId).val() || $('#MinOzonCommission_' + 
 1729            var maxOzonCommission = extractNumber($('#MaxOzonCommission_' + orderId).val() || $('#MaxOzonCommission_' + 
 1730
 1731            var startCommission = price - costPrice;
 1732            var minProfit = startCommission - maxOzonCommission;
 1733            var maxProfit = startCommission - minOzonCommission;
 1734            var minDiscount = (minProfit / costPrice) * 100;
 1735            var maxDiscount = (maxProfit / costPrice) * 100;
 1736
 1737            // Округляем до целого числа и обрезаем до 4 знаков, если нужно
 1738            minProfit = Math.floor(minProfit);
 1739            maxProfit = Math.floor(maxProfit);
 1740            minDiscount = Math.floor(minDiscount);
 1741            maxDiscount = Math.floor(maxDiscount);
 1742
 1743            var displayMinProfit = minProfit > 9999 ? minProfit.toString().slice(0, 4) + '...' : minProfit.toString();
 1744            var displayMaxProfit = maxProfit > 9999 ? maxProfit.toString().slice(0, 4) + '...' : maxProfit.toString();
 1745            var displayMinDiscount = minDiscount > 9999 ? minDiscount.toString().slice(0, 4) + '...' : minDiscount.toStr
 1746            var displayMaxDiscount = maxDiscount > 9999 ? maxDiscount.toString().slice(0, 4) + '...' : maxDiscount.toStr
 1747
 1748            $('#MinProfit_' + orderId).text(!isNaN(minProfit) ? displayMinProfit : "");
 1749            $('#MaxProfit_' + orderId).text(!isNaN(maxProfit) ? displayMaxProfit : "");
 1750            $('#MaxDiscount_' + orderId).text(!isNaN(maxDiscount) ? displayMaxDiscount + ' %' : "");
 1751            $('#MinDiscount_' + orderId).text(!isNaN(minDiscount) ? displayMinDiscount + ' %' : "");
 1752
 1753            // 13,5% от цены сайта рядом с прибылью (fallback: цена заказа)
 1754            var targetSpan = $('#TargetProfit_' + orderId);
 1755            var targetSpan2 = $('#TargetProfit2_' + orderId);
 1756            if (targetSpan.length) {
 1757                var basePrice = null;
 1758
 1759                // Ищем строку заказа по ячейке с MaxProfit
 1760                var row = $('#MaxProfit_' + orderId).closest('tr');
 1761                if (row.length) {
 1762                    basePrice = currentPrice !== null && currentPrice > 0
 1763                        ? currentPrice
 1764                        : extractNumber(row.find('[id^="Price_"]').text());
 1765                }
 1766
 1767                if (basePrice !== null && !isNaN(basePrice) && basePrice > 0) {
 1768                    var targetProfit = Math.floor(basePrice * 0.135);
 1769                    var suffixText = ' / -' + targetProfit;
 1770                    targetSpan.text(suffixText).addClass('tx-metric-suffix');
 1771                    targetSpan2.text(suffixText).addClass('tx-metric-suffix');
 1772                } else {
 1773                    targetSpan.text('').removeClass('tx-metric-suffix');
 1774                    targetSpan2.text('').removeClass('tx-metric-suffix');
 1775                }
 1776            }
 1777
 1778            $('#MinProfit_' + orderId).css('color', minProfit < 0 ? 'red' : '');
 1779            $('#MaxProfit_' + orderId).css('color', maxProfit < 0 ? 'red' : '');
 1780            $('#MaxDiscount_' + orderId).css('color', maxDiscount < 0 ? 'red' : '');
 1781            $('#MinDiscount_' + orderId).css('color', minDiscount < 0 ? 'red' : '');
 1782
 1783            // Добавляем title к полям
 1784            $('#MinProfit_' + orderId).attr('title', `${price} (Цена сайта) - ${costPrice} (Себестоимость) - ${maxOzonCo
 1785            $('#MaxProfit_' + orderId).attr('title', `${price} (Цена сайта) - ${costPrice} (Себестоимость) - ${minOzonCo
 1786
 1787            $('#MaxDiscount_' + orderId).attr('title', `${maxProfit} (Макс. Прибыль) / ${costPrice} (Себестоимость) * 10
 1788            $('#MinDiscount_' + orderId).attr('title', `${minProfit} (Мин. Прибыль) / ${costPrice} (Себестоимость) * 100
 1789        }
 1790    });
 1791
 1792    document.addEventListener('DOMContentLoaded', function () {
 1793        // Находим общее поле для ввода и все целевые поля для обновления
 1794        var universalField = document.getElementById('universalOrderNumberToSupplier');
 1795        var universalOrderNumberToSupplier = document.querySelectorAll('.orderNumberToSupplie-field');
 1796
 1797        // Добавляем обработчик события на изменение значения общего поля
 1798        universalField.addEventListener('input', function () {
 1799            var value = this.value; // Получаем текущее значение из общего поля
 1800
 1801            // Обновляем значения целевых полей в цикле
 1802            universalOrderNumberToSupplier.forEach(function (field) {
 1803                field.value = value;
 1804            });
 1805        });
 1806    });
 1807
 1808    function handleSelectChange(selectElement) {
 1809        if (!selectElement) return;
 1810        if (selectElement.value === 'create') {
 01811            window.location.href = '@Url.Action("Create", "Supplier")';
 1812            return;
 1813        }
 1814        if (!selectElement.options || selectElement.selectedIndex < 0) return;
 1815        var selectedOption = selectElement.options[selectElement.selectedIndex];
 1816        if (!selectedOption) return;
 1817        var supplierId = selectedOption.value;
 1818        if (!supplierId) return;
 1819        var currencyCode = selectedOption.getAttribute('data-currency-code') || '';
 1820        document.querySelectorAll('.supplier-select').forEach(function (supplierSelect) {
 1821            if (supplierSelect) {
 1822                supplierSelect.value = supplierId;
 1823                supplierSelect.dispatchEvent(new Event('change', { bubbles: true }));
 1824                var currencySpan = supplierSelect.closest('td')?.querySelector('.currency-code');
 1825                if (currencySpan) currencySpan.textContent = currencyCode || '';
 1826            }
 1827        });
 1828    }
 1829
 1830    window.handleStatusSelectChange = function (selectElement) {
 1831        if (!selectElement) return;
 1832        if (selectElement.value === 'create') {
 01833            window.location.href = '@Url.Action("Create", "AppStatus")';
 1834            return;
 1835        }
 1836
 1837        var selectedStatus = selectElement.value;
 1838        var rowStatusSelects = document.querySelectorAll('#shipmentTable tbody .status-select');
 1839        var supplierValuesMap = {};
 1840
 1841        rowStatusSelects.forEach(function (statusSelect) {
 1842            if (!statusSelect || !statusSelect.id) return;
 1843            var orderId = statusSelect.id.split('_')[1];
 1844            var supplierSelect = document.getElementById('SupplierId_' + orderId);
 1845            if (supplierSelect) {
 1846                supplierValuesMap[orderId] = supplierSelect.value;
 1847            }
 1848            statusSelect.value = selectedStatus;
 1849            if (typeof window.syncStatusSelectAppearance === 'function') {
 1850                window.syncStatusSelectAppearance(statusSelect);
 1851            }
 1852            statusSelect.dispatchEvent(new Event('change', { bubbles: true }));
 1853        });
 1854
 1855        if (typeof window.syncStatusSelectAppearance === 'function') {
 1856            window.syncStatusSelectAppearance(selectElement);
 1857        }
 1858
 1859        requestAnimationFrame(function () {
 1860            Object.keys(supplierValuesMap).forEach(function (orderId) {
 1861                var supplierValue = supplierValuesMap[orderId];
 1862                if (!supplierValue) return;
 1863                var supplierSelect = document.getElementById('SupplierId_' + orderId);
 1864                if (supplierSelect && supplierSelect.value !== supplierValue) {
 1865                    supplierSelect.value = supplierValue;
 1866                    supplierSelect.dispatchEvent(new Event('change', { bubbles: true }));
 1867                }
 1868            });
 1869        });
 1870    };
 1871
 1872    window.positionDropdownFixed = window.positionDropdownFixed || function (triggerId, dropdownId) {
 1873        var trigger = document.getElementById(triggerId);
 1874        var ul = document.getElementById(dropdownId);
 1875        if (!trigger || !ul) return;
 1876
 1877        // Закрываем все остальные открытые фильтр-дропдауны
 1878        document.querySelectorAll('.filter-dropdown-list').forEach(function (el) {
 1879            if (el.id !== dropdownId) {
 1880                el.style.display = 'none';
 1881                el.classList.remove('show');
 1882            }
 1883        });
 1884
 1885        if (ul.parentElement !== document.body) {
 1886            document.body.appendChild(ul);
 1887        }
 1888
 1889        var rect = trigger.getBoundingClientRect();
 1890        // getBoundingClientRect() returns visual-px (already scaled by html{zoom}).
 1891        // position:fixed uses CSS px. Convert: css_px = visual_px / zoom.
 1892        var zoom = parseFloat(window.getComputedStyle(document.documentElement).zoom) || 1;
 1893        var vpH = window.innerHeight;
 1894        var vpW = window.innerWidth;
 1895        var minWidth = Math.max(Math.round(rect.width), 160);
 1896
 1897        ul.style.display = 'block';
 1898        ul.style.visibility = 'hidden';
 1899        ul.style.position = 'fixed';
 1900        ul.style.zIndex = '10000';
 1901        ul.style.right = 'auto';
 1902        ul.style.bottom = 'auto';
 1903        ul.style.width = 'max-content';
 1904        ul.style.minWidth = minWidth + 'px';
 1905        ul.style.maxWidth = Math.max(vpW - 8, minWidth) + 'px';
 1906
 1907        var ulHeight = ul.offsetHeight || 200;
 1908        var top = rect.bottom / zoom + 2;
 1909        if (top + ulHeight > vpH - 4) {
 1910            top = Math.max(4, rect.top / zoom - ulHeight - 2);
 1911        }
 1912        var left = rect.left / zoom;
 1913        var ulWidth = ul.offsetWidth || minWidth;
 1914        if (left + ulWidth > vpW - 4) {
 1915            left = Math.max(4, vpW - ulWidth - 4);
 1916        }
 1917
 1918        top = Math.max(4, Math.round(top));
 1919        left = Math.max(4, Math.round(left));
 1920
 1921        ul.style.transform = 'none';
 1922        ul.style.margin = '0';
 1923        ul.style.right = 'auto';
 1924        ul.style.bottom = 'auto';
 1925        ul.style.setProperty('top', top + 'px', 'important');
 1926        ul.style.setProperty('left', left + 'px', 'important');
 1927        ul.style.setProperty('position', 'fixed', 'important');
 1928        ul.style.setProperty('display', 'block', 'important');
 1929        ul.style.setProperty('z-index', '10000', 'important');
 1930        ul.style.visibility = 'visible';
 1931        ul.classList.add('show');
 1932
 1933        ul.dataset.filterDropdownTrigger = triggerId;
 1934    };
 1935
 1936    document.addEventListener('DOMContentLoaded', function () {
 1937        // Инициализация обработчиков для полей связи продуктов
 1938        initializeReplacementArticleInputs();
 1939    });
 1940
 1941    // Функция для инициализации обработчиков полей связи продуктов
 1942    function initializeReplacementArticleInputs() {
 1943        let debounceTimer;
 1944
 1945        // Обработка клика на иконку цепочки - показываем/скрываем поле
 1946        $(document).on('click', '.replacement-link-toggle', function (e) {
 1947            e.preventDefault();
 1948            e.stopPropagation();
 1949
 1950            const $toggle = $(this);
 1951            const $wrapper = $toggle.siblings('.replacement-input-wrapper');
 1952            const $input = $wrapper.find('.replacement-article-input');
 1953
 1954            if ($wrapper.hasClass('show')) {
 1955                // Скрываем поле
 1956                $wrapper.removeClass('show');
 1957                $toggle.removeClass('active');
 1958                // Если поле пустое, очищаем его
 1959                if (!$input.val() || $input.val().trim() === '') {
 1960                    $input.val('');
 1961                }
 1962            } else {
 1963                // Показываем поле
 1964                $wrapper.addClass('show');
 1965                $toggle.addClass('active');
 1966                // Фокусируемся на поле
 1967                setTimeout(function () {
 1968                    $input.focus();
 1969                }, 100);
 1970            }
 1971        });
 1972
 1973        // При потере фокуса, если поле пустое - скрываем его
 1974        $(document).on('blur', '.replacement-article-input', function () {
 1975            const $input = $(this);
 1976            const $wrapper = $input.closest('.replacement-input-wrapper');
 1977            const $toggle = $wrapper.siblings('.replacement-link-toggle');
 1978
 1979            if (!$input.val() || $input.val().trim() === '') {
 1980                // Не скрываем автоматически, оставляем видимым пока пользователь не закроет вручную
 1981            }
 1982        });
 1983
 1984        $(document).on('input', '.replacement-article-input', function () {
 1985            const $input = $(this);
 1986            const replacementArticle = $input.val().trim();
 1987            const productInfoId = $input.data('product-info-id');
 1988            const originalArticle = $input.data('original-article');
 1989            const currentReplacement = $input.data('replacement-article');
 1990
 1991            // Очищаем предыдущий таймер
 1992            clearTimeout(debounceTimer);
 1993
 1994            // Если поле пустое, очищаем связь
 1995            if (!replacementArticle) {
 1996                if (currentReplacement) {
 1997                    // Можно добавить логику для удаления связи, если нужно
 1998                }
 1999                return;
 2000            }
 2001
 2002            // Если значение не изменилось, ничего не делаем
 2003            if (replacementArticle === currentReplacement) {
 2004                return;
 2005            }
 2006
 2007            // Если нет ProductInfoId, нужно сначала найти или создать продукт
 2008            if (!productInfoId) {
 2009                showNotification('У заказа нет связанного продукта. Сначала создайте продукт.', 'danger');
 2010                return;
 2011            }
 2012
 2013            // Debounce: ждем 1 секунду после последнего ввода
 2014            debounceTimer = setTimeout(function () {
 2015                linkReplacementProduct(productInfoId, replacementArticle, $input, originalArticle);
 2016            }, 1000);
 2017        });
 2018
 2019        // Обработка нажатия Enter
 2020        $(document).on('keydown', '.replacement-article-input', function (e) {
 2021            if (e.key === 'Enter') {
 2022                e.preventDefault();
 2023                clearTimeout(debounceTimer);
 2024                const $input = $(this);
 2025                const replacementArticle = $input.val().trim();
 2026                const productInfoId = $input.data('product-info-id');
 2027                const originalArticle = $input.data('original-article');
 2028                const currentReplacement = $input.data('replacement-article');
 2029
 2030                if (!replacementArticle) {
 2031                    return;
 2032                }
 2033
 2034                if (replacementArticle === currentReplacement) {
 2035                    return;
 2036                }
 2037
 2038                if (!productInfoId) {
 2039                    showNotification('У заказа нет связанного продукта. Сначала создайте продукт.', 'danger');
 2040                    return;
 2041                }
 2042
 2043                linkReplacementProduct(productInfoId, replacementArticle, $input, originalArticle);
 2044            }
 2045        });
 2046    }
 2047
 2048    // Функция для связывания продуктов
 2049    function linkReplacementProduct(originalProductId, replacementArticle, $input, originalArticle) {
 2050        // Показываем индикатор загрузки
 2051        $input.prop('disabled', true);
 2052        $input.css('background-color', '#f0f0f0');
 2053
 2054        $.ajax({
 02055            url: '@Url.Action("LinkReplacementProduct", "Products", new { area = "Studio2" })',
 2056            method: 'POST',
 2057            data: {
 2058                originalProductId: originalProductId,
 2059                replacementArticle: replacementArticle
 2060            },
 2061            success: function (response) {
 2062                $input.prop('disabled', false);
 2063                $input.css('background-color', '');
 2064
 2065                if (response.success) {
 2066                    // Обновляем данные в поле
 2067                    $input.data('replacement-article', replacementArticle);
 2068
 2069                    // Показываем успешное сообщение
 2070                    const message = response.wasCreated
 2071                        ? `Создан новый продукт "${replacementArticle}" и связан с "${originalArticle || 'оригинальным'}
 2072                        : `Продукт "${replacementArticle}" успешно связан с "${originalArticle || 'оригинальным'}"`;
 2073
 2074                    showNotification(message, 'success');
 2075
 2076                    // НЕ очищаем поле - оставляем введенное значение
 2077                } else {
 2078                    showNotification(response.message || 'Не удалось связать продукты', 'danger');
 2079                    // Восстанавливаем предыдущее значение при ошибке
 2080                    const currentReplacement = $input.data('replacement-article') || '';
 2081                    $input.val(currentReplacement);
 2082                }
 2083            },
 2084            error: function (xhr, status, error) {
 2085                $input.prop('disabled', false);
 2086                $input.css('background-color', '');
 2087
 2088                let errorMessage = 'Произошла ошибка при связывании продуктов';
 2089                if (xhr.responseJSON && xhr.responseJSON.message) {
 2090                    errorMessage = xhr.responseJSON.message;
 2091                }
 2092
 2093                showNotification(errorMessage, 'danger');
 2094
 2095                // Восстанавливаем предыдущее значение при ошибке
 2096                const currentReplacement = $input.data('replacement-article') || '';
 2097                $input.val(currentReplacement);
 2098            }
 2099        });
 2100    }
 2101
 2102    // Функция для показа уведомлений (используем метод из Index.cshtml)
 2103    function showNotification(message, type = 'success') {
 2104        // Создаем контейнер для уведомлений если его нет
 2105        let notificationContainer = document.getElementById('notification-container');
 2106        if (!notificationContainer) {
 2107            notificationContainer = document.createElement('div');
 2108            notificationContainer.id = 'notification-container';
 2109            notificationContainer.style.cssText = 'position: fixed; top: 20px; right: 20px; z-index: 99999; display: fle
 2110            document.body.appendChild(notificationContainer);
 2111        }
 2112
 2113        // Определяем класс Bootstrap в зависимости от типа
 2114        const alertClass = type === 'success' ? 'alert-success' : type === 'error' || type === 'danger' ? 'alert-danger'
 2115
 2116        // Создаем уведомление
 2117        const toast = document.createElement('div');
 2118        toast.className = `alert ${alertClass} alert-dismissible fade show`;
 2119        toast.style.cssText = 'min-width: 300px; max-width: 400px; box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);';
 2120        toast.innerHTML = `
 2121            ${message}
 2122            <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
 2123        `;
 2124
 2125        // Добавляем уведомление в контейнер
 2126        notificationContainer.appendChild(toast);
 2127
 2128        // Инициализируем Bootstrap alert
 2129        const bsAlert = new bootstrap.Alert(toast);
 2130
 2131        // Автоматическое скрытие через 5 секунд
 2132        setTimeout(() => {
 2133            if (toast.parentNode) {
 2134                bsAlert.close();
 2135            }
 2136        }, 5000);
 2137
 2138        // Удаляем элемент из DOM после скрытия
 2139        toast.addEventListener('closed.bs.alert', function () {
 2140            if (toast.parentNode) {
 2141                toast.parentNode.removeChild(toast);
 2142            }
 2143        });
 2144    }
 2145</script>
 2146
 2147@* Функция показа/скрытия столбца дополнительных расходов *@
 2148<script>
 2149    function toggleExtraExpensesColumn() {
 2150        const thElement = document.getElementById('thExtraExpenses');
 2151        const tdElements = document.querySelectorAll('.extra-expenses-cell');
 2152        const linkElements = document.querySelectorAll('.toggleExtraExpensesLink');
 2153
 2154        if (thElement && tdElements.length > 0) {
 2155            // Проверяем текущее состояние (по умолчанию скрыто)
 2156            const isCurrentlyHidden = thElement.style.display === 'none' ||
 2157                thElement.style.display === '' ||
 2158                window.getComputedStyle(thElement).display === 'none';
 2159
 2160            // Переключаем видимость заголовка
 2161            thElement.style.display = isCurrentlyHidden ? 'table-cell' : 'none';
 2162
 2163            // Переключаем видимость всех ячеек
 2164            tdElements.forEach(td => {
 2165                td.style.display = isCurrentlyHidden ? 'table-cell' : 'none';
 2166            });
 2167
 2168            // Меняем иконку во всех ссылках
 2169            linkElements.forEach(linkElement => {
 2170                const icon = linkElement.querySelector('i');
 2171                if (icon) {
 2172                    icon.className = isCurrentlyHidden ? 'fas fa-minus-circle' : 'fas fa-plus-circle';
 2173                }
 2174            });
 2175        }
 2176    }
 2177</script>
 2178
 2179@* Дополнительные расходы *@
 2180<script src="~/js/Studio2/Orders/Transactions/expTypeHandler.js"></script>
 2181
 2182@* Подключаем скрипт Combobox для автодополнения засылов *@
 2183<script>
 2184    // class Combobox вынесен в /js/shared/combobox.js (подключён в _Layout).
 2185
 2186    (function () {
 2187        function initMultiplayCustomSelects() {
 2188            if (typeof window.initCustomSelects !== 'function') return;
 2189            window.initCustomSelects('#shipmentTable .custom-select-init');
 2190            if (typeof window.syncStatusSelectAppearance === 'function') {
 2191                document.querySelectorAll('#shipmentTable .status-select').forEach(window.syncStatusSelectAppearance);
 2192            }
 2193            if (typeof window.initTransactionRowStatusHandlers === 'function') {
 2194                window.initTransactionRowStatusHandlers();
 2195            }
 2196        }
 2197        if (document.readyState === 'loading') {
 2198            document.addEventListener('DOMContentLoaded', initMultiplayCustomSelects);
 2199        } else {
 2200            initMultiplayCustomSelects();
 2201        }
 2202    })();
 2203</script>