This commit is contained in:
Katanaa Die 2024-05-17 23:22:03 +04:00
parent 2e03dc50a7
commit afd5bd91ce
44 changed files with 1370 additions and 26 deletions

View File

@ -8,6 +8,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="DocumentFormat.OpenXml" Version="3.0.2" /> <PackageReference Include="DocumentFormat.OpenXml" Version="3.0.2" />
<PackageReference Include="MailKit" Version="4.5.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.16" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.16" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.16" /> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.16" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.16"> <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.16">

View File

@ -8,6 +8,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace BarBusinessLogic.BusinessLogics namespace BarBusinessLogic.BusinessLogics
@ -101,11 +102,11 @@ namespace BarBusinessLogic.BusinessLogics
{ {
throw new ArgumentNullException("Нет ФИО пользователя", nameof(model.ClientFIO)); throw new ArgumentNullException("Нет ФИО пользователя", nameof(model.ClientFIO));
} }
if (string.IsNullOrEmpty(model.Email)) if (string.IsNullOrEmpty(model.Email) || !Regex.IsMatch(model.Email, @"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$", RegexOptions.IgnoreCase))
{ {
throw new ArgumentNullException("Нет почты пользователя", nameof(model.Email)); throw new ArgumentNullException("Нет почты пользователя", nameof(model.Email));
} }
if (string.IsNullOrEmpty(model.Password)) if (string.IsNullOrEmpty(model.Password) || !Regex.IsMatch(model.Password, @"^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$"))
{ {
throw new ArgumentNullException("Нет пароля пользователя", nameof(model.Password)); throw new ArgumentNullException("Нет пароля пользователя", nameof(model.Password));
} }

View File

@ -0,0 +1,99 @@
using BarContracts.BindingModels;
using BarContracts.BusinessLogicsContracts;
using BarContracts.SearchModels;
using BarContracts.StoragesContracts;
using BarContracts.ViewModels;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BarBusinessLogic.BusinessLogics
{
public class MessageInfoLogic : IMessageInfoLogic
{
private readonly ILogger _logger;
private readonly IMessageInfoStorage _messageStorage;
private readonly IClientStorage _clientStorage;
public MessageInfoLogic(IMessageInfoStorage messageStorage, ILogger<MessageInfoLogic> logger, IClientStorage clientStorage)
{
_messageStorage = messageStorage;
_logger = logger;
_clientStorage = clientStorage;
}
public bool Create(MessageInfoBindingModel model)
{
CheckModel(model);
if (_messageStorage.Insert(model) == null)
{
_logger.LogWarning("Insert operation failed");
return false;
}
return true;
}
public List<MessageInfoViewModel>? ReadList(MessageInfoSearchModel? model)
{
_logger.LogInformation("ReadList. ClientID:{ClientID}. ID:{ ID}", model?.ClientId, model?.MessageId);
var list = model == null ? _messageStorage.GetFullList() : _messageStorage.GetFilteredList(model);
if (list == null)
{
_logger.LogWarning("ReadList return null list");
return null;
}
_logger.LogInformation("ReadList. Count:{Count}", list.Count);
return list;
}
private void CheckModel(MessageInfoBindingModel model, bool withParams = true)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
if (!withParams)
{
return;
}
if (string.IsNullOrEmpty(model.MessageId))
{
throw new ArgumentNullException("Не указан id сообщения", nameof(model.MessageId));
}
if (string.IsNullOrEmpty(model.SenderName))
{
throw new ArgumentNullException("Не указана почта", nameof(model.SenderName));
}
if (string.IsNullOrEmpty(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
{
Email = model.SenderName
});
if (element == null)
{
_logger.LogWarning("Не удалось найти клиента, отправившего письмо с адреса Email:{Email}", model.SenderName);
}
else
{
model.ClientId = element.Id;
}
}
}
}

View File

@ -10,6 +10,7 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using BarBusinessLogic.MailWorker;
namespace BarBusinessLogic.BusinessLogics namespace BarBusinessLogic.BusinessLogics
{ {
@ -17,12 +18,16 @@ namespace BarBusinessLogic.BusinessLogics
{ {
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IOrderStorage _orderStorage; private readonly IOrderStorage _orderStorage;
private readonly IClientStorage _clientStorage;
private readonly AbstractMailWorker _mailLogic;
static readonly object _locker = new object(); static readonly object _locker = new object();
public OrderLogic(ILogger<OrderLogic> logger, IOrderStorage orderStorage) public OrderLogic(ILogger<OrderLogic> logger, IOrderStorage orderStorage, IClientStorage clientStorage, AbstractMailWorker worker)
{ {
_logger = logger; _logger = logger;
_orderStorage = orderStorage; _orderStorage = orderStorage;
_clientStorage = clientStorage;
_mailLogic = worker;
} }
public OrderViewModel? ReadElement(OrderSearchModel model) public OrderViewModel? ReadElement(OrderSearchModel model)
@ -61,11 +66,15 @@ namespace BarBusinessLogic.BusinessLogics
CheckModel(model); CheckModel(model);
if (model.Status != OrderStatus.Неизвестен) return false; if (model.Status != OrderStatus.Неизвестен) return false;
model.Status = OrderStatus.Принят; model.Status = OrderStatus.Принят;
if (_orderStorage.Insert(model) == null) var order = _orderStorage.Insert(model);
if (order == null)
{ {
_logger.LogWarning("Insert operation failed"); _logger.LogWarning("Insert operation failed");
return false; return false;
} }
var clientView = _clientStorage.GetElement(new() { Id = order!.ClientId });
SendEmail(clientView, order);
return true; return true;
} }
public bool ChangeStatus(OrderBindingModel model, OrderStatus status) public bool ChangeStatus(OrderBindingModel model, OrderStatus status)
@ -85,8 +94,11 @@ namespace BarBusinessLogic.BusinessLogics
if (element.ImplementerId != null) if (element.ImplementerId != null)
element.ImplementerId = model.ImplementerId; element.ImplementerId = model.ImplementerId;
model.Status = status; model.Status = status;
if (model.Status == OrderStatus.Готов || model.Status == OrderStatus.Выдан) model.DateImplement = DateTime.Now; if (model.Status == OrderStatus.Выдан || model.Status == OrderStatus.Готов) model.DateImplement = DateTime.Now;
_orderStorage.Update(model); _orderStorage.Update(model);
var clientView = _clientStorage.GetElement(new() { Id = element.ClientId });
SendEmail(clientView, element);
return true; return true;
} }
@ -128,5 +140,37 @@ namespace BarBusinessLogic.BusinessLogics
} }
_logger.LogInformation("Order. Sum:{ Cost}. Id: { Id}", model.Sum, model.Id); _logger.LogInformation("Order. Sum:{ Cost}. Id: { Id}", model.Sum, model.Id);
} }
public void SendEmail(ClientViewModel clientModel, OrderViewModel orderModel)
{
if (clientModel == null && orderModel == null)
{
return;
}
MailSendInfoBindingModel mailModel;
if (orderModel.Status == OrderStatus.Принят)
{
mailModel = new MailSendInfoBindingModel
{
MailAddress = clientModel.Email,
Subject = $"Order №{orderModel.Id}",
Text = $"Your order №{orderModel.Id} by {orderModel.DateCreate} on {orderModel.Sum} was accepted!"
};
}
else
{
mailModel = new MailSendInfoBindingModel
{
MailAddress = clientModel.Email,
Subject = $"Order №{orderModel.Id}",
Text = $"Order №{orderModel.Id} status was changed to {orderModel.Status}"
};
}
_mailLogic.MailSendAsync(mailModel);
}
} }
} }

