ISbd-21 Gordeev I.V. LabWork_07 Base #13

Closed
Igor_Gordeev wants to merge 5 commits from Lab_07 into Lab_06
23 changed files with 525 additions and 138 deletions
Showing only changes of commit 69557dc426 - Show all commits

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="SmtpClientHost" value="smtp.gmail.com" />
<add key="SmtpClientPort" value="587" />
<add key="PopHost" value="pop.gmail.com" />
<add key="PopPort" value="995" />
<add key="MailLogin" value="89176335310x@gmail.com" />
<add key="MailPassword" value="wmbu qrgy ocwl tadm" />
</appSettings>
</configuration>

View File

@ -8,6 +8,8 @@ using SushiBarContracts.BusinessLogicsContracts;
using SushiBarContracts.StoragesContracts;
using SushiBarDatabaseImplement.Implements;
using SushiBarBusinessLogic;
using SushiBarBusinessLogic.MailWorker;
using SushiBarContracts.BindingModels;
namespace SushiBarView
{
@ -24,13 +26,32 @@ namespace SushiBarView
// To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration.
ApplicationConfiguration.Initialize();
var services = new ServiceCollection();
ConfigureServices(services);
_serviceProvider = services.BuildServiceProvider();
try
{
var mailSender = _serviceProvider.GetService<AbstractMailWorker>();
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 services = new ServiceCollection();
ConfigureServices(services);
_serviceProvider = services.BuildServiceProvider();
var timer = new System.Threading.Timer(new TimerCallback(MailCheck!), null, 0, 100000);
}
catch (Exception ex)
{
var logger = _serviceProvider.GetService<ILogger>();
logger?.LogError(ex, "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
}
Application.Run(_serviceProvider.GetRequiredService<FormMain>());
}
Application.Run(_serviceProvider.GetRequiredService<FormMain>());
}
private static void ConfigureServices(ServiceCollection services)
{
@ -44,16 +65,18 @@ namespace SushiBarView
services.AddTransient<ISushiStorage, SushiStorage>();
services.AddTransient<IClientStorage, ClientStorage>();
services.AddTransient<IImplementerStorage, ImplementerStorage>();
services.AddTransient<IMessageInfoStorage, MessageInfoStorage>();
services.AddTransient<IIngredientLogic, IngredientLogic>();
services.AddTransient<IIngredientLogic, IngredientLogic>();
services.AddTransient<IOrderLogic, OrderLogic>();
services.AddTransient<ISushiLogic, SushiLogic>();
services.AddTransient<IClientLogic, ClientLogic>();
services.AddTransient<IReportLogic, ReportLogic>();
services.AddTransient<IImplementerLogic, ImplementerLogic>();
services.AddTransient<IWorkProcess, WorkModeling>();
services.AddTransient<IMessageInfoLogic, MessageInfoLogic>();
services.AddTransient<FormMain>();
services.AddTransient<FormMain>();
services.AddTransient<FormIngredient>();
services.AddTransient<FormIngredients>();
services.AddTransient<FormCreateOrder>();
@ -70,7 +93,8 @@ namespace SushiBarView
services.AddTransient<AbstractSaveToExcel, SaveToExcel>();
services.AddTransient<AbstractSaveToWord, SaveToWord>();
services.AddTransient<AbstractSaveToPdf, SaveToPdf>();
}
}
services.AddSingleton<AbstractMailWorker, MailKitWorker>();
}
private static void MailCheck(object obj) => ServiceProvider?.GetService<AbstractMailWorker>()?.MailCheck();
}
}

View File

