PIbd-22. Shabunov O.A. Lab work 07 #12

Closed
olshab wants to merge 12 commits from Lab7 into Lab6
43 changed files with 1485 additions and 217 deletions

View File

@ -8,6 +8,7 @@
<ItemGroup>
<PackageReference Include="DocumentFormat.OpenXml" Version="2.19.0" />
<PackageReference Include="MailKit" Version="4.5.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
<PackageReference Include="PdfSharp.MigraDoc.Standard" Version="1.51.15" />
</ItemGroup>

View File

@ -4,10 +4,11 @@ using AutoWorkshopContracts.SearchModels;
using AutoWorkshopContracts.StoragesContracts;
using AutoWorkshopContracts.ViewModels;
using Microsoft.Extensions.Logging;
using System.Text.RegularExpressions;
namespace AutoWorkshopBusinessLogic.BusinessLogics
{
public class ClientLogic : IClientLogic
public class ClientLogic : IClientLogic
{
private readonly ILogger _logger;
private readonly IClientStorage _clientStorage;
@ -100,11 +101,11 @@ namespace AutoWorkshopBusinessLogic.BusinessLogics
if (string.IsNullOrEmpty(Model.ClientFIO))
throw new ArgumentNullException("Нет ФИО клиента", nameof(Model.ClientFIO));
if (string.IsNullOrEmpty(Model.Email))
throw new ArgumentNullException("Нет Email клиента", nameof(Model.ClientFIO));
if (string.IsNullOrEmpty(Model.Email) || !Regex.IsMatch(Model.Email, @"^[a-z0-9._%+-]+\@([a-z0-9-]+\.)+[a-z]{2,4}$"))
throw new ArgumentException("Почта не соответствует требованиям", nameof(Model.Email));
if (string.IsNullOrEmpty(Model.Password))
throw new ArgumentNullException("Нет пароля клиента", nameof(Model.ClientFIO));
if (string.IsNullOrEmpty(Model.Password) || !Regex.IsMatch(Model.Password, @"^(?=.*[A-Za-z])(?=.*\d)(?=.*[^A-Za-z0-9\n]).{10,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);

View File

@ -0,0 +1,85 @@
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.BusinessLogicContracts;
using AutoWorkshopContracts.SearchModels;
using AutoWorkshopContracts.StoragesContracts;
using AutoWorkshopContracts.ViewModels;
using Microsoft.Extensions.Logging;
namespace AutoWorkshopBusinessLogic.BusinessLogics
{
public class MessageInfoLogic : IMessageInfoLogic
{
private readonly ILogger _logger;
private readonly IMessageInfoStorage _messageInfoStorage;
private readonly IClientStorage _clientStorage;
public MessageInfoLogic(ILogger<MessageInfoLogic> Logger, IMessageInfoStorage MessageInfoStorage, IClientStorage ClientStorage)
{
_logger = Logger;
_messageInfoStorage = MessageInfoStorage;
_clientStorage = ClientStorage;
}
public List<MessageInfoViewModel>? ReadList(MessageInfoSearchModel? Model)
{
_logger.LogDebug("ReadList. MessageId: {MessageId}, ClientId: {ClientId}", Model?.MessageId, Model?.ClientId);
var Result = Model == null ? _messageInfoStorage.GetFullList() : _messageInfoStorage.GetFilteredList(Model);
_logger.LogDebug("ReadList result. Count: {Count}", Result.Count);
return Result;
}
public bool Create(MessageInfoBindingModel Model)
{
CheckModel(Model);
if (_messageInfoStorage.Insert(Model) == null)
{
_logger.LogWarning("Insert operation failed");
return false;
}
return true;
}
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}", Model.SenderName);
}
else
{
Model.ClientId = Element.Id;
}
}
}
}

View File

@ -1,4 +1,5 @@
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopBusinessLogic.MailWorker;
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.BusinessLogicContracts;
using AutoWorkshopContracts.SearchModels;
using AutoWorkshopContracts.StoragesContracts;
@ -8,18 +9,21 @@ using Microsoft.Extensions.Logging;
namespace AutoWorkshopBusinessLogic.BusinessLogics
{
public class OrderLogic : IOrderLogic
public class OrderLogic : IOrderLogic
{
private readonly ILogger _logger;
private readonly IOrderStorage _orderStorage;
private readonly AbstractMailWorker _mailLogic;
static readonly object _locker = new object();
public OrderLogic(ILogger<RepairLogic> Logger, IOrderStorage OrderStorage)
public OrderLogic(ILogger<RepairLogic> Logger, IOrderStorage OrderStorage, AbstractMailWorker MailLogic)
{
_logger = Logger;
_orderStorage = OrderStorage;
_mailLogic = MailLogic;
}
public List<OrderViewModel>? ReadList(OrderSearchModel? Model)
@ -36,6 +40,7 @@ namespace AutoWorkshopBusinessLogic.BusinessLogics
_logger.LogInformation("ReadList. Count: {Count}", List.Count);
return List;
}
public bool CreateOrder(OrderBindingModel Model)
{
CheckModel(Model);
@ -48,23 +53,30 @@ namespace AutoWorkshopBusinessLogic.BusinessLogics
Model.Status = OrderStatus.Accepted;
if (_orderStorage.Insert(Model) is null)
var CreatedOrder = _orderStorage.Insert(Model);
if (CreatedOrder == null)
{
_logger.LogWarning("Insert operation failed");
return false;
}
return true;
}
private bool ChangeOrderStatus(OrderBindingModel Model, OrderStatus NewStatus)
{
CheckModel(Model, false);
var Order = _orderStorage.GetElement(new OrderSearchModel { Id = Model.Id });
if (Order == null)
Task.Run(() => _mailLogic.SendMailAsync(new MailSendInfoBindingModel
{
MailAddress = CreatedOrder.ClientEmail,
Subject = $"Изменение статуса заказа номер {CreatedOrder.Id}",
Text = $"Ваш заказ номер {CreatedOrder.Id} на ремонт {CreatedOrder.RepairName} от {CreatedOrder.DateCreate} на сумму {CreatedOrder.Sum} принят."
}));
return true;
}
private bool ChangeOrderStatus(OrderBindingModel Model, OrderStatus NewStatus)
{
CheckModel(Model, false);
var Order = _orderStorage.GetElement(new OrderSearchModel { Id = Model.Id });
if (Order == null)
{
_logger.LogWarning("Change status operation failed. Order not found");
return false;
}
@ -92,10 +104,18 @@ namespace AutoWorkshopBusinessLogic.BusinessLogics
if (_orderStorage.Update(Model) == null)
{
_logger.LogWarning("Change status operation failed");
return false;
}
return false;
}
return true;
string DateInfo = Model.DateImplement.HasValue ? $"Дата выполнения: {Model.DateImplement}" : "";
Task.Run(() => _mailLogic.SendMailAsync(new MailSendInfoBindingModel
{
MailAddress = Order.ClientEmail,
Subject = $"Изменение статуса заказа номер {Order.Id}",
Text = $"Ваш заказ номер {Order.Id} на ремонт {Order.RepairName} от {Order.DateCreate} на сумму {Order.Sum}. Статус изменен на {NewStatus}. {DateInfo}"
}));
return true;
}
public bool TakeOrderInWork(OrderBindingModel Model)

View File

@ -0,0 +1,84 @@
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.BusinessLogicContracts;
using Microsoft.Extensions.Logging;
namespace AutoWorkshopBusinessLogic.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;
}
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("MailConfig: {Login}, {Password}, {ClientHost}, {ClientPort}, {PopHost}, {PopPort}",
_mailLogin, _mailPassword, _smtpClientHost, _smtpClientPort, _popHost, _popPort);
}
public async void SendMailAsync(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("MailSendAsync: {To}, {Subject}", Info.MailAddress, Info.Subject);
await SendMailImpl(Info);
}
public async void CheckMailAsync()
{
if (string.IsNullOrEmpty(_mailLogin) || string.IsNullOrEmpty(_mailPassword))
return;
if (string.IsNullOrEmpty(_popHost) || _popPort == 0)
return;
if (_messageInfoLogic == null)
return;
var List = await ReceiveMailImpl();
_logger.LogDebug("CheckMailAsync: New mails: {Count}", List.Count);
foreach (var Mail in List)
{
_messageInfoLogic.Create(Mail);
}
}
protected abstract Task SendMailImpl(MailSendInfoBindingModel Info);
protected abstract Task<List<MessageInfoBindingModel>> ReceiveMailImpl();
}
}