View File

@ -120,8 +120,7 @@ namespace BarBusinessLogic.BusinessLogics
_logger.LogDebug("DoWork. Worker {Id} finish order {Order}", implementer.Id, runOrder.Id); _logger.LogDebug("DoWork. Worker {Id} finish order {Order}", implementer.Id, runOrder.Id);
_orderLogic.FinishOrder(new OrderBindingModel _orderLogic.FinishOrder(new OrderBindingModel
{ {
Id = runOrder.Id, Id = runOrder.Id
ImplementerId = implementer.Id,
}); });
// отдыхаем // отдыхаем
Thread.Sleep(implementer.Qualification * _rnd.Next(10, 100)); Thread.Sleep(implementer.Qualification * _rnd.Next(10, 100));

View File

@ -0,0 +1,82 @@
using BarContracts.BindingModels;
using BarContracts.BusinessLogicsContracts;
using DocumentFormat.OpenXml.Spreadsheet;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BarBusinessLogic.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;
public AbstractMailWorker(ILogger<AbstractMailWorker> logger, IMessageInfoLogic messageInfoLogic)
{
_logger = logger;
_messageInfoLogic = messageInfoLogic;
_logger.LogWarning("INIT ABSTRACT MAIL WORKER");
}
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)
{
_messageInfoLogic.Create(mail);
}
}
protected abstract Task SendMailAsync(MailSendInfoBindingModel info);
protected abstract Task<List<MessageInfoBindingModel>> ReceiveMailAsync();
}
}

View File

@ -0,0 +1,79 @@
using BarContracts.BindingModels;
using BarContracts.BusinessLogicsContracts;
using MailKit.Net.Pop3;
using MailKit.Security;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Mail;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace BarBusinessLogic.MailWorker
{
public class MailKitWorker : AbstractMailWorker
{
public MailKitWorker(ILogger<MailKitWorker> 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;
objSmtpClient.UseDefaultCredentials = false;
objSmtpClient.EnableSsl = true;
objSmtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
objSmtpClient.Credentials = new NetworkCredential(_mailLogin, _mailPassword);
await Task.Run(() => objSmtpClient.Send(objMailMessage));
}
catch (Exception ex)
{
throw;
}
}
protected override async Task<List<MessageInfoBindingModel>> ReceiveMailAsync()
{
var list = new List<MessageInfoBindingModel>();
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;
}
}
}

View File

@ -144,5 +144,15 @@ namespace BarClientApp.Controllers
var piz = APIClient.GetRequest<CocktailViewModel>($"api/main/getcocktail?cocktailId={cocktail}"); var piz = APIClient.GetRequest<CocktailViewModel>($"api/main/getcocktail?cocktailId={cocktail}");
return count * (piz?.Price ?? 1); return count * (piz?.Price ?? 1);
} }
[HttpGet]
public IActionResult Mails()
{
if (APIClient.Client == null)
{
return Redirect("~/Home/Enter");
}
return View(APIClient.GetRequest<List<MessageInfoViewModel>>($"api/client/getmessages?clientId={APIClient.Client.Id}"));
}
} }
} }

View File

@ -24,7 +24,7 @@
<div class="col-4"><input type="submit" value="Создать" class="btn btn-primary" /></div> <div class="col-4"><input type="submit" value="Создать" class="btn btn-primary" /></div>
</div> </div>
</form> </form>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script> <script>
$('#cocktail').on('change', function () { $('#cocktail').on('change', function () {
check(); check();

View File

@ -0,0 +1,52 @@
@using BarContracts.ViewModels
@model List<MessageInfoViewModel>
@{
ViewData["Title"] = "Mails";
}
<div class="text-center">
<h1 class="display-4">Заказы</h1>
</div>
<div class="text-center">
@{
if (Model == null)
{
<h3 class="display-4">Авторизируйтесь</h3>
return;
}
<table class="table">
<thead>
<tr>
<th>
Дата письма
</th>
<th>
Заголовок
</th>
<th>
Текст
</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem =>
item.DateDelivery)
</td>
<td>
@Html.DisplayFor(modelItem =>
item.Subject)
</td>
<td>
@Html.DisplayFor(modelItem =>
item.Body)
</td>
</tr>
}
</tbody>
</table>
}
</div>

View File

@ -31,6 +31,9 @@
<li class="nav-item"> <li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Register">Регистрация</a> <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Register">Регистрация</a>
</li> </li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Mails">Письма</a>
</li>
</ul> </ul>
</div> </div>
</div> </div>

View File

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BarContracts.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; }
}
}

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BarContracts.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;
}
}

