| | | 1 | | @using OzonOrdersWeb.Areas.Studio2.ViewModels.Grid |
| | | 2 | | @using OzonOrdersWeb.WebServices.Directories |
| | | 3 | | @model List<OzonClientGridRow> |
| | | 4 | | @{ |
| | 0 | 5 | | ViewData["Title"] = $"Клиенты ({Model.Count})"; |
| | 0 | 6 | | Layout = "~/Views/Shared/_Layout.cshtml"; |
| | 0 | 7 | | var jsonOptions = new System.Text.Json.JsonSerializerOptions(System.Text.Json.JsonSerializerDefaults.Web); |
| | | 8 | | } |
| | | 9 | | |
| | 0 | 10 | | @await Html.PartialAsync("_BsxGridShell") |
| | | 11 | | |
| | | 12 | | <div class="container-fluid py-3 bsx-surface"> |
| | | 13 | | <div class="app-section-hero app-section-hero--import d-flex flex-wrap justify-content-between align-items-start gap |
| | | 14 | | <div> |
| | | 15 | | <h1><i class="fas fa-store me-2 text-primary"></i>Клиенты Ozon</h1> |
| | | 16 | | <div class="subtitle">Учётные записи маркетплейсов Ozon и Yandex — API, валюта, склад 1С</div> |
| | | 17 | | <div class="subtitle-help"> |
| | | 18 | | Каждый клиент — отдельный кабинет продавца: по его <strong>Client ID и API Key</strong> система |
| | | 19 | | загружает заказы, отчёты и остатки. <strong>ИНН</strong> связывает клиента с юрлицом в 1С, |
| | | 20 | | <strong>склад Bitrix</strong> — с физическим складом для документов. Связи складов Ozon ↔ 1С |
| | | 21 | | настраиваются отдельно в справочнике маппинга. API Key и остальные поля меняются на странице изменения к |
| | | 22 | | там же проверяется доступ к API. |
| | | 23 | | </div> |
| | | 24 | | <div class="app-section-hero__quick-links"> |
| | | 25 | | <a asp-area="Studio2" asp-controller="WarehouseMapping" asp-action="Index"><i class="fas fa-link"></i>Св |
| | | 26 | | <a asp-area="Studio2" asp-controller="BitrixStock" asp-action="Index"><i class="fas fa-boxes"></i>Синхро |
| | | 27 | | <a asp-area="Studio2" asp-controller="ClientStatus" asp-action="Index"><i class="fas fa-user-tag"></i>Ст |
| | | 28 | | </div> |
| | | 29 | | </div> |
| | | 30 | | <div class="d-flex flex-wrap gap-2 align-items-center"> |
| | | 31 | | <div class="bsx-dir-stats"> |
| | 0 | 32 | | <span class="bsx-dir-stat">Всего <b>@Model.Count</b></span> |
| | 0 | 33 | | <span class="bsx-dir-stat">Ozon <b>@Model.Count(c => c.ClientType == "Ozon")</b></span> |
| | 0 | 34 | | <span class="bsx-dir-stat">Yandex <b>@Model.Count(c => c.ClientType == "Yandex")</b></span> |
| | 0 | 35 | | @if (Model.Any(c => !c.HasApiKey)) |
| | | 36 | | { |
| | 0 | 37 | | <span class="bsx-dir-stat bsx-dir-stat--warn">Без API Key <b>@Model.Count(c => !c.HasApiKey)</b></sp |
| | | 38 | | } |
| | | 39 | | </div> |
| | | 40 | | <a asp-action="Create" class="btn btn-primary btn-sm"><i class="fas fa-plus me-1"></i>Добавить</a> |
| | | 41 | | </div> |
| | | 42 | | </div> |
| | | 43 | | |
| | 0 | 44 | | @await Html.PartialAsync("_BsxDirectoryGrid", new BsxDirectoryGridViewModel("ozonClient", "Список клиентов", "fa-lis |
| | 0 | 45 | | "Двойной клик по строке — страница изменения клиента.")) |
| | | 46 | | </div> |
| | | 47 | | |
| | | 48 | | @section Scripts { |
| | | 49 | | <script src="~/js/Studio2/Grid/bsx-directory.js" asp-append-version="true"></script> |
| | | 50 | | <script> |
| | | 51 | | (function () { |
| | | 52 | | const D = window.BsxDirectory; |
| | | 53 | | const esc = BsxGrid.esc; |
| | 0 | 54 | | const editUrl = id => '@Url.Action("Edit", "OzonClients", new { area = "Studio2" })/' + id; |
| | | 55 | | const TYPE_TONE = { Ozon: ['accent', 'fa-shopping-bag'], Yandex: ['danger', 'fa-shopping-cart'] }; |
| | | 56 | | const text = p => p.value || '—'; |
| | | 57 | | |
| | | 58 | | D.grid({ |
| | | 59 | | key: 'dirOzonClient', |
| | | 60 | | prefix: 'ozonClient', |
| | 0 | 61 | | rows: @Html.Raw(System.Text.Json.JsonSerializer.Serialize(Model, jsonOptions)), |
| | | 62 | | rowUrl: r => editUrl(r.id), |
| | | 63 | | columnDefs: [ |
| | | 64 | | D.setCol({ field: 'clientType', headerName: 'Тип', width: 120, filterParams: { labels: { '': 'Другой' } |
| | | 65 | | cellRenderer: p => p.value ? D.tone(p.value, TYPE_TONE[p.value][0], TYPE_TONE[p.value][1]) : D.tone('Д |
| | | 66 | | { field: 'name', headerName: 'Название', flex: 1, minWidth: 200, sort: 'asc', cellClass: 'fw-semibold' } |
| | | 67 | | { field: 'clientId', headerName: 'Client Id', headerTooltip: 'Seller API', width: 170, valueFormatter: t |
| | | 68 | | D.setCol({ field: 'hasApiKey', headerName: 'API Key', width: 120, filterParams: { labels: { 'true': 'Зад |
| | | 69 | | cellRenderer: p => p.value ? '<span class="bsx-muted" title="Ключ задан — изменить на странице редакти |
| | | 70 | | D.setCol({ field: 'currencyCode', headerName: 'Валюта', width: 105, filterParams: { labels: { NON: '—' } |
| | | 71 | | { field: 'innCode', headerName: 'ИНН', headerTooltip: 'Юрлицо 1С', width: 140, valueFormatter: text }, |
| | | 72 | | D.setCol({ colId: 'owner', headerName: 'Юрлицо 1С', flex: 1, minWidth: 190, |
| | | 73 | | valueGetter: p => p.data.owner.state === 'ok' ? p.data.owner.name : p.data.owner.state === 'missing' ? |
| | | 74 | | filterParams: { labels: { '': '(ИНН не задан)' } }, tooltipValueGetter: p => p.data.owner.fullName || |
| | | 75 | | cellRenderer: p => { |
| | | 76 | | const o = p.data.owner; |
| | | 77 | | if (o.state === 'ok') return `<span class="bsx-tone-text-accent text-truncate"><i class="fas fa-ch |
| | | 78 | | if (o.state === 'missing') return '<span class="bsx-tone-text-danger"><i class="fas fa-exclamation |
| | | 79 | | return '<span class="bsx-muted">—</span>'; |
| | | 80 | | } }), |
| | | 81 | | D.setCol({ field: 'warehouseName', headerName: 'Склад', headerTooltip: 'Склад Bitrix / 1С', width: 190, |
| | | 82 | | D.actionsCol(r => [ |
| | | 83 | | { icon: 'fa-pencil-alt', title: 'Изменить', href: editUrl(r.id) }, |
| | 0 | 84 | | { icon: 'fa-trash', title: 'Удалить клиента', kind: 'danger', href: '@Url.Action("Delete", "OzonClie |
| | | 85 | | ], { width: 100 }) |
| | | 86 | | ] |
| | | 87 | | }); |
| | | 88 | | })(); |
| | | 89 | | </script> |
| | | 90 | | } |