< Summary

Information
Class: Services.ApiSupplierSettingsServices.ApiSupplierSettingsService
Assembly: Services
File(s): /home/runner/work/Studio2Prod/Studio2Prod/AppRepository/ApiSupplierSettings/ApiSupplierSettingsService.cs
Line coverage
67%
Covered lines: 74
Uncovered lines: 36
Coverable lines: 110
Total lines: 250
Line coverage: 67.2%
Branch coverage
71%
Covered branches: 27
Total branches: 38
Branch coverage: 71%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
GetDefaultDisplayName(...)50%271044.44%
.ctor(...)100%11100%
.ctor(...)100%11100%
GetAllAsync()50%4490%
InvalidateCache()100%11100%
GetAsync()100%22100%
SaveAsync()100%11100%
SaveAsync()81.81%222295.83%
GetArmtekAsync()100%11100%
SaveArmtekAsync()100%11100%
GetArmtekByAsync(...)100%11100%
SaveArmtekByAsync(...)100%11100%
GetShateMAsync()100%11100%
SaveShateMAsync()100%11100%
GetAvdAsync(...)100%11100%
SaveAvdAsync(...)100%11100%
GetBergAsync(...)100%11100%
SaveBergAsync(...)100%11100%
GetMotexAsync(...)100%11100%
SaveMotexAsync(...)100%210%
GetMlAutoAsync(...)100%11100%
SaveMlAutoAsync(...)100%210%
GetMlAutoRuAsync(...)100%210%
SaveMlAutoRuAsync(...)100%210%
GetForumAutoAsync(...)100%210%
SaveForumAutoAsync(...)100%210%
GetForumAutoInterpartsAsync(...)100%210%
SaveForumAutoInterpartsAsync(...)100%210%
GetForumAutoPiterAsync(...)100%210%
SaveForumAutoPiterAsync(...)100%210%
GetForumAutoRostovAsync(...)100%210%
SaveForumAutoRostovAsync(...)100%210%
GetForumAutoIstraAsync(...)100%210%
SaveForumAutoIstraAsync(...)100%210%
GetFavoritPartsAsync(...)100%210%
SaveFavoritPartsAsync(...)100%210%
GetFavoritPartsIstraAsync(...)100%210%
SaveFavoritPartsIstraAsync(...)100%210%
GetFavoritPartsRostovAsync(...)100%210%
SaveFavoritPartsRostovAsync(...)100%210%
SaveWithDeliveryAddressAsync()100%210%
GetMoskvorechieIstraAsync(...)100%11100%
SaveMoskvorechieIstraAsync(...)100%210%
GetProfitLigaAsync(...)100%210%
SaveProfitLigaAsync(...)100%210%
GetNikeiAsync(...)100%210%
GetMikadoMskHod20Async(...)100%210%
GetJapartsAsync(...)100%210%
GetZZapMoscowAsync(...)100%210%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/AppRepository/ApiSupplierSettings/ApiSupplierSettingsService.cs

