diff --git a/BlacksmithWorkshop/BlacksmithListImplement/DataListSingleton.cs b/BlacksmithWorkshop/BlacksmithListImplement/DataListSingleton.cs index 75ddb55..b4c9366 100644 --- a/BlacksmithWorkshop/BlacksmithListImplement/DataListSingleton.cs +++ b/BlacksmithWorkshop/BlacksmithListImplement/DataListSingleton.cs @@ -17,7 +17,8 @@ namespace BlacksmithWorkshopListImplement public List Clients { get; set; } public List Implementers { get; set; } public List Shops { get; set; } - private DataListSingleton() + public List MessageInfos { get; set; } + private DataListSingleton() { Components = new List(); Orders = new List(); @@ -25,6 +26,7 @@ namespace BlacksmithWorkshopListImplement Shops = new List(); Clients = new List(); Implementers = new List(); + MessageInfos = new List(); } public static DataListSingleton GetInstance() { @@ -35,4 +37,4 @@ namespace BlacksmithWorkshopListImplement return _instance; } } -} \ No newline at end of file +} diff --git a/BlacksmithWorkshop/BlacksmithListImplement/Implements/MessageInfoStorage.cs b/BlacksmithWorkshop/BlacksmithListImplement/Implements/MessageInfoStorage.cs new file mode 100644 index 0000000..a2467f5 --- /dev/null +++ b/BlacksmithWorkshop/BlacksmithListImplement/Implements/MessageInfoStorage.cs @@ -0,0 +1,77 @@ +using BlacksmithWorkshopContracts.BindingModels; +using BlacksmithWorkshopContracts.SearchModels; +using BlacksmithWorkshopContracts.StorageContracts; +using BlacksmithWorkshopContracts.ViewModels; +using BlacksmithWorkshopListImplement.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BlacksmithWorkshopListImplement.Implements +{ + public class MessageInfoStorage : IMessageInfoStorage + { + private readonly DataListSingleton _source; + public MessageInfoStorage() + { + _source = DataListSingleton.GetInstance(); + } + public MessageInfoViewModel? GetElement(MessageInfoSearchModel model) + { + foreach (var elem in _source.MessageInfos) + { + if (!string.IsNullOrEmpty(model.MessageId) && model.MessageId == elem.MessageId) + return elem.GetViewModel; + } + return null; + } + public List GetFilteredList(MessageInfoSearchModel model) + { + var result = new List(); + if (model.ClientId.HasValue) + { + foreach (var message in _source.MessageInfos) + { + if (message.ClientId.HasValue && message.ClientId == model.ClientId) + { + result.Add(message.GetViewModel); + } + } + } + return result; + } + public List GetFullList() + { + var result = new List(); + foreach (var message in _source.MessageInfos) + { + result.Add(message.GetViewModel); + } + return result; + } + public MessageInfoViewModel? Insert(MessageInfoBindingModel model) + { + var newMessage = MessageInfo.Create(model); + if (newMessage == null) + { + return null; + } + _source.MessageInfos.Add(newMessage); + return newMessage.GetViewModel; + } + public MessageInfoViewModel? Update(MessageInfoBindingModel model) + { + foreach (var message in _source.MessageInfos) + { + if (message.MessageId == model.MessageId) + { + message.Update(model); + return message.GetViewModel; + } + } + return null; + } + } +} diff --git a/BlacksmithWorkshop/BlacksmithListImplement/Models/MessageInfo.cs b/BlacksmithWorkshop/BlacksmithListImplement/Models/MessageInfo.cs new file mode 100644 index 0000000..20f6242 --- /dev/null +++ b/BlacksmithWorkshop/BlacksmithListImplement/Models/MessageInfo.cs @@ -0,0 +1,55 @@ +using BlacksmithWorkshopContracts.BindingModels; +using BlacksmithWorkshopContracts.ViewModels; +using BlacksmithWorkshopDataModels.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BlacksmithWorkshopListImplement.Models +{ + public class MessageInfo : IMessageInfoModel + { + public string MessageId { get; private set; } = string.Empty; + public int? ClientId { get; private set; } + public string SenderName { get; private set; } = string.Empty; + public DateTime DateDelivery { get; private set; } = DateTime.Now; + public string Subject { get; private set; } = string.Empty; + public string Body { get; private set; } = string.Empty; + public bool IsRead { get; private set; } = false; + public string? ReplyText { get; private set; } + public static MessageInfo? Create(MessageInfoBindingModel? model) + { + if (model == null) + { + return null; + } + return new MessageInfo() + { + MessageId = model.MessageId, + ClientId = model.ClientId, + SenderName = model.SenderName, + DateDelivery = model.DateDelivery, + Subject = model.Subject, + Body = model.Body + }; + } + public void Update(MessageInfoBindingModel model) + { + IsRead = model.IsRead; + ReplyText = model.ReplyText; + } + public MessageInfoViewModel GetViewModel => new() + { + MessageId = MessageId, + ClientId = ClientId, + SenderName = SenderName, + DateDelivery = DateDelivery, + Subject = Subject, + Body = Body, + IsRead = IsRead, + ReplyText = ReplyText + }; + } +} diff --git a/BlacksmithWorkshop/BlacksmithWorkshopBusinessLogic/BlacksmithWorkshopBusinessLogic.csproj b/BlacksmithWorkshop/BlacksmithWorkshopBusinessLogic/BlacksmithWorkshopBusinessLogic.csproj index ab679fa..805f20b 100644 --- a/BlacksmithWorkshop/BlacksmithWorkshopBusinessLogic/BlacksmithWorkshopBusinessLogic.csproj +++ b/BlacksmithWorkshop/BlacksmithWorkshopBusinessLogic/BlacksmithWorkshopBusinessLogic.csproj @@ -8,6 +8,7 @@ + diff --git a/BlacksmithWorkshop/BlacksmithWorkshopBusinessLogic/BusinessLogics/ClientLogic.cs b/BlacksmithWorkshop/BlacksmithWorkshopBusinessLogic/BusinessLogics/ClientLogic.cs index 9692616..7cc3745 100644 --- a/BlacksmithWorkshop/BlacksmithWorkshopBusinessLogic/BusinessLogics/ClientLogic.cs +++ b/BlacksmithWorkshop/BlacksmithWorkshopBusinessLogic/BusinessLogics/ClientLogic.cs @@ -9,6 +9,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; +using System.Text.RegularExpressions; using System.Threading.Tasks; namespace BlacksmithWorkshopBusinessLogic.BusinessLogics @@ -103,6 +104,15 @@ namespace BlacksmithWorkshopBusinessLogic.BusinessLogics { throw new ArgumentNullException("Нет пароля учетной записи клиента", nameof(model.ClientFIO)); } + if (!Regex.IsMatch(model.Email, @"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$", RegexOptions.IgnoreCase)) + { + throw new ArgumentException("Некорректная адрес электронной почты", nameof(model.Email)); + } + if (!Regex.IsMatch(model.Password, @"^((\w+\d+\W+)|(\w+\W+\d+)|(\d+\w+\W+)|(\d+\W+\w+)|(\W+\w+\d+)|(\W+\d+\w+))[\w\d\W]*$") + || model.Password.Length < 10 || model.Password.Length > 50) + { + throw new ArgumentException("Некорректный пароль", nameof(model.Password)); + } _logger.LogInformation("Client. ClientFIO:{ClientFIO}. Email:{Email}. Password:{Password}. Id:{Id}", model.ClientFIO, model.Email, model.Password, model.Id); var element = _clientStorage.GetElement(new ClientSearchModel { diff --git a/BlacksmithWorkshop/BlacksmithWorkshopBusinessLogic/BusinessLogics/MessageInfoLogic.cs b/BlacksmithWorkshop/BlacksmithWorkshopBusinessLogic/BusinessLogics/MessageInfoLogic.cs new file mode 100644 index 0000000..7d397a5 --- /dev/null +++ b/BlacksmithWorkshop/BlacksmithWorkshopBusinessLogic/BusinessLogics/MessageInfoLogic.cs @@ -0,0 +1,71 @@ +using BlacksmithWorkshopContracts.BindingModels; +using BlacksmithWorkshopContracts.BusinessLogicsContracts; +using BlacksmithWorkshopContracts.SearchModels; +using BlacksmithWorkshopContracts.StorageContracts; +using BlacksmithWorkshopContracts.ViewModels; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BlacksmithWorkshopBusinessLogic.BusinessLogics +{ + public class MessageInfoLogic : IMessageInfoLogic + { + private readonly ILogger _logger; + private readonly IMessageInfoStorage _messageInfoStorage; + public MessageInfoLogic(ILogger logger, IMessageInfoStorage messageInfoStorage) + { + _logger = logger; + _messageInfoStorage = messageInfoStorage; + } + public bool Create(MessageInfoBindingModel model) + { + if (_messageInfoStorage.Insert(model) == null) + { + _logger.LogWarning("Insert operation failed"); + return false; + } + return true; + } + 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. MessageId:{Id}", element.MessageId); + return element; + } + public List? ReadList(MessageInfoSearchModel? model) + { + _logger.LogInformation("ReadList. MessageId:{MessageId}", model?.MessageId); + var list = model == null ? _messageInfoStorage.GetFullList() : _messageInfoStorage.GetFilteredList(model); + if (list == null) + { + _logger.LogWarning("ReadList return null list"); + return null; + } + _logger.LogInformation("ReadList. Count:{Count}", list.Count); + return list.OrderByDescending(x => x.DateDelivery).ToList(); + } + public bool Update(MessageInfoBindingModel model) + { + if (_messageInfoStorage.Update(model) == null) + { + _logger.LogWarning("Update operation failed"); + return false; + } + return true; + } + } +} diff --git a/BlacksmithWorkshop/BlacksmithWorkshopBusinessLogic/BusinessLogics/OrderLogic.cs b/BlacksmithWorkshop/BlacksmithWorkshopBusinessLogic/BusinessLogics/OrderLogic.cs index 822a50b..d77c1a2 100644 --- a/BlacksmithWorkshop/BlacksmithWorkshopBusinessLogic/BusinessLogics/OrderLogic.cs +++ b/BlacksmithWorkshop/BlacksmithWorkshopBusinessLogic/BusinessLogics/OrderLogic.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; - +using BlacksmithWorkshopBusinessLogic.MailWorker; using BlacksmithWorkshopContracts.BindingModels; using BlacksmithWorkshopContracts.BusinessLogicsContracts; using BlacksmithWorkshopContracts.SearchModels; @@ -20,12 +20,16 @@ namespace BlacksmithWorkshopBusinessLogic.BusinessLogics private readonly IOrderStorage _orderStorage; private readonly IShopLogic _shopLogic; private readonly IManufactureStorage _manufactureStorage; - public OrderLogic(ILogger logger, IOrderStorage orderStorage, IShopLogic shopLogic, IManufactureStorage manufactureStorage) + private readonly AbstractMailWorker _abstractMailWorker; + private readonly IClientStorage _clientStorage; + public OrderLogic(ILogger logger, IOrderStorage orderStorage, IShopLogic shopLogic, IManufactureStorage manufactureStorage, AbstractMailWorker abstractMailWorker, IClientStorage clientStorage) { _logger = logger; _orderStorage = orderStorage; _shopLogic = shopLogic; _manufactureStorage = manufactureStorage; + _abstractMailWorker = abstractMailWorker; + _clientStorage = clientStorage; } public List? ReadList(OrderSearchModel? model) { @@ -57,21 +61,28 @@ namespace BlacksmithWorkshopBusinessLogic.BusinessLogics } public bool CreateOrder(OrderBindingModel model) { - CheckModel(model); - if (model.Status != OrderStatus.Неизвестен) - { - _logger.LogWarning("Insert operation failed. Order status is incorrect."); - return false; - } - model.Status = OrderStatus.Принят; - if (_orderStorage.Insert(model) == null) - { - model.Status = OrderStatus.Неизвестен; - _logger.LogWarning("Insert operation failed"); - return false; - } - return true; - } + CheckModel(model); + if (model.Status != OrderStatus.Неизвестен) + { + _logger.LogWarning("Insert operation failed. Order status is incorrect."); + return false; + } + model.Status = OrderStatus.Принят; + var order = _orderStorage.Insert(model); + if (order == null) + { + _logger.LogWarning("Insert operation failed"); + return false; + } + var client = _clientStorage.GetElement(new() { Id = order.ClientId }); + if (client == null) + { + _logger.LogWarning("Client not found"); + return false; + } + SendMail(client.Email, $"Новый заказ создан. Номер заказа - {order.Id}", $"Заказ №{order.Id} от {order.DateCreate} на сумму {order.Sum:C2} принят."); + return true; + } public bool TakeOrderInWork(OrderBindingModel model) { return StatusUpdate(model, OrderStatus.Выполняется); @@ -132,7 +143,7 @@ namespace BlacksmithWorkshopBusinessLogic.BusinessLogics if (!_shopLogic.AddManufactures(manufacture, viewModel.Count)) { model.Status = OrderStatus.Ожидание; - _logger.LogWarning($"AddManufactures operation failed"); + _logger.LogWarning($"AddTravels operation failed"); } else { @@ -148,12 +159,29 @@ namespace BlacksmithWorkshopBusinessLogic.BusinessLogics model.ImplementerId = viewModel.ImplementerId.Value; } CheckModel(model, false); - if (_orderStorage.Update(model) == null) + var order = _orderStorage.Update(model); + if (order == null) { _logger.LogWarning("Change status operation failed"); return false; } + var client = _clientStorage.GetElement(new() { Id = order.ClientId }); + if (client == null) + { + _logger.LogWarning("Client not found"); + return false; + } + SendMail(client.Email, $"Заказ №{order.Id}", $"Заказ №{order.Id} изменил статус на {order.Status}."); return true; } - } + public void SendMail(string email, string title, string body) + { + _abstractMailWorker.MailSendAsync(new() + { + MailAddress = email, + Subject = title, + Text = body + }); + } + } } diff --git a/BlacksmithWorkshop/BlacksmithWorkshopBusinessLogic/MailWorker/AbstractMailWorker.cs b/BlacksmithWorkshop/BlacksmithWorkshopBusinessLogic/MailWorker/AbstractMailWorker.cs new file mode 100644 index 0000000..f6084f6 --- /dev/null +++ b/BlacksmithWorkshop/BlacksmithWorkshopBusinessLogic/MailWorker/AbstractMailWorker.cs @@ -0,0 +1,81 @@ +using BlacksmithWorkshopContracts.BindingModels; +using BlacksmithWorkshopContracts.BusinessLogicsContracts; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BlacksmithWorkshopBusinessLogic.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; + private readonly IClientLogic _clientLogic; + public AbstractMailWorker(ILogger logger, IMessageInfoLogic messageInfoLogic, IClientLogic clientLogic) + { + _logger = logger; + _messageInfoLogic = messageInfoLogic; + _clientLogic = clientLogic; + } + 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, _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(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; + } + if (string.IsNullOrEmpty(_popHost) || _popPort == 0) + { + return; + } + if (_messageInfoLogic == null) + { + return; + } + var list = await ReceiveMailAsync(); + _logger.LogDebug("Check Mail: {Count} new mails", list.Count); + foreach (var mail in list) + { + mail.ClientId = _clientLogic.ReadElement(new() { Email = mail.SenderName })?.Id; + _messageInfoLogic.Create(mail); + } + } + protected abstract Task SendMailAsync(MailSendInfoBindingModel info); + protected abstract Task> ReceiveMailAsync(); + } +} diff --git a/BlacksmithWorkshop/BlacksmithWorkshopBusinessLogic/MailWorker/MailKitWorker.cs b/BlacksmithWorkshop/BlacksmithWorkshopBusinessLogic/MailWorker/MailKitWorker.cs new file mode 100644 index 0000000..7869e93 --- /dev/null +++ b/BlacksmithWorkshop/BlacksmithWorkshopBusinessLogic/MailWorker/MailKitWorker.cs @@ -0,0 +1,83 @@ +using BlacksmithWorkshopContracts.BindingModels; +using BlacksmithWorkshopContracts.BusinessLogicsContracts; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Mail; +using System.Net; +using System.Security.Authentication; +using System.Text; +using System.Threading.Tasks; +using MailKit.Net.Pop3; +using MailKit.Security; +using AuthenticationException = MailKit.Security.AuthenticationException; + +namespace BlacksmithWorkshopBusinessLogic.MailWorker +{ + public class MailKitWorker : AbstractMailWorker + { + public MailKitWorker(ILogger logger, IMessageInfoLogic messageInfoLogic, IClientLogic clientLogic) + : base(logger, messageInfoLogic, clientLogic) { } + 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; + + objSmtpClient.UseDefaultCredentials = false; + objSmtpClient.EnableSsl = true; + objSmtpClient.DeliveryMethod = SmtpDeliveryMethod.Network; + objSmtpClient.Credentials = new NetworkCredential(_mailLogin, _mailPassword); + + await Task.Run(() => objSmtpClient.Send(objMailMessage)); + } + catch (Exception) + { + throw; + } + } + 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 (AuthenticationException) + { } + finally + { + client.Disconnect(true); + } + }); + return list; + } + } +} diff --git a/BlacksmithWorkshop/BlacksmithWorkshopClientApp/Controllers/HomeController.cs b/BlacksmithWorkshop/BlacksmithWorkshopClientApp/Controllers/HomeController.cs index 8540789..c00cd24 100644 --- a/BlacksmithWorkshop/BlacksmithWorkshopClientApp/Controllers/HomeController.cs +++ b/BlacksmithWorkshop/BlacksmithWorkshopClientApp/Controllers/HomeController.cs @@ -132,5 +132,17 @@ namespace BlacksmithWorkshopClientApp.Controllers var prod = APIClient.GetRequest($"api/main/getmanufacture?manufactureId={manufacture}"); return count * (prod?.Price ?? 1); } - } + [HttpGet] + public IActionResult Mails(int page = 0) + { + if (APIClient.Client == null) + { + return Redirect("~/Home/Enter"); + } + var messages = APIClient.GetRequest>($"api/client/getmessages?clientId={APIClient.Client.Id}&page={page}"); + ViewBag.PageIsLast = messages!.Count == 0; + ViewBag.Page = page; + return View(messages); + } + } } \ No newline at end of file diff --git a/BlacksmithWorkshop/BlacksmithWorkshopClientApp/Views/Home/Mails.cshtml b/BlacksmithWorkshop/BlacksmithWorkshopClientApp/Views/Home/Mails.cshtml new file mode 100644 index 0000000..2dc7a7a --- /dev/null +++ b/BlacksmithWorkshop/BlacksmithWorkshopClientApp/Views/Home/Mails.cshtml @@ -0,0 +1,68 @@ +@using BlacksmithWorkshopContracts.ViewModels; + +@model List + +@{ + ViewData["Title"] = "Mails"; +} + +
+

Письма

+
+ + +
+ @{ + if (Model == null) + { +

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

+ return; + } + + + + + + + + + + + @foreach (var item in Model) + { + + + + + + } + +
+ Дата письма + + Заголовок + + Текст +
+ @Html.DisplayFor(modelItem => item.DateDelivery) + + @Html.DisplayFor(modelItem => item.Subject) + + @Html.DisplayFor(modelItem => item.Body) +
+ } + @if (ViewBag.Page != 0) + { + + < Назад + + } + @if (!ViewBag.PageIsLast) + { + + Вперед > + + } +
\ No newline at end of file diff --git a/BlacksmithWorkshop/BlacksmithWorkshopClientApp/Views/Shared/_Layout.cshtml b/BlacksmithWorkshop/BlacksmithWorkshopClientApp/Views/Shared/_Layout.cshtml index 117c713..d769df3 100644 --- a/BlacksmithWorkshop/BlacksmithWorkshopClientApp/Views/Shared/_Layout.cshtml +++ b/BlacksmithWorkshop/BlacksmithWorkshopClientApp/Views/Shared/_Layout.cshtml @@ -26,6 +26,9 @@ + diff --git a/BlacksmithWorkshop/BlacksmithWorkshopContracts/BindingModels/MailConfigBindingModel.cs b/BlacksmithWorkshop/BlacksmithWorkshopContracts/BindingModels/MailConfigBindingModel.cs new file mode 100644 index 0000000..98000d7 --- /dev/null +++ b/BlacksmithWorkshop/BlacksmithWorkshopContracts/BindingModels/MailConfigBindingModel.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BlacksmithWorkshopContracts.BindingModels +{ + public class MailConfigBindingModel + { + public string MailLogin { get; set; } = string.Empty; + public string MailPassword { get; set; } = string.Empty; + public string SmtpClientHost { get; set; } = string.Empty; + public int SmtpClientPort { get; set; } + public string PopHost { get; set; } = string.Empty; + public int PopPort { get; set; } + } +} diff --git a/BlacksmithWorkshop/BlacksmithWorkshopContracts/BindingModels/MailSendInfoBindingModel.cs b/BlacksmithWorkshop/BlacksmithWorkshopContracts/BindingModels/MailSendInfoBindingModel.cs new file mode 100644 index 0000000..6770bdf --- /dev/null +++ b/BlacksmithWorkshop/BlacksmithWorkshopContracts/BindingModels/MailSendInfoBindingModel.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BlacksmithWorkshopContracts.BindingModels +{ + public class MailSendInfoBindingModel + { + public string MailAddress { get; set; } = string.Empty; + public string Subject { get; set; } = string.Empty; + public string Text { get; set; } = string.Empty; + } +} diff --git a/BlacksmithWorkshop/BlacksmithWorkshopContracts/BindingModels/MessageInfoBindingModel.cs b/BlacksmithWorkshop/BlacksmithWorkshopContracts/BindingModels/MessageInfoBindingModel.cs new file mode 100644 index 0000000..ad2b7a3 --- /dev/null +++ b/BlacksmithWorkshop/BlacksmithWorkshopContracts/BindingModels/MessageInfoBindingModel.cs @@ -0,0 +1,21 @@ +using BlacksmithWorkshopDataModels.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BlacksmithWorkshopContracts.BindingModels +{ + public class MessageInfoBindingModel : IMessageInfoModel + { + public string MessageId { get; set; } = string.Empty; + public int? ClientId { get; set; } + public string SenderName { get; set; } = string.Empty; + public string Subject { get; set; } = string.Empty; + public string Body { get; set; } = string.Empty; + public DateTime DateDelivery { get; set; } + public bool IsRead { get; set; } = false; + public string? ReplyText { get; set; } = string.Empty; + } +} diff --git a/BlacksmithWorkshop/BlacksmithWorkshopContracts/BusinessLogicsContracts/IMessageInfoLogic.cs b/BlacksmithWorkshop/BlacksmithWorkshopContracts/BusinessLogicsContracts/IMessageInfoLogic.cs new file mode 100644 index 0000000..4de4a40 --- /dev/null +++ b/BlacksmithWorkshop/BlacksmithWorkshopContracts/BusinessLogicsContracts/IMessageInfoLogic.cs @@ -0,0 +1,19 @@ +using BlacksmithWorkshopContracts.BindingModels; +using BlacksmithWorkshopContracts.SearchModels; +using BlacksmithWorkshopContracts.ViewModels; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BlacksmithWorkshopContracts.BusinessLogicsContracts +{ + public interface IMessageInfoLogic + { + List? ReadList(MessageInfoSearchModel? model); + bool Create(MessageInfoBindingModel model); + MessageInfoViewModel? ReadElement(MessageInfoSearchModel? model); + bool Update(MessageInfoBindingModel model); + } +} diff --git a/BlacksmithWorkshop/BlacksmithWorkshopContracts/SearchModels/MessageInfoSearchModel.cs b/BlacksmithWorkshop/BlacksmithWorkshopContracts/SearchModels/MessageInfoSearchModel.cs new file mode 100644 index 0000000..51c2ef1 --- /dev/null +++ b/BlacksmithWorkshop/BlacksmithWorkshopContracts/SearchModels/MessageInfoSearchModel.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BlacksmithWorkshopContracts.SearchModels +{ + public class MessageInfoSearchModel + { + public int? ClientId { get; set; } + public string? MessageId { get; set; } + public int? Page { get; set; } + public int? PageSize { get; set; } + } +} diff --git a/BlacksmithWorkshop/BlacksmithWorkshopContracts/StorageContracts/IMessageInfoStorage.cs b/BlacksmithWorkshop/BlacksmithWorkshopContracts/StorageContracts/IMessageInfoStorage.cs new file mode 100644 index 0000000..9a020f0 --- /dev/null +++ b/BlacksmithWorkshop/BlacksmithWorkshopContracts/StorageContracts/IMessageInfoStorage.cs @@ -0,0 +1,20 @@ +using BlacksmithWorkshopContracts.BindingModels; +using BlacksmithWorkshopContracts.SearchModels; +using BlacksmithWorkshopContracts.ViewModels; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BlacksmithWorkshopContracts.StorageContracts +{ + public interface IMessageInfoStorage + { + List GetFullList(); + List GetFilteredList(MessageInfoSearchModel model); + MessageInfoViewModel? GetElement(MessageInfoSearchModel model); + MessageInfoViewModel? Insert(MessageInfoBindingModel model); + MessageInfoViewModel? Update(MessageInfoBindingModel model); + } +} diff --git a/BlacksmithWorkshop/BlacksmithWorkshopContracts/ViewModels/MessageInfoViewModel.cs b/BlacksmithWorkshop/BlacksmithWorkshopContracts/ViewModels/MessageInfoViewModel.cs new file mode 100644 index 0000000..229c91a --- /dev/null +++ b/BlacksmithWorkshop/BlacksmithWorkshopContracts/ViewModels/MessageInfoViewModel.cs @@ -0,0 +1,28 @@ +using BlacksmithWorkshopDataModels.Models; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BlacksmithWorkshopContracts.ViewModels +{ + public class MessageInfoViewModel : IMessageInfoModel + { + public string MessageId { get; set; } = string.Empty; + public int? ClientId { get; set; } + [DisplayName("Отправитель")] + public string SenderName { get; set; } = string.Empty; + [DisplayName("Дата письма")] + public DateTime DateDelivery { get; set; } + [DisplayName("Заголовок")] + public string Subject { get; set; } = string.Empty; + [DisplayName("Текст")] + public string Body { get; set; } = string.Empty; + [DisplayName("Прочитано")] + public bool IsRead { get; set; } = false; + [DisplayName("Ответ")] + public string? ReplyText { get; set; } + } +} diff --git a/BlacksmithWorkshop/BlacksmithWorkshopDataModels/Models/IMessageInfoModel.cs b/BlacksmithWorkshop/BlacksmithWorkshopDataModels/Models/IMessageInfoModel.cs new file mode 100644 index 0000000..1b4da92 --- /dev/null +++ b/BlacksmithWorkshop/BlacksmithWorkshopDataModels/Models/IMessageInfoModel.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BlacksmithWorkshopDataModels.Models +{ + public interface IMessageInfoModel + { + string MessageId { get; } + int? ClientId { get; } + string SenderName { get; } + DateTime DateDelivery { get; } + string Subject { get; } + string Body { get; } + bool IsRead { get; } + string? ReplyText { get; } + } +} diff --git a/BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/BlacksmithWorkshopDatabase.cs b/BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/BlacksmithWorkshopDatabase.cs index 9326ff7..d2661eb 100644 --- a/BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/BlacksmithWorkshopDatabase.cs +++ b/BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/BlacksmithWorkshopDatabase.cs @@ -21,5 +21,6 @@ namespace BlacksmithWorkshopDatabaseImplement public virtual DbSet ListManufacture { set; get; } public virtual DbSet Clients { set; get; } public virtual DbSet Implementers { set; get; } + public virtual DbSet MessageInfos { set; get; } } } diff --git a/BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/BlacksmithWorkshopDatabaseImplement.csproj b/BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/BlacksmithWorkshopDatabaseImplement.csproj index a475681..592c18e 100644 --- a/BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/BlacksmithWorkshopDatabaseImplement.csproj +++ b/BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/BlacksmithWorkshopDatabaseImplement.csproj @@ -20,8 +20,4 @@
- - - - diff --git a/BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/Implements/ClientStorage.cs b/BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/Implements/ClientStorage.cs index 1c7fc1a..9d3991f 100644 --- a/BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/Implements/ClientStorage.cs +++ b/BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/Implements/ClientStorage.cs @@ -52,6 +52,10 @@ namespace BlacksmithWorkshopDatabaseImplement.Implements return context.Clients .FirstOrDefault(x => (x.Email == model.Email && x.Password == model.Password))?.GetViewModel; } + else if (!string.IsNullOrEmpty(model.Email)) + return context.Clients + .FirstOrDefault(x => x.Email == model.Email) + ?.GetViewModel; return new(); } public ClientViewModel? Insert(ClientBindingModel model) diff --git a/BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/Implements/MessageInfoStorage.cs b/BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/Implements/MessageInfoStorage.cs new file mode 100644 index 0000000..36c3360 --- /dev/null +++ b/BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/Implements/MessageInfoStorage.cs @@ -0,0 +1,77 @@ +using BlacksmithWorkshopContracts.BindingModels; +using BlacksmithWorkshopContracts.SearchModels; +using BlacksmithWorkshopContracts.StorageContracts; +using BlacksmithWorkshopContracts.ViewModels; +using BlacksmithWorkshopDatabaseImplement.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BlacksmithWorkshopDatabaseImplement.Implements +{ + public class MessageInfoStorage : IMessageInfoStorage + { + public List GetFullList() + { + using var context = new BlacksmithWorkshopDatabase(); + return context.MessageInfos + .Select(x => x.GetViewModel) + .ToList(); + } + public List GetFilteredList(MessageInfoSearchModel model) + { + using var context = new BlacksmithWorkshopDatabase(); + if (model.ClientId.HasValue && model.Page.HasValue && model.PageSize.HasValue) + { + return context.MessageInfos + .Where(x => x.ClientId == model.ClientId) + .Skip(model.PageSize.Value * model.Page.Value) + .Take(model.PageSize.Value) + .Select(x => x.GetViewModel) + .ToList(); + } + else if (model.Page.HasValue && model.PageSize.HasValue) + { + return context.MessageInfos + .Skip(model.PageSize.Value * model.Page.Value) + .Take(model.PageSize.Value) + .Select(x => x.GetViewModel) + .ToList(); + } + return new(); + } + public MessageInfoViewModel? GetElement(MessageInfoSearchModel model) + { + using var context = new BlacksmithWorkshopDatabase(); + return context.MessageInfos + .FirstOrDefault(x => !string.IsNullOrEmpty(x.MessageId) && x.MessageId == model.MessageId) + ?.GetViewModel; + } + public MessageInfoViewModel? Insert(MessageInfoBindingModel model) + { + using var context = new BlacksmithWorkshopDatabase(); + var newMessage = MessageInfo.Create(model); + if (newMessage == null) + { + return null; + } + context.MessageInfos.Add(newMessage); + context.SaveChanges(); + return newMessage.GetViewModel; + } + public MessageInfoViewModel? Update(MessageInfoBindingModel model) + { + using var context = new BlacksmithWorkshopDatabase(); + var message = context.MessageInfos.FirstOrDefault(x => x.MessageId == model.MessageId); + if (message == null) + { + return null; + } + message.Update(model); + context.SaveChanges(); + return message.GetViewModel; + } + } +} diff --git a/BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/Migrations/20230505211018_Init.Designer.cs b/BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/Migrations/20230612104157_Init.Designer.cs similarity index 87% rename from BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/Migrations/20230505211018_Init.Designer.cs rename to BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/Migrations/20230612104157_Init.Designer.cs index 9b78345..023ca04 100644 --- a/BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/Migrations/20230505211018_Init.Designer.cs +++ b/BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/Migrations/20230612104157_Init.Designer.cs @@ -12,7 +12,7 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace BlacksmithWorkshopDatabaseImplement.Migrations { [DbContext(typeof(BlacksmithWorkshopDatabase))] - [Migration("20230505211018_Init")] + [Migration("20230612104157_Init")] partial class Init { /// @@ -143,6 +143,42 @@ namespace BlacksmithWorkshopDatabaseImplement.Migrations b.ToTable("ManufactureComponents"); }); + modelBuilder.Entity("BlacksmithWorkshopDatabaseImplement.Models.MessageInfo", b => + { + b.Property("MessageId") + .HasColumnType("nvarchar(450)"); + + b.Property("Body") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("DateDelivery") + .HasColumnType("datetime2"); + + b.Property("IsRead") + .HasColumnType("bit"); + + b.Property("ReplyText") + .HasColumnType("nvarchar(max)"); + + b.Property("SenderName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.ToTable("MessageInfos"); + }); + modelBuilder.Entity("BlacksmithWorkshopDatabaseImplement.Models.Order", b => { b.Property("Id") @@ -258,6 +294,15 @@ namespace BlacksmithWorkshopDatabaseImplement.Migrations b.Navigation("Manufacture"); }); + modelBuilder.Entity("BlacksmithWorkshopDatabaseImplement.Models.MessageInfo", b => + { + b.HasOne("BlacksmithWorkshopDatabaseImplement.Models.Client", "Client") + .WithMany() + .HasForeignKey("ClientId"); + + b.Navigation("Client"); + }); + modelBuilder.Entity("BlacksmithWorkshopDatabaseImplement.Models.Order", b => { b.HasOne("BlacksmithWorkshopDatabaseImplement.Models.Client", "Client") diff --git a/BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/Migrations/20230505211018_Init.cs b/BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/Migrations/20230612104157_Init.cs similarity index 87% rename from BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/Migrations/20230505211018_Init.cs rename to BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/Migrations/20230612104157_Init.cs index 603b332..c8513b0 100644 --- a/BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/Migrations/20230505211018_Init.cs +++ b/BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/Migrations/20230612104157_Init.cs @@ -86,6 +86,29 @@ namespace BlacksmithWorkshopDatabaseImplement.Migrations table.PrimaryKey("PK_Shops", x => x.Id); }); + migrationBuilder.CreateTable( + name: "MessageInfos", + columns: table => new + { + MessageId = table.Column(type: "nvarchar(450)", nullable: false), + ClientId = table.Column(type: "int", nullable: true), + SenderName = table.Column(type: "nvarchar(max)", nullable: false), + DateDelivery = table.Column(type: "datetime2", nullable: false), + Subject = table.Column(type: "nvarchar(max)", nullable: false), + Body = table.Column(type: "nvarchar(max)", nullable: false), + IsRead = table.Column(type: "bit", nullable: false), + ReplyText = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_MessageInfos", x => x.MessageId); + table.ForeignKey( + name: "FK_MessageInfos_Clients_ClientId", + column: x => x.ClientId, + principalTable: "Clients", + principalColumn: "Id"); + }); + migrationBuilder.CreateTable( name: "ManufactureComponents", columns: table => new @@ -197,6 +220,11 @@ namespace BlacksmithWorkshopDatabaseImplement.Migrations table: "ManufactureComponents", column: "ManufactureId"); + migrationBuilder.CreateIndex( + name: "IX_MessageInfos_ClientId", + table: "MessageInfos", + column: "ClientId"); + migrationBuilder.CreateIndex( name: "IX_Orders_ClientId", table: "Orders", @@ -222,6 +250,9 @@ namespace BlacksmithWorkshopDatabaseImplement.Migrations migrationBuilder.DropTable( name: "ManufactureComponents"); + migrationBuilder.DropTable( + name: "MessageInfos"); + migrationBuilder.DropTable( name: "Orders"); diff --git a/BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/Migrations/BlacksmithWorkshopDatabaseModelSnapshot.cs b/BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/Migrations/BlacksmithWorkshopDatabaseModelSnapshot.cs index 12d6113..2a8d94e 100644 --- a/BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/Migrations/BlacksmithWorkshopDatabaseModelSnapshot.cs +++ b/BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/Migrations/BlacksmithWorkshopDatabaseModelSnapshot.cs @@ -140,6 +140,42 @@ namespace BlacksmithWorkshopDatabaseImplement.Migrations b.ToTable("ManufactureComponents"); }); + modelBuilder.Entity("BlacksmithWorkshopDatabaseImplement.Models.MessageInfo", b => + { + b.Property("MessageId") + .HasColumnType("nvarchar(450)"); + + b.Property("Body") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("DateDelivery") + .HasColumnType("datetime2"); + + b.Property("IsRead") + .HasColumnType("bit"); + + b.Property("ReplyText") + .HasColumnType("nvarchar(max)"); + + b.Property("SenderName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.ToTable("MessageInfos"); + }); + modelBuilder.Entity("BlacksmithWorkshopDatabaseImplement.Models.Order", b => { b.Property("Id") @@ -255,6 +291,15 @@ namespace BlacksmithWorkshopDatabaseImplement.Migrations b.Navigation("Manufacture"); }); + modelBuilder.Entity("BlacksmithWorkshopDatabaseImplement.Models.MessageInfo", b => + { + b.HasOne("BlacksmithWorkshopDatabaseImplement.Models.Client", "Client") + .WithMany() + .HasForeignKey("ClientId"); + + b.Navigation("Client"); + }); + modelBuilder.Entity("BlacksmithWorkshopDatabaseImplement.Models.Order", b => { b.HasOne("BlacksmithWorkshopDatabaseImplement.Models.Client", "Client") diff --git a/BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/Models/MessageInfo.cs b/BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/Models/MessageInfo.cs new file mode 100644 index 0000000..feb9428 --- /dev/null +++ b/BlacksmithWorkshop/BlacksmithWorkshopDatabaseImplement/Models/MessageInfo.cs @@ -0,0 +1,63 @@ +using BlacksmithWorkshopContracts.BindingModels; +using BlacksmithWorkshopContracts.ViewModels; +using BlacksmithWorkshopDataModels.Models; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BlacksmithWorkshopDatabaseImplement.Models +{ + public class MessageInfo : IMessageInfoModel + { + [Key] + public string MessageId { get; set; } = string.Empty; + public int? ClientId { get; set; } + [Required] + public string SenderName { get; set; } = string.Empty; + [Required] + public DateTime DateDelivery { get; set; } = DateTime.Now; + [Required] + public string Subject { get; set; } = string.Empty; + [Required] + public string Body { get; set; } = string.Empty; + [Required] + public bool IsRead { get; private set; } = false; + public string? ReplyText { get; private set; } + public virtual Client? Client { get; set; } + public static MessageInfo? Create(MessageInfoBindingModel? model) + { + if (model == null) + { + return null; + } + return new MessageInfo() + { + MessageId = model.MessageId, + ClientId = model.ClientId, + SenderName = model.SenderName, + DateDelivery = model.DateDelivery, + Subject = model.Subject, + Body = model.Body + }; + } + public void Update(MessageInfoBindingModel model) + { + IsRead = model.IsRead; + ReplyText = model.ReplyText; + } + public MessageInfoViewModel GetViewModel => new() + { + MessageId = MessageId, + ClientId = ClientId, + SenderName = SenderName, + DateDelivery = DateDelivery, + Subject = Subject, + Body = Body, + IsRead = IsRead, + ReplyText = ReplyText + }; + } +} diff --git a/BlacksmithWorkshop/BlacksmithWorkshopFileImplement/DataFileSingleton.cs b/BlacksmithWorkshop/BlacksmithWorkshopFileImplement/DataFileSingleton.cs index f388c8a..2de3e9c 100644 --- a/BlacksmithWorkshop/BlacksmithWorkshopFileImplement/DataFileSingleton.cs +++ b/BlacksmithWorkshop/BlacksmithWorkshopFileImplement/DataFileSingleton.cs @@ -18,12 +18,14 @@ namespace BlacksmithWorkshopFileImplement private readonly string ClientFileName = "Client.xml"; private readonly string ImplementerFileName = "Implementer.xml"; private readonly string ShopFileName = "Shop.xml"; - public List Components { get; private set; } + private readonly string MessageInfoFileName = "MessageInfo.xml"; + public List Components { get; private set; } public List Orders { get; private set; } public List Manufactures { get; private set; } public List Shops { get; private set; } public List Clients { get; private set; } public List Implementers { get; private set; } + public List MessageInfos { get; private set; } public static DataFileSingleton GetInstance() { if (instance == null) @@ -38,6 +40,7 @@ namespace BlacksmithWorkshopFileImplement public void SaveClients() => SaveData(Clients, ClientFileName, "Clients", x => x.GetXElement); public void SaveShops() => SaveData(Shops, ShopFileName, "Shops", x => x.GetXElement); public void SaveImplementers() => SaveData(Implementers, ImplementerFileName, "Implementers", x => x.GetXElement); + public void SaveMessageInfos() => SaveData(MessageInfos, MessageInfoFileName, "MessageInfos", x => x.GetXElement); private DataFileSingleton() { Components = LoadData(ComponentFileName, "Component", x => Component.Create(x)!)!; @@ -46,7 +49,8 @@ namespace BlacksmithWorkshopFileImplement Clients = LoadData(ClientFileName, "Client", x => Client.Create(x)!)!; Implementers = LoadData(ImplementerFileName, "Implementer", x => Implementer.Create(x)!)!; Shops = LoadData(ShopFileName, "Shop", x => Shop.Create(x)!)!; - } + MessageInfos = LoadData(MessageInfoFileName, "MessageInfo", x => MessageInfo.Create(x)!)!; + } private static List? LoadData(string filename, string xmlNodeName, Func selectFunction) { if (File.Exists(filename)) diff --git a/BlacksmithWorkshop/BlacksmithWorkshopFileImplement/Implements/MessageInfoStorage.cs b/BlacksmithWorkshop/BlacksmithWorkshopFileImplement/Implements/MessageInfoStorage.cs new file mode 100644 index 0000000..75b5001 --- /dev/null +++ b/BlacksmithWorkshop/BlacksmithWorkshopFileImplement/Implements/MessageInfoStorage.cs @@ -0,0 +1,69 @@ +using BlacksmithWorkshopContracts.BindingModels; +using BlacksmithWorkshopContracts.SearchModels; +using BlacksmithWorkshopContracts.StorageContracts; +using BlacksmithWorkshopContracts.ViewModels; +using BlacksmithWorkshopFileImplement.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BlacksmithWorkshopFileImplement.Implements +{ + public class MessageInfoStorage : IMessageInfoStorage + { + private readonly DataFileSingleton _source; + public MessageInfoStorage() + { + _source = DataFileSingleton.GetInstance(); + } + public MessageInfoViewModel? GetElement(MessageInfoSearchModel model) + { + if (!string.IsNullOrEmpty(model.MessageId)) + { + return _source.MessageInfos + .FirstOrDefault(x => x.MessageId == model.MessageId) + ?.GetViewModel; + } + return null; + } + public List GetFilteredList(MessageInfoSearchModel model) + { + if (model.ClientId.HasValue) + { + return _source.MessageInfos + .Where(x => x.ClientId == model.ClientId) + .Select(x => x.GetViewModel) + .ToList(); + } + return new(); + } + public List GetFullList() + { + return _source.MessageInfos.Select(x => x.GetViewModel).ToList(); + } + public MessageInfoViewModel? Insert(MessageInfoBindingModel model) + { + var newMessage = MessageInfo.Create(model); + if (newMessage == null) + { + return null; + } + _source.MessageInfos.Add(newMessage); + _source.SaveClients(); + return newMessage.GetViewModel; + } + public MessageInfoViewModel? Update(MessageInfoBindingModel model) + { + var message = _source.MessageInfos.FirstOrDefault(x => x.MessageId == model.MessageId); + if (message == null) + { + return null; + } + message.Update(model); + _source.SaveMessageInfos(); + return message.GetViewModel; + } + } +} diff --git a/BlacksmithWorkshop/BlacksmithWorkshopFileImplement/Models/MessageInfo.cs b/BlacksmithWorkshop/BlacksmithWorkshopFileImplement/Models/MessageInfo.cs new file mode 100644 index 0000000..165ab8b --- /dev/null +++ b/BlacksmithWorkshop/BlacksmithWorkshopFileImplement/Models/MessageInfo.cs @@ -0,0 +1,81 @@ +using BlacksmithWorkshopContracts.BindingModels; +using BlacksmithWorkshopContracts.ViewModels; +using BlacksmithWorkshopDataModels.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Linq; + +namespace BlacksmithWorkshopFileImplement.Models +{ + public class MessageInfo : IMessageInfoModel + { + public string MessageId { get; set; } = string.Empty; + public int? ClientId { get; set; } + public string SenderName { get; set; } = string.Empty; + public DateTime DateDelivery { get; set; } = DateTime.Now; + public string Subject { get; set; } = string.Empty; + public string Body { get; set; } = string.Empty; + public bool IsRead { get; private set; } = false; + public string? ReplyText { get; private set; } + public static MessageInfo? Create(MessageInfoBindingModel model) + { + if (model == null) + { + return null; + } + return new MessageInfo() + { + MessageId = model.MessageId, + ClientId = model.ClientId, + SenderName = model.SenderName, + DateDelivery = model.DateDelivery, + Subject = model.Subject, + Body = model.Body + }; + } + public static MessageInfo? Create(XElement element) + { + if (element == null) + { + return null; + } + return new MessageInfo() + { + MessageId = element.Element("MessageId")!.Value, + ClientId = Convert.ToInt32(element.Element("ClientId")!.Value), + SenderName = element.Element("MessageId")!.Value, + DateDelivery = DateTime.ParseExact(element.Element("DateDelivery")!.Value, "G", null), + Subject = element.Element("MessageId")!.Value, + Body = element.Element("MessageId")!.Value + }; + } + public void Update(MessageInfoBindingModel model) + { + IsRead = model.IsRead; + ReplyText = model.ReplyText; + } + public MessageInfoViewModel GetViewModel => new() + { + MessageId = MessageId, + ClientId = ClientId, + SenderName = SenderName, + DateDelivery = DateDelivery, + Subject = Subject, + Body = Body, + IsRead = IsRead, + ReplyText = ReplyText + }; + public XElement GetXElement => new("MessageInfo", + new XAttribute("MessageId", MessageId), + new XElement("ClientId", ClientId), + new XElement("SenderName", SenderName), + new XElement("DateDelivery", DateDelivery), + new XElement("Subject", Subject), + new XElement("Body", Body), + new XElement("IsRead", IsRead), + new XElement("ReplyText", ReplyText)); + } +} diff --git a/BlacksmithWorkshop/BlacksmithWorkshopRestApi/Controllers/ClientController.cs b/BlacksmithWorkshop/BlacksmithWorkshopRestApi/Controllers/ClientController.cs index d7d3361..c53bdbd 100644 --- a/BlacksmithWorkshop/BlacksmithWorkshopRestApi/Controllers/ClientController.cs +++ b/BlacksmithWorkshop/BlacksmithWorkshopRestApi/Controllers/ClientController.cs @@ -12,11 +12,13 @@ namespace BlacksmithWorkshopRestApi.Controllers { private readonly ILogger _logger; private readonly IClientLogic _logic; - public ClientController(IClientLogic logic, ILogger logger) + private readonly IMessageInfoLogic _mailLogic; + public ClientController(IClientLogic logic, IMessageInfoLogic mailLogic, ILogger logger) { _logger = logger; _logic = logic; - } + _mailLogic = mailLogic; + } [HttpGet] public ClientViewModel? Login(string login, string password) { @@ -60,5 +62,23 @@ namespace BlacksmithWorkshopRestApi.Controllers throw; } } + [HttpGet] + public List? GetMessages(int clientId, int page) + { + try + { + return _mailLogic.ReadList(new MessageInfoSearchModel + { + ClientId = clientId, + Page = page, + PageSize = 5 + }); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка получения писем клиента"); + throw; + } + } } } diff --git a/BlacksmithWorkshop/BlacksmithWorkshopRestApi/Program.cs b/BlacksmithWorkshop/BlacksmithWorkshopRestApi/Program.cs index c91da4a..31b594b 100644 --- a/BlacksmithWorkshop/BlacksmithWorkshopRestApi/Program.cs +++ b/BlacksmithWorkshop/BlacksmithWorkshopRestApi/Program.cs @@ -1,4 +1,6 @@ using BlacksmithWorkshopBusinessLogic.BusinessLogics; +using BlacksmithWorkshopBusinessLogic.MailWorker; +using BlacksmithWorkshopContracts.BindingModels; using BlacksmithWorkshopContracts.BusinessLogicsContracts; using BlacksmithWorkshopContracts.StorageContracts; using BlacksmithWorkshopDatabaseImplement.Implements; @@ -15,12 +17,16 @@ builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); +builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); +builder.Services.AddTransient(); + +builder.Services.AddSingleton(); builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle @@ -32,6 +38,17 @@ builder.Services.AddSwaggerGen(c => var app = builder.Build(); +var mailSender = app.Services.GetService(); +mailSender?.MailConfig(new MailConfigBindingModel +{ + MailLogin = builder.Configuration?.GetSection("MailLogin")?.Value?.ToString() ?? string.Empty, + MailPassword = builder.Configuration?.GetSection("MailPassword")?.Value?.ToString() ?? string.Empty, + SmtpClientHost = builder.Configuration?.GetSection("SmtpClientHost")?.Value?.ToString() ?? string.Empty, + SmtpClientPort = Convert.ToInt32(builder.Configuration?.GetSection("SmtpClientPort")?.Value?.ToString()), + PopHost = builder.Configuration?.GetSection("PopHost")?.Value?.ToString() ?? string.Empty, + PopPort = Convert.ToInt32(builder.Configuration?.GetSection("PopPort")?.Value?.ToString()) +}); + // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { diff --git a/BlacksmithWorkshop/BlacksmithWorkshopRestApi/appsettings.json b/BlacksmithWorkshop/BlacksmithWorkshopRestApi/appsettings.json index 10f68b8..7b413a2 100644 --- a/BlacksmithWorkshop/BlacksmithWorkshopRestApi/appsettings.json +++ b/BlacksmithWorkshop/BlacksmithWorkshopRestApi/appsettings.json @@ -5,5 +5,11 @@ "Microsoft.AspNetCore": "Warning" } }, - "AllowedHosts": "*" + "AllowedHosts": "*", + "SmtpClientHost": "smtp.gmail.com", + "SmtpClientPort": "587", + "PopHost": "pop.gmail.com", + "PopPort": "995", + "MailLogin": "lab7rppzyzf@gmail.com", + "MailPassword": "zbzc zorb ozlq bxuc" } diff --git a/BlacksmithWorkshop/BlacksmithWorkshopView/App.config b/BlacksmithWorkshop/BlacksmithWorkshopView/App.config new file mode 100644 index 0000000..6fd5d5d --- /dev/null +++ b/BlacksmithWorkshop/BlacksmithWorkshopView/App.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/BlacksmithWorkshop/BlacksmithWorkshopView/BlacksmithWorkshopView.csproj b/BlacksmithWorkshop/BlacksmithWorkshopView/BlacksmithWorkshopView.csproj index b7b0549..59a166f 100644 --- a/BlacksmithWorkshop/BlacksmithWorkshopView/BlacksmithWorkshopView.csproj +++ b/BlacksmithWorkshop/BlacksmithWorkshopView/BlacksmithWorkshopView.csproj @@ -26,6 +26,9 @@ + + Always + Always diff --git a/BlacksmithWorkshop/BlacksmithWorkshopView/FormMain.Designer.cs b/BlacksmithWorkshop/BlacksmithWorkshopView/FormMain.Designer.cs index 9fce03a..d3a66b7 100644 --- a/BlacksmithWorkshop/BlacksmithWorkshopView/FormMain.Designer.cs +++ b/BlacksmithWorkshop/BlacksmithWorkshopView/FormMain.Designer.cs @@ -49,6 +49,7 @@ buttonRef = new Button(); buttonAddManufactureInShop = new Button(); buttonSellManufacture = new Button(); + messagesToolStripMenuItem = new ToolStripMenuItem(); menuStrip1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit(); SuspendLayout(); @@ -56,7 +57,7 @@ // menuStrip1 // menuStrip1.ImageScalingSize = new Size(20, 20); - menuStrip1.Items.AddRange(new ToolStripItem[] { guideToolStripMenuItem, отчетыToolStripMenuItem, workToolStripMenuItem }); + menuStrip1.Items.AddRange(new ToolStripItem[] { guideToolStripMenuItem, отчетыToolStripMenuItem, workToolStripMenuItem, messagesToolStripMenuItem }); menuStrip1.Location = new Point(0, 0); menuStrip1.Name = "menuStrip1"; menuStrip1.Padding = new Padding(6, 3, 0, 3); @@ -74,35 +75,35 @@ // componentsToolStripMenuItem // componentsToolStripMenuItem.Name = "componentsToolStripMenuItem"; - componentsToolStripMenuItem.Size = new Size(224, 26); + componentsToolStripMenuItem.Size = new Size(185, 26); componentsToolStripMenuItem.Text = "Компоненты"; componentsToolStripMenuItem.Click += ComponentsToolStripMenuItem_Click; // // goodsToolStripMenuItem // goodsToolStripMenuItem.Name = "goodsToolStripMenuItem"; - goodsToolStripMenuItem.Size = new Size(224, 26); + goodsToolStripMenuItem.Size = new Size(185, 26); goodsToolStripMenuItem.Text = "Изделия"; goodsToolStripMenuItem.Click += GoodsToolStripMenuItem_Click; // // ShopsToolStripMenuItem // ShopsToolStripMenuItem.Name = "ShopsToolStripMenuItem"; - ShopsToolStripMenuItem.Size = new Size(224, 26); + ShopsToolStripMenuItem.Size = new Size(185, 26); ShopsToolStripMenuItem.Text = "Магазины"; ShopsToolStripMenuItem.Click += ShopsToolStripMenuItem_Click; // // clientsToolStripMenuItem // clientsToolStripMenuItem.Name = "clientsToolStripMenuItem"; - clientsToolStripMenuItem.Size = new Size(224, 26); + clientsToolStripMenuItem.Size = new Size(185, 26); clientsToolStripMenuItem.Text = "Клиенты"; clientsToolStripMenuItem.Click += ClientsToolStripMenuItem_Click; // // implemntersToolStripMenuItem // implemntersToolStripMenuItem.Name = "implemntersToolStripMenuItem"; - implemntersToolStripMenuItem.Size = new Size(224, 26); + implemntersToolStripMenuItem.Size = new Size(185, 26); implemntersToolStripMenuItem.Text = "Исполнители"; implemntersToolStripMenuItem.Click += ImplemntersToolStripMenuItem_Click; // @@ -226,6 +227,13 @@ buttonSellManufacture.Text = "Продать изделие"; buttonSellManufacture.UseVisualStyleBackColor = true; buttonSellManufacture.Click += ButtonSellManufacture_Click; + // + // messagesToolStripMenuItem + // + messagesToolStripMenuItem.Name = "messagesToolStripMenuItem"; + messagesToolStripMenuItem.Size = new Size(77, 24); + messagesToolStripMenuItem.Text = "Письма"; + messagesToolStripMenuItem.Click += messagesToolStripMenuItem_Click; // // FormMain // @@ -278,5 +286,6 @@ private ToolStripMenuItem shopsCapacityToolStripMenuItem; private ToolStripMenuItem ordersByDateToolStripMenuItem; private ToolStripMenuItem ShopsToolStripMenuItem; + private ToolStripMenuItem messagesToolStripMenuItem; } -} \ No newline at end of file +} diff --git a/BlacksmithWorkshop/BlacksmithWorkshopView/FormMain.cs b/BlacksmithWorkshop/BlacksmithWorkshopView/FormMain.cs index ad3f8e4..31ed105 100644 --- a/BlacksmithWorkshop/BlacksmithWorkshopView/FormMain.cs +++ b/BlacksmithWorkshop/BlacksmithWorkshopView/FormMain.cs @@ -206,5 +206,13 @@ namespace BlacksmithWorkshopView form.ShowDialog(); } } + private void messagesToolStripMenuItem_Click(object sender, EventArgs e) + { + var service = Program.ServiceProvider?.GetService(typeof(FormMessages)); + if (service is FormMessages form) + { + form.ShowDialog(); + } + } } } diff --git a/BlacksmithWorkshop/BlacksmithWorkshopView/FormMessage.Designer.cs b/BlacksmithWorkshop/BlacksmithWorkshopView/FormMessage.Designer.cs new file mode 100644 index 0000000..798d3d4 --- /dev/null +++ b/BlacksmithWorkshop/BlacksmithWorkshopView/FormMessage.Designer.cs @@ -0,0 +1,151 @@ +namespace BlacksmithWorkshopView +{ + partial class FormMessage + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + labelSender = new Label(); + textBoxSender = new TextBox(); + labelSubject = new Label(); + textBoxSubject = new TextBox(); + labelBody = new Label(); + textBoxBody = new TextBox(); + textBoxReply = new TextBox(); + labelReply = new Label(); + buttonSend = new Button(); + SuspendLayout(); + // + // labelSender + // + labelSender.AutoSize = true; + labelSender.Location = new Point(12, 9); + labelSender.Name = "labelSender"; + labelSender.Size = new Size(117, 25); + labelSender.TabIndex = 0; + labelSender.Text = "Отправитель"; + // + // textBoxSender + // + textBoxSender.Location = new Point(12, 37); + textBoxSender.Name = "textBoxSender"; + textBoxSender.Size = new Size(347, 31); + textBoxSender.TabIndex = 1; + // + // labelSubject + // + labelSubject.AutoSize = true; + labelSubject.Location = new Point(12, 86); + labelSubject.Name = "labelSubject"; + labelSubject.Size = new Size(99, 25); + labelSubject.TabIndex = 2; + labelSubject.Text = "Заголовок"; + // + // textBoxSubject + // + textBoxSubject.Location = new Point(12, 114); + textBoxSubject.Name = "textBoxSubject"; + textBoxSubject.Size = new Size(347, 31); + textBoxSubject.TabIndex = 3; + // + // labelBody + // + labelBody.AutoSize = true; + labelBody.Location = new Point(12, 167); + labelBody.Name = "labelBody"; + labelBody.Size = new Size(152, 25); + labelBody.TabIndex = 4; + labelBody.Text = "Текст сообщения"; + // + // textBoxBody + // + textBoxBody.Location = new Point(12, 195); + textBoxBody.Multiline = true; + textBoxBody.Name = "textBoxBody"; + textBoxBody.Size = new Size(347, 243); + textBoxBody.TabIndex = 5; + // + // textBoxReply + // + textBoxReply.Location = new Point(430, 37); + textBoxReply.Multiline = true; + textBoxReply.Name = "textBoxReply"; + textBoxReply.Size = new Size(358, 361); + textBoxReply.TabIndex = 6; + // + // labelReply + // + labelReply.AutoSize = true; + labelReply.Location = new Point(430, 9); + labelReply.Name = "labelReply"; + labelReply.Size = new Size(112, 25); + labelReply.TabIndex = 7; + labelReply.Text = "Текст ответа"; + // + // buttonSend + // + buttonSend.Location = new Point(430, 404); + buttonSend.Name = "buttonSend"; + buttonSend.Size = new Size(358, 34); + buttonSend.TabIndex = 8; + buttonSend.Text = "Отправить"; + buttonSend.UseVisualStyleBackColor = true; + buttonSend.Click += ButtonSend_Click; + // + // FormMessage + // + AutoScaleDimensions = new SizeF(10F, 25F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(800, 450); + Controls.Add(buttonSend); + Controls.Add(labelReply); + Controls.Add(textBoxReply); + Controls.Add(textBoxBody); + Controls.Add(labelBody); + Controls.Add(textBoxSubject); + Controls.Add(labelSubject); + Controls.Add(textBoxSender); + Controls.Add(labelSender); + Name = "FormMessage"; + Text = "Ответ"; + Load += FormMessage_Load; + ResumeLayout(false); + PerformLayout(); + } + + #endregion + + private Label labelSender; + private TextBox textBoxSender; + private Label labelSubject; + private TextBox textBoxSubject; + private Label labelBody; + private TextBox textBoxBody; + private TextBox textBoxReply; + private Label labelReply; + private Button buttonSend; + } +} \ No newline at end of file diff --git a/BlacksmithWorkshop/BlacksmithWorkshopView/FormMessage.cs b/BlacksmithWorkshop/BlacksmithWorkshopView/FormMessage.cs new file mode 100644 index 0000000..a1250f0 --- /dev/null +++ b/BlacksmithWorkshop/BlacksmithWorkshopView/FormMessage.cs @@ -0,0 +1,113 @@ +using BlacksmithWorkshopBusinessLogic.MailWorker; +using BlacksmithWorkshopContracts.BusinessLogicsContracts; +using BlacksmithWorkshopContracts.SearchModels; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace BlacksmithWorkshopView +{ + public partial class FormMessage : Form + { + private readonly ILogger _logger; + private readonly IMessageInfoLogic _logic; + private readonly AbstractMailWorker _mailWorker; + private readonly IClientLogic _clientLogic; + private string? _id; + public string Id { set { _id = value; } } + public FormMessage(ILogger logger, IMessageInfoLogic messageInfoLogic, AbstractMailWorker abstractMailWorker, IClientLogic clientLogic) + { + InitializeComponent(); + _logger = logger; + _logic = messageInfoLogic; + _clientLogic = clientLogic; + _mailWorker = abstractMailWorker; + } + private void ButtonSend_Click(object sender, EventArgs e) + { + if (string.IsNullOrEmpty(textBoxBody.Text)) + { + MessageBox.Show("Заполните содержимое письма", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + _logger.LogInformation("Отправка ответа"); + try + { + var view = _logic.ReadElement(new() { MessageId = _id }); + if (view != null) + { + var operationResult = _logic.Update(new() + { + MessageId = view.MessageId, + IsRead = view.IsRead, + ReplyText = textBoxReply.Text + }); + if (!operationResult) + { + throw new Exception("Ошибка при сохранении. Дополнительная информация в логах."); + } + _mailWorker.MailSendAsync(new() + { + MailAddress = _clientLogic.ReadElement(new ClientSearchModel { Id = view.ClientId })!.Email, + Subject = textBoxSubject.Text, + Text = textBoxReply.Text, + }); + MessageBox.Show("Сохранение и отправление прошло успешно", "Сообщение", MessageBoxButtons.OK, MessageBoxIcon.Information); + DialogResult = DialogResult.OK; + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка сохранения исполнителя"); + MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + private void FormMessage_Load(object sender, EventArgs e) + { + if (!string.IsNullOrEmpty(_id)) + { + try + { + _logger.LogInformation("Получение письма"); + var view = _logic.ReadElement(new MessageInfoSearchModel + { + MessageId = _id + }); + if (view == null) + { + return; + } + textBoxSender.Text = view.SenderName; + textBoxSubject.Text = view.Subject; + textBoxBody.Text = view.Body; + if (!view.IsRead) + { + var updateResult = _logic.Update(new() + { + MessageId = _id, + ReplyText = view.ReplyText, + IsRead = true, + }); + if (!updateResult) + { + throw new Exception("Ошибка при обновлении"); + } + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка получения письма"); + MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, + MessageBoxIcon.Error); + } + } + } + } +} diff --git a/BlacksmithWorkshop/BlacksmithWorkshopView/FormMessage.resx b/BlacksmithWorkshop/BlacksmithWorkshopView/FormMessage.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/BlacksmithWorkshop/BlacksmithWorkshopView/FormMessage.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/BlacksmithWorkshop/BlacksmithWorkshopView/FormMessages.Designer.cs b/BlacksmithWorkshop/BlacksmithWorkshopView/FormMessages.Designer.cs new file mode 100644 index 0000000..7c9cbad --- /dev/null +++ b/BlacksmithWorkshop/BlacksmithWorkshopView/FormMessages.Designer.cs @@ -0,0 +1,119 @@ +namespace BlacksmithWorkshopView +{ + partial class FormMessages + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + dataGridView = new DataGridView(); + panel = new Panel(); + buttonForward = new Button(); + buttonBack = new Button(); + buttonOpen = new Button(); + ((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit(); + panel.SuspendLayout(); + SuspendLayout(); + // + // dataGridView + // + dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; + dataGridView.Dock = DockStyle.Fill; + dataGridView.Location = new Point(0, 0); + dataGridView.Margin = new Padding(4, 5, 4, 5); + dataGridView.Name = "dataGridView"; + dataGridView.RowHeadersWidth = 62; + dataGridView.RowTemplate.Height = 25; + dataGridView.Size = new Size(1279, 697); + dataGridView.TabIndex = 0; + // + // panel + // + panel.Controls.Add(buttonForward); + panel.Controls.Add(buttonBack); + panel.Controls.Add(buttonOpen); + panel.Dock = DockStyle.Right; + panel.Location = new Point(1096, 0); + panel.Name = "panel"; + panel.Size = new Size(183, 697); + panel.TabIndex = 1; + // + // buttonForward + // + buttonForward.Anchor = AnchorStyles.Bottom | AnchorStyles.Right; + buttonForward.Location = new Point(106, 651); + buttonForward.Name = "buttonForward"; + buttonForward.Size = new Size(65, 34); + buttonForward.TabIndex = 2; + buttonForward.Text = ">"; + buttonForward.UseVisualStyleBackColor = true; + buttonForward.Click += ButtonForward_Click; + // + // buttonBack + // + buttonBack.Anchor = AnchorStyles.Bottom | AnchorStyles.Right; + buttonBack.Location = new Point(14, 651); + buttonBack.Name = "buttonBack"; + buttonBack.Size = new Size(65, 34); + buttonBack.TabIndex = 1; + buttonBack.Text = "<"; + buttonBack.UseVisualStyleBackColor = true; + buttonBack.Click += ButtonBack_Click; + // + // buttonOpen + // + buttonOpen.Location = new Point(14, 12); + buttonOpen.Name = "buttonOpen"; + buttonOpen.Size = new Size(157, 34); + buttonOpen.TabIndex = 0; + buttonOpen.Text = "Открыть"; + buttonOpen.UseVisualStyleBackColor = true; + buttonOpen.Click += ButtonOpen_Click; + // + // FormMessages + // + AutoScaleDimensions = new SizeF(10F, 25F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(1279, 697); + Controls.Add(panel); + Controls.Add(dataGridView); + Margin = new Padding(4, 5, 4, 5); + Name = "FormMessages"; + Text = "Сообщения"; + Load += FormMessages_Load; + ((System.ComponentModel.ISupportInitialize)dataGridView).EndInit(); + panel.ResumeLayout(false); + ResumeLayout(false); + } + + #endregion + + private DataGridView dataGridView; + private Panel panel; + private Button buttonOpen; + private Button buttonForward; + private Button buttonBack; + } +} \ No newline at end of file diff --git a/BlacksmithWorkshop/BlacksmithWorkshopView/FormMessages.cs b/BlacksmithWorkshop/BlacksmithWorkshopView/FormMessages.cs new file mode 100644 index 0000000..ccc9895 --- /dev/null +++ b/BlacksmithWorkshop/BlacksmithWorkshopView/FormMessages.cs @@ -0,0 +1,79 @@ +using BlacksmithWorkshopContracts.BusinessLogicsContracts; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using static BlacksmithWorkshopView.FormMessages; + +namespace BlacksmithWorkshopView +{ + public partial class FormMessages : Form + { + private readonly ILogger _logger; + private readonly IMessageInfoLogic _logic; + private readonly int pageSize = 5; + private int pageNumber = 0; + public FormMessages(ILogger logger, IMessageInfoLogic logic) + { + InitializeComponent(); + _logger = logger; + _logic = logic; + } + private void FormMessages_Load(object sender, EventArgs e) + { + LoadData(0); + } + private void LoadData(int page) + { + try + { + var list = _logic.ReadList(new() { Page = page, PageSize = pageSize }); + if (list != null) + { + dataGridView.DataSource = list; + dataGridView.Columns["ClientId"].Visible = false; + dataGridView.Columns["MessageId"].Visible = false; + dataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill; + } + _logger.LogInformation("Загрузка сообщений"); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка загрузки сообщений"); + MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + private void ButtonBack_Click(object sender, EventArgs e) + { + if (pageNumber != 0) + { + pageNumber--; + } + LoadData(pageNumber); + } + private void ButtonForward_Click(object sender, EventArgs e) + { + pageNumber++; + LoadData(pageNumber); + } + private void ButtonOpen_Click(object sender, EventArgs e) + { + if (dataGridView.SelectedRows.Count == 1) + { + var service = Program.ServiceProvider?.GetService(typeof(FormMessage)); + if (service is FormMessage form) + { + form.Id = dataGridView.SelectedRows[0].Cells["MessageId"].Value.ToString(); + form.ShowDialog(); + LoadData(0); + } + } + } + } +} diff --git a/BlacksmithWorkshop/BlacksmithWorkshopView/FormMessages.resx b/BlacksmithWorkshop/BlacksmithWorkshopView/FormMessages.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/BlacksmithWorkshop/BlacksmithWorkshopView/FormMessages.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/BlacksmithWorkshop/BlacksmithWorkshopView/Program.cs b/BlacksmithWorkshop/BlacksmithWorkshopView/Program.cs index cc53233..b434396 100644 --- a/BlacksmithWorkshop/BlacksmithWorkshopView/Program.cs +++ b/BlacksmithWorkshop/BlacksmithWorkshopView/Program.cs @@ -1,4 +1,4 @@ -using BlacksmithWorkshopBusinessLogic.BusinessLogics; +using BlacksmithWorkshopBusinessLogic.BusinessLogics; using BlacksmithWorkshopBusinessLogic.OfficePackage; using BlacksmithWorkshopBusinessLogic.OfficePackage.Implements; using BlacksmithWorkshopContracts.BusinessLogicsContracts; @@ -8,7 +8,8 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using NLog.Extensions.Logging; using ManufactureCompanyBusinessLogic.BusinessLogics; - +using BlacksmithWorkshopBusinessLogic.MailWorker; +using BlacksmithWorkshopContracts.BindingModels; namespace BlacksmithWorkshopView { @@ -28,7 +29,28 @@ namespace BlacksmithWorkshopView var services = new ServiceCollection(); ConfigureServices(services); _serviceProvider = services.BuildServiceProvider(); - Application.Run(_serviceProvider.GetRequiredService()); + try + { + var mailSender = _serviceProvider.GetService(); + mailSender?.MailConfig(new MailConfigBindingModel + { + MailLogin = System.Configuration.ConfigurationManager.AppSettings["MailLogin"] ?? string.Empty, + MailPassword = System.Configuration.ConfigurationManager.AppSettings["MailPassword"] ?? string.Empty, + SmtpClientHost = System.Configuration.ConfigurationManager.AppSettings["SmtpClientHost"] ?? string.Empty, + SmtpClientPort = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["SmtpClientPort"]), + PopHost = System.Configuration.ConfigurationManager.AppSettings["PopHost"] ?? string.Empty, + PopPort = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["PopPort"]) + }); + // Создаем таймер + var timer = new System.Threading.Timer(new TimerCallback(MailCheck!), null, 0, 100000); + } + catch (Exception ex) + { + var logger = _serviceProvider.GetService(); + logger?.LogError(ex, "Ошибка работы с почтой"); + } + + Application.Run(_serviceProvider.GetRequiredService()); } private static void ConfigureServices(ServiceCollection services) { @@ -43,6 +65,7 @@ namespace BlacksmithWorkshopView services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); @@ -55,7 +78,9 @@ namespace BlacksmithWorkshopView services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); services.AddTransient(); + services.AddSingleton(); services.AddTransient(); services.AddTransient(); services.AddTransient(); @@ -77,6 +102,9 @@ namespace BlacksmithWorkshopView services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); + services.AddTransient(); } - } -} \ No newline at end of file + private static void MailCheck(object obj) => ServiceProvider?.GetService()?.MailCheck(); + } +}