View File

@ -0,0 +1,24 @@
using BarDataModels.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BarContracts.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 DateTime DateDelivery { get; set; }
public string Subject { get; set; } = string.Empty;
public string Body { get; set; } = string.Empty;
}
}

View File

@ -0,0 +1,17 @@
using BarContracts.BindingModels;
using BarContracts.SearchModels;
using BarContracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BarContracts.BusinessLogicsContracts
{
public interface IMessageInfoLogic
{
List<MessageInfoViewModel>? ReadList(MessageInfoSearchModel? model);
bool Create(MessageInfoBindingModel viewModel);
}
}

View File

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BarContracts.SearchModels
{
public class MessageInfoSearchModel
{
public string? MessageId { get; set; }
public int? ClientId { get; set; }
}
}

View File

@ -0,0 +1,19 @@
using BarContracts.BindingModels;
using BarContracts.SearchModels;
using BarContracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BarContracts.StoragesContracts
{
public interface IMessageInfoStorage
{
List<MessageInfoViewModel> GetFullList();
List<MessageInfoViewModel> GetFilteredList(MessageInfoSearchModel model);
MessageInfoViewModel? GetElement(MessageInfoSearchModel model);
MessageInfoViewModel? Insert(MessageInfoBindingModel mode);
}
}

View File

@ -0,0 +1,25 @@
using BarDataModels.Models;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BarContracts.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;
}
}

View File

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BarDataModels.Models
{
public interface IMessageInfoModel
{
string MessageId { get; }
int? ClientId { get; }
string SenderName { get; }
DateTime DateDelivery { get; }
string Subject { get; }
string Body { get; }
}
}

View File

@ -28,5 +28,6 @@ namespace BarDatabaseImplement
public virtual DbSet<Order> Orders { get; set; } public virtual DbSet<Order> Orders { get; set; }
public virtual DbSet<Client> Clients { get; set; } public virtual DbSet<Client> Clients { get; set; }
public virtual DbSet<Implementer> Implementers { set; get; } public virtual DbSet<Implementer> Implementers { set; get; }
public virtual DbSet<MessageInfo> Messages { get; set; }
} }
} }

View File

@ -7,6 +7,8 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="MailKit" Version="4.5.0" />
<PackageReference Include="MailKit.NET" Version="2.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.16" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.16" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.16" /> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.16" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.16"> <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.16">

View File

@ -37,7 +37,7 @@ namespace BarDatabaseImplement.Implements
} }
using var context = new BarDatabase(); using var context = new BarDatabase();
return context.Clients.FirstOrDefault(x => return context.Clients.FirstOrDefault(x =>
(!string.IsNullOrEmpty(model.Email) && x.Email == model.Email && !string.IsNullOrEmpty(model.Password) && x.Password == model.Password) || (!string.IsNullOrEmpty(model.Email) && model.Email.Equals(x.Email) && !string.IsNullOrEmpty(model.Password) && model.Password.Equals(x.Password)) ||
(model.Id.HasValue && x.Id == model.Id)) (model.Id.HasValue && x.Id == model.Id))
?.GetViewModel; ?.GetViewModel;
} }

View File

@ -0,0 +1,55 @@
using BarContracts.BindingModels;
using BarContracts.SearchModels;
using BarContracts.StoragesContracts;
using BarContracts.ViewModels;
using Microsoft.EntityFrameworkCore;
using BarDatabaseImplement.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BarDatabaseImplement.Implements
{
public class MessageInfoStorage : IMessageInfoStorage
{
public MessageInfoViewModel? GetElement(MessageInfoSearchModel model)
{
if (string.IsNullOrEmpty(model.MessageId))
{
return null;
}
using var context = new BarDatabase();
return context.Messages.Include(x => x.Client).FirstOrDefault(x => x.MessageId.Equals(model.MessageId))?.GetViewModel;
}
public List<MessageInfoViewModel> GetFilteredList(MessageInfoSearchModel model)
{
if (!model.ClientId.HasValue)
{
return new();
}
using var context = new BarDatabase();
return context.Messages.Include(x => x.Client).Where(x => x.ClientId == model.ClientId).Select(x => x.GetViewModel).ToList();
}
public List<MessageInfoViewModel> GetFullList()
{
using var context = new BarDatabase();
return context.Messages.Include(x => x.Client).Select(x => x.GetViewModel).ToList();
}
public MessageInfoViewModel? Insert(MessageInfoBindingModel model)
{
var newMessage = MessageInfo.Create(model);
if (newMessage == null) return null;
using var context = new BarDatabase();
context.Messages.Add(newMessage);
context.SaveChanges();
return newMessage.GetViewModel;
}
}
}

View File