#LineLine coverage
 1using Microsoft.EntityFrameworkCore;
 2using Microsoft.Extensions.Caching.Memory;
 3using OzonDomains;
 4using OzonDomains.Models;
 5using OzonRepositories.Context;
 6
 7namespace Services.ApiSupplierSettingsServices;
 8
 9/// <summary>Единая точка чтения и сохранения параметров API-поставщиков.</summary>
 10public sealed class ApiSupplierSettingsService
 11{
 12    // Таблица ~20 строк, меняется только из админки (ApiSupplierSettingsController -> SaveAsync).
 13    // Раньше страница транзакции делала ~19 последовательных SingleOrDefaultAsync подряд —
 14    // теперь один ToListAsync под кэшем + инвалидация при сохранении.
 15    private const string CacheKey = "ApiSupplierSettings:AllByProviderKey";
 116    private static readonly TimeSpan CacheTtl = TimeSpan.FromMinutes(10);
 17
 18    private readonly ApplicationDbContext _context;
 19    private readonly IMemoryCache _cache;
 20
 321    public static string GetDefaultDisplayName(string providerKey) => providerKey switch
 322    {
 023        ApiSupplierSettings.ForumAutoProviderKey => "Форум-Авто Союз (Ходынка)",
 024        ApiSupplierSettings.ForumAutoInterpartsProviderKey => "Форум-Авто Интерпартс (Ходынка)",
 025        ApiSupplierSettings.ForumAutoPiterProviderKey => "Форум-Авто Интерпартс (Питер)",
 026        ApiSupplierSettings.ForumAutoRostovProviderKey => "Форум-Авто Интерпартс (Ростов)",
 027        ApiSupplierSettings.ForumAutoIstraProviderKey => "Форум-Авто Интерпартс (Истра)",
 328        _ => providerKey
 329    };
 30
 5631    public ApiSupplierSettingsService(ApplicationDbContext context, IMemoryCache cache)
 32    {
 5633        _context = context;
 5634        _cache = cache;
 5635    }
 36
 37    /// <summary>Упрощённый конструктор для тестов — с изолированным кэшем.</summary>
 38    public ApiSupplierSettingsService(ApplicationDbContext context)
 5639        : this(context, new MemoryCache(new MemoryCacheOptions()))
 40    {
 5641    }
 42
 43    private async Task<IReadOnlyDictionary<string, ApiSupplierSettings>> GetAllAsync(CancellationToken cancellationToken
 44    {
 3545        if (_cache.TryGetValue(CacheKey, out IReadOnlyDictionary<string, ApiSupplierSettings>? cached) && cached != null
 046            return cached;
 47
 3548        var rows = await _context.ApiSupplierSettings
 3549            .Include(x => x.Supplier)
 3550            .AsNoTracking()
 3551            .ToListAsync(cancellationToken);
 52
 3353        IReadOnlyDictionary<string, ApiSupplierSettings> map = rows
 3054            .GroupBy(x => x.ProviderKey)
 9355            .ToDictionary(g => g.Key, g => g.First());
 56
 3357        _cache.Set(CacheKey, map, CacheTtl);
 3358        return map;
 3359    }
 60
 1061    private void InvalidateCache() => _cache.Remove(CacheKey);
 62
 63    public async Task<ApiSupplierSettings> GetAsync(string providerKey, CurrencyCode defaultCurrency,
 64        CancellationToken cancellationToken = default)
 65    {
 3566        var all = await GetAllAsync(cancellationToken);
 3367        if (all.TryGetValue(providerKey, out var settings))
 3068            return settings;
 69
 370        return new ApiSupplierSettings
 371        {
 372            ProviderKey = providerKey,
 373            CurrencyCode = defaultCurrency,
 374            IsQuotationEnabled = true,
 375            DisplayName = GetDefaultDisplayName(providerKey)
 376        };
 3377    }
 78
 79    public async Task SaveAsync(string providerKey, int? supplierId, CurrencyCode defaultCurrency, bool isQuotationEnabl
 80        CancellationToken cancellationToken = default)
 681        => await SaveAsync(providerKey, supplierId, defaultCurrency, isQuotationEnabled, null, cancellationToken, false)
 82
 83    public async Task SaveAsync(string providerKey, int? supplierId, CurrencyCode defaultCurrency, bool isQuotationEnabl
 84        string? deliveryAddress, CancellationToken cancellationToken = default, bool updateDeliveryAddress = true,
 85        int? extraDeliveryHours = null, decimal? priceMultiplier = null, string? displayName = null)
 86    {
 1187        var settings = await _context.ApiSupplierSettings.SingleOrDefaultAsync(
 1188            x => x.ProviderKey == providerKey, cancellationToken);
 1189        if (settings == null)
 90        {
 891            settings = new ApiSupplierSettings { ProviderKey = providerKey };
 892            await _context.ApiSupplierSettings.AddAsync(settings, cancellationToken);
 93        }
 94
 1195        Supplier? supplier = null;
 1196        if (supplierId.HasValue)
 97        {
 398            supplier = await _context.Suppliers.SingleOrDefaultAsync(x => x.Id == supplierId.Value, cancellationToken)
 399                ?? throw new InvalidOperationException("Выбранный системный поставщик не найден.");
 100        }
 101
 10102        settings.SupplierId = supplier?.Id;
 10103        settings.Supplier = supplier;
 10104        settings.CurrencyCode = supplier?.CurrencyCode ?? defaultCurrency;
 10105        settings.IsQuotationEnabled = isQuotationEnabled;
 10106        if (displayName != null)
 0107            settings.DisplayName = string.IsNullOrWhiteSpace(displayName) ? GetDefaultDisplayName(providerKey) : display
 10108        if (extraDeliveryHours.HasValue)
 3109            settings.ExtraDeliveryHours = Math.Clamp(extraDeliveryHours.Value, 0, SupplierDeliverySurcharge.MaxExtraHour
 10110        if (priceMultiplier.HasValue)
 2111            settings.PriceMultiplier = SupplierQuotationPriceMultiplier.Clamp(priceMultiplier.Value);
 10112        if (updateDeliveryAddress)
 5113            settings.DeliveryAddress = string.IsNullOrWhiteSpace(deliveryAddress) ? null : deliveryAddress.Trim();
 10114        await _context.SaveChangesAsync(cancellationToken);
 10115        InvalidateCache();
 10116    }
 117
 118    public async Task<ApiSupplierSettings> GetArmtekAsync(CancellationToken cancellationToken = default)
 119    {
 8120        return await GetAsync(ApiSupplierSettings.ArmtekProviderKey, CurrencyCode.RUB, cancellationToken);
 7121    }
 122
 123    public async Task SaveArmtekAsync(int? supplierId, bool isQuotationEnabled,
 124        CancellationToken cancellationToken = default)
 125    {
 2126        await SaveAsync(ApiSupplierSettings.ArmtekProviderKey, supplierId, CurrencyCode.RUB, isQuotationEnabled, cancell
 1127    }
 128
 129    public Task<ApiSupplierSettings> GetArmtekByAsync(CancellationToken cancellationToken = default)
 2130        => GetAsync(ApiSupplierSettings.ArmtekByProviderKey, CurrencyCode.BYN, cancellationToken);
 131
 132    public Task SaveArmtekByAsync(int? supplierId, bool isQuotationEnabled, CancellationToken cancellationToken = defaul
 1133        => SaveAsync(ApiSupplierSettings.ArmtekByProviderKey, supplierId, CurrencyCode.BYN, isQuotationEnabled, cancella
 134
 135    public async Task<ApiSupplierSettings> GetShateMAsync(CancellationToken cancellationToken = default)
 1136        => await GetAsync(ApiSupplierSettings.ShateMProviderKey, CurrencyCode.BYN, cancellationToken);
 137
 138    public async Task SaveShateMAsync(int? supplierId, bool isQuotationEnabled, CancellationToken cancellationToken = de
 139    {
 1140        await SaveAsync(ApiSupplierSettings.ShateMProviderKey, supplierId, CurrencyCode.BYN, isQuotationEnabled, cancell
 1141    }
 142
 143    public Task<ApiSupplierSettings> GetAvdAsync(CancellationToken cancellationToken = default)
 1144        => GetAsync(ApiSupplierSettings.AvdProviderKey, CurrencyCode.RUB, cancellationToken);
 145
 146    public Task SaveAvdAsync(int? supplierId, bool isQuotationEnabled, CancellationToken cancellationToken = default)
 1147        => SaveAsync(ApiSupplierSettings.AvdProviderKey, supplierId, CurrencyCode.RUB, isQuotationEnabled, cancellationT
 148
 149    public Task<ApiSupplierSettings> GetBergAsync(CancellationToken cancellationToken = default)
 5150        => GetAsync(ApiSupplierSettings.BergProviderKey, CurrencyCode.RUB, cancellationToken);
 151
 152    public Task SaveBergAsync(int? supplierId, bool isQuotationEnabled, CancellationToken cancellationToken = default)
 1153        => SaveAsync(ApiSupplierSettings.BergProviderKey, supplierId, CurrencyCode.RUB, isQuotationEnabled, cancellation
 154
 155    public Task<ApiSupplierSettings> GetMotexAsync(CancellationToken cancellationToken = default)
 7156        => GetAsync(ApiSupplierSettings.MotexProviderKey, CurrencyCode.BYN, cancellationToken);
 157
 158    public Task SaveMotexAsync(int? supplierId, bool isQuotationEnabled, CancellationToken cancellationToken = default)
 0159        => SaveAsync(ApiSupplierSettings.MotexProviderKey, supplierId, CurrencyCode.BYN, isQuotationEnabled, cancellatio
 160
 161    public Task<ApiSupplierSettings> GetMlAutoAsync(CancellationToken cancellationToken = default)
 1162        => GetAsync(ApiSupplierSettings.MlAutoProviderKey, CurrencyCode.BYN, cancellationToken);
 163
 164    public Task SaveMlAutoAsync(int? supplierId, bool isQuotationEnabled, CancellationToken cancellationToken = default)
 0165        => SaveAsync(ApiSupplierSettings.MlAutoProviderKey, supplierId, CurrencyCode.BYN, isQuotationEnabled, cancellati
 166
 167    public Task<ApiSupplierSettings> GetMlAutoRuAsync(CancellationToken cancellationToken = default)
 0168        => GetAsync(ApiSupplierSettings.MlAutoRuProviderKey, CurrencyCode.RUB, cancellationToken);
 169
 170    public Task SaveMlAutoRuAsync(int? supplierId, bool isQuotationEnabled, CancellationToken cancellationToken = defaul
 0171        => SaveAsync(ApiSupplierSettings.MlAutoRuProviderKey, supplierId, CurrencyCode.RUB, isQuotationEnabled, cancella
 172
 173    public Task<ApiSupplierSettings> GetForumAutoAsync(CancellationToken cancellationToken = default)
 0174        => GetAsync(ApiSupplierSettings.ForumAutoProviderKey, CurrencyCode.RUB, cancellationToken);
 175
 176    public Task SaveForumAutoAsync(int? supplierId, bool isQuotationEnabled, CancellationToken cancellationToken = defau
 0177        => SaveAsync(ApiSupplierSettings.ForumAutoProviderKey, supplierId, CurrencyCode.RUB, isQuotationEnabled, cancell
 178
 179    public Task<ApiSupplierSettings> GetForumAutoInterpartsAsync(CancellationToken cancellationToken = default)
 0180        => GetAsync(ApiSupplierSettings.ForumAutoInterpartsProviderKey, CurrencyCode.RUB, cancellationToken);
 181
 182    public Task SaveForumAutoInterpartsAsync(int? supplierId, bool isQuotationEnabled, CancellationToken cancellationTok
 0183        => SaveAsync(ApiSupplierSettings.ForumAutoInterpartsProviderKey, supplierId, CurrencyCode.RUB, isQuotationEnable
 184
 185    public Task<ApiSupplierSettings> GetForumAutoPiterAsync(CancellationToken cancellationToken = default)
 0186        => GetAsync(ApiSupplierSettings.ForumAutoPiterProviderKey, CurrencyCode.RUB, cancellationToken);
 187
 188    public Task SaveForumAutoPiterAsync(int? supplierId, bool isQuotationEnabled, CancellationToken cancellationToken = 
 0189        => SaveAsync(ApiSupplierSettings.ForumAutoPiterProviderKey, supplierId, CurrencyCode.RUB, isQuotationEnabled, ca
 190
 191    public Task<ApiSupplierSettings> GetForumAutoRostovAsync(CancellationToken cancellationToken = default)
 0192        => GetAsync(ApiSupplierSettings.ForumAutoRostovProviderKey, CurrencyCode.RUB, cancellationToken);
 193
 194    public Task SaveForumAutoRostovAsync(int? supplierId, bool isQuotationEnabled, CancellationToken cancellationToken =
 0195        => SaveAsync(ApiSupplierSettings.ForumAutoRostovProviderKey, supplierId, CurrencyCode.RUB, isQuotationEnabled, c
 196
 197    public Task<ApiSupplierSettings> GetForumAutoIstraAsync(CancellationToken cancellationToken = default)
 0198        => GetAsync(ApiSupplierSettings.ForumAutoIstraProviderKey, CurrencyCode.RUB, cancellationToken);
 199
 200    public Task SaveForumAutoIstraAsync(int? supplierId, bool isQuotationEnabled, CancellationToken cancellationToken = 
 0201        => SaveAsync(ApiSupplierSettings.ForumAutoIstraProviderKey, supplierId, CurrencyCode.RUB, isQuotationEnabled, ca
 202
 203    public Task<ApiSupplierSettings> GetFavoritPartsAsync(CancellationToken cancellationToken = default)
 0204        => GetAsync(ApiSupplierSettings.FavoritPartsProviderKey, CurrencyCode.RUB, cancellationToken);
 205
 206    public Task SaveFavoritPartsAsync(int? supplierId, bool isQuotationEnabled, string? deliveryAddress, CancellationTok
 0207        => SaveWithDeliveryAddressAsync(ApiSupplierSettings.FavoritPartsProviderKey, supplierId, isQuotationEnabled, del
 208
 209    public Task<ApiSupplierSettings> GetFavoritPartsIstraAsync(CancellationToken cancellationToken = default)
 0210        => GetAsync(ApiSupplierSettings.FavoritPartsIstraProviderKey, CurrencyCode.RUB, cancellationToken);
 211
 212    public Task SaveFavoritPartsIstraAsync(int? supplierId, bool isQuotationEnabled, string? deliveryAddress, Cancellati
 0213        => SaveWithDeliveryAddressAsync(ApiSupplierSettings.FavoritPartsIstraProviderKey, supplierId, isQuotationEnabled
 214
 215    public Task<ApiSupplierSettings> GetFavoritPartsRostovAsync(CancellationToken cancellationToken = default)
 0216        => GetAsync(ApiSupplierSettings.FavoritPartsRostovProviderKey, CurrencyCode.RUB, cancellationToken);
 217
 218    public Task SaveFavoritPartsRostovAsync(int? supplierId, bool isQuotationEnabled, string? deliveryAddress, Cancellat
 0219        => SaveWithDeliveryAddressAsync(ApiSupplierSettings.FavoritPartsRostovProviderKey, supplierId, isQuotationEnable
 220
 221    private async Task SaveWithDeliveryAddressAsync(string providerKey, int? supplierId, bool isQuotationEnabled,
 222        string? deliveryAddress, CancellationToken cancellationToken)
 223    {
 0224        await SaveAsync(providerKey, supplierId, CurrencyCode.RUB, isQuotationEnabled, deliveryAddress, cancellationToke
 0225    }
 226
 227    public Task<ApiSupplierSettings> GetMoskvorechieIstraAsync(CancellationToken cancellationToken = default)
 3228        => GetAsync(ApiSupplierSettings.MoskvorechieIstraProviderKey, CurrencyCode.RUB, cancellationToken);
 229
 230    public Task SaveMoskvorechieIstraAsync(int? supplierId, bool isQuotationEnabled, CancellationToken cancellationToken
 0231        => SaveAsync(ApiSupplierSettings.MoskvorechieIstraProviderKey, supplierId, CurrencyCode.RUB, isQuotationEnabled,
 232
 233    public Task<ApiSupplierSettings> GetProfitLigaAsync(CancellationToken cancellationToken = default)
 0234        => GetAsync(ApiSupplierSettings.ProfitLigaProviderKey, CurrencyCode.RUB, cancellationToken);
 235
 236    public Task SaveProfitLigaAsync(int? supplierId, bool isQuotationEnabled, CancellationToken cancellationToken = defa
 0237        => SaveAsync(ApiSupplierSettings.ProfitLigaProviderKey, supplierId, CurrencyCode.RUB, isQuotationEnabled, cancel
 238
 239    public Task<ApiSupplierSettings> GetNikeiAsync(CancellationToken cancellationToken = default)
 0240        => GetAsync(ApiSupplierSettings.NikeiProviderKey, CurrencyCode.RUB, cancellationToken);
 241
 242    public Task<ApiSupplierSettings> GetMikadoMskHod20Async(CancellationToken cancellationToken = default)
 0243        => GetAsync(ApiSupplierSettings.MikadoMskHod20ProviderKey, CurrencyCode.RUB, cancellationToken);
 244
 245    public Task<ApiSupplierSettings> GetJapartsAsync(CancellationToken cancellationToken = default)
 0246        => GetAsync(ApiSupplierSettings.JapartsProviderKey, CurrencyCode.RUB, cancellationToken);
 247
 248    public Task<ApiSupplierSettings> GetZZapMoscowAsync(CancellationToken cancellationToken = default)
 0249        => GetAsync(ApiSupplierSettings.ZZapMoscowProviderKey, CurrencyCode.RUB, cancellationToken);
 250}

Methods/Properties

.cctor()
GetDefaultDisplayName(System.String)
.ctor(OzonRepositories.Context.ApplicationDbContext,Microsoft.Extensions.Caching.Memory.IMemoryCache)
.ctor(OzonRepositories.Context.ApplicationDbContext)
GetAllAsync()
InvalidateCache()
GetAsync()
SaveAsync()
SaveAsync()
GetArmtekAsync()
SaveArmtekAsync()
GetArmtekByAsync(System.Threading.CancellationToken)
SaveArmtekByAsync(System.Nullable`1<System.Int32>,System.Boolean,System.Threading.CancellationToken)
GetShateMAsync()
SaveShateMAsync()
GetAvdAsync(System.Threading.CancellationToken)
SaveAvdAsync(System.Nullable`1<System.Int32>,System.Boolean,System.Threading.CancellationToken)
GetBergAsync(System.Threading.CancellationToken)
SaveBergAsync(System.Nullable`1<System.Int32>,System.Boolean,System.Threading.CancellationToken)
GetMotexAsync(System.Threading.CancellationToken)
SaveMotexAsync(System.Nullable`1<System.Int32>,System.Boolean,System.Threading.CancellationToken)
GetMlAutoAsync(System.Threading.CancellationToken)
SaveMlAutoAsync(System.Nullable`1<System.Int32>,System.Boolean,System.Threading.CancellationToken)
GetMlAutoRuAsync(System.Threading.CancellationToken)
SaveMlAutoRuAsync(System.Nullable`1<System.Int32>,System.Boolean,System.Threading.CancellationToken)
GetForumAutoAsync(System.Threading.CancellationToken)
SaveForumAutoAsync(System.Nullable`1<System.Int32>,System.Boolean,System.Threading.CancellationToken)
GetForumAutoInterpartsAsync(System.Threading.CancellationToken)
SaveForumAutoInterpartsAsync(System.Nullable`1<System.Int32>,System.Boolean,System.Threading.CancellationToken)
GetForumAutoPiterAsync(System.Threading.CancellationToken)
SaveForumAutoPiterAsync(System.Nullable`1<System.Int32>,System.Boolean,System.Threading.CancellationToken)
GetForumAutoRostovAsync(System.Threading.CancellationToken)
SaveForumAutoRostovAsync(System.Nullable`1<System.Int32>,System.Boolean,System.Threading.CancellationToken)
GetForumAutoIstraAsync(System.Threading.CancellationToken)
SaveForumAutoIstraAsync(System.Nullable`1<System.Int32>,System.Boolean,System.Threading.CancellationToken)
GetFavoritPartsAsync(System.Threading.CancellationToken)
SaveFavoritPartsAsync(System.Nullable`1<System.Int32>,System.Boolean,System.String,System.Threading.CancellationToken)
GetFavoritPartsIstraAsync(System.Threading.CancellationToken)
SaveFavoritPartsIstraAsync(System.Nullable`1<System.Int32>,System.Boolean,System.String,System.Threading.CancellationToken)
GetFavoritPartsRostovAsync(System.Threading.CancellationToken)
SaveFavoritPartsRostovAsync(System.Nullable`1<System.Int32>,System.Boolean,System.String,System.Threading.CancellationToken)
SaveWithDeliveryAddressAsync()
GetMoskvorechieIstraAsync(System.Threading.CancellationToken)
SaveMoskvorechieIstraAsync(System.Nullable`1<System.Int32>,System.Boolean,System.Threading.CancellationToken)
GetProfitLigaAsync(System.Threading.CancellationToken)
SaveProfitLigaAsync(System.Nullable`1<System.Int32>,System.Boolean,System.Threading.CancellationToken)
GetNikeiAsync(System.Threading.CancellationToken)
GetMikadoMskHod20Async(System.Threading.CancellationToken)
GetJapartsAsync(System.Threading.CancellationToken)
GetZZapMoscowAsync(System.Threading.CancellationToken)