< Summary

Information
Class: OzonOrdersWeb.WebServices.Transactions.Grid.Commit.Steps.ApplyEditsStep
Assembly: OzonOrdersWeb
File(s): /home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/WebServices/Transactions/Grid/Commit/Steps/ApplyEditsStep.cs
Line coverage
52%
Covered lines: 38
Uncovered lines: 35
Coverable lines: 73
Total lines: 131
Line coverage: 52%
Branch coverage
51%
Covered branches: 28
Total branches: 54
Branch coverage: 51.8%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%210%
.ctor(...)100%210%
get_Key()100%210%
ExecuteAsync()0%110100%
IsZeroQuantity(...)0%2040%
BuildFormOrder(...)72.22%3636100%
Has()100%22100%
BuildSubmittedFields(...)0%620%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/WebServices/Transactions/Grid/Commit/Steps/ApplyEditsStep.cs

#LineLine coverage
 1using Microsoft.EntityFrameworkCore;
 2using OzonDomains.Models;
 3using OzonOrdersWeb.WebServices.Transactions.Grid.Contracts;
 4using OzonOrdersWeb.WebServices.Transactions.Grid.Definitions;
 5using OzonRepositories.Context;
 6using Services.DataServices;
 7
 8namespace OzonOrdersWeb.WebServices.Transactions.Grid.Commit.Steps;
 9
 10/// <summary>
 11/// Применяет правки строк к заказам через <see cref="OrdersDataServices.TransactOrder"/> — тот же путь, что у
 12/// классической формы: собираем «разреженный» <see cref="Order"/> с тем же набором полей, что постила форма,
 13/// и передаём список отправленных полей, чтобы отсутствующие не трактовались как очистка.
 14/// Уменьшение количества разбивает заказ (/1 остаток, /2 — в транзакцию) внутри TransactOrder.
 15/// </summary>
 16public sealed class ApplyEditsStep : ITransactionCommitStep
 17{
 18    /// <summary>Поля, которые классическая форма отправляет всегда (см. _TransactionTableBody.cshtml).</summary>
 019    private static readonly string[] LegacyFormFields =
 020    {
 021        nameof(Order.Id), nameof(Order.ShipmentNumber), nameof(Order.Price), nameof(Order.OzonClientId), nameof(Order.Oz
 022        nameof(Order.Article), nameof(Order.ShipmentWarehouse), nameof(Order.SupplierId), nameof(Order.Quantity),
 023        nameof(Order.PurchasePrice), nameof(Order.OriginalPurchasePrice), nameof(Order.ProductInfo),
 024        nameof(Order.MinOzonCommission), nameof(Order.MaxOzonCommission), nameof(Order.OrderNumberToSupplier),
 025        nameof(Order.AppStatusId), nameof(Order.ExtraExpenses)
 026    };
 27
 28    private readonly ApplicationDbContext _context;
 29    private readonly OrdersDataServices _orders;
 30
 031    public ApplyEditsStep(ApplicationDbContext context, OrdersDataServices orders)
 32    {
 033        _context = context;
 034        _orders = orders;
 035    }
 36
 037    public string Key => TransactionCommitStepKeys.ApplyEdits;
 38
 39    public async Task ExecuteAsync(TransactionCommitContext ctx)
 40    {
 41        var ids = ctx.Orders.Select(o => o.Id).ToList();
 042        ctx.FromStatusByOrderId = await _context.Orders.AsNoTracking()
 043            .Where(o => ids.Contains(o.Id))
 044            .Select(o => new { o.Id, FromStatusId = o.AppStatusId ?? 0 })
 45            .ToDictionaryAsync(x => x.Id, x => x.FromStatusId, ctx.CancellationToken);
 46
 047        await ctx.StageAsync("orders", "Меняем статусы заказов", ctx.Orders.Count == 1 ? "1 заказ" : $"заказов: {ctx.Ord
 48
 049        var updated = new List<Order>(ctx.Orders.Count);
 050        var d = ctx.Definition;
 051        foreach (var order in ctx.Orders)
 52        {
 053            var edit = ctx.Edits[order.Id];
 54            // Транзит утерь (ShippedToSeller с qty = 0, LostByCommissioner целиком) проводит ZeroQuantityPolicyStep:
 55            // ему нужны «формы» до TransactOrder — остатки WS, склады маппинга, отдельная транзакция.
 056            if (d.ZeroQuantityPolicy == ZeroQuantityPolicy.LostByCommissioner
 057                && (d.Type == OzonDomains.TransactionType.LostByCommissioner || IsZeroQuantity(edit)))
 58            {
 059                ctx.DeferredOrderIds.Add(order.Id);
 060                continue;
 61            }
 62
 063            var form = BuildFormOrder(order, edit, ctx);
 064            var submitted = BuildSubmittedFields(edit);
 065            updated.Add(await _orders.TransactOrder(form, submitted, ctx.User.Name));
 66        }
 67
 068        ctx.UpdatedOrders = updated;
 069    }
 70
 71    internal static bool IsZeroQuantity(TransactionGridRowEdit edit)
 072        => edit.Changed.Contains("quantity", StringComparer.OrdinalIgnoreCase) && edit.Quantity is 0;
 73
 74    /// <summary>Заказ «как из формы»: значения БД, поверх — правки; навигации только те, что были в hidden-полях.</summ
 75    internal static Order BuildFormOrder(Order db, TransactionGridRowEdit edit, TransactionCommitContext ctx)
 76    {
 477        var d = ctx.Definition;
 478        var editable = d.EditableFields.ToHashSet(StringComparer.OrdinalIgnoreCase);
 479        var changed = edit.Changed.ToHashSet(StringComparer.OrdinalIgnoreCase);
 3280        bool Has(string field) => editable.Contains(field) && changed.Contains(field);
 81
 82        // Проценка статус не меняет; остальные — статус из строки (по умолчанию клиент подставляет целевой).
 483        var appStatusId = d.PriceEditingOnly ? db.AppStatusId : edit.AppStatusId ?? db.AppStatusId;
 84
 485        var form = new Order
 486        {
 487            Id = db.Id,
 488            Key = db.Key,
 489            ShipmentNumber = db.ShipmentNumber,
 490            ShipmentId = db.ShipmentId,
 491            Price = Has("price") ? edit.Price : db.Price,
 492            OzonClientId = db.OzonClientId,
 493            OzonClient = db.OzonClientId.HasValue ? new OzonClient { Id = db.OzonClientId.Value } : null,
 494            Article = db.Article,
 495            ShipmentWarehouseId = Has("shipmentWarehouseId") ? edit.ShipmentWarehouseId : db.ShipmentWarehouseId,
 496            ShipmentWarehouse = db.ShipmentWarehouse?.Name != null ? new Warehouse { Name = db.ShipmentWarehouse.Name } 
 497            SupplierId = Has("supplierId") ? edit.SupplierId : db.SupplierId,
 498            Quantity = Has("quantity") ? edit.Quantity : db.Quantity,
 499            PurchasePrice = Has("purchasePrice") ? edit.PurchasePrice : db.PurchasePrice,
 4100            OriginalPurchasePrice = db.OriginalPurchasePrice,
 4101            ProductInfoId = db.ProductInfoId,
 4102            ProductInfo = db.ProductInfoId.HasValue
 4103                ? new Product { Id = db.ProductInfoId.Value, Weight = Has("weight") ? edit.Weight : db.ProductInfo?.Weig
 4104                : null,
 4105            MinOzonCommission = db.MinOzonCommission,
 4106            MaxOzonCommission = db.MaxOzonCommission,
 4107            OrderNumberToSupplier = Has("orderNumberToSupplier") ? edit.OrderNumberToSupplier : db.OrderNumberToSupplier
 4108            AppStatusId = appStatusId,
 4109            ExtraExpenses = Has("extraExpenses")
 4110                ? edit.ExtraExpenses
 2111                    .Where(e => e.ExpenseTypeId > 0 && e.Amount > 0)
 1112                    .Select(e => new OrderExtraExpense { OrderId = db.Id, ExpenseTypeId = e.ExpenseTypeId, Amount = e.Am
 4113                    .ToList()
 4114                // Как форма: существующие расходы «переотправляются» и пересоздаются в SaveExtraExpensesForOrders.
 3115                : db.ExtraExpenses?.Select(e => new OrderExtraExpense { OrderId = db.Id, ExpenseTypeId = e.ExpenseTypeId
 4116        };
 117
 4118        return form;
 119    }
 120
 121    internal static IReadOnlySet<string> BuildSubmittedFields(TransactionGridRowEdit edit)
 122    {
 0123        var set = new HashSet<string>(LegacyFormFields, StringComparer.OrdinalIgnoreCase);
 0124        if (edit.Changed.Contains("shipmentWarehouseId", StringComparer.OrdinalIgnoreCase))
 125        {
 0126            set.Add(nameof(Order.ShipmentWarehouseId));
 127        }
 128
 0129        return set;
 130    }
 131}