@ -12,7 +12,7 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace BarDatabaseImplement.Migrations namespace BarDatabaseImplement.Migrations
{ {
[DbContext(typeof(BarDatabase))] [DbContext(typeof(BarDatabase))]
[Migration("20240517092627_init")] [Migration("20240517095734_init")]
partial class init partial class init
{ {
/// <inheritdoc /> /// <inheritdoc />
@ -143,6 +143,36 @@ namespace BarDatabaseImplement.Migrations
b.ToTable("Implementers"); b.ToTable("Implementers");
}); });
modelBuilder.Entity("BarDatabaseImplement.Models.MessageInfo", b =>
{
b.Property<string>("MessageId")
.HasColumnType("nvarchar(450)");
b.Property<string>("Body")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int?>("ClientId")
.HasColumnType("int");
b.Property<DateTime>("DateDelivery")
.HasColumnType("datetime2");
b.Property<string>("SenderName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Subject")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("MessageId");
b.HasIndex("ClientId");
b.ToTable("Messages");
});
modelBuilder.Entity("BarDatabaseImplement.Models.Order", b => modelBuilder.Entity("BarDatabaseImplement.Models.Order", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")
@ -205,6 +235,15 @@ namespace BarDatabaseImplement.Migrations
b.Navigation("Component"); b.Navigation("Component");
}); });
modelBuilder.Entity("BarDatabaseImplement.Models.MessageInfo", b =>
{
b.HasOne("BarDatabaseImplement.Models.Client", "Client")
.WithMany("Messages")
.HasForeignKey("ClientId");
b.Navigation("Client");
});
modelBuilder.Entity("BarDatabaseImplement.Models.Order", b => modelBuilder.Entity("BarDatabaseImplement.Models.Order", b =>
{ {
b.HasOne("BarDatabaseImplement.Models.Client", "Client") b.HasOne("BarDatabaseImplement.Models.Client", "Client")
@ -232,6 +271,8 @@ namespace BarDatabaseImplement.Migrations
modelBuilder.Entity("BarDatabaseImplement.Models.Client", b => modelBuilder.Entity("BarDatabaseImplement.Models.Client", b =>
{ {
b.Navigation("Messages");
b.Navigation("Orders"); b.Navigation("Orders");
}); });

View File

@ -70,6 +70,27 @@ namespace BarDatabaseImplement.Migrations
table.PrimaryKey("PK_Implementers", x => x.Id); table.PrimaryKey("PK_Implementers", x => x.Id);
}); });
migrationBuilder.CreateTable(
name: "Messages",
columns: table => new
{
MessageId = table.Column<string>(type: "nvarchar(450)", nullable: false),
ClientId = table.Column<int>(type: "int", nullable: true),
SenderName = table.Column<string>(type: "nvarchar(max)", nullable: false),
DateDelivery = table.Column<DateTime>(type: "datetime2", nullable: false),
Subject = table.Column<string>(type: "nvarchar(max)", nullable: false),
Body = table.Column<string>(type: "nvarchar(max)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Messages", x => x.MessageId);
table.ForeignKey(
name: "FK_Messages_Clients_ClientId",
column: x => x.ClientId,
principalTable: "Clients",
principalColumn: "Id");
});
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "CocktailComponents", name: "CocktailComponents",
columns: table => new columns: table => new
@ -144,6 +165,11 @@ namespace BarDatabaseImplement.Migrations
table: "CocktailComponents", table: "CocktailComponents",
column: "ComponentId"); column: "ComponentId");
migrationBuilder.CreateIndex(
name: "IX_Messages_ClientId",
table: "Messages",
column: "ClientId");
migrationBuilder.CreateIndex( migrationBuilder.CreateIndex(
name: "IX_Orders_ClientId", name: "IX_Orders_ClientId",
table: "Orders", table: "Orders",
@ -166,6 +192,9 @@ namespace BarDatabaseImplement.Migrations
migrationBuilder.DropTable( migrationBuilder.DropTable(
name: "CocktailComponents"); name: "CocktailComponents");
migrationBuilder.DropTable(
name: "Messages");
migrationBuilder.DropTable( migrationBuilder.DropTable(
name: "Orders"); name: "Orders");

View File

@ -140,6 +140,36 @@ namespace BarDatabaseImplement.Migrations
b.ToTable("Implementers"); b.ToTable("Implementers");
}); });
modelBuilder.Entity("BarDatabaseImplement.Models.MessageInfo", b =>
{
b.Property<string>("MessageId")
.HasColumnType("nvarchar(450)");
b.Property<string>("Body")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int?>("ClientId")
.HasColumnType("int");
b.Property<DateTime>("DateDelivery")
.HasColumnType("datetime2");
b.Property<string>("SenderName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Subject")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("MessageId");
b.HasIndex("ClientId");
b.ToTable("Messages");
});
modelBuilder.Entity("BarDatabaseImplement.Models.Order", b => modelBuilder.Entity("BarDatabaseImplement.Models.Order", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")
@ -202,6 +232,15 @@ namespace BarDatabaseImplement.Migrations
b.Navigation("Component"); b.Navigation("Component");
}); });
modelBuilder.Entity("BarDatabaseImplement.Models.MessageInfo", b =>
{
b.HasOne("BarDatabaseImplement.Models.Client", "Client")
.WithMany("Messages")
.HasForeignKey("ClientId");
b.Navigation("Client");
});
modelBuilder.Entity("BarDatabaseImplement.Models.Order", b => modelBuilder.Entity("BarDatabaseImplement.Models.Order", b =>
{ {
b.HasOne("BarDatabaseImplement.Models.Client", "Client") b.HasOne("BarDatabaseImplement.Models.Client", "Client")
@ -229,6 +268,8 @@ namespace BarDatabaseImplement.Migrations
modelBuilder.Entity("BarDatabaseImplement.Models.Client", b => modelBuilder.Entity("BarDatabaseImplement.Models.Client", b =>
{ {
b.Navigation("Messages");
b.Navigation("Orders"); b.Navigation("Orders");
}); });

View File

@ -24,6 +24,8 @@ namespace BarDatabaseImplement.Models
[ForeignKey("ClientId")] [ForeignKey("ClientId")]
public virtual List<Order> Orders { get; set; } = new(); public virtual List<Order> Orders { get; set; } = new();
[ForeignKey("ClientId")]
public virtual List<MessageInfo> Messages { get; set; } = new();
public static Client? Create(ClientBindingModel model) public static Client? Create(ClientBindingModel model)
{ {

View File

@ -0,0 +1,54 @@
using BarContracts.BindingModels;
using BarContracts.ViewModels;
using BarDataModels.Models;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BarDatabaseImplement.Models
{
public class MessageInfo : IMessageInfoModel
{
[Key]
public string MessageId { get; private set; } = string.Empty;
public int? ClientId { get; private set; }
[Required]
public string SenderName { get; private set; } = string.Empty;
[Required]
public DateTime DateDelivery { get; private set; }
[Required]
public string Subject { get; private set; } = string.Empty;
[Required]
public string Body { get; private set; } = string.Empty;
public virtual Client? Client { 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,
Body = model.Body,
DateDelivery = model.DateDelivery,
Subject = model.Subject,
};
}
public MessageInfoViewModel GetViewModel => new()
{
MessageId = MessageId,
ClientId = ClientId,
SenderName = SenderName,
Body = Body,
DateDelivery = DateDelivery,
Subject = Subject,
};
}
}

View File

@ -18,12 +18,14 @@ namespace BarContracts.BindingModels
private readonly string CocktailFileName = "Cocktail.xml"; private readonly string CocktailFileName = "Cocktail.xml";
private readonly string ClientFileName = "Client.xml"; private readonly string ClientFileName = "Client.xml";
private readonly string ImplementerFileName = "Implement.xml"; private readonly string ImplementerFileName = "Implement.xml";
private readonly string MessageInfoFileName = "MessageInfo.xml";
public List<Component> Components { get; private set; } public List<Component> Components { get; private set; }
public List<Order> Orders { get; private set; } public List<Order> Orders { get; private set; }
public List<Cocktail> Cocktails { get; private set; } public List<Cocktail> Cocktails { get; private set; }
public List<Client> Clients { get; private set; } public List<Client> Clients { get; private set; }
public List<Implementer> Implementers { get; private set; } public List<Implementer> Implementers { get; private set; }
public List<MessageInfo> Messages { get; private set; }
public static DataFileSingleton GetInstance() public static DataFileSingleton GetInstance()
{ {
@ -54,6 +56,7 @@ namespace BarContracts.BindingModels
public void SaveOrders() => SaveData(Orders, OrderFileName, "Orders", x => x.GetXElement); public void SaveOrders() => SaveData(Orders, OrderFileName, "Orders", x => x.GetXElement);
public void SaveClients() => SaveData(Clients, ClientFileName, "Clients", x => x.GetXElement); public void SaveClients() => SaveData(Clients, ClientFileName, "Clients", x => x.GetXElement);
public void SaveImplements() => SaveData(Implementers, ImplementerFileName, "Implements", x => x.GetXElement); public void SaveImplements() => SaveData(Implementers, ImplementerFileName, "Implements", x => x.GetXElement);
public void SaveMessages() => SaveData(Messages, MessageInfoFileName, "Messages", x => x.GetXElement);
private DataFileSingleton() private DataFileSingleton()
{ {
@ -62,6 +65,7 @@ namespace BarContracts.BindingModels
Orders = LoadData(OrderFileName, "Order", x => Order.Create(x)!)!; Orders = LoadData(OrderFileName, "Order", x => Order.Create(x)!)!;
Clients = LoadData(ClientFileName, "Client", x => Client.Create(x)!)!; Clients = LoadData(ClientFileName, "Client", x => Client.Create(x)!)!;
Implementers = LoadData(ImplementerFileName, "Implement", x => Implementer.Create(x)!)!; Implementers = LoadData(ImplementerFileName, "Implement", x => Implementer.Create(x)!)!;
Messages = LoadData(MessageInfoFileName, "MessageInfo", x => MessageInfo.Create(x)!)!;
} }
} }

View File

@ -0,0 +1,58 @@
using BarContracts.BindingModels;
using BarContracts.SearchModels;
using BarContracts.StoragesContracts;
using BarContracts.ViewModels;
using BarFileImplement.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BarFileImplement.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 null;
}
return _source.Messages.FirstOrDefault(x => x.MessageId.Equals(model.MessageId))?.GetViewModel;
}
public List<MessageInfoViewModel> GetFilteredList(MessageInfoSearchModel model)
{
if (!model.ClientId.HasValue)
{
return new();
}
return _source.Messages.Where(x => x.ClientId == model.ClientId).Select(x => x.GetViewModel).ToList();
}
public List<MessageInfoViewModel> GetFullList()
{
return _source.Messages.Select(x => x.GetViewModel).ToList();
}
public MessageInfoViewModel? Insert(MessageInfoBindingModel model)
{
var newMessage = MessageInfo.Create(model);
if (newMessage == null)
{
return null;
}
_source.Messages.Add(newMessage);
_source.SaveMessages();
return newMessage.GetViewModel;
}
}
}

View File

@ -0,0 +1,80 @@
using BarContracts.BindingModels;
using BarContracts.ViewModels;
using BarDataModels.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace BarFileImplement.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; }
public string Subject { get; set; } = string.Empty;
public string Body { get; set; } = string.Empty;
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.Attribute("MessageId")!.Value,
ClientId = Convert.ToInt32(element.Attribute("ClientId")!.Value),
SenderName = element.Element("SenderName")!.Value,
DateDelivery = Convert.ToDateTime(element.Element("DateDelivery")!.Value),
Subject = element.Attribute("Subject")!.Value,
Body = element.Attribute("Body")!.Value,
};
}
public MessageInfoViewModel GetViewModel => new()
{
MessageId = MessageId,
ClientId = ClientId,
SenderName = SenderName,
DateDelivery = DateDelivery,
Subject = Subject,
Body = Body
};
public XElement GetXElement => new("MessageInfo", new XAttribute("MessageId", MessageId),
new XElement("ClientId", ClientId.ToString()),
new XElement("SenderName", SenderName),
new XElement("DateDelivery", DateDelivery),
new XElement("Subject", Subject),
new XElement("Body", Body),
new XElement("SenderName", SenderName));
}
}

