< Summary

Information
Class: Services.StockSyncServices.WarehouseStockLookupService
Assembly: Services
File(s): /home/runner/work/Studio2Prod/Studio2Prod/AppRepository/StockSyncServices/WarehouseStockLookupService.cs
Line coverage
100%
Covered lines: 86
Uncovered lines: 0
Coverable lines: 86
Total lines: 145
Line coverage: 100%
Branch coverage
91%
Covered branches: 31
Total branches: 34
Branch coverage: 91.1%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
LookupAsync()75%44100%
LoadCandidatesByArticlesAsync()100%66100%
BuildC0MapAsync()100%88100%
ApplyOriginalPurchasePricesAsync()100%44100%
ResolveC0(...)83.33%1212100%
ToLookupResult(...)100%11100%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/AppRepository/StockSyncServices/WarehouseStockLookupService.cs

#LineLine coverage
 1using Microsoft.EntityFrameworkCore;
 2using OzonDomains.Models;
 3using OzonRepositories.Context;
 4
 5namespace Services.StockSyncServices;
 6
 7public class WarehouseStockLookupService : IWarehouseStockLookupService
 8{
 9    private readonly ApplicationDbContext _context;
 10
 1411    public WarehouseStockLookupService(ApplicationDbContext context)
 12    {
 1413        _context = context;
 1414    }
 15
 16    public async Task<WarehouseStockLookupResult?> LookupAsync(
 17        string article,
 18        string? manufacturer,
 19        CancellationToken cancellationToken = default)
 20    {
 521        if (string.IsNullOrWhiteSpace(article))
 322            return null;
 23
 224        var candidates = await LoadCandidatesByArticlesAsync(new[] { article.Trim() }, cancellationToken);
 225        var match = WarehouseStockLookupMatcher.FindMatch(
 226            candidates,
 227            WarehouseStockLookupMatcher.Normalize(article),
 228            WarehouseStockLookupMatcher.Normalize(manufacturer),
 429            x => x.Article,
 430            x => x.Manufacturer);
 31
 232        return match == null ? null : ToLookupResult(match.Item, !match.ManufacturerMatched);
 533    }
 34
 35    public async Task<IReadOnlyList<WarehouseStockSnapshotCandidate>> LoadCandidatesByArticlesAsync(
 36        IEnumerable<string> articles,
 37        CancellationToken cancellationToken = default)
 38    {
 1039        var distinctArticles = articles
 1340            .Where(a => !string.IsNullOrWhiteSpace(a))
 1141            .Select(a => a.Trim())
 1042            .Distinct(StringComparer.OrdinalIgnoreCase)
 1043            .ToList();
 44
 1045        if (distinctArticles.Count == 0)
 146            return Array.Empty<WarehouseStockSnapshotCandidate>();
 47
 948        var merged = new Dictionary<string, WarehouseStockSnapshotCandidate>(StringComparer.OrdinalIgnoreCase);
 49
 3850        foreach (var article in distinctArticles)
 51        {
 1052            var rows = await _context.WarehouseStockSnapshots
 1053                .AsNoTracking()
 1054                .Where(x => x.Article != null && x.Article.Contains(article))
 1055                .Select(x => new WarehouseStockSnapshotCandidate
 1056                {
 1057                    Id = x.Id,
 1058                    SourceRowNumber = x.SourceRowNumber,
 1059                    Article = x.Article,
 1060                    Manufacturer = x.Manufacturer,
 1061                    M2Qty = x.M2Qty,
 1062                    M1Qty = x.M1Qty,
 1063                    M3Qty = x.M3Qty,
 1064                    B1Qty = x.B1Qty,
 1065                    B2Qty = x.B2Qty,
 1066                    C0 = x.C0
 1067                })
 1068                .ToListAsync(cancellationToken);
 69
 4070            foreach (var row in rows)
 71            {
 1072                var key = $"{row.Article}|{row.Manufacturer}|{row.Id}";
 1073                merged.TryAdd(key, row);
 74            }
 75        }
 76
 977        return merged.Values.ToList();
 1078    }
 79
 80    public async Task<Dictionary<int, decimal>> BuildC0MapAsync(
 81        IEnumerable<Order> orders,
 82        CancellationToken cancellationToken = default)
 83    {
 584        var orderList = orders
 585            .Where(o => !string.IsNullOrWhiteSpace(o.Article))
 586            .ToList();
 87
 588        if (orderList.Count == 0)
 189            return new Dictionary<int, decimal>();
 90
 491        var candidates = await LoadCandidatesByArticlesAsync(
 492            orderList.Select(o => o.Article!),
 493            cancellationToken);
 94
 495        var result = new Dictionary<int, decimal>();
 1696        foreach (var order in orderList)
 97        {
 498            var c0 = ResolveC0(order, candidates);
 499            if (c0 is > 0)
 3100                result[order.Id] = c0.Value;
 101        }
 102
 4103        return result;
 5104    }
 105
 106    public async Task ApplyOriginalPurchasePricesAsync(
 107        IEnumerable<Order> orders,
 108        CancellationToken cancellationToken = default)
 109    {
 1110        var map = await BuildC0MapAsync(orders, cancellationToken);
 4111        foreach (var order in orders)
 112        {
 1113            if (map.TryGetValue(order.Id, out var c0))
 1114                order.OriginalPurchasePrice = c0;
 115        }
 1116    }
 117
 118    private static decimal? ResolveC0(Order order, IReadOnlyList<WarehouseStockSnapshotCandidate> candidates)
 119    {
 4120        var manufacturerName = order.EtProducer?.Name ?? order.Manufacturer?.Name;
 4121        var match = WarehouseStockLookupMatcher.FindMatch(
 4122            candidates,
 4123            WarehouseStockLookupMatcher.Normalize(order.Article),
 4124            WarehouseStockLookupMatcher.Normalize(manufacturerName),
 8125            x => x.Article,
 8126            x => x.Manufacturer);
 127
 4128        return match?.Item.C0 is > 0 ? match.Item.C0 : null;
 129    }
 130
 131    private static WarehouseStockLookupResult ToLookupResult(WarehouseStockSnapshotCandidate match, bool fuzzyManufactur
 2132        new()
 2133        {
 2134            Found = true,
 2135            FuzzyManufacturer = fuzzyManufacturer,
 2136            Id = match.Id,
 2137            SourceRowNumber = match.SourceRowNumber,
 2138            M2Qty = match.M2Qty,
 2139            M1Qty = match.M1Qty,
 2140            M3Qty = match.M3Qty,
 2141            B1Qty = match.B1Qty,
 2142            B2Qty = match.B2Qty,
 2143            C0 = match.C0
 2144        };
 145}