View File

@ -0,0 +1,85 @@
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.BusinessLogicContracts;
using MailKit.Net.Pop3;
using MailKit.Security;
using Microsoft.Extensions.Logging;
using System.Net;
using System.Net.Mail;
using System.Text;
namespace AutoWorkshopBusinessLogic.MailWorker
{
public class MailKitWorker : AbstractMailWorker
{
public MailKitWorker(ILogger<MailKitWorker> Logger, IMessageInfoLogic MessageInfoLogic)
: base(Logger, MessageInfoLogic) { }
protected override async Task SendMailImpl(MailSendInfoBindingModel Info)
{
using var MailMessage = new MailMessage();
using var SmtpClient = new SmtpClient(_smtpClientHost, _smtpClientPort);
try
{
MailMessage.From = new MailAddress(_mailLogin);
MailMessage.To.Add(new MailAddress(Info.MailAddress));
MailMessage.Subject = Info.Subject;
MailMessage.Body = Info.Text;
MailMessage.SubjectEncoding = Encoding.UTF8;
MailMessage.BodyEncoding = Encoding.UTF8;
SmtpClient.UseDefaultCredentials = false;
SmtpClient.EnableSsl = true;
SmtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
SmtpClient.Credentials = new NetworkCredential(_mailLogin, _mailPassword);
await Task.Run(() => SmtpClient.Send(MailMessage));
}
catch (Exception)
{
throw;
}
}
protected override async Task<List<MessageInfoBindingModel>> ReceiveMailImpl()
{
var Result = 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)
{
Result.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 Result;
}
}
}

View File

@ -156,5 +156,16 @@ namespace AutoWorkshopClientApp.Controllers
RepairViewModel? Repair = ApiClient.GetRequest<RepairViewModel>($"api/main/getrepair?repairId={repair}");
return count * (Repair?.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

@ -0,0 +1,51 @@
@using AutoWorkshopContracts.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

@ -26,6 +26,9 @@
<li class="nav-item">
<a class="nav-link text-dark" asparea="" asp-controller="Home" asp-action="Privacy">Личные данные</a>
</li>
<li>
<a class="nav-link text-dark" asparea="" asp-controller="Home" asp-action="Mails">Письма</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asparea="" asp-controller="Home" asp-action="Enter">Вход</a>
</li>

View File

@ -0,0 +1,17 @@
namespace AutoWorkshopContracts.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,11 @@
namespace AutoWorkshopContracts.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,19 @@
using AutoWorkshopDataModels.Models;
namespace AutoWorkshopContracts.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,13 @@
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.SearchModels;
using AutoWorkshopContracts.ViewModels;
namespace AutoWorkshopContracts.BusinessLogicContracts
{
public interface IMessageInfoLogic
{
List<MessageInfoViewModel>? ReadList(MessageInfoSearchModel? Model);
bool Create(MessageInfoBindingModel Model);
}
}

View File

@ -0,0 +1,9 @@
namespace AutoWorkshopContracts.SearchModels
{
public class MessageInfoSearchModel
{
public string? MessageId { get; set; }
public int? ClientId { get; set; }
}
}

View File

@ -0,0 +1,17 @@
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.SearchModels;
using AutoWorkshopContracts.ViewModels;
namespace AutoWorkshopContracts.StoragesContracts
{
public interface IMessageInfoStorage
{
List<MessageInfoViewModel> GetFullList();
List<MessageInfoViewModel> GetFilteredList(MessageInfoSearchModel Model);
MessageInfoViewModel? GetElement(MessageInfoSearchModel Model);
MessageInfoViewModel? Insert(MessageInfoBindingModel Model);
}
}

View File

@ -0,0 +1,24 @@
using AutoWorkshopDataModels.Models;
using System.ComponentModel;
namespace AutoWorkshopContracts.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

@ -19,6 +19,9 @@ namespace AutoWorkshopContracts.ViewModels
[DisplayName("Клиент")]
public string ClientFIO { get; set; } = string.Empty;
[DisplayName("Почта клиента")]
public string ClientEmail { get; set; } = string.Empty;
public int? ImplementerId { get; set; }
[DisplayName("Исполнитель")]

View File

@ -0,0 +1,17 @@
namespace AutoWorkshopDataModels.Models
{
public interface IMessageInfoModel
{
string MessageId { get; }
int? ClientId { get; }
string SenderName { get; }
DateTime DateDelivery { get; }
string Subject { get; }
string Body { get; }
}
}

View File

@ -29,5 +29,7 @@ namespace AutoWorkshopDatabaseImplement
public virtual DbSet<Client> Clients { set; get; }
public virtual DbSet<Implementer> Implementers { set; get; }
public virtual DbSet<MessageInfo> Messages { set; get; }
}
}

View File