View File

@ -4,6 +4,7 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Forms;
using BarListImplement.Models; using BarListImplement.Models;
@ -17,6 +18,7 @@ namespace BarContracts.BindingModels
public List<Cocktail> Cocktails { get; set; } public List<Cocktail> Cocktails { get; set; }
public List<Client> Clients { get; set; } public List<Client> Clients { get; set; }
public List<Implementer> Implementers { get; set; } public List<Implementer> Implementers { get; set; }
public List<MessageInfo> Messages { get; set; }
private DataListSingleton() private DataListSingleton()
{ {
@ -25,6 +27,7 @@ namespace BarContracts.BindingModels
Cocktails = new List<Cocktail>(); Cocktails = new List<Cocktail>();
Clients = new List<Client>(); Clients = new List<Client>();
Implementers = new List<Implementer>(); Implementers = new List<Implementer>();
Messages = new List<MessageInfo>();
} }
public static DataListSingleton GetInstance() public static DataListSingleton GetInstance()

View File

@ -0,0 +1,73 @@
using BarContracts.BindingModels;
using BarContracts.SearchModels;
using BarContracts.StoragesContracts;
using BarContracts.ViewModels;
using BarListImplement.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BarListImplement.Implements
{
public class MessageInfoStorage : IMessageInfoStorage
{
private readonly DataListSingleton _source;
public MessageInfoStorage(DataListSingleton source)
{
_source = DataListSingleton.GetInstance();
}
public MessageInfoViewModel? GetElement(MessageInfoSearchModel model)
{
if (string.IsNullOrEmpty(model.MessageId))
{
return null;
}
foreach (var msg in _source.Messages)
{
if (msg.MessageId.Equals(model.MessageId))
{
return msg.GetViewModel;
}
}
return null;
}
public List<MessageInfoViewModel> GetFilteredList(MessageInfoSearchModel model)
{
var list = new List<MessageInfoViewModel>();
foreach (var msg in _source.Messages)
{
if (msg.ClientId.HasValue && model.ClientId == msg.ClientId)
{
list.Add(msg.GetViewModel);
}
}
return list;
}
public List<MessageInfoViewModel> GetFullList()
{
var list = new List<MessageInfoViewModel>();
foreach (var msg in _source.Messages)
{
list.Add(msg.GetViewModel);
}
return list;
}
public MessageInfoViewModel? Insert(MessageInfoBindingModel model)
{
var newMessage = MessageInfo.Create(model);
if (newMessage == null)
{
return null;
}
_source.Messages.Add(newMessage);
return newMessage.GetViewModel;
}
}
}

