< Summary

Information
Class: Services.ArmtekEtpServices.ArmtekEtpSyncJob
Assembly: Services
File(s): /home/runner/work/Studio2Prod/Studio2Prod/AppRepository/ArmtekEtpServices/ArmtekEtpSyncJob.cs
Line coverage
68%
Covered lines: 11
Uncovered lines: 5
Coverable lines: 16
Total lines: 64
Line coverage: 68.7%
Branch coverage
42%
Covered branches: 6
Total branches: 14
Branch coverage: 42.8%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
.ctor(...)100%11100%
ExecuteAsync()100%210%
ExecuteRangeAsync(...)100%210%
ExecuteRangeAsync()0%620%
ExecuteInvoicesAsync()50%121285.71%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/AppRepository/ArmtekEtpServices/ArmtekEtpSyncJob.cs

#LineLine coverage
 1using Hangfire;
 2
 3namespace Services.ArmtekEtpServices;
 4
 5/// <summary>Плановая выгрузка взаиморасчётов и фактур из кабинета Armtek (etp.armtek.ru).</summary>
 6public sealed class ArmtekEtpSyncJob
 7{
 8    public const string JobId = "armtek-etp-settlements-sync";
 9    /// <summary>Каждое утро в 07:00 по Москве (часовой пояс задаёт регистрация джоба).</summary>
 10    public const string DefaultCron = "0 7 * * *";
 11
 12    /// <summary>Один замок на все методы: плановый запуск и загрузка с кнопки не идут одновременно (одна сессия кабинет
 13    private const string LockResource = "armtek-etp-sync";
 14
 15    /// <summary>Через сколько продолжать догрузку фактур к Excel, если за раз все не вошли (лимит или суточная квота AP
 116    public static readonly TimeSpan ContinueInvoicesAfter = TimeSpan.FromHours(1);
 17
 18    private readonly ArmtekEtpSyncService _sync;
 19    private readonly IBackgroundJobClient? _jobs;
 20
 121    public ArmtekEtpSyncJob(ArmtekEtpSyncService sync, IBackgroundJobClient? jobs = null)
 22    {
 123        _sync = sync;
 124        _jobs = jobs;
 125    }
 26
 27    [DisableConcurrentExecution(LockResource, 0)]
 28    [AutomaticRetry(Attempts = 0)]
 029    public async Task<string> ExecuteAsync() => (await _sync.SyncAsync()).ToString();
 30
 31    /// <summary>Догрузка за произвольный период, например истории: BackgroundJob.Enqueue&lt;ArmtekEtpSyncJob&gt;(j => j
 32    [DisableConcurrentExecution(LockResource, 0)]
 33    [AutomaticRetry(Attempts = 0)]
 034    public Task<string> ExecuteRangeAsync(DateTime from, DateTime to) => ExecuteRangeAsync(from, to, null);
 35
 36    /// <summary>Загрузка с кнопки на странице: в журнал запусков пишется пользователь.</summary>
 37    [DisableConcurrentExecution(LockResource, 0)]
 38    [AutomaticRetry(Attempts = 0)]
 39    public async Task<string> ExecuteRangeAsync(DateTime from, DateTime to, string? user) =>
 040        (await _sync.SyncAsync(DateOnly.FromDateTime(from), DateOnly.FromDateTime(to),
 041            trigger: string.IsNullOrWhiteSpace(user) ? "Вручную" : user)).ToString();
 42
 43    /// <summary>
 44    /// Фактуры по API для документов взаиморасчётов за период — после импорта Excel. В кабинет не входит (взаиморасчёты
 45    /// только что пришли из файла), поэтому капча кабинета ему не мешает.
 46    /// </summary>
 47    [DisableConcurrentExecution(LockResource, 0)]
 48    [AutomaticRetry(Attempts = 0)]
 49    public async Task<string> ExecuteInvoicesAsync(DateTime from, DateTime to, string? user)
 50    {
 151        var result = await _sync.SyncAsync(DateOnly.FromDateTime(from), DateOnly.FromDateTime(to),
 152            trigger: "Фактуры к Excel" + (string.IsNullOrWhiteSpace(user) ? "" : " — " + user), includeSettlements: fals
 53
 54        // Утренняя загрузка смотрит только последние дни, поэтому история из Excel (год и больше) дочитывается
 55        // этой же задачей порциями, пока не кончатся фактуры. Остановились на квоте (ни загрузок, ни ошибок) — тоже
 56        // продолжаем; если же всё упало ошибками без единой загрузки — нет, иначе задача крутилась бы вечно.
 157        if (result.InvoicesRemaining > 0 && (result.Invoices > 0 || result.InvoiceErrors == 0) && _jobs != null)
 58        {
 159            var next = _jobs.Schedule<ArmtekEtpSyncJob>(j => j.ExecuteInvoicesAsync(from, to, user), ContinueInvoicesAft
 160            return result + $"; продолжение — задача {next} через {ContinueInvoicesAfter.TotalMinutes:0} мин";
 61        }
 062        return result.ToString();
 163    }
 64}