@ -93,12 +93,12 @@ namespace SushiBarBusinessLogic
{
throw new ArgumentNullException("Нет ФИО пользователя", nameof(model.ClientFIO));
}
if (string.IsNullOrEmpty(model.Email) || !Regex.IsMatch(model.Email, @"^[a-z0-9._%+-]+\@([a-z0-9-]+\.)+[a-z]{2,4}$"))
if (string.IsNullOrEmpty(model.Email) || !Regex.IsMatch(model.Email, @"^[A-Za-z0-9._%+-]+\@([a-z0-9-]+\.)+[a-z]{2,4}$"))
{
throw new ArgumentNullException("Нет указана валидная почта", nameof(model.Email));
}
if (string.IsNullOrEmpty(model.Password) || !Regex.IsMatch(model.Password, @"^(?=.*[A-Za-z])(?=.*\d)(?=.*[^A-Za-z0-9\n]).{10,50}$"))
{
if (!Regex.IsMatch(model.Email, @"^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$"))
{
throw new ArgumentNullException("Не указан правильный пароль", nameof(model.Password));
}
_logger.LogInformation("Client. ClientFIO:{ClientFIO}.Email:{Email}.Id:{Id}",

View File

@ -1,17 +1,10 @@
using Microsoft.Extensions.Logging;
using SushiBar.SearchModels;
using SushiBar.StoragesContracts;
using SushiBarContracts.BindingModels;
using SushiBarContracts.BusinessLogicsContracts;
using SushiBarContracts.SearchModel;
using SushiBarContracts.SearchModels;
using SushiBarContracts.StoragesContracts;
using SushiBarContracts.ViewModels;
using SushiBarDataModels.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SushiBarBusinessLogic
{

View File

@ -11,17 +11,18 @@ namespace SushiBarBusinessLogic.BusinessLogics
{
public class OrderLogic : IOrderLogic
{
private readonly ILogger _logger;
private readonly IOrderStorage _orderStorage;
private readonly AbstractMailWorker _mailWorker;
static readonly object _locker = new object();
public OrderLogic(ILogger<OrderLogic> logger, IOrderStorage orderStorage,AbstractMailWorker mailWorker)
{
_logger = logger;
_orderStorage = orderStorage;
_mailWorker = mailWorker;
}
public List<OrderViewModel>? ReadList(OrderSearchModel? model)
private readonly ILogger _logger;
private readonly IOrderStorage _orderStorage;
private readonly AbstractMailWorker _mailWorker;
private readonly IClientLogic _clientLogic;
public OrderLogic(ILogger<OrderLogic> logger, IOrderStorage orderStorage, AbstractMailWorker mailWorker, IClientLogic clientLogic)
{
_logger = logger;
_orderStorage = orderStorage;
_mailWorker = mailWorker;
_clientLogic = clientLogic;
}
public List<OrderViewModel>? ReadList(OrderSearchModel? model)
{
_logger.LogInformation("ReadList. ClientId:{ClientId}.Status:{Status}.ImplementerId:{ImplementerId}.DateFrom:{DateFrom}.DateTo:{DateTo}OrderId:{Id}",
model?.ClientId, model?.Status, model?.ImplementerId, model?.DateFrom, model?.DateTo, model?.Id);
@ -52,25 +53,23 @@ namespace SushiBarBusinessLogic.BusinessLogics
Subject = $"Изменение статуса заказа номер {element.Id}",
Text = $"Ваш заказ номер {element.Id} на суши {element.SushiName} от {element.DateCreate} на сумму {element.Sum} принят."
}));
return true;
SendOrderStatusMail(element.ClientId, $"Новый заказ создан. Номер заказа #{element.Id}", $"Заказ #{element.Id} от {element.DateCreate} на сумму {element.Sum:0.00} принят");
return true;
}
public bool TakeOrderInWork(OrderBindingModel model)
{
lock (_locker)
{
return ChangeStatus(model, OrderStatus.Выполняется);
}
}
return StatusUpdate(model, OrderStatus.Выполняется);
}
public bool FinishOrder(OrderBindingModel model)
{
return ChangeStatus(model, OrderStatus.Готов);
return StatusUpdate(model, OrderStatus.Готов);
}
public bool DeliveryOrder(OrderBindingModel model)
{
return ChangeStatus(model, OrderStatus.Выдан);
return StatusUpdate(model, OrderStatus.Выдан);
}
private void CheckModel(OrderBindingModel model, bool withParams = true)
@ -99,48 +98,43 @@ namespace SushiBarBusinessLogic.BusinessLogics
model.SushiId, model.Count, model.Sum, model.Id);
}
private bool ChangeStatus(OrderBindingModel model, OrderStatus requiredStatus)
{
CheckModel(model, false);
var element = _orderStorage.GetElement(new OrderSearchModel()
{
Id = model.Id
});
if (element == null)
{
throw new InvalidOperationException(nameof(element));
}
model.DateCreate = element.DateCreate;
model.SushiId = element.SushiId;
model.DateImplement = element.DateImplement;
model.ClientId = element.ClientId;
if (!model.ImplementerId.HasValue)
{
model.ImplementerId = element.ImplementerId;
}
model.Status = element.Status;
model.Count = element.Count;
model.Sum = element.Sum;
if (requiredStatus - model.Status == 1)
{
model.Status = requiredStatus;
if (model.Status == OrderStatus.Готов)
{
model.DateImplement = DateTime.Now;
}
if (_orderStorage.Update(model) == null)
{
_logger.LogWarning("Update operation failed");
return false;
}
return true;
}
_logger.LogWarning("Changing status operation faled: Current-{Status}:required-{requiredStatus}.", model.Status, requiredStatus);
throw new InvalidOperationException($"Невозможно приствоить статус {requiredStatus} заказу с текущим статусом {model.Status}");
private bool StatusUpdate(OrderBindingModel model, OrderStatus newStatus)
{
var viewModel = _orderStorage.GetElement(new OrderSearchModel { Id = model.Id });
if (viewModel == null)
{
throw new ArgumentNullException(nameof(model));
}
if (viewModel.Status + 1 != newStatus)
{
_logger.LogWarning("Change status operation failed");
throw new InvalidOperationException();
}
model.Status = newStatus;
if (model.Status == OrderStatus.Готов)
{
model.DateImplement = DateTime.Now;
}
else
{
model.DateImplement = viewModel.DateImplement;
}
if (viewModel.ImplementerId.HasValue)
{
model.ImplementerId = viewModel.ImplementerId.Value;
}
CheckModel(model, false);
var result = _orderStorage.Update(model);
if (result == null)
{
_logger.LogWarning("Update operation failed");
return false;
}
SendOrderStatusMail(result.ClientId, $"Изменен статус заказа #{result.Id}", $"Заказ #{model.Id} изменен статус на {result.Status}");
return true;
}
}
public OrderViewModel? ReadElement(OrderSearchModel model)
public OrderViewModel? ReadElement(OrderSearchModel model)
{
if (model == null)
{
@ -157,5 +151,20 @@ namespace SushiBarBusinessLogic.BusinessLogics
_logger.LogInformation("ReadElement find. Id:{Id}", element.Id);
return element;
}
}
private bool SendOrderStatusMail(int clientId, string subject, string text)
{
var client = _clientLogic.ReadElement(new() { Id = clientId });
if (client == null)
{
return false;
}
_mailWorker.MailSendAsync(new()
{
MailAddress = client.Email,
Subject = subject,
Text = text
});
return true;
}
}
}

