< Summary

Information
Class: Services.BitrixStockServices.BitrixStockSyncApplyArticleLogService
Assembly: Services
File(s): /home/runner/work/Studio2Prod/Studio2Prod/AppRepository/BitrixStockServices/BitrixStockSyncApplyArticleLogService.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 169
Coverable lines: 169
Total lines: 237
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 118
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%
WriteAsync()0%2040%
GetPageAsync()0%3906620%
GetJobIdsAsync()0%156120%
GetAnalysisAsync()0%1482380%
AddParam(...)0%620%

File(s)

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

#LineLine coverage
 1using Microsoft.EntityFrameworkCore;
 2using OzonRepositories.Context;
 3
 4namespace Services.BitrixStockServices;
 5
 06public class BitrixStockSyncApplyArticleLogService(IDbContextFactory<ApplicationDbContext> dbFactory)
 7{
 8    public async Task WriteAsync(
 9        ApplicationDbContext db,
 10        string reportId,
 11        string jobId,
 12        BitrixStockSyncApplyArticleLogEntry entry,
 13        CancellationToken ct = default)
 14    {
 015        var c1 = entry.Client1;
 016        var c2 = entry.Client2;
 017        await db.Database.ExecuteSqlRawAsync(@"
 018INSERT INTO BitrixStockSyncApplyArticleLog
 019(ReportId,JobId,AppliedAtUtc,Article,OneCStore,OneCQty,
 020 Client1Id,Client1Name,Client1QtyBefore,Client1QtyAfter,Client1WasArchived,Client1ActionCode,Client1ActionLabel,
 021 Client2Id,Client2Name,Client2QtyBefore,Client2QtyAfter,Client2WasArchived,Client2ActionCode,Client2ActionLabel,
 022 Summary)
 023VALUES ({0},{1},UTC_TIMESTAMP(6),{2},{3},{4},
 024{5},{6},{7},{8},{9},{10},{11},
 025{12},{13},{14},{15},{16},{17},{18},
 026{19});",
 027            EfSqlRawParameterGuard.Materialize(
 028                reportId, jobId,
 029                entry.Article, entry.OneCStore, entry.OneCQty,
 030                c1.ClientId, c1.ClientName, c1.QtyBefore, c1.QtyAfter,
 031                c1.WasArchived.HasValue ? (c1.WasArchived.Value ? 1 : 0) : (object?)DBNull.Value,
 032                c1.ActionCode, c1.ActionLabel,
 033                c2.ClientId, c2.ClientName, c2.QtyBefore, c2.QtyAfter,
 034                c2.WasArchived.HasValue ? (c2.WasArchived.Value ? 1 : 0) : (object?)DBNull.Value,
 035                c2.ActionCode, c2.ActionLabel,
 036                entry.Summary), ct);
 037    }
 38
 39    public async Task<BitrixStockSyncApplyArticleLogPageDto> GetPageAsync(
 40        string reportId,
 41        string? jobId = null,
 42        string? article = null,
 43        int page = 1,
 44        int pageSize = 50,
 45        CancellationToken ct = default)
 46    {
 047        await using var db = await dbFactory.CreateDbContextAsync(ct);
 48
 049        var where = " WHERE ReportId = @rid";
 050        if (!string.IsNullOrWhiteSpace(jobId))    where += " AND JobId = @jid";
 051        if (!string.IsNullOrWhiteSpace(article))  where += " AND Article LIKE CONCAT('%',@art,'%')";
 52
 053        page     = Math.Max(1, page);
 054        pageSize = Math.Clamp(pageSize, 10, 200);
 55
 056        var conn = db.Database.GetDbConnection();
 057        var wasOpen = conn.State == System.Data.ConnectionState.Open;
 058        if (!wasOpen) await conn.OpenAsync(ct);
 59        try
 60        {
 61            // count
 062            using var cntCmd = conn.CreateCommand();
 063            cntCmd.CommandText = "SELECT COUNT(*) FROM BitrixStockSyncApplyArticleLog" + where;
 064            AddParam(cntCmd, "@rid", reportId);
 065            if (!string.IsNullOrWhiteSpace(jobId))   AddParam(cntCmd, "@jid", jobId);
 066            if (!string.IsNullOrWhiteSpace(article)) AddParam(cntCmd, "@art", article);
 067            var total = Convert.ToInt32(await cntCmd.ExecuteScalarAsync(ct) ?? 0);
 068            var totalPages = total == 0 ? 1 : (int)Math.Ceiling(total / (double)pageSize);
 069            if (page > totalPages) page = totalPages;
 70
 71            // rows
 072            using var rowCmd = conn.CreateCommand();
 073            rowCmd.CommandText = @"SELECT
 074Id,ReportId,JobId,AppliedAtUtc,Article,OneCStore,OneCQty,
 075Client1Id,Client1Name,Client1QtyBefore,Client1QtyAfter,Client1WasArchived,Client1ActionCode,Client1ActionLabel,
 076Client2Id,Client2Name,Client2QtyBefore,Client2QtyAfter,Client2WasArchived,Client2ActionCode,Client2ActionLabel,
 077Summary
 078FROM BitrixStockSyncApplyArticleLog" + where + " ORDER BY Article, OneCStore LIMIT @take OFFSET @skip;";
 079            AddParam(rowCmd, "@rid", reportId);
 080            if (!string.IsNullOrWhiteSpace(jobId))   AddParam(rowCmd, "@jid", jobId);
 081            if (!string.IsNullOrWhiteSpace(article)) AddParam(rowCmd, "@art", article);
 082            AddParam(rowCmd, "@take", pageSize);
 083            AddParam(rowCmd, "@skip", (page - 1) * pageSize);
 84
 085            var items = new List<BitrixStockSyncApplyArticleLogEntry>();
 086            await using var r = await rowCmd.ExecuteReaderAsync(ct);
 087            while (await r.ReadAsync(ct))
 88            {
 089                items.Add(new BitrixStockSyncApplyArticleLogEntry
 090                {
 091                    Id           = r.GetInt64(0),
 092                    ReportId     = r.GetString(1),
 093                    JobId        = r.GetString(2),
 094                    AppliedAtUtc = r.GetDateTime(3),
 095                    Article      = r.GetString(4),
 096                    OneCStore    = r.GetString(5),
 097                    OneCQty      = r.GetInt32(6),
 098                    Client1 = new ApplyArticleClientEntry
 099                    {
 0100                        ClientId      = r.IsDBNull(7)  ? null : r.GetInt32(7),
 0101                        ClientName    = r.IsDBNull(8)  ? null : r.GetString(8),
 0102                        QtyBefore     = r.IsDBNull(9)  ? null : r.GetInt32(9),
 0103                        QtyAfter      = r.IsDBNull(10) ? null : r.GetInt32(10),
 0104                        WasArchived   = r.IsDBNull(11) ? null : r.GetInt32(11) != 0,
 0105                        ActionCode    = r.IsDBNull(12) ? null : r.GetString(12),
 0106                        ActionLabel   = r.IsDBNull(13) ? null : r.GetString(13)
 0107                    },
 0108                    Client2 = new ApplyArticleClientEntry
 0109                    {
 0110                        ClientId      = r.IsDBNull(14) ? null : r.GetInt32(14),
 0111                        ClientName    = r.IsDBNull(15) ? null : r.GetString(15),
 0112                        QtyBefore     = r.IsDBNull(16) ? null : r.GetInt32(16),
 0113                        QtyAfter      = r.IsDBNull(17) ? null : r.GetInt32(17),
 0114                        WasArchived   = r.IsDBNull(18) ? null : r.GetInt32(18) != 0,
 0115                        ActionCode    = r.IsDBNull(19) ? null : r.GetString(19),
 0116                        ActionLabel   = r.IsDBNull(20) ? null : r.GetString(20)
 0117                    },
 0118                    Summary = r.IsDBNull(21) ? null : r.GetString(21)
 0119                });
 120            }
 121
 0122            return new BitrixStockSyncApplyArticleLogPageDto
 0123            {
 0124                Items = items, TotalCount = total,
 0125                Page = page, PageSize = pageSize, TotalPages = totalPages
 0126            };
 0127        }
 0128        finally { if (!wasOpen) await conn.CloseAsync(); }
 0129    }
 130
 131    /// <summary>Получить список уникальных JobId для отчёта (для выбора прогона).</summary>
 132    public async Task<List<(string JobId, DateTime AppliedAt)>> GetJobIdsAsync(
 133        string reportId, CancellationToken ct = default)
 134    {
 0135        await using var db = await dbFactory.CreateDbContextAsync(ct);
 0136        var conn = db.Database.GetDbConnection();
 0137        var wasOpen = conn.State == System.Data.ConnectionState.Open;
 0138        if (!wasOpen) await conn.OpenAsync(ct);
 139        try
 140        {
 0141            using var cmd = conn.CreateCommand();
 0142            cmd.CommandText = "SELECT JobId, MIN(AppliedAtUtc) FROM BitrixStockSyncApplyArticleLog WHERE ReportId=@rid G
 0143            AddParam(cmd, "@rid", reportId);
 0144            var result = new List<(string, DateTime)>();
 0145            await using var r = await cmd.ExecuteReaderAsync(ct);
 0146            while (await r.ReadAsync(ct))
 0147                result.Add((r.GetString(0), r.GetDateTime(1)));
 0148            return result;
 0149        }
 0150        finally { if (!wasOpen) await conn.CloseAsync(); }
 0151    }
 152
 153    public async Task<BitrixStockSyncApplyLogAnalysisDto> GetAnalysisAsync(
 154        string reportId,
 155        string? jobId = null,
 156        string? article = null,
 157        CancellationToken ct = default)
 158    {
 0159        await using var db = await dbFactory.CreateDbContextAsync(ct);
 160
 0161        var where = " WHERE ReportId = @rid";
 0162        if (!string.IsNullOrWhiteSpace(jobId)) where += " AND JobId = @jid";
 0163        if (!string.IsNullOrWhiteSpace(article)) where += " AND Article LIKE CONCAT('%',@art,'%')";
 164
 0165        var conn = db.Database.GetDbConnection();
 0166        var wasOpen = conn.State == System.Data.ConnectionState.Open;
 0167        if (!wasOpen) await conn.OpenAsync(ct);
 168        try
 169        {
 0170            using var cmd = conn.CreateCommand();
 0171            cmd.CommandText = @"SELECT
 0172Article, OneCStore, OneCQty,
 0173Client1Id, Client1Name, Client1QtyBefore, Client1QtyAfter, Client1WasArchived, Client1ActionCode, Client1ActionLabel
 0174FROM BitrixStockSyncApplyArticleLog" + where + " ORDER BY Article, OneCStore, AppliedAtUtc, Id;";
 0175            AddParam(cmd, "@rid", reportId);
 0176            if (!string.IsNullOrWhiteSpace(jobId)) AddParam(cmd, "@jid", jobId);
 0177            if (!string.IsNullOrWhiteSpace(article)) AddParam(cmd, "@art", article);
 178
 0179            var items = new List<BitrixStockSyncApplyLogAnalysisItemDto>();
 0180            var index = new Dictionary<string, BitrixStockSyncApplyLogAnalysisItemDto>(StringComparer.OrdinalIgnoreCase)
 0181            var clientTotals = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
 182
 0183            await using var r = await cmd.ExecuteReaderAsync(ct);
 0184            while (await r.ReadAsync(ct))
 185            {
 0186                var itemKey = $"{r.GetString(0)}||{r.GetString(1)}";
 0187                if (!index.TryGetValue(itemKey, out var item))
 188                {
 0189                    item = new BitrixStockSyncApplyLogAnalysisItemDto
 0190                    {
 0191                        Article = r.GetString(0),
 0192                        OneCStore = r.GetString(1),
 0193                        OneCQty = r.GetInt32(2)
 0194                    };
 0195                    index[itemKey] = item;
 0196                    items.Add(item);
 197                }
 198
 0199                var clientName = r.IsDBNull(4) ? "—" : r.GetString(4);
 0200                var entry = new ApplyArticleClientEntry
 0201                {
 0202                    ClientId = r.IsDBNull(3) ? null : r.GetInt32(3),
 0203                    ClientName = clientName,
 0204                    QtyBefore = r.IsDBNull(5) ? null : r.GetInt32(5),
 0205                    QtyAfter = r.IsDBNull(6) ? null : r.GetInt32(6),
 0206                    WasArchived = r.IsDBNull(7) ? null : r.GetInt32(7) != 0,
 0207                    ActionCode = r.IsDBNull(8) ? null : r.GetString(8),
 0208                    ActionLabel = r.IsDBNull(9) ? null : r.GetString(9)
 0209                };
 0210                item.Clients.Add(entry);
 211
 0212                if (!clientTotals.ContainsKey(clientName))
 0213                    clientTotals[clientName] = 0;
 0214                clientTotals[clientName]++;
 215            }
 216
 0217            return new BitrixStockSyncApplyLogAnalysisDto
 0218            {
 0219                TotalRows = items.Count,
 0220                ClientTotals = clientTotals,
 0221                Items = items
 0222            };
 0223        }
 224        finally
 225        {
 0226            if (!wasOpen) await conn.CloseAsync();
 227        }
 0228    }
 229
 230    private static void AddParam(System.Data.Common.DbCommand cmd, string name, object? value)
 231    {
 0232        var p = cmd.CreateParameter();
 0233        p.ParameterName = name;
 0234        p.Value = value ?? DBNull.Value;
 0235        cmd.Parameters.Add(p);
 0236    }
 237}