< Summary

Information
Class: Services.BitrixStockServices.OzonProductsCatalogService
Assembly: Services
File(s): /home/runner/work/Studio2Prod/Studio2Prod/AppRepository/BitrixStockServices/OzonProductsCatalogService.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 136
Coverable lines: 136
Total lines: 234
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 46
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/AppRepository/BitrixStockServices/OzonProductsCatalogService.cs

#LineLine coverage
 1using Microsoft.EntityFrameworkCore;
 2using OzonDomains.Models.OzonApi;
 3using OzonRepositories.Context;
 4
 5namespace Services.BitrixStockServices;
 6
 7public class OzonProductsCatalogService : IOzonProductsCatalogService
 8{
 9    private const int PageSize = 1000;
 10
 11    private readonly IDbContextFactory<OzonApiContext> _dbFactory;
 12
 013    public OzonProductsCatalogService(IDbContextFactory<OzonApiContext> dbFactory)
 14    {
 015        _dbFactory = dbFactory;
 016    }
 17
 18    public async IAsyncEnumerable<OzonProductCatalogRow> StreamByAccountAsync(
 19        string accountId,
 20        OzonProductsCatalogFilter filter,
 21        [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken = default)
 22    {
 023        await foreach (var row in StreamInternalAsync(accountId, filter, cancellationToken))
 024            yield return row;
 025    }
 26
 27    public async IAsyncEnumerable<OzonProductCatalogRow> StreamNonBatchByAccountAsync(
 28        string accountId,
 29        OzonProductsCatalogFilter filter,
 30        [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken = default)
 31    {
 032        var nonBatchFilter = new OzonProductsCatalogFilter
 033        {
 034            Visibility = filter.Visibility,
 035            IncludeArchived = filter.IncludeArchived,
 036            ExcludeBatchVariants = true
 037        };
 038        await foreach (var row in StreamInternalAsync(accountId, nonBatchFilter, cancellationToken))
 039            yield return row;
 040    }
 41
 42    private async IAsyncEnumerable<OzonProductCatalogRow> StreamInternalAsync(
 43        string accountId,
 44        OzonProductsCatalogFilter filter,
 45        [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken = default)
 46    {
 047        if (string.IsNullOrWhiteSpace(accountId))
 048            yield break;
 49
 050        var normalizedAccountId = accountId.Trim();
 051        uint lastId = 0;
 52
 053        while (true)
 54        {
 055            cancellationToken.ThrowIfCancellationRequested();
 056            await using var db = await _dbFactory.CreateDbContextAsync(cancellationToken);
 57
 058            var page = await BuildQuery(db, normalizedAccountId, filter)
 059                .Where(p => p.Id > lastId)
 060                .OrderBy(p => p.Id)
 061                .Take(PageSize)
 062                .ToListAsync(cancellationToken);
 63
 064            if (page.Count == 0)
 065                yield break;
 66
 067            foreach (var product in page)
 068                yield return MapToRow(product);
 69
 070            lastId = page[^1].Id;
 071            if (page.Count < PageSize)
 072                yield break;
 073        }
 074    }
 75
 76    public async Task<IReadOnlyList<OzonProductCatalogRow>> GetBatchVariantsAsync(
 77        string accountId,
 78        OzonProductsCatalogFilter filter,
 79        CancellationToken cancellationToken = default)
 80    {
 081        if (string.IsNullOrWhiteSpace(accountId))
 082            return Array.Empty<OzonProductCatalogRow>();
 83
 084        await using var db = await _dbFactory.CreateDbContextAsync(cancellationToken);
 085        var rows = await BuildQuery(db, accountId.Trim(), filter)
 086            .Where(p => EF.Functions.Like(p.OfferId, "%[%]%"))
 087            .ToListAsync(cancellationToken);
 88
 089        return rows
 090            .Select(MapToRow)
 091            .Where(r => BitrixStockOrphanOfferMatching.ExtractBatchMultiplier(r.OfferId) > 1)
 092            .ToList();
 093    }
 94
 95    public async Task<IReadOnlyList<OzonProductCatalogRow>> GetBracketedNonBatchVariantsAsync(
 96        string accountId,
 97        OzonProductsCatalogFilter filter,
 98        CancellationToken cancellationToken = default)
 99    {
 0100        if (string.IsNullOrWhiteSpace(accountId))
 0101            return Array.Empty<OzonProductCatalogRow>();
 102
 0103        await using var db = await _dbFactory.CreateDbContextAsync(cancellationToken);
 0104        var rows = await BuildQuery(db, accountId.Trim(), filter)
 0105            .Where(p => EF.Functions.Like(p.OfferId, "%[%]%"))
 0106            .ToListAsync(cancellationToken);
 107
 0108        return rows
 0109            .Select(MapToRow)
 0110            .Where(r => BitrixStockOrphanOfferMatching.ExtractBatchMultiplier(r.OfferId) <= 1)
 0111            .ToList();
 0112    }
 113
 114    public async Task<IReadOnlyDictionary<string, OzonProductCatalogRow>> GetByOfferIdsAsync(
 115        string accountId,
 116        IReadOnlyCollection<string> offerIds,
 117        CancellationToken cancellationToken = default)
 118    {
 0119        if (string.IsNullOrWhiteSpace(accountId) || offerIds.Count == 0)
 0120            return new Dictionary<string, OzonProductCatalogRow>(StringComparer.OrdinalIgnoreCase);
 121
 0122        var normalized = offerIds
 0123            .Where(id => !string.IsNullOrWhiteSpace(id))
 0124            .Select(id => id.Trim())
 0125            .Distinct(StringComparer.OrdinalIgnoreCase)
 0126            .ToList();
 127
 0128        if (normalized.Count == 0)
 0129            return new Dictionary<string, OzonProductCatalogRow>(StringComparer.OrdinalIgnoreCase);
 130
 0131        await using var db = await _dbFactory.CreateDbContextAsync(cancellationToken);
 0132        var rows = await db.OzonProducts
 0133            .AsNoTracking()
 0134            .Where(p => p.AccountId == accountId.Trim() && normalized.Contains(p.OfferId))
 0135            .ToListAsync(cancellationToken);
 136
 0137        return rows
 0138            .Select(MapToRow)
 0139            .ToDictionary(r => r.OfferId, StringComparer.OrdinalIgnoreCase);
 0140    }
 141
 142    public async Task<int> CountByAccountAsync(
 143        string accountId,
 144        OzonProductsCatalogFilter filter,
 145        CancellationToken cancellationToken = default)
 146    {
 0147        var meta = await GetCatalogMetaAsync(accountId, filter, cancellationToken);
 0148        return meta.TotalCount;
 0149    }
 150
 151    public async Task<int> CountNonBatchByAccountAsync(
 152        string accountId,
 153        OzonProductsCatalogFilter filter,
 154        CancellationToken cancellationToken = default)
 155    {
 0156        if (string.IsNullOrWhiteSpace(accountId))
 0157            return 0;
 158
 0159        var nonBatchFilter = new OzonProductsCatalogFilter
 0160        {
 0161            Visibility = filter.Visibility,
 0162            IncludeArchived = filter.IncludeArchived,
 0163            ExcludeBatchVariants = true
 0164        };
 0165        await using var db = await _dbFactory.CreateDbContextAsync(cancellationToken);
 0166        return await BuildQuery(db, accountId.Trim(), nonBatchFilter).CountAsync(cancellationToken);
 0167    }
 168
 169    public async Task<OzonProductsCatalogMeta> GetCatalogMetaAsync(
 170        string accountId,
 171        OzonProductsCatalogFilter filter,
 172        CancellationToken cancellationToken = default)
 173    {
 0174        if (string.IsNullOrWhiteSpace(accountId))
 0175            return new OzonProductsCatalogMeta();
 176
 0177        await using var db = await _dbFactory.CreateDbContextAsync(cancellationToken);
 0178        var query = BuildQuery(db, accountId.Trim(), filter);
 0179        var total = await query.CountAsync(cancellationToken);
 0180        if (total == 0)
 0181            return new OzonProductsCatalogMeta { TotalCount = 0 };
 182
 0183        var maxUpdated = await query.MaxAsync(p => p.UpdatedAt, cancellationToken);
 0184        var accountName = await query
 0185            .Where(p => p.AccountName != null && p.AccountName != "")
 0186            .Select(p => p.AccountName)
 0187            .FirstOrDefaultAsync(cancellationToken);
 188
 0189        return new OzonProductsCatalogMeta
 0190        {
 0191            TotalCount = total,
 0192            MaxUpdatedAtUtc = maxUpdated,
 0193            AccountName = accountName
 0194        };
 0195    }
 196
 197    private static IQueryable<OzonProduct> BuildQuery(
 198        OzonApiContext db,
 199        string accountId,
 200        OzonProductsCatalogFilter filter)
 201    {
 0202        var query = db.OzonProducts.AsNoTracking().Where(p => p.AccountId == accountId);
 203
 0204        if (!filter.IncludeArchived && !string.IsNullOrWhiteSpace(filter.Visibility))
 0205            query = query.Where(p => p.Visibility == filter.Visibility);
 206
 0207        if (filter.ExcludeBatchVariants)
 0208            query = query.Where(p => !EF.Functions.Like(p.OfferId, "%[%]%"));
 209
 0210        return query;
 211    }
 212
 0213    private static OzonProductCatalogRow MapToRow(OzonProduct p) => new()
 0214    {
 0215        OfferId = p.OfferId,
 0216        ProductId = p.ProductId,
 0217        AccountName = p.AccountName,
 0218        Name = p.Name,
 0219        Price = p.Price,
 0220        OldPrice = p.OldPrice,
 0221        MarketingPrice = p.MarketingPrice,
 0222        MinOzonPrice = p.MinOzonPrice,
 0223        CommFbs = p.CommFbs,
 0224        CommFbo = p.CommFbo,
 0225        Acquiring = p.Acquiring,
 0226        FbsDeliv = p.FbsDeliv,
 0227        FbsDirectMin = p.FbsDirectMin,
 0228        FbsDirectMax = p.FbsDirectMax,
 0229        FbsMileMin = p.FbsMileMin,
 0230        FbsMileMax = p.FbsMileMax,
 0231        Visibility = p.Visibility,
 0232        UpdatedAt = p.UpdatedAt
 0233    };
 234}