View File

@ -1,34 +1,36 @@
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SushiBar.StoragesContracts;
using SushiBarContracts.BindingModels;
using SushiBarContracts.BusinessLogicsContracts;
using SushiBarContracts.SearchModels;
using SushiBarContracts.StoragesContracts;
using SushiBarContracts.ViewModels;
namespace SushiBarBusinessLogic.MailWorker
{
public abstract class AbstractMailWorker
{
protected string _mailLogin = string.Empty;
protected string _mailPassword = string.Empty;
protected string _smtpClientHost = string.Empty;
protected int _smtpClientPort;
protected string _popHost = string.Empty;
protected int _popPort;
private readonly IMessageInfoLogic _messageInfoLogic;
private readonly IClientLogic _clientLogic;
private readonly ILogger _logger;
public AbstractMailWorker(ILogger<AbstractMailWorker> logger, IMessageInfoLogic messageInfoLogic)
public AbstractMailWorker(ILogger<AbstractMailWorker> logger, IMessageInfoLogic messageInfoLogic, IClientLogic clientLogic)
{
_logger = logger;
_messageInfoLogic = messageInfoLogic;
_clientLogic = clientLogic;
}
public void MailConfig(MailConfigBindingModel config)
{
_mailLogin = config.MailLogin;
@ -37,8 +39,9 @@ namespace SushiBarBusinessLogic.MailWorker
_smtpClientPort = config.SmtpClientPort;
_popHost = config.PopHost;
_popPort = config.PopPort;
_logger.LogDebug("Config: {login}, {password}, {clientHost}, {clientPOrt}, {popHost}, {popPort}", _mailLogin, _mailPassword.Length, _smtpClientHost, _smtpClientPort, _popHost, _popPort);
_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))
@ -59,6 +62,7 @@ namespace SushiBarBusinessLogic.MailWorker
_logger.LogDebug("Send Mail: {To}, {Subject}", info.MailAddress, info.Subject);
await SendMailAsync(info);
}
public async void MailCheck()
{
if (string.IsNullOrEmpty(_mailLogin) || string.IsNullOrEmpty(_mailPassword))
@ -80,10 +84,14 @@ namespace SushiBarBusinessLogic.MailWorker
_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<List<MessageInfoBindingModel>> ReceiveMailAsync();
}
}