View File

@ -0,0 +1,51 @@
using BarContracts.BindingModels;
using BarContracts.ViewModels;
using BarDataModels.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BarListImplement.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; }
public string Subject { get; set; } = string.Empty;
public string Body { get; set; } = string.Empty;
public static MessageInfo? Create(MessageInfoBindingModel? model)
{
if (model == null)
{
return null;
}
return new()
{
MessageId = model.MessageId,
SenderName = model.SenderName,
DateDelivery = model.DateDelivery,
Subject = model.Subject,
Body = model.Body,
};
}
public MessageInfoViewModel GetViewModel => new()
{
MessageId = MessageId,
SenderName = SenderName,
DateDelivery = DateDelivery,
Subject = Subject,
Body = Body
};
}
}

View File

@ -13,11 +13,13 @@ namespace BarRestApi.Controllers
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IClientLogic _logic; private readonly IClientLogic _logic;
private readonly IMessageInfoLogic _mailLogic;
public ClientController(IClientLogic logic, ILogger<ClientController> logger) public ClientController(IClientLogic logic, ILogger<ClientController> logger, IMessageInfoLogic message)
{ {
_logger = logger; _logger = logger;
_logic = logic; _logic = logic;
_mailLogic = message;
} }
[HttpGet] [HttpGet]
@ -65,5 +67,21 @@ namespace BarRestApi.Controllers
throw; throw;
} }
} }
[HttpGet]
public List<MessageInfoViewModel>? GetMessages(int clientId)
{
try
{
return _mailLogic.ReadList(new MessageInfoSearchModel
{
ClientId = clientId
});
}
catch (Exception ex)
{
_logger.LogError(ex, "Îøèáêà ïîëó÷åíèÿ ïèñåì êëèåíòà");
throw;
}
}
} }
} }

View File

