< Summary

Information
Class: OzonOrdersWeb.Controllers.TransactionController
Assembly: OzonOrdersWeb
File(s): /home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Areas/Studio2/Controllers/TransactionController.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 362
Coverable lines: 362
Total lines: 681
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 241
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Areas/Studio2/Controllers/TransactionController.cs

#LineLine coverage
 1using Microsoft.AspNetCore.Authorization;
 2using Microsoft.AspNetCore.Identity;
 3using Microsoft.AspNetCore.Mvc;
 4using Microsoft.AspNetCore.Mvc.Rendering;
 5using Newtonsoft.Json;
 6using OServices.FiltersServices.FilterModels;
 7using OzonDomains;
 8using OzonDomains.Models;
 9using OzonOrdersWeb.ViewModels.TransactionViewModels;
 10using OzonRepositories.Context;
 11using OzonRepositories.Context.Identity;
 12using Services.Builders.PdfBuilder.Builders;
 13using Services.CacheServices.Cache.OzonOrdersCache;
 14using Services.CacheServices.Cache.UniqueValuesCache;
 15using Services.CacheServices.Cache.UserCacheService;
 16using Services.FiltersServices.DataFilterManagers;
 17using Services.ChannelTaskServices;
 18using Services.DataServices;
 19using Services.FiltersServices.FilterModels;
 20using Services.FiltersServices.SortModels;
 21using Services.ParserServices.FielParsers;
 22using Services.CacheServices.Cache;
 23using System;
 24using OzonRepositories.Data.Bitrix;
 25
 26namespace OzonOrdersWeb.Controllers
 27{
 28    [Authorize(Roles = "User,Admin")]
 29    [Area("Studio2")]
 30    public class TransactionController : Controller
 31    {
 32        private readonly TransactionDataServices _transactionDataServices;
 33        private readonly OrdersDataServices _orderServices;
 34        private readonly TransactionCache _cache;
 35        private readonly OrderCache _orderCache;
 36        private readonly TransactionDataFilterManager _dataFilterManager;
 37        private readonly OrderDataFilterManager _orderDataFilterManager;
 38        private readonly UserManager<CustomIdentityUser> _userManager;
 39        private readonly AppStatusDataServices _appStatusServices;
 40        private readonly SupplierDataServices _supplierDataServices;
 41        private readonly CacheUpdater<Transaction> _cacheUpdater;
 42        private readonly OzonClientServices _ozonClientServices;
 43        private readonly WarehouseDataServices _warehouseDataServices;
 44        private readonly ApplicationDbContext _context;
 45        private readonly ExcelExporter _excelExporter;
 46        private readonly IUniqueValuesCache _uniqueValuesCache;
 47        private readonly IUserCacheService _userCacheService;
 48        private readonly PdfService _pdfService;
 49        private readonly BitrixStockRepository _stockRepository;
 50        private readonly ClientStatusDataServices _clientStatusServices;
 51        private readonly DeliveryDataServices _deliveryDataServices;
 52        private readonly IChannelTaskService _channelTasks;
 053        public TransactionController(TransactionDataServices transactionDataServices,
 054                                    OrdersDataServices ordersDataServices,
 055                                    TransactionCache cache,
 056                                    OrderCache orderCache,
 057                                    TransactionDataFilterManager dataFilterManager,
 058                                    UserManager<CustomIdentityUser> userManager,
 059                                    AppStatusDataServices appStatusDataServices,
 060                                    SupplierDataServices supplierDataServices,
 061                                    OrderDataFilterManager orderDataFilterManager,
 062                                    CacheUpdater<Transaction> cacheUpdater,
 063                                    OzonClientServices ozonClientServices,
 064                                    WarehouseDataServices warehouseDataServices,
 065                                    ApplicationDbContext ApplicationDbContext,
 066                                    ExcelExporter excelExporter,
 067                                    IUniqueValuesCache uniqueValuesCache,
 068                                    IUserCacheService userCacheService,
 069                                    PdfService pdfService,
 070                                    BitrixStockRepository stockRepository,
 071                                    ClientStatusDataServices clientStatusServices,
 072                                    DeliveryDataServices deliveryDataServices,
 073                                    IChannelTaskService channelTasks
 074                                    )
 75        {
 076            _transactionDataServices = transactionDataServices;
 077            _orderServices = ordersDataServices;
 078            _cache = cache;
 079            _orderCache = orderCache;
 080            _dataFilterManager = dataFilterManager;
 081            _userManager = userManager;
 082            _appStatusServices = appStatusDataServices;
 083            _supplierDataServices = supplierDataServices;
 084            _orderDataFilterManager = orderDataFilterManager;
 085            _cacheUpdater = cacheUpdater;
 086            _ozonClientServices = ozonClientServices;
 087            _warehouseDataServices = warehouseDataServices;
 088            _context = ApplicationDbContext;
 089            _excelExporter = excelExporter;
 090            _uniqueValuesCache = uniqueValuesCache;
 091            _userCacheService = userCacheService;
 092            _pdfService = pdfService;
 093            _stockRepository = stockRepository;
 094            _clientStatusServices = clientStatusServices;
 095            _deliveryDataServices = deliveryDataServices;
 096            _channelTasks = channelTasks;
 097        }
 98
 99        private async Task PopulateJournalFilterViewBagAsync()
 100        {
 101            var appStatuses = (await _appStatusServices.GetAppStatuses()).OrderBy(a => a.Name).ToList();
 0102            ViewBag.AppStatuses = new SelectList(appStatuses, "Name", "Name");
 0103            ViewBag.StatusColors = appStatuses
 104                .Where(s => s.Name != null)
 105                .ToDictionary(s => s.Name!, s => s.GetStatusColor());
 0106            ViewBag.AppStatusIsFinal = appStatuses
 107                .Where(s => s.Name != null)
 108                .ToDictionary(s => s.Name!, s => s.IsFinal);
 109
 110            var clientStatuses = (await _clientStatusServices.GetClientStatuses()).OrderBy(s => s.Name).ToList();
 0111            ViewBag.Statuses = new SelectList(clientStatuses, nameof(ClientStatus.Name), nameof(ClientStatus.Name));
 112            ViewBag.StatusesIsFinal = clientStatuses.ToDictionary(s => s.Name, s => s.IsFinal);
 113            ViewBag.ClientStatusColors = clientStatuses.ToDictionary(s => s.Name, s => s.GetStatusColor());
 114
 115            var providers = (await _deliveryDataServices.GetProviders()).OrderBy(a => a.Name).ToList();
 0116            ViewBag.Providers = new SelectList(providers, "Name", "Name");
 117
 118            ViewBag.Suppliers = new SelectList((await _supplierDataServices.GetSuppliers()).OrderBy(a => a.Name), "Name"
 119            ViewBag.Clients = new SelectList((await _ozonClientServices.GetOzonClients()).OrderBy(a => a.Name), "Name", 
 120            ViewBag.Warehouses = new SelectList((await _warehouseDataServices.GetWarehouses()).OrderBy(a => a.Name), "Na
 0121        }
 122
 123        public async Task<IActionResult> Index(OrderSortState sortOrder = OrderSortState.StandardState, int page = 1)
 124        {
 0125            SaveSortStateCookie(sortOrder);
 126
 0127            var transactions = await _cache.Get(page);
 128
 0129            await PopulateJournalFilterViewBagAsync();
 130
 0131            var filterDataString = HttpContext.Request.Cookies["TransactionFilterData"];
 0132            var filterData = new TransactionFilterModel();
 133
 0134            var orderFilterDataString = HttpContext.Request.Cookies["OrderFilterData"];
 0135            var orderFilterData = new OrderFilterModel();
 136
 0137            if (!string.IsNullOrEmpty(filterDataString))
 138            {
 0139                filterData = JsonConvert.DeserializeObject<TransactionFilterModel>(filterDataString) ?? new TransactionF
 140            }
 141
 0142            if (!string.IsNullOrEmpty(orderFilterDataString))
 143            {
 0144                orderFilterData = JsonConvert.DeserializeObject<OrderFilterModel>(orderFilterDataString) ?? new OrderFil
 145            }
 146
 0147            if (!string.IsNullOrEmpty(filterDataString) || !string.IsNullOrEmpty(orderFilterDataString))
 148            {
 0149                transactions = await _dataFilterManager.FilterByFilterData(transactions, orderFilterData, filterData);
 150
 0151                foreach (var trans in transactions)
 152                {
 0153                    trans.Orders = await _orderDataFilterManager.FilterTransactionsOrdersByFilterData(trans.Orders.ToLis
 154                }
 155
 156                transactions = transactions.Where(e => e.Orders.Count > 0).ToList();
 157            }
 158
 0159            if (sortOrder == OrderSortState.StandardState && Request.Cookies.ContainsKey("SortState"))
 160            {
 0161                sortOrder = GetSortStateCookie();
 162            }
 163
 0164            SetSortOrderViewData(sortOrder);
 165
 0166            foreach (var trans in transactions)
 167            {
 0168                trans.Orders = (await ApplySortOrder(trans.Orders, sortOrder)).ToList();
 169            }
 170
 0171            int pageSize = Int32.TryParse(Request.Cookies["PageSize"], out var size)
 0172                ? size
 0173                : 15;
 174
 175            // Сначала пагинация, потом LoadClientStatusColors — только для отображаемой страницы
 176            var sortedTransactions = transactions.OrderByDescending(tr => tr.CreatedDateTime).ToList();
 0177            var pagedTransactions = sortedTransactions.Skip((page - 1) * pageSize).Take(pageSize).ToList();
 178
 179            // Загружаем StatusColor для ClientStatus только для заказов на текущей странице
 180            var pageOrders = pagedTransactions.SelectMany(t => t.Orders).ToList();
 0181            if (pageOrders.Any())
 182            {
 0183                await _transactionDataServices.LoadClientStatusColorsForOrders(pageOrders);
 184            }
 185
 0186            var pageViewModel = new TransactionViewModel<Transaction, TransactionFilterModel>(sortedTransactions, page, 
 0187            {
 0188                UniqueArticles = await _orderServices.GetArticleCountsForOrdersAsync(pageOrders),
 0189                UniqueDeliveryCitys = await _orderServices.GetDeliveryCityCountsForOrdersAsync(pageOrders),
 0190                UniqueNumbers = await _orderServices.GetShipmentBaseCountsForOrdersAsync(pageOrders),
 0191
 0192                OrderFilterModel = orderFilterData,
 0193                UserNames = _userManager.Users.Select(u => u.UserName).Where(u => u != null).Cast<string>().ToList(),
 0194                TransactionTypes = [
 0195                    (TransactionType.OrderedToSupplier, "Заказан поставщику"),
 0196                    (TransactionType.ShippedBySupplier, "Отгружен поставщиком"),
 0197                    (TransactionType.ShippedToSeller, "Отгружен реализатором"),
 0198                    (TransactionType.OrderedToSeller, "Заказан реализатору"),
 0199                    (TransactionType.ShippedToClient, "Отгружен клиенту"),
 0200                    (TransactionType.Percentage, "Проценён"),
 0201                    (TransactionType.ReceiptNote, "Приходная накладная"),
 0202                    (TransactionType.AcceptedToWarehouse, "Принят на складе"),
 0203                    (TransactionType.ToCancellation, "К отмене"),
 0204                    (TransactionType.Cancelled, "Отменен"),
 0205                    (TransactionType.CustomerReturn, "Возврат покупателя"),
 0206                    (TransactionType.WarehouseChange, "Изменение склада"),
 0207                    (TransactionType.ReturnToSupplier, "Возвращено поставщику"),
 0208                    (TransactionType.ReturnToWarehouse, "Возврат на склад"),
 0209                    (TransactionType.WarehouseTransfer, "Перемещение между складами"),
 0210                    (TransactionType.ShippedToCommissioner, "Отгружен комиссионеру"),
 0211                    (TransactionType.ReturnTransfer, "Перемещение")
 0212                ],
 0213                User = (await _userCacheService.GetCachedUserAsync(User))!,
 0214            };
 215
 0216            if (pageViewModel.User.AccessProfileId != null)
 217            {
 0218                pageViewModel.User.AccessProfile = await _context.AccessProfiles.FindAsync(pageViewModel.User.AccessProf
 219            }
 220
 0221            ViewData["DisplayName"] = pageViewModel.TransactionTypes.FirstOrDefault(t => t.Item1 == filterData.Type).Ite
 222
 0223            return View(pageViewModel);
 0224        }
 225        public async Task<IActionResult> GetTransaction(int transactionId)
 226        {
 0227            var transaction = await _transactionDataServices.GetTransaction(transactionId);
 0228            if (transaction == null)
 229            {
 0230                return NotFound();
 231            }
 232
 0233            List<Transaction> transactions = [transaction];
 234
 0235            await PopulateJournalFilterViewBagAsync();
 236
 0237            int pageSize = Int32.TryParse(Request.Cookies["PageSize"], out var size)
 0238                ? size
 0239                : 15;
 240
 0241            var journalOrders = transaction.Orders ?? new List<Order>();
 242
 243            var pageViewModel = new TransactionViewModel<Transaction, TransactionFilterModel>(transactions.OrderByDescen
 0244            {
 0245                UniqueArticles = await _orderServices.GetArticleCountsForOrdersAsync(journalOrders),
 0246                UniqueDeliveryCitys = await _orderServices.GetDeliveryCityCountsForOrdersAsync(journalOrders),
 0247                UniqueNumbers = await _orderServices.GetShipmentBaseCountsForOrdersAsync(journalOrders),
 0248
 0249                OrderFilterModel = new OrderFilterModel(),
 0250                UserNames = _userManager.Users.Select(u => u.UserName).Where(u => u != null).Cast<string>().ToList(),
 0251                TransactionTypes = [
 0252                    (TransactionType.OrderedToSupplier, "Заказан поставщику"),
 0253                    (TransactionType.ShippedBySupplier, "Отгружен поставщиком"),
 0254                    (TransactionType.ShippedToSeller, "Отгружен реализатором"),
 0255                    (TransactionType.OrderedToSeller, "Заказан реализатору"),
 0256                    (TransactionType.ShippedToClient, "Отгружен клиенту"),
 0257                    (TransactionType.Percentage, "Проценён"),
 0258                    (TransactionType.ReceiptNote, "Приходная накладная"),
 0259                    (TransactionType.AcceptedToWarehouse, "Принят на складе"),
 0260                    (TransactionType.ToCancellation, "К отмене"),
 0261                    (TransactionType.Cancelled, "Отменен"),
 0262                    (TransactionType.CustomerReturn, "Возврат покупателя"),
 0263                    (TransactionType.WarehouseChange, "Изменение склада"),
 0264                    (TransactionType.ReturnToSupplier, "Возвращено поставщику"),
 0265                    (TransactionType.ReturnToWarehouse, "Возврат на склад"),
 0266                    (TransactionType.WarehouseTransfer, "Перемещение между складами"),
 0267                    (TransactionType.ShippedToCommissioner, "Отгружен комиссионеру"),
 0268                    (TransactionType.ReturnTransfer, "Перемещение")
 0269                ],
 0270                User = (await _userCacheService.GetCachedUserAsync(User))!,
 0271            };
 272
 0273            if (pageViewModel.User.AccessProfileId != null)
 274            {
 0275                pageViewModel.User.AccessProfile = await _context.AccessProfiles.FindAsync(pageViewModel.User.AccessProf
 276            }
 277
 0278            return View("Index", pageViewModel);
 0279        }
 280
 281        [HttpPost]
 282        public async Task<IActionResult> Index(TransactionFilterModel filterData, OrderFilterModel orderFilterData, int 
 283        {
 0284            var transactions = await _cache.Get(page);
 285
 0286            await PopulateJournalFilterViewBagAsync();
 287
 0288            var serializedFilterData = JsonConvert.SerializeObject(filterData);
 0289            HttpContext.Response.Cookies.Append("TransactionFilterData", serializedFilterData);
 290
 0291            var serializedoOrderFilterData = JsonConvert.SerializeObject(orderFilterData);
 0292            HttpContext.Response.Cookies.Append("OrderFilterData", serializedoOrderFilterData);
 293
 0294            transactions = await _dataFilterManager.FilterByFilterData(transactions, orderFilterData, filterData);
 295
 0296            foreach (var trans in transactions)
 297            {
 0298                trans.Orders = await _orderDataFilterManager.FilterTransactionsOrdersByFilterData(trans.Orders.ToList(),
 299            }
 300
 301            transactions = transactions.Where(e => e.Orders.Count > 0).ToList();
 302
 0303            int pageSize = Int32.TryParse(Request.Cookies["PageSize"], out var size)
 0304                ? size
 0305                : 15;
 306
 307            // При массовом поиске по номерам — отключаем пагинацию и вычисляем не найденные
 0308            var searchedShipmentNumbers = OrderDataFilterManager.GetShipmentNumbersFromFilter(orderFilterData.ShipmentNu
 0309            if (searchedShipmentNumbers.Count > 1)
 310            {
 0311                pageSize = int.MaxValue;
 312                var transactionOrders = transactions.SelectMany(t => t.Orders).ToList();
 0313                var notFoundNumbers = searchedShipmentNumbers
 0314                    .Where(n => transactionOrders.All(o => !OrderDataFilterManager.ShipmentNumberMatchesSearch(o.Shipmen
 0315                    .ToList();
 0316                var foundList = searchedShipmentNumbers
 0317                    .Where(n => transactionOrders.Any(o => OrderDataFilterManager.ShipmentNumberMatchesSearch(o.Shipment
 0318                    .ToList();
 0319                ViewBag.ShipmentNumbersSearched = searchedShipmentNumbers;
 0320                ViewBag.ShipmentNumbersFound = foundList;
 0321                if (notFoundNumbers.Count > 0)
 0322                    ViewBag.ShipmentNumbersNotFound = notFoundNumbers;
 323            }
 324
 325            // Сначала пагинация, потом LoadClientStatusColors — только для отображаемой страницы
 326            var sortedTransactions = transactions.OrderByDescending(tr => tr.CreatedDateTime).ToList();
 0327            var pagedTransactions = sortedTransactions.Skip((page - 1) * pageSize).Take(pageSize).ToList();
 328
 329            var pageOrders = pagedTransactions.SelectMany(t => t.Orders).ToList();
 0330            if (pageOrders.Any())
 331            {
 0332                await _transactionDataServices.LoadClientStatusColorsForOrders(pageOrders);
 333            }
 334
 0335            var pageViewModel = new TransactionViewModel<Transaction, TransactionFilterModel>(sortedTransactions, page, 
 0336            {
 0337                UniqueArticles = await _orderServices.GetArticleCountsForOrdersAsync(pageOrders),
 0338                UniqueDeliveryCitys = await _orderServices.GetDeliveryCityCountsForOrdersAsync(pageOrders),
 0339                UniqueNumbers = await _orderServices.GetShipmentBaseCountsForOrdersAsync(pageOrders),
 0340
 0341                UserNames = _userManager.Users.Select(u => u.UserName).Where(u => u != null).Cast<string>().ToList(),
 0342                TransactionTypes = [
 0343                    (TransactionType.OrderedToSupplier, "Заказан поставщику"),
 0344                    (TransactionType.ShippedBySupplier, "Отгружен поставщиком"),
 0345                    (TransactionType.ShippedToSeller, "Отгружен реализатором"),
 0346                    (TransactionType.OrderedToSeller, "Заказан реализатору"),
 0347                    (TransactionType.ShippedToClient, "Отгружен клиенту"),
 0348                    (TransactionType.Percentage, "Проценён"),
 0349                    (TransactionType.ReceiptNote, "Приходная накладная"),
 0350                    (TransactionType.AcceptedToWarehouse, "Принят на складе"),
 0351                    (TransactionType.ToCancellation, "К отмене"),
 0352                    (TransactionType.Cancelled, "Отменен"),
 0353                    (TransactionType.CustomerReturn, "Возврат покупателя"),
 0354                    (TransactionType.WarehouseChange, "Изменение склада"),
 0355                    (TransactionType.ReturnToSupplier, "Возвращено поставщику"),
 0356                    (TransactionType.ReturnToWarehouse, "Возврат на склад"),
 0357                    (TransactionType.WarehouseTransfer, "Перемещение между складами"),
 0358                    (TransactionType.ShippedToCommissioner, "Отгружен комиссионеру"),
 0359                    (TransactionType.ReturnTransfer, "Перемещение")
 0360                ],
 0361                User = (await _userCacheService.GetCachedUserAsync(User))!,
 0362            };
 363
 0364            if (pageViewModel.User.AccessProfileId != null)
 365            {
 0366                pageViewModel.User.AccessProfile = await _context.AccessProfiles.FindAsync(pageViewModel.User.AccessProf
 367            }
 368
 0369            ViewData["DisplayName"] = pageViewModel.TransactionTypes.FirstOrDefault(t => t.Item1 == filterData.Type).Ite
 370
 0371            return View(pageViewModel);
 0372        }
 373        public async Task<IActionResult> Update()
 374        {
 0375            await _cacheUpdater.Update(_cache);
 0376            return RedirectToAction("Index");
 0377        }
 378
 379        [HttpGet]
 380        public IActionResult PrintTransactionToExcel(int transactionId)
 0381            => StartTransactionExcelTask(transactionId, null, null, tableMode: false);
 382
 383        [HttpGet("excel-tasks/start"), HttpPost("excel-tasks/start")]
 384        [IgnoreAntiforgeryToken]
 385        public IActionResult StartTransactionExcelTask(
 386            [FromQuery] int? transactionId = null,
 387            [FromQuery] string? ids = null,
 388            [FromQuery] string? deletedIds = null,
 389            [FromQuery] bool tableMode = false)
 390        {
 0391            var payload = new TransactionExcelTaskPayload
 0392            {
 0393                TransactionId = transactionId,
 0394                TableMode = tableMode,
 0395                OrderIds = ParseIds(ids),
 0396                DeletedOrderIds = ParseIds(deletedIds)
 0397            };
 398
 0399            if (!tableMode && transactionId is not > 0)
 0400                return BadRequest(new { success = false, error = "transactionId обязателен" });
 401
 0402            if (tableMode && payload.OrderIds.Length == 0)
 0403                return BadRequest(new { success = false, error = "Не указаны ID заказов" });
 404
 0405            var task = _channelTasks.Submit(ChannelTaskType.TransactionExcel, payload);
 0406            return Ok(ChannelTaskResponses.ToStartResponse(task));
 407        }
 408
 409        public async Task<IActionResult> PrintTransactionToPdf(int transactionId)
 410        {
 0411            Transaction? transaction = await _transactionDataServices.GetTransaction(transactionId);
 0412            if (transaction?.Orders != null)
 413            {
 0414                var stock = await _stockRepository.SetStocksForOrdersAsyncFromBitrix(transaction.Orders.ToList());
 0415                _pdfService.stocks = stock;
 0416                byte[]? pdfFile = _pdfService.GenerateTransactionPdf(transaction);
 0417                if (pdfFile == null)
 418                {
 0419                    return NotFound("Transaction PDF could not be generated");
 420                }
 421
 0422                string transactionTypeName = transaction.Type?.GetDisplayName() ?? "Unknown";
 423
 0424                return File(pdfFile, "application/pdf",
 0425                    $"{transactionTypeName}_{transaction.CreateBy}_{transaction.CreatedDateTime:dd.MM.yyyy}.pdf");
 426            }
 0427            return NotFound("Transaction not found");
 0428        }
 429
 430        [HttpGet]
 431        public async Task<IActionResult> PrintTransactionTableToPdf(string ids, string? deletedIds = null)
 432        {
 0433            if (string.IsNullOrEmpty(ids))
 434            {
 0435                return BadRequest("Не указаны ID заказов");
 436            }
 437
 438            try
 439            {
 0440                var idArray = ParseIds(ids);
 0441                var deletedIdSet = ParseIds(deletedIds).ToHashSet();
 0442                idArray = idArray.Where(id => !deletedIdSet.Contains(id)).ToArray();
 443
 0444                if (idArray.Length == 0)
 445                {
 0446                    return NotFound("После исключения удалённых строк не осталось заказов для печати");
 447                }
 448
 0449                List<Order> orders = new List<Order>();
 450
 0451                foreach (var orderId in idArray)
 452                {
 0453                    var order = await _orderServices.GetAsyncNoTracking(orderId);
 0454                    if (order != null)
 455                    {
 0456                        orders.Add(order);
 457                    }
 458                }
 459
 0460                if (orders.Count == 0)
 461                {
 0462                    return NotFound("Заказы не найдены");
 463                }
 464
 465                // Получаем остатки Bitrix для всех заказов
 0466                var bitrixStocks = await _stockRepository.SetStocksForOrdersAsyncFromBitrix(orders);
 467                // Словарь: артикул -> общий остаток (по всем складам)
 0468                var articleToStock = new Dictionary<string, int>();
 0469                foreach (var order in orders)
 470                {
 0471                    if (string.IsNullOrWhiteSpace(order.ProductKey)) continue;
 0472                    var article = order.ProductKey.Split('=')[0].Trim();
 0473                    if (bitrixStocks.TryGetValue(order.Id, out var stocks) && stocks != null)
 474                    {
 475                        articleToStock[article] = (int)stocks.Sum(s => s.Amount);
 476                    }
 477                }
 478
 479                // Ограничиваем длину названия товара (не более 60 символов)
 0480                foreach (var order in orders)
 481                {
 0482                    if (!string.IsNullOrEmpty(order.ProductName) && order.ProductName.Length > 60)
 483                    {
 0484                        order.ProductName = order.ProductName.Substring(0, 60) + "...";
 485                    }
 486                }
 487
 0488                var pdfBuilder = new TransactionTablePdfBuilder();
 0489                byte[] pdfFile = pdfBuilder.GeneratePdfWithStocks(orders, articleToStock);
 490
 0491                string fileName = $"Таблица_заказов_{DateTime.Now:dd.MM.yyyy_HHmmss}.pdf";
 0492                return File(pdfFile, "application/pdf", fileName);
 493            }
 0494            catch (Exception ex)
 495            {
 0496                return StatusCode(500, $"Ошибка при генерации PDF: {ex.Message}");
 497            }
 0498        }
 499
 500        [HttpGet]
 501        public IActionResult PrintTransactionTableToExcel(string ids, string? deletedIds = null)
 0502            => StartTransactionExcelTask(null, ids, deletedIds, tableMode: true);
 503
 504        private static int[] ParseIds(string? ids)
 505        {
 0506            if (string.IsNullOrWhiteSpace(ids))
 507            {
 0508                return Array.Empty<int>();
 509            }
 510
 0511            return ids
 0512                .Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
 0513                .Select(id => int.TryParse(id, out var parsed) ? parsed : (int?)null)
 0514                .Where(id => id.HasValue)
 0515                .Select(id => id!.Value)
 0516                .Distinct()
 0517                .ToArray();
 518        }
 519
 520        public void SetSortOrderViewData(OrderSortState sortOrder)
 521        {
 0522            ViewData["ShipmentNumberSort"] = sortOrder == OrderSortState.ShipmentNumberAsc ? OrderSortState.ShipmentNumb
 0523            ViewData["ProcessingDateSort"] = sortOrder == OrderSortState.ProcessingDateAsc ? OrderSortState.ProcessingDa
 0524            ViewData["ShippingDateSort"] = sortOrder == OrderSortState.ShippingDateAsc ? OrderSortState.ShippingDateDesc
 0525            ViewData["StatusSort"] = sortOrder == OrderSortState.StatusAsc ? OrderSortState.StatusDesc : OrderSortState.
 0526            ViewData["CurrentPriceSort"] = sortOrder == OrderSortState.CurrentPriceAsc ? OrderSortState.CurrentPriceDesc
 0527            ViewData["AppStatusIdSort"] = sortOrder == OrderSortState.AppStatusIdAsc ? OrderSortState.AppStatusIdDesc : 
 0528            ViewData["ShipmentAmountSort"] = sortOrder == OrderSortState.ShipmentAmountAsc ? OrderSortState.ShipmentAmou
 0529            ViewData["ProductNameSort"] = sortOrder == OrderSortState.ProductNameAsc ? OrderSortState.ProductNameDesc : 
 0530            ViewData["ArticleSort"] = sortOrder == OrderSortState.ArticleAsc ? OrderSortState.ArticleDesc : OrderSortSta
 0531            ViewData["PriceSort"] = sortOrder == OrderSortState.PriceAsc ? OrderSortState.PriceDesc : OrderSortState.Pri
 0532            ViewData["QuantitySort"] = sortOrder == OrderSortState.QuantityAsc ? OrderSortState.QuantityDesc : OrderSort
 0533            ViewData["ShipmentWarehouseSort"] = sortOrder == OrderSortState.ShipmentWarehouseIdAsc ? OrderSortState.Ship
 0534            ViewData["SupplierSort"] = sortOrder == OrderSortState.SupplierAsc ? OrderSortState.SupplierDesc : OrderSort
 0535            ViewData["PurchasePriceSort"] = sortOrder == OrderSortState.PurchasePriceAsc ? OrderSortState.PurchasePriceD
 0536            ViewData["ProductInfoIdSort"] = sortOrder == OrderSortState.ProductInfoIdAsc ? OrderSortState.ProductInfoIdD
 0537            ViewData["OzonCommissionSort"] = sortOrder == OrderSortState.MinOzonCommissionAsc ? OrderSortState.MinOzonCo
 0538            ViewData["VolumeSort"] = sortOrder == OrderSortState.VolumeAsc ? OrderSortState.VolumeDesc : OrderSortState.
 0539            ViewData["ProfitSort"] = sortOrder == OrderSortState.ProfitAsc ? OrderSortState.ProfitDesc : OrderSortState.
 0540            ViewData["DiscountSort"] = sortOrder == OrderSortState.DiscountAsc ? OrderSortState.DiscountDesc : OrderSort
 0541            ViewData["DeliveryCitySort"] = sortOrder == OrderSortState.DeliveryCityAsc ? OrderSortState.DeliveryCityDesc
 0542            ViewData["CategorySort"] = sortOrder == OrderSortState.CategoryAsc ? OrderSortState.CategoryDesc : OrderSort
 0543            ViewData["OrderNumberToSupplierSort"] = sortOrder == OrderSortState.OrderNumberToSupplierAsc ? OrderSortStat
 0544            ViewData["OzonClient"] = sortOrder == OrderSortState.OzonClientAsc ? OrderSortState.OzonClientDesc : OrderSo
 0545            ViewData["ManufacturerSort"] = sortOrder == OrderSortState.ManufacturerAsc ? OrderSortState.ManufacturerDesc
 0546            ViewData["FromFileSort"] = sortOrder == OrderSortState.FromFileAsc ? OrderSortState.FromFileDesc : OrderSort
 0547            ViewData["DeliveryPeriodSort"] = sortOrder == OrderSortState.DeliveryPeriodAsc ? OrderSortState.DeliveryPeri
 0548            ViewData["CostPriceсеSort"] = sortOrder == OrderSortState.CostPriceAsc ? OrderSortState.CostPriceDesc : Orde
 0549            ViewData["TimeLeftSort"] = sortOrder == OrderSortState.TimeLeftAsc ? OrderSortState.TimeLeftDesc : OrderSort
 0550            ViewData["LastStatusChangeDateSort"] = sortOrder == OrderSortState.LastStatusChangeDateAsc ? OrderSortState.
 0551        }
 552        public async Task<IEnumerable<Order>> ApplySortOrder(IEnumerable<Order> orders, OrderSortState sortOrder)
 553        {
 0554            await Task.CompletedTask;
 0555            return sortOrder switch
 0556            {
 557                OrderSortState.ShipmentNumberAsc => orders.OrderBy(o => o.ShipmentNumber),
 558                OrderSortState.ShipmentNumberDesc => orders.OrderByDescending(o => o.ShipmentNumber),
 0559
 560                OrderSortState.ProcessingDateAsc => orders.OrderBy(o => o.ProcessingDate),
 561                OrderSortState.ProcessingDateDesc => orders.OrderByDescending(o => o.ProcessingDate),
 0562
 563                OrderSortState.ShippingDateAsc => orders.OrderBy(o => o.ShippingDate),
 564                OrderSortState.ShippingDateDesc => orders.OrderByDescending(o => o.ShippingDate),
 0565
 566                OrderSortState.StatusAsc => orders.OrderBy(o => o.Status),
 567                OrderSortState.StatusDesc => orders.OrderByDescending(o => o.Status),
 0568
 569                OrderSortState.AppStatusIdAsc => orders.OrderBy(o => o.AppStatus?.Name ?? string.Empty),
 570                OrderSortState.AppStatusIdDesc => orders.OrderByDescending(o => o.AppStatus?.Name ?? string.Empty),
 0571
 572                OrderSortState.ShipmentAmountAsc => orders.OrderBy(o => o.ShipmentAmount),
 573                OrderSortState.ShipmentAmountDesc => orders.OrderByDescending(o => o.ShipmentAmount),
 0574
 575                OrderSortState.ProductNameAsc => orders.OrderBy(o => o.ProductName),
 576                OrderSortState.ProductNameDesc => orders.OrderByDescending(o => o.ProductName),
 0577
 578                OrderSortState.ArticleAsc => orders.OrderBy(o => o.ProductKey),
 579                OrderSortState.ArticleDesc => orders.OrderByDescending(o => o.ProductKey),
 0580
 581                OrderSortState.PriceAsc => orders.OrderBy(o => o.Price),
 582                OrderSortState.PriceDesc => orders.OrderByDescending(o => o.Price),
 0583
 584                OrderSortState.QuantityAsc => orders.OrderBy(o => o.Quantity),
 585                OrderSortState.QuantityDesc => orders.OrderByDescending(o => o.Quantity),
 0586
 587                OrderSortState.ShipmentWarehouseIdAsc => orders.OrderBy(o => o.ShipmentWarehouseId),
 588                OrderSortState.ShipmentWarehouseIdDesc => orders.OrderByDescending(o => o.ShipmentWarehouseId),
 0589
 590                OrderSortState.СurrencyIdAsc => orders.OrderBy(o => o.СurrencyId),
 591                OrderSortState.СurrencyIdDesc => orders.OrderByDescending(o => o.СurrencyId),
 0592
 593                OrderSortState.SupplierAsc => orders.OrderBy(o => o.Supplier?.Name ?? string.Empty),
 594                OrderSortState.SupplierDesc => orders.OrderByDescending(o => o.Supplier?.Name ?? string.Empty),
 0595
 596                OrderSortState.PurchasePriceAsc => orders.OrderBy(o => o.PurchasePrice),
 597                OrderSortState.PurchasePriceDesc => orders.OrderByDescending(o => o.PurchasePrice),
 0598
 599                OrderSortState.ProductInfoIdAsc => orders.OrderBy(o => o.ProductInfoId),
 600                OrderSortState.ProductInfoIdDesc => orders.OrderByDescending(o => o.ProductInfoId),
 0601
 602                OrderSortState.MinOzonCommissionAsc => orders.OrderBy(o => o.MinOzonCommission),
 603                OrderSortState.MinOzonCommissionDesc => orders.OrderByDescending(o => o.MinOzonCommission),
 0604
 605                OrderSortState.MaxOzonCommissionAsc => orders.OrderBy(o => o.MaxOzonCommission),
 606                OrderSortState.MaxOzonCommissionDesc => orders.OrderByDescending(o => o.MaxOzonCommission),
 0607
 608                OrderSortState.ProfitAsc => orders.OrderBy(o => o.MinProfit),
 609                OrderSortState.ProfitDesc => orders.OrderByDescending(o => o.MinProfit),
 0610
 611                OrderSortState.CurrentPriceAsc => orders.OrderBy(o => o.ProductInfo?.CurrentPriceWithDiscount),
 612                OrderSortState.CurrentPriceDesc => orders.OrderByDescending(o => o.ProductInfo?.CurrentPriceWithDiscount
 0613
 614                OrderSortState.VolumeAsc => orders.OrderBy(o => o.ProductInfo?.VolumetricWeight),
 615                OrderSortState.VolumeDesc => orders.OrderByDescending(o => o.ProductInfo?.VolumetricWeight),
 0616
 617                OrderSortState.DiscountAsc => orders.OrderBy(o => o.MinDiscount),
 618                OrderSortState.DiscountDesc => orders.OrderByDescending(o => o.MinDiscount),
 0619
 620                OrderSortState.DeliveryCityAsc => orders.OrderBy(o => o.DeliveryCity),
 621                OrderSortState.DeliveryCityDesc => orders.OrderByDescending(o => o.DeliveryCity),
 0622
 623                OrderSortState.CategoryAsc => orders.OrderBy(o => o.NewCategory),
 624                OrderSortState.CategoryDesc => orders.OrderByDescending(o => o.NewCategory),
 0625
 626                OrderSortState.OrderNumberToSupplierAsc => orders.OrderBy(o => o.OrderNumberToSupplier),
 627                OrderSortState.OrderNumberToSupplierDesc => orders.OrderByDescending(o => o.OrderNumberToSupplier),
 0628
 629                OrderSortState.OzonClientAsc => orders.OrderBy(o => o.OzonClient?.Name ?? string.Empty),
 630                OrderSortState.OzonClientDesc => orders.OrderByDescending(o => o.OzonClient?.Name ?? string.Empty),
 0631
 0632                OrderSortState.ManufacturerAsc => orders
 633                    .OrderBy(o => o.EtProducer?.Name ?? string.Empty)
 634                    .ThenBy(o => o.ProductKey ?? string.Empty),
 0635                OrderSortState.ManufacturerDesc => orders
 636                    .OrderByDescending(o => o.EtProducer?.Name ?? string.Empty)
 637                    .ThenBy(o => o.ProductKey ?? string.Empty),
 0638
 639                OrderSortState.DeliveryPeriodAsc => orders.OrderBy(x => x.DeliveryPeriodDay),
 640                OrderSortState.DeliveryPeriodDesc => orders.OrderByDescending(x => x.DeliveryPeriodDay),
 0641
 642                OrderSortState.CostPriceAsc => orders.OrderBy(o => o.CostPrice),
 643                OrderSortState.CostPriceDesc => orders.OrderByDescending(o => o.CostPrice),
 0644
 645                OrderSortState.TimeLeftAsc => orders.OrderBy(o => o.TimeLeftDay),
 646                OrderSortState.TimeLeftDesc => orders.OrderByDescending(o => o.TimeLeftDay),
 0647
 648                OrderSortState.LastStatusChangeDateAsc => orders.OrderBy(o => o.LastStatusChangeDate),
 649                OrderSortState.LastStatusChangeDateDesc => orders.OrderByDescending(o => o.LastStatusChangeDate),
 0650
 0651                _ => orders
 0652            };
 0653        }
 654        public void SaveSortStateCookie(OrderSortState sortOrder)
 655        {
 0656            if (sortOrder != OrderSortState.StandardState)
 657            {
 0658                Response.Cookies.Delete("SortState");
 0659                Response.Cookies.Append("SortState", sortOrder.ToString());
 660            }
 0661        }
 662        private OrderSortState GetSortStateCookie()
 663        {
 0664            var sortStateCookie = Request.Cookies["SortState"];
 0665            if (!string.IsNullOrEmpty(sortStateCookie) && Enum.TryParse<OrderSortState>(sortStateCookie, out var savedSo
 666            {
 0667                return savedSortState;
 668            }
 0669            return OrderSortState.StandardState;
 670        }
 671        public async Task<IActionResult> DelSortStateCookieForV2()
 672        {
 0673            await Task.CompletedTask;
 0674            Response.Cookies.Delete("SortState");
 0675            Response.Cookies.Append("SortState", OrderSortState.StandardState.ToString());
 0676            return RedirectToAction("Index");
 0677        }
 678    }
 679
 680
 681}

Methods/Properties

.ctor(Services.DataServices.TransactionDataServices,Services.DataServices.OrdersDataServices,Services.CacheServices.Cache.OzonOrdersCache.TransactionCache,Services.CacheServices.Cache.OzonOrdersCache.OrderCache,Services.FiltersServices.DataFilterManagers.TransactionDataFilterManager,Microsoft.AspNetCore.Identity.UserManager`1<OzonRepositories.Context.Identity.CustomIdentityUser>,Services.DataServices.AppStatusDataServices,Services.DataServices.SupplierDataServices,Services.FiltersServices.DataFilterManagers.OrderDataFilterManager,Services.CacheServices.Cache.CacheUpdater`1<OzonDomains.Models.Transaction>,Services.DataServices.OzonClientServices,Services.DataServices.WarehouseDataServices,OzonRepositories.Context.ApplicationDbContext,Services.ParserServices.FielParsers.ExcelExporter,Services.CacheServices.Cache.UniqueValuesCache.IUniqueValuesCache,Services.CacheServices.Cache.UserCacheService.IUserCacheService,PdfService,OzonRepositories.Data.Bitrix.BitrixStockRepository,Services.DataServices.ClientStatusDataServices,Services.DataServices.DeliveryDataServices,Services.ChannelTaskServices.IChannelTaskService)
PopulateJournalFilterViewBagAsync()
Index()
GetTransaction()
Index()
Update()
PrintTransactionToExcel(System.Int32)
StartTransactionExcelTask(System.Nullable`1<System.Int32>,System.String,System.String,System.Boolean)
PrintTransactionToPdf()
PrintTransactionTableToPdf()
PrintTransactionTableToExcel(System.String,System.String)
ParseIds(System.String)
SetSortOrderViewData(Services.FiltersServices.SortModels.OrderSortState)
ApplySortOrder()
SaveSortStateCookie(Services.FiltersServices.SortModels.OrderSortState)
GetSortStateCookie()
DelSortStateCookieForV2()