diff --git a/SushiBar/SushiBarBusinessLogic_/ComponentLogic.cs b/SushiBar/SushiBarBusinessLogic_/BusinessLogics/ComponentLogic.cs similarity index 100% rename from SushiBar/SushiBarBusinessLogic_/ComponentLogic.cs rename to SushiBar/SushiBarBusinessLogic_/BusinessLogics/ComponentLogic.cs diff --git a/SushiBar/SushiBarBusinessLogic_/ReportLogic.cs b/SushiBar/SushiBarBusinessLogic_/BusinessLogics/ReportLogic.cs similarity index 61% rename from SushiBar/SushiBarBusinessLogic_/ReportLogic.cs rename to SushiBar/SushiBarBusinessLogic_/BusinessLogics/ReportLogic.cs index 81ae29c..9f795ff 100644 --- a/SushiBar/SushiBarBusinessLogic_/ReportLogic.cs +++ b/SushiBar/SushiBarBusinessLogic_/BusinessLogics/ReportLogic.cs @@ -11,24 +11,25 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace SushiBarBusinessLogic +namespace SushiBarBusinessLogic.BusinessLogics { public class ReportLogic : IReportLogic { private readonly IComponentStorage _componentStorage; private readonly ISushiStorage _SushiStorage; private readonly IOrderStorage _orderStorage; + private readonly IShopStorage _shopStorage; private readonly AbstractSaveToExcel _saveToExcel; private readonly AbstractSaveToWord _saveToWord; private readonly AbstractSaveToPdf _saveToPdf; - public ReportLogic(ISushiStorage SushiStorage, IComponentStorage componentStorage, IOrderStorage orderStorage, + public ReportLogic(ISushiStorage SushiStorage, IComponentStorage componentStorage, IOrderStorage orderStorage, IShopStorage shopStorage, AbstractSaveToExcel saveToExcel, AbstractSaveToWord saveToWord, AbstractSaveToPdf saveToPdf) { _SushiStorage = SushiStorage; _componentStorage = componentStorage; _orderStorage = orderStorage; - + _shopStorage = shopStorage; _saveToExcel = saveToExcel; _saveToWord = saveToWord; _saveToPdf = saveToPdf; @@ -89,5 +90,55 @@ namespace SushiBarBusinessLogic Orders = GetOrders(model) }); } + + public List GetShops() + { + return _shopStorage.GetFullList().Select(x => new ReportShopsViewModel + { + ShopName = x.ShopName, + Sushis = x.ShopSushis.Select(x => (x.Value.Item1.SushiName, x.Value.Item2)).ToList(), + TotalCount = x.ShopSushis.Select(x => x.Value.Item2).Sum() + }).ToList(); + } + + public List GetGroupedOrders() + { + return _orderStorage.GetFullList().GroupBy(x => x.DateCreate.Date).Select(x => new ReportGroupOrdersViewModel + { + Date = x.Key, + OrdersCount = x.Count(), + OrdersSum = x.Select(y => y.Sum).Sum() + }).ToList(); + } + + public void SaveShopsToWordFile(ReportBindingModel model) + { + _saveToWord.CreateShopsDoc(new WordShopInfo + { + FileName = model.FileName, + Title = "Список магазинов", + Shops = _shopStorage.GetFullList() + }); + } + + public void SaveShopsToExcelFile(ReportBindingModel model) + { + _saveToExcel.CreateShopSushisReport(new ExcelShop + { + FileName = model.FileName, + Title = "Наполненость магазинов", + ShopSushis = GetShops() + }); + } + + public void SaveGroupedOrdersToPdfFile(ReportBindingModel model) + { + _saveToPdf.CreateGroupedOrdersDoc(new PdfGroupedOrdersInfo + { + FileName = model.FileName, + Title = "Список заказов сгруппированных по дате заказов", + GroupedOrders = GetGroupedOrders() + }); + } } } diff --git a/SushiBar/SushiBarBusinessLogic_/BusinessLogics/ShopLogic.cs b/SushiBar/SushiBarBusinessLogic_/BusinessLogics/ShopLogic.cs new file mode 100644 index 0000000..f14617f --- /dev/null +++ b/SushiBar/SushiBarBusinessLogic_/BusinessLogics/ShopLogic.cs @@ -0,0 +1,186 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SushiBarContracts.BindingModels; +using SushiBarContracts.BusinessLogicsContracts; +using SushiBarContracts.SearchModels; +using SushiBarContracts.StoragesContracts; +using SushiBarContracts.ViewModels; + +namespace SushiBarBusinessLogic.BusinessLogics +{ + public class ShopLogic : IShopLogic + { + private readonly ILogger _logger; + private readonly IShopStorage _shopStorage; + private readonly ISushiStorage _sushiStorage; + + public ShopLogic(ILogger logger, IShopStorage shopStorage, ISushiStorage sushiStorage) + { + _logger = logger; + _shopStorage = shopStorage; + _sushiStorage = sushiStorage; + } + + public List? ReadList(ShopSearchModel? model) + { + _logger.LogInformation("ReadList. ShopName:{ShopName}.Id:{ Id}", model?.ShopName, model?.Id); + var list = model == null ? _shopStorage.GetFullList() : _shopStorage.GetFilteredList(model); + if (list == null) + { + _logger.LogWarning("ReadList return null list"); + return null; + } + _logger.LogInformation("ReadList. Count:{Count}", list.Count); + return list; + } + + public ShopViewModel? ReadElement(ShopSearchModel model) + { + if (model == null) + { + throw new ArgumentNullException(nameof(model)); + } + _logger.LogInformation("ReadElement. ShopName:{ShopName}.Id:{ Id}", model.ShopName, model.Id); + var element = _shopStorage.GetElement(model); + if (element == null) + { + _logger.LogWarning("ReadElement element not found"); + return null; + } + _logger.LogInformation("ReadElement find. Id:{Id}", element.Id); + return element; + } + + public bool Create(ShopBindingModel model) + { + CheckModel(model); + if (_shopStorage.Insert(model) == null) + { + _logger.LogWarning("Insert operation failed"); + return false; + } + return true; + } + + public bool Update(ShopBindingModel model) + { + CheckModel(model); + if (_shopStorage.Update(model) == null) + { + _logger.LogWarning("Update operation failed"); + return false; + } + return true; + } + + public bool Delete(ShopBindingModel model) + { + CheckModel(model, false); + _logger.LogInformation("Delete. Id:{Id}", model.Id); + if (_shopStorage.Delete(model) == null) + { + _logger.LogWarning("Delete operation failed"); + return false; + } + return true; + } + + public bool MakeSupply(SupplyBindingModel model) + { + if (model == null) + { + throw new ArgumentNullException(nameof(model)); + } + if (model.Count <= 0) + { + throw new ArgumentException("Количество изделий должно быть больше 0"); + } + var shop = _shopStorage.GetElement(new ShopSearchModel + { + Id = model.ShopId + }); + if (shop == null) + { + throw new ArgumentException("Магазина не существует"); + } + if (shop.ShopSushis.ContainsKey(model.SushiId)) + { + var oldValue = shop.ShopSushis[model.SushiId]; + oldValue.Item2 += model.Count; + shop.ShopSushis[model.SushiId] = oldValue; + } + else + { + var sushi = _sushiStorage.GetElement(new SushiSearchModel + { + Id = model.SushiId + }); + if (sushi == null) + { + throw new ArgumentException($"Поставка: Товар с id:{model.SushiId} не найденн"); + } + shop.ShopSushis.Add(model.SushiId, (sushi, model.Count)); + } + + _shopStorage.Update(new ShopBindingModel() + { + Id = shop.Id, + ShopName = shop.ShopName, + Adress = shop.Adress, + OpeningDate = shop.OpeningDate, + ShopSushis = shop.ShopSushis, + SushiMaxCount = shop.SushiMaxCount, + }); + return true; + } + + private void CheckModel(ShopBindingModel model, bool withParams = true) + { + if (model == null) + { + throw new ArgumentNullException(nameof(model)); + } + if (!withParams) + { + return; + } + if (string.IsNullOrEmpty(model.Adress)) + { + throw new ArgumentException("Адрес магазина длжен быть заполнен", nameof(model.Adress)); + } + if (string.IsNullOrEmpty(model.ShopName)) + { + throw new ArgumentException("Название магазина должно быть заполнено", nameof(model.ShopName)); + } + _logger.LogInformation("Shop. ShopName:{ShopName}.Adres:{Adres}.OpeningDate:{OpeningDate}.Id:{ Id}", model.ShopName, model.Adress, model.OpeningDate, model.Id); + var element = _shopStorage.GetElement(new ShopSearchModel + { + ShopName = model.ShopName + }); + if (element != null && element.Id != model.Id) + { + throw new InvalidOperationException("Магазин с таким названием уже есть"); + } + } + + public bool Sale(SupplySearchModel model) + { + if (!model.SushiId.HasValue || !model.Count.HasValue) + { + return false; + } + _logger.LogInformation("Check sushi count in all shops"); + if (_shopStorage.Sale(model)) + { + _logger.LogInformation("Selling sucsess"); + return true; + } + _logger.LogInformation("Selling failed"); + return false; + } + } +} diff --git a/SushiBar/SushiBarBusinessLogic_/SushiLogic.cs b/SushiBar/SushiBarBusinessLogic_/BusinessLogics/SushiLogic.cs similarity index 93% rename from SushiBar/SushiBarBusinessLogic_/SushiLogic.cs rename to SushiBar/SushiBarBusinessLogic_/BusinessLogics/SushiLogic.cs index 339a27a..e9b39fc 100644 --- a/SushiBar/SushiBarBusinessLogic_/SushiLogic.cs +++ b/SushiBar/SushiBarBusinessLogic_/BusinessLogics/SushiLogic.cs @@ -92,11 +92,11 @@ namespace SushiBarBusinessLogic.BusinessLogics } if (string.IsNullOrEmpty(model.SushiName)) { - throw new ArgumentNullException("Нет названия пиццы", nameof(model.SushiName)); + throw new ArgumentNullException("Нет названия суши", nameof(model.SushiName)); } if (model.Price <= 0) { - throw new ArgumentNullException("Цена пиццы должна быть больше 0", nameof(model.Price)); + throw new ArgumentNullException("Цена суши должна быть больше 0", nameof(model.Price)); } if (model.SushiComponents == null || model.SushiComponents.Count == 0) { @@ -109,7 +109,7 @@ namespace SushiBarBusinessLogic.BusinessLogics }); if (element != null && element.Id != model.Id) { - throw new InvalidOperationException("Пицца с таким названием уже есть"); + throw new InvalidOperationException("Суши с таким названием уже есть"); } } } diff --git a/SushiBar/SushiBarBusinessLogic_/MailWorker/AbstractMailWorker.cs b/SushiBar/SushiBarBusinessLogic_/MailWorker/AbstractMailWorker.cs index b0d6a54..33d0a68 100644 --- a/SushiBar/SushiBarBusinessLogic_/MailWorker/AbstractMailWorker.cs +++ b/SushiBar/SushiBarBusinessLogic_/MailWorker/AbstractMailWorker.cs @@ -15,75 +15,119 @@ namespace SushiBarBusinessLogic.MailWorker { public abstract class AbstractMailWorker { - protected string _mailLogin = string.Empty; - protected string _mailPassword = string.Empty; - protected string _smtpClientHost = string.Empty; - protected int _smtpClientPort; - protected string _popHost = string.Empty; - protected int _popPort; - private readonly IMessageInfoLogic _messageInfoLogic; - private readonly ILogger _logger; + protected string _mailLogin = string.Empty; + protected string _mailPassword = string.Empty; + protected string _smtpClientHost = string.Empty; + protected int _smtpClientPort; + protected string _popHost = string.Empty; + protected int _popPort; + private readonly IMessageInfoLogic _messageInfoLogic; + private readonly ILogger _logger; - public AbstractMailWorker(ILogger logger, IMessageInfoLogic messageInfoLogic) - { - _logger = logger; - _messageInfoLogic = messageInfoLogic; - } - public void MailConfig(MailConfigBindingModel config) - { - _mailLogin = config.MailLogin; - _mailPassword = config.MailPassword; - _smtpClientHost = config.SmtpClientHost; - _smtpClientPort = config.SmtpClientPort; - _popHost = config.PopHost; - _popPort = config.PopPort; - _logger.LogDebug("Config: {login}, {password}, {clientHost}, {clientPOrt}, {popHost}, {popPort}", _mailLogin, _mailPassword.Length, _smtpClientHost, _smtpClientPort, _popHost, _popPort); - } - public async void MailSendAsync(MailSendInfoBindingModel info) - { - if (string.IsNullOrEmpty(_mailLogin) || string.IsNullOrEmpty(_mailPassword)) - { - return; - } + public AbstractMailWorker(ILogger logger, IMessageInfoLogic messageInfoLogic) + { + _logger = logger; + _messageInfoLogic = messageInfoLogic; + } + public void MailConfig(MailConfigBindingModel config) + { + _mailLogin = config.MailLogin; + _mailPassword = config.MailPassword; + _smtpClientHost = config.SmtpClientHost; + _smtpClientPort = config.SmtpClientPort; + _popHost = config.PopHost; + _popPort = config.PopPort; + _logger.LogDebug("Config: {login}, {password}, {clientHost}, {clientPOrt}, {popHost}, {popPort}", _mailLogin, _mailPassword.Length, _smtpClientHost, _smtpClientPort, _popHost, _popPort); + } + public async void MailSendAsync(MailSendInfoBindingModel info) + { + if (string.IsNullOrEmpty(_mailLogin) || string.IsNullOrEmpty(_mailPassword)) + { + return; + } - if (string.IsNullOrEmpty(_smtpClientHost) || _smtpClientPort == 0) - { - return; - } + if (string.IsNullOrEmpty(_smtpClientHost) || _smtpClientPort == 0) + { + return; + } - if (string.IsNullOrEmpty(info.MailAddress) || string.IsNullOrEmpty(info.Subject) || string.IsNullOrEmpty(info.Text)) - { - return; - } + if (string.IsNullOrEmpty(info.MailAddress) || string.IsNullOrEmpty(info.Subject) || string.IsNullOrEmpty(info.Text)) + { + return; + } - _logger.LogDebug("Send Mail: {To}, {Subject}", info.MailAddress, info.Subject); - await SendMailAsync(info); - } - public async void MailCheck() - { - if (string.IsNullOrEmpty(_mailLogin) || string.IsNullOrEmpty(_mailPassword)) - { - return; - } + _logger.LogDebug("Send Mail: {To}, {Subject}", info.MailAddress, info.Subject); + await SendMailAsync(info); + } + public async void MailCheck() + { + if (string.IsNullOrEmpty(_mailLogin) || string.IsNullOrEmpty(_mailPassword)) + { + return; + } - if (string.IsNullOrEmpty(_popHost) || _popPort == 0) - { - return; - } + if (string.IsNullOrEmpty(_popHost) || _popPort == 0) + { + return; + } - if (_messageInfoLogic == null) - { - return; - } + if (_messageInfoLogic == null) + { + return; + } - var list = await ReceiveMailAsync(); - _logger.LogDebug("Check Mail: {Count} new mails", list.Count); - foreach (var mail in list) - { - _messageInfoLogic.Create(mail); - } - } - protected abstract Task SendMailAsync(MailSendInfoBindingModel info); - protected abstract Task> ReceiveMailAsync(); - } -} + var list = await ReceiveMailAsync(); + _logger.LogDebug("Check Mail: {Count} new mails", list.Count); + foreach (var mail in list) + { + _messageInfoLogic.Create(mail); + } + } + + public async void MailSendReplyAsync(MailReplySendInfoBindingModel info) + { + if (string.IsNullOrEmpty(_mailLogin) || string.IsNullOrEmpty(_mailPassword)) + { + return; + } + + if (string.IsNullOrEmpty(_smtpClientHost) || _smtpClientPort == 0) + { + return; + } + + if (string.IsNullOrEmpty(info.MailAddress) || string.IsNullOrEmpty(info.Subject) || string.IsNullOrEmpty(info.Text) || string.IsNullOrEmpty(info.ParentMessageId)) + { + return; + } + + _logger.LogDebug("Send Mail as reply: {To}, {Subject}, {parentId}", info.MailAddress, info.Subject, info.ParentMessageId); + + string? messageId = await SendMailAsync(info); + if (string.IsNullOrEmpty(messageId)) + { + throw new InvalidOperationException("Непредвиденная ошибка при отправке сообщения в ответ"); + } + if (_messageInfoLogic.Create(new MessageInfoBindingModel + { + MessageId = messageId, + DateDelivery = DateTime.Now, + SenderName = _mailLogin, + IsReply = true, + Subject = info.Subject, + Body = info.Text, + })) + { + _messageInfoLogic.Update(new MessageInfoBindingModel() + { + MessageId = info.ParentMessageId, + ReplyMessageId = messageId, + IsReaded = true + }); + } + } + + protected abstract Task SendMailAsync(MailSendInfoBindingModel info); + protected abstract Task> ReceiveMailAsync(); + } +} \ No newline at end of file diff --git a/SushiBar/SushiBarBusinessLogic_/MailWorker/MailKitWorker.cs b/SushiBar/SushiBarBusinessLogic_/MailWorker/MailKitWorker.cs index b86598b..bcf30e4 100644 --- a/SushiBar/SushiBarBusinessLogic_/MailWorker/MailKitWorker.cs +++ b/SushiBar/SushiBarBusinessLogic_/MailWorker/MailKitWorker.cs @@ -15,69 +15,90 @@ namespace SushiBarBusinessLogic.MailWorker { public class MailKitWorker : AbstractMailWorker { - public MailKitWorker(ILogger logger, IMessageInfoLogic messageInfoLogic) : base(logger, messageInfoLogic) { } + public MailKitWorker(ILogger logger, IMessageInfoLogic messageInfoLogic) : base(logger, messageInfoLogic) { } - protected override async Task SendMailAsync(MailSendInfoBindingModel info) - { - using var objMailMessage = new MailMessage(); - using var objSmtpClient = new SmtpClient(_smtpClientHost, _smtpClientPort); - try - { - objMailMessage.From = new MailAddress(_mailLogin); - objMailMessage.To.Add(new MailAddress(info.MailAddress)); - objMailMessage.Subject = info.Subject; - objMailMessage.Body = info.Text; - objMailMessage.SubjectEncoding = Encoding.UTF8; - objMailMessage.BodyEncoding = Encoding.UTF8; - + protected override async Task SendMailAsync(MailSendInfoBindingModel info) + { + string? resount = null; + using var objMailMessage = new MailMessage(); + using var objSmtpClient = new SmtpClient(_smtpClientHost, _smtpClientPort); + try + { + ConfigurateSmtpClient(objSmtpClient); + CreateMessage(objMailMessage, info); - objSmtpClient.UseDefaultCredentials = false; - objSmtpClient.EnableSsl = true; - objSmtpClient.DeliveryMethod = SmtpDeliveryMethod.Network; - objSmtpClient.Credentials = new NetworkCredential(_mailLogin, _mailPassword); + if (info is MailReplySendInfoBindingModel replyInfo) + { + objMailMessage.Headers.Add("In-Reply-To", replyInfo.ParentMessageId); + objMailMessage.Headers.Add("References", replyInfo.ParentMessageId); - await Task.Run(() => objSmtpClient.Send(objMailMessage)); - } - catch (Exception) - { - throw; - } - } + string messageGuid = Guid.NewGuid().ToString(); + objMailMessage.Headers.Add("Message-Id", messageGuid); + resount = messageGuid; + } - protected override async Task> ReceiveMailAsync() - { - var list = new List(); - using var client = new Pop3Client(); - await Task.Run(() => - { - try - { - client.Connect(_popHost, _popPort, SecureSocketOptions.SslOnConnect); - client.Authenticate(_mailLogin, _mailPassword); - for (int i = 0; i < client.Count; i++) - { - var message = client.GetMessage(i); - foreach (var mail in message.From.Mailboxes) - { - list.Add(new MessageInfoBindingModel - { - DateDelivery = message.Date.DateTime, - MessageId = message.MessageId, - SenderName = mail.Address, - Subject = message.Subject, - Body = message.TextBody - }); - } - } - } - catch (MailKit.Security.AuthenticationException) - { } - finally - { - client.Disconnect(true); - } - }); - return list; - } - } -} + await Task.Run(() => objSmtpClient.Send(objMailMessage)); + } + catch (Exception) + { + throw; + } + return resount; + } + + protected override async Task> ReceiveMailAsync() + { + var list = new List(); + using var client = new Pop3Client(); + await Task.Run(() => + { + try + { + client.Connect(_popHost, _popPort, SecureSocketOptions.SslOnConnect); + client.Authenticate(_mailLogin, _mailPassword); + for (int i = 0; i < client.Count; i++) + { + var message = client.GetMessage(i); + foreach (var mail in message.From.Mailboxes) + { + list.Add(new MessageInfoBindingModel + { + DateDelivery = message.Date.DateTime, + MessageId = message.MessageId, + SenderName = mail.Address, + Subject = message.Subject, + Body = message.TextBody + }); + } + } + } + catch (MailKit.Security.AuthenticationException) + { } + finally + { + client.Disconnect(true); + } + }); + return list; + } + + private void CreateMessage(MailMessage objMailMessage, MailSendInfoBindingModel info) + { + objMailMessage.From = new MailAddress(_mailLogin); + objMailMessage.To.Add(new MailAddress(info.MailAddress)); + objMailMessage.Subject = info.Subject; + objMailMessage.Body = info.Text; + objMailMessage.SubjectEncoding = Encoding.UTF8; + objMailMessage.BodyEncoding = Encoding.UTF8; + } + + private void ConfigurateSmtpClient(SmtpClient objSmtpClient) + { + + objSmtpClient.UseDefaultCredentials = false; + objSmtpClient.EnableSsl = true; + objSmtpClient.DeliveryMethod = SmtpDeliveryMethod.Network; + objSmtpClient.Credentials = new NetworkCredential(_mailLogin, _mailPassword); + } + } +} \ No newline at end of file diff --git a/SushiBar/SushiBarBusinessLogic_/MessageInfoLogic.cs b/SushiBar/SushiBarBusinessLogic_/MessageInfoLogic.cs index 5a3a4d0..749cc4a 100644 --- a/SushiBar/SushiBarBusinessLogic_/MessageInfoLogic.cs +++ b/SushiBar/SushiBarBusinessLogic_/MessageInfoLogic.cs @@ -28,8 +28,12 @@ namespace SushiBarBusinessLogic } public List? ReadList(MessageInfoSearchModel? model) { - _logger.LogInformation("ReadList. MessageId:{MessageId}.ClientId:{ClientId}", model?.MessageId, model?.ClientId); - var list = model == null ? _messageInfoStorage.GetFullList() : _messageInfoStorage.GetFilteredList(model); + if (model == null) + { + throw new ArgumentNullException(nameof(model)); + } + _logger.LogInformation("ReadList. MessageId:{MessageId}.ClientId:{ClientId}.PageLength:{PageLength}.PageCount:{PageIndex}", model?.MessageId, model?.ClientId, model?.PageLength, model?.PageIndex); + var list = _messageInfoStorage.GetFilteredList(model); if (list == null) { _logger.LogWarning("ReadList return null list"); @@ -41,7 +45,8 @@ namespace SushiBarBusinessLogic public bool Create(MessageInfoBindingModel model) { CheckModel(model); - if (_messageInfoStorage.Insert(model) == null) + var message = _messageInfoStorage.Insert(model); + if (message == null) { _logger.LogWarning("Insert operation failed"); return false; @@ -54,27 +59,26 @@ namespace SushiBarBusinessLogic { throw new ArgumentNullException(nameof(model)); } - if (!withParams) - { - return; - } if (string.IsNullOrEmpty(model.MessageId)) { throw new ArgumentNullException("Не указан id сообщения", nameof(model.MessageId)); } + if (!withParams) + { + return; + } if (string.IsNullOrEmpty(model.SenderName)) { - throw new ArgumentNullException("Не указао почта", nameof(model.SenderName)); + throw new ArgumentNullException("Не указао имя отправителя(электронная почта)", nameof(model.SenderName)); } if (string.IsNullOrEmpty(model.Subject)) { - throw new ArgumentNullException("Не указана тема", nameof(model.Subject)); + throw new ArgumentNullException("Не указана темма", nameof(model.Subject)); } if (string.IsNullOrEmpty(model.Body)) { throw new ArgumentNullException("Не указан текст сообщения", nameof(model.Subject)); } - _logger.LogInformation("MessageInfo. MessageId:{MessageId}.SenderName:{SenderName}.Subject:{Subject}.Body:{Body}", model.MessageId, model.SenderName, model.Subject, model.Body); var element = _clientStorage.GetElement(new ClientSearchModel { @@ -89,5 +93,33 @@ namespace SushiBarBusinessLogic model.ClientId = element.Id; } } + + public MessageInfoViewModel? ReadElement(MessageInfoSearchModel model) + { + if (model == null) + { + throw new ArgumentNullException(nameof(model)); + } + _logger.LogInformation("ReadElement. MessageId:{MessageId}", model?.MessageId); + var element = _messageInfoStorage.GetElement(model); + if (element == null) + { + _logger.LogWarning("ReadElement element not found"); + return null; + } + _logger.LogInformation("ReadElement find. Id:{Id}", element.MessageId); + return element; + } + + public bool Update(MessageInfoBindingModel model) + { + CheckModel(model, withParams: false); + if (_messageInfoStorage.Update(model) == null) + { + _logger.LogWarning("Update operation failed"); + return false; + } + return true; + } } -} +} \ No newline at end of file diff --git a/SushiBar/SushiBarBusinessLogic_/OfficePackage/AbstractSaveToExcel.cs b/SushiBar/SushiBarBusinessLogic_/OfficePackage/AbstractSaveToExcel.cs index 7c71989..dfe03e7 100644 --- a/SushiBar/SushiBarBusinessLogic_/OfficePackage/AbstractSaveToExcel.cs +++ b/SushiBar/SushiBarBusinessLogic_/OfficePackage/AbstractSaveToExcel.cs @@ -13,6 +13,7 @@ namespace SushiBarBusinessLogic.OfficePackage public void CreateReport(ExcelInfo info) { CreateExcel(info); + InsertCellInWorksheet(new ExcelCellParameters { ColumnName = "A", @@ -20,40 +21,46 @@ namespace SushiBarBusinessLogic.OfficePackage Text = info.Title, StyleInfo = ExcelStyleInfoType.Title }); + MergeCells(new ExcelMergeParameters { CellFromName = "A1", CellToName = "C1" }); + uint rowIndex = 2; - foreach (var sc in info.SushiComponents) + foreach (var pc in info.SushiComponents) { InsertCellInWorksheet(new ExcelCellParameters { ColumnName = "A", RowIndex = rowIndex, - Text = sc.SushiName, + Text = pc.SushiName, StyleInfo = ExcelStyleInfoType.Text }); rowIndex++; - foreach (var component in sc.Components) + + foreach (var (Component, Count) in pc.Components) { InsertCellInWorksheet(new ExcelCellParameters { ColumnName = "B", RowIndex = rowIndex, - Text = component.Item1, + Text = Component, StyleInfo = ExcelStyleInfoType.TextWithBroder }); + InsertCellInWorksheet(new ExcelCellParameters { ColumnName = "C", RowIndex = rowIndex, - Text = component.Item2.ToString(), + Text = Count.ToString(), StyleInfo = ExcelStyleInfoType.TextWithBroder }); + rowIndex++; } + InsertCellInWorksheet(new ExcelCellParameters { ColumnName = "A", @@ -65,33 +72,90 @@ namespace SushiBarBusinessLogic.OfficePackage { ColumnName = "C", RowIndex = rowIndex, - Text = sc.TotalCount.ToString(), + Text = pc.TotalCount.ToString(), StyleInfo = ExcelStyleInfoType.Text }); rowIndex++; } + SaveExcel(info); } - /// - /// Создание excel-файла - /// - /// - protected abstract void CreateExcel(ExcelInfo info); - /// - /// Добавляем новую ячейку в лист - /// - /// - protected abstract void InsertCellInWorksheet(ExcelCellParameters - excelParams); - /// - /// Объединение ячеек - /// - /// + + public void CreateShopSushisReport(ExcelShop info) + { + CreateExcel(info); + + InsertCellInWorksheet(new ExcelCellParameters + { + ColumnName = "A", + RowIndex = 1, + Text = info.Title, + StyleInfo = ExcelStyleInfoType.Title + }); + + MergeCells(new ExcelMergeParameters + { + CellFromName = "A1", + CellToName = "C1" + }); + + uint rowIndex = 2; + foreach (var sr in info.ShopSushis) + { + InsertCellInWorksheet(new ExcelCellParameters + { + ColumnName = "A", + RowIndex = rowIndex, + Text = sr.ShopName, + StyleInfo = ExcelStyleInfoType.Text + }); + rowIndex++; + + foreach (var (Sushi, Count) in sr.Sushis) + { + InsertCellInWorksheet(new ExcelCellParameters + { + ColumnName = "B", + RowIndex = rowIndex, + Text = Sushi, + StyleInfo = ExcelStyleInfoType.TextWithBroder + }); + + + InsertCellInWorksheet(new ExcelCellParameters + { + ColumnName = "C", + RowIndex = rowIndex, + Text = Count.ToString(), + StyleInfo = ExcelStyleInfoType.TextWithBroder + }); + + rowIndex++; + } + + InsertCellInWorksheet(new ExcelCellParameters + { + ColumnName = "A", + RowIndex = rowIndex, + Text = "Итого", + StyleInfo = ExcelStyleInfoType.Text + }); + InsertCellInWorksheet(new ExcelCellParameters + { + ColumnName = "C", + RowIndex = rowIndex, + Text = sr.TotalCount.ToString(), + StyleInfo = ExcelStyleInfoType.Text + }); + rowIndex++; + } + + SaveExcel(info); + } + + protected abstract void CreateExcel(IDocument info); + protected abstract void InsertCellInWorksheet(ExcelCellParameters excelParams); protected abstract void MergeCells(ExcelMergeParameters excelParams); - /// - /// Сохранение файла - /// - /// - protected abstract void SaveExcel(ExcelInfo info); + protected abstract void SaveExcel(IDocument info); } } diff --git a/SushiBar/SushiBarBusinessLogic_/OfficePackage/AbstractSaveToPdf.cs b/SushiBar/SushiBarBusinessLogic_/OfficePackage/AbstractSaveToPdf.cs index b3f0d21..1795203 100644 --- a/SushiBar/SushiBarBusinessLogic_/OfficePackage/AbstractSaveToPdf.cs +++ b/SushiBar/SushiBarBusinessLogic_/OfficePackage/AbstractSaveToPdf.cs @@ -13,67 +13,65 @@ namespace SushiBarBusinessLogic.OfficePackage public void CreateDoc(PdfInfo info) { CreatePdf(info); - CreateParagraph(new PdfParagraph - { - Text = info.Title, - Style = "NormalTitle", - ParagraphAlignment = PdfParagraphAlignmentType.Center - }); - CreateParagraph(new PdfParagraph - { - Text = $"с { info.DateFrom.ToShortDateString() } по { info.DateTo.ToShortDateString() }", Style = "Normal", - ParagraphAlignment = PdfParagraphAlignmentType.Center - }); - CreateTable(new List { "1cm", "3cm", "4cm", "6cm", "3cm" }); + CreateParagraph(new PdfParagraph { Text = info.Title, Style = "NormalTitle", ParagraphAlignment = PdfParagraphAlignmentType.Center }); + CreateParagraph(new PdfParagraph { Text = $"с {info.DateFrom.ToShortDateString()} по {info.DateTo.ToShortDateString()}", Style = "Normal", ParagraphAlignment = PdfParagraphAlignmentType.Center }); + + CreateTable(new List { "2cm", "3cm", "6cm", "3cm", "3cm" }); + CreateRow(new PdfRowParameters { - Texts = new List { "Номер", "Дата заказа", "Статус", "Изделие", "Сумма" }, + Texts = new List { "Номер", "Дата заказа", "Пицца", "Статус", "Сумма" }, Style = "NormalTitle", ParagraphAlignment = PdfParagraphAlignmentType.Center }); + foreach (var order in info.Orders) { CreateRow(new PdfRowParameters { - Texts = new List { order.Id.ToString(), order.DateCreate.ToShortDateString(), order.Status.ToString(), order.SushiName, order.Sum.ToString() }, + Texts = new List { order.Id.ToString(), order.DateCreate.ToShortDateString(), order.SushiName, order.Status.ToString(), order.Sum.ToString() }, Style = "Normal", ParagraphAlignment = PdfParagraphAlignmentType.Left }); } - CreateParagraph(new PdfParagraph - { - Text = $"Итого: {info.Orders.Sum(x => x.Sum)}\t", - Style = "Normal", - ParagraphAlignment = PdfParagraphAlignmentType.Rigth - }); + CreateParagraph(new PdfParagraph { Text = $"Итого: {info.Orders.Sum(x => x.Sum)}\t", Style = "Normal", ParagraphAlignment = PdfParagraphAlignmentType.Rigth }); + SavePdf(info); } - /// - /// Создание doc-файла - /// - /// - protected abstract void CreatePdf(PdfInfo info); - /// - /// Создание параграфа с текстом - /// - /// - /// + + public void CreateGroupedOrdersDoc(PdfGroupedOrdersInfo info) + { + CreatePdf(info); + CreateParagraph(new PdfParagraph { Text = info.Title, Style = "NormalTitle", ParagraphAlignment = PdfParagraphAlignmentType.Center }); + + CreateTable(new List { "4cm", "3cm", "2cm" }); + CreateRow(new PdfRowParameters + { + Texts = new List { "Дата заказа", "Кол-во", "Сумма" }, + Style = "NormalTitle", + ParagraphAlignment = PdfParagraphAlignmentType.Center + }); + + + foreach (var groupedOrder in info.GroupedOrders) + { + CreateRow(new PdfRowParameters + { + Texts = new List { groupedOrder.Date.ToShortDateString(), groupedOrder.OrdersCount.ToString(), groupedOrder.OrdersSum.ToString() }, + Style = "Normal", + ParagraphAlignment = PdfParagraphAlignmentType.Left + }); + } + + CreateParagraph(new PdfParagraph { Text = $"Итого: {info.GroupedOrders.Sum(x => x.OrdersSum)}\t", Style = "Normal", ParagraphAlignment = PdfParagraphAlignmentType.Center }); + + SavePdf(info); + } + + protected abstract void CreatePdf(IDocument info); protected abstract void CreateParagraph(PdfParagraph paragraph); - /// - /// Создание таблицы - /// - /// - /// protected abstract void CreateTable(List columns); - /// - /// Создание и заполнение строки - /// - /// protected abstract void CreateRow(PdfRowParameters rowParameters); - /// - /// Сохранение файла - /// - /// - protected abstract void SavePdf(PdfInfo info); + protected abstract void SavePdf(IDocument info); } } diff --git a/SushiBar/SushiBarBusinessLogic_/OfficePackage/AbstractSaveToWord.cs b/SushiBar/SushiBarBusinessLogic_/OfficePackage/AbstractSaveToWord.cs index bd162a0..3e15d25 100644 --- a/SushiBar/SushiBarBusinessLogic_/OfficePackage/AbstractSaveToWord.cs +++ b/SushiBar/SushiBarBusinessLogic_/OfficePackage/AbstractSaveToWord.cs @@ -38,21 +38,52 @@ namespace SushiBarBusinessLogic.OfficePackage } SaveWord(info); } - /// - /// Создание doc-файла - /// - /// - protected abstract void CreateWord(WordInfo info); - /// - /// Создание абзаца с текстом - /// - /// - /// + + public void CreateShopsDoc(WordShopInfo info) + { + CreateWord(info); + CreateParagraph(new WordParagraph + { + Texts = new List<(string, WordTextProperties)> { (info.Title, new WordTextProperties { Bold = true, Size = "24", }) }, + TextProperties = new WordTextProperties + { + Size = "24", + JustificationType = WordJustificationType.Center + } + }); + + CreateTable(new List { "3000", "3000", "3000" }); + CreateRow(new WordRowParameters + { + Texts = new List { "Название", "Адрес", "Дата открытия" }, + TextProperties = new WordTextProperties + { + Size = "24", + Bold = true, + JustificationType = WordJustificationType.Center + } + }); + + foreach (var shop in info.Shops) + { + CreateRow(new WordRowParameters + { + Texts = new List { shop.ShopName, shop.Adress, shop.OpeningDate.ToString() }, + TextProperties = new WordTextProperties + { + Size = "22", + JustificationType = WordJustificationType.Both + } + }); + } + + SaveWord(info); + } + + protected abstract void CreateWord(IDocument info); protected abstract void CreateParagraph(WordParagraph paragraph); - /// - /// Сохранение файла - /// - /// - protected abstract void SaveWord(WordInfo info); + protected abstract void SaveWord(IDocument info); + protected abstract void CreateTable(List colums); + protected abstract void CreateRow(WordRowParameters rowParameters); } } \ No newline at end of file diff --git a/SushiBar/SushiBarBusinessLogic_/OfficePackage/HelperModels/ExcelInfo.cs b/SushiBar/SushiBarBusinessLogic_/OfficePackage/HelperModels/ExcelInfo.cs index d9b69b4..f4ea133 100644 --- a/SushiBar/SushiBarBusinessLogic_/OfficePackage/HelperModels/ExcelInfo.cs +++ b/SushiBar/SushiBarBusinessLogic_/OfficePackage/HelperModels/ExcelInfo.cs @@ -2,7 +2,7 @@ namespace SushiBarBusinessLogic.OfficePackage.HelperModels { - public class ExcelInfo + public class ExcelInfo : IDocument { public string FileName { get; set; } = string.Empty; public string Title { get; set; } = string.Empty; diff --git a/SushiBar/SushiBarBusinessLogic_/OfficePackage/HelperModels/ExcelShop.cs b/SushiBar/SushiBarBusinessLogic_/OfficePackage/HelperModels/ExcelShop.cs new file mode 100644 index 0000000..680c521 --- /dev/null +++ b/SushiBar/SushiBarBusinessLogic_/OfficePackage/HelperModels/ExcelShop.cs @@ -0,0 +1,16 @@ +using SushiBarContracts.ViewModels; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SushiBarBusinessLogic.OfficePackage.HelperModels +{ + public class ExcelShop : IDocument + { + public string FileName { get; set; } = string.Empty; + public string Title { get; set; } = string.Empty; + public List ShopSushis { get; set; } = new(); + } +} diff --git a/SushiBar/SushiBarBusinessLogic_/OfficePackage/HelperModels/PdfGroupedOrdersInfo.cs b/SushiBar/SushiBarBusinessLogic_/OfficePackage/HelperModels/PdfGroupedOrdersInfo.cs new file mode 100644 index 0000000..fbcc93d --- /dev/null +++ b/SushiBar/SushiBarBusinessLogic_/OfficePackage/HelperModels/PdfGroupedOrdersInfo.cs @@ -0,0 +1,18 @@ +using SushiBarContracts.ViewModels; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SushiBarBusinessLogic.OfficePackage.HelperModels +{ + public class PdfGroupedOrdersInfo : IDocument + { + public string FileName { get; set; } = string.Empty; + public string Title { get; set; } = string.Empty; + public DateTime DateFrom { get; set; } + public DateTime DateTo { get; set; } + public List GroupedOrders { get; set; } = new(); + } +} diff --git a/SushiBar/SushiBarBusinessLogic_/OfficePackage/HelperModels/PdfInfo.cs b/SushiBar/SushiBarBusinessLogic_/OfficePackage/HelperModels/PdfInfo.cs index bf4b058..189cdd8 100644 --- a/SushiBar/SushiBarBusinessLogic_/OfficePackage/HelperModels/PdfInfo.cs +++ b/SushiBar/SushiBarBusinessLogic_/OfficePackage/HelperModels/PdfInfo.cs @@ -8,7 +8,7 @@ using System.Threading.Tasks; namespace SushiBarBusinessLogic.OfficePackage.HelperModels { - public class PdfInfo + public class PdfInfo : IDocument { public string FileName { get; set; } = string.Empty; public string Title { get; set; } = string.Empty; diff --git a/SushiBar/SushiBarBusinessLogic_/OfficePackage/HelperModels/WordInfo.cs b/SushiBar/SushiBarBusinessLogic_/OfficePackage/HelperModels/WordInfo.cs index 472a5aa..8e36208 100644 --- a/SushiBar/SushiBarBusinessLogic_/OfficePackage/HelperModels/WordInfo.cs +++ b/SushiBar/SushiBarBusinessLogic_/OfficePackage/HelperModels/WordInfo.cs @@ -2,7 +2,7 @@ namespace SushiBarBusinessLogic.OfficePackage.HelperModels { - public class WordInfo + public class WordInfo : IDocument { public string FileName { get; set; } = string.Empty; public string Title { get; set; } = string.Empty; diff --git a/SushiBar/SushiBarBusinessLogic_/OfficePackage/HelperModels/WordRowParameters.cs b/SushiBar/SushiBarBusinessLogic_/OfficePackage/HelperModels/WordRowParameters.cs new file mode 100644 index 0000000..2df1cd9 --- /dev/null +++ b/SushiBar/SushiBarBusinessLogic_/OfficePackage/HelperModels/WordRowParameters.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SushiBarBusinessLogic.OfficePackage.HelperModels +{ + public class WordRowParameters + { + public List Texts { get; set; } = new(); + public WordTextProperties TextProperties { get; set; } = new(); + } +} diff --git a/SushiBar/SushiBarBusinessLogic_/OfficePackage/HelperModels/WordShopInfo.cs b/SushiBar/SushiBarBusinessLogic_/OfficePackage/HelperModels/WordShopInfo.cs new file mode 100644 index 0000000..75515bf --- /dev/null +++ b/SushiBar/SushiBarBusinessLogic_/OfficePackage/HelperModels/WordShopInfo.cs @@ -0,0 +1,16 @@ +using SushiBarContracts.ViewModels; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SushiBarBusinessLogic.OfficePackage.HelperModels +{ + public class WordShopInfo : IDocument + { + public string FileName { get; set; } = string.Empty; + public string Title { get; set; } = string.Empty; + public List Shops { get; set; } = new(); + } +} diff --git a/SushiBar/SushiBarBusinessLogic_/OfficePackage/IDocument.cs b/SushiBar/SushiBarBusinessLogic_/OfficePackage/IDocument.cs new file mode 100644 index 0000000..14e64b9 --- /dev/null +++ b/SushiBar/SushiBarBusinessLogic_/OfficePackage/IDocument.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SushiBarBusinessLogic.OfficePackage +{ + public interface IDocument + { + public string FileName { get; set; } + public string Title { get; set; } + } +} diff --git a/SushiBar/SushiBarBusinessLogic_/OfficePackage/Implements/SaveToExcel.cs b/SushiBar/SushiBarBusinessLogic_/OfficePackage/Implements/SaveToExcel.cs index 99c7ee3..05ef135 100644 --- a/SushiBar/SushiBarBusinessLogic_/OfficePackage/Implements/SaveToExcel.cs +++ b/SushiBar/SushiBarBusinessLogic_/OfficePackage/Implements/SaveToExcel.cs @@ -14,167 +14,110 @@ namespace SushiBarBusinessLogic.OfficePackage.Implements private SpreadsheetDocument? _spreadsheetDocument; private SharedStringTablePart? _shareStringPart; private Worksheet? _worksheet; - /// - /// Настройка стилей для файла - /// - /// + private static void CreateStyles(WorkbookPart workbookpart) { var sp = workbookpart.AddNewPart(); sp.Stylesheet = new Stylesheet(); + var fonts = new Fonts() { Count = 2U, KnownFonts = true }; + var fontUsual = new Font(); fontUsual.Append(new FontSize() { Val = 12D }); - fontUsual.Append(new DocumentFormat.OpenXml.Office2010.Excel.Color() - { Theme = 1U }); + fontUsual.Append(new DocumentFormat.OpenXml.Office2010.Excel.Color() { Theme = 1U }); fontUsual.Append(new FontName() { Val = "Times New Roman" }); fontUsual.Append(new FontFamilyNumbering() { Val = 2 }); fontUsual.Append(new FontScheme() { Val = FontSchemeValues.Minor }); + var fontTitle = new Font(); fontTitle.Append(new Bold()); fontTitle.Append(new FontSize() { Val = 14D }); - fontTitle.Append(new DocumentFormat.OpenXml.Office2010.Excel.Color() - { Theme = 1U }); + fontTitle.Append(new DocumentFormat.OpenXml.Office2010.Excel.Color() { Theme = 1U }); fontTitle.Append(new FontName() { Val = "Times New Roman" }); fontTitle.Append(new FontFamilyNumbering() { Val = 2 }); fontTitle.Append(new FontScheme() { Val = FontSchemeValues.Minor }); + fonts.Append(fontUsual); fonts.Append(fontTitle); + var fills = new Fills() { Count = 2U }; + var fill1 = new Fill(); fill1.Append(new PatternFill() { PatternType = PatternValues.None }); + var fill2 = new Fill(); - fill2.Append(new PatternFill() - { - PatternType = PatternValues.Gray125 - }); + fill2.Append(new PatternFill() { PatternType = PatternValues.Gray125 }); + fills.Append(fill1); fills.Append(fill2); + var borders = new Borders() { Count = 2U }; + var borderNoBorder = new Border(); borderNoBorder.Append(new LeftBorder()); borderNoBorder.Append(new RightBorder()); borderNoBorder.Append(new TopBorder()); borderNoBorder.Append(new BottomBorder()); borderNoBorder.Append(new DiagonalBorder()); + var borderThin = new Border(); + var leftBorder = new LeftBorder() { Style = BorderStyleValues.Thin }; - leftBorder.Append(new DocumentFormat.OpenXml.Office2010.Excel.Color() - { Indexed = 64U }); - var rightBorder = new RightBorder() - { - Style = BorderStyleValues.Thin - }; - rightBorder.Append(new - DocumentFormat.OpenXml.Office2010.Excel.Color() - { Indexed = 64U }); + leftBorder.Append(new DocumentFormat.OpenXml.Office2010.Excel.Color() { Indexed = 64U }); + + var rightBorder = new RightBorder() { Style = BorderStyleValues.Thin }; + rightBorder.Append(new DocumentFormat.OpenXml.Office2010.Excel.Color() { Indexed = 64U }); + var topBorder = new TopBorder() { Style = BorderStyleValues.Thin }; - topBorder.Append(new DocumentFormat.OpenXml.Office2010.Excel.Color() - { Indexed = 64U }); - var bottomBorder = new BottomBorder() - { - Style = - BorderStyleValues.Thin - }; - bottomBorder.Append(new - DocumentFormat.OpenXml.Office2010.Excel.Color() - { Indexed = 64U }); + topBorder.Append(new DocumentFormat.OpenXml.Office2010.Excel.Color() { Indexed = 64U }); + + var bottomBorder = new BottomBorder() { Style = BorderStyleValues.Thin }; + bottomBorder.Append(new DocumentFormat.OpenXml.Office2010.Excel.Color() { Indexed = 64U }); + borderThin.Append(leftBorder); borderThin.Append(rightBorder); borderThin.Append(topBorder); borderThin.Append(bottomBorder); borderThin.Append(new DiagonalBorder()); + borders.Append(borderNoBorder); borders.Append(borderThin); + var cellStyleFormats = new CellStyleFormats() { Count = 1U }; - var cellFormatStyle = new CellFormat() - { - NumberFormatId = 0U, - FontId - = 0U, - FillId = 0U, - BorderId = 0U - }; + var cellFormatStyle = new CellFormat() { NumberFormatId = 0U, FontId = 0U, FillId = 0U, BorderId = 0U }; + cellStyleFormats.Append(cellFormatStyle); + var cellFormats = new CellFormats() { Count = 3U }; - var cellFormatFont = new CellFormat() - { - NumberFormatId = 0U, - FontId = - 0U, - FillId = 0U, - BorderId = 0U, - FormatId = 0U, - ApplyFont = true - }; - var cellFormatFontAndBorder = new CellFormat() - { - NumberFormatId = 0U, - FontId = 0U, - FillId = 0U, - BorderId = 1U, - FormatId = 0U, - ApplyFont = true, - ApplyBorder = true - }; - var cellFormatTitle = new CellFormat() - { - NumberFormatId = 0U, - FontId - = 1U, - FillId = 0U, - BorderId = 0U, - FormatId = 0U, - Alignment = new Alignment() - { - Vertical = VerticalAlignmentValues.Center, - WrapText = true, - Horizontal = - HorizontalAlignmentValues.Center - }, - ApplyFont = true - }; + var cellFormatFont = new CellFormat() { NumberFormatId = 0U, FontId = 0U, FillId = 0U, BorderId = 0U, FormatId = 0U, ApplyFont = true }; + var cellFormatFontAndBorder = new CellFormat() { NumberFormatId = 0U, FontId = 0U, FillId = 0U, BorderId = 1U, FormatId = 0U, ApplyFont = true, ApplyBorder = true }; + var cellFormatTitle = new CellFormat() { NumberFormatId = 0U, FontId = 1U, FillId = 0U, BorderId = 0U, FormatId = 0U, Alignment = new Alignment() { Vertical = VerticalAlignmentValues.Center, WrapText = true, Horizontal = HorizontalAlignmentValues.Center }, ApplyFont = true }; + cellFormats.Append(cellFormatFont); cellFormats.Append(cellFormatFontAndBorder); cellFormats.Append(cellFormatTitle); - var cellStyles = new CellStyles() { Count = 1U }; - cellStyles.Append(new CellStyle() - { - Name = "Normal", - FormatId = 0U, - BuiltinId = 0U - }); - var differentialFormats = new - DocumentFormat.OpenXml.Office2013.Excel.DifferentialFormats() - { Count = 0U }; - var tableStyles = new TableStyles() - { - Count = 0U, - DefaultTableStyle = "TableStyleMedium2", - DefaultPivotStyle = "PivotStyleLight16" - }; + var cellStyles = new CellStyles() { Count = 1U }; + + cellStyles.Append(new CellStyle() { Name = "Normal", FormatId = 0U, BuiltinId = 0U }); + + var differentialFormats = new DocumentFormat.OpenXml.Office2013.Excel.DifferentialFormats() { Count = 0U }; + + var tableStyles = new TableStyles() { Count = 0U, DefaultTableStyle = "TableStyleMedium2", DefaultPivotStyle = "PivotStyleLight16" }; + var stylesheetExtensionList = new StylesheetExtensionList(); - var stylesheetExtension1 = new StylesheetExtension() - { - Uri = "{EB79DEF2-80B8-43e5-95BD-54CBDDF9020C}" - }; + + var stylesheetExtension1 = new StylesheetExtension() { Uri = "{EB79DEF2-80B8-43e5-95BD-54CBDDF9020C}" }; stylesheetExtension1.AddNamespaceDeclaration("x14", "http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"); - stylesheetExtension1.Append(new SlicerStyles() - { - DefaultSlicerStyle = "SlicerStyleLight1" - }); - var stylesheetExtension2 = new StylesheetExtension() - { - Uri = "{9260A510-F301-46a8-8635-F512D64BE5F5}" - }; + stylesheetExtension1.Append(new SlicerStyles() { DefaultSlicerStyle = "SlicerStyleLight1" }); + + var stylesheetExtension2 = new StylesheetExtension() { Uri = "{9260A510-F301-46a8-8635-F512D64BE5F5}" }; stylesheetExtension2.AddNamespaceDeclaration("x15", "http://schemas.microsoft.com/office/spreadsheetml/2010/11/main"); - stylesheetExtension2.Append(new TimelineStyles() - { - DefaultTimelineStyle = "TimeSlicerStyleLight1" - }); + stylesheetExtension2.Append(new TimelineStyles() { DefaultTimelineStyle = "TimeSlicerStyleLight1" }); + stylesheetExtensionList.Append(stylesheetExtension1); stylesheetExtensionList.Append(stylesheetExtension2); + sp.Stylesheet.Append(fonts); sp.Stylesheet.Append(fills); sp.Stylesheet.Append(borders); @@ -185,11 +128,7 @@ namespace SushiBarBusinessLogic.OfficePackage.Implements sp.Stylesheet.Append(tableStyles); sp.Stylesheet.Append(stylesheetExtensionList); } - /// - /// Получение номера стиля из типа - /// - /// - /// + private static uint GetStyleValue(ExcelStyleInfoType styleInfo) { return styleInfo switch @@ -200,40 +139,44 @@ namespace SushiBarBusinessLogic.OfficePackage.Implements _ => 0U, }; } - protected override void CreateExcel(ExcelInfo info) + + protected override void CreateExcel(IDocument info) { - _spreadsheetDocument = SpreadsheetDocument.Create(info.FileName, - SpreadsheetDocumentType.Workbook); + _spreadsheetDocument = SpreadsheetDocument.Create(info.FileName, SpreadsheetDocumentType.Workbook); + // Создаем книгу (в ней хранятся листы) var workbookpart = _spreadsheetDocument.AddWorkbookPart(); workbookpart.Workbook = new Workbook(); + CreateStyles(workbookpart); - _shareStringPart = - _spreadsheetDocument.WorkbookPart!.GetPartsOfType().Any() - ? - _spreadsheetDocument.WorkbookPart.GetPartsOfType().First() - : - _spreadsheetDocument.WorkbookPart.AddNewPart(); + + // Получаем/создаем хранилище текстов для книги + _shareStringPart = _spreadsheetDocument.WorkbookPart!.GetPartsOfType().Any() + ? _spreadsheetDocument.WorkbookPart.GetPartsOfType().First() + : _spreadsheetDocument.WorkbookPart.AddNewPart(); + // Создаем SharedStringTable, если его нет if (_shareStringPart.SharedStringTable == null) { _shareStringPart.SharedStringTable = new SharedStringTable(); } + // Создаем лист в книгу var worksheetPart = workbookpart.AddNewPart(); worksheetPart.Worksheet = new Worksheet(new SheetData()); + // Добавляем лист в книгу - var sheets = - _spreadsheetDocument.WorkbookPart.Workbook.AppendChild(new Sheets()); + var sheets = _spreadsheetDocument.WorkbookPart.Workbook.AppendChild(new Sheets()); var sheet = new Sheet() { - Id = - _spreadsheetDocument.WorkbookPart.GetIdOfPart(worksheetPart), + Id = _spreadsheetDocument.WorkbookPart.GetIdOfPart(worksheetPart), SheetId = 1, Name = "Лист" }; sheets.Append(sheet); + _worksheet = worksheetPart.Worksheet; } + protected override void InsertCellInWorksheet(ExcelCellParameters excelParams) { if (_worksheet == null || _shareStringPart == null) @@ -245,6 +188,7 @@ namespace SushiBarBusinessLogic.OfficePackage.Implements { return; } + // Ищем строку, либо добавляем ее Row row; if (sheetData.Elements().Where(r => r.RowIndex! == excelParams.RowIndex).Any()) @@ -256,7 +200,8 @@ namespace SushiBarBusinessLogic.OfficePackage.Implements row = new Row() { RowIndex = excelParams.RowIndex }; sheetData.Append(row); } - // Ищем нужную ячейку + + // Ищем нужную ячейку Cell cell; if (row.Elements().Where(c => c.CellReference!.Value == excelParams.CellReference).Any()) { @@ -275,20 +220,22 @@ namespace SushiBarBusinessLogic.OfficePackage.Implements break; } } - var newCell = new Cell() - { - CellReference = excelParams.CellReference - }; + + var newCell = new Cell() { CellReference = excelParams.CellReference }; row.InsertBefore(newCell, refCell); + cell = newCell; } + // вставляем новый текст _shareStringPart.SharedStringTable.AppendChild(new SharedStringItem(new Text(excelParams.Text))); _shareStringPart.SharedStringTable.Save(); + cell.CellValue = new CellValue((_shareStringPart.SharedStringTable.Elements().Count() - 1).ToString()); cell.DataType = new EnumValue(CellValues.SharedString); cell.StyleIndex = GetStyleValue(excelParams.StyleInfo); } + protected override void MergeCells(ExcelMergeParameters excelParams) { if (_worksheet == null) @@ -296,6 +243,7 @@ namespace SushiBarBusinessLogic.OfficePackage.Implements return; } MergeCells mergeCells; + if (_worksheet.Elements().Any()) { mergeCells = _worksheet.Elements().First(); @@ -303,24 +251,25 @@ namespace SushiBarBusinessLogic.OfficePackage.Implements else { mergeCells = new MergeCells(); + if (_worksheet.Elements().Any()) { - _worksheet.InsertAfter(mergeCells, - _worksheet.Elements().First()); + _worksheet.InsertAfter(mergeCells, _worksheet.Elements().First()); } else { - _worksheet.InsertAfter(mergeCells, - _worksheet.Elements().First()); + _worksheet.InsertAfter(mergeCells, _worksheet.Elements().First()); } } + var mergeCell = new MergeCell() { Reference = new StringValue(excelParams.Merge) }; mergeCells.Append(mergeCell); } - protected override void SaveExcel(ExcelInfo info) + + protected override void SaveExcel(IDocument info) { if (_spreadsheetDocument == null) { diff --git a/SushiBar/SushiBarBusinessLogic_/OfficePackage/Implements/SaveToPdf.cs b/SushiBar/SushiBarBusinessLogic_/OfficePackage/Implements/SaveToPdf.cs index a5840f7..ed10be5 100644 --- a/SushiBar/SushiBarBusinessLogic_/OfficePackage/Implements/SaveToPdf.cs +++ b/SushiBar/SushiBarBusinessLogic_/OfficePackage/Implements/SaveToPdf.cs @@ -11,6 +11,7 @@ namespace SushiBarBusinessLogic.OfficePackage.Implements private Document? _document; private Section? _section; private Table? _table; + private static ParagraphAlignment GetParagraphAlignment(PdfParagraphAlignmentType type) { return type switch @@ -21,24 +22,25 @@ namespace SushiBarBusinessLogic.OfficePackage.Implements _ => ParagraphAlignment.Justify, }; } - /// - /// Создание стилей для документа - /// - /// + private static void DefineStyles(Document document) { var style = document.Styles["Normal"]; style.Font.Name = "Times New Roman"; style.Font.Size = 14; + style = document.Styles.AddStyle("NormalTitle", "Normal"); style.Font.Bold = true; } - protected override void CreatePdf(PdfInfo info) + + protected override void CreatePdf(IDocument info) { _document = new Document(); DefineStyles(_document); + _section = _document.AddSection(); } + protected override void CreateParagraph(PdfParagraph pdfParagraph) { if (_section == null) @@ -50,6 +52,7 @@ namespace SushiBarBusinessLogic.OfficePackage.Implements paragraph.Format.Alignment = GetParagraphAlignment(pdfParagraph.ParagraphAlignment); paragraph.Style = pdfParagraph.Style; } + protected override void CreateTable(List columns) { if (_document == null) @@ -57,11 +60,13 @@ namespace SushiBarBusinessLogic.OfficePackage.Implements return; } _table = _document.LastSection.AddTable(); + foreach (var elem in columns) { _table.AddColumn(elem); } } + protected override void CreateRow(PdfRowParameters rowParameters) { if (_table == null) @@ -72,20 +77,25 @@ namespace SushiBarBusinessLogic.OfficePackage.Implements for (int i = 0; i < rowParameters.Texts.Count; ++i) { row.Cells[i].AddParagraph(rowParameters.Texts[i]); + if (!string.IsNullOrEmpty(rowParameters.Style)) { row.Cells[i].Style = rowParameters.Style; } + Unit borderWidth = 0.5; + row.Cells[i].Borders.Left.Width = borderWidth; row.Cells[i].Borders.Right.Width = borderWidth; row.Cells[i].Borders.Top.Width = borderWidth; row.Cells[i].Borders.Bottom.Width = borderWidth; + row.Cells[i].Format.Alignment = GetParagraphAlignment(rowParameters.ParagraphAlignment); row.Cells[i].VerticalAlignment = VerticalAlignment.Center; } } - protected override void SavePdf(PdfInfo info) + + protected override void SavePdf(IDocument info) { var renderer = new PdfDocumentRenderer(true) { @@ -95,4 +105,4 @@ namespace SushiBarBusinessLogic.OfficePackage.Implements renderer.PdfDocument.Save(info.FileName); } } -} \ No newline at end of file +} \ No newline at end of file diff --git a/SushiBar/SushiBarBusinessLogic_/OfficePackage/Implements/SaveToWord.cs b/SushiBar/SushiBarBusinessLogic_/OfficePackage/Implements/SaveToWord.cs index 6c1fc93..0e5ffa3 100644 --- a/SushiBar/SushiBarBusinessLogic_/OfficePackage/Implements/SaveToWord.cs +++ b/SushiBar/SushiBarBusinessLogic_/OfficePackage/Implements/SaveToWord.cs @@ -11,13 +11,8 @@ namespace SushiBarBusinessLogic.OfficePackage.Implements { private WordprocessingDocument? _wordDocument; private Body? _docBody; - /// - /// Получение типа выравнивания - /// - /// - /// - private static JustificationValues - GetJustificationValues(WordJustificationType type) + + private static JustificationValues GetJustificationValues(WordJustificationType type) { return type switch { @@ -26,59 +21,60 @@ namespace SushiBarBusinessLogic.OfficePackage.Implements _ => JustificationValues.Left, }; } - /// - /// Настройки страницы - /// - /// + private static SectionProperties CreateSectionProperties() { var properties = new SectionProperties(); + var pageSize = new PageSize { Orient = PageOrientationValues.Portrait }; + properties.AppendChild(pageSize); + return properties; } - /// - /// Задание форматирования для абзаца - /// - /// - /// + private static ParagraphProperties? CreateParagraphProperties(WordTextProperties? paragraphProperties) { if (paragraphProperties == null) { return null; } + var properties = new ParagraphProperties(); + properties.AppendChild(new Justification() { Val = GetJustificationValues(paragraphProperties.JustificationType) }); + properties.AppendChild(new SpacingBetweenLines { LineRule = LineSpacingRuleValues.Auto }); + properties.AppendChild(new Indentation()); + var paragraphMarkRunProperties = new ParagraphMarkRunProperties(); if (!string.IsNullOrEmpty(paragraphProperties.Size)) { - paragraphMarkRunProperties.AppendChild(new FontSize - { - Val = paragraphProperties.Size - }); + paragraphMarkRunProperties.AppendChild(new FontSize { Val = paragraphProperties.Size }); } properties.AppendChild(paragraphMarkRunProperties); + return properties; } - protected override void CreateWord(WordInfo info) + + protected override void CreateWord(IDocument info) { _wordDocument = WordprocessingDocument.Create(info.FileName, WordprocessingDocumentType.Document); MainDocumentPart mainPart = _wordDocument.AddMainDocumentPart(); mainPart.Document = new Document(); _docBody = mainPart.Document.AppendChild(new Body()); } + protected override void CreateParagraph(WordParagraph paragraph) { if (_docBody == null || paragraph == null) @@ -88,9 +84,11 @@ namespace SushiBarBusinessLogic.OfficePackage.Implements var docParagraph = new Paragraph(); docParagraph.AppendChild(CreateParagraphProperties(paragraph.TextProperties)); + foreach (var run in paragraph.Texts) { var docRun = new Run(); + var properties = new RunProperties(); properties.AppendChild(new FontSize { Val = run.Item2.Size }); if (run.Item2.Bold) @@ -98,24 +96,97 @@ namespace SushiBarBusinessLogic.OfficePackage.Implements properties.AppendChild(new Bold()); } docRun.AppendChild(properties); - docRun.AppendChild(new Text - { - Text = run.Item1, - Space = SpaceProcessingModeValues.Preserve - }); + + docRun.AppendChild(new Text { Text = run.Item1, Space = SpaceProcessingModeValues.Preserve }); + docParagraph.AppendChild(docRun); } + _docBody.AppendChild(docParagraph); } - protected override void SaveWord(WordInfo info) + + protected override void SaveWord(IDocument info) { if (_docBody == null || _wordDocument == null) { return; } _docBody.AppendChild(CreateSectionProperties()); + _wordDocument.MainDocumentPart!.Document.Save(); _wordDocument.Dispose(); } + + private Table? _lastTable; + protected override void CreateTable(List columns) + { + if (_docBody == null) + return; + + _lastTable = new Table(); + + var tableProp = new TableProperties(); + tableProp.AppendChild(new TableLayout { Type = TableLayoutValues.Fixed }); + tableProp.AppendChild(new TableBorders( + new TopBorder() { Val = new EnumValue(BorderValues.Single), Size = 4 }, + new LeftBorder() { Val = new EnumValue(BorderValues.Single), Size = 4 }, + new RightBorder() { Val = new EnumValue(BorderValues.Single), Size = 4 }, + new BottomBorder() { Val = new EnumValue(BorderValues.Single), Size = 4 }, + new InsideHorizontalBorder() { Val = new EnumValue(BorderValues.Single), Size = 4 }, + new InsideVerticalBorder() { Val = new EnumValue(BorderValues.Single), Size = 4 } + )); + tableProp.AppendChild(new TableWidth { Type = TableWidthUnitValues.Auto }); + _lastTable.AppendChild(tableProp); + + TableGrid tableGrid = new TableGrid(); + foreach (var column in columns) + { + tableGrid.AppendChild(new GridColumn() { Width = column }); + } + _lastTable.AppendChild(tableGrid); + + _docBody.AppendChild(_lastTable); + } + + protected override void CreateRow(WordRowParameters rowParameters) + { + if (_docBody == null || _lastTable == null) + return; + + TableRow docRow = new TableRow(); + foreach (var column in rowParameters.Texts) + { + var docParagraph = new Paragraph(); + WordParagraph paragraph = new WordParagraph + { + Texts = new List<(string, WordTextProperties)> { (column, rowParameters.TextProperties) }, + TextProperties = rowParameters.TextProperties + }; + + docParagraph.AppendChild(CreateParagraphProperties(paragraph.TextProperties)); + + foreach (var run in paragraph.Texts) + { + var docRun = new Run(); + + var properties = new RunProperties(); + properties.AppendChild(new FontSize { Val = run.Item2.Size }); + if (run.Item2.Bold) + { + properties.AppendChild(new Bold()); + } + docRun.AppendChild(properties); + + docRun.AppendChild(new Text { Text = run.Item1, Space = SpaceProcessingModeValues.Preserve }); + + docParagraph.AppendChild(docRun); + } + + TableCell docCell = new TableCell(); + docCell.AppendChild(docParagraph); + docRow.AppendChild(docCell); + } + _lastTable.AppendChild(docRow); + } } } diff --git a/SushiBar/SushiBarBusinessLogic_/OrderLogic.cs b/SushiBar/SushiBarBusinessLogic_/OrderLogic.cs index b1ea738..d101c25 100644 --- a/SushiBar/SushiBarBusinessLogic_/OrderLogic.cs +++ b/SushiBar/SushiBarBusinessLogic_/OrderLogic.cs @@ -19,18 +19,39 @@ namespace SushiBarBusinessLogic.BusinessLogics { private readonly ILogger _logger; private readonly IOrderStorage _orderStorage; - private readonly AbstractMailWorker _mailWorker; - static readonly object _locker = new object(); - public OrderLogic(ILogger logger, IOrderStorage orderStorage, AbstractMailWorker mailWorker) - { + private readonly AbstractMailWorker _mailWorker; + static readonly object _locker = new object(); + private readonly IShopStorage _shopStorage; + public OrderLogic(ILogger logger, IOrderStorage orderStorage, IShopStorage shopStorage, AbstractMailWorker mailWorker) + { _logger = logger; _orderStorage = orderStorage; - _mailWorker = mailWorker; - } + _shopStorage = shopStorage; + _mailWorker = mailWorker; + } + + public OrderViewModel? ReadElement(OrderSearchModel model) + { + if (model == null) + { + throw new ArgumentNullException(nameof(model)); + } + _logger.LogInformation("ReadElement. ClientId:{ClientId}.Status:{Status}.ImplementerId:{ImplementerId}.DateFrom:{DateFrom}.DateTo:{DateTo}OrderId:{Id}", + model.ClientId, model.Status, model.ImplementerId, model.DateFrom, model.DateTo, model.Id); + var element = _orderStorage.GetElement(model); + if (element == null) + { + _logger.LogWarning("ReadElement element not found"); + return null; + } + _logger.LogInformation("ReadElement find. Id:{Id}", element.Id); + return element; + } + public List? ReadList(OrderSearchModel? model) { _logger.LogInformation("ReadList. ClientId:{ClientId}.Status:{Status}.ImplementerId:{ImplementerId}.DateFrom:{DateFrom}.DateTo:{DateTo}OrderId:{Id}", - model?.ClientId, model?.Status, model?.ImplementerId, model?.DateFrom, model?.DateTo, model?.Id); + model?.ClientId, model?.Status, model?.ImplementerId, model?.DateFrom, model?.DateTo, model?.Id); var list = model == null ? _orderStorage.GetFullList() : _orderStorage.GetFilteredList(model); if (list == null) { @@ -40,25 +61,26 @@ namespace SushiBarBusinessLogic.BusinessLogics _logger.LogInformation("ReadList. Count:{Count}", list.Count); return list; } + public bool CreateOrder(OrderBindingModel model) { CheckModel(model); if (model.Status != OrderStatus.Неизвестен) return false; model.Status = OrderStatus.Принят; - var element = _orderStorage.Insert(model); - if (element == null) - { + var element = _orderStorage.Insert(model); + if (element == null) + { _logger.LogWarning("Insert operation failed"); return false; } - Task.Run(() => _mailWorker.MailSendAsync(new MailSendInfoBindingModel - { - MailAddress = element.ClientEmail, - Subject = $"Изменение статуса заказа номер {element.Id}", - Text = $"Ваш заказ номер {element.Id} на суши {element.SushiName} от {element.DateCreate} на сумму {element.Sum} принят." - })); - return true; + Task.Run(() => _mailWorker.MailSendAsync(new MailSendInfoBindingModel + { + MailAddress = element.ClientEmail, + Subject = $"Изменение статуса заказа номер {element.Id}", + Text = $"Ваш заказ номер {element.Id} на пиццу {element.SushiName} от {element.DateCreate} на сумму {element.Sum} принят." + })); + return true; } public bool TakeOrderInWork(OrderBindingModel model) @@ -76,7 +98,31 @@ namespace SushiBarBusinessLogic.BusinessLogics public bool DeliveryOrder(OrderBindingModel model) { - return ChangeStatus(model, OrderStatus.Выдан); + lock (_locker) + { + (model, var element) = FillOrderBindingModel(model); + if (model.Status != OrderStatus.Готов && model.Status != OrderStatus.Ожидает) + { + _logger.LogWarning("Changing status operation faled: Current-{Status}:required-Выдан.", model.Status); + throw new InvalidOperationException($"Невозможно приствоить статус выдан заказу с текущим статусом {model.Status}"); + } + if (!_shopStorage.RestockingShops(new SupplyBindingModel + { + SushiId = model.SushiId, + Count = model.Count + })) + { + if (model.Status == OrderStatus.Готов) + { + model.Status = OrderStatus.Ожидает; + + UpdateOrder(model, element); + } + throw new ArgumentException("Недостаточно места в магазинах для поставки"); + } + model.Status = OrderStatus.Выдан; + return UpdateOrder(model, element); + } } private void CheckModel(OrderBindingModel model, bool withParams = true) @@ -104,8 +150,22 @@ namespace SushiBarBusinessLogic.BusinessLogics _logger.LogInformation("Sushi. SushiId:{SushiId}.Count:{Count}.Sum:{Sum}Id:{Id}", model.SushiId, model.Count, model.Sum, model.Id); } - private bool ChangeStatus(OrderBindingModel model, OrderStatus requiredStatus) + { + (model, var element) = FillOrderBindingModel(model); + + if (requiredStatus - model.Status == 1) + { + model.Status = requiredStatus; + if (model.Status == OrderStatus.Готов) + model.DateImplement = DateTime.Now; + return UpdateOrder(model, element); + } + _logger.LogWarning("Changing status operation faled: Current-{Status}:required-{requiredStatus}.", model.Status, requiredStatus); + throw new InvalidOperationException($"Невозможно приствоить статус {requiredStatus} заказу с текущим статусом {model.Status}"); + } + + private (OrderBindingModel, OrderViewModel) FillOrderBindingModel(OrderBindingModel model) { CheckModel(model, false); var element = _orderStorage.GetElement(new OrderSearchModel() @@ -116,59 +176,38 @@ namespace SushiBarBusinessLogic.BusinessLogics { throw new InvalidOperationException(nameof(element)); } + model.Id = element.Id; model.DateCreate = element.DateCreate; model.SushiId = element.SushiId; model.DateImplement = element.DateImplement; model.ClientId = element.ClientId; + model.Status = element.Status; + model.Count = element.Count; + model.Sum = element.Sum; if (!model.ImplementerId.HasValue) { model.ImplementerId = element.ImplementerId; } - model.Status = element.Status; - model.Count = element.Count; - model.Sum = element.Sum; - if (requiredStatus - model.Status == 1) - { - model.Status = requiredStatus; - if (model.Status == OrderStatus.Готов) - { - model.DateImplement = DateTime.Now; - } - if (_orderStorage.Update(model) == null) - { - _logger.LogWarning("Update operation failed"); - return false; - } - string DateInfo = model.DateImplement.HasValue ? $"Дата выполнения {model.DateImplement}" : ""; - Task.Run(() => _mailWorker.MailSendAsync(new MailSendInfoBindingModel - { - MailAddress = element.ClientEmail, - Subject = $"Изменение статуса заказа номер {element.Id}", - Text = $"Ваш заказ номер {element.Id} на суши {element.SushiName} от {element.DateCreate} на сумму {element.Sum} {model.Status}. {DateInfo}" - })); - return true; - } - _logger.LogWarning("Changing status operation faled: Current-{Status}:required-{requiredStatus}.", model.Status, requiredStatus); - throw new InvalidOperationException($"Невозможно приствоить статус {requiredStatus} заказу с текущим статусом {model.Status}"); - + return (model, element); } - public OrderViewModel? ReadElement(OrderSearchModel model) + private bool UpdateOrder(OrderBindingModel model, OrderViewModel MailNotificationModel) { - if (model == null) + if (_orderStorage.Update(model) == null) { - throw new ArgumentNullException(nameof(model)); + _logger.LogWarning("Update operation failed"); + return false; } - _logger.LogInformation("ReadElement. ClientId:{ClientId}.Status:{Status}.ImplementerId:{ImplementerId}.DateFrom:{DateFrom}.DateTo:{DateTo}OrderId:{Id}", - model.ClientId, model.Status, model.ImplementerId, model.DateFrom, model.DateTo, model.Id); - var element = _orderStorage.GetElement(model); - if (element == null) + _logger.LogWarning("Update operation sucsess"); + string DateInfo = model.DateImplement.HasValue ? $"Дата выполнения {model.DateImplement}" : ""; + Task.Run(() => _mailWorker.MailSendAsync(new MailSendInfoBindingModel { - _logger.LogWarning("ReadElement element not found"); - return null; - } - _logger.LogInformation("ReadElement find. Id:{Id}", element.Id); - return element; + MailAddress = MailNotificationModel.ClientEmail, + Subject = $"Изменение статуса заказа номер {MailNotificationModel.Id}", + Text = $"Ваш заказ номер {MailNotificationModel.Id} на изделие {MailNotificationModel.SushiName} от" + + $" {MailNotificationModel.DateCreate} на сумму {MailNotificationModel.Sum} {model.Status}. {DateInfo}" + })); + return true; } } -} +} \ No newline at end of file diff --git a/SushiBar/SushiBarBusinessLogic_/WorkModeling .cs b/SushiBar/SushiBarBusinessLogic_/WorkModeling .cs index 14802a4..39a5b00 100644 --- a/SushiBar/SushiBarBusinessLogic_/WorkModeling .cs +++ b/SushiBar/SushiBarBusinessLogic_/WorkModeling .cs @@ -36,7 +36,8 @@ namespace SushiBarBusinessLogic return; } var orders = _orderLogic.ReadList(new OrderSearchModel { Status = OrderStatus.Принят }); - if (orders == null || orders.Count == 0) + + if (orders == null ) { _logger.LogWarning("DoWork. Orders is null or empty"); return; @@ -54,7 +55,8 @@ namespace SushiBarBusinessLogic { return; } - await RunOrderInWork(implementer); + await DeliverWaitingOrder(implementer); + await RunOrderInWork(implementer); await Task.Run(() => { @@ -76,7 +78,8 @@ namespace SushiBarBusinessLogic { Id = order.Id }); - } + _orderLogic.DeliveryOrder(new OrderBindingModel { Id = order.Id }); + } // кто-то мог уже перехватить заказ, игнорируем ошибку catch (InvalidOperationException ex) { @@ -135,5 +138,47 @@ namespace SushiBarBusinessLogic throw; } } - } + + private async Task DeliverWaitingOrder(ImplementerViewModel implementer) + { + if (_orderLogic == null || implementer == null) + { + return; + } + var waitingOrders = await Task.Run(() => _orderLogic.ReadList(new OrderSearchModel + { + ImplementerId = implementer.Id, + Status = OrderStatus.Ожидает + })); + if (waitingOrders == null || waitingOrders.Count == 0) + { + return; + } + _logger.LogInformation("DeliverWaitingOrder. Find some waitig order for implementer:{id}.Count:{count}", implementer.Id, waitingOrders.Count); + foreach (var waitingOrder in waitingOrders) + { + try + { + _logger.LogInformation("DeliverWaitingOrder. Trying to deliver order id:{id}", waitingOrder.Id); + var res = _orderLogic.DeliveryOrder(new OrderBindingModel + { + Id = waitingOrder.Id + }); + } + catch (ArgumentException ex) + { + _logger.LogWarning(ex, "DeliverWaitingOrder. Fault"); + } + catch (InvalidOperationException ex) + { + _logger.LogWarning(ex, "Error try deliver order"); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error while do work"); + throw; + } + } + } + } } diff --git a/SushiBar/SushiBarClientApp/APIClient.cs b/SushiBar/SushiBarClientApp/APIClient.cs index 83268e4..05ad940 100644 --- a/SushiBar/SushiBarClientApp/APIClient.cs +++ b/SushiBar/SushiBarClientApp/APIClient.cs @@ -10,14 +10,18 @@ namespace SushiBarClientApp public class APIClient { private static readonly HttpClient _client = new(); + + public static string? Password { get; set; } public static ClientViewModel? Client { get; set; } = null; + public static int MailPage { get; set; } = 1; + public static void Connect(IConfiguration configuration) { _client.BaseAddress = new Uri(configuration["IPAddress"]); _client.DefaultRequestHeaders.Accept.Clear(); - _client.DefaultRequestHeaders.Accept.Add(new - MediaTypeWithQualityHeaderValue("application/json")); + _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); } + public static T? GetRequest(string requestUrl) { var response = _client.GetAsync(requestUrl); @@ -31,12 +35,24 @@ namespace SushiBarClientApp throw new Exception(result); } } + public static void PostRequest(string requestUrl, T model) { var json = JsonConvert.SerializeObject(model); - var data = new StringContent(json, Encoding.UTF8, - "application/json"); + var data = new StringContent(json, Encoding.UTF8, "application/json"); + var response = _client.PostAsync(requestUrl, data); + + var result = response.Result.Content.ReadAsStringAsync().Result; + if (!response.Result.IsSuccessStatusCode) + { + throw new Exception(result); + } + } + + public static void DeleteRequest(string requestUrl) + { + var response = _client.DeleteAsync(requestUrl); var result = response.Result.Content.ReadAsStringAsync().Result; if (!response.Result.IsSuccessStatusCode) { @@ -44,5 +60,5 @@ namespace SushiBarClientApp } } } - } + diff --git a/SushiBar/SushiBarClientApp/Controllers/HomeController.cs b/SushiBar/SushiBarClientApp/Controllers/HomeController.cs index 35552d9..f2831e8 100644 --- a/SushiBar/SushiBarClientApp/Controllers/HomeController.cs +++ b/SushiBar/SushiBarClientApp/Controllers/HomeController.cs @@ -11,19 +11,21 @@ namespace SushiBarClientApp.Controllers public class HomeController : Controller { private readonly ILogger _logger; + public HomeController(ILogger logger) { _logger = logger; } + public IActionResult Index() { if (APIClient.Client == null) { return Redirect("~/Home/Enter"); } - return - View(APIClient.GetRequest>($"api/main/getorders?clientId={APIClient.Client.Id}")); + return View(APIClient.GetRequest>($"api/main/getorders?clientId={APIClient.Client.Id}")); } + [HttpGet] public IActionResult Privacy() { @@ -33,6 +35,7 @@ namespace SushiBarClientApp.Controllers } return View(APIClient.Client); } + [HttpPost] public void Privacy(string login, string password, string fio) { @@ -40,70 +43,65 @@ namespace SushiBarClientApp.Controllers { throw new Exception("Вы как суда попали? Суда вход только авторизованным"); } - if (string.IsNullOrEmpty(login) || - string.IsNullOrEmpty(password) || string.IsNullOrEmpty(fio)) + if (string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(fio)) { throw new Exception("Введите логин, пароль и ФИО"); } - APIClient.PostRequest("api/client/updatedata", new - ClientBindingModel + APIClient.PostRequest("api/client/updatedata", new ClientBindingModel { Id = APIClient.Client.Id, ClientFIO = fio, Email = login, Password = password }); + APIClient.Client.ClientFIO = fio; APIClient.Client.Email = login; APIClient.Client.Password = password; Response.Redirect("Index"); } - [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, - NoStore = true)] + + [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public IActionResult Error() { - return View(new ErrorViewModel - { - RequestId = - Activity.Current?.Id ?? HttpContext.TraceIdentifier - }); + return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); } + [HttpGet] public IActionResult Enter() { return View(); } + [HttpPost] public void Enter(string login, string password) { - if (string.IsNullOrEmpty(login) || - string.IsNullOrEmpty(password)) + if (string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password)) { throw new Exception("Введите логин и пароль"); } - APIClient.Client = - APIClient.GetRequest($"api/client/login?login={login}&password={password}"); + APIClient.Client = APIClient.GetRequest($"api/client/login?login={login}&password={password}"); if (APIClient.Client == null) { throw new Exception("Неверный логин/пароль"); } Response.Redirect("Index"); } + [HttpGet] public IActionResult Register() { return View(); } + [HttpPost] public void Register(string login, string password, string fio) { - if (string.IsNullOrEmpty(login) || - string.IsNullOrEmpty(password) || string.IsNullOrEmpty(fio)) + if (string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(fio)) { throw new Exception("Введите логин, пароль и ФИО"); } - APIClient.PostRequest("api/client/register", new - ClientBindingModel + APIClient.PostRequest("api/client/register", new ClientBindingModel { ClientFIO = fio, Email = login, @@ -112,15 +110,16 @@ namespace SushiBarClientApp.Controllers Response.Redirect("Enter"); return; } + [HttpGet] public IActionResult Create() { - ViewBag.Sushis = - APIClient.GetRequest>("api/main/getsushilist"); + ViewBag.Sushis = APIClient.GetRequest>("api/main/getSushilist"); return View(); } + [HttpPost] - public void Create(int sushi, int count) + public void Create(int Sushi, int count) { if (APIClient.Client == null) { @@ -133,31 +132,31 @@ namespace SushiBarClientApp.Controllers APIClient.PostRequest("api/main/createorder", new OrderBindingModel { ClientId = APIClient.Client.Id, - SushiId = sushi, + SushiId = Sushi, Count = count, - Sum = Calc(count, sushi) + Sum = Calc(count, Sushi) }); Response.Redirect("Index"); } + [HttpPost] - public double Calc(int count, int sushi) + public double Calc(int count, int Sushi) { - var prod = - APIClient.GetRequest($"api/main/getsushi?sushiId={sushi}" - ); - return count * (prod?.Price ?? 1); + var sus = APIClient.GetRequest($"api/main/getSushi?SushiId={Sushi}"); + return count * (sus?.Price ?? 1); } [HttpGet] - public IActionResult Mails() + public IActionResult Mails(int page = 1) { if (APIClient.Client == null) { return Redirect("~/Home/Enter"); } - return View(APIClient.GetRequest>($"api/client/getmessages?clientId={APIClient.Client.Id}")); - } + page = Math.Max(page, 1); + return View(APIClient.GetRequest>($"api/client/getmessages?clientId={APIClient.Client.Id}&page={page}")); + } } } diff --git a/SushiBar/SushiBarClientApp/Views/Home/Index.cshtml b/SushiBar/SushiBarClientApp/Views/Home/Index.cshtml index 843135f..4cedcf6 100644 --- a/SushiBar/SushiBarClientApp/Views/Home/Index.cshtml +++ b/SushiBar/SushiBarClientApp/Views/Home/Index.cshtml @@ -15,61 +15,61 @@ @{ if (Model == null) { -

Авторизируйтесь

+

Авторизируйтесь

return; } -

- Создать заказ -

- - - - - - - - - - - - +

+ Создать заказ +

+
- Номер - - Суши - - Дата создания - - Количество - - Сумма - - Статус -
+ + + + + + + + + + + @foreach (var item in Model) { - - + - + - + - + - + - + - + + } - -
+ Номер + + Пицца + + Дата создания + + Количество + + Сумма + + Статус +
+
@Html.DisplayFor(modelItem => item.Id) - + @Html.DisplayFor(modelItem => item.SushiName) - + @Html.DisplayFor(modelItem => item.DateCreate) - + @Html.DisplayFor(modelItem => item.Count) - + @Html.DisplayFor(modelItem => item.Sum) - + @Html.DisplayFor(modelItem => item.Status) -
+ + } \ No newline at end of file diff --git a/SushiBar/SushiBarClientApp/Views/Home/Mails.cshtml b/SushiBar/SushiBarClientApp/Views/Home/Mails.cshtml index b1fa224..fc65729 100644 --- a/SushiBar/SushiBarClientApp/Views/Home/Mails.cshtml +++ b/SushiBar/SushiBarClientApp/Views/Home/Mails.cshtml @@ -1,6 +1,7 @@ @using SushiBarContracts.ViewModels @model List +@Url.ActionContext.RouteData.Values["page"] @{ ViewData["Title"] = "Mails"; @@ -16,40 +17,58 @@ @{ if (Model == null) { -

Авторизируйтесь

+

Авторизируйтесь

return; } - - - - - - - - - +
- Дата письма - - Заголовок - - Текст -
+ + + + + + + + @foreach (var item in Model) { - - + - + - + - + + } - -
+ Дата письма + + Заголовок + + Текст +
+
@Html.DisplayFor(modelItem => item.DateDelivery) - + @Html.DisplayFor(modelItem => item.Subject) - + @Html.DisplayFor(modelItem => item.Body) -
+ + +
+ @{ + int page = int.Parse(Context.Request.Query["page"]); +
+ +
+ if (page > 1) + { + <- + } + else + { +

<-

+ } + + -> + } +
} - + \ No newline at end of file diff --git a/SushiBar/SushiBarClientApp/Views/Home/Shop.cshtml b/SushiBar/SushiBarClientApp/Views/Home/Shop.cshtml new file mode 100644 index 0000000..3c7dca9 --- /dev/null +++ b/SushiBar/SushiBarClientApp/Views/Home/Shop.cshtml @@ -0,0 +1,74 @@ +@using SushiBarDataModels.Models; +@using SushiBarContracts.ViewModels; + @model ShopSushiViewModel + +@{ + ViewData["Title"] = "Shop"; +} + +
+ @{ + if (Model == null) + { +

Создание магазина

+ } + else + { +

Изменение магазина

+ } + } +
+ +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + @{ + if (Model != null && Model.Shop != null) + { + + } + } +
+
+@{ + if (Model != null && Model.Shop != null) + { +
+
Содержимое магазина
+
+ + + + + + + + + @foreach (var item in Model.ShopSushi) + { + + + + + } + + +
НазваниеКоличество
@Html.DisplayFor(modelItem => item.Value.Sushi.SushiName)@Html.DisplayFor(modelItem => item.Value.Count)
+ } +} \ No newline at end of file diff --git a/SushiBar/SushiBarClientApp/Views/Home/Supply.cshtml b/SushiBar/SushiBarClientApp/Views/Home/Supply.cshtml new file mode 100644 index 0000000..a5a73ae --- /dev/null +++ b/SushiBar/SushiBarClientApp/Views/Home/Supply.cshtml @@ -0,0 +1,22 @@ +@{ + ViewData["Title"] = "Supply"; +} +
+

Создание поставки

+
+
+
+ + +
+
+ + +
+
+ + +
+ + Отмена +
diff --git a/SushiBar/SushiBarClientApp/Views/Shared/_Layout.cshtml b/SushiBar/SushiBarClientApp/Views/Shared/_Layout.cshtml index d2b20db..2049c06 100644 --- a/SushiBar/SushiBarClientApp/Views/Shared/_Layout.cshtml +++ b/SushiBar/SushiBarClientApp/Views/Shared/_Layout.cshtml @@ -14,27 +14,28 @@