View File

@ -6,41 +6,41 @@ using SushiBarContracts.BusinessLogicsContracts;
using SushiBarContracts.BindingModels;
using MailKit.Net.Pop3;
using MailKit.Security;
using MailChimp.Net.Logic;
namespace SushiBarBusinessLogic.MailWorker
{
public class MailKitWorker : AbstractMailWorker
{
public MailKitWorker(ILogger<MailKitWorker> logger, IMessageInfoLogic messageInfoLogic) : base(logger, messageInfoLogic) { }
public MailKitWorker(ILogger<MailKitWorker> 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;
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);
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;
}
}
await Task.Run(() => objSmtpClient.Send(objMailMessage));
}
catch (Exception)
{
throw;
}
}
protected override async Task<List<MessageInfoBindingModel>> ReceiveMailAsync()
protected override async Task<List<MessageInfoBindingModel>> ReceiveMailAsync()
{
var list = new List<MessageInfoBindingModel>();
using var client = new Pop3Client();

View File

@ -8,6 +8,7 @@
<ItemGroup>
<PackageReference Include="DocumentFormat.OpenXml" Version="3.0.2" />
<PackageReference Include="MailChimp.Net.V3" Version="5.5.0" />
<PackageReference Include="MailKit" Version="4.5.0" />
<PackageReference Include="MigraDocCore.DocumentObjectModel" Version="1.3.63" />
<PackageReference Include="MigraDocCore.Rendering" Version="1.3.63" />

View File

@ -146,7 +146,13 @@ namespace SushiBarClientApp.Controllers
);
return count * (prod?.Price ?? 1);
}
}
}
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

@ -0,0 +1,54 @@
@using SushiBarContracts.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

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

View File

@ -1,4 +1,5 @@
using SushiBarDataModels.Models;
using PrecastConcretePlantDataModels.Models;
using SushiBarDataModels.Models;
using System;
using System.Collections.Generic;
using System.Linq;

View File

@ -1,4 +1,5 @@
using SushiBarDataModels.Models;
using PrecastConcretePlantDataModels.Models;
using SushiBarDataModels.Models;
using System;
using System.Collections.Generic;
using System.ComponentModel;

View File

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

View File

@ -0,0 +1,52 @@
using SushiBarContracts.BindingModels;
using SushiBarContracts.SearchModels;
using SushiBarContracts.StoragesContracts;
using SushiBarContracts.ViewModels;
using SushiBarDatabaseImplement.Models;
namespace SushiBarDatabaseImplement.Implements
{
public class MessageInfoStorage : IMessageInfoStorage
{
public MessageInfoViewModel? GetElement(MessageInfoSearchModel model)
{
using var context = new SushiBarDatabase();
if (model.MessageId != null)
{
return context.Messages.FirstOrDefault(x => x.MessageId == model.MessageId)?.GetViewModel;
}
return null;
}
public List<MessageInfoViewModel> GetFilteredList(MessageInfoSearchModel model)
{
using var context = new SushiBarDatabase();
return context.Messages
.Where(x => x.ClientId == model.ClientId)
.Select(x => x.GetViewModel)
.ToList();
}
public List<MessageInfoViewModel> GetFullList()
{
using var context = new SushiBarDatabase();
return context.Messages
.Select(x => x.GetViewModel)
.ToList();
}
public MessageInfoViewModel? Insert(MessageInfoBindingModel model)
{
using var context = new SushiBarDatabase();
var newMessage = MessageInfo.Create(model);
if (newMessage == null || context.Messages.Any(x => x.MessageId.Equals(model.MessageId)))
{
return null;
}
context.Messages.Add(newMessage);
context.SaveChanges();
return newMessage.GetViewModel;
}
}
}