@ -1,4 +1,5 @@
using BarBusinessLogic.BusinessLogics; using BarBusinessLogic.BusinessLogics;
using BarBusinessLogic.MailWorker;
using BarContracts.BusinessLogicsContracts; using BarContracts.BusinessLogicsContracts;
using BarContracts.StoragesContracts; using BarContracts.StoragesContracts;
using BarDatabaseImplement.Implements; using BarDatabaseImplement.Implements;
@ -15,6 +16,11 @@ builder.Services.AddTransient<IImplementerStorage, ImplementerStorage>();
builder.Services.AddTransient<IOrderStorage, OrderStorage>(); builder.Services.AddTransient<IOrderStorage, OrderStorage>();
builder.Services.AddTransient<ICocktailStorage, CocktailStorage>(); builder.Services.AddTransient<ICocktailStorage, CocktailStorage>();
builder.Services.AddTransient<IMessageInfoLogic, MessageInfoLogic>();
builder.Services.AddTransient<IMessageInfoStorage, MessageInfoStorage>();
builder.Services.AddSingleton<AbstractMailWorker, MailKitWorker>();
builder.Services.AddTransient<IOrderLogic, OrderLogic>(); builder.Services.AddTransient<IOrderLogic, OrderLogic>();
builder.Services.AddTransient<IImplementerLogic, ImplementerLogic>(); builder.Services.AddTransient<IImplementerLogic, ImplementerLogic>();
builder.Services.AddTransient<IClientLogic, ClientLogic>(); builder.Services.AddTransient<IClientLogic, ClientLogic>();
@ -29,6 +35,17 @@ builder.Services.AddSwaggerGen(c =>
}); });
var app = builder.Build(); var app = builder.Build();
var mailSender = app.Services.GetService<AbstractMailWorker>();
mailSender?.MailConfig(new()
{
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. // Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment()) if (app.Environment.IsDevelopment())

View File

@ -5,5 +5,12 @@
"Microsoft.AspNetCore": "Warning" "Microsoft.AspNetCore": "Warning"
} }
}, },
"AllowedHosts": "*" "AllowedHosts": "*",
"SmtpClientHost": "smtp.mail.ru",
"SmtpClientPort": "587",
"PopHost": "pop.mail.ru",
"PopPort": "995",
"MailLogin": "pibd21.teryokhin@mail.ru",
"MailPassword": "fZNuZY6BPTmvgcPqw08B"
} }

11
Bar/BarView/App.config Normal file
View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="SmtpClientHost" value="smtp.mail.ru" />
<add key="SmtpClientPort" value="587" />
<add key="PopHost" value="pop.mail.ru" />
<add key="PopPort" value="995" />
<add key="MailLogin" value="pibd21.teryokhin@mail.ru" />
<add key="MailPassword" value="fZNuZY6BPTmvgcPqw08B" />
</appSettings>
</configuration>

62
Bar/BarView/FormMail.Designer.cs generated Normal file
View File

@ -0,0 +1,62 @@
namespace BarView
{
partial class FormMail
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
dataGridView = new DataGridView();
((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
SuspendLayout();
//
// dataGridView
//
dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
dataGridView.Location = new Point(12, 12);
dataGridView.Name = "dataGridView";
dataGridView.RowHeadersWidth = 51;
dataGridView.RowTemplate.Height = 29;
dataGridView.Size = new Size(776, 426);
dataGridView.TabIndex = 0;
//
// FormMail
//
AutoScaleDimensions = new SizeF(8F, 20F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(800, 450);
Controls.Add(dataGridView);
Name = "FormMail";
Text = "Формочка с письмами";
Load += FormEmails_Load;
((System.ComponentModel.ISupportInitialize)dataGridView).EndInit();
ResumeLayout(false);
}
#endregion
private DataGridView dataGridView;
}
}

53
Bar/BarView/FormMail.cs Normal file
View File

@ -0,0 +1,53 @@
using BarContracts.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;
namespace BarView
{
public partial class FormMail : Form
{
private readonly ILogger _logger;
private readonly IMessageInfoLogic _logic;
public FormMail(ILogger<FormMail> logger, IMessageInfoLogic logic)
{
InitializeComponent();
_logger = logger;
_logic = logic;
}
private void FormEmails_Load(object sender, EventArgs e)
{
LoadData();
}
private void LoadData()
{
try
{
var list = _logic.ReadList(null);
if (list != null)
{
dataGridView.DataSource = list;
dataGridView.Columns["ClientId"].Visible = false;
dataGridView.Columns["MessageId"].Visible = false;
dataGridView.Columns["Body"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
}
_logger.LogInformation("Loading materials");
}
catch (Exception ex)
{
_logger.LogError(ex, "Error loading materials");
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}

120
Bar/BarView/FormMail.resx Normal file
View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -39,6 +39,7 @@
отчетыToolStripMenuItem = new ToolStripMenuItem(); отчетыToolStripMenuItem = new ToolStripMenuItem();
клиентToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); клиентToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
исполнителиToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); исполнителиToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
почтовыеПисьмаToolStripMenuItem = new ToolStripMenuItem();
запускРаботToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); запускРаботToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
ComponentsToolStripMenuItem = new ToolStripMenuItem(); ComponentsToolStripMenuItem = new ToolStripMenuItem();
ComponentCocktailToolStripMenuItem = new ToolStripMenuItem(); ComponentCocktailToolStripMenuItem = new ToolStripMenuItem();
@ -99,7 +100,7 @@
// компонентыToolStripMenuItem // компонентыToolStripMenuItem
// //
компонентыToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { компонентыToolStripMenuItem1, изделияToolStripMenuItem, компонентыToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { компонентыToolStripMenuItem1, изделияToolStripMenuItem,
клиентToolStripMenuItem, исполнителиToolStripMenuItem }); клиентToolStripMenuItem, исполнителиToolStripMenuItem, почтовыеПисьмаToolStripMenuItem });
компонентыToolStripMenuItem.Name = омпонентыToolStripMenuItem"; компонентыToolStripMenuItem.Name = омпонентыToolStripMenuItem";
компонентыToolStripMenuItem.Size = new Size(94, 20); компонентыToolStripMenuItem.Size = new Size(94, 20);
компонентыToolStripMenuItem.Text = "Справочники"; компонентыToolStripMenuItem.Text = "Справочники";
@ -156,6 +157,13 @@
this.исполнителиToolStripMenuItem.Text = "Исполнители"; this.исполнителиToolStripMenuItem.Text = "Исполнители";
this.исполнителиToolStripMenuItem.Click += new System.EventHandler(this.employersToolStripMenuItem_Click); this.исполнителиToolStripMenuItem.Click += new System.EventHandler(this.employersToolStripMenuItem_Click);
// //
// почтовыеПисьмаToolStripMenuItem
//
почтовыеПисьмаToolStripMenuItem.Name = "почтовыеПисьмаToolStripMenuItem";
почтовыеПисьмаToolStripMenuItem.Size = new Size(149, 22);
почтовыеПисьмаToolStripMenuItem.Text = "ПочтовыеПисьма";
почтовыеПисьмаToolStripMenuItem.Click += emailsToolStripMenuItem_Click;
//
// //
// запускРаботToolStripMenuItem // запускРаботToolStripMenuItem
// //
@ -207,5 +215,6 @@
private ToolStripMenuItem клиентToolStripMenuItem; private ToolStripMenuItem клиентToolStripMenuItem;
private ToolStripMenuItem исполнителиToolStripMenuItem; private ToolStripMenuItem исполнителиToolStripMenuItem;
private ToolStripMenuItem запускРаботToolStripMenuItem; private ToolStripMenuItem запускРаботToolStripMenuItem;
private ToolStripMenuItem почтовыеПисьмаToolStripMenuItem;
} }
} }