@ -19,7 +19,7 @@ namespace AutoWorkshopDatabaseImplement.Implements
public List<ClientViewModel> GetFilteredList(ClientSearchModel Model)
{
if (string.IsNullOrEmpty(Model.ClientFIO) && string.IsNullOrEmpty(Model.Email))
if (string.IsNullOrEmpty(Model.Email) && string.IsNullOrEmpty(Model.ClientFIO))
return new();
using var Context = new AutoWorkshopDatabase();
@ -44,7 +44,7 @@ namespace AutoWorkshopDatabaseImplement.Implements
return Context.Clients
.FirstOrDefault(x => (string.IsNullOrEmpty(Model.ClientFIO) || x.ClientFIO == Model.ClientFIO) &&
(!Model.Id.HasValue || x.Id == Model.Id) && (string.IsNullOrEmpty(Model.Email) || x.Email == Model.Email) &&
(string.IsNullOrEmpty(Model.Email) || x.Email == Model.Email) && (!Model.Id.HasValue || x.Id == Model.Id) &&
(string.IsNullOrEmpty(Model.Password) || x.Password == Model.Password))?
.GetViewModel;
}

View File

@ -0,0 +1,56 @@
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.SearchModels;
using AutoWorkshopContracts.StoragesContracts;
using AutoWorkshopContracts.ViewModels;
using AutoWorkshopDatabaseImplement.Models;
namespace AutoWorkshopDatabaseImplement.Implements
{
public class MessageInfoStorage : IMessageInfoStorage
{
public List<MessageInfoViewModel> GetFullList()
{
using var Context = new AutoWorkshopDatabase();
return Context.Messages
.Select(x => x.GetViewModel)
.ToList();
}
public List<MessageInfoViewModel> GetFilteredList(MessageInfoSearchModel Model)
{
using var Context = new AutoWorkshopDatabase();
return Context.Messages
.Where(x => x.ClientId.HasValue && x.ClientId == Model.ClientId)
.Select(x => x.GetViewModel)
.ToList();
}
public MessageInfoViewModel? GetElement(MessageInfoSearchModel Model)
{
if (string.IsNullOrEmpty(Model.MessageId))
return null;
using var Context = new AutoWorkshopDatabase();
return Context.Messages
.FirstOrDefault(x => x.MessageId == Model.MessageId)?
.GetViewModel;
}
public MessageInfoViewModel? Insert(MessageInfoBindingModel Model)
{
var NewMessageInfo = MessageInfo.Create(Model);
if (NewMessageInfo == null)
return null;
using var Context = new AutoWorkshopDatabase();
Context.Messages.Add(NewMessageInfo);
Context.SaveChanges();
return NewMessageInfo.GetViewModel;
}
}
}

View File

@ -12,8 +12,8 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace AutoWorkshopDatabaseImplement.Migrations
{
[DbContext(typeof(AutoWorkshopDatabase))]
[Migration("20240416160914_Implementers")]
partial class Implementers
[Migration("20240419194703_Mails")]
partial class Mails
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
@ -97,6 +97,36 @@ namespace AutoWorkshopDatabaseImplement.Migrations
b.ToTable("Implementers");
});
modelBuilder.Entity("AutoWorkshopDatabaseImplement.Models.MessageInfo", b =>
{
b.Property<string>("MessageId")
.HasColumnType("text");
b.Property<string>("Body")
.IsRequired()
.HasColumnType("text");
b.Property<int?>("ClientId")
.HasColumnType("integer");
b.Property<DateTime>("DateDelivery")
.HasColumnType("timestamp without time zone");
b.Property<string>("SenderName")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Subject")
.IsRequired()
.HasColumnType("text");
b.HasKey("MessageId");
b.HasIndex("ClientId");
b.ToTable("Messages");
});
modelBuilder.Entity("AutoWorkshopDatabaseImplement.Models.Order", b =>
{
b.Property<int>("Id")
@ -186,10 +216,17 @@ namespace AutoWorkshopDatabaseImplement.Migrations
b.ToTable("RepairComponents");
});
modelBuilder.Entity("AutoWorkshopDatabaseImplement.Models.MessageInfo", b =>
{
b.HasOne("AutoWorkshopDatabaseImplement.Models.Client", null)
.WithMany("ClientMessages")
.HasForeignKey("ClientId");
});
modelBuilder.Entity("AutoWorkshopDatabaseImplement.Models.Order", b =>
{
b.HasOne("AutoWorkshopDatabaseImplement.Models.Client", "Client")
.WithMany("Orders")
.WithMany("ClientOrders")
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
@ -232,7 +269,9 @@ namespace AutoWorkshopDatabaseImplement.Migrations
modelBuilder.Entity("AutoWorkshopDatabaseImplement.Models.Client", b =>
{
b.Navigation("Orders");
b.Navigation("ClientMessages");
b.Navigation("ClientOrders");
});
modelBuilder.Entity("AutoWorkshopDatabaseImplement.Models.Component", b =>

View File

@ -7,7 +7,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace AutoWorkshopDatabaseImplement.Migrations
{
/// <inheritdoc />
public partial class Implementers : Migration
public partial class Mails : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
@ -71,6 +71,27 @@ namespace AutoWorkshopDatabaseImplement.Migrations
table.PrimaryKey("PK_Repairs", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Messages",
columns: table => new
{
MessageId = table.Column<string>(type: "text", nullable: false),
ClientId = table.Column<int>(type: "integer", nullable: true),
SenderName = table.Column<string>(type: "text", nullable: false),
DateDelivery = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
Subject = table.Column<string>(type: "text", nullable: false),
Body = table.Column<string>(type: "text", 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
@ -135,6 +156,11 @@ namespace AutoWorkshopDatabaseImplement.Migrations
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Messages_ClientId",
table: "Messages",
column: "ClientId");
migrationBuilder.CreateIndex(
name: "IX_Orders_ClientId",
table: "Orders",
@ -164,6 +190,9 @@ namespace AutoWorkshopDatabaseImplement.Migrations
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Messages");
migrationBuilder.DropTable(
name: "Orders");

View File

@ -94,6 +94,36 @@ namespace AutoWorkshopDatabaseImplement.Migrations
b.ToTable("Implementers");
});
modelBuilder.Entity("AutoWorkshopDatabaseImplement.Models.MessageInfo", b =>
{
b.Property<string>("MessageId")
.HasColumnType("text");
b.Property<string>("Body")
.IsRequired()
.HasColumnType("text");
b.Property<int?>("ClientId")
.HasColumnType("integer");
b.Property<DateTime>("DateDelivery")
.HasColumnType("timestamp without time zone");
b.Property<string>("SenderName")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Subject")
.IsRequired()
.HasColumnType("text");
b.HasKey("MessageId");
b.HasIndex("ClientId");
b.ToTable("Messages");
});
modelBuilder.Entity("AutoWorkshopDatabaseImplement.Models.Order", b =>
{
b.Property<int>("Id")
@ -183,10 +213,17 @@ namespace AutoWorkshopDatabaseImplement.Migrations
b.ToTable("RepairComponents");
});
modelBuilder.Entity("AutoWorkshopDatabaseImplement.Models.MessageInfo", b =>
{
b.HasOne("AutoWorkshopDatabaseImplement.Models.Client", null)
Review

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

Связь настроена не до конца
.WithMany("ClientMessages")
.HasForeignKey("ClientId");
});
modelBuilder.Entity("AutoWorkshopDatabaseImplement.Models.Order", b =>
{
b.HasOne("AutoWorkshopDatabaseImplement.Models.Client", "Client")
.WithMany("Orders")
.WithMany("ClientOrders")
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
@ -229,7 +266,9 @@ namespace AutoWorkshopDatabaseImplement.Migrations
modelBuilder.Entity("AutoWorkshopDatabaseImplement.Models.Client", b =>
{
b.Navigation("Orders");
b.Navigation("ClientMessages");
b.Navigation("ClientOrders");
});
modelBuilder.Entity("AutoWorkshopDatabaseImplement.Models.Component", b =>

View File

@ -20,7 +20,10 @@ namespace AutoWorkshopDatabaseImplement.Models
public string Password { get; set; } = string.Empty;
[ForeignKey("ClientId")]
public virtual List<Order> Orders { get; set; } = new();
public virtual List<Order> ClientOrders { get; set; } = new();
[ForeignKey("ClientId")]
public virtual List<MessageInfo> ClientMessages { get; set; } = new();
public static Client? Create(ClientBindingModel Model)
{

View File

@ -0,0 +1,49 @@
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.ViewModels;
using AutoWorkshopDataModels.Models;
using System.ComponentModel.DataAnnotations;
namespace AutoWorkshopDatabaseImplement.Models
{
public class MessageInfo : IMessageInfoModel
{
[Key]
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,
ClientId = Model.ClientId,
SenderName = Model.SenderName,
DateDelivery = Model.DateDelivery,
Subject = Model.Subject,
Body = Model.Body
};
}
public MessageInfoViewModel GetViewModel => new()
{
MessageId = MessageId,
ClientId = ClientId,
SenderName = SenderName,
DateDelivery = DateDelivery,
Subject = Subject,
Body = Body
};
}
}

View File

@ -75,6 +75,7 @@ namespace AutoWorkshopDatabaseImplement.Models
ImplementerId = ImplementerId,
RepairName = Repair.RepairName,
ClientFIO = Client.ClientFIO,
ClientEmail = Client.Email,
ImplementerFIO = Implementer?.ImplementerFIO,
Count = Count,
Sum = Sum,

View File

@ -12,8 +12,9 @@ namespace AutoWorkshopFileImplement
private readonly string RepairFileName = "Repair.xml";
private readonly string ClientFileName = "Client.xml";
private readonly string ImplementerFileName = "Implementer.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; }
@ -23,14 +24,17 @@ namespace AutoWorkshopFileImplement
public List<Implementer> Implementers { get; private set; }
private DataFileSingleton()
public List<MessageInfo> Messages { get; private set; }
private DataFileSingleton()
{
Components = LoadData(ComponentFileName, "Component", x => Component.Create(x)!)!;
Repairs = LoadData(RepairFileName, "Repair", x => Repair.Create(x)!)!;
Orders = LoadData(OrderFileName, "Order", x => Order.Create(x)!)!;
Clients = LoadData(ClientFileName, "Client", x => Client.Create(x)!)!;
Implementers = LoadData(ImplementerFileName, "Implementer", x => Implementer.Create(x)!)!;
}
Messages = LoadData(MessageInfoFileName, "MessageInfo", x => MessageInfo.Create(x)!)!;
}
public static DataFileSingleton GetInstance()
{
@ -47,8 +51,9 @@ namespace AutoWorkshopFileImplement
public void SaveOrders() => SaveData(Orders, OrderFileName, "Orders", x => x.GetXElement);
public void SaveClients() => SaveData(Clients, ClientFileName, "Clients", x => x.GetXElement);
public void SaveImplementers() => SaveData(Implementers, ImplementerFileName, "Implementers", x => x.GetXElement);
public void SaveMessages() => SaveData(Orders, ImplementerFileName, "Messages", x => x.GetXElement);
private static List<T>? LoadData<T>(string FileName, string XmlNodeName, Func<XElement, T> SelectFunction)
private static List<T>? LoadData<T>(string FileName, string XmlNodeName, Func<XElement, T> SelectFunction)
{
if (File.Exists(FileName))
{

View File

@ -0,0 +1,56 @@
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.SearchModels;
using AutoWorkshopContracts.StoragesContracts;
using AutoWorkshopContracts.ViewModels;
using AutoWorkshopFileImplement.Models;
namespace AutoWorkshopFileImplement.Implements
{
public class MessageInfoStorage : IMessageInfoStorage
{
private readonly DataFileSingleton _source;
public MessageInfoStorage()
{
_source = DataFileSingleton.GetInstance();
}
public List<MessageInfoViewModel> GetFullList()
{
return _source.Messages
.Select(x => x.GetViewModel)
.ToList();
}
public List<MessageInfoViewModel> GetFilteredList(MessageInfoSearchModel Model)
{
return _source.Messages
.Where(x => x.ClientId.HasValue && x.ClientId == Model.ClientId)
.Select(x => x.GetViewModel)
.ToList();
}
public MessageInfoViewModel? GetElement(MessageInfoSearchModel Model)
{
if (string.IsNullOrEmpty(Model.MessageId))
return null;
return _source.Messages
.FirstOrDefault(x => x.MessageId == Model.MessageId)?
.GetViewModel;
}
public MessageInfoViewModel? Insert(MessageInfoBindingModel Model)
{
var NewMessageInfo = MessageInfo.Create(Model);
if (NewMessageInfo == null)
return null;
_source.Messages.Add(NewMessageInfo);
_source.SaveMessages();
return NewMessageInfo.GetViewModel;
}
}
}

View File

@ -0,0 +1,74 @@
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.ViewModels;
using AutoWorkshopDataModels.Models;
using System.Xml.Linq;
namespace AutoWorkshopFileImplement.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,
ClientId = Model.ClientId,
SenderName = Model.SenderName,
DateDelivery = Model.DateDelivery,
Subject = Model.Subject,
Body = Model.Body
};
}
public MessageInfoViewModel GetViewModel => new()
{
MessageId = MessageId,
ClientId = ClientId,
SenderName = SenderName,
DateDelivery = DateDelivery,
Subject = Subject,
Body = Body
};
public static MessageInfo? Create(XElement Element)
{
if (Element == null)
return null;
return new()
{
MessageId = Element.Attribute("MessageId")!.Value,
ClientId = Convert.ToInt32(Element.Attribute("ClientId")!.Value),
SenderName = Element.Attribute("SenderName")!.Value,
DateDelivery = Convert.ToDateTime(Element.Attribute("DateDelivery")!.Value),
Subject = Element.Attribute("Subject")!.Value,
Body = Element.Attribute("Body")!.Value,
};
}
public XElement GetXElement => new(
"MessageInfo",
new XAttribute("MessageId", MessageId),
new XAttribute("ClientId", ClientId),
new XAttribute("SenderName", SenderName),
new XAttribute("DateDelivery", DateDelivery),
new XAttribute("Subject", Subject),
new XAttribute("Body", Body)
);
}
}

View File

@ -16,6 +16,8 @@ namespace AutoWorkshopListImplement
public List<Implementer> Implementers { get; set; }
public List<MessageInfo> Messages { get; set; }
private DataListSingleton()
{
Components = new List<Component>();
@ -23,6 +25,7 @@ namespace AutoWorkshopListImplement
Repairs = new List<Repair>();
Clients = new List<Client>();
Implementers = new List<Implementer>();
Messages = new List<MessageInfo>();
}
public static DataListSingleton GetInstance()

View File

@ -0,0 +1,54 @@
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.SearchModels;
using AutoWorkshopContracts.StoragesContracts;
using AutoWorkshopContracts.ViewModels;
using AutoWorkshopListImplement.Models;
namespace AutoWorkshopListImplement.Implements
{
public class MessageInfoStorage : IMessageInfoStorage
{
private readonly DataListSingleton _source;
public MessageInfoStorage()
{
_source = DataListSingleton.GetInstance();
}
public List<MessageInfoViewModel> GetFullList()
{
return _source.Messages
.Select(x => x.GetViewModel)
.ToList();
}
public List<MessageInfoViewModel> GetFilteredList(MessageInfoSearchModel Model)
{
return _source.Messages
.Where(x => x.ClientId.HasValue && x.ClientId == Model.ClientId)
.Select(x => x.GetViewModel)
.ToList();
}
public MessageInfoViewModel? GetElement(MessageInfoSearchModel Model)
{
if (string.IsNullOrEmpty(Model.MessageId))
return null;
return _source.Messages
.FirstOrDefault(x => x.MessageId == Model.MessageId)?
.GetViewModel;
}
public MessageInfoViewModel? Insert(MessageInfoBindingModel Model)
{
var NewMessageInfo = MessageInfo.Create(Model);
if (NewMessageInfo == null)
return null;
_source.Messages.Add(NewMessageInfo);
return NewMessageInfo.GetViewModel;
}
}
}

View File

@ -0,0 +1,47 @@
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.ViewModels;
using AutoWorkshopDataModels.Models;
namespace AutoWorkshopListImplement.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,
ClientId = Model.ClientId,
SenderName = Model.SenderName,
DateDelivery = Model.DateDelivery,
Subject = Model.Subject,
Body = Model.Body
};
}
public MessageInfoViewModel GetViewModel => new()
{
MessageId = MessageId,
ClientId = ClientId,
SenderName = SenderName,
DateDelivery = DateDelivery,
Subject = Subject,
Body = Body
};
}
}

View File

@ -12,11 +12,13 @@ namespace AutoWorkshopRestApi.Controllers
{
private readonly ILogger _logger;
private readonly IClientLogic _clientLogic;
private readonly IMessageInfoLogic _mailLogic;
public ClientController(IClientLogic ClientLogic, ILogger<ClientController> Logger)
public ClientController(IClientLogic ClientLogic, IMessageInfoLogic MailLogic, ILogger<ClientController> Logger)
{
_logger = Logger;
_clientLogic = ClientLogic;
_mailLogic = MailLogic;
}
[HttpGet]
@ -64,5 +66,22 @@ namespace AutoWorkshopRestApi.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,4 +1,6 @@
using AutoWorkshopBusinessLogic.BusinessLogics;
using AutoWorkshopBusinessLogic.MailWorker;
using AutoWorkshopContracts.BindingModels;
using AutoWorkshopContracts.BusinessLogicContracts;
using AutoWorkshopContracts.BusinessLogicsContracts;
using AutoWorkshopContracts.StoragesContracts;
@ -14,11 +16,15 @@ Builder.Services.AddTransient<IClientStorage, ClientStorage>();
Builder.Services.AddTransient<IOrderStorage, OrderStorage>();
Builder.Services.AddTransient<IRepairStorage, RepairStorage>();
Builder.Services.AddTransient<IImplementerStorage, ImplementerStorage>();
Builder.Services.AddTransient<IMessageInfoStorage, MessageInfoStorage>();
Builder.Services.AddTransient<IOrderLogic, OrderLogic>();
Builder.Services.AddTransient<IClientLogic, ClientLogic>();
Builder.Services.AddTransient<IRepairLogic, RepairLogic>();
Builder.Services.AddTransient<IImplementerLogic, ImplementerLogic>();
Builder.Services.AddTransient<IMessageInfoLogic, MessageInfoLogic>();
Builder.Services.AddSingleton<AbstractMailWorker, MailKitWorker>();
Builder.Services.AddControllers();
@ -34,6 +40,18 @@ 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())
});
if (App.Environment.IsDevelopment())
{
App.UseSwagger();

View File

@ -5,5 +5,12 @@
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
"AllowedHosts": "*",
"SmtpClientHost": "smtp.gmail.com",
"SmtpClientPort": "587",
"PopHost": "pop.gmail.com",
"PopPort": "995",
"MailLogin": "testingpurposeslab7@gmail.com",
"MailPassword": "gvdg ovtu lmis djwq"
}

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="testingpurposeslab7@gmail.com" />
<add key="MailPassword" value="gvdg ovtu lmis djwq" />
</appSettings>
</configuration>

View File

@ -0,0 +1,68 @@
namespace AutoWorkshopView.Forms
{
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.AllowUserToAddRows = false;
DataGridView.AllowUserToDeleteRows = false;
DataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
DataGridView.Dock = DockStyle.Fill;
DataGridView.Location = new Point(0, 0);
DataGridView.Margin = new Padding(3, 2, 3, 2);
DataGridView.Name = "DataGridView";
DataGridView.ReadOnly = true;
DataGridView.RowHeadersWidth = 51;
DataGridView.RowTemplate.Height = 29;
DataGridView.Size = new Size(1084, 456);
DataGridView.TabIndex = 0;
//
// FormMail
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(1084, 456);
Controls.Add(DataGridView);
Margin = new Padding(3, 2, 3, 2);
Name = "FormMail";
Text = "Письма";
Load += FormMail_Load;
((System.ComponentModel.ISupportInitialize)DataGridView).EndInit();
ResumeLayout(false);
}
#endregion
private DataGridView DataGridView;
}
}

View File

@ -0,0 +1,47 @@
using AutoWorkshopContracts.BusinessLogicContracts;
using Microsoft.Extensions.Logging;
namespace AutoWorkshopView.Forms
{
public partial class FormMail : Form
{
private readonly ILogger _logger;
private readonly IMessageInfoLogic _messageLogic;
public FormMail(ILogger<FormMail> Logger, IMessageInfoLogic MessageLogic)
{
InitializeComponent();
_logger = Logger;
_messageLogic = MessageLogic;
}
private void LoadData()
{
try
{
var List = _messageLogic.ReadList(null);
if (List != null)
{
DataGridView.DataSource = List;
DataGridView.Columns["MessageId"].Visible = false;
DataGridView.Columns["ClientId"].Visible = false;
DataGridView.Columns["Body"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
}
_logger.LogInformation("Загрузка почтовых собщений");
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка загрузки почтовых сообщений");
MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void FormMail_Load(object sender, EventArgs e)
{
LoadData();
}
}
}

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

@ -20,182 +20,190 @@
base.Dispose(disposing);
}
#region Windows Form Designer generated code
#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()
{
MenuStrip = new MenuStrip();
ToolStripMenu = new ToolStripMenuItem();
ComponentsStripMenuItem = new ToolStripMenuItem();
RepairStripMenuItem = new ToolStripMenuItem();
ClientsToolStripMenuItem = new ToolStripMenuItem();
ImplementersToolStripMenuItem = new ToolStripMenuItem();
ReportsToolStripMenuItem = new ToolStripMenuItem();
ComponentsToolStripMenuItem1 = new ToolStripMenuItem();
ComponentRepairToolStripMenuItem1 = new ToolStripMenuItem();
OrdersToolStripMenuItem = new ToolStripMenuItem();
WorkStartToolStripMenuItem = new ToolStripMenuItem();
DataGridView = new DataGridView();
CreateOrderButton = new Button();
IssuedButton = new Button();
RefreshButton = new Button();
MenuStrip.SuspendLayout();
((System.ComponentModel.ISupportInitialize)DataGridView).BeginInit();
SuspendLayout();
//
// MenuStrip
//
MenuStrip.ImageScalingSize = new Size(20, 20);
MenuStrip.Items.AddRange(new ToolStripItem[] { ToolStripMenu, ReportsToolStripMenuItem, WorkStartToolStripMenuItem });
MenuStrip.Location = new Point(0, 0);
MenuStrip.Name = "MenuStrip";
MenuStrip.Padding = new Padding(5, 2, 0, 2);
MenuStrip.Size = new Size(1356, 24);
MenuStrip.TabIndex = 0;
MenuStrip.Text = "TopMenuStrip";
//
// ToolStripMenu
//
ToolStripMenu.DropDownItems.AddRange(new ToolStripItem[] { ComponentsStripMenuItem, RepairStripMenuItem, ClientsToolStripMenuItem, ImplementersToolStripMenuItem });
ToolStripMenu.Name = "ToolStripMenu";
ToolStripMenu.Size = new Size(94, 20);
ToolStripMenu.Text = "Справочники";
//
// ComponentsStripMenuItem
//
ComponentsStripMenuItem.Name = "ComponentsStripMenuItem";
ComponentsStripMenuItem.Size = new Size(149, 22);
ComponentsStripMenuItem.Text = "Компоненты";
ComponentsStripMenuItem.Click += ComponentsStripMenuItem_Click;
//
// RepairStripMenuItem
//
RepairStripMenuItem.Name = "RepairStripMenuItem";
RepairStripMenuItem.Size = new Size(149, 22);
RepairStripMenuItem.Text = "Ремонты";
RepairStripMenuItem.Click += RepairsStripMenuItem_Click;
//
// ClientsToolStripMenuItem
//
ClientsToolStripMenuItem.Name = "ClientsToolStripMenuItem";
ClientsToolStripMenuItem.Size = new Size(149, 22);
ClientsToolStripMenuItem.Text = "Клиенты";
ClientsToolStripMenuItem.Click += ClientsToolStripMenuItem_Click;
//
// ImplementersToolStripMenuItem
//
ImplementersToolStripMenuItem.Name = "ImplementersToolStripMenuItem";
ImplementersToolStripMenuItem.Size = new Size(149, 22);
ImplementersToolStripMenuItem.Text = "Исполнители";
ImplementersToolStripMenuItem.Click += EmployersToolStripMenuItem_Click;
//
// ReportsToolStripMenuItem
//
ReportsToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { ComponentsToolStripMenuItem1, ComponentRepairToolStripMenuItem1, OrdersToolStripMenuItem });
ReportsToolStripMenuItem.Name = "ReportsToolStripMenuItem";
ReportsToolStripMenuItem.Size = new Size(60, 20);
ReportsToolStripMenuItem.Text = "Отчёты";
//
// ComponentsToolStripMenuItem1
//
ComponentsToolStripMenuItem1.Name = "ComponentsToolStripMenuItem1";
ComponentsToolStripMenuItem1.Size = new Size(210, 22);
ComponentsToolStripMenuItem1.Text = "Ремонты";
ComponentsToolStripMenuItem1.Click += ComponentsToolStripMenuItem_Click;
//
// ComponentRepairToolStripMenuItem1
//
ComponentRepairToolStripMenuItem1.Name = "ComponentRepairToolStripMenuItem1";
ComponentRepairToolStripMenuItem1.Size = new Size(210, 22);
ComponentRepairToolStripMenuItem1.Text = "Ремонт с компонентами";
ComponentRepairToolStripMenuItem1.Click += ComponentRepairToolStripMenuItem_Click;
//
// OrdersToolStripMenuItem
//
OrdersToolStripMenuItem.Name = "OrdersToolStripMenuItem";
OrdersToolStripMenuItem.Size = new Size(210, 22);
OrdersToolStripMenuItem.Text = "Заказы";
OrdersToolStripMenuItem.Click += OrdersToolStripMenuItem_Click;
//
// WorkStartToolStripMenuItem
//
WorkStartToolStripMenuItem.Name = "WorkStartToolStripMenuItem";
WorkStartToolStripMenuItem.Size = new Size(92, 20);
WorkStartToolStripMenuItem.Text = "Запуск работ";
WorkStartToolStripMenuItem.Click += StartWorkToolStripMenuItem_Click;
//
// DataGridView
//
DataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
DataGridView.Location = new Point(10, 23);
DataGridView.Margin = new Padding(3, 2, 3, 2);
DataGridView.Name = "DataGridView";
DataGridView.RowHeadersWidth = 51;
DataGridView.Size = new Size(1101, 358);
DataGridView.TabIndex = 1;
//
// CreateOrderButton
//
CreateOrderButton.Location = new Point(1117, 26);
CreateOrderButton.Margin = new Padding(3, 2, 3, 2);
CreateOrderButton.Name = "CreateOrderButton";
CreateOrderButton.Size = new Size(227, 30);
CreateOrderButton.TabIndex = 2;
CreateOrderButton.Text = "Создать заказ";
CreateOrderButton.UseVisualStyleBackColor = true;
CreateOrderButton.Click += CreateOrderButton_Click;
//
// IssuedButton
//
IssuedButton.Location = new Point(1117, 70);
IssuedButton.Margin = new Padding(3, 2, 3, 2);
IssuedButton.Name = "IssuedButton";
IssuedButton.Size = new Size(227, 30);
IssuedButton.TabIndex = 5;
IssuedButton.Text = "Заказ выдан";
IssuedButton.UseVisualStyleBackColor = true;
IssuedButton.Click += OrderDeliveredButton_Click;
//
// RefreshButton
//
RefreshButton.Location = new Point(1117, 114);
RefreshButton.Margin = new Padding(3, 2, 3, 2);
RefreshButton.Name = "RefreshButton";
RefreshButton.Size = new Size(227, 30);
RefreshButton.TabIndex = 6;
RefreshButton.Text = "Обновить";
RefreshButton.UseVisualStyleBackColor = true;
RefreshButton.Click += RefreshButton_Click;
//
// MainForm
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(1356, 392);
Controls.Add(RefreshButton);
Controls.Add(IssuedButton);
Controls.Add(CreateOrderButton);
Controls.Add(DataGridView);
Controls.Add(MenuStrip);
MainMenuStrip = MenuStrip;
Margin = new Padding(3, 2, 3, 2);
Name = "MainForm";
Text = "Основная форма";
Load += MainForm_Load;
MenuStrip.ResumeLayout(false);
MenuStrip.PerformLayout();
((System.ComponentModel.ISupportInitialize)DataGridView).EndInit();
ResumeLayout(false);
PerformLayout();
}
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
MenuStrip = new MenuStrip();
ToolStripMenu = new ToolStripMenuItem();
ComponentsStripMenuItem = new ToolStripMenuItem();
RepairStripMenuItem = new ToolStripMenuItem();
ClientsToolStripMenuItem = new ToolStripMenuItem();
ImplementersToolStripMenuItem = new ToolStripMenuItem();
ReportsToolStripMenuItem = new ToolStripMenuItem();
ComponentsToolStripMenuItem1 = new ToolStripMenuItem();
ComponentRepairToolStripMenuItem1 = new ToolStripMenuItem();
OrdersToolStripMenuItem = new ToolStripMenuItem();
WorkStartToolStripMenuItem = new ToolStripMenuItem();
MailToolStripMenuItem = new ToolStripMenuItem();
DataGridView = new DataGridView();
CreateOrderButton = new Button();
IssuedButton = new Button();
RefreshButton = new Button();
MenuStrip.SuspendLayout();
((System.ComponentModel.ISupportInitialize)DataGridView).BeginInit();
SuspendLayout();
//
// MenuStrip
//
MenuStrip.ImageScalingSize = new Size(20, 20);
MenuStrip.Items.AddRange(new ToolStripItem[] { ToolStripMenu, ReportsToolStripMenuItem, WorkStartToolStripMenuItem, MailToolStripMenuItem });
MenuStrip.Location = new Point(0, 0);
MenuStrip.Name = "MenuStrip";
MenuStrip.Padding = new Padding(5, 2, 0, 2);
MenuStrip.Size = new Size(1356, 24);
MenuStrip.TabIndex = 0;
MenuStrip.Text = "TopMenuStrip";
//
// ToolStripMenu
//
ToolStripMenu.DropDownItems.AddRange(new ToolStripItem[] { ComponentsStripMenuItem, RepairStripMenuItem, ClientsToolStripMenuItem, ImplementersToolStripMenuItem });
ToolStripMenu.Name = "ToolStripMenu";
ToolStripMenu.Size = new Size(94, 20);
ToolStripMenu.Text = "Справочники";
//
// ComponentsStripMenuItem
//
ComponentsStripMenuItem.Name = "ComponentsStripMenuItem";
ComponentsStripMenuItem.Size = new Size(149, 22);
ComponentsStripMenuItem.Text = "Компоненты";
ComponentsStripMenuItem.Click += ComponentsStripMenuItem_Click;
//
// RepairStripMenuItem
//
RepairStripMenuItem.Name = "RepairStripMenuItem";
RepairStripMenuItem.Size = new Size(149, 22);
RepairStripMenuItem.Text = "Ремонты";
RepairStripMenuItem.Click += RepairsStripMenuItem_Click;
//
// ClientsToolStripMenuItem
//
ClientsToolStripMenuItem.Name = "ClientsToolStripMenuItem";
ClientsToolStripMenuItem.Size = new Size(149, 22);
ClientsToolStripMenuItem.Text = "Клиенты";
ClientsToolStripMenuItem.Click += ClientsToolStripMenuItem_Click;
//
// ImplementersToolStripMenuItem
//
ImplementersToolStripMenuItem.Name = "ImplementersToolStripMenuItem";
ImplementersToolStripMenuItem.Size = new Size(149, 22);
ImplementersToolStripMenuItem.Text = "Исполнители";
ImplementersToolStripMenuItem.Click += EmployersToolStripMenuItem_Click;
//
// ReportsToolStripMenuItem
//
ReportsToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { ComponentsToolStripMenuItem1, ComponentRepairToolStripMenuItem1, OrdersToolStripMenuItem });
ReportsToolStripMenuItem.Name = "ReportsToolStripMenuItem";
ReportsToolStripMenuItem.Size = new Size(60, 20);
ReportsToolStripMenuItem.Text = "Отчёты";
//
// ComponentsToolStripMenuItem1
//
ComponentsToolStripMenuItem1.Name = "ComponentsToolStripMenuItem1";
ComponentsToolStripMenuItem1.Size = new Size(210, 22);
ComponentsToolStripMenuItem1.Text = "Ремонты";
ComponentsToolStripMenuItem1.Click += ComponentsToolStripMenuItem_Click;
//
// ComponentRepairToolStripMenuItem1
//
ComponentRepairToolStripMenuItem1.Name = "ComponentRepairToolStripMenuItem1";
ComponentRepairToolStripMenuItem1.Size = new Size(210, 22);
ComponentRepairToolStripMenuItem1.Text = "Ремонт с компонентами";
ComponentRepairToolStripMenuItem1.Click += ComponentRepairToolStripMenuItem_Click;
//
// OrdersToolStripMenuItem
//
OrdersToolStripMenuItem.Name = "OrdersToolStripMenuItem";
OrdersToolStripMenuItem.Size = new Size(210, 22);
OrdersToolStripMenuItem.Text = "Заказы";
OrdersToolStripMenuItem.Click += OrdersToolStripMenuItem_Click;
//
// WorkStartToolStripMenuItem
//
WorkStartToolStripMenuItem.Name = "WorkStartToolStripMenuItem";
WorkStartToolStripMenuItem.Size = new Size(92, 20);
WorkStartToolStripMenuItem.Text = "Запуск работ";
WorkStartToolStripMenuItem.Click += StartWorkToolStripMenuItem_Click;
//
// MailToolStripMenuItem
//
MailToolStripMenuItem.Name = "MailToolStripMenuItem";
MailToolStripMenuItem.Size = new Size(53, 20);
MailToolStripMenuItem.Text = "Почта";
MailToolStripMenuItem.Click += MailToolStripMenuItem_Click;
//
// DataGridView
//
DataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
DataGridView.Location = new Point(10, 23);
DataGridView.Margin = new Padding(3, 2, 3, 2);
DataGridView.Name = "DataGridView";
DataGridView.RowHeadersWidth = 51;
DataGridView.Size = new Size(1101, 358);
DataGridView.TabIndex = 1;
//
// CreateOrderButton
//
CreateOrderButton.Location = new Point(1117, 26);
CreateOrderButton.Margin = new Padding(3, 2, 3, 2);
CreateOrderButton.Name = "CreateOrderButton";
CreateOrderButton.Size = new Size(227, 30);
CreateOrderButton.TabIndex = 2;
CreateOrderButton.Text = "Создать заказ";
CreateOrderButton.UseVisualStyleBackColor = true;
CreateOrderButton.Click += CreateOrderButton_Click;
//
// IssuedButton
//
IssuedButton.Location = new Point(1117, 70);
IssuedButton.Margin = new Padding(3, 2, 3, 2);
IssuedButton.Name = "IssuedButton";
IssuedButton.Size = new Size(227, 30);
IssuedButton.TabIndex = 5;
IssuedButton.Text = "Заказ выдан";
IssuedButton.UseVisualStyleBackColor = true;
IssuedButton.Click += OrderDeliveredButton_Click;
//
// RefreshButton
//
RefreshButton.Location = new Point(1117, 114);
RefreshButton.Margin = new Padding(3, 2, 3, 2);
RefreshButton.Name = "RefreshButton";
RefreshButton.Size = new Size(227, 30);
RefreshButton.TabIndex = 6;
RefreshButton.Text = "Обновить";
RefreshButton.UseVisualStyleBackColor = true;
RefreshButton.Click += RefreshButton_Click;
//
// MainForm
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(1356, 392);
Controls.Add(RefreshButton);
Controls.Add(IssuedButton);
Controls.Add(CreateOrderButton);
Controls.Add(DataGridView);
Controls.Add(MenuStrip);
MainMenuStrip = MenuStrip;
Margin = new Padding(3, 2, 3, 2);
Name = "MainForm";
Text = "Основная форма";
Load += MainForm_Load;
MenuStrip.ResumeLayout(false);
MenuStrip.PerformLayout();
((System.ComponentModel.ISupportInitialize)DataGridView).EndInit();
ResumeLayout(false);
PerformLayout();
}
#endregion
#endregion
private MenuStrip MenuStrip;
private MenuStrip MenuStrip;
private ToolStripMenuItem ToolStripMenu;
private ToolStripMenuItem ComponentsStripMenuItem;
private ToolStripMenuItem RepairStripMenuItem;
@ -210,5 +218,6 @@
private ToolStripMenuItem ClientsToolStripMenuItem;
private ToolStripMenuItem ImplementersToolStripMenuItem;
private ToolStripMenuItem WorkStartToolStripMenuItem;
}
private ToolStripMenuItem MailToolStripMenuItem;
}
}

View File

@ -42,7 +42,8 @@ namespace AutoWorkshopView
DataGridView.DataSource = List;
DataGridView.Columns["RepairId"].Visible = false;
DataGridView.Columns["ClientId"].Visible = false;
DataGridView.Columns["ImplementerId"].Visible = false;
DataGridView.Columns["ClientEmail"].Visible = false;
DataGridView.Columns["ImplementerId"].Visible = false;
DataGridView.Columns["RepairName"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
}
@ -232,5 +233,15 @@ namespace AutoWorkshopView
MessageBox.Show("Процесс обработки запущен", "Сообщение", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
private void MailToolStripMenuItem_Click(object sender, EventArgs e)
{
var Service = Program.ServiceProvider?.GetService(typeof(FormMail));
if (Service is FormMail Form)
{
Form.ShowDialog();
}
}
}
}

View File

@ -9,6 +9,8 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using NLog.Extensions.Logging;
using AutoWorkshopContracts.BusinessLogicsContracts;
using AutoWorkshopBusinessLogic.MailWorker;
using AutoWorkshopContracts.BindingModels;
namespace AutoWorkshopView
{
@ -25,11 +27,35 @@ namespace AutoWorkshopView
var Services = new ServiceCollection();
ConfigureServices(Services);
_serviceProvider = Services.BuildServiceProvider();
Application.Run(_serviceProvider.GetRequiredService<MainForm>());
_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 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<MainForm>());
}
private static void ConfigureServices(ServiceCollection Services)
private static void MailCheck(object obj) => ServiceProvider?.GetService<AbstractMailWorker>()?.CheckMailAsync();
private static void ConfigureServices(ServiceCollection Services)
{
Services.AddLogging(option =>
{
@ -42,6 +68,7 @@ namespace AutoWorkshopView
Services.AddTransient<IRepairStorage, RepairStorage>();
Services.AddTransient<IClientStorage, ClientStorage>();
Services.AddTransient<IImplementerStorage, ImplementerStorage>();
Services.AddTransient<IMessageInfoStorage, MessageInfoStorage>();
Services.AddTransient<IComponentLogic, ComponentLogic>();
Services.AddTransient<IOrderLogic, OrderLogic>();
@ -50,10 +77,12 @@ namespace AutoWorkshopView
Services.AddTransient<IClientLogic, ClientLogic>();
Services.AddTransient<IImplementerLogic, ImplementerLogic>();
Services.AddTransient<IWorkProcess, WorkModeling>();
Services.AddTransient<IMessageInfoLogic, MessageInfoLogic>();
Services.AddTransient<AbstractSaveToWord, SaveToWord>();
Services.AddTransient<AbstractSaveToExcel, SaveToExcel>();
Services.AddTransient<AbstractSaveToPdf, SaveToPdf>();
Services.AddSingleton<AbstractMailWorker, MailKitWorker>();
Services.AddTransient<MainForm>();
Services.AddTransient<FormComponent>();
@ -67,6 +96,7 @@ namespace AutoWorkshopView
Services.AddTransient<FormClients>();
Services.AddTransient<FormImplementers>();
Services.AddTransient<FormImplementer>();
Services.AddTransient<FormMail>();
}
}
}