< Summary

Class:SVETA.Api.Controllers.ReportsController
Assembly:SVETA.Api
File(s):/opt/dev/sveta_api_build/SVETA.Api/Controllers/ReportsController.cs
Covered lines:0
Uncovered lines:572
Coverable lines:572
Total lines:870
Line coverage:0% (0 of 572)
Covered branches:0
Total branches:135
Branch coverage:0% (0 of 135)

Metrics

MethodLine coverage Branch coverage
.ctor(...)0%100%
Reports()0%100%
Reports()0%0%
GetMovementExcel()0%0%
GoodAccounting()0%0%
GoodAccuountingToFile()0%0%
GetResponseParam(...)0%0%
MoneyAccounting()0%0%
MoneyAccountingToFile()0%0%
EveryDayReport()0%0%
GetMatrixReport()0%0%
StatusReport()0%100%
DownloadPrices()0%0%

File(s)

/opt/dev/sveta_api_build/SVETA.Api/Controllers/ReportsController.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.IO;
 4using System.Linq;
 5using System.Reflection;
 6using System.Text;
 7using System.Threading.Tasks;
 8using ClosedXML.Excel;
 9using DocumentFormat.OpenXml.Wordprocessing;
 10using Microsoft.AspNetCore.Authorization;
 11using Microsoft.AspNetCore.Mvc;
 12using Microsoft.Extensions.Logging;
 13using SVETA.Api.Data.Domain;
 14using SVETA.Api.Data.DTO;
 15using SVETA.Api.Data.DTO.Reports;
 16using SVETA.Api.Data.DTO.Showcase;
 17using SVETA.Api.Helpers;
 18using SVETA.Api.Services.Interfaces;
 19using Swashbuckle.AspNetCore.Annotations;
 20using WinSolutions.Sveta.Common;
 21using WinSolutions.Sveta.Server.Data.DataModel.Entities;
 22using WinSolutions.Sveta.Server.Data.DataModel.Reports;
 23using WinSolutions.Sveta.Server.Services.Interfaces;
 24using WinSolutions.Sveta.Common.Extensions;
 25using WinSolutions.Sveta.Server.Data.DataModel.Kinds;
 26using WinSolutions.Sveta.Server.Domain;
 27
 28namespace SVETA.Api.Controllers
 29{
 30    [Authorize]
 31    [Route("api/v1/Reports")]
 32    public class ReportsController : SvetaController
 33    {
 34        private const string _routing = "api/v1/Reports";
 35
 36        private readonly ILogger<ReportsController> _logger;
 37        private readonly IReportService _reportService;
 38        private readonly IAuthenticationService _authenticationService;
 39        private readonly IDepartmentService _departmentService;
 40        private readonly IMovementWorker _movementWorker;
 41        private readonly IShowcaseWorker _showcaseWorker;
 42        private readonly IDiskStorageService _diskStorage;
 43
 44        private IEnumerable<(int, string)> reports;
 45
 46        public ReportsController(ILogger<ReportsController> logger,
 47            IReportService reportService,
 48            IAuthenticationService authenticationService,
 49            IMovementWorker movementWorker,
 50            IDepartmentService departmentService,
 51            IShowcaseWorker worker,
 52            IDiskStorageService diskStorage,
 053            IAuthenticationService authUserService) : base(logger)
 054        {
 055            _reportService = reportService;
 056            _authenticationService = authenticationService;
 057            _movementWorker = movementWorker;
 058            _departmentService = departmentService;
 059            _showcaseWorker = worker;
 060            _diskStorage = diskStorage;
 061            _logger = logger;
 062            reports = new[]
 063            {
 064                (1, "Список заявок"),
 065                (2, "Список отгрузок"),
 066                (3, "Отчет по статусам документов"),
 067                (4, "Товарный отчет"),
 068                (5, "Отчет финансовый учет"),
 069                (6, "Ежедневный отчет"),
 070                (7, "Отчет матрица")
 071                /*(8, "Отчет прайс-лист")*/
 072            };
 073        }
 74
 75        /// <summary>
 76        /// Возвращает список доступных отчетов
 77        /// </summary>
 78        /// <returns></returns>
 79        [HttpGet]
 80        [Authorize(Roles = Role.SystemOperator + "," + Role.SystemAdmin)]
 81        [SwaggerResponse(200, "Успешно", typeof(List<ReportInfoDto>))]
 82        [SwaggerResponse(403, "Ошибка прав доступа", typeof(ErrorDTO))]
 83        [SwaggerResponse(500, "Ошибка на стороне сервера", typeof(ErrorDTO))]
 84        public async Task<IActionResult> Reports()
 085        {
 086            long count = 1;
 087            var reportsName = reports
 088                .Select(d => new ReportInfoDto
 089                {
 090                    Id = d.Item1,
 091                    Name = d.Item2
 092                })
 093                .ToList();
 094            return Ok(reportsName);
 095        }
 96
 97        /// <summary>
 98        /// Общий метод для получения отчета из списка - все параметры не обязательны, набор параметров специфичен для к
 99        /// Параметр supplierId - используется в качестве contragentId в отчете GoodAccuountingToFile и MoneyAccountingT
 100        /// </summary>
 101        /// <param name="id">Идентификатор отчета</param>
 102        /// <param name="customerId">Идентификатор контрагента заказчика - для всех 0</param>
 103        /// <param name="supplierId">Идентификатор контрагента поставщика - для всех 0</param>
 104        /// <param name="receiverId">Идентификатор департамента получателя - магазин - для всех 0</param>
 105        /// <param name="senderId">Идентификатор департамента поставщика - склад - для всех 0 </param>
 106        /// <param name="categoryId">Идентификатор категории - для всех 0</param>
 107        /// <param name="movementId">Идентификатор документа - для всех 0</param>
 108        /// <param name="dateFrom">Дата начала отбора - для всех null</param>
 109        /// <param name="dateTo">Дата окончания отбора - для всех null</param>
 110        /// <param name="stateId">Идентификатор состояния записи - для всех 0</param>
 111        /// <param name="statusId">Идентификатор статуса документа - для всех 0</param>
 112        /// <param name="documentNumber">Номер документа - для всех null</param>
 113        /// <param name="sort">Тип сортировки - отличается для каждого отчета - смотри для конкретного метода</param>
 114        /// <param name="showAnonymous">Получение анонимных документов для построения списка заявок по умолчанию nonanon
 115        /// <param name="filter">Строковое значение для фильтрации по названию</param>
 116        /// <param name="page">Страница отбора по умолчанию - 1</param>
 117        /// <param name="limit">Количество для отбора - по умолчанию 10</param>
 118        /// <returns></returns>
 119        [HttpGet("{id}")]
 120        [Authorize(Roles = Role.SystemOperator + "," + Role.SystemAdmin)]
 121        [SwaggerResponse(200, "Успешно", typeof(File))]
 122        [SwaggerResponse(403, "Ошибка прав доступа", typeof(ErrorDTO))]
 123        [SwaggerResponse(500, "Ошибка на стороне сервера", typeof(ErrorDTO))]
 124        public async Task<IActionResult> Reports(long id, long customerId = 0, long supplierId = 0, long receiverId = 0,
 125            long senderId = 0, long categoryId = 0, long movementId = 0, DateTimeOffset dateFrom = default,
 126            DateTimeOffset dateTo = default, int stateId = 0, int statusId = 0, string documentNumber = default,
 127            string sort = default, string showAnonymous = default, string filter = default, int page = 1,
 128            int limit = 10)
 0129        {
 0130            return id switch
 0131            {
 0132                1 => await GetMovementExcel(movementId, customerId, receiverId, supplierId, senderId,  dateFrom,
 0133                    dateTo, stateId, statusId, documentNumber, sort, showAnonymous, 1),
 0134                2 => await GetMovementExcel(movementId, customerId, receiverId, supplierId, senderId,  dateFrom,
 0135                    dateTo, stateId, statusId, documentNumber, sort, showAnonymous, 2),
 0136                3 => await StatusReport(dateFrom, dateTo),
 0137                4 => await GoodAccuountingToFile(supplierId, categoryId, dateFrom, dateTo, sort, filter),
 0138                5 => await MoneyAccountingToFile(supplierId, dateFrom, dateTo, sort, filter),
 0139                6 => await EveryDayReport(),
 0140                7 => await GetMatrixReport(dateFrom, dateTo),
 0141                8 => await DownloadPrices(filter)
 0142            };
 0143        }
 144
 145        /// <summary>
 146        /// Возвращает отфильтрованный и отсортированный список документов
 147        /// </summary>
 148        /// <remarks>author: aabelentsov, oboligatov</remarks>
 149        /// <param name="id">Идентификатор документа (0 для всех)</param>
 150        /// <param name="documentNumber">Номер документа (null для всех)</param>
 151        /// <param name="customerId">Идентификтор заказчика - (контрагент) (0 для всех)</param>
 152        /// <param name="receiverId">Идентификтор получателя - (магазин) (0 для всех)</param>
 153        /// <param name="supplierId">Идентификтор поставщика  - (контрагент) (0 для всех)</param>
 154        /// <param name="fromDate">Дата начала отбора (null для всех)</param>
 155        /// <param name="toDate">Дата окончания отбора (null для всех)</param>
 156        /// <param name="statusId">Статус документа - 0 для всех</param>
 157        /// <param name="stateId">Состояние документа - 0 для всех</param>
 158        /// <param name="sort">сортировка по умолчанию по id - id|desc,created_on,created_on|desc,state,state|desc,statu
 159        /// <param name="showAnonymous">отображение анонимных заявок - по умолчанию nonanonymous, anonymousonly - только
 160        /// <param name="kind">Тип документов - MovementTypes - 1 - Заявки, 2 - Отгрузки</param>
 161        /// <returns></returns>
 162        [HttpGet("ExcelShipments")]
 163        [SwaggerResponse(200, "Успешно", typeof(File))]
 164        [SwaggerResponse(400, "Ошибка валидации входных параметров", typeof(ErrorDTO))]
 165        [SwaggerResponse(403, "Ошибка прав доступа", typeof(ErrorDTO))]
 166        [SwaggerResponse(500, "Ошибка на стороне сервера", typeof(ErrorDTO))]
 167        [Authorize(Roles = Role.ShopOwner + "," + Role.ShopMerchandiser + "," + Role.ShopSeller + "," + Role.SystemOpera
 168        public async Task<IActionResult> GetMovementExcel(long id = 0, long customerId = 0, long receiverId = 0, long su
 169            DateTimeOffset fromDate = default, DateTimeOffset toDate = default, int stateId = 0, int statusId = 0, strin
 170            string sort = null, string showAnonymous = "nonanonymous", long kind = 1)
 0171        {
 0172            documentNumber = documentNumber.NormalizeName();
 0173            var movementKind = kind switch
 0174            {
 0175                (long) MovementKind.Order => MovementKind.Order,
 0176                (long) MovementKind.Shipment => MovementKind.Shipment,
 0177                _ => MovementKind.Order
 0178            };
 0179            var requestParam = new MovementParam(id, customerId, receiverId, supplierId,senderId, fromDate.GetStartOfDat
 0180                toDate.GetEndOfDate(), movementKind, stateId, statusId, documentNumber,0, Int32.MaxValue,
 0181                sort, default, showAnonymous, true);
 0182            PaginatedData<List<MovementDTO>> orders =  await _movementWorker.GetMovements(requestParam);
 0183            using var book = new XLWorkbook();
 0184            var worksheet = book.Worksheets.Add("Report");
 0185            var currentRow = 1;
 0186            worksheet.Cell(currentRow, 1).Value = "№п/п";
 0187            worksheet.Cell(currentRow, 2).Value = "Дата создания";
 0188            worksheet.Cell(currentRow, 3).Value = "Номер документа";
 0189            worksheet.Cell(currentRow, 4).Value = "Заказчик";
 0190            worksheet.Cell(currentRow, 5).Value = "Поставщик";
 0191            worksheet.Cell(currentRow, 6).Value = "Получатель";
 0192            worksheet.Cell(currentRow, 7).Value = "Отправитель";
 0193            worksheet.Cell(currentRow, 8).Value = "Статус";
 0194            worksheet.Cell(currentRow, 9).Value = "Сумма";
 0195            worksheet.Cell(currentRow, 10).Value = "Количество позиций";
 0196            worksheet.Cell(currentRow, 11).Value = "Получение заказа";
 0197            int count = 1;
 0198            foreach (var order in orders.Result)
 0199            {
 0200                currentRow++;
 0201                worksheet.Cell(currentRow, 1).Value = count;
 0202                worksheet.Cell(currentRow, 2).Value = order.CreationDateTime;
 0203                worksheet.Cell(currentRow, 3).Value = order.DocumentNumber;
 0204                worksheet.Cell(currentRow, 4).Value = order.Customer.ShortName;
 0205                worksheet.Cell(currentRow, 5).Value = order.Supplier.ShortName;
 0206                worksheet.Cell(currentRow, 6).Value = order.Receiver.Name;
 0207                worksheet.Cell(currentRow, 7).Value = order.Sender.Name;
 0208                worksheet.Cell(currentRow, 8).Value = order.MovementStatus.Name;
 0209                worksheet.Cell(currentRow, 9).Value = order.Sum;
 0210                worksheet.Cell(currentRow, 10).Value = order.ItemsCount;
 0211                worksheet.Cell(currentRow, 11).Value = order.DeliveryType?.Name;
 0212            }
 0213            using var stream = new MemoryStream();
 0214            book.SaveAs(stream);
 0215            var content = stream.ToArray();
 0216            return File(content, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
 0217                "movementListList.xlsx");
 0218        }
 219
 220        /// <summary>
 221        /// Строит отчет для склада по категории товара
 222        /// </summary>
 223        /// <param name="contragentId">Контрагент с типом Дистрибьютор владеющий складом, для которого строится отчет</p
 224        /// <param name="categoryId">Категория товара - 0 для всех</param>
 225        /// <param name="dateFrom">дата начала отбора - по умолчанию все</param>
 226        /// <param name="dateTo">дата окончания отбора - по умолчанию все</param>
 227        /// <param name="sort">сортировка по умолчанию по имени товара - good, good|desc, category, category|desc, sum, 
 228        /// <param name="filter">Фильтр по наименованию товара - по умолчанию для всех</param>
 229        /// <param name="page">Страница отбора - 1 по умолчанию</param>
 230        /// <param name="limit">Лимит отбора - 10 по умолчанию</param>
 231        /// <returns></returns>
 232        [Authorize(Roles = Role.SystemOperator + "," + Role.SystemAdmin)]
 233        [HttpGet("GoodAccounting/{contragentId}/{categoryId}")]
 234        [SwaggerResponse(200, "Успешно", typeof(BaseResponseDTO<GoodAccount>))]
 235        [SwaggerResponse(403, "Ошибка прав доступа", typeof(ErrorDTO))]
 236        [SwaggerResponse(500, "Ошибка на стороне сервера", typeof(ErrorDTO))]
 237        public async Task<IActionResult> GoodAccounting(long contragentId, long categoryId, DateTimeOffset dateFrom = de
 238            string sort = default, string filter = default, int page = 1, int limit = 10)
 0239        {
 0240            filter = filter.NormalizeName();
 0241            if (!_authenticationService.IsUserPlatform())
 0242                contragentId = _authenticationService.ContragentId;
 0243            var result = await _reportService.GoodAccountingReport(contragentId, categoryId, dateFrom.GetStartOfDate(), 
 0244                sort, filter,  page, limit);
 0245            var param = GetResponseParam(dateFrom, dateTo);
 0246            var rout = _routing + $"/GoodAccounting/{contragentId}/{categoryId}";
 0247            var response = new BaseResponseDTO<GoodAccount>(rout, page, limit, result.TotalFilteredCount,
 0248                result.TotalCount, sort, param: param)
 0249            {
 0250                Data = result.Result ?? new List<GoodAccount>()
 0251            };
 0252            return Ok(response);
 0253        }
 254
 255        /// <summary>
 256        /// Отчет для склада по категории товара в файл
 257        /// </summary>
 258        /// <param name="contragentId">Контрагент с типом Дистрибьютор владеющий складом, для которого строится отчет</p
 259        /// <param name="categoryId">Категория товара - 0 для всех</param>
 260        /// <param name="dateFrom">дата начала отбора - по умолчанию все</param>
 261        /// <param name="dateTo">дата окончания отбора - по умолчанию все</param>
 262        /// <param name="sort">сортировка по умолчанию по имени товара - good, good|desc, category, category|desc, sum, 
 263        /// <param name="filter">Фильтр по наименованию товара - по умолчанию для всех</param>
 264        /// <param name="fileType">Тип файла для выгрузки - по умолчанию excel | excel, csv</param>
 265        /// <returns></returns>
 266        [Authorize(Roles = Role.SystemOperator + "," + Role.SystemAdmin)]
 267        [HttpGet("GoodAccountingToFile/{contragentId}/{categoryId}")]
 268        [SwaggerResponse(200, "Успешно", typeof(File))]
 269        [SwaggerResponse(403, "Ошибка прав доступа", typeof(ErrorDTO))]
 270        [SwaggerResponse(500, "Ошибка на стороне сервера", typeof(ErrorDTO))]
 271        public async Task<IActionResult> GoodAccuountingToFile(long contragentId, long categoryId,
 272            DateTimeOffset dateFrom = default, DateTimeOffset dateTo = default,
 273            string sort = default, string filter = default, string fileType = "excel")
 0274        {
 0275            filter = filter.NormalizeName();
 0276            if (!_authenticationService.IsUserPlatform())
 0277                contragentId = _authenticationService.ContragentId;
 0278            var result = await _reportService.GoodAccountingReportWithoutPagination(contragentId, categoryId, dateFrom.G
 0279                sort, filter);
 0280            if (result != null)
 0281            {
 0282                switch (fileType.ToLower())
 283                {
 284                    case "csv":
 0285                   {
 0286                       StringBuilder builder = new StringBuilder();
 0287                       builder.Append(
 0288                           "Категория;Товар;Количество продаж;Количество проданных штук;Сумма;Количество покупателей\n")
 0289                       foreach (var item in result)
 0290                       {
 0291                           builder.Append(item.CategoryName);
 0292                           builder.Append(";");
 0293                           builder.Append(item.GoodName);
 0294                           builder.Append(";");
 0295                           builder.Append(item.SellCount);
 0296                           builder.Append(";");
 0297                           builder.Append(item.SellItemCount);
 0298                           builder.Append(";");
 0299                           builder.Append(item.Sum);
 0300                           builder.Append(";");
 0301                           builder.Append(item.BuyerCount);
 0302                           builder.Append("\n");
 0303                       }
 0304                       using var stream = new MemoryStream();
 0305                       StreamWriter writer = new StreamWriter(stream);
 0306                       writer.Write(builder.ToString());
 0307                       writer.Close();
 0308                       var content = stream.ToArray();
 0309                       return File(content, "text/csv",
 0310                           "accountReport.csv");
 311                   }
 312                    default:
 0313                    {
 0314                        using var book = new XLWorkbook();
 0315                        var worksheet = book.Worksheets.Add("Report");
 0316                        var currentRow = 1;
 0317                        worksheet.Cell(currentRow, 1).Value = "Категория";
 0318                        worksheet.Cell(currentRow, 2).Value = "Товар";
 0319                        worksheet.Cell(currentRow, 3).Value = "Количество продаж";
 0320                        worksheet.Cell(currentRow, 4).Value = "Количество проданных штук";
 0321                        worksheet.Cell(currentRow, 5).Value = "Сумма";
 0322                        worksheet.Cell(currentRow, 6).Value = "Количество покупателей";
 0323                        foreach (var item in result)
 0324                        {
 0325                            currentRow++;
 0326                            worksheet.Cell(currentRow, 1).Value = item.CategoryName;
 0327                            worksheet.Cell(currentRow, 2).Value = item.GoodName;
 0328                            worksheet.Cell(currentRow, 3).Value = item.SellCount;
 0329                            worksheet.Cell(currentRow, 4).Value = item.SellItemCount;
 0330                            worksheet.Cell(currentRow, 5).Value = item.Sum;
 0331                            worksheet.Cell(currentRow, 6).Value = item.BuyerCount;
 0332                        }
 333
 0334                        using var stream = new MemoryStream();
 0335                        book.SaveAs(stream);
 0336                        var content = stream.ToArray();
 0337                        return File(content, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
 0338                            "accountReport.xlsx");
 339                    }
 340                }
 341            }
 0342            return NoContent();
 0343        }
 344
 345        private string GetResponseParam(DateTimeOffset dateFrom = default, DateTimeOffset dateTo = default)
 0346        {
 0347            StringBuilder param = new StringBuilder();
 348            try
 0349            {
 0350                if (dateFrom != DateTime.MinValue)
 0351                    param.Append($"&dateFrom={dateFrom.ToISOString()}");
 0352                if (dateTo != DateTime.MinValue)
 0353                    param.Append($"&dateTo={dateTo.ToISOString()}");
 0354            }
 0355            catch (Exception e)
 0356            {
 0357                _logger.LogError(e.Message + " " + e.StackTrace);
 0358            }
 0359            return param.ToString();
 0360        }
 361
 362        /// <summary>
 363        /// Отчет Фин. учет
 364        /// </summary>
 365        /// <param name="contragentId">Контрагент, с типом дистрибьютор, владеющий складом - 0 для всех </param>
 366        /// <param name="dateFrom">Дата начала отборки - по умолчанию за все время</param>
 367        /// <param name="dateTo">Дата окончания отборки - по умолчанию за все время</param>
 368        /// <param name="sort">сортировка - по умолчани по customer - customer, customer|desc, holdedsum, holdedsum|desc
 369        /// <param name="filter">Поиск по имени покупателя</param>
 370        /// <returns></returns>
 371        [Authorize(Roles = Role.SystemOperator + "," + Role.SystemAdmin)]
 372        [HttpGet("MoneyAccounting/{contragentId}")]
 373        [SwaggerResponse(200, "Успешно", typeof(MoneyAccountReportDto))]
 374        [SwaggerResponse(403, "Ошибка прав доступа", typeof(ErrorDTO))]
 375        [SwaggerResponse(500, "Ошибка на стороне сервера", typeof(ErrorDTO))]
 376        public async Task<IActionResult> MoneyAccounting(long contragentId, DateTimeOffset dateFrom = default,
 377            DateTimeOffset dateTo = default,
 378            string sort = default, string filter = default, int page = 1, int limit = 10)
 0379        {
 0380            filter = filter.NormalizeName();
 0381            var df = dateFrom != default ? dateFrom.GetStartOfDate() : new DateTime(DateTime.Now.Year, 1, 1);
 0382            var dt = dateTo != default ? dateTo.GetEndOfDate() : DateTime.Now.EndOfDate();
 0383            var result = await _reportService.MoneyAccountingReport(contragentId,
 0384                df, dt, sort, filter, page, limit);
 0385            var param = $"MoneyAccounting/{contragentId}{GetResponseParam(df, dt)}";
 0386            var rout = _routing + $"/MoneyAccounting/{contragentId}";
 0387            var pagination = new BasePaginationResponseDto(rout, page, limit,
 0388                result.Pagination.TotalFilteredCount,
 0389                result.Pagination.TotalCount, sort, param: param);
 0390            var response = new MoneyAccountReportDto
 0391            {
 0392                Data = result.Data,
 0393                Pagination = pagination,
 0394                Summary = result.MoneyAccountReportSummary
 0395            };
 0396            return Ok(response);
 0397        }
 398
 399
 400
 401        /// <summary>
 402        /// Отчет фин учет в файл
 403        /// </summary>
 404        /// <param name="contragentId">Контрагент, с типом дистрибьютор, владеющий складом </param>
 405        /// <param name="dateFrom">Дата начала отборки - по умолчанию за все время</param>
 406        /// <param name="dateTo">Дата окончания отборки - по умолчанию за все время</param>
 407        /// <param name="sort">сортировка - по умолчани по customer - customer, customer|desc, holdedsum, holdedsum|desc
 408        /// <param name="filter">Поиск по имени покупателя</param>
 409        /// <param name="fileType">Тип файла для выгрузки - по умолчанию excel | excel, csv</param>
 410        /// <returns></returns>
 411        [Authorize(Roles = Role.SystemOperator + "," + Role.SystemAdmin)]
 412        [HttpGet("MoneyAccountingToFile/{contragentId}")]
 413        [SwaggerResponse(200, "Успешно", typeof(File))]
 414        [SwaggerResponse(403, "Ошибка прав доступа", typeof(ErrorDTO))]
 415        [SwaggerResponse(500, "Ошибка на стороне сервера", typeof(ErrorDTO))]
 416        public async Task<IActionResult> MoneyAccountingToFile(long contragentId, DateTimeOffset dateFrom = default,
 417            DateTimeOffset dateTo = default,
 418            string sort = default, string filter = default, string fileType = "excel")
 0419        {
 0420            filter = filter.NormalizeName();
 0421            var df = dateFrom != default ? dateFrom.GetStartOfDate() : new DateTime(DateTime.Now.Year, 1, 1);
 0422            var dt = dateTo != default ? dateTo.GetEndOfDate() : DateTime.Now.EndOfDate();
 0423            var result = await _reportService.MoneyAccountingReportWithoutPagination(contragentId,
 0424                df, dt, sort, filter);
 0425            if (result == null || result.Count == 0)
 0426                return NoContent();
 0427            switch (fileType.ToLower())
 428            {
 429                case "csv":
 0430                {
 0431                    StringBuilder builder = new StringBuilder();
 0432                    builder.Append(
 0433                        "Название покупателя;Количество заявок;Отгрузок в работе;Отгрузок принято;Отгрузок отклонено;Сум
 0434                    foreach (var item in result)
 0435                    {
 0436                        builder.Append(item.BuyerName);
 0437                        builder.Append(";");
 0438                        builder.Append(item.OrderCount);
 0439                        builder.Append(";");
 0440                        builder.Append(item.ShipmentInWorkCount);
 0441                        builder.Append(";");
 0442                        builder.Append(item.ShipmentReceivedCount);
 0443                        builder.Append(";");
 0444                        builder.Append(item.ShipmentRejectedCount);
 0445                        builder.Append(";");
 0446                        builder.Append(item.HoldedMoneySum);
 0447                        builder.Append(";");
 0448                        builder.Append(item.RejectedMoneySum);
 0449                        builder.Append(";");
 0450                        builder.Append(item.AcceptedMoneySum);
 0451                        builder.Append("\n");
 0452                    }
 0453                    using var stream = new MemoryStream();
 0454                    StreamWriter writer = new StreamWriter(stream);
 0455                    writer.Write(builder.ToString());
 0456                    writer.Close();
 0457                    var content = stream.ToArray();
 0458                    return File(content, "text/csv",
 0459                        "moneyReport.csv");
 460                }
 461                default:
 0462                {
 0463                    using var book = new XLWorkbook();
 0464                    var worksheet = book.Worksheets.Add("Report");
 0465                    var currentRow = 1;
 0466                    worksheet.Cell(currentRow, 1).Value = "Название покупателя";
 0467                    worksheet.Cell(currentRow, 2).Value = "Количество заявок";
 0468                    worksheet.Cell(currentRow, 3).Value = "Отгрузок в работе";
 0469                    worksheet.Cell(currentRow, 4).Value = "Отгрузок принято";
 0470                    worksheet.Cell(currentRow, 5).Value = "Отгрузок отклонено";
 0471                    worksheet.Cell(currentRow, 6).Value = "Сумма зарезервированных средств";
 0472                    worksheet.Cell(currentRow, 7).Value = "Сумма отклоненных средств";
 0473                    worksheet.Cell(currentRow, 8).Value = "Сумма принятых средств";
 0474                    foreach (var item in result)
 0475                    {
 0476                        currentRow++;
 0477                        worksheet.Cell(currentRow, 1).Value =item.BuyerName;
 0478                        worksheet.Cell(currentRow, 2).Value =item.OrderCount;
 0479                        worksheet.Cell(currentRow, 3).Value =item.ShipmentInWorkCount;
 0480                        worksheet.Cell(currentRow, 4).Value =item.ShipmentReceivedCount;
 0481                        worksheet.Cell(currentRow, 5).Value =item.ShipmentRejectedCount;
 0482                        worksheet.Cell(currentRow, 6).Value =item.HoldedMoneySum;
 0483                        worksheet.Cell(currentRow, 7).Value =item.RejectedMoneySum;
 0484                        worksheet.Cell(currentRow, 8).Value =item.AcceptedMoneySum;
 0485                    }
 486
 0487                    using var stream = new MemoryStream();
 0488                    book.SaveAs(stream);
 0489                    var content = stream.ToArray();
 0490                    return File(content, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
 0491                        "moneyReport.xlsx");
 492                }
 493
 494            }
 0495        }
 496
 497        /// <summary>
 498        /// Выгрузка ежедневного отчета
 499        /// </summary>
 500        /// <param name="fileType">Тип файла выгрузки -по умолчанию excel - excel, csv</param>
 501        /// <returns></returns>
 502        [Authorize(Roles = Role.SystemOperator + "," + Role.SystemAdmin)]
 503        [HttpGet("EveryDayReport")]
 504        [SwaggerResponse(200, "Успешно", typeof(File))]
 505        [SwaggerResponse(403, "Ошибка прав доступа", typeof(ErrorDTO))]
 506        [SwaggerResponse(500, "Ошибка на стороне сервера", typeof(ErrorDTO))]
 507        public async Task<IActionResult> EveryDayReport(string fileType = "excel")
 0508        {
 0509            var result = _reportService.EveryDayReport();
 0510            if (result == null || result.Count == 0)
 0511                return NoContent();
 0512            switch (fileType.ToLower())
 513            {
 514                case "csv":
 0515                {
 0516                    StringBuilder builder = new StringBuilder();
 0517                    builder.Append(
 0518                        "№п/п;Наименование покупателя;ИНН покупателя;№ заказа;Дата заказа;Сумма заказа;Статус (все списк
 0519                    for (int i = 1; i < result.Count(); i++)
 0520                    {
 0521                        builder.Append(i);
 0522                        builder.Append(";");
 0523                        builder.Append(result[i].Name);
 0524                        builder.Append(";");
 0525                        builder.Append(result[i].Inn);
 0526                        builder.Append(";");
 0527                        builder.Append(result[i].MovementId);
 0528                        builder.Append(";");
 0529                        builder.Append(result[i].Sum);
 0530                        builder.Append(";");
 0531                        builder.Append(result[i].Statuses);
 0532                        builder.Append(";");
 0533                        builder.Append(result[i].Comment);
 0534                        builder.Append("\n");
 0535                    }
 536
 0537                    using var stream = new MemoryStream();
 0538                    StreamWriter writer = new StreamWriter(stream);
 0539                    writer.Write(builder.ToString());
 0540                    writer.Close();
 0541                    var content = stream.ToArray();
 0542                    return File(content, "text/csv",
 0543                        "everyDayReport.csv");
 544                }
 545                default:
 0546                {
 0547                    using var book = new XLWorkbook();
 0548                    var worksheet = book.Worksheets.Add("Report");
 0549                    var currentRow = 1;
 0550                    worksheet.Cell(currentRow, 1).Value = "№п/п";
 0551                    worksheet.Cell(currentRow, 2).Value = "Наименование покупателя";
 0552                    worksheet.Cell(currentRow, 3).Value = "ИНН покупателя";
 0553                    worksheet.Cell(currentRow, 4).Value = "№ заказа";
 0554                    worksheet.Cell(currentRow, 5).Value = "Дата заказа";
 0555                    worksheet.Cell(currentRow, 6).Value = "Сумма заказа";
 0556                    worksheet.Cell(currentRow, 7).Value = "Статус (все списком)";
 0557                    worksheet.Cell(currentRow, 8).Value = "Комментарий в системе";
 0558                    for (int i = 1; i < result.Count(); i++)
 0559                    {
 0560                        currentRow++;
 0561                        worksheet.Cell(currentRow, 1).Value = i;
 0562                        worksheet.Cell(currentRow, 2).Value = result[i].Name;
 0563                        worksheet.Cell(currentRow, 3).Value = result[i].Inn;
 0564                        worksheet.Cell(currentRow, 4).Value = result[i].MovementId;
 0565                        worksheet.Cell(currentRow, 5).Value = result[i].Date.ToMoscowTime()
 0566                            .ToString("yyyy-MM-dd HH:mm:ss");
 0567                        worksheet.Cell(currentRow, 6).Value = result[i].Sum;
 0568                        worksheet.Cell(currentRow, 7).Value = result[i].Statuses;
 0569                        worksheet.Cell(currentRow, 8).Value = result[i].Comment;
 0570                    }
 571
 0572                    using var stream = new MemoryStream();
 0573                    book.SaveAs(stream);
 0574                    var content = stream.ToArray();
 0575                    return File(content, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
 0576                        "everyDayReport.xlsx");
 577                }
 578            }
 0579        }
 580
 581        /// <summary>
 582        /// Выгрзука отчета матрицы
 583        /// </summary>
 584        /// <param name="dateFrom">Дата начала отбора включая дату - по умолчанию за все время</param>
 585        /// <param name="dateTo">Дата окончания отбора включая дату - по умолчанию за все время</param>
 586        /// <param name="fileType">Тип файла выгрузки -по умолчанию excel - excel, csv</param>
 587        /// <returns></returns>
 588        [Authorize(Roles = Role.SystemOperator + "," + Role.SystemAdmin)]
 589        [HttpGet("MatrixReport")]
 590        [SwaggerResponse(200, "Успешно", typeof(File))]
 591        [SwaggerResponse(403, "Ошибка прав доступа", typeof(ErrorDTO))]
 592        [SwaggerResponse(500, "Ошибка на стороне сервера", typeof(ErrorDTO))]
 593        public async Task<IActionResult> GetMatrixReport(DateTimeOffset dateFrom = default, DateTimeOffset dateTo = defa
 0594        {
 0595            var result = _reportService.GetMatrixReport(dateFrom.GetStartOfDate(), dateTo.GetEndOfDate());
 0596            if (result == null || result.Count == 0)
 0597                return NoContent();
 598
 0599            switch (fileType.ToLower())
 600            {
 601                case "csv":
 0602                {
 0603                    StringBuilder builder = new StringBuilder();
 0604                    builder.Append(
 0605                        "№п/п;Наименование покупателя;ИНН покупателя;№ заказа;Дата заказа;Сумма заказа;Черновик(Заявка);
 0606                        "В очереди на обработку(Заявка);В обработке(Заявка);Отказ(Заявка);Обработана(Заявка);Черновик(От
 0607                        "Ожидает оплаты(Отгрузка);Сборка(Отгрузка);Готово к выдаче(Отгрузка);Коректировка(Отгрузка);" +
 0608                        "Выдано(Отгрузка);Получено(Отгрузка);Отказ покупателя(Отгрузка);Отказ поставщика(Отгрузка);Отказ
 0609                        "Претензия в обработке;Претензия подтверждено;Претензия отклонено\n");
 0610                    for (int i = 1; i < result.Count(); i++)
 0611                    {
 0612                        builder.Append(i+1);
 0613                        builder.Append(";");
 0614                        builder.Append(result[i].Name);
 0615                        builder.Append(";");
 0616                        builder.Append(result[i].Inn);
 0617                        builder.Append(";");
 0618                        builder.Append(result[i].MovementId);
 0619                        builder.Append(";");
 0620                        builder.Append(result[i].Sum);
 0621                        builder.Append(";");
 0622                        builder.Append(result[i].OrderDraft);
 0623                        builder.Append(";");
 0624                        builder.Append(result[i].OrderInQueue);
 0625                        builder.Append(";");
 0626                        builder.Append(result[i].OrderInProgress);
 0627                        builder.Append(";");
 0628                        builder.Append(result[i].OrderReject);
 0629                        builder.Append(";");
 0630                        builder.Append(result[i].OrderFinished);
 0631                        builder.Append(";");
 0632                        builder.Append(result[i].ShipmentDraft);
 0633                        builder.Append(";");
 0634                        builder.Append(result[i].ShipmentPaimentAwating);
 0635                        builder.Append(";");
 0636                        builder.Append(result[i].ShipmentPicking);
 0637                        builder.Append(";");
 0638                        builder.Append(result[i].ShipmentReadyToShip);
 0639                        builder.Append(";");
 0640                        builder.Append(result[i].ShipmentCorrection);
 0641                        builder.Append(";");
 0642                        builder.Append(result[i].ShipmentShipped);
 0643                        builder.Append(";");
 0644                        builder.Append(result[i].ShipmentReceived);
 0645                        builder.Append(";");
 0646                        builder.Append(result[i].ShipmentCustomerReject);
 0647                        builder.Append(";");
 0648                        builder.Append(result[i].ShipmentSupplierReject);
 0649                        builder.Append(";");
 0650                        builder.Append(result[i].ShipmentReject);
 0651                        builder.Append(";");
 0652                        builder.Append(result[i].ClaimInProgress);
 0653                        builder.Append(";");
 0654                        builder.Append(result[i].ClaimAccedpted);
 0655                        builder.Append(";");
 0656                        builder.Append(result[i].ClaimDeclined);
 0657                        builder.Append("\n");
 0658                    }
 659
 0660                    using var stream = new MemoryStream();
 0661                    StreamWriter writer = new StreamWriter(stream);
 0662                    writer.Write(builder.ToString());
 0663                    writer.Close();
 0664                    var content = stream.ToArray();
 0665                    return File(content, "text/csv",
 0666                        "matrixreport.csv");
 667                }
 668                default:
 0669                {
 0670                    using var book = new XLWorkbook();
 0671                    var worksheet = book.Worksheets.Add("Report");
 0672                    var currentRow = 1;
 0673                    worksheet.Cell(currentRow, 1).Value = "№п/п";
 0674                    worksheet.Cell(currentRow, 2).Value = "Наименование покупателя";
 0675                    worksheet.Cell(currentRow, 3).Value = "ИНН покупателя";
 0676                    worksheet.Cell(currentRow, 4).Value = "№ заказа";
 0677                    worksheet.Cell(currentRow, 5).Value = "Дата заказа";
 0678                    worksheet.Cell(currentRow, 6).Value = "Сумма заказа";
 0679                    worksheet.Cell(currentRow, 7).Value = "Черновик(Заявка)";
 0680                    worksheet.Cell(currentRow, 8).Value = "В очереди на обработку(Заявка)";
 0681                    worksheet.Cell(currentRow, 9).Value = "В обработке(Заявка)";
 0682                    worksheet.Cell(currentRow, 10).Value = "Отказ(Заявка)";
 0683                    worksheet.Cell(currentRow, 11).Value = "Обработана(Заявка)";
 0684                    worksheet.Cell(currentRow, 12).Value = "Черновик(Отгрузка)";
 0685                    worksheet.Cell(currentRow, 13).Value = "Ожидает оплаты(Отгрузка)";
 0686                    worksheet.Cell(currentRow, 14).Value = "Сборка(Отгрузка)";
 0687                    worksheet.Cell(currentRow, 15).Value = "Готово к выдаче(Отгрузка)";
 0688                    worksheet.Cell(currentRow, 16).Value = "Коректировка(Отгрузка)";
 0689                    worksheet.Cell(currentRow, 17).Value = "Выдано(Отгрузка)";
 0690                    worksheet.Cell(currentRow, 18).Value = "Получено(Отгрузка)";
 0691                    worksheet.Cell(currentRow, 19).Value = "Отказ покупателя(Отгрузка)";
 0692                    worksheet.Cell(currentRow, 20).Value = "Отказ поставщика(Отгрузка)";
 0693                    worksheet.Cell(currentRow, 21).Value = "Отказ по регламенту(Отгрузка)";
 0694                    worksheet.Cell(currentRow, 22).Value = "Претензия в обработке";
 0695                    worksheet.Cell(currentRow, 23).Value = "Претензия подтверждено";
 0696                    worksheet.Cell(currentRow, 24).Value = "Претензия отклонено";
 0697                    for (int i = 0; i < result.Count(); i++)
 0698                    {
 0699                        currentRow++;
 0700                        worksheet.Cell(currentRow, 1).Value = i+1;
 0701                        worksheet.Cell(currentRow, 2).Value = result[i].Name;
 0702                        worksheet.Cell(currentRow, 3).Value = result[i].Inn;
 0703                        worksheet.Cell(currentRow, 4).Value = result[i].MovementId;
 0704                        worksheet.Cell(currentRow, 5).Value = result[i].Date.ToUniversalTime().ToMoscowTime()
 0705                            .ToString("yyyy-MM-dd HH:mm:ss");
 0706                        worksheet.Cell(currentRow, 6).Value = result[i].Sum;
 0707                        worksheet.Cell(currentRow, 7).Value = result[i].OrderDraft?.ToString("yyyy-MM-dd HH:mm:ss");
 0708                        worksheet.Cell(currentRow, 8).Value = result[i].OrderInQueue?.ToString("yyyy-MM-dd HH:mm:ss");;
 0709                        worksheet.Cell(currentRow, 9).Value = result[i].OrderInProgress?.ToString("yyyy-MM-dd HH:mm:ss")
 0710                        worksheet.Cell(currentRow, 10).Value = result[i].OrderReject?.ToString("yyyy-MM-dd HH:mm:ss");;
 0711                        worksheet.Cell(currentRow, 11).Value = result[i].OrderFinished?.ToString("yyyy-MM-dd HH:mm:ss");
 0712                        worksheet.Cell(currentRow, 12).Value = result[i].ShipmentDraft?.ToString("yyyy-MM-dd HH:mm:ss");
 0713                        worksheet.Cell(currentRow, 13).Value = result[i].ShipmentPaimentAwating?.ToString("yyyy-MM-dd HH
 0714                        worksheet.Cell(currentRow, 14).Value = result[i].ShipmentPicking?.ToString("yyyy-MM-dd HH:mm:ss"
 0715                        worksheet.Cell(currentRow, 15).Value = result[i].ShipmentReadyToShip?.ToString("yyyy-MM-dd HH:mm
 0716                        worksheet.Cell(currentRow, 16).Value = result[i].ShipmentCorrection?.ToString("yyyy-MM-dd HH:mm:
 0717                        worksheet.Cell(currentRow, 17).Value = result[i].ShipmentShipped?.ToString("yyyy-MM-dd HH:mm:ss"
 0718                        worksheet.Cell(currentRow, 18).Value = result[i].ShipmentReceived?.ToString("yyyy-MM-dd HH:mm:ss
 0719                        worksheet.Cell(currentRow, 19).Value = result[i].ShipmentCustomerReject?.ToString("yyyy-MM-dd HH
 0720                        worksheet.Cell(currentRow, 20).Value = result[i].ShipmentSupplierReject?.ToString("yyyy-MM-dd HH
 0721                        worksheet.Cell(currentRow, 21).Value = result[i].ShipmentReject?.ToString("yyyy-MM-dd HH:mm:ss")
 0722                        worksheet.Cell(currentRow, 22).Value = result[i].ClaimInProgress?.ToString("yyyy-MM-dd HH:mm:ss"
 0723                        worksheet.Cell(currentRow, 23).Value = result[i].ClaimAccedpted?.ToString("yyyy-MM-dd HH:mm:ss")
 0724                        worksheet.Cell(currentRow, 24).Value = result[i].ClaimDeclined?.ToString("yyyy-MM-dd HH:mm:ss");
 0725                    }
 726
 0727                    using var stream = new MemoryStream();
 0728                    book.SaveAs(stream);
 0729                    var content = stream.ToArray();
 0730                    return File(content, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
 0731                        "matrixReport.xlsx");
 732                }
 733            }
 0734        }
 735
 736        /// <summary>
 737        /// Выгрзука отчета статусов
 738        /// </summary>
 739        /// <param name="dateFrom">Дата начала отбора включая дату - по умолчанию за все время</param>
 740        /// <param name="dateTo">Дата окончания отбора включая дату - по умолчанию за все время</param>
 741        /// <returns></returns>
 742        [Authorize(Roles = Role.SystemOperator + "," + Role.SystemAdmin)]
 743        [HttpGet("StatusReport")]
 744        [SwaggerResponse(200, "Успешно", typeof(File))]
 745        [SwaggerResponse(403, "Ошибка прав доступа", typeof(ErrorDTO))]
 746        [SwaggerResponse(500, "Ошибка на стороне сервера", typeof(ErrorDTO))]
 747        public async Task<IActionResult> StatusReport(DateTimeOffset dateFrom = default,
 748            DateTimeOffset dateTo = default)
 0749        {
 0750            List<StatusReport> res = await _reportService.StatusReports(dateFrom.GetStartOfDate(), dateTo.GetEndOfDate()
 0751            using var book = new XLWorkbook();
 0752            var worksheet = book.Worksheets.Add("Report");
 753
 0754            var table = worksheet.Cell(2, 1).InsertTable(res, "Result");
 755
 0756            table.Cell(1, 1).SetValue("Статус");
 0757            table.Cell(1, 2).SetValue("Автор");
 0758            table.Cell(1, 3).SetValue("Контрагент");
 0759            table.Cell(1, 4).SetValue("Поставщик");
 0760            table.Cell(1, 5).SetValue("Основание");
 0761            table.Cell(1, 6).SetValue("Время события");
 0762            table.Cell(1, 7).SetValue("Документ");
 0763            table.Cell(1, 8).SetValue("СтатНомер");
 0764            table.Cell(1, 9).SetValue("Сумма");
 0765            table.Cell(1, 10).SetValue("Месяц создания");
 0766            table.Cell(1, 11).SetValue("Родитель");
 0767            table.Cell(1, 12).SetValue("ТПЗ");
 0768            var ptSheet = book.Worksheets.Add("PivotTable");
 0769            var pt = ptSheet.PivotTables.Add("PivotTables", ptSheet.Cell(1, 1), table.AsRange());
 0770            pt.RowLabels.Add("Контрагент", "Контрагент");
 0771            pt.RowLabels.Add("Месяц создания", "Месяц создания");
 0772            pt.RowLabels.Add("Основание", "Основание");
 0773            pt.RowLabels.Add("ТПЗ", "ТПЗ");
 0774            pt.RowLabels.Add("Документ", "Документ");
 0775            pt.RowLabels.Add("Время события", "Время события");
 0776            pt.RowLabels.Add("Автор", "Автор");
 0777            pt.ReportFilters.Add("Поставщик");
 0778            pt.ColumnLabels.Add("СтатНомер", "СтатНомер");
 0779            pt.ColumnLabels.Add("Статус", "Статус");
 0780            pt.Values.Add("Сумма");
 0781            pt.ShowGrandTotalsColumns = false;
 0782            pt.ShowGrandTotalsRows = false;
 0783            pt.ClassicPivotTableLayout = true;
 0784            ptSheet.Columns("A", "Z").Width = 20;
 0785            book.Worksheet(2).SetTabActive();
 0786            using var stream = new MemoryStream();
 0787            book.SaveAs(stream);
 0788            var content = stream.ToArray();
 0789            return File(content, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
 0790                "StatusReport.xlsx");
 0791        }
 792
 793        /// <summary>
 794        /// Выгрузка номенклатуры в excel
 795        /// </summary>
 796        /// <param name="departmentFilter">Фильтр по магазинам</param>
 797        /// <returns></returns>
 798        [HttpGet("DownloadPrices")]
 799        [SwaggerResponse(200, "Успешно")]
 800        [SwaggerResponse(500, "Ошибка на стороне сервера", typeof(ErrorDTO))]
 801        [Authorize(Roles = Role.SystemAdmin + "," + Role.SystemOperator)]
 802        public async Task<IActionResult> DownloadPrices(string departmentFilter = null)
 0803        {
 0804            if(string.IsNullOrWhiteSpace(departmentFilter))
 0805            {
 0806                throw new ArgumentException("Не задан фильтр по магазинам");
 807            }
 0808            departmentFilter = departmentFilter.NormalizeName().ToLower();
 809
 0810            var rows = new List<string[]>();
 0811            rows.Add(new string[]
 0812            {
 0813                "Дата выгрузки",
 0814                "Магазин-Получатель",
 0815                "ИД Товара",
 0816                "ШК товара",
 0817                "Артикул Товара",
 0818                "Название товара",
 0819                "Регулярная Цена товара",
 0820                "Акционная цена товара",
 0821                "Скидка",
 0822                "Количество на складе",
 0823                "Ярлыки товара",
 0824                "Наличие картинки",
 0825                "Название картинки"
 0826            });
 827
 0828            var downloadDate = DateTime.Today.ToString();
 0829            var departments = (await _departmentService.GetAllDepartments())
 0830                .Where(x => x.Name.ToLower().Contains(departmentFilter) && x.Cluster != null && !x.Cluster.IsDeleted)
 0831                .ToList();
 0832            foreach(var dep in departments)
 0833            {
 0834                var goods = _showcaseWorker.GetShowcaseGoods((long?)null, dep.Id, true, 0, int.MaxValue, null, null, nul
 0835                goods.ForEach(x =>
 0836                {
 0837                    string pictureFileName = "";
 0838                    if (x.Photos.Any())
 0839                    {
 0840                        pictureFileName = x.Photos.First().FullSizeUrl;
 0841                        Uri uri = new Uri(pictureFileName);
 0842                        pictureFileName = Path.GetFileName(uri.LocalPath);
 0843                    }
 0844
 0845                    rows.Add(new string[]
 0846                    {
 0847                        downloadDate,
 0848                        dep.Name,
 0849                        x.UniqueCode,
 0850                        x.MainBarcode?.Code,
 0851                        x.VendorCode,
 0852                        x.Name,
 0853                        x.OldPrice?.ToString(),
 0854                        x.Price.ToString(),
 0855                        x.Discount?.ToString(),
 0856                        x.RestQuantity.ToString(),
 0857                        string.Join(',', x.Labels.Select(x => x.Name).ToArray()),
 0858                        _diskStorage.PictureExists(pictureFileName) ? "1" : "0",
 0859                        pictureFileName
 0860                    });
 0861                });
 0862            }
 863
 0864            var stream = CsvUtil.ToExcelStream(rows);
 0865            _diskStorage.SaveDownload("prices.xlsx", stream, out string fileName);
 0866            return File(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", Path.GetFileName(fi
 0867        }
 868    }
 869
 870}