View File

@ -98,7 +98,7 @@ namespace BarView
id); id);
try try
{ {
var operationResult = _orderLogic.DeliveryOrder(new OrderBindingModel { Id = id}); var operationResult = _orderLogic.DeliveryOrder(CreateBindingModel(id));
if (!operationResult) if (!operationResult)
{ {
throw new Exception("Ошибка при сохранении. Дополнительная информация в логах."); throw new Exception("Ошибка при сохранении. Дополнительная информация в логах.");
@ -169,6 +169,14 @@ namespace BarView
form.ShowDialog(); form.ShowDialog();
} }
} }
private void emailsToolStripMenuItem_Click(object sender, EventArgs e)
{
var service = Program.ServiceProvider?.GetService(typeof(FormMail));
if (service is FormMail form)
{
form.ShowDialog();
}
}
} }
} }

View File

@ -1,4 +1,4 @@
using BarContracts.BusinessLogicsContracts; using BarContracts.BusinessLogicsContracts;
using BarContracts.StoragesContracts; using BarContracts.StoragesContracts;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using BarDatabaseImplement.Implements; using BarDatabaseImplement.Implements;
@ -7,6 +7,7 @@ using NLog.Extensions.Logging;
using BarBusinessLogic.OfficePackage.Implements; using BarBusinessLogic.OfficePackage.Implements;
using BarBusinessLogic.OfficePackage; using BarBusinessLogic.OfficePackage;
using BarBusinessLogic.BusinessLogics; using BarBusinessLogic.BusinessLogics;
using BarBusinessLogic.MailWorker;
namespace BarView namespace BarView
{ {
@ -26,6 +27,25 @@ namespace BarView
var services = new ServiceCollection(); var services = new ServiceCollection();
ConfigureServices(services); ConfigureServices(services);
_serviceProvider = services.BuildServiceProvider(); _serviceProvider = services.BuildServiceProvider();
try
{
var mailSender = _serviceProvider.GetService<AbstractMailWorker>();
mailSender?.MailConfig(new()
{
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<ILogger>();
logger?.LogError(ex, "Îøèáêà ðàáîòû ñ ïî÷òîé");
}
Application.Run(_serviceProvider.GetRequiredService<FormMain>()); Application.Run(_serviceProvider.GetRequiredService<FormMain>());
} }
private static void ConfigureServices(ServiceCollection services) private static void ConfigureServices(ServiceCollection services)
@ -40,6 +60,7 @@ namespace BarView
services.AddTransient<ICocktailStorage, CocktailStorage>(); services.AddTransient<ICocktailStorage, CocktailStorage>();
services.AddTransient<IClientStorage, ClientStorage>(); services.AddTransient<IClientStorage, ClientStorage>();
services.AddTransient<IImplementerStorage, ImplementerStorage>(); services.AddTransient<IImplementerStorage, ImplementerStorage>();
services.AddTransient<IMessageInfoStorage, MessageInfoStorage>();
services.AddTransient<IComponentLogic, ComponentLogic>(); services.AddTransient<IComponentLogic, ComponentLogic>();
services.AddTransient<IOrderLogic, OrderLogic>(); services.AddTransient<IOrderLogic, OrderLogic>();
@ -49,6 +70,8 @@ namespace BarView
services.AddTransient<IComponentLogic, ComponentLogic>(); services.AddTransient<IComponentLogic, ComponentLogic>();
services.AddTransient<IImplementerLogic, ImplementerLogic>(); services.AddTransient<IImplementerLogic, ImplementerLogic>();
services.AddTransient<IWorkProcess, WorkModeling>(); services.AddTransient<IWorkProcess, WorkModeling>();
services.AddSingleton<AbstractMailWorker, MailKitWorker>();
services.AddTransient<IMessageInfoLogic, MessageInfoLogic>();
services.AddTransient<AbstractSaveToWord, SaveToWord>(); services.AddTransient<AbstractSaveToWord, SaveToWord>();
services.AddTransient<AbstractSaveToExcel, SaveToExcel>(); services.AddTransient<AbstractSaveToExcel, SaveToExcel>();
@ -67,7 +90,9 @@ namespace BarView
services.AddTransient<FormImplementers>(); services.AddTransient<FormImplementers>();
services.AddTransient<FormImplementer>(); services.AddTransient<FormImplementer>();
services.AddTransient<FormClients>(); services.AddTransient<FormClients>();
services.AddTransient<FormMail>();
} }
private static void MailCheck(object obj) => ServiceProvider?.GetService<AbstractMailWorker>()?.MailCheck();
} }
} }