| | | 1 | | @model OzonOrdersWeb.Areas.Studio2.ViewModels.OneCDocumentViewModel |
| | | 2 | | @{ |
| | 0 | 3 | | ViewData["Title"] = string.IsNullOrWhiteSpace(Model.Number) ? "Документ 1С" : $"1С · {Model.Number}"; |
| | 0 | 4 | | var publicAccessKey = ViewBag.AccessKey as string ?? string.Empty; |
| | 0 | 5 | | var accessKeySuffix = string.IsNullOrEmpty(publicAccessKey) |
| | 0 | 6 | | ? string.Empty |
| | 0 | 7 | | : "&accessKey=" + Uri.EscapeDataString(publicAccessKey); |
| | | 8 | | |
| | 0 | 9 | | bool hasChars = Model.Lines.Any(l => !string.IsNullOrWhiteSpace(l.Characteristic)); |
| | 0 | 10 | | bool hasBatch = Model.Lines.Any(l => !string.IsNullOrWhiteSpace(l.Batch)); |
| | 0 | 11 | | bool hasWarehouse = Model.Lines.Any(l => !string.IsNullOrWhiteSpace(l.Warehouse)); |
| | 0 | 12 | | bool hasVat = Model.Lines.Any(l => l.VatAmount != 0 || !string.IsNullOrWhiteSpace(l.VatRate)); |
| | 0 | 13 | | int colspan = 6 + (hasChars ? 1 : 0) + (hasBatch ? 1 : 0) + (hasWarehouse ? 1 : 0) + (hasVat ? 1 : 0); |
| | | 14 | | } |
| | | 15 | | |
| | | 16 | | <link rel="stylesheet" href="~/css/Studio2/OneCDocument/one-c-document-details.css" asp-append-version="true"/> |
| | | 17 | | |
| | | 18 | | <div class="container py-3 ocd-page"> |
| | | 19 | | |
| | 0 | 20 | | @if (!string.IsNullOrWhiteSpace(Model.ErrorMessage)) |
| | | 21 | | { |
| | | 22 | | <div class="alert alert-danger d-flex align-items-center gap-2"> |
| | | 23 | | <i class="fas fa-circle-exclamation"></i> |
| | 0 | 24 | | <span>@Model.ErrorMessage</span> |
| | | 25 | | </div> |
| | | 26 | | <a href="javascript:history.back()" class="btn btn-outline-secondary btn-sm"> |
| | | 27 | | <i class="fas fa-arrow-left me-1"></i>Назад |
| | | 28 | | </a> |
| | 0 | 29 | | return; |
| | | 30 | | } |
| | | 31 | | |
| | | 32 | | <div class="app-section-hero app-section-hero--import d-flex flex-wrap justify-content-between align-items-start gap |
| | | 33 | | <div> |
| | 0 | 34 | | <h1><i class="fas fa-file-invoice me-2 text-primary"></i>@(string.IsNullOrWhiteSpace(Model.DocTypeLabel) ? " |
| | 0 | 35 | | <div class="subtitle">@(string.IsNullOrWhiteSpace(Model.Number) ? "Реквизиты и строки документа" : $"№ {Mode |
| | | 36 | | <div class="subtitle-help">Проверьте реквизиты, товары, суммы и НДС по данным учётной системы.</div> |
| | | 37 | | <div class="app-section-hero__quick-links"> |
| | | 38 | | <a href="javascript:history.back()"><i class="fas fa-arrow-left"></i>Назад</a> |
| | | 39 | | <a asp-area="Studio2" asp-controller="WarehouseStock" asp-action="Index"><i class="fas fa-warehouse"></i |
| | | 40 | | </div> |
| | | 41 | | </div> |
| | | 42 | | <div class="d-flex gap-2 align-items-center flex-wrap"> |
| | 0 | 43 | | @if (Model.Posted) |
| | | 44 | | { |
| | | 45 | | <span class="badge bg-success-subtle text-success border border-success-subtle"><i class="fas fa-circle- |
| | | 46 | | } |
| | | 47 | | else |
| | | 48 | | { |
| | | 49 | | <span class="badge bg-warning-subtle text-warning border border-warning-subtle"><i class="fas fa-circle- |
| | | 50 | | } |
| | 0 | 51 | | @if (Model.DeletionMark) |
| | | 52 | | { |
| | | 53 | | <span class="badge bg-danger-subtle text-danger border border-danger-subtle"><i class="fas fa-trash me-1 |
| | | 54 | | } |
| | | 55 | | </div> |
| | | 56 | | </div> |
| | | 57 | | |
| | | 58 | | <!-- Реквизиты --> |
| | | 59 | | <div class="card ocd-card mb-3"> |
| | | 60 | | <div class="card-header d-flex align-items-center gap-2 flex-wrap py-2"> |
| | | 61 | | <span class="fw-semibold"><i class="fas fa-list-check text-primary me-1"></i>Реквизиты документа</span> |
| | | 62 | | </div> |
| | | 63 | | |
| | | 64 | | <!-- Реквизиты --> |
| | | 65 | | <div class="card-body py-2 px-3"> |
| | | 66 | | <div class="row g-2"> |
| | 0 | 67 | | @if (!string.IsNullOrWhiteSpace(Model.Number)) |
| | | 68 | | { |
| | | 69 | | <div class="col-6 col-md-4 col-lg-3 col-xl-2"> |
| | | 70 | | <div class="ocd-attr-label">Номер</div> |
| | 0 | 71 | | <div class="ocd-attr-value">@Model.Number</div> |
| | | 72 | | </div> |
| | | 73 | | } |
| | 0 | 74 | | @if (Model.Date.HasValue) |
| | | 75 | | { |
| | | 76 | | <div class="col-6 col-md-4 col-lg-3 col-xl-2"> |
| | | 77 | | <div class="ocd-attr-label">Дата</div> |
| | 0 | 78 | | <div class="ocd-attr-value">@Model.Date.Value.ToString("dd.MM.yyyy HH:mm")</div> |
| | | 79 | | </div> |
| | | 80 | | } |
| | 0 | 81 | | @if (!string.IsNullOrWhiteSpace(Model.OperationKind)) |
| | | 82 | | { |
| | | 83 | | <div class="col-6 col-md-4 col-lg-3 col-xl-2"> |
| | | 84 | | <div class="ocd-attr-label">Операция</div> |
| | 0 | 85 | | <div class="ocd-attr-value">@Model.OperationKind</div> |
| | | 86 | | </div> |
| | | 87 | | } |
| | 0 | 88 | | @if (!string.IsNullOrWhiteSpace(Model.Organization)) |
| | | 89 | | { |
| | | 90 | | <div class="col-6 col-md-4 col-lg-3 col-xl-2"> |
| | | 91 | | <div class="ocd-attr-label">Организация</div> |
| | 0 | 92 | | <div class="ocd-attr-value">@Model.Organization</div> |
| | | 93 | | </div> |
| | | 94 | | } |
| | 0 | 95 | | @if (!string.IsNullOrWhiteSpace(Model.Counterparty)) |
| | | 96 | | { |
| | | 97 | | <div class="col-6 col-md-4 col-lg-3 col-xl-2"> |
| | | 98 | | <div class="ocd-attr-label">Покупатель / поставщик</div> |
| | 0 | 99 | | <div class="ocd-attr-value fw-medium">@Model.Counterparty</div> |
| | | 100 | | </div> |
| | | 101 | | } |
| | 0 | 102 | | @if (!string.IsNullOrWhiteSpace(Model.Contract)) |
| | | 103 | | { |
| | | 104 | | <div class="col-6 col-md-4 col-lg-3 col-xl-2"> |
| | | 105 | | <div class="ocd-attr-label">Договор</div> |
| | 0 | 106 | | <div class="ocd-attr-value">@Model.Contract</div> |
| | | 107 | | </div> |
| | | 108 | | } |
| | 0 | 109 | | @if (!string.IsNullOrWhiteSpace(Model.WarehouseRecipient)) |
| | | 110 | | { |
| | 0 | 111 | | @if (!string.IsNullOrWhiteSpace(Model.Warehouse)) |
| | | 112 | | { |
| | | 113 | | <div class="col-6 col-md-4 col-lg-3 col-xl-2"> |
| | | 114 | | <div class="ocd-attr-label">Склад-отправитель</div> |
| | 0 | 115 | | <div class="ocd-attr-value">@Model.Warehouse</div> |
| | | 116 | | </div> |
| | | 117 | | } |
| | | 118 | | <div class="col-6 col-md-4 col-lg-3 col-xl-2"> |
| | | 119 | | <div class="ocd-attr-label">Склад-получатель</div> |
| | 0 | 120 | | <div class="ocd-attr-value">@Model.WarehouseRecipient</div> |
| | | 121 | | </div> |
| | | 122 | | } |
| | 0 | 123 | | else if (!string.IsNullOrWhiteSpace(Model.Warehouse)) |
| | | 124 | | { |
| | | 125 | | <div class="col-6 col-md-4 col-lg-3 col-xl-2"> |
| | | 126 | | <div class="ocd-attr-label">Склад</div> |
| | 0 | 127 | | <div class="ocd-attr-value">@Model.Warehouse</div> |
| | | 128 | | </div> |
| | | 129 | | } |
| | 0 | 130 | | @if (!string.IsNullOrWhiteSpace(Model.Comment)) |
| | | 131 | | { |
| | | 132 | | <div class="col-12"> |
| | | 133 | | <div class="ocd-attr-label">Комментарий</div> |
| | 0 | 134 | | <div class="ocd-attr-value text-secondary">@Model.Comment</div> |
| | | 135 | | </div> |
| | | 136 | | } |
| | | 137 | | </div> |
| | 0 | 138 | | @if (!string.IsNullOrWhiteSpace(Model.RefKey)) |
| | | 139 | | { |
| | | 140 | | <div class="ocd-guid mt-2"> |
| | 0 | 141 | | GUID: <span class="font-monospace user-select-all">@Model.RefKey</span> |
| | | 142 | | </div> |
| | | 143 | | } |
| | | 144 | | </div> |
| | | 145 | | </div> |
| | | 146 | | |
| | | 147 | | <!-- Таблица товаров --> |
| | | 148 | | <div class="card mb-3"> |
| | | 149 | | <div class="card-header d-flex align-items-center gap-3 py-2"> |
| | | 150 | | <span class="fw-semibold small text-muted"> |
| | | 151 | | <i class="fas fa-list me-1"></i>Товары |
| | | 152 | | </span> |
| | 0 | 153 | | <span class="badge bg-secondary-subtle text-secondary">@Model.Lines.Count поз.</span> |
| | 0 | 154 | | @if (Model.Lines.Count > 5) |
| | | 155 | | { |
| | | 156 | | <input type="text" id="doc-search" class="form-control form-control-sm ocd-search ms-auto" |
| | | 157 | | placeholder="Поиск по артикулу / названию…" oninput="filterLines(this.value)"> |
| | | 158 | | } |
| | | 159 | | </div> |
| | | 160 | | <div class="table-responsive"> |
| | | 161 | | <table class="table table-sm table-hover ocd-lines-table mb-0" id="doc-lines-table"> |
| | | 162 | | <thead class="table-light"> |
| | | 163 | | <tr> |
| | | 164 | | <th class="text-center text-muted" style="width:36px">№</th> |
| | | 165 | | <th class="col-nom">Номенклатура</th> |
| | | 166 | | <th class="col-art">Артикул</th> |
| | 0 | 167 | | @if (hasChars) { <th>Характ.</th> } |
| | 0 | 168 | | @if (hasBatch) { <th>Партия</th> } |
| | 0 | 169 | | @if (hasWarehouse) { <th>Склад</th> } |
| | | 170 | | <th class="text-end" style="width:70px">Кол-во</th> |
| | | 171 | | <th class="text-end" style="width:90px">Цена, ₽</th> |
| | | 172 | | <th class="text-end" style="width:100px">Сумма, ₽</th> |
| | 0 | 173 | | @if (hasVat) { <th class="text-end" style="width:80px">НДС, ₽</th> } |
| | | 174 | | </tr> |
| | | 175 | | </thead> |
| | | 176 | | <tbody id="doc-tbody"> |
| | 0 | 177 | | @if (!Model.Lines.Any()) |
| | | 178 | | { |
| | | 179 | | <tr> |
| | | 180 | | <td colspan="@colspan" class="text-center text-muted py-4"> |
| | | 181 | | <i class="fas fa-inbox me-2"></i>Позиций нет |
| | | 182 | | </td> |
| | | 183 | | </tr> |
| | | 184 | | } |
| | 0 | 185 | | @foreach (var line in Model.Lines.OrderBy(l => l.LineNumber)) |
| | | 186 | | { |
| | 0 | 187 | | <tr data-search="@($"{line.Article} {line.Nomenclature}".ToLower())"> |
| | 0 | 188 | | <td class="text-center text-muted">@line.LineNumber</td> |
| | 0 | 189 | | <td class="col-nom">@(string.IsNullOrWhiteSpace(line.Nomenclature) ? "—" : line.Nomenclature |
| | | 190 | | <td class="col-art"> |
| | 0 | 191 | | @if (!string.IsNullOrWhiteSpace(line.Article)) |
| | | 192 | | { |
| | | 193 | | <a href="/Studio2/WarehouseStock/movement-map?article=@Uri.EscapeDataString(line.Art |
| | | 194 | | target="_blank" class="font-monospace text-decoration-none" |
| | 0 | 195 | | title="Карта движений">@line.Article</a> |
| | | 196 | | } |
| | | 197 | | </td> |
| | 0 | 198 | | @if (hasChars) { <td class="text-muted small">@line.Characteristic</td> } |
| | 0 | 199 | | @if (hasBatch) { <td class="text-muted small">@line.Batch</td> } |
| | 0 | 200 | | @if (hasWarehouse) { <td class="text-muted small">@line.Warehouse</td> } |
| | 0 | 201 | | <td class="text-end fw-medium">@line.Quantity.ToString("0.###")</td> |
| | 0 | 202 | | <td class="text-end">@line.Price.ToString("N2")</td> |
| | 0 | 203 | | <td class="text-end fw-semibold">@line.Amount.ToString("N2")</td> |
| | 0 | 204 | | @if (hasVat) { <td class="text-end text-muted">@line.VatAmount.ToString("N2")</td> } |
| | | 205 | | </tr> |
| | | 206 | | } |
| | | 207 | | </tbody> |
| | | 208 | | </table> |
| | | 209 | | </div> |
| | | 210 | | |
| | | 211 | | <!-- Итоги --> |
| | 0 | 212 | | @if (Model.TotalAmount != 0 || Model.VatAmount != 0) |
| | | 213 | | { |
| | | 214 | | <div class="card-footer d-flex justify-content-end gap-4 py-2 small"> |
| | 0 | 215 | | @if (Model.VatAmount != 0) |
| | | 216 | | { |
| | 0 | 217 | | <span><span class="text-muted">НДС:</span> <span class="fw-medium">@Model.VatAmount.ToString("N2") ₽ |
| | | 218 | | } |
| | 0 | 219 | | <span><span class="text-muted">Итого:</span> <span class="fw-bold">@Model.TotalAmount.ToString("N2") ₽</ |
| | | 220 | | </div> |
| | | 221 | | } |
| | | 222 | | </div> |
| | | 223 | | |
| | | 224 | | </div> |
| | | 225 | | |
| | | 226 | | @section Scripts { |
| | | 227 | | <script> |
| | | 228 | | function filterLines(q) { |
| | | 229 | | q = (q || '').toLowerCase().trim(); |
| | | 230 | | document.querySelectorAll('#doc-tbody tr[data-search]').forEach(tr => { |
| | | 231 | | const match = !q || tr.dataset.search.includes(q); |
| | | 232 | | tr.style.display = match ? '' : 'none'; |
| | | 233 | | tr.classList.toggle('ocd-highlight', !!q && match); |
| | | 234 | | }); |
| | | 235 | | } |
| | | 236 | | </script> |
| | | 237 | | } |