< Summary

Information
Class: Services.ApiServices.InterpartsPriceApi.InterpartsCurrencyRateService
Assembly: Services
File(s): /home/runner/work/Studio2Prod/Studio2Prod/AppRepository/ApiServices/InterpartsPriceApi/InterpartsCurrencyRateService.cs
Line coverage
36%
Covered lines: 12
Uncovered lines: 21
Coverable lines: 33
Total lines: 82
Line coverage: 36.3%
Branch coverage
60%
Covered branches: 6
Total branches: 10
Branch coverage: 60%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%210%
.ctor(...)100%11100%
GetRatesToRubAsync()100%210%
GetDirectoryAsync()0%2040%
InvalidateRatesCache()100%210%
GetRateToRub(...)100%66100%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/AppRepository/ApiServices/InterpartsPriceApi/InterpartsCurrencyRateService.cs

#LineLine coverage
 1using Microsoft.EntityFrameworkCore;
 2using Microsoft.Extensions.Caching.Memory;
 3using OzonRepositories.Context;
 4
 5namespace Services.ApiServices.InterpartsPriceApi;
 6
 7/// <summary>Справочник валют Interparts: курс к рублю и отображаемое имя по id.</summary>
 8/// <param name="Rates">id валюты → курс к рублю.</param>
 9/// <param name="Names">id валюты → название из справочника.</param>
 10public sealed record InterpartsCurrencyDirectory(
 11    IReadOnlyDictionary<int, decimal> Rates,
 12    IReadOnlyDictionary<int, string> Names);
 13
 14/// <summary>
 15/// Курсы валют из таблицы InterpartsSutCurrencies (основная MySQL БД) для перевода цен Interparts в рубли.
 16/// </summary>
 17public sealed class InterpartsCurrencyRateService
 18{
 19    private const string CacheKey = "Interparts_SutCurrency_Directory_v3_mysql";
 020    private static readonly TimeSpan CacheTtl = TimeSpan.FromMinutes(10);
 21
 22    private readonly ApplicationDbContext _db;
 23    private readonly IMemoryCache _cache;
 24
 525    public InterpartsCurrencyRateService(ApplicationDbContext db, IMemoryCache cache)
 26    {
 527        _db = db;
 528        _cache = cache;
 529    }
 30
 31    public async Task<IReadOnlyDictionary<int, decimal>> GetRatesToRubAsync(CancellationToken cancellationToken = defaul
 32    {
 033        var directory = await GetDirectoryAsync(cancellationToken).ConfigureAwait(false);
 034        return directory.Rates;
 035    }
 36
 37    /// <summary>Курсы вместе с названиями валют — для подсказки «цена × курс» в проценке.</summary>
 38    public async Task<InterpartsCurrencyDirectory> GetDirectoryAsync(CancellationToken cancellationToken = default)
 39    {
 040        if (_cache.TryGetValue(CacheKey, out InterpartsCurrencyDirectory? cached) && cached != null)
 041            return cached;
 42
 043        var rows = await _db.InterpartsSutCurrencies
 044            .AsNoTracking()
 045            .Select(c => new { c.Id, c.Name, c.RateToRub })
 046            .ToListAsync(cancellationToken)
 047            .ConfigureAwait(false);
 48
 049        var directory = new InterpartsCurrencyDirectory(
 050            rows.ToDictionary(x => x.Id, x => x.RateToRub),
 051            rows.ToDictionary(x => x.Id, x => x.Name));
 52
 053        _cache.Set(CacheKey, directory, new MemoryCacheEntryOptions
 054        {
 055            AbsoluteExpirationRelativeToNow = CacheTtl
 056        });
 57
 058        return directory;
 059    }
 60
 61    /// <summary>Сбрасывает кэш после ручного изменения курсов в админке.</summary>
 062    public void InvalidateRatesCache() => _cache.Remove(CacheKey);
 63
 64    /// <summary>
 65    /// Курс для SupplierCurrencyId; при отсутствии id или записи — 1 и <paramref name="usedFallback"/> = true.
 66    /// </summary>
 67    public static decimal GetRateToRub(int? supplierCurrencyId, IReadOnlyDictionary<int, decimal> rates, out bool usedFa
 68    {
 4469        usedFallback = false;
 4470        if (!supplierCurrencyId.HasValue || supplierCurrencyId.Value <= 0)
 71        {
 372            usedFallback = true;
 373            return 1m;
 74        }
 75
 4176        if (rates.TryGetValue(supplierCurrencyId.Value, out var rate))
 1377            return rate;
 78
 2879        usedFallback = true;
 2880        return 1m;
 81    }
 82}