< Summary

Information
Class: Services.BitrixStockServices.BitrixStockSyncReportGridService
Assembly: Services
File(s): /home/runner/work/Studio2Prod/Studio2Prod/AppRepository/BitrixStockServices/BitrixStockSyncReportGridService.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 118
Coverable lines: 118
Total lines: 199
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 80
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
GetLinesAsync()0%420200%
GetFacetsAsync()0%506220%
CreateCommand(...)0%620%
AddParam(...)0%620%
S()0%620%
I()0%620%
L()0%620%
D()0%620%
T()0%620%
B()0%620%
ReadLine(...)0%506220%

File(s)

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

#LineLine coverage
 1using System.Data.Common;
 2using Microsoft.EntityFrameworkCore;
 3using OzonRepositories.Context;
 4
 5namespace Services.BitrixStockServices;
 6
 7/// <summary>
 8/// Данные грида отчёта синхронизации (/Studio2/BitrixStock?tab=sync&amp;report=…): блоки строк с серверной
 9/// сортировкой/фильтрами и счётчики значений для справочных фильтров.
 10/// </summary>
 11public interface IBitrixStockSyncReportGridService
 12{
 13    Task<BitrixSyncGridLinesResult> GetLinesAsync(string reportId, BitrixSyncGridLinesQuery query, CancellationToken can
 14
 15    /// <summary>Значения колонки с количеством строк при текущих фильтрах (без фильтра самой колонки).</summary>
 16    Task<List<BitrixSyncGridFacetValue>> GetFacetsAsync(string reportId, string colId, BitrixSyncGridLinesQuery query, C
 17}
 18
 19public sealed class BitrixStockSyncReportGridService : IBitrixStockSyncReportGridService
 20{
 21    private const int CommandTimeoutSeconds = 60;
 22    private const int MaxFacetValues = 500;
 23
 24    private readonly IDbContextFactory<ApplicationDbContext> _dbFactory;
 25
 026    public BitrixStockSyncReportGridService(IDbContextFactory<ApplicationDbContext> dbFactory)
 27    {
 028        _dbFactory = dbFactory;
 029    }
 30
 31    public async Task<BitrixSyncGridLinesResult> GetLinesAsync(
 32        string reportId,
 33        BitrixSyncGridLinesQuery query,
 34        CancellationToken cancellationToken = default)
 35    {
 036        var result = new BitrixSyncGridLinesResult();
 037        if (string.IsNullOrWhiteSpace(reportId)) return result;
 38
 039        var start = Math.Max(0, query.StartRow);
 040        var take = Math.Clamp(query.EndRow - start, 1, BitrixStockSyncReportGridSql.MaxBlockSize);
 041        var built = BitrixStockSyncReportGridSql.Build(reportId.Trim(), query);
 42
 043        await using var db = await _dbFactory.CreateDbContextAsync(cancellationToken);
 044        await db.Database.OpenConnectionAsync(cancellationToken);
 45        try
 46        {
 047            var connection = db.Database.GetDbConnection();
 48
 049            await using (var countCmd = CreateCommand(connection, built))
 50            {
 051                countCmd.CommandText = "SELECT COUNT(*) FROM BitrixStockSyncReportLines l"
 052                                       + (built.NeedsPriceJoin ? BitrixStockSyncReportGridSql.PriceJoinSql : string.Empt
 053                                       + built.Where;
 054                result.TotalCount = Convert.ToInt32(await countCmd.ExecuteScalarAsync(cancellationToken) ?? 0);
 55            }
 56
 057            if (result.TotalCount == 0 || start >= result.TotalCount) return result;
 58
 059            await using var rowsCmd = CreateCommand(connection, built);
 060            rowsCmd.CommandText = "SELECT " + BitrixStockSyncReportGridSql.SelectColumns
 061                                  + " FROM BitrixStockSyncReportLines l" + BitrixStockSyncReportGridSql.PriceJoinSql
 062                                  + built.Where + built.OrderBy + " LIMIT @take OFFSET @skip";
 063            AddParam(rowsCmd, "@take", take);
 064            AddParam(rowsCmd, "@skip", start);
 65
 066            await using var reader = await rowsCmd.ExecuteReaderAsync(cancellationToken);
 067            while (await reader.ReadAsync(cancellationToken))
 68            {
 069                result.Rows.Add(ReadLine(reader));
 70            }
 071        }
 72        finally
 73        {
 074            await db.Database.CloseConnectionAsync();
 75        }
 76
 077        return result;
 078    }
 79
 80    public async Task<List<BitrixSyncGridFacetValue>> GetFacetsAsync(
 81        string reportId,
 82        string colId,
 83        BitrixSyncGridLinesQuery query,
 84        CancellationToken cancellationToken = default)
 85    {
 086        var result = new List<BitrixSyncGridFacetValue>();
 087        if (string.IsNullOrWhiteSpace(reportId)) return result;
 088        if (!BitrixStockSyncReportGridSql.TryGetFacetExpression(colId, out var expression, out var needsPrice)) return r
 89
 090        var built = BitrixStockSyncReportGridSql.Build(reportId.Trim(), query, excludeColId: colId);
 91
 092        await using var db = await _dbFactory.CreateDbContextAsync(cancellationToken);
 093        await db.Database.OpenConnectionAsync(cancellationToken);
 94        try
 95        {
 096            await using var cmd = CreateCommand(db.Database.GetDbConnection(), built);
 097            cmd.CommandText = "SELECT COALESCE(" + expression + ", '') AS v, COUNT(*) FROM BitrixStockSyncReportLines l"
 098                              + (needsPrice || built.NeedsPriceJoin ? BitrixStockSyncReportGridSql.PriceJoinSql : string
 099                              + built.Where + " GROUP BY v ORDER BY COUNT(*) DESC LIMIT " + MaxFacetValues;
 0100            await using var reader = await cmd.ExecuteReaderAsync(cancellationToken);
 0101            while (await reader.ReadAsync(cancellationToken))
 102            {
 0103                result.Add(new BitrixSyncGridFacetValue
 0104                {
 0105                    Value = reader.IsDBNull(0) ? string.Empty : Convert.ToString(reader.GetValue(0)) ?? string.Empty,
 0106                    Count = Convert.ToInt32(reader.GetValue(1))
 0107                });
 108            }
 0109        }
 110        finally
 111        {
 0112            await db.Database.CloseConnectionAsync();
 113        }
 114
 0115        return result;
 0116    }
 117
 118    private static DbCommand CreateCommand(DbConnection connection, BitrixStockSyncReportGridSql.Built built)
 119    {
 0120        var cmd = connection.CreateCommand();
 0121        cmd.CommandTimeout = CommandTimeoutSeconds;
 0122        foreach (var (name, value) in built.Parameters)
 123        {
 0124            AddParam(cmd, name, value);
 125        }
 126
 0127        return cmd;
 128    }
 129
 130    private static void AddParam(DbCommand cmd, string name, object? value)
 131    {
 0132        var p = cmd.CreateParameter();
 0133        p.ParameterName = name;
 0134        p.Value = value ?? DBNull.Value;
 0135        cmd.Parameters.Add(p);
 0136    }
 137
 138    private static BitrixSyncGridLineDto ReadLine(DbDataReader r)
 139    {
 0140        string? S(int i) => r.IsDBNull(i) ? null : Convert.ToString(r.GetValue(i));
 0141        int? I(int i) => r.IsDBNull(i) ? null : Convert.ToInt32(r.GetValue(i));
 0142        long? L(int i) => r.IsDBNull(i) ? null : Convert.ToInt64(r.GetValue(i));
 0143        decimal? D(int i) => r.IsDBNull(i) ? null : Convert.ToDecimal(r.GetValue(i));
 0144        DateTime? T(int i) => r.IsDBNull(i) ? null : r.GetDateTime(i);
 0145        bool B(int i) => !r.IsDBNull(i) && Convert.ToInt32(r.GetValue(i)) != 0;
 146
 0147        return new BitrixSyncGridLineDto
 0148        {
 0149            LineId = r.GetInt64(0),
 0150            ProductId = I(1) ?? 0,
 0151            Article = S(2) ?? string.Empty,
 0152            OfferId = S(3),
 0153            OneCStore = S(4) ?? string.Empty,
 0154            OzonWarehouseName = S(5) ?? string.Empty,
 0155            OzonWarehouseId = L(6) ?? 0,
 0156            MappingDescription = S(7) ?? string.Empty,
 0157            OneCQty = I(8) ?? 0,
 0158            OzonQty = I(9) ?? 0,
 0159            Delta = I(10) ?? 0,
 0160            ReservedQty = I(11) ?? 0,
 0161            OzonQtyAfter = I(12),
 0162            Action = S(13) ?? string.Empty,
 0163            ActionLabel = S(14) ?? string.Empty,
 0164            ActionIcon = S(15) ?? string.Empty,
 0165            RowClass = S(16) ?? string.Empty,
 0166            Note = S(17),
 0167            OzonProductId = L(18),
 0168            OzonApplyStatus = S(19),
 0169            OzonAppliedUtc = T(20),
 0170            OzonApplyError = S(21),
 0171            OzonCleanupStatus = S(22),
 0172            OzonCleanupAtUtc = T(23),
 0173            OzonCleanupError = S(24),
 0174            OzonClientId = I(25) ?? 0,
 0175            OzonClientName = S(26) ?? string.Empty,
 0176            OneCPrice = D(27),
 0177            PrevOneCPrice = D(28),
 0178            IsArchived = B(29),
 0179            IsAutoArchived = B(30),
 0180            PromoName = S(31),
 0181            IsOzonOrphan = B(32),
 0182            OzonOrphanStatus = S(33),
 0183            BatchMultiplier = I(34) ?? 1,
 0184            BatchBaseArticle = S(35),
 0185            BatchPushedPrice = D(36),
 0186            ManufacturerName = S(37),
 0187            DeltaC0 = S(38) ?? "none",
 0188            TargetQty = I(39),
 0189            InPromo = S(40) == "yes",
 0190            TruePrice = D(41),
 0191            SellingPrice = D(42),
 0192            ColorIndex = S(43) ?? "NONE",
 0193            PricePushedOld = D(44),
 0194            PricePushedNew = D(45),
 0195            PricePushStatus = S(46),
 0196            PricePushError = S(47)
 0197        };
 198    }
 199}