View File

@ -12,8 +12,8 @@ using SushiBarDatabaseImplement;
namespace SushiBarDatabaseImplement.Migrations
{
[DbContext(typeof(SushiBarDatabase))]
[Migration("20240512150027_6Lab")]
partial class _6Lab
[Migration("20240516141726_tested17")]
partial class tested17
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
@ -97,6 +97,36 @@ namespace SushiBarDatabaseImplement.Migrations
b.ToTable("Ingredients");
});
modelBuilder.Entity("SushiBarDatabaseImplement.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("SushiBarDatabaseImplement.Models.Order", b =>
{
b.Property<int>("Id")
@ -186,6 +216,15 @@ namespace SushiBarDatabaseImplement.Migrations
b.ToTable("SushiIngredients");
});
modelBuilder.Entity("SushiBarDatabaseImplement.Models.MessageInfo", b =>
{
b.HasOne("SushiBarDatabaseImplement.Models.Client", "Client")
.WithMany()
.HasForeignKey("ClientId");
b.Navigation("Client");
});
modelBuilder.Entity("SushiBarDatabaseImplement.Models.Order", b =>
{
b.HasOne("SushiBarDatabaseImplement.Models.Client", "Client")

View File

@ -6,7 +6,7 @@ using Microsoft.EntityFrameworkCore.Migrations;
namespace SushiBarDatabaseImplement.Migrations
{
/// <inheritdoc />
public partial class _6Lab : Migration
public partial class tested17 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
@ -70,6 +70,27 @@ namespace SushiBarDatabaseImplement.Migrations
table.PrimaryKey("PK_ListSushi", 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(
name: "Orders",
columns: table => new
@ -134,6 +155,11 @@ namespace SushiBarDatabaseImplement.Migrations
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Messages_ClientId",
table: "Messages",
column: "ClientId");
migrationBuilder.CreateIndex(
name: "IX_Orders_ClientId",
table: "Orders",
@ -163,6 +189,9 @@ namespace SushiBarDatabaseImplement.Migrations
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Messages");
migrationBuilder.DropTable(
name: "Orders");

View File

@ -94,6 +94,36 @@ namespace SushiBarDatabaseImplement.Migrations
b.ToTable("Ingredients");
});
modelBuilder.Entity("SushiBarDatabaseImplement.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("SushiBarDatabaseImplement.Models.Order", b =>
{
b.Property<int>("Id")
@ -183,6 +213,15 @@ namespace SushiBarDatabaseImplement.Migrations
b.ToTable("SushiIngredients");
});
modelBuilder.Entity("SushiBarDatabaseImplement.Models.MessageInfo", b =>
{
b.HasOne("SushiBarDatabaseImplement.Models.Client", "Client")
.WithMany()
Review

Связь настроена не до конца

Связь настроена не до конца
.HasForeignKey("ClientId");
b.Navigation("Client");
});
modelBuilder.Entity("SushiBarDatabaseImplement.Models.Order", b =>
{
b.HasOne("SushiBarDatabaseImplement.Models.Client", "Client")

View File

@ -0,0 +1,54 @@
using PrecastConcretePlantDataModels.Models;
using SushiBarContracts.BindingModels;
using SushiBarContracts.ViewModels;
using System.ComponentModel.DataAnnotations;
namespace SushiBarDatabaseImplement.Models
{
public class MessageInfo : IMessageInfoModel
{
[Key]
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 Client? Client { get; private set; }
public static MessageInfo? Create(MessageInfoBindingModel model)
{
if (model == null)
{
return null;
}
return new()
{
Body = model.Body,
Subject = model.Subject,
ClientId = model.ClientId,
MessageId = model.MessageId,
SenderName = model.SenderName,
DateDelivery = model.DateDelivery,
};
}
public MessageInfoViewModel GetViewModel => new()
{
Body = Body,
Subject = Subject,
ClientId = ClientId,
MessageId = MessageId,
SenderName = SenderName,
DateDelivery = DateDelivery,
};
}
}

View File

@ -10,7 +10,7 @@ namespace SushiBarDatabaseImplement
{
if (optionsBuilder.IsConfigured == false)
{
optionsBuilder.UseSqlServer(@"Data Source=DESKTOP-E2VPEN3\SQLEXPRESS;Initial Catalog=SushiBarDatabase;Integrated Security=True;MultipleActiveResultSets=True;;TrustServerCertificate=True");
optionsBuilder.UseSqlServer(@"Data Source=DESKTOP-E2VPEN3\SQLEXPRESS;Initial Catalog=SushiBarDatabaseTest;Integrated Security=True;MultipleActiveResultSets=True;;TrustServerCertificate=True");
}
base.OnConfiguring(optionsBuilder);
}
@ -23,5 +23,6 @@ namespace SushiBarDatabaseImplement
public virtual DbSet<Order> Orders { set; get; }
public virtual DbSet<Client> Clients { set; get; }
public virtual DbSet<Implementer> Implementers { set; get; }
}
public virtual DbSet<MessageInfo> Messages { set; get; }
}
}

View File

@ -2,6 +2,7 @@
using SushiBarContracts.BindingModel;
using SushiBarContracts.BusinessLogicsContracts;
using SushiBarContracts.SearchModel;
using SushiBarContracts.SearchModels;
using SushiBarContracts.ViewModels;
@ -12,12 +13,13 @@ namespace SushiBarRestApi.Controllers
public class ClientController : Controller
{
private readonly ILogger _logger;
private readonly IClientLogic _logic;
public ClientController(IClientLogic logic, ILogger<ClientController>
logger)
private readonly IClientLogic _logic;
private readonly IMessageInfoLogic _mailLogic;
public ClientController(IClientLogic logic, IMessageInfoLogic mailLogic, ILogger<ClientController> logger)
{
_logger = logger;
_logic = logic;
_mailLogic = mailLogic;
}
[HttpGet]
public ClientViewModel? Login(string login, string password)
@ -62,7 +64,22 @@ namespace SushiBarRestApi.Controllers
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,6 +1,8 @@
using Microsoft.OpenApi.Models;
using SushiBarBusinessLogic;
using SushiBarBusinessLogic.BusinessLogics;
using SushiBarBusinessLogic.MailWorker;
using SushiBarContracts.BindingModels;
using SushiBarContracts.BusinessLogicsContracts;
using SushiBarContracts.StoragesContracts;
using SushiBarDatabaseImplement.Implements;
@ -14,9 +16,13 @@ builder.Services.AddTransient<IOrderStorage, OrderStorage>();
builder.Services.AddTransient<ISushiStorage, SushiStorage>();
builder.Services.AddTransient<IOrderLogic, OrderLogic>();
builder.Services.AddTransient<IClientLogic, ClientLogic>();
builder.Services.AddTransient<IMessageInfoLogic, MessageInfoLogic>();
builder.Services.AddTransient<IMessageInfoStorage, MessageInfoStorage>();
builder.Services.AddTransient<ISushiLogic, SushiLogic>();
builder.Services.AddTransient<IImplementerStorage, ImplementerStorage>();
builder.Services.AddTransient<IImplementerLogic, ImplementerLogic>();
builder.Services.AddSingleton<AbstractMailWorker, MailKitWorker>();
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
@ -31,6 +37,16 @@ builder.Services.AddSwaggerGen(c =>
});
});
var app = builder.Build();
var mailSender = app.Services.GetService<AbstractMailWorker>();
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())
{
@ -38,7 +54,7 @@ if (app.Environment.IsDevelopment())
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json",
"AbstractShopRestApi v1"));
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();

View File

@ -5,5 +5,11 @@
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
"AllowedHosts": "*",
"SmtpClientHost": "smtp.gmail.com",
"SmtpClientPort": "587",
"PopHost": "pop.gmail.com",
"PopPort": "995",
"MailLogin": "89176335310x@gmail.com",
"MailPassword": "wmbu qrgy ocwl tadm"
}