< Summary

Information
Class: OzonOrdersWeb.Authorization.Seed.Studio2AppPageHierarchySync
Assembly: OzonOrdersWeb
File(s): /home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Authorization/Seed/Studio2AppPageHierarchySync.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 108
Coverable lines: 108
Total lines: 164
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 62
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
EnsureAsync()0%2040%
EnsureSectionHeadersAsync()0%1056320%
LinkTransactionPagesAsync()0%2040%
LinkOrdersPagesAsync()0%620%
GetParentIdAsync()100%210%
ApplyPageMetaAsync()0%420200%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Authorization/Seed/Studio2AppPageHierarchySync.cs

#LineLine coverage
 1using System.Linq;
 2using Microsoft.EntityFrameworkCore;
 3using Microsoft.Extensions.Caching.Memory;
 4using OzonDomains.Models.Authorization;
 5using OzonOrdersWeb.Authorization;
 6using OzonRepositories.Context;
 7
 8namespace OzonOrdersWeb.Authorization.Seed;
 9
 10/// <summary>
 11/// Иерархия и оформление (иконка + цвет) для страниц Studio2: заказы и транзакции, как в выпадающем меню.
 12/// </summary>
 13public static class Studio2AppPageHierarchySync
 14{
 15    private const string Area = "Studio2";
 16    private const string SectionPrefix = "Studio2.Section.";
 17
 18    public static async Task<int> EnsureAsync(ApplicationDbContext db, IMemoryCache? cache, CancellationToken ct = defau
 19    {
 020        var n = 0;
 021        n += await EnsureSectionHeadersAsync(db, ct);
 022        n += await LinkTransactionPagesAsync(db, ct);
 023        n += await LinkOrdersPagesAsync(db, ct);
 024        if (n > 0 && cache is not null)
 025            AutoPageAuthorizationFilter.InvalidatePageRegistry(cache);
 026        return n;
 027    }
 28
 29    private static async Task<int> EnsureSectionHeadersAsync(ApplicationDbContext db, CancellationToken ct)
 30    {
 031        var changed = 0;
 32
 33        // Порядок: сначала корень «Транзакции», затем подгруппы.
 034        var sections = new List<(string Code, string Title, string? ParentCode, int Sort, string? Icon, string? Accent)>
 035        {
 036            ("Studio2.Section.Transactions", "Транзакции", null, 100, "fas fa-random", "text-secondary"),
 037            ("Studio2.Section.TxMain", "Основные операции", "Studio2.Section.Transactions", 110, null, null),
 038            ("Studio2.Section.TxReturns", "Возвраты", "Studio2.Section.Transactions", 200, null, null),
 039            ("Studio2.Section.TxWarehouse", "Складские операции", "Studio2.Section.Transactions", 300, null, null),
 040            ("Studio2.Section.TxCancel", "Отмена", "Studio2.Section.Transactions", 400, null, null),
 041            ("Studio2.Section.Orders", "Заказы (Studio2)", null, 50, "fas fa-box-open", "text-primary"),
 042        };
 43
 044        foreach (var (code, title, parentCode, sort, icon, accent) in sections)
 45        {
 046            int? parentId = null;
 047            if (!string.IsNullOrEmpty(parentCode))
 48            {
 049                parentId = await db.AppPages.AsNoTracking()
 050                    .Where(x => x.Code == parentCode)
 051                    .Select(x => (int?)x.Id)
 052                    .FirstOrDefaultAsync(ct);
 53            }
 54
 055            var p = await db.AppPages.FirstOrDefaultAsync(x => x.Code == code, ct);
 056            if (p is null)
 57            {
 058                db.AppPages.Add(new AppPage
 059                {
 060                    Code = code,
 061                    DisplayName = title,
 062                    Area = Area,
 063                    Controller = "Section",
 064                    Action = "H_" + (code.Length > SectionPrefix.Length ? code[SectionPrefix.Length..].Replace(".", "_")
 065                    ParentId = parentId,
 066                    SortOrder = sort,
 067                    Icon = icon,
 068                    AccentClass = accent,
 069                    IsSectionHeader = true,
 070                    IsMenuItem = false,
 071                    IsActive = true
 072                });
 073                await db.SaveChangesAsync(ct);
 074                changed++;
 75            }
 76            else
 77            {
 078                var touch = false;
 079                if (p.DisplayName != title) { p.DisplayName = title; touch = true; }
 080                if (p.ParentId != parentId) { p.ParentId = parentId; touch = true; }
 081                if (p.SortOrder != sort) { p.SortOrder = sort; touch = true; }
 082                if (icon is not null && p.Icon != icon) { p.Icon = icon; touch = true; }
 083                if (accent is not null && p.AccentClass != accent) { p.AccentClass = accent; touch = true; }
 084                if (!p.IsSectionHeader) { p.IsSectionHeader = true; touch = true; }
 085                if (!p.IsActive) { p.IsActive = true; touch = true; }
 086                if (p.IsMenuItem) { p.IsMenuItem = false; touch = true; }
 087                if (touch) { p.UpdatedAt = DateTime.UtcNow; changed++; }
 88            }
 089        }
 90
 091        if (changed > 0) await db.SaveChangesAsync(ct);
 092        return changed;
 093    }
 94
 95    private static async Task<int> LinkTransactionPagesAsync(ApplicationDbContext db, CancellationToken ct)
 96    {
 097        var idBySection = new Dictionary<string, int>(StringComparer.Ordinal);
 098        foreach (var key in new[] { "Studio2.Section.TxMain", "Studio2.Section.TxReturns", "Studio2.Section.TxWarehouse"
 99        {
 0100            var id = await GetParentIdAsync(db, key, ct);
 0101            if (id is null) return 0;
 0102            idBySection[key] = id.Value;
 0103        }
 104
 0105        var map = Studio2RolePageMenuCatalog.TransactionRows
 0106            .Select(r => (
 0107                r.Code,
 0108                idBySection[r.ParentSectionCode],
 0109                r.Sort,
 0110                r.Title,
 0111                r.Icon,
 0112                (string?)r.Accent))
 0113            .ToArray();
 114
 0115        return await ApplyPageMetaAsync(db, map, ct);
 0116    }
 117
 118    private static async Task<int> LinkOrdersPagesAsync(ApplicationDbContext db, CancellationToken ct)
 119    {
 0120        var idOrd = await GetParentIdAsync(db, "Studio2.Section.Orders", ct);
 0121        if (idOrd is null) return 0;
 122
 0123        var map = Studio2RolePageMenuCatalog.OrderRows
 0124            .Select(r => (
 0125                r.Code,
 0126                idOrd.Value,
 0127                r.Sort,
 0128                r.Title,
 0129                r.Icon,
 0130                (string?)r.Accent))
 0131            .ToArray();
 132
 0133        return await ApplyPageMetaAsync(db, map, ct);
 0134    }
 135
 136    private static async Task<int?> GetParentIdAsync(ApplicationDbContext db, string code, CancellationToken ct) =>
 0137        await db.AppPages.AsNoTracking()
 0138            .Where(x => x.Code == code)
 0139            .Select(x => (int?)x.Id)
 0140            .FirstOrDefaultAsync(ct);
 141
 142    private static async Task<int> ApplyPageMetaAsync(
 143        ApplicationDbContext db,
 144        (string Code, int ParentId, int Sort, string Title, string Icon, string? Accent)[] map,
 145        CancellationToken ct)
 146    {
 0147        var n = 0;
 0148        foreach (var (code, parentId, sort, title, icon, accent) in map)
 149        {
 0150            var p = await db.AppPages.FirstOrDefaultAsync(x => x.Code == code, ct);
 0151            if (p is null) continue;
 0152            var row = false;
 0153            if (p.ParentId != parentId) { p.ParentId = parentId; row = true; }
 0154            if (p.SortOrder != sort) { p.SortOrder = sort; row = true; }
 0155            if (p.DisplayName != title) { p.DisplayName = title; row = true; }
 0156            if (p.Icon != icon) { p.Icon = icon; row = true; }
 0157            if (p.AccentClass != accent) { p.AccentClass = accent; row = true; }
 0158            if (p.IsSectionHeader) { p.IsSectionHeader = false; row = true; }
 0159            if (row) { p.UpdatedAt = DateTime.UtcNow; n++; }
 0160        }
 0161        if (n > 0) await db.SaveChangesAsync(ct);
 0162        return n;
 0163    }
 164}