< Summary

Information
Class: Services.ApiServices.OzonApi.AssemblyListRunRepository
Assembly: Services
File(s): /home/runner/work/Studio2Prod/Studio2Prod/AppRepository/ApiServices/OzonApi/AssemblyListRunRepository.cs
Line coverage
19%
Covered lines: 24
Uncovered lines: 101
Coverable lines: 125
Total lines: 197
Line coverage: 19.2%
Branch coverage
29%
Covered branches: 10
Total branches: 34
Branch coverage: 29.4%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
CreateRunAsync()100%210%
CompleteRunAsync()100%210%
SaveItemsAsync()0%620%
GetOrderInfoByPostingNumbersAsync()0%506220%
GetZasylValuesByShipmentNumbersAsync()100%1010100%
GetRecentRunsAsync()100%210%
GetLastCompletedRunAsync()100%210%
GetRunAsync()100%210%
GetRunItemsAsync()100%210%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/AppRepository/ApiServices/OzonApi/AssemblyListRunRepository.cs

#LineLine coverage
 1using Microsoft.EntityFrameworkCore;
 2using OzonDomains.Models;
 3using OzonRepositories.Context;
 4
 5namespace Services.ApiServices.OzonApi;
 6
 7public class AssemblyListRunRepository
 8{
 9    private readonly ApplicationDbContext _db;
 10
 411    public AssemblyListRunRepository(ApplicationDbContext db)
 12    {
 413        _db = db;
 414    }
 15
 16    public async Task<long> CreateRunAsync(AssemblyListRun run)
 17    {
 018        _db.AssemblyListRuns.Add(run);
 019        await _db.SaveChangesAsync();
 020        return run.Id;
 021    }
 22
 23    public async Task CompleteRunAsync(long runId, string status, int totalPostings, int totalItems, string? errorMessag
 24    {
 025        await _db.AssemblyListRuns
 026            .Where(r => r.Id == runId)
 027            .ExecuteUpdateAsync(s => s
 028                .SetProperty(r => r.CompletedAtUtc, DateTime.UtcNow)
 029                .SetProperty(r => r.RunStatus, status)
 030                .SetProperty(r => r.TotalPostings, totalPostings)
 031                .SetProperty(r => r.TotalItems, totalItems)
 032                .SetProperty(r => r.ErrorMessage, errorMessage));
 033    }
 34
 35    public async Task SaveItemsAsync(long runId, List<AssemblyListItem> items)
 36    {
 037        if (items.Count == 0) return;
 38
 039        var entities = items.Select(i => new AssemblyListRunItem
 040        {
 041            RunId = runId,
 042            ItemIndex = i.Index,
 043            PostingNumber = i.PostingNumber,
 044            Status = i.Status,
 045            StatusLabel = i.StatusLabel,
 046            WarehouseId = i.WarehouseId,
 047            WarehouseName = i.WarehouseName,
 048            OfferId = i.OfferId,
 049            ProductName = i.ProductName,
 050            ImageUrl = i.ImageUrl,
 051            Quantity = i.Quantity,
 052            CutoffDate = i.CutoffDate,
 053            LabelUrl = i.LabelUrl,
 054            LabelError = i.LabelError,
 055            SupplierName = i.SupplierName,
 056            OrderedToSupplierDate = i.OrderedToSupplierDate,
 057            OneCBalance = i.OneCBalance,
 058            OneCReceiptDoc = i.OneCReceiptDoc,
 059            OneCReceiptDocKey = i.OneCReceiptDocKey,
 060            OneCOtherStock = i.OneCOtherStock,
 061        }).ToList();
 62
 063        _db.AssemblyListRunItems.AddRange(entities);
 064        await _db.SaveChangesAsync();
 065    }
 66
 67    /// <summary>
 68    /// Возвращает для каждого posting_number: имя поставщика (текущий заказ) и дату транзакции
 69    /// «Заказан поставщику» (из temporal-истории Orders).
 70    /// </summary>
 71    public async Task<Dictionary<string, (string? SupplierName, DateTime? OrderedDate)>> GetOrderInfoByPostingNumbersAsy
 72        IEnumerable<string> postingNumbers)
 73    {
 074        var numbers = postingNumbers.Where(n => !string.IsNullOrEmpty(n)).Distinct().ToList();
 075        if (numbers.Count == 0)
 076            return new Dictionary<string, (string?, DateTime?)>();
 77
 78        // Текущий поставщик из актуальных Orders
 079        var supplierMap = await _db.Orders
 080            .Where(o => o.ShipmentNumber != null && numbers.Contains(o.ShipmentNumber))
 081            .Select(o => new { o.ShipmentNumber, SupplierName = o.Supplier != null ? o.Supplier.Name : null })
 082            .ToListAsync();
 83
 84        // Дата транзакции «Заказан поставщику»:
 85        // 1) из orders_history — первая запись о выставлении SupplierId
 86        // 2) fallback — прямой join Order → Transaction WHERE Type=0 (работает, если заказ
 87        //    ещё не переведён в следующую транзакцию)
 088        var inList = string.Join(",", numbers.Select(n => $"'{n.Replace("'", "''")}'"));
 089        var sql = $@"
 090            SELECT o.ShipmentNumber,
 091                   COALESCE(
 092                       (SELECT MIN(h.ChangedAt)
 093                        FROM orders_history h
 094                        WHERE h.OrderId = o.Id
 095                          AND h.ColumnName = 'SupplierId'
 096                          AND h.NewValue IS NOT NULL
 097                          AND h.NewValue <> ''),
 098                       (SELECT t.CreatedDateTime
 099                        FROM Transactions t
 0100                        WHERE t.Id = o.TransactionId AND t.Type = 0
 0101                        LIMIT 1)
 0102                   ) AS OrderedDate
 0103            FROM Orders o
 0104            WHERE o.ShipmentNumber IN ({inList})";
 105
 0106        var orderedDates = new Dictionary<string, DateTime>(StringComparer.Ordinal);
 0107        var conn = _db.Database.GetDbConnection();
 0108        var wasOpen = conn.State == System.Data.ConnectionState.Open;
 0109        if (!wasOpen) await conn.OpenAsync();
 110        try
 111        {
 0112            await using var cmd = conn.CreateCommand();
 0113            cmd.CommandText = sql;
 0114            await using var reader = await cmd.ExecuteReaderAsync();
 0115            while (await reader.ReadAsync())
 116            {
 0117                var shipment = reader.GetString(0);
 0118                if (!reader.IsDBNull(1))
 0119                    orderedDates[shipment] = reader.GetDateTime(1);
 120            }
 0121        }
 122        finally
 123        {
 0124            if (!wasOpen) await conn.CloseAsync();
 125        }
 126
 0127        var result = new Dictionary<string, (string?, DateTime?)>(StringComparer.Ordinal);
 0128        foreach (var n in numbers)
 129        {
 0130            var supplier = supplierMap.FirstOrDefault(s => s.ShipmentNumber == n);
 0131            orderedDates.TryGetValue(n, out var orderedDate);
 0132            result[n] = (supplier?.SupplierName, orderedDate == default ? null : orderedDate);
 133        }
 0134        return result;
 0135    }
 136
 137    /// <summary>
 138    /// Возвращает для каждого posting_number значение "Засыла" (OrderExtension.Key == "Засыл"),
 139    /// если он задан хотя бы у одного из заказов этого отправления.
 140    /// </summary>
 141    public async Task<Dictionary<string, string?>> GetZasylValuesByShipmentNumbersAsync(IEnumerable<string> shipmentNumb
 142    {
 7143        var numbers = shipmentNumbers.Where(n => !string.IsNullOrEmpty(n)).Distinct().ToList();
 4144        if (numbers.Count == 0)
 1145            return new Dictionary<string, string?>();
 146
 3147        var rows = await _db.Orders
 3148            .Where(o => o.ShipmentNumber != null && numbers.Contains(o.ShipmentNumber))
 3149            .Select(o => new
 3150            {
 3151                o.ShipmentNumber,
 3152                Zasyl = o.OrderExtensions
 3153                    .Where(e => e.Key == "Засыл" && e.Value != null && e.Value != "")
 3154                    .Select(e => e.Value)
 3155                    .FirstOrDefault(),
 3156            })
 3157            .ToListAsync();
 158
 3159        var result = new Dictionary<string, string?>(StringComparer.OrdinalIgnoreCase);
 14160        foreach (var row in rows)
 161        {
 4162            if (row.ShipmentNumber == null) continue;
 4163            if (!string.IsNullOrEmpty(row.Zasyl) || !result.ContainsKey(row.ShipmentNumber))
 4164                result[row.ShipmentNumber] = row.Zasyl;
 165        }
 3166        return result;
 4167    }
 168
 169    public async Task<List<AssemblyListRun>> GetRecentRunsAsync(int limit = 100)
 170    {
 0171        return await _db.AssemblyListRuns
 0172            .OrderByDescending(r => r.StartedAtUtc)
 0173            .Take(limit)
 0174            .ToListAsync();
 0175    }
 176
 177    public async Task<AssemblyListRun?> GetLastCompletedRunAsync()
 178    {
 0179        return await _db.AssemblyListRuns
 0180            .Where(r => r.RunStatus == "completed" && r.TotalItems > 0)
 0181            .OrderByDescending(r => r.StartedAtUtc)
 0182            .FirstOrDefaultAsync();
 0183    }
 184
 185    public async Task<AssemblyListRun?> GetRunAsync(long runId)
 186    {
 0187        return await _db.AssemblyListRuns.FindAsync(runId);
 0188    }
 189
 190    public async Task<List<AssemblyListRunItem>> GetRunItemsAsync(long runId)
 191    {
 0192        return await _db.AssemblyListRunItems
 0193            .Where(i => i.RunId == runId)
 0194            .OrderBy(i => i.ItemIndex)
 0195            .ToListAsync();
 0196    }
 197}