< Summary

Information
Class: Services.TransactionUtilsServices.TransactionTimeTrackingService
Assembly: Services
File(s): /home/runner/work/Studio2Prod/Studio2Prod/AppRepository/TransactionUtilsServices/TransactionTimeTrackingService.cs
Line coverage
100%
Covered lines: 71
Uncovered lines: 0
Coverable lines: 71
Total lines: 146
Line coverage: 100%
Branch coverage
95%
Covered branches: 21
Total branches: 22
Branch coverage: 95.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%
StartSessionAsync()100%66100%
CompleteSessionAsync()87.5%88100%
MarkAbandonedAsync()100%22100%
Truncate(...)100%66100%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/AppRepository/TransactionUtilsServices/TransactionTimeTrackingService.cs

#LineLine coverage
 1using OzonDomains;
 2using OzonDomains.Models;
 3using Services.DataServices;
 4
 5namespace Services.TransactionUtilsServices;
 6
 7public interface ITransactionTimeTrackingService
 8{
 9    Task<string> StartSessionAsync(
 10        string userName,
 11        int? accessProfileId,
 12        TransactionType transactionType,
 13        IEnumerable<int> orderIds,
 14        string? sourceUrl,
 15        string? clientIp,
 16        string? userAgent);
 17
 18    Task<long?> CompleteSessionAsync(
 19        string trackingKey,
 20        long transactionId,
 21        int ordersCountFinal,
 22        string? comment,
 23        string transactionUrl);
 24
 25    Task<int> MarkAbandonedAsync(TimeSpan olderThan);
 26}
 27
 28public class TransactionTimeTrackingService : ITransactionTimeTrackingService
 29{
 30    // Длины колонок TransactionTimeTrackingSessions/Results (см. [MaxLength] в TransactionTimeTrackingModels).
 31    // URL грида содержит закодированное состояние фильтров и легко превышает 1000 символов (#1825, #2353).
 32    private const int SourceUrlMaxLength = 1000;
 33    private const int ClientIpMaxLength = 64;
 34    private const int UserAgentMaxLength = 512;
 35    private const int TransactionUrlMaxLength = 1000;
 36    private const int CommentMaxLength = 1000;
 37
 38    private readonly TransactionTimeTrackingDataServices _dataServices;
 39
 3040    public TransactionTimeTrackingService(TransactionTimeTrackingDataServices dataServices)
 41    {
 3042        _dataServices = dataServices;
 3043    }
 44
 45    public async Task<string> StartSessionAsync(
 46        string userName,
 47        int? accessProfileId,
 48        TransactionType transactionType,
 49        IEnumerable<int> orderIds,
 50        string? sourceUrl,
 51        string? clientIp,
 52        string? userAgent)
 53    {
 1954        var ids = orderIds?.Distinct().ToList() ?? new List<int>();
 1955        var trackingKey = Guid.NewGuid().ToString("N");
 1956        var now = DateTime.UtcNow;
 57
 1958        var session = new TransactionTimeTrackingSession
 1959        {
 1960            TrackingKey = trackingKey,
 1961            UserName = userName,
 1962            AccessProfileId = accessProfileId,
 1963            TransactionType = transactionType.ToString(),
 1964            OrdersCountInitial = ids.Count,
 1965            OrderIdsJson = ids.Count == 0 ? null : string.Join(",", ids),
 1966            StartedAtUtc = now,
 1967            LastSeenAtUtc = now,
 1968            IsCompleted = false,
 1969            IsAbandoned = false,
 1970            SourceUrl = Truncate(sourceUrl, SourceUrlMaxLength),
 1971            ClientIp = Truncate(clientIp, ClientIpMaxLength),
 1972            UserAgent = Truncate(userAgent, UserAgentMaxLength),
 1973            CreatedAtUtc = now
 1974        };
 75
 1976        await _dataServices.AddSession(session);
 1977        return trackingKey;
 1978    }
 79
 80    public async Task<long?> CompleteSessionAsync(
 81        string trackingKey,
 82        long transactionId,
 83        int ordersCountFinal,
 84        string? comment,
 85        string transactionUrl)
 86    {
 1487        if (string.IsNullOrWhiteSpace(trackingKey))
 488            return null;
 89
 1090        var session = await _dataServices.GetSessionByTrackingKey(trackingKey);
 1091        if (session == null)
 192            return null;
 93
 994        var existingResult = await _dataServices.GetResultByTrackingKey(trackingKey);
 995        if (existingResult != null)
 196            return existingResult.Id;
 97
 898        var completedAt = DateTime.UtcNow;
 899        session.IsCompleted = true;
 8100        session.IsAbandoned = false;
 8101        session.CompletedAtUtc = completedAt;
 8102        session.LastSeenAtUtc = completedAt;
 8103        await _dataServices.UpdateSession(session);
 104
 8105        var durationSeconds = (int)Math.Max(0, (completedAt - session.StartedAtUtc).TotalSeconds);
 8106        var result = new TransactionTimeTrackingResult
 8107        {
 8108            TrackingSessionId = session.Id,
 8109            TrackingKey = session.TrackingKey,
 8110            UserName = session.UserName,
 8111            AccessProfileId = session.AccessProfileId,
 8112            TransactionType = session.TransactionType,
 8113            OrdersCountFinal = ordersCountFinal,
 8114            StartedAtUtc = session.StartedAtUtc,
 8115            CompletedAtUtc = completedAt,
 8116            DurationSeconds = durationSeconds,
 8117            TransactionId = transactionId,
 8118            TransactionUrl = Truncate(transactionUrl, TransactionUrlMaxLength) ?? string.Empty,
 8119            Comment = Truncate(comment, CommentMaxLength),
 8120            CreatedAtUtc = completedAt
 8121        };
 122
 8123        await _dataServices.AddResult(result);
 8124        return result.Id;
 14125    }
 126
 127    public async Task<int> MarkAbandonedAsync(TimeSpan olderThan)
 128    {
 5129        var olderThanUtc = DateTime.UtcNow.Subtract(olderThan);
 5130        var candidates = await _dataServices.GetAbandonedCandidates(olderThanUtc);
 5131        var marked = 0;
 132
 20133        foreach (var session in candidates)
 134        {
 5135            session.IsAbandoned = true;
 5136            session.LastSeenAtUtc = DateTime.UtcNow;
 5137            await _dataServices.UpdateSession(session);
 5138            marked++;
 139        }
 140
 5141        return marked;
 5142    }
 143
 144    private static string? Truncate(string? value, int maxLength)
 73145        => value is { Length: > 0 } && value.Length > maxLength ? value[..maxLength